fix: fix cluster template

1. Fix the params when create or update cluster template
2. Show search for all select items
3. Fix the route path for update cluster template

Change-Id: Ic3435abb340f6e129815fde368b5b12bcabcdcb5
This commit is contained in:
xusongfu 2022-06-23 17:15:40 +08:00
parent bf6c765fb1
commit ec4bcb3c93
20 changed files with 423 additions and 315 deletions

View File

@ -74,6 +74,11 @@ export default class BaseForm extends React.Component {
this.unMountActions && this.unMountActions(); this.unMountActions && this.unMountActions();
} }
get path() {
const { location: { pathname = '' } = {} } = this.props;
return pathname || '';
}
get disableSubmit() { get disableSubmit() {
return false; return false;
} }

View File

@ -62,6 +62,7 @@ export default class index extends Component {
checkOptions, checkOptions,
checkBoxInfo, checkBoxInfo,
allowClear = true, allowClear = true,
showSearch = true,
...rest ...rest
} = this.props; } = this.props;
if (isUndefined(value) || isNull(value)) { if (isUndefined(value) || isNull(value)) {
@ -69,6 +70,7 @@ export default class index extends Component {
<Select <Select
{...rest} {...rest}
allowClear={allowClear} allowClear={allowClear}
showSearch={showSearch}
placeholder={placeholder} placeholder={placeholder}
onChange={this.onChange} onChange={this.onChange}
/> />
@ -88,6 +90,7 @@ export default class index extends Component {
<Select <Select
{...rest} {...rest}
allowClear={allowClear} allowClear={allowClear}
showSearch={showSearch}
placeholder={placeholder} placeholder={placeholder}
onChange={this.onChange} onChange={this.onChange}
value={this.getValue()} value={this.getValue()}
@ -104,6 +107,7 @@ export default class index extends Component {
<Select <Select
{...rest} {...rest}
allowClear={allowClear} allowClear={allowClear}
showSearch={showSearch}
placeholder={placeholder} placeholder={placeholder}
onChange={this.onChange} onChange={this.onChange}
value={this.getValue()} value={this.getValue()}

View File

@ -58,6 +58,11 @@ export default class BaseStepForm extends React.Component {
this.unMountActions && this.unMountActions(); this.unMountActions && this.unMountActions();
} }
get path() {
const { location: { pathname = '' } = {} } = this.props;
return pathname || '';
}
get hasConfirmStep() { get hasConfirmStep() {
return false; return false;
} }

View File

@ -672,7 +672,7 @@ const renderMenu = (t) => {
level: 2, level: 2,
}, },
{ {
path: /^\/container-infra\/cluster-template\/update\/.[^/]+\/.[^/]+$/, path: /^\/container-infra\/cluster-template\/update\/.[^/]+$/,
name: t('Update Cluster Template'), name: t('Update Cluster Template'),
key: 'containerInfraUpdateClusterTemplate', key: 'containerInfraUpdateClusterTemplate',
level: 2, level: 2,

View File

@ -322,9 +322,9 @@
"Checksum": "Checksum", "Checksum": "Checksum",
"Chile": "Chile", "Chile": "Chile",
"China": "China", "China": "China",
"Choose a External Network ID": "Choose a External Network ID", "Choose a External Network": "Choose a External Network",
"Choose a Network Driver": "Choose a Network Driver", "Choose a Network Driver": "Choose a Network Driver",
"Choose a Private Network ID": "Choose a Private Network ID", "Choose a Private Network": "Choose a Private Network",
"Choose a Private Network at first": "Choose a Private Network at first", "Choose a Private Network at first": "Choose a Private Network at first",
"Choose a host to live migrate instance to. If not selected, the scheduler will auto select target host.": "Choose a host to live migrate instance to. If not selected, the scheduler will auto select target host.", "Choose a host to live migrate instance to. If not selected, the scheduler will auto select target host.": "Choose a host to live migrate instance to. If not selected, the scheduler will auto select target host.",
"Choose a host to migrate instance to. If not selected, the scheduler will auto select target host.": "Choose a host to migrate instance to. If not selected, the scheduler will auto select target host.", "Choose a host to migrate instance to. If not selected, the scheduler will auto select target host.": "Choose a host to migrate instance to. If not selected, the scheduler will auto select target host.",
@ -542,7 +542,6 @@
"Current Flavor": "Current Flavor", "Current Flavor": "Current Flavor",
"Current Host": "Current Host", "Current Host": "Current Host",
"Current Interface": "Current Interface", "Current Interface": "Current Interface",
"Current Master Flavor": "Current Master Flavor",
"Current Password": "Current Password", "Current Password": "Current Password",
"Current Path: ": "Current Path: ", "Current Path: ": "Current Path: ",
"Current Project": "Current Project", "Current Project": "Current Project",
@ -911,7 +910,9 @@
"Fixed IP Address": "Fixed IP Address", "Fixed IP Address": "Fixed IP Address",
"Fixed IPs": "Fixed IPs", "Fixed IPs": "Fixed IPs",
"Fixed Network": "Fixed Network", "Fixed Network": "Fixed Network",
"Fixed Network ID": "Fixed Network ID",
"Fixed Subnet": "Fixed Subnet", "Fixed Subnet": "Fixed Subnet",
"Fixed Subnet ID": "Fixed Subnet ID",
"Flavor": "Flavor", "Flavor": "Flavor",
"Flavor Detail": "Flavor Detail", "Flavor Detail": "Flavor Detail",
"Flavor ID": "Flavor ID", "Flavor ID": "Flavor ID",

View File

@ -322,9 +322,9 @@
"Checksum": "校验和", "Checksum": "校验和",
"Chile": "智利", "Chile": "智利",
"China": "中国大陆", "China": "中国大陆",
"Choose a External Network ID": "选择外部网络 ID", "Choose a External Network": "选择外部网络",
"Choose a Network Driver": "选择网络驱动程序", "Choose a Network Driver": "选择网络驱动程序",
"Choose a Private Network ID": "选择专用网络 ID", "Choose a Private Network": "选择专用网络",
"Choose a Private Network at first": "首先选择一个专用网络", "Choose a Private Network at first": "首先选择一个专用网络",
"Choose a host to live migrate instance to. If not selected, the scheduler will auto select target host.": "选择计算节点来热迁移云主机,如果没有选择,调度器会自动选择目标计算节点。", "Choose a host to live migrate instance to. If not selected, the scheduler will auto select target host.": "选择计算节点来热迁移云主机,如果没有选择,调度器会自动选择目标计算节点。",
"Choose a host to migrate instance to. If not selected, the scheduler will auto select target host.": "选择计算节点来迁移云主机,如果没有选择,调度器会自动选择目标计算节点。", "Choose a host to migrate instance to. If not selected, the scheduler will auto select target host.": "选择计算节点来迁移云主机,如果没有选择,调度器会自动选择目标计算节点。",
@ -542,7 +542,6 @@
"Current Flavor": "当前配置", "Current Flavor": "当前配置",
"Current Host": "当前主机", "Current Host": "当前主机",
"Current Interface": "当前接口", "Current Interface": "当前接口",
"Current Master Flavor": "当前主类型",
"Current Password": "原密码", "Current Password": "原密码",
"Current Path: ": "当前路径:", "Current Path: ": "当前路径:",
"Current Project": "当前项目", "Current Project": "当前项目",
@ -911,7 +910,9 @@
"Fixed IP Address": "内网IP地址", "Fixed IP Address": "内网IP地址",
"Fixed IPs": "内网IP", "Fixed IPs": "内网IP",
"Fixed Network": "内网", "Fixed Network": "内网",
"Fixed Network ID": "内网ID",
"Fixed Subnet": "内网子网", "Fixed Subnet": "内网子网",
"Fixed Subnet ID": "内网子网ID",
"Flavor": "云主机类型", "Flavor": "云主机类型",
"Flavor Detail": "云主机类型详情", "Flavor Detail": "云主机类型详情",
"Flavor ID": "云主机类型ID", "Flavor ID": "云主机类型ID",

View File

@ -10,9 +10,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import Base from 'containers/BaseDetail';
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import Base from 'containers/BaseDetail';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
export class BaseDetail extends Base { export class BaseDetail extends Base {
@ -28,82 +27,94 @@ export class BaseDetail extends Base {
const options = [ const options = [
{ {
label: t('COE'), label: t('COE'),
dataIndex: 'coe' dataIndex: 'coe',
}, },
{ {
label: t('Cluster Distro'), label: t('Cluster Distro'),
dataIndex: 'cluster_distro' dataIndex: 'cluster_distro',
}, },
{ {
label: t('Server Type'), label: t('Server Type'),
dataIndex: 'server_type' dataIndex: 'server_type',
}, },
{ {
label: t('Public'), label: t('Public'),
dataIndex: 'public', dataIndex: 'public',
valueRender: 'yesNo' valueRender: 'yesNo',
}, },
{ {
label: t('Registry Enabled'), label: t('Registry Enabled'),
dataIndex: 'registry_enabled', dataIndex: 'registry_enabled',
valueRender: 'yesNo' valueRender: 'yesNo',
}, },
{ {
label: t('TLS Disabled'), label: t('TLS Disabled'),
dataIndex: 'tls_disabled', dataIndex: 'tls_disabled',
valueRender: 'yesNo' valueRender: 'yesNo',
}, },
]; ];
return { return {
title: t('Cluster Type'), title: t('Cluster Type'),
options options,
}; };
} }
get networkCard() { get networkCard() {
const { external_network_id, fixed_network } = this.detailData || {};
const externalNetworkUrl = external_network_id
? this.getLinkRender('networkDetail', external_network_id, {
id: external_network_id,
})
: '-';
const fixedNetworkUrl = fixed_network
? this.getLinkRender('networkDetail', fixed_network, {
id: fixed_network,
})
: '-';
const options = [ const options = [
{ {
label: t('Network Driver'), label: t('Network Driver'),
dataIndex: 'network_driver' dataIndex: 'network_driver',
}, },
{ {
label: t('HTTP Proxy'), label: t('HTTP Proxy'),
dataIndex: 'http_proxy' dataIndex: 'http_proxy',
}, },
{ {
label: t('HTTPS Proxy'), label: t('HTTPS Proxy'),
dataIndex: 'https_proxy' dataIndex: 'https_proxy',
}, },
{ {
label: t('No Proxy'), label: t('No Proxy'),
dataIndex: 'no_proxy' dataIndex: 'no_proxy',
}, },
{ {
label: t('External Network ID'), label: t('External Network ID'),
dataIndex: 'external_network_id' content: externalNetworkUrl,
}, },
{ {
label: t('Fixed Network'), label: t('Fixed Network ID'),
dataIndex: 'fixed_network' content: fixedNetworkUrl,
}, },
{ {
label: t('Fixed Subnet'), label: t('Fixed Subnet ID'),
dataIndex: 'fixed_subnet' dataIndex: 'fixed_subnet',
}, },
{ {
label: t('DNS'), label: t('DNS'),
dataIndex: 'dns_nameserver' dataIndex: 'dns_nameserver',
}, },
{ {
label: t('Master LB Enabled'), label: t('Master LB Enabled'),
dataIndex: 'master_lb_enabled', dataIndex: 'master_lb_enabled',
valueRender: 'yesNo' valueRender: 'yesNo',
}, },
{ {
label: t('Floating IP Enabled'), label: t('Floating IP Enabled'),
dataIndex: 'floating_ip_enabled', dataIndex: 'floating_ip_enabled',
valueRender: 'yesNo' valueRender: 'yesNo',
}, },
]; ];
@ -114,44 +125,64 @@ export class BaseDetail extends Base {
} }
get specCard() { get specCard() {
const image = this.detailData.image_id; const { image_id, keypair_id, flavor_id, master_flavor_id } =
const imageUrl = this.getRoutePath('imageDetail', { id: image }); this.detailData;
const imageUrl = image_id
? this.getLinkRender('imageDetail', image_id, {
id: image_id,
})
: '-';
const keypair = this.detailData.keypair_id; const keypairUrl = keypair_id
const keypairUrl = this.getRoutePath('keypairDetail', { id: keypair }); ? this.getLinkRender('keypairDetail', keypair_id, {
id: keypair_id,
})
: '-';
const flavorUrl = flavor_id
? this.getLinkRender('flavorDetail', flavor_id, {
id: flavor_id,
})
: '-';
const masterFlavorUrl = master_flavor_id
? this.getLinkRender('flavorDetail', master_flavor_id, {
id: master_flavor_id,
})
: '-';
const options = [ const options = [
{ {
label: t('Image ID'), label: t('Image ID'),
content: <Link to={imageUrl}>{image}</Link> content: imageUrl,
}, },
{ {
label: t('Keypair'), label: t('Keypair'),
content: <Link to={keypairUrl}>{keypair}</Link> content: keypairUrl,
}, },
{ {
label: t('Flavor ID'), label: t('Flavor ID'),
dataIndex: 'flavor_id' content: flavorUrl,
}, },
{ {
label: t('Master Flavor ID'), label: t('Master Flavor ID'),
dataIndex: 'master_flavor_id' content: masterFlavorUrl,
}, },
{ {
label: t('Volume Driver'), label: t('Volume Driver'),
dataIndex: 'volume_driver' dataIndex: 'volume_driver',
}, },
{ {
label: t('Docker Storage Driver'), label: t('Docker Storage Driver'),
dataIndex: 'docker_storage_driver' dataIndex: 'docker_storage_driver',
}, },
{ {
label: t('Docker Volume Size'), label: t('Docker Volume Size'),
dataIndex: 'docker_volume_size' dataIndex: 'docker_volume_size',
}, },
{ {
label: t('Insecure Registry'), label: t('Insecure Registry'),
dataIndex: 'insecure_registry' dataIndex: 'insecure_registry',
}, },
]; ];
@ -166,9 +197,20 @@ export class BaseDetail extends Base {
{ {
label: t('labels'), label: t('labels'),
dataIndex: 'labels', dataIndex: 'labels',
render: (value) => value ? Object.entries(value).map(([key, val]) => { render: (value) =>
return <div key={key}><ul><li>{key} : {val}</li></ul></div> value
}) : '-' ? Object.entries(value).map(([key, val]) => {
return (
<div key={key}>
<ul>
<li>
{key} : {val}
</li>
</ul>
</div>
);
})
: '-',
}, },
]; ];
@ -180,4 +222,4 @@ export class BaseDetail extends Base {
} }
} }
export default inject("rootStore")(observer(BaseDetail)) export default inject('rootStore')(observer(BaseDetail));

View File

@ -12,8 +12,9 @@
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import Base from 'containers/TabDetail'; import Base from 'containers/TabDetail';
import BaseDetail from './BaseDetail';
import globalClusterTemplateStore from 'src/stores/magnum/clusterTemplates'; import globalClusterTemplateStore from 'src/stores/magnum/clusterTemplates';
import BaseDetail from './BaseDetail';
import actionConfigs from '../actions';
export class ClusterTemplateDetail extends Base { export class ClusterTemplateDetail extends Base {
init() { init() {
@ -32,6 +33,10 @@ export class ClusterTemplateDetail extends Base {
return 'container-infra:clustertemplate:detail'; return 'container-infra:clustertemplate:detail';
} }
get actionConfigs() {
return actionConfigs;
}
get detailInfos() { get detailInfos() {
return [ return [
{ {
@ -41,12 +46,12 @@ export class ClusterTemplateDetail extends Base {
{ {
title: t('Created'), title: t('Created'),
dataIndex: 'created_at', dataIndex: 'created_at',
valueRender: 'toLocalTime' valueRender: 'toLocalTime',
}, },
{ {
title: t('Updated'), title: t('Updated'),
dataIndex: 'updated_at', dataIndex: 'updated_at',
valueRender: 'toLocalTime' valueRender: 'toLocalTime',
}, },
]; ];
} }
@ -62,4 +67,4 @@ export class ClusterTemplateDetail extends Base {
} }
} }
export default inject("rootStore")(observer(ClusterTemplateDetail)) export default inject('rootStore')(observer(ClusterTemplateDetail));

View File

@ -13,7 +13,7 @@
import { ConfirmAction } from 'containers/Action'; import { ConfirmAction } from 'containers/Action';
import globalClusterTemplateStore from 'stores/magnum/clusterTemplates'; import globalClusterTemplateStore from 'stores/magnum/clusterTemplates';
export default class DeleteClusterTemplates extends ConfirmAction { export default class Delete extends ConfirmAction {
get id() { get id() {
return 'delete'; return 'delete';
} }

View File

@ -14,11 +14,9 @@
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import { getPath } from 'src/utils/route-map'; import { getPath } from 'src/utils/route-map';
import StepCreate from './StepCreate'; import { StepCreate as Base } from './StepCreate';
@inject('rootStore') export class Edit extends Base {
@observer
export default class Edit extends StepCreate {
static id = 'update-cluster-template'; static id = 'update-cluster-template';
static title = t('Update Cluster Template'); static title = t('Update Cluster Template');
@ -43,3 +41,5 @@ export default class Edit extends StepCreate {
return Promise.resolve(true); return Promise.resolve(true);
} }
} }
export default inject('rootStore')(observer(Edit));

View File

@ -12,16 +12,16 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import Base from "components/Form"; import Base from 'components/Form';
import { inject, observer } from "mobx-react"; import { inject, observer } from 'mobx-react';
export class StepInfo extends Base { export class StepInfo extends Base {
get title() { get title() {
return t("Info") return t('Info');
} }
get name() { get name() {
return t("Info") return t('Info');
} }
get isEdit() { get isEdit() {
@ -32,22 +32,28 @@ export class StepInfo extends Base {
return true; return true;
} }
onCOEChange = (value) => {
this.updateContext({
coeSelectRows: value,
});
}
get defaultValue() { get defaultValue() {
const values = {}; let values = {};
if (this.isEdit) { if (this.isEdit) {
values.clusterTemplateName = this.props.extra.name; const {
values.coe = this.props.extra.coe; extra: {
values.cluster_template_public = this.props.extra.public; name,
values.cluster_template_hidden = this.props.extra.hidden; coe,
values.docker_registry_enabled = this.props.extra.registry_enabled; public: publics,
values.tls_disabled = this.props.extra.tls_disabled; hidden,
registry_enabled,
tls_disabled,
} = {},
} = this.props;
values = {
name,
coe,
public: publics,
hidden,
registry_enabled,
tls_disabled,
};
} }
return values; return values;
} }
@ -55,64 +61,62 @@ export class StepInfo extends Base {
get formItems() { get formItems() {
return [ return [
{ {
name: "clusterTemplateName", name: 'name',
label: t("Cluster Template Name"), label: t('Cluster Template Name'),
type: "input", type: 'input',
placeholder: t("Cluster Template Name"), placeholder: t('Cluster Template Name'),
required: true required: true,
}, },
{ {
name: "coe", name: 'coe',
label: t("Container Orchestration Engine"), label: t('Container Orchestration Engine'),
type: "select", type: 'select',
options: [ options: [
{ {
label: t("Kubernetes"), label: t('Kubernetes'),
value: "kubernetes" value: 'kubernetes',
}, },
{ {
label: t("Docker Swarm"), label: t('Docker Swarm'),
value: "swarm" value: 'swarm',
}, },
{ {
label: t("Docker Swarm Mode"), label: t('Docker Swarm Mode'),
value: "swarm-mode" value: 'swarm-mode',
}, },
{ {
label: t("Mesos"), label: t('Mesos'),
value: "mesos" value: 'mesos',
}, },
{ {
label: t("DC/OS"), label: t('DC/OS'),
value: "dcos" value: 'dcos',
}, },
], ],
onChange: this.onCOEChange, required: true,
allowClear: true,
showSearch: true
}, },
{ {
name: "cluster_template_public", name: 'public',
label: t("Public"), label: t('Public'),
type: "check" type: 'check',
}, },
{ {
name: "cluster_template_hidden", name: 'hidden',
label: t("Hidden"), label: t('Hidden'),
type: "check" type: 'check',
}, },
{ {
name: "docker_registry_enabled", name: 'registry_enabled',
label: t("Enable Registry"), label: t('Enable Registry'),
type: "check" type: 'check',
}, },
{ {
name: "tls_disabled", name: 'tls_disabled',
label: t("Disable TLS"), label: t('Disable TLS'),
type: "check" type: 'check',
} },
] ];
} }
} }
export default inject("rootStore")(observer(StepInfo)) export default inject('rootStore')(observer(StepInfo));

View File

@ -10,8 +10,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import Base from "components/Form"; import Base from 'components/Form';
import { inject, observer } from "mobx-react"; import { inject, observer } from 'mobx-react';
import KeyValueInput from 'components/FormItem/KeyValueInput'; import KeyValueInput from 'components/FormItem/KeyValueInput';
export class StepLabel extends Base { export class StepLabel extends Base {
@ -23,6 +23,30 @@ export class StepLabel extends Base {
return t('Labels'); return t('Labels');
} }
get isStep() {
return true;
}
get isEdit() {
return !!this.props.extra;
}
get defaultValue() {
const values = {};
if (this.isEdit) {
const {
extra: { labels },
} = this.props;
values.additionalLabels = Object.keys(labels || {}).map((key) => ({
value: {
key,
value: labels[key],
},
}));
}
return values;
}
get formItems() { get formItems() {
return [ return [
{ {
@ -32,8 +56,8 @@ export class StepLabel extends Base {
itemComponent: KeyValueInput, itemComponent: KeyValueInput,
addText: t('Add Label'), addText: t('Add Label'),
}, },
] ];
} }
} }
export default inject("rootStore")(observer(StepLabel)) export default inject('rootStore')(observer(StepLabel));

View File

@ -18,10 +18,11 @@ import globalNetworkStore from 'src/stores/neutron/network';
import globalSubnetStore from 'src/stores/neutron/subnet'; import globalSubnetStore from 'src/stores/neutron/subnet';
export class StepNetwork extends Base { export class StepNetwork extends Base {
init() { async init() {
const { extra: { fixed_network } = {} } = this.props;
this.state.selectedSubnetId = fixed_network || '';
this.getFloatingIps(); this.getFloatingIps();
this.getSubnets(); this.getSubnets();
this.state = { selectedSubnetId: '' };
} }
get title() { get title() {
@ -46,7 +47,11 @@ export class StepNetwork extends Base {
get getFloatingIpList() { get getFloatingIpList() {
return (globalNetworkStore.list.data || []) return (globalNetworkStore.list.data || [])
.filter((it) => it['router:external'] === true && it.project_id === this.currentProjectId) .filter(
(it) =>
it['router:external'] === true &&
it.project_id === this.currentProjectId
)
.map((it) => ({ .map((it) => ({
value: it.id, value: it.id,
label: it.name, label: it.name,
@ -55,7 +60,11 @@ export class StepNetwork extends Base {
get getPrivateFloatingIpList() { get getPrivateFloatingIpList() {
return (globalNetworkStore.list.data || []) return (globalNetworkStore.list.data || [])
.filter((it) => it['router:external'] === false && it.project_id === this.currentProjectId) .filter(
(it) =>
it['router:external'] === false &&
it.project_id === this.currentProjectId
)
.map((it) => ({ .map((it) => ({
value: it.id, value: it.id,
label: it.name, label: it.name,
@ -80,49 +89,71 @@ export class StepNetwork extends Base {
this.setState({ this.setState({
selectedSubnetId: value, selectedSubnetId: value,
}); });
this.resetFormValue(['fixedSubnet']); this.resetFormValue(['fixed_subnet']);
} }
get getNetworkDriver() { get getNetworkDriver() {
const { context = {} } = this.props; const { context = {} } = this.props;
const { const { coeSelectRows = '', coe = '' } = context;
coeSelectRows = "", const networkDriver = [];
coe = ""
} = context;
let networkDriver = [];
if (!coeSelectRows || !coe) { if (!coeSelectRows || !coe) {
networkDriver.push({ val: "docker", name: "Docker" }, { val: "flannel", name: "Flannel" }, { val: "calico", name: "Calico" }) networkDriver.push(
{ val: 'docker', name: 'Docker' },
{ val: 'flannel', name: 'Flannel' },
{ val: 'calico', name: 'Calico' }
);
} }
if (coeSelectRows === "swarm" || coeSelectRows === "swarm-mode") { if (coeSelectRows === 'swarm' || coeSelectRows === 'swarm-mode') {
networkDriver.push({ val: "docker", name: "Docker" }, { val: "flannel", name: "Flannel" }) networkDriver.push(
{ val: 'docker', name: 'Docker' },
{ val: 'flannel', name: 'Flannel' }
);
} }
if (coeSelectRows === "kubernetes") { if (coeSelectRows === 'kubernetes') {
networkDriver.push({ val: "calico", name: "Calico" }, { val: "flannel", name: "Flannel" }) networkDriver.push(
{ val: 'calico', name: 'Calico' },
{ val: 'flannel', name: 'Flannel' }
);
} }
if (coeSelectRows === "mesos" || coeSelectRows === "dcos") { if (coeSelectRows === 'mesos' || coeSelectRows === 'dcos') {
networkDriver.push({ val: "docker", name: "Docker" }) networkDriver.push({ val: 'docker', name: 'Docker' });
} }
return (networkDriver || []) return (networkDriver || []).map((it) => ({
.map((it) => ({
value: it.val, value: it.val,
label: it.name, label: it.name,
})); }));
} }
get defaultValue() { get defaultValue() {
const values = {}; let values = {};
if (this.isEdit) { if (this.isEdit) {
values.networkDriver = this.props.extra.network_driver; const {
values.HTTPProxy = this.props.extra.http_proxy; extra: {
values.HTTPSProxy = this.props.extra.https_proxy; network_driver,
values.noProxy = this.props.extra.no_proxy; http_proxy,
values.externalNetworkID = this.props.extra.external_network_id; https_proxy,
values.fixedNetwork = this.props.extra.fixed_network; no_proxy,
values.fixedSubnet = this.props.extra.fixed_subnet; external_network_id,
values.DNS = this.props.extra.dns_nameserver; fixed_network,
values.masterLB = this.props.extra.master_lb_enabled; fixed_subnet,
values.floatingIP = this.props.extra.floating_ip_enabled; dns_nameserver,
master_lb_enabled,
floating_ip_enabled,
} = {},
} = this.props;
values = {
network_driver,
http_proxy,
https_proxy,
no_proxy,
external_network_id,
fixed_network,
fixed_subnet,
dns_nameserver,
master_lb_enabled,
floating_ip_enabled,
};
} }
return values; return values;
} }
@ -130,78 +161,70 @@ export class StepNetwork extends Base {
get formItems() { get formItems() {
return [ return [
{ {
name: "networkDriver", name: 'network_driver',
label: t("Network Driver"), label: t('Network Driver'),
placeholder: t("Choose a Network Driver"), placeholder: t('Choose a Network Driver'),
type: "select", type: 'select',
options: this.getNetworkDriver, options: this.getNetworkDriver,
allowClear: true,
showSearch: true
}, },
{ {
name: "HTTPProxy", name: 'http_proxy',
label: t("HTTP Proxy"), label: t('HTTP Proxy'),
placeholder: t("The http_proxy address to use for nodes in cluster"), placeholder: t('The http_proxy address to use for nodes in cluster'),
type: "input" type: 'input',
}, },
{ {
name: "HTTPSProxy", name: 'https_proxy',
label: t("HTTPS Proxy"), label: t('HTTPS Proxy'),
placeholder: t("The https_proxy address to use for nodes in cluster"), placeholder: t('The https_proxy address to use for nodes in cluster'),
type: "input" type: 'input',
}, },
{ {
name: "noProxy", name: 'no_proxy',
label: t("No Proxy"), label: t('No Proxy'),
placeholder: t("The no_proxy address to use for nodes in cluster"), placeholder: t('The no_proxy address to use for nodes in cluster'),
type: "input" type: 'input',
}, },
{ {
name: "externalNetworkID", name: 'external_network_id',
label: t("External Network ID"), label: t('External Network'),
placeholder: t("Choose a External Network ID"), placeholder: t('Choose a External Network'),
type: "select", type: 'select',
options: this.getFloatingIpList, options: this.getFloatingIpList,
allowClear: true,
showSearch: true
}, },
{ {
name: "fixedNetwork", name: 'fixed_network',
label: t("Fixed Network"), label: t('Fixed Network'),
placeholder: t("Choose a Private Network ID"), placeholder: t('Choose a Private Network'),
type: "select", type: 'select',
options: this.getPrivateFloatingIpList, options: this.getPrivateFloatingIpList,
onChange: (val) => this.onSelectChangeFixedNetwork(val), onChange: (val) => this.onSelectChangeFixedNetwork(val),
allowClear: true,
showSearch: true
}, },
{ {
name: "fixedSubnet", name: 'fixed_subnet',
label: t("Fixed Subnet"), label: t('Fixed Subnet'),
placeholder: t("Choose a Private Network at first"), placeholder: t('Choose a Private Network at first'),
type: "select", type: 'select',
options: this.getSubnetList, options: this.getSubnetList,
allowClear: true,
showSearch: true
}, },
{ {
name: "DNS", name: 'dns_nameserver',
label: t("DNS"), label: t('DNS'),
placeholder: t("The DNS nameserver to use for this cluster template"), placeholder: t('The DNS nameserver to use for this cluster template'),
type: "input" type: 'input',
}, },
{ {
name: "masterLB", name: 'master_lb_enabled',
label: t("Master LB"), label: t('Master LB'),
type: "check" type: 'check',
}, },
{ {
name: "floatingIP", name: 'floating_ip_enabled',
label: t("Floating IP"), label: t('Floating IP'),
type: "check" type: 'check',
} },
] ];
} }
} }
export default inject("rootStore")(observer(StepNetwork)) export default inject('rootStore')(observer(StepNetwork));

View File

@ -94,18 +94,33 @@ export class StepNodeSpec extends Base {
}; };
get defaultValue() { get defaultValue() {
const values = {}; let values = {};
if (this.isEdit) { if (this.isEdit) {
values.image = this.props.extra.image_id; const {
values.keypair = this.props.extra.keypair_id; extra: {
values.flavorCurrent = this.props.extra.flavor_id; image_id,
values.flavor = this.props.extra.flavor_id; keypair_id,
values.masterFlavor = this.props.extra.master_flavor_id; flavor_id,
values.masterFlavorCurrent = this.props.extra.master_flavor_id; master_flavor_id,
values.volumeDriver = this.props.extra.volume_driver; volume_driver,
values.dockerStorageDriver = this.props.extra.docker_storage_driver; docker_storage_driver,
values.dockerVolumeSize = this.props.extra.docker_volume_size; docker_volume_size,
} = {},
} = this.props;
values = {
image_id,
keypair_id,
volume_driver,
docker_storage_driver,
docker_volume_size,
};
if (flavor_id) {
values.flavor = { selectedRowKeys: [flavor_id] };
}
if (master_flavor_id) {
values.masterFlavor = { selectedRowKeys: [master_flavor_id] };
}
} }
return values; return values;
} }
@ -113,26 +128,17 @@ export class StepNodeSpec extends Base {
get formItems() { get formItems() {
return [ return [
{ {
name: 'image', name: 'image_id',
label: t('Image'), label: t('Image'),
type: 'select', type: 'select',
options: this.getImageOsDistroList, options: this.getImageOsDistroList,
allowClear: true, required: true,
showSearch: true,
}, },
{ {
name: 'keypair', name: 'keypair_id',
label: t('Keypair'), label: t('Keypair'),
type: 'select', type: 'select',
options: this.getKeypairList, options: this.getKeypairList,
allowClear: true,
showSearch: true,
},
{
name: 'flavorCurrent',
label: t('Current Flavor'),
type: 'label',
iconType: 'flavor',
}, },
{ {
name: 'flavor', name: 'flavor',
@ -140,12 +146,6 @@ export class StepNodeSpec extends Base {
type: 'select-table', type: 'select-table',
component: <FlavorSelectTable onChange={this.onFlavorChange} />, component: <FlavorSelectTable onChange={this.onFlavorChange} />,
}, },
{
name: 'masterFlavorCurrent',
label: t('Current Master Flavor'),
type: 'label',
iconType: 'flavor',
},
{ {
name: 'masterFlavor', name: 'masterFlavor',
label: t('Master Flavor'), label: t('Master Flavor'),
@ -153,15 +153,13 @@ export class StepNodeSpec extends Base {
component: <FlavorSelectTable onChange={this.onFlavorChange} />, component: <FlavorSelectTable onChange={this.onFlavorChange} />,
}, },
{ {
name: 'volumeDriver', name: 'volume_driver',
label: t('Volume Driver'), label: t('Volume Driver'),
type: 'select', type: 'select',
options: this.getVolumeDriver, options: this.getVolumeDriver,
allowClear: true,
showSearch: true,
}, },
{ {
name: 'dockerStorageDriver', name: 'docker_storage_driver',
label: t('Docker Storage Driver'), label: t('Docker Storage Driver'),
type: 'select', type: 'select',
options: [ options: [
@ -174,15 +172,13 @@ export class StepNodeSpec extends Base {
value: 'overlay2', value: 'overlay2',
}, },
], ],
allowClear: true,
showSearch: true,
}, },
{ {
name: 'dockerVolumeSize', name: 'docker_volume_size',
label: t('Docker Volume Size (GiB)'), label: t('Docker Volume Size (GiB)'),
type: 'input-number', type: 'input-int',
min: '1', min: 1,
placeholder: 'Spec', placeholder: t('Spec'),
}, },
]; ];
} }

View File

@ -10,14 +10,15 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import StepInfo from "./StepInfo"; import { inject, observer } from 'mobx-react';
import StepNodeSpec from "./StepNodeSpec"; import { StepAction } from 'src/containers/Action';
import StepNetwork from "./StepNetwork"; import globalClusterTemplateStore from 'src/stores/magnum/clusterTemplates';
import StepLabel from "./StepLabel"; import { toJS } from 'mobx';
import { inject, observer } from "mobx-react"; import { admission_control_list } from 'resources/magnum/template';
import { StepAction } from "src/containers/Action"; import StepInfo from './StepInfo';
import globalClusterTemplateStore from "src/stores/magnum/clusterTemplates"; import StepNodeSpec from './StepNodeSpec';
import { toJS } from "mobx"; import StepNetwork from './StepNetwork';
import StepLabel from './StepLabel';
export class StepCreate extends StepAction { export class StepCreate extends StepAction {
init() { init() {
@ -25,29 +26,28 @@ export class StepCreate extends StepAction {
this.getDetail(); this.getDetail();
} }
static id = "create-cluster-template"; static id = 'create-cluster-template';
static title = t("Create Cluster Template"); static title = t('Create Cluster Template');
static path = "/container-infra/cluster-template/create"; static path = '/container-infra/cluster-template/create';
static policy = "container-infra:clustertemplate:create"; static policy = 'container-infra:clustertemplate:create';
static allowed() { static allowed() {
return Promise.resolve(true); return Promise.resolve(true);
} }
get name() { get name() {
return t("Create Cluster Template"); return t('Create Cluster Template');
} }
get listUrl() { get listUrl() {
return this.getRoutePath("clusterTemplate"); return this.getRoutePath('clusterTemplate');
} }
get isEdit() { get isEdit() {
const { pathname } = this.props.location; return this.path.includes('update');
return pathname.indexOf('update') >= 0;
} }
get hasExtraProps() { get hasExtraProps() {
@ -75,73 +75,53 @@ export class StepCreate extends StepAction {
get steps() { get steps() {
return [ return [
{ {
title: t("Info *"), title: t('Info *'),
component: StepInfo component: StepInfo,
}, },
{ {
title: t("Node Spec *"), title: t('Node Spec *'),
component: StepNodeSpec component: StepNodeSpec,
}, },
{ {
title: t("Network"), title: t('Network'),
component: StepNetwork component: StepNetwork,
}, },
{ {
title: t("Labels"), title: t('Labels'),
component: StepLabel component: StepLabel,
} },
] ];
} }
onSubmit = (values) => { onSubmit = (values) => {
const { flavor, masterFlavor, additionalLabels, ...rest } = values;
const requestLabels = {}; const requestLabels = {};
const { additionalLabels } = values;
if (additionalLabels) { if (additionalLabels) {
additionalLabels.forEach(item => { additionalLabels.forEach((item) => {
const labelKey = item.value.key.toLowerCase().trim(); const labelKey = item.value.key.toLowerCase().trim();
const labelValue = item.value.value.toLowerCase().trim(); const labelValue = item.value.value.toLowerCase().trim();
requestLabels[labelKey] = labelValue; requestLabels[labelKey] = labelValue;
}) });
} }
const body = { const body = {
labels: { labels: {
...requestLabels, ...requestLabels,
admission_control_list: 'NodeRestriction,NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,TaintNodesByCondition,Priority,DefaultTolerationSeconds,DefaultStorageClass,StorageObjectInUseProtection,PersistentVolumeClaimResize,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,RuntimeClass' admission_control_list,
}, },
fixed_subnet: values.fixedSubnet, ...rest,
master_flavor_id: values.masterFlavor, };
http_proxy: values.HTTPProxy != null ? values.HTTPProxy : null, if (flavor) {
https_proxy: values.HTTPSProxy != null ? values.HTTPSProxy : null, body.flavor_id = flavor.selectedRowKeys[0];
no_proxy: values.noProxy != null ? values.noProxy : null, }
keypair_id: values.keypair, if (masterFlavor) {
docker_volume_size: values.dockerVolumeSize, body.master_flavor_id = masterFlavor.selectedRowKeys[0];
external_network_id: values.externalNetworkID,
image_id: values.image,
volume_driver: values.volumeDriver,
public: values.cluster_template_public,
hidden: values.cluster_template_hidden,
tls_disabled: values.tls_disabled,
registry_enabled: values.docker_registry_enabled,
master_lb_enabled: values.masterLB,
floating_ip_enabled: values.floatingIP,
docker_storage_driver: values.dockerStorageDriver,
name: values.clusterTemplateName,
network_driver: values.networkDriver,
fixed_network: values.fixedNetwork,
coe: values.coe,
flavor_id: values.flavor,
dns_nameserver: values.DNS,
} }
if (this.isEdit) { if (this.isEdit) {
return this.store.update({ id: this.params.id }, body); return this.store.update({ id: this.params.id }, body);
} else { }
return this.store.create(body); return this.store.create(body);
} };
}
} }
export default inject("rootStore")(observer(StepCreate)) export default inject('rootStore')(observer(StepCreate));

View File

@ -9,19 +9,17 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import StepCreate from './StepCreate'; import Create from './StepCreate';
import DeleteClusterTemplates from './Delete'; import Delete from './Delete';
import EditClusterTemplateStep from './EditStep'; import Edit from './Edit';
const actionConfigs = { const actionConfigs = {
rowActions: { rowActions: {
firstAction: DeleteClusterTemplates, firstAction: Delete,
moreActions: [ moreActions: [{ action: Edit }],
{ action: EditClusterTemplateStep },
],
}, },
batchActions: [DeleteClusterTemplates], batchActions: [Delete],
primaryActions: [StepCreate], primaryActions: [Create],
}; };
export default actionConfigs; export default actionConfigs;

View File

@ -38,7 +38,9 @@ export class ClusterTemplates extends Base {
title: t('ID'), title: t('ID'),
dataIndex: 'uuid', dataIndex: 'uuid',
render: (data) => { render: (data) => {
return this.getLinkRender("containerInfraClusterTemplateDetail", data, { id: data }) return this.getLinkRender('containerInfraClusterTemplateDetail', data, {
id: data,
});
}, },
}, },
{ {
@ -56,10 +58,10 @@ export class ClusterTemplates extends Base {
isHideable: true, isHideable: true,
dataIndex: 'keypair_id', dataIndex: 'keypair_id',
render: (value) => { render: (value) => {
return this.getLinkRender("keypairDetail", value, { id: value }) return this.getLinkRender('keypairDetail', value, { id: value });
} },
}, },
]; ];
} }
export default inject("rootStore")(observer(ClusterTemplates)) export default inject('rootStore')(observer(ClusterTemplates));

View File

@ -20,7 +20,7 @@ import ClusterTemplates from '../containers/ClusterTemplates';
import ClusterTemplateDetail from '../containers/ClusterTemplates/Detail'; import ClusterTemplateDetail from '../containers/ClusterTemplates/Detail';
import ClustersCreate from '../containers/Clusters/actions/StepCreate'; import ClustersCreate from '../containers/Clusters/actions/StepCreate';
import ClustersTemplateCreate from '../containers/ClusterTemplates/actions/StepCreate'; import ClustersTemplateCreate from '../containers/ClusterTemplates/actions/StepCreate';
import StepUpdateClusterTemplate from '../containers/ClusterTemplates/actions/EditStep'; import StepUpdateClusterTemplate from '../containers/ClusterTemplates/actions/Edit';
const PATH = '/container-infra'; const PATH = '/container-infra';
export default [ export default [

View File

@ -0,0 +1,16 @@
// Copyright 2022 99cloud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
export const admission_control_list =
'NodeRestriction,NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,TaintNodesByCondition,Priority,DefaultTolerationSeconds,DefaultStorageClass,StorageObjectInUseProtection,PersistentVolumeClaimResize,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,RuntimeClass';

View File

@ -32,18 +32,20 @@ export class ClusterTemplatesStore extends Base {
} }
@action @action
async get(data) { async update({ id }, body) {
return this.client.get(data); const newBody = Object.keys(body).map((key) => ({
path: `/${key}`,
value: key === 'labels' ? JSON.stringify(body[key] || {}) : body[key],
op: [null, undefined, ''].includes(body[key]) ? 'remove' : 'replace',
}));
return this.submitting(this.client.patch(id, newBody));
} }
@action get mapper() {
async update({ id }, newbody) { return (data) => ({
return this.client.update(id, newbody); ...data,
} id: data.uuid,
});
async listDidFetch(items) {
if (!items.length) return items
return items.map(it => ({ ...it, id: it.uuid }));
} }
} }