import { intl } from '@/utils/intl'; import { useState, useEffect } from 'react'; import { useModel } from 'umi'; import { Space, Button, Tooltip, Row, Switch, Table, Spin, Form, message, } from 'antd'; import { QuestionCircleOutlined } from '@ant-design/icons'; import { ProCard, ProForm, ProFormText, ProFormRadio, ProFormDigit, } from '@ant-design/pro-components'; import type { ColumnsType } from 'antd/es/table'; import { handleQuit, getErrorInfo, getRandomPassword } from '@/utils'; import useRequest from '@/utils/useRequest'; import { queryComponentParameters } from '@/services/ob-deploy-web/Components'; import Parameter from './Parameter'; import TooltipInput from './TooltipInput'; import { commonStyle, pathRule, onlyComponentsKeys, componentsConfig, componentVersionTypeToComponent, } from '../constants'; import { getLocale } from 'umi'; import EnStyles from './indexEn.less'; import ZhStyles from './indexZh.less'; const locale = getLocale(); const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; interface Parameter extends API.Parameter { description?: string; } interface FormValues extends API.Components { oceanbase?: { mode?: string; parameters?: any; }; } const showConfigKeys = { oceanbase: [ 'home_path', 'mode', 'root_password', 'data_dir', 'redo_dir', 'mysql_port', 'rpc_port', ], obproxy: ['home_path', 'listen_port', 'prometheus_listen_port'], obagent: ['home_path', 'monagent_http_port', 'mgragent_http_port'], ocpexpress: ['home_path', 'port'], }; export default function ClusterConfig() { const { setCurrentStep, configData, setConfigData, currentType, lowVersion, clusterMore, setClusterMore, componentsMore, setComponentsMore, clusterMoreConfig, setClusterMoreConfig, componentsMoreConfig, setComponentsMoreConfig, handleQuitProgress, setErrorVisible, setErrorsList, errorsList, } = useModel('global'); const { components = {}, home_path } = configData || {}; const { oceanbase = {}, ocpexpress = {}, obproxy = {}, obagent = {}, } = components; const [form] = ProForm.useForm(); const [currentMode, setCurrentMode] = useState( oceanbase?.mode || 'PRODUCTION', ); const [passwordVisible, setPasswordVisible] = useState(true); const [clusterMoreLoading, setClusterMoreLoading] = useState(false); const [componentsMoreLoading, setComponentsMoreLoading] = useState(false); const { run: getMoreParamsters } = useRequest(queryComponentParameters); const formatParameters = (dataSource: any) => { if (dataSource) { const parameterKeys = Object.keys(dataSource); return parameterKeys.map((key) => { const { params, ...rest } = dataSource[key]; return { key, ...rest, ...params, }; }); } else { return []; } }; const setData = (dataSource: FormValues) => { let newComponents: API.Components = { ...components }; if (currentType === 'all') { newComponents.obproxy = { ...(components.obproxy || {}), ...dataSource.obproxy, parameters: formatParameters(dataSource.obproxy?.parameters), }; if (!lowVersion) { newComponents.ocpexpress = { ...(components.ocpexpress || {}), ...dataSource.ocpexpress, parameters: formatParameters(dataSource.ocpexpress?.parameters), }; } newComponents.obagent = { ...(components.obagent || {}), ...dataSource.obagent, parameters: formatParameters(dataSource.obagent?.parameters), }; } newComponents.oceanbase = { ...(components.oceanbase || {}), ...dataSource.oceanbase, parameters: formatParameters(dataSource.oceanbase?.parameters), }; setConfigData({ ...configData, components: newComponents }); }; const prevStep = () => { const formValues = form.getFieldsValue(true); setData(formValues); setCurrentStep(2); setErrorVisible(false); setErrorsList([]); window.scrollTo(0, 0); }; const nextStep = () => { form .validateFields() .then((values) => { setData(values); setCurrentStep(4); setErrorVisible(false); setErrorsList([]); window.scrollTo(0, 0); }) .catch(({ errorFields }) => { const errorName = errorFields?.[0].name; form.scrollToField(errorName); message.destroy(); if (errorName.includes('parameters')) { message.warning( intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.RequiredParametersForMoreConfigurations', defaultMessage: '更多配置有必填参数未填入', }), ); } }); }; const onValuesChange = (values: FormValues) => { if (values?.oceanbase?.mode) { setCurrentMode(values?.oceanbase?.mode); } }; const portValidator = (_: any, value: number) => { if (value) { if (value >= 1024 && value <= 65535) { return Promise.resolve(); } return Promise.reject( new Error( intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.ThePortNumberCanOnly', defaultMessage: '端口号只支持 1024~65535 范围', }), ), ); } }; const formatMoreConfig = (dataSource: API.ParameterMeta[]) => { return dataSource.map((item) => { const component = componentVersionTypeToComponent[item.component] ? componentVersionTypeToComponent[item.component] : item.component; const componentConfig = componentsConfig[component]; // filter out existing parameters let configParameter = item?.config_parameters.filter((parameter) => { return !showConfigKeys?.[componentConfig.componentKey]?.includes( parameter.name, ); }); const newConfigParameter: API.NewConfigParameter[] = configParameter.map( (parameterItem) => { return { ...parameterItem, parameterValue: { value: parameterItem.default, adaptive: parameterItem.auto, auto: parameterItem.auto, require: parameterItem.require, }, }; }, ); const result: API.NewParameterMeta = { ...item, componentKey: componentConfig.componentKey, label: componentConfig.labelName, configParameter: newConfigParameter, }; return result; }); }; const getInitialParameters = ( currentComponent: string, dataSource: API.MoreParameter[], data: API.NewParameterMeta[], ) => { const currentComponentNameConfig = data?.filter( (item) => item.component === currentComponent, )?.[0]; if (currentComponentNameConfig) { const parameters: any = {}; currentComponentNameConfig.configParameter.forEach((item) => { let parameter = { ...item, key: item.name, params: { value: item.default, adaptive: item.auto, auto: item.auto, require: item.require, }, }; dataSource?.some((dataItem) => { if (item.name === dataItem.key) { parameter = { key: dataItem.key, description: parameter.description, params: { ...parameter.params, ...dataItem, }, }; return true; } return false; }); parameters[item.name] = parameter; }); return parameters; } else { return undefined; } }; const getClusterMoreParamsters = async () => { setClusterMoreLoading(true); try { const { success, data } = await getMoreParamsters( {}, { filters: [ { component: oceanbase?.component, version: oceanbase?.version, is_essential_only: true, }, ], }, ); if (success) { const newClusterMoreConfig = formatMoreConfig(data?.items); setClusterMoreConfig(newClusterMoreConfig); form.setFieldsValue({ oceanbase: { parameters: getInitialParameters( oceanbase?.component, oceanbase?.parameters, newClusterMoreConfig, ), }, }); } } catch (e: any) { setClusterMore(false); const errorInfo = getErrorInfo(e); setErrorVisible(true); setErrorsList([...errorsList, errorInfo]); } setClusterMoreLoading(false); }; const getComponentsMoreParamsters = async () => { const filters: API.ParameterFilter[] = []; let currentOnlyComponentsKeys: string[] = onlyComponentsKeys; if (lowVersion) { currentOnlyComponentsKeys = onlyComponentsKeys.filter( (key) => key !== 'ocpexpress', ); } currentOnlyComponentsKeys.forEach((item) => { if (components[item]) { filters.push({ component: components[item]?.component, version: components[item]?.version, is_essential_only: true, }); } }); setComponentsMoreLoading(true); try { const { success, data } = await getMoreParamsters({}, { filters }); if (success) { const newComponentsMoreConfig = formatMoreConfig(data?.items); setComponentsMoreConfig(newComponentsMoreConfig); const setValues = { obproxy: { parameters: getInitialParameters( obproxy?.component, obproxy?.parameters, newComponentsMoreConfig, ), }, obagent: { parameters: getInitialParameters( obagent?.component, obagent?.parameters, newComponentsMoreConfig, ), }, }; if (!lowVersion) { setValues.ocpexpress = { parameters: getInitialParameters( ocpexpress?.component, ocpexpress?.parameters, newComponentsMoreConfig, ), }; } form.setFieldsValue(setValues); } } catch (e) { setComponentsMore(false); const errorInfo = getErrorInfo(e); setErrorVisible(true); setErrorsList([...errorsList, errorInfo]); } setComponentsMoreLoading(false); }; const handleCluserMoreChange = (checked: boolean) => { setClusterMore(checked); if (!clusterMoreConfig?.length) { getClusterMoreParamsters(); } }; const handleComponentsMoreChange = (checked: boolean) => { setComponentsMore(checked); if (!componentsMoreConfig?.length) { getComponentsMoreParamsters(); } }; const parameterValidator = (_: any, value?: API.ParameterValue) => { if (value?.adaptive) { return Promise.resolve(); } else if (value?.require && !value?.value) { return Promise.reject( new Error( intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.RequiredForCustomParameters', defaultMessage: '自定义参数时必填', }), ), ); } return Promise.resolve(); }; const getMoreColumns = (label: string, componentKey: string) => { const columns: ColumnsType = [ { title: label, dataIndex: 'name', width: 250, render: (text) => text || '-', }, { title: intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.ParameterValue', defaultMessage: '参数值', }), width: locale === 'zh-CN' ? 240 : 320, dataIndex: 'parameterValue', render: (text, record) => { return ( ); }, }, { title: intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.Introduction', defaultMessage: '介绍', }), dataIndex: 'description', render: (text, record) => text ? (
{text}
) : ( '-' ), }, ]; return columns; }; const getTableConfig = ( showVisible: boolean, dataSource: API.NewParameterMeta[], loading: boolean, ) => { return showVisible ? ( {dataSource.map((moreItem) => ( ))} ) : null; }; useEffect(() => { if (clusterMore && !clusterMoreConfig?.length) { getClusterMoreParamsters(); } if (componentsMore && !componentsMoreConfig?.length) { getComponentsMoreParamsters(); } }, []); const initPassword = getRandomPassword(); const initialValues = { oceanbase: { mode: oceanbase?.mode || 'PRODUCTION', root_password: oceanbase?.root_password || initPassword, data_dir: oceanbase?.data_dir || undefined, redo_dir: oceanbase?.redo_dir || undefined, mysql_port: oceanbase?.mysql_port || 2881, rpc_port: oceanbase?.rpc_port || 2882, parameters: getInitialParameters( oceanbase?.component, oceanbase?.parameters, clusterMoreConfig, ), }, obproxy: { listen_port: obproxy?.listen_port || 2883, prometheus_listen_port: obproxy?.prometheus_listen_port || 2884, parameters: getInitialParameters( obproxy?.component, obproxy?.parameters, componentsMoreConfig, ), }, obagent: { monagent_http_port: obagent?.monagent_http_port || 8088, mgragent_http_port: obagent?.mgragent_http_port || 8089, parameters: getInitialParameters( obagent?.component, obagent?.parameters, componentsMoreConfig, ), }, }; if (!lowVersion) { initialValues.ocpexpress = { port: ocpexpress?.port || 8180, parameters: getInitialParameters( ocpexpress?.component, ocpexpress?.parameters, componentsMoreConfig, ), }; } const singleItemStyle = { width: 448 }; const initDir = `${home_path}/oceanbase/store`; return ( {intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.ViewModeConfigurationRules', defaultMessage: '查看模式配置规则', })}
{currentMode === 'PRODUCTION' ? intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.ThisModeWillMaximizeThe', defaultMessage: '此模式将最大化利用环境资源,保证集群的性能与稳定性,推荐使用此模式。', }) : intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.ConfigureResourceParametersThatMeet', defaultMessage: '配置满足集群正常运行的资源参数', })}
{intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.MoreConfigurations', defaultMessage: '更多配置', })}
{clusterMore ? getTableConfig( clusterMore, clusterMoreConfig, clusterMoreLoading, ) : null}
{currentType === 'all' ? ( {intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.PortObproxyExporter', defaultMessage: 'OBProxy Exporter 端口', })} } fieldProps={{ style: commonStyle }} placeholder={intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.PleaseEnter', defaultMessage: '请输入', })} rules={[ { required: true, message: intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.PleaseEnter', defaultMessage: '请输入', }), }, { validator: portValidator }, ]} /> {!lowVersion ? ( ) : null}
{intl.formatMessage({ id: 'OBD.pages.components.ClusterConfig.MoreConfigurations', defaultMessage: '更多配置', })}
{componentsMore ? getTableConfig( componentsMore, componentsMoreConfig, componentsMoreLoading, ) : null}
) : null}
); }