Skip to content

Commit 13ecf34

Browse files
committed
fix: add deployment CRUD with service expose
1 parent 257f890 commit 13ecf34

2 files changed

Lines changed: 105 additions & 3 deletions

File tree

web/src/DeploymentExposeModal.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React, {useEffect, useRef} from "react";
2+
import {Form, Input, InputNumber, Modal, Select} from "antd";
3+
import * as ServiceBackend from "./backend/ServiceBackend";
4+
import * as Setting from "./Setting";
5+
6+
function DeploymentExposeModal({deploy, open, onClose}) {
7+
const [form] = Form.useForm();
8+
const [submitting, setSubmitting] = React.useState(false);
9+
const prevOpen = useRef(false);
10+
11+
useEffect(() => {
12+
if (open && !prevOpen.current && deploy) {
13+
form.setFieldsValue({
14+
name: deploy.name,
15+
port: 80,
16+
targetPort: 80,
17+
type: "ClusterIP",
18+
});
19+
}
20+
prevOpen.current = open;
21+
}, [open, deploy, form]);
22+
23+
function handleOk() {
24+
form.validateFields().then(values => {
25+
const payload = {
26+
namespace: deploy.namespace,
27+
name: values.name,
28+
type: values.type,
29+
selector: {"app": deploy.name},
30+
ports: [{
31+
name: "http",
32+
protocol: "TCP",
33+
port: values.port,
34+
targetPort: String(values.targetPort),
35+
}],
36+
};
37+
setSubmitting(true);
38+
ServiceBackend.addService(payload).then(res => {
39+
if (res.status === "ok") {
40+
Setting.showMessage("success", `Service "${values.name}" created`);
41+
onClose();
42+
} else {
43+
Setting.showMessage("error", res.msg);
44+
}
45+
}).catch(e => Setting.showMessage("error", e.message))
46+
.finally(() => setSubmitting(false));
47+
});
48+
}
49+
50+
return (
51+
<Modal
52+
title={`Expose Deployment: ${deploy?.name ?? ""}`}
53+
open={open}
54+
onOk={handleOk}
55+
onCancel={onClose}
56+
confirmLoading={submitting}
57+
okText="Create Service"
58+
width={480}
59+
destroyOnHidden
60+
>
61+
<Form form={form} layout="vertical">
62+
<Form.Item
63+
label="Service Name"
64+
name="name"
65+
rules={[{required: true, message: "Service name is required"}]}
66+
>
67+
<Input placeholder="my-deployment" />
68+
</Form.Item>
69+
<Form.Item label="Type" name="type" rules={[{required: true}]}>
70+
<Select options={[
71+
{label: "ClusterIP — 集群内访问", value: "ClusterIP"},
72+
{label: "NodePort — 节点端口对外暴露", value: "NodePort"},
73+
{label: "LoadBalancer — 云负载均衡器", value: "LoadBalancer"},
74+
]} />
75+
</Form.Item>
76+
<Form.Item label="Port (Service 端口)" name="port" rules={[{required: true}]}>
77+
<InputNumber min={1} max={65535} style={{width: "100%"}} />
78+
</Form.Item>
79+
<Form.Item label="Target Port (Pod 容器端口)" name="targetPort" rules={[{required: true}]}>
80+
<InputNumber min={1} max={65535} style={{width: "100%"}} />
81+
</Form.Item>
82+
</Form>
83+
</Modal>
84+
);
85+
}
86+
87+
export default DeploymentExposeModal;

web/src/DeploymentListPage.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import React from "react";
22
import {
33
Alert, Badge, Button, Form, Input, InputNumber, Modal, Popconfirm, Select, Space, Table
44
} from "antd";
5-
import {DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined} from "@ant-design/icons";
5+
import {DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined, ShareAltOutlined} from "@ant-design/icons";
66
import * as DeploymentBackend from "./backend/DeploymentBackend";
77
import * as NamespaceBackend from "./backend/NamespaceBackend";
88
import * as Setting from "./Setting";
9+
import DeploymentExposeModal from "./DeploymentExposeModal";
910

1011
class DeploymentListPage extends React.Component {
1112
constructor(props) {
@@ -19,6 +20,7 @@ class DeploymentListPage extends React.Component {
1920
modalMode: "add",
2021
submitting: false,
2122
editingDeploy: null,
23+
exposeDeploy: null,
2224
};
2325
this.formRef = React.createRef();
2426
}
@@ -140,7 +142,7 @@ class DeploymentListPage extends React.Component {
140142
}
141143

142144
render() {
143-
const {deployments, namespaces, loading, error, modalVisible, modalMode, submitting} = this.state;
145+
const {deployments, namespaces, loading, error, modalVisible, modalMode, submitting, exposeDeploy} = this.state;
144146

145147
const nsOptions = namespaces.map(ns => ({label: ns.name, value: ns.name}));
146148

@@ -170,7 +172,7 @@ class DeploymentListPage extends React.Component {
170172
{
171173
title: "Actions",
172174
key: "actions",
173-
width: 140,
175+
width: 210,
174176
render: (_, record) => (
175177
<Space>
176178
<Button
@@ -180,6 +182,13 @@ class DeploymentListPage extends React.Component {
180182
>
181183
Edit
182184
</Button>
185+
<Button
186+
size="small"
187+
icon={<ShareAltOutlined />}
188+
onClick={() => this.setState({exposeDeploy: record})}
189+
>
190+
Expose
191+
</Button>
183192
<Popconfirm
184193
title={`Delete Deployment "${record.name}"?`}
185194
okText="Delete"
@@ -229,6 +238,12 @@ class DeploymentListPage extends React.Component {
229238
)}
230239
/>
231240

241+
<DeploymentExposeModal
242+
deploy={exposeDeploy}
243+
open={exposeDeploy !== null}
244+
onClose={() => this.setState({exposeDeploy: null})}
245+
/>
246+
232247
<Modal
233248
title={modalMode === "add" ? "Add Deployment" : "Edit Deployment"}
234249
open={modalVisible}

0 commit comments

Comments
 (0)