From 26a95abdf24d6fd7fc7662c2799c24c3ba0a0811 Mon Sep 17 00:00:00 2001 From: songyg <94501396+RainBondsongyg@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:57:01 +0800 Subject: [PATCH] fix: install cluster init (#1329) * fix: install cluster init * fix: etcd file --------- Co-authored-by: songyg --- .../Cluster/ACKBuyConfig/index.less | 33 + src/components/Cluster/RKEClusterAdd/index.js | 9 + .../Cluster/RainbondClusterInit/index.js | 964 ++++++++++++++---- .../Cluster/RainbondClusterInit/index.less | 146 +++ .../Cluster/RainbondClusterInit/selectNode.js | 106 ++ src/pages/AddCluster/RainbondInit/index.js | 22 +- 6 files changed, 1097 insertions(+), 183 deletions(-) create mode 100644 src/components/Cluster/RainbondClusterInit/index.less create mode 100644 src/components/Cluster/RainbondClusterInit/selectNode.js diff --git a/src/components/Cluster/ACKBuyConfig/index.less b/src/components/Cluster/ACKBuyConfig/index.less index 1b25e7b14..ca86473da 100644 --- a/src/components/Cluster/ACKBuyConfig/index.less +++ b/src/components/Cluster/ACKBuyConfig/index.less @@ -9,4 +9,37 @@ li { line-height: 24px; } +} +.selectRow{ + :global{ + .ant-form-explain{ + margin-left: 230px; + } + } +} +.panelTitle{ + width: 200px; + display: inline-block; + font-size: 16px; + font-weight: 600; +} +.panelSpan{ + width: 540px; + display: inline-block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: -7px; + font-size: 14px; + color: #8d8d8d; +} +.spanList{ + display: inline-block; + width: 340px; + margin-top: 4px; + margin-left: 20px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: -7px; } \ No newline at end of file diff --git a/src/components/Cluster/RKEClusterAdd/index.js b/src/components/Cluster/RKEClusterAdd/index.js index 6541634f7..c7d40fc33 100644 --- a/src/components/Cluster/RKEClusterAdd/index.js +++ b/src/components/Cluster/RKEClusterAdd/index.js @@ -623,6 +623,15 @@ export default class RKEClusterConfig extends PureComponent { const { getFieldValue } = form; const info = {}; const yamls = getFieldValue('yamls') || yamlVal; + const ipArr = dataSource.map(item => { + return { + ip: item.ip, + internalIP: item.internalIP, + } + }); + const jsonString = JSON.stringify(ipArr); + // 使用localStorage存储JSON字符串 + window.localStorage.setItem("ipAddresses", jsonString); if (yamls || (dataSource && dataSource.length > 0)) { if (key === '2') { info.nodes = dataSource; diff --git a/src/components/Cluster/RainbondClusterInit/index.js b/src/components/Cluster/RainbondClusterInit/index.js index c8007fc88..94cdc9b67 100644 --- a/src/components/Cluster/RainbondClusterInit/index.js +++ b/src/components/Cluster/RainbondClusterInit/index.js @@ -9,7 +9,13 @@ import { Form, Modal, notification, - Typography + Typography, + Collapse, + Input, + Row, + AutoComplete, + Radio, + Switch } from 'antd'; import { connect } from 'dva'; import React, { Fragment, PureComponent } from 'react'; @@ -21,10 +27,15 @@ import { import cloud from '../../../utils/cloud'; import globalUtil from '../../../utils/global'; import CodeMirrorForm from '../../CodeMirrorForm'; -import styles from '../ACKBuyConfig/index.less'; import ClusterComponents from '../ClusterComponents'; import InitRainbondDetail from '../ShowInitRainbondDetail'; +import yaml from 'js-yaml' +import SelectNode from './selectNode'; +import Etcd from '../../../pages/AddCluster/component/etcd'; +import styles from './index.less'; + +const { Panel } = Collapse; const { Paragraph } = Typography; @connect(({ global }) => ({ @@ -41,10 +52,20 @@ export default class RainbondClusterInit extends PureComponent { showInitDetail: false, task: null, isComponents: false, - guideStep: 10 + guideStep: 10, + ipArray: [], + isStorage: 'default', + isEtcd: 'default', + isImage: 'default', + isDatabase: 'default', + isMirror: 'default', + isEctype: 'default' }; } componentDidMount() { + const storedJsonString = window.localStorage.getItem("ipAddresses"); + const storedIpAddressArray = JSON.parse(storedJsonString); + this.setState({ ipArray: storedIpAddressArray }); this.loadTask(); } @@ -57,48 +78,45 @@ export default class RainbondClusterInit extends PureComponent { rainbondInfo, enterprise } = this.props; - const { checked, task } = this.state; - if (checked) { - this.setState({ loading: true }); - dispatch({ - type: 'cloud/initRainbondRegion', - payload: { - enterprise_id: eid, - providerName: selectProvider, - clusterID, - retry: task && task.status === 'complete' - }, - callback: data => { - if (data) { - globalUtil.putInstallClusterLog(enterprise, rainbondInfo, { - eid, - taskID: data.taskID, - status: 'start', - install_step: 'createRainbond', - provider: selectProvider - }); - this.setState({ - loading: false, - task: data, - showInitDetail: true - }); - } - }, - handleError: res => { - if (res && res.data && res.data.code === 7005) { - this.setState({ - loading: false, - showInitDetail: true, - task: res.data.data - }); - return; - } - cloud.handleCloudAPIError(res); + const { task } = this.state; + this.setState({ loading: true }); + dispatch({ + type: 'cloud/initRainbondRegion', + payload: { + enterprise_id: eid, + providerName: selectProvider, + clusterID, + retry: task && task.status === 'complete' + }, + callback: data => { + if (data) { + globalUtil.putInstallClusterLog(enterprise, rainbondInfo, { + eid, + taskID: data.taskID, + status: 'start', + install_step: 'createRainbond', + provider: selectProvider + }); + this.setState({ + loading: false, + task: data, + showInitDetail: true + }); } - }); - } else { - notification.warning({ message: formatMessage({id:'notification.warn.read'}) }); - } + }, + handleError: res => { + if (res && res.data && res.data.code === 7005) { + this.setState({ + loading: false, + showInitDetail: true, + task: res.data.data + }); + return; + } + cloud.handleCloudAPIError(res); + } + }); + }; loadTask = noopen => { @@ -167,20 +185,102 @@ export default class RainbondClusterInit extends PureComponent { }; handleSubmit = () => { const { form, eid, clusterID } = this.props; + const { ipArray } = this.state; form.validateFields((err, values) => { + let dataObj = { + apiVersion: 'rainbond.io/v1alpha1', + kind: 'RainbondCluster', + metadata: { + name: 'rainbondcluster', + namespace: 'rbd-system' + }, + spec: {} + }; if (!err) { - setRainbondClusterConfig( - { enterprise_id: eid, clusterID, config: values.config }, - res => { - if (res && res.data && res.data.code === 404) { - return; + if (values.gatewayIngressIPs) { + dataObj.spec.gatewayIngressIPs = values.gatewayIngressIPs + } + + if (values.nodesForGateway) { + const gatewayArr = []; + for (let i = 0; i < values.nodesForGateway.length; i++) { + for (let j = 0; j < ipArray.length; j++) { + if (values.nodesForGateway[i].name === ipArray[j].ip) { + // 合并两个对象 + let mergedObject = { + name: values.nodesForGateway[i].name, + internalIP: ipArray[j].internalIP, + externalIP: ipArray[j].ip + }; + gatewayArr.push(mergedObject); + } } - cloud.handleCloudAPIError(res); } - ).then(re => { - if (re && re.status_code === 200) { - notification.success({ message: formatMessage({id:'notification.success.setting_successfully'}) }); - this.setState({ showClusterInitConfig: false }); + dataObj.spec.nodesForGateway = gatewayArr + } + if (values.nodesForChaos) { + dataObj.spec.nodesForChaos = values.nodesForChaos + } + if (values.isEtcd == 'custom') { + dataObj.spec.etcdConfig = { + endpoints: values.endpoints.map(item => item.ip) + } + dataObj.spec.etcdConfig = { + secretName: values.secretName + } + } + if (values.advanced) { + dataObj.spec.enableHA = true + } else { + dataObj.spec.enableHA = false + } + if (values.image == 'custom') { + dataObj.spec.imageHub = { + domain: values.domain + } + + dataObj.spec.imageHub = { + namespace: values.namespace + } + dataObj.spec.imageHub = { + username: values.username + } + dataObj.spec.imageHub = { + password: values.password + } + } + if (values.isStorage == 'custom') { + dataObj.spec.rainbondVolumeSpecRWX = { + storageClassName: values.storageClassName1 + } + dataObj.spec.rainbondVolumeSpecRWO = { + storageClassName: values.storageClassName2 + } + } + if (values.database == 'custom') { + dataObj.spec.regionDatabase = { + host: values.regionDatabase_host, + port: values.regionDatabase_port, + username: values.regionDatabase_username, + password: values.regionDatabase_password, + dbname: values.regionDatabase_dbname + } + } + if (values.mirror == 'custom') { + dataObj.spec.rainbondImageRepository = values.mirror_address + } + if (values.ectype == 'custom') { + dataObj.spec.replicas = Number(values.replicas) + } + + const yamls = yaml.dump(dataObj) + setRainbondClusterConfig({ + enterprise_id: eid, + clusterID, + config: yamls + }).then(res => { + if (res && res.status_code === 200) { + this.initRainbondCluster() } }); } @@ -192,7 +292,7 @@ export default class RainbondClusterInit extends PureComponent { }); }; handleNewbieGuiding = info => { - const { prevStep, nextStep, handleClick = () => {} } = info; + const { prevStep, nextStep, handleClick = () => { } } = info; return ( { + if (value && value.length > 0) { + let isPass = false; + value.some(item => { + if (item.ip || item.name) { + isPass = true; + } else { + isPass = false; + return true; + } + }); + if (isPass) { + callback(); + } else { + callback('请填写完整的节点名称'); + } + } else { + callback(); + } + }; + hanldeStorageChange = (e) => { + this.setState({ isStorage: e.target.value }); + } + hanldeEtcdChange = (e) => { + this.setState({ isEtcd: e.target.value }); + } + hanldeImageChange = (e) => { + this.setState({ isImage: e.target.value }); + } + hanldeDatabaseChange = (e) => { + this.setState({ isDatabase: e.target.value }); + } + hanldeMirrorChange = (e) => { + this.setState({ isMirror: e.target.value }); + } + hanldeEctypeChange = (e) => { + this.setState({ isEctype: e.target.value }); + } render() { const { preStep, eid, selectProvider, form, clusterID } = this.props; const { @@ -229,7 +368,14 @@ export default class RainbondClusterInit extends PureComponent { initconfig, isComponents, guideStep, - checked + checked, + ipArray, + isStorage, + isEtcd, + isImage, + isDatabase, + isMirror, + isEctype } = this.state; const formItemLayout = { labelCol: { @@ -239,125 +385,602 @@ export default class RainbondClusterInit extends PureComponent { xs: { span: 24 } } }; + const is_formItemLayout = { + labelCol: { + xs: { span: 2 }, + sm: { span: 2 } + }, + wrapperCol: { + xs: { span: 6 }, + sm: { span: 6 } + } + }; const { getFieldDecorator, setFieldsValue } = form; const highlighted = guideStep === 10 ? { - position: 'relative', - zIndex: 1000, - padding: '0 16px', - margin: '0 -16px', - background: '#fff' - } + position: 'relative', + zIndex: 1000, + padding: '0 16px', + margin: '0 -16px', + background: '#fff' + } : {}; const showComponent = (selectProvider === 'rke' || selectProvider === 'custom') && ( - - ); + + ); return (
-

- - {selectProvider === 'ack' && ( - -
    -
  • - - - -
  • -
  • - - - -
  • -
  • - - - -
  • -
  • - - - -
  • -
-
- )} - {(selectProvider === 'rke' || selectProvider === 'custom') && ( - - - - )} - - - - - {guideStep === 10 && - this.handleNewbieGuiding({ - tit: formatMessage({id:'enterpriseColony.RainbondClusterInit.service'}), - send: false, - configName: 'kclustersAttentionAttention', - nextStep: 11, - btnText: formatMessage({id:'enterpriseColony.RainbondClusterInit.Known'}), - conPosition: { left: 0, bottom: '-192px' }, - svgPosition: { left: '3px', marginTop: '-19px' }, - handleClick: () => { - this.setState({ checked: true }); - } - })} - + {getFieldDecorator('storageClassName1', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_storageClass' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + } + + {isStorage == 'custom' && + } + > + {getFieldDecorator('storageClassName2', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.StorageClass' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + } + + +
+ Etcd +
+ } + > + {getFieldDecorator('isEtcd', { + initialValue: isEtcd + })( + + 默认 + 自定义 + + )} + + {isEtcd == 'custom' && + } + > + {getFieldDecorator('secretName', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.inpiut_name' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + } + {isEtcd == 'custom' && + } + > + {getFieldDecorator('endpoints', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_node' }) + }, + { + validator: this.handleValidatorsNodes + } + ] + })()} + } +
+ + + + {/* 高级配置说明 */} + + + 高级配置说明 + } + key="advanced" + > + {/* 高可用 */} + +
+ 高可用 +
+ } + > + {getFieldDecorator('advanced', { + })( + + )} + +
+ {/* 镜像仓库 */} + +
+ 镜像仓库 +
+ } + > + {getFieldDecorator('image', { + initialValue: isImage + })( + + 默认 + 自定义 + + )} + + {isImage == 'custom' && + <> + } + className={styles.antd_form} + > + {getFieldDecorator('domain', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.add_mirror' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + + } + className={styles.antd_form} + > + {getFieldDecorator('namespace', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_namespace' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })( + + )} + + } + className={styles.antd_form} + > + {getFieldDecorator('username', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_user_name' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + + } + className={styles.antd_form} + > + {getFieldDecorator('password', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_password' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + + } +
+ {/* 数据库 */} + +
+ 数据库 +
+ } + > + {getFieldDecorator('database', { + initialValue: isDatabase + })( + + 默认 + 自定义 + + )} + + {isDatabase == 'custom' && + <> + } + style={{ display: 'flex' }} + > + {/* 控制台数据库 */} + {getFieldDecorator('regionDatabase_host', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_address' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + + {/* 连接端口 */} + } + style={{ display: 'flex' }} + > + {/* 控制台数据库 */} + {getFieldDecorator('regionDatabase_port', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_port' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + + {/* 用户名 */} + } + style={{ display: 'flex' }} + > + {/* 控制台数据库 */} + {getFieldDecorator('regionDatabase_username', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_user_name' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + + {/* 密码 */} + } + style={{ display: 'flex' }} + > + {/* 控制台数据库 */} + {getFieldDecorator('regionDatabase_password', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_password' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + + {/* 数据库名称 */} + } + style={{ display: 'flex' }} + > + {/* 控制台数据库 */} + {getFieldDecorator('regionDatabase_dbname', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_access_name' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })( + + )} + + } +
+ {/* 组件镜像源 */} + +
+ 组件镜像源 +
+ } + > + {getFieldDecorator('mirror', { + initialValue: isMirror + })( + + 默认 + 自定义 + + )} + + {isMirror == 'custom' && + + {/* 仓库地址 */} + {getFieldDecorator('mirror_address', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_address' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + } +
+ {/* 副本数 */} + +
+ 副本数 +
+ } + > + {getFieldDecorator('ectype', { + initialValue: isEctype + })( + + 默认 + 自定义 + + )} + + {isEctype == 'custom' && + + {/* 仓库地址 */} + {getFieldDecorator('replicas', { + rules: [ + { + required: true, + message: formatMessage({ id: 'enterpriseColony.Advanced.input_address' }) + }, + { + pattern: /^[^\s]*$/, + message: formatMessage({ id: 'placeholder.no_spaces' }) + } + ] + })()} + } +
+
+
+
+ {task && task.status !== 'complete' ? ( {showComponent} + ) : ( {showComponent} )} {guideStep === 11 && this.handleNewbieGuiding({ - tit: formatMessage({id:'enterpriseColony.RainbondClusterInit.start'}), - desc: formatMessage({id:'enterpriseColony.RainbondClusterInit.configuration'}), + tit: formatMessage({ id: 'enterpriseColony.RainbondClusterInit.start' }), + desc: formatMessage({ id: 'enterpriseColony.RainbondClusterInit.configuration' }), send: true, configName: 'kclustersAttentionAttention', nextStep: 12, conPosition: { left: '63%', bottom: '-39px' }, svgPosition: { left: '58%', marginTop: '-13px' }, handleClick: () => { - this.initRainbondCluster(); + this.handleSubmit(); } })} @@ -420,8 +1044,7 @@ export default class RainbondClusterInit extends PureComponent { taskID={task.taskID} /> )} - {showClusterInitConfig && ( - } onOk={this.handleSubmit} @@ -449,8 +1072,7 @@ export default class RainbondClusterInit extends PureComponent { message={} width="750px" /> - - )} + */} ); } diff --git a/src/components/Cluster/RainbondClusterInit/index.less b/src/components/Cluster/RainbondClusterInit/index.less new file mode 100644 index 000000000..cf04c6025 --- /dev/null +++ b/src/components/Cluster/RainbondClusterInit/index.less @@ -0,0 +1,146 @@ +.typeBtnWrap{ + text-align: center; + font-size: 16px; + float:left; + width: 150px; + margin-right: 24px; + .typeBtn { + display: block; + cursor: pointer; + height:40px; + line-height: 40px; + width: 150px; + margin-bottom:-3px; + position: relative; + :global { + .anticon {visibility: hidden;margin-left: 30px} + } + border:1px solid #e8e8e8; + margin-bottom: -1px; + background: #fafafa; + + } + .typeBtn:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; + } + .typeBtn:last-child { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + } + .active { + background: #fff; + z-index:1; + + :global { + .anticon {visibility: visible;} + } + } + +} +.en_typeBtnWrap{ + text-align: center; + font-size: 16px; + float:left; + width: 180px; + margin-right: 24px; + .en_typeBtn { + display: block; + cursor: pointer; + height:40px; + line-height: 40px; + width: 180px; + margin-bottom:-3px; + position: relative; + :global { + .anticon {visibility: hidden;margin-left: 15px} + } + border:1px solid #e8e8e8; + margin-bottom: -1px; + background: #fafafa; + + } + .en_typeBtn:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; + } + .en_typeBtn:last-child { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + } + .active { + background: #fff; + z-index:1; + + :global { + .anticon {visibility: visible;} + } + } + +} + +.content { + min-height: 500px; +} + +.ant_radio_disabled{ + :global{ + span{ + color: rgba(0, 0, 0, 0.65); + } + .ant-form-explain{ + + } + } +} + +.ports { + + +} +.selectRow{ + :global{ + .ant-form-explain{ + margin-left: 230px; + } + } +} +.panelTitle{ + width: 200px; + display: inline-block; + font-size: 16px; + font-weight: 600; +} +.panelSpan{ + width: 540px; + display: inline-block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: -7px; + font-size: 14px; + color: #8d8d8d; +} +.spanList{ + display: inline-block; + width: 340px; + margin-top: 4px; + margin-left: 20px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: -7px; +} + +.basics{ + .row{ + padding: 12px 24px; + border-bottom: 1px dashed #e8e8e8; + .title_name{ + font-weight: bold; + font-size: 16px; + margin-bottom: 12px; + } + } + +} diff --git a/src/components/Cluster/RainbondClusterInit/selectNode.js b/src/components/Cluster/RainbondClusterInit/selectNode.js new file mode 100644 index 000000000..a6f16f422 --- /dev/null +++ b/src/components/Cluster/RainbondClusterInit/selectNode.js @@ -0,0 +1,106 @@ +/* eslint-disable react/sort-comp */ +import { Col, Icon, Select, Row } from 'antd'; +import React, { Component } from 'react'; +import { formatMessage, FormattedMessage } from 'umi-plugin-locale'; + +const { Option } = Select; +class DAinput extends Component { + constructor(props) { + super(props); + this.state = { + values: [{ name: '' }] + }; + } + handleNodes = (value, index) => { + const { values } = this.state; + values[index].name = value; + this.triggerChange(values); + this.setValues(values); + }; + setValues(arr) { + const setArr = arr || []; + if (!setArr.length) { + setArr.push({ name: '' }); + } + this.setState({ values: setArr }); + } + initFromProps(value) { + const setValue = value; + if (setValue) { + this.setValues(setValue); + } + } + add = () => { + const { values } = this.state; + if (values.length > 99) { + return null; + } + this.setState({ + values: values.concat({ name: '' }) + }); + }; + + remove = index => { + const { values } = this.state; + values.splice(index, 1); + this.setValues(values); + this.triggerChange(values); + }; + triggerChange(values) { + const res = []; + for (let i = 0; i < values.length; i++) { + res.push({ + name: values[i].name + }); + } + const { onChange } = this.props; + if (onChange) { + onChange(res); + } + } + render() { + const namePlaceholder = `${formatMessage({id:'enterpriseColony.Advanced.master'})}`; + const { values } = this.state; + const { keys, ipArr } = this.props; + return ( +
+ {values.map((item, index) => { + const first = index === 0; + return ( + + + + + + { + if (first) { + this.add(); + } else { + this.remove(index); + } + }} + /> + + + ); + })} +
+ ); + } +} + +export default DAinput; diff --git a/src/pages/AddCluster/RainbondInit/index.js b/src/pages/AddCluster/RainbondInit/index.js index 3eac63757..8f9718bae 100644 --- a/src/pages/AddCluster/RainbondInit/index.js +++ b/src/pages/AddCluster/RainbondInit/index.js @@ -111,18 +111,16 @@ export default class RainbondInit extends PureComponent { ))} - - - - - + + + ); }