diff --git a/scaleph-api/src/main/java/cn/sliew/scaleph/api/controller/ws/WsDorisTemplateController.java b/scaleph-api/src/main/java/cn/sliew/scaleph/api/controller/ws/WsDorisTemplateController.java index e5ab31f8f..da311ef06 100644 --- a/scaleph-api/src/main/java/cn/sliew/scaleph/api/controller/ws/WsDorisTemplateController.java +++ b/scaleph-api/src/main/java/cn/sliew/scaleph/api/controller/ws/WsDorisTemplateController.java @@ -24,6 +24,7 @@ import cn.sliew.scaleph.engine.doris.service.param.WsDorisTemplateAddParam; import cn.sliew.scaleph.engine.doris.service.param.WsDorisTemplateListParam; import cn.sliew.scaleph.engine.doris.service.param.WsDorisTemplateUpdateParam; +import cn.sliew.scaleph.engine.doris.service.resource.template.DorisTemplate; import cn.sliew.scaleph.system.model.ResponseVO; import cn.sliew.scaleph.system.snowflake.exception.UidGenerateException; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -61,6 +62,14 @@ public ResponseEntity> selectOne(@PathVariable("i return new ResponseEntity(ResponseVO.success(dto), HttpStatus.OK); } + @Logging + @PostMapping("asYaml") + @Operation(summary = "转换模板信息", description = "转换模板信息") + public ResponseEntity> asYaml(@RequestBody WsDorisTemplateDTO dto) { + DorisTemplate template = wsDorisTemplateService.asYaml(dto); + return new ResponseEntity(ResponseVO.success(template), HttpStatus.OK); + } + @Logging @PutMapping @Operation(summary = "新增模板", description = "新增模板") diff --git a/scaleph-dao/src/main/java/cn/sliew/scaleph/dao/entity/master/ws/WsDorisTemplate.java b/scaleph-dao/src/main/java/cn/sliew/scaleph/dao/entity/master/ws/WsDorisTemplate.java index cb7cd5464..b938b191a 100644 --- a/scaleph-dao/src/main/java/cn/sliew/scaleph/dao/entity/master/ws/WsDorisTemplate.java +++ b/scaleph-dao/src/main/java/cn/sliew/scaleph/dao/entity/master/ws/WsDorisTemplate.java @@ -34,7 +34,6 @@ public class WsDorisTemplate extends BaseDO { private static final long serialVersionUID = 1L; - @Schema(description = "项目id") @TableField("project_id") private Long projectId; @@ -47,23 +46,18 @@ public class WsDorisTemplate extends BaseDO { @TableField("namespace") private String namespace; - @Schema(description = "session handler") @TableField("`admin`") private String admin; - @Schema(description = "fe spec") @TableField("fe_spec") private String feSpec; - @Schema(description = "be spec") @TableField("be_spec") private String beSpec; - @Schema(description = "cn spec") @TableField("cn_spec") private String cnSpec; - @Schema(description = "broker spec") @TableField("broker_spec") private String brokerSpec; diff --git a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/operator/spec/AdminUser.java b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/operator/spec/AdminUser.java index b705099ba..392209268 100644 --- a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/operator/spec/AdminUser.java +++ b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/operator/spec/AdminUser.java @@ -24,7 +24,7 @@ * AdminUser describe administrator for manage components in specified cluster. */ @Data -public class AdminUser extends BaseSpec { +public class AdminUser { /** * the user name for admin service’s node. diff --git a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/WsDorisTemplateService.java b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/WsDorisTemplateService.java index 77c037b71..9763db7a6 100644 --- a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/WsDorisTemplateService.java +++ b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/WsDorisTemplateService.java @@ -22,7 +22,7 @@ import cn.sliew.scaleph.engine.doris.service.param.WsDorisTemplateAddParam; import cn.sliew.scaleph.engine.doris.service.param.WsDorisTemplateListParam; import cn.sliew.scaleph.engine.doris.service.param.WsDorisTemplateUpdateParam; -import cn.sliew.scaleph.engine.doris.service.resource.DorisTemplate; +import cn.sliew.scaleph.engine.doris.service.resource.template.DorisTemplate; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import java.util.List; @@ -33,7 +33,7 @@ public interface WsDorisTemplateService { WsDorisTemplateDTO selectOne(Long id); - DorisTemplate asYaml(Long id); + DorisTemplate asYaml(WsDorisTemplateDTO dto); int insert(WsDorisTemplateAddParam param); diff --git a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/dto/WsDorisTemplateDTO.java b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/dto/WsDorisTemplateDTO.java index efd0b365e..7d814b371 100644 --- a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/dto/WsDorisTemplateDTO.java +++ b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/dto/WsDorisTemplateDTO.java @@ -38,7 +38,7 @@ public class WsDorisTemplateDTO extends BaseDTO { private String namespace; - @Schema(description = "session handler") + @Schema(description = "admin user") private AdminUser admin; @Schema(description = "fe spec") diff --git a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/impl/WsDorisTemplateServiceImpl.java b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/impl/WsDorisTemplateServiceImpl.java index ba1354516..42f09b70d 100644 --- a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/impl/WsDorisTemplateServiceImpl.java +++ b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/impl/WsDorisTemplateServiceImpl.java @@ -18,6 +18,7 @@ package cn.sliew.scaleph.engine.doris.service.impl; +import cn.sliew.milky.common.util.JacksonUtil; import cn.sliew.scaleph.common.util.UUIDUtil; import cn.sliew.scaleph.dao.entity.master.ws.WsDorisTemplate; import cn.sliew.scaleph.dao.mapper.master.ws.WsDorisTemplateMapper; @@ -27,7 +28,8 @@ import cn.sliew.scaleph.engine.doris.service.param.WsDorisTemplateAddParam; import cn.sliew.scaleph.engine.doris.service.param.WsDorisTemplateListParam; import cn.sliew.scaleph.engine.doris.service.param.WsDorisTemplateUpdateParam; -import cn.sliew.scaleph.engine.doris.service.resource.DorisTemplate; +import cn.sliew.scaleph.engine.doris.service.resource.template.DorisTemplate; +import cn.sliew.scaleph.engine.doris.service.resource.template.DorisTemplateConverter; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -68,8 +70,8 @@ public WsDorisTemplateDTO selectOne(Long id) { } @Override - public DorisTemplate asYaml(Long id) { - return null; + public DorisTemplate asYaml(WsDorisTemplateDTO dto) { + return DorisTemplateConverter.INSTANCE.convertTo(dto); } @Override @@ -77,6 +79,21 @@ public int insert(WsDorisTemplateAddParam param) { WsDorisTemplate record = new WsDorisTemplate(); BeanUtils.copyProperties(param, record); record.setTemplateId(UUIDUtil.randomUUId()); + if (param.getAdmin() != null) { + record.setAdmin(JacksonUtil.toJsonString(param.getAdmin())); + } + if (param.getFeSpec() != null) { + record.setFeSpec(JacksonUtil.toJsonString(param.getFeSpec())); + } + if (param.getBeSpec() != null) { + record.setBeSpec(JacksonUtil.toJsonString(param.getBeSpec())); + } + if (param.getCnSpec() != null) { + record.setCnSpec(JacksonUtil.toJsonString(param.getCnSpec())); + } + if (param.getBrokerSpec() != null) { + record.setBrokerSpec(JacksonUtil.toJsonString(param.getBrokerSpec())); + } return wsDorisTemplateMapper.insert(record); } @@ -84,6 +101,21 @@ public int insert(WsDorisTemplateAddParam param) { public int update(WsDorisTemplateUpdateParam param) { WsDorisTemplate record = new WsDorisTemplate(); BeanUtils.copyProperties(param, record); + if (param.getAdmin() != null) { + record.setAdmin(JacksonUtil.toJsonString(param.getAdmin())); + } + if (param.getFeSpec() != null) { + record.setFeSpec(JacksonUtil.toJsonString(param.getFeSpec())); + } + if (param.getBeSpec() != null) { + record.setBeSpec(JacksonUtil.toJsonString(param.getBeSpec())); + } + if (param.getCnSpec() != null) { + record.setCnSpec(JacksonUtil.toJsonString(param.getCnSpec())); + } + if (param.getBrokerSpec() != null) { + record.setBrokerSpec(JacksonUtil.toJsonString(param.getBrokerSpec())); + } return wsDorisTemplateMapper.updateById(record); } diff --git a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/param/WsDorisTemplateAddParam.java b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/param/WsDorisTemplateAddParam.java index 35d170583..7319f29b1 100644 --- a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/param/WsDorisTemplateAddParam.java +++ b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/param/WsDorisTemplateAddParam.java @@ -18,6 +18,7 @@ package cn.sliew.scaleph.engine.doris.service.param; +import cn.sliew.scaleph.engine.doris.operator.spec.*; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -39,6 +40,23 @@ public class WsDorisTemplateAddParam { @Schema(description = "namespace") private String namespace; + @NotNull + @Schema(description = "admin user") + private AdminUser admin; + + @NotNull + @Schema(description = "fe spec") + private FeSpec feSpec; + + @Schema(description = "be spec") + private BeSpec beSpec; + + @Schema(description = "cn spec") + private CnSpec cnSpec; + + @Schema(description = "broker spec") + private BrokerSpec brokerSpec; + @Schema(description = "remark") private String remark; } diff --git a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/param/WsDorisTemplateUpdateParam.java b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/param/WsDorisTemplateUpdateParam.java index e8c2b657b..72ec12ee6 100644 --- a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/param/WsDorisTemplateUpdateParam.java +++ b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/param/WsDorisTemplateUpdateParam.java @@ -18,6 +18,7 @@ package cn.sliew.scaleph.engine.doris.service.param; +import cn.sliew.scaleph.engine.doris.operator.spec.*; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -39,6 +40,23 @@ public class WsDorisTemplateUpdateParam { @Schema(description = "namespace") private String namespace; + @NotNull + @Schema(description = "admin user") + private AdminUser admin; + + @NotNull + @Schema(description = "fe spec") + private FeSpec feSpec; + + @Schema(description = "be spec") + private BeSpec beSpec; + + @Schema(description = "cn spec") + private CnSpec cnSpec; + + @Schema(description = "broker spec") + private BrokerSpec brokerSpec; + @Schema(description = "remark") private String remark; } diff --git a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/resource/DorisTemplate.java b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/resource/DorisTemplate.java deleted file mode 100644 index 91d944a36..000000000 --- a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/resource/DorisTemplate.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.sliew.scaleph.engine.doris.service.resource; - -import cn.sliew.scaleph.engine.doris.operator.spec.DorisClusterSpec; -import cn.sliew.scaleph.engine.doris.operator.status.DorisClusterStatus; -import cn.sliew.scaleph.kubernetes.Constant; -import cn.sliew.scaleph.kubernetes.resource.Resource; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import io.fabric8.kubernetes.client.CustomResource; -import io.fabric8.kubernetes.model.annotation.Group; -import io.fabric8.kubernetes.model.annotation.Version; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Data -@Group(Constant.SCALEPH_GROUP) -@Version(Constant.SCALEPH_VERSION) -@EqualsAndHashCode -@JsonPropertyOrder({"apiVersion", "kind", "metadata", "spec", "status"}) -public class DorisTemplate extends CustomResource implements Resource { -} diff --git a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/resource/template/DorisTemplate.java b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/resource/template/DorisTemplate.java new file mode 100644 index 000000000..27f2b4eb9 --- /dev/null +++ b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/resource/template/DorisTemplate.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package cn.sliew.scaleph.engine.doris.service.resource.template; + +import cn.sliew.scaleph.engine.doris.operator.spec.DorisClusterSpec; +import cn.sliew.scaleph.engine.doris.operator.status.DorisClusterStatus; +import cn.sliew.scaleph.kubernetes.Constant; +import cn.sliew.scaleph.kubernetes.resource.Resource; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.fabric8.kubernetes.client.CustomResource; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.Version; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@Group(Constant.SCALEPH_GROUP) +@Version(Constant.SCALEPH_VERSION) +@EqualsAndHashCode +@JsonPropertyOrder({"apiVersion", "kind", "metadata", "spec", "status"}) +public class DorisTemplate extends CustomResource implements Resource { +} diff --git a/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/resource/template/DorisTemplateConverter.java b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/resource/template/DorisTemplateConverter.java new file mode 100644 index 000000000..f567d92d4 --- /dev/null +++ b/scaleph-engine/scaleph-engine-doris/src/main/java/cn/sliew/scaleph/engine/doris/service/resource/template/DorisTemplateConverter.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package cn.sliew.scaleph.engine.doris.service.resource.template; + +import cn.sliew.scaleph.config.resource.ResourceLabels; +import cn.sliew.scaleph.engine.doris.operator.spec.DorisClusterSpec; +import cn.sliew.scaleph.engine.doris.service.dto.WsDorisTemplateDTO; +import cn.sliew.scaleph.kubernetes.resource.ResourceConverter; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import org.springframework.util.StringUtils; + +import java.util.Map; + +public enum DorisTemplateConverter implements ResourceConverter { + INSTANCE; + + @Override + public DorisTemplate convertTo(WsDorisTemplateDTO source) { + DorisTemplate template = new DorisTemplate(); + ObjectMetaBuilder builder = new ObjectMetaBuilder(true); + String name = StringUtils.hasText(source.getTemplateId()) ? source.getTemplateId() : source.getName(); + builder.withName(name); + builder.withNamespace(source.getNamespace()); + builder.withLabels(Map.of(ResourceLabels.SCALEPH_LABEL_NAME, source.getName())); + template.setMetadata(builder.build()); + DorisClusterSpec spec = new DorisClusterSpec(); + spec.setFeSpec(source.getFeSpec()); + spec.setBeSpec(source.getBeSpec()); + spec.setCnSpec(source.getCnSpec()); + spec.setBrokerSpec(source.getBrokerSpec()); + spec.setAdminUser(source.getAdmin()); + template.setSpec(spec); + return template; + } + + @Override + public WsDorisTemplateDTO convertFrom(DorisTemplate target) { + WsDorisTemplateDTO dto = new WsDorisTemplateDTO(); + String name = target.getMetadata().getName(); + if (target.getMetadata().getLabels() != null) { + Map labels = target.getMetadata().getLabels(); + name = labels.computeIfAbsent(ResourceLabels.SCALEPH_LABEL_NAME, key -> target.getMetadata().getName()); + } + dto.setName(name); + dto.setTemplateId(target.getMetadata().getName()); + dto.setNamespace(target.getMetadata().getNamespace()); + + DorisClusterSpec spec = target.getSpec(); + dto.setFeSpec(spec.getFeSpec()); + dto.setBeSpec(spec.getBeSpec()); + dto.setCnSpec(spec.getCnSpec()); + dto.setBrokerSpec(spec.getBrokerSpec()); + dto.setAdmin(spec.getAdminUser()); + return dto; + } +} diff --git a/scaleph-kubernetes/src/main/java/cn/sliew/scaleph/kubernetes/resource/ResourceConverter.java b/scaleph-kubernetes/src/main/java/cn/sliew/scaleph/kubernetes/resource/ResourceConverter.java index 3fc5e987b..aab3162e3 100644 --- a/scaleph-kubernetes/src/main/java/cn/sliew/scaleph/kubernetes/resource/ResourceConverter.java +++ b/scaleph-kubernetes/src/main/java/cn/sliew/scaleph/kubernetes/resource/ResourceConverter.java @@ -20,7 +20,7 @@ public interface ResourceConverter { - T convertTo(S source) throws Exception; + T convertTo(S source); S convertFrom(T target); } diff --git a/scaleph-ui-react/src/locales/zh-CN/pages/project.ts b/scaleph-ui-react/src/locales/zh-CN/pages/project.ts index df5e4fb98..cff721b09 100644 --- a/scaleph-ui-react/src/locales/zh-CN/pages/project.ts +++ b/scaleph-ui-react/src/locales/zh-CN/pages/project.ts @@ -939,6 +939,10 @@ export default { 'pages.project.doris.template.steps.component.base.requests.memory': '内存', 'pages.project.doris.template.steps.component.base.limits.cpu': '最大CPU', 'pages.project.doris.template.steps.component.base.limits.memory': '最大内存', + 'pages.project.doris.template.steps.yaml': 'YAML', + 'pages.project.doris.template.detail': '模版详情', + 'pages.project.doris.template.detail.component': '集群组件', + 'pages.project.doris.template.detail.yaml': 'YAML', 'Run': '运行', diff --git a/scaleph-ui-react/src/models/project/workspace/doris/template/dorisTemplateSteps.ts b/scaleph-ui-react/src/models/project/workspace/doris/template/dorisTemplateSteps.ts new file mode 100644 index 000000000..57cec9362 --- /dev/null +++ b/scaleph-ui-react/src/models/project/workspace/doris/template/dorisTemplateSteps.ts @@ -0,0 +1,61 @@ +import {WsDorisTemplate} from "@/services/project/typings"; +import {Effect, Reducer} from "umi"; +import YAML from "yaml"; +import {WsDorisTemplateService} from "@/services/project/WsDorisTemplateService"; + +export interface StateType { + template: WsDorisTemplate, + templateYaml: string + templateYamlWithDefault: string +} + +export interface ModelType { + namespace: string; + + state: StateType; + + effects: { + queryTemplate: Effect; + }; + + reducers: { + updateTemplate: Reducer; + }; +} + +const model: ModelType = { + namespace: "dorisTemplateSteps", + + state: { + template: null, + templateYaml: null, + templateYamlWithDefault: null + }, + + effects: { + * editTemplate({payload}, {call, put}) { + const {data} = yield call(WsDorisTemplateService.asYaml, payload); + const response = yield call(WsDorisTemplateService.asYaml, payload); + yield put({type: 'updateTemplate', + payload: { + template: payload, + templateYaml: YAML.stringify(data), + templateYamlWithDefault: YAML.stringify(response.data) + } + }); + }, + }, + + reducers: { + updateTemplate(state, {payload}) { + return { + ...state, + template: payload.template, + templateYaml: payload.templateYaml, + templateYamlWithDefault: payload.templateYamlWithDefault, + }; + }, + }, +}; + +export default model; diff --git a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Detail/index.tsx b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Detail/index.tsx index 95c79b982..69e29cbda 100644 --- a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Detail/index.tsx +++ b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Detail/index.tsx @@ -1,13 +1,182 @@ import {useIntl, useLocation} from "umi"; -import React from "react"; -import {WsFlinkKubernetesTemplate} from "@/services/project/typings"; +import React, {useEffect, useRef, useState} from "react"; +import {WsDorisTemplate} from "@/services/project/typings"; +import {PageContainer, ProCard, StatisticCard} from "@ant-design/pro-components"; +import {Divider, Space, Statistic} from "antd"; +import RcResizeObserver from 'rc-resize-observer'; +import Editor, {Monaco, useMonaco} from "@monaco-editor/react"; +import {WsDorisTemplateService} from "@/services/project/WsDorisTemplateService"; +import YAML from "yaml"; const DorisTemplateDetailWeb: React.FC = () => { const intl = useIntl(); - const data = useLocation().state as WsFlinkKubernetesTemplate + const data = useLocation().state as WsDorisTemplate + const editorRef = useRef(null); + const monaco = useMonaco(); + + const [yaml, setYaml] = useState(null); + const [responsive, setResponsive] = useState(false); + + useEffect(() => { + monaco?.languages.typescript.javascriptDefaults.setEagerModelSync(true); + }, [monaco]); + + const handleEditorDidMount = (editor, monaco: Monaco) => { + editorRef.current = editor; + } + + useEffect(() => { + WsDorisTemplateService.asYaml(data).then((response) => { + if (response.success) { + setYaml(YAML.stringify(response.data)) + } + }); + }, []); return ( -
DorisTemplateDetailWeb
+ + { + setResponsive(offset.width < 596); + }} + > + + + + + + + + + ), + }} + footer={ +
{intl.formatMessage({id: 'pages.project.doris.template.steps.component.base.image'}) + ": " + data.feSpec?.image ? data.feSpec?.image : '-'}
+ } + /> +
+ + + + + + + + + ), + }} + footer={ +
{intl.formatMessage({id: 'pages.project.doris.template.steps.component.base.image'}) + ": " + data.beSpec?.image ? data.beSpec?.image : '-'}
+ } + /> +
+ + + + + + + + + ), + }} + footer={ +
{intl.formatMessage({id: 'pages.project.doris.template.steps.component.base.image'}) + ": " + data.cnSpec?.image ? data.cnSpec?.image : '-'}
+ } + /> +
+ + + + + + + + + ), + }} + footer={ +
{intl.formatMessage({id: 'pages.project.doris.template.steps.component.base.image'}) + ": " + data.brokerSpec?.image ? data.brokerSpec?.image : '-'}
+ } + /> +
+
+ + + + + + +
+
); } diff --git a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisAdminUser.tsx b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisAdminUser.tsx index 0364d81ec..8143ce489 100644 --- a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisAdminUser.tsx +++ b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisAdminUser.tsx @@ -1,5 +1,5 @@ import {useIntl} from "umi"; -import {ProCard, ProFormDigit, ProFormGroup, ProFormList, ProFormText} from "@ant-design/pro-components"; +import {ProCard, ProFormGroup, ProFormText} from "@ant-design/pro-components"; const DorisAdminUser: React.FC = () => { const intl = useIntl(); @@ -8,20 +8,22 @@ const DorisAdminUser: React.FC = () => { title={intl.formatMessage({id: 'pages.project.doris.template.steps.component.admin'})} headerBordered collapsible={true}> - - + + + + ); } diff --git a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisBeComponent.tsx b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisBeComponent.tsx index 51549db54..5c3f470e6 100644 --- a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisBeComponent.tsx +++ b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisBeComponent.tsx @@ -9,51 +9,53 @@ const DorisFeComponent: React.FC = () => { headerBordered collapsible={true} defaultCollapsed> - - - - - - + + + + + + + + ); } diff --git a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisCnComponent.tsx b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisCnComponent.tsx index 9305937f9..c9fff33c9 100644 --- a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisCnComponent.tsx +++ b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisCnComponent.tsx @@ -1,5 +1,5 @@ import {useIntl} from "umi"; -import {ProCard, ProFormDigit, ProFormText} from "@ant-design/pro-components"; +import {ProCard, ProFormDigit, ProFormGroup, ProFormText} from "@ant-design/pro-components"; const DorisFeComponent: React.FC = () => { const intl = useIntl(); @@ -9,51 +9,53 @@ const DorisFeComponent: React.FC = () => { headerBordered collapsible={true} defaultCollapsed> - - - - - - + + + + + + + + ); } diff --git a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisFeComponent.tsx b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisFeComponent.tsx index d57bd9a8c..45c3908a2 100644 --- a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisFeComponent.tsx +++ b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/Component/DorisFeComponent.tsx @@ -9,51 +9,53 @@ const DorisFeComponent: React.FC = () => { headerBordered collapsible={true} defaultCollapsed> - - - - - - + + + + + + + + ); } diff --git a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/ComponentStepForm.tsx b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/ComponentStepForm.tsx index e35ccb672..6a144ec82 100644 --- a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/ComponentStepForm.tsx +++ b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/ComponentStepForm.tsx @@ -1,5 +1,4 @@ import React from "react"; -import {Form} from "antd"; import {ProCard} from "@ant-design/pro-components"; import DorisFeComponent from "@/pages/Project/Workspace/Doris/Template/Steps/Component/DorisFeComponent"; import DorisAdminUser from "@/pages/Project/Workspace/Doris/Template/Steps/Component/DorisAdminUser"; @@ -7,8 +6,6 @@ import DorisBeComponent from "@/pages/Project/Workspace/Doris/Template/Steps/Com import DorisCnComponent from "@/pages/Project/Workspace/Doris/Template/Steps/Component/DorisCnComponent"; const DorisTemplateComponent: React.FC = () => { - const [form] = Form.useForm() - return ( diff --git a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/YAMLStepForm.tsx b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/YAMLStepForm.tsx new file mode 100644 index 000000000..c02566c83 --- /dev/null +++ b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/YAMLStepForm.tsx @@ -0,0 +1,41 @@ +import React, {useEffect, useRef} from "react"; +import {ProCard} from "@ant-design/pro-components"; +import Editor, {Monaco, useMonaco} from "@monaco-editor/react"; +import {connect} from "umi"; + +const DorisTemplateYAML: React.FC = (props: any) => { + const editorRef = useRef(null); + const monaco = useMonaco(); + + useEffect(() => { + monaco?.languages.typescript.javascriptDefaults.setEagerModelSync(true); + }, [monaco]); + + const handleEditorDidMount = (editor, monaco: Monaco) => { + editorRef.current = editor; + } + + return ( + + + + + ); +} + +const mapModelToProps = ({dorisTemplateSteps}: any) => ({dorisTemplateSteps}) +export default connect(mapModelToProps)(DorisTemplateYAML); diff --git a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/index.tsx b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/index.tsx index 4f89b9931..ae7d35242 100644 --- a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/index.tsx +++ b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/Steps/index.tsx @@ -1,15 +1,53 @@ -import {useIntl} from "umi"; +import {connect, history, useIntl} from "umi"; import React, {useRef} from "react"; import {ProCard, ProFormInstance, StepsForm} from "@ant-design/pro-components"; import {WORKSPACE_CONF} from "@/constant"; import DorisTemplateComponent from "@/pages/Project/Workspace/Doris/Template/Steps/ComponentStepForm"; import DorisTemplateBase from "@/pages/Project/Workspace/Doris/Template/Steps/BaseStepForm"; +import DorisTemplateYAML from "@/pages/Project/Workspace/Doris/Template/Steps/YAMLStepForm"; +import {WsDorisTemplate} from "@/services/project/typings"; +import {WsDorisTemplateService} from "@/services/project/WsDorisTemplateService"; -const DorisTemplateSteps: React.FC = () => { +const DorisTemplateSteps: React.FC = (props: any) => { const intl = useIntl(); const formRef = useRef(); const projectId = localStorage.getItem(WORKSPACE_CONF.projectId); + const onBaseStepFinish = (values: Record) => { + const template: WsDorisTemplate = { + projectId: projectId, + name: values.name, + namespace: values.namespace, + remark: values.remark, + } + editDorisTemplate(template) + return Promise.resolve(true) + } + + const onComponentStepFinish = (values: Record) => { + try { + const template: WsDorisTemplate = WsDorisTemplateService.formatData(props.dorisTemplateSteps.template, values) + editDorisTemplate(template) + } catch (unused) { + } + return Promise.resolve(true) + } + + const editDorisTemplate = (template: WsDorisTemplate) => { + props.dispatch({ + type: 'dorisTemplateSteps/editTemplate', + payload: template + }) + } + + const onAllFinish = (values: Record) => { + return WsDorisTemplateService.add(props.dorisTemplateSteps.template).then((response) => { + if (response.success) { + history.back() + } + }) + } + return ( { grid: true, rowProps: {gutter: [16, 8]} }} + onFinish={onAllFinish} > + style={{width: 1000}} + onFinish={onBaseStepFinish}> + style={{width: 1000}} + onFinish={onComponentStepFinish}> + + + ) } -export default DorisTemplateSteps; +const mapModelToProps = ({dorisTemplateSteps}: any) => ({dorisTemplateSteps}) +export default connect(mapModelToProps)(DorisTemplateSteps); diff --git a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/index.tsx b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/index.tsx index a0e092727..f8f13bafd 100644 --- a/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/index.tsx +++ b/scaleph-ui-react/src/pages/Project/Workspace/Doris/Template/index.tsx @@ -1,6 +1,6 @@ import {history, useAccess, useIntl} from "umi"; import React, {useRef, useState} from "react"; -import {Button, message, Modal, Space, Tooltip} from "antd"; +import {Button, message, Modal, Space, Tag, Tooltip} from "antd"; import {DeleteOutlined, EditOutlined, NodeIndexOutlined} from "@ant-design/icons"; import {ActionType, ProColumns, ProFormInstance, ProTable} from "@ant-design/pro-components"; import {PRIVILEGE_CODE, WORKSPACE_CONF} from "@/constant"; diff --git a/scaleph-ui-react/src/services/project/WsDorisTemplateService.ts b/scaleph-ui-react/src/services/project/WsDorisTemplateService.ts index 36fa1ffbc..0cc1761bd 100644 --- a/scaleph-ui-react/src/services/project/WsDorisTemplateService.ts +++ b/scaleph-ui-react/src/services/project/WsDorisTemplateService.ts @@ -20,6 +20,13 @@ export const WsDorisTemplateService = { }); }, + asYaml: async (param: WsDorisTemplate) => { + return request>(`${WsDorisTemplateService.url}/asYaml`, { + method: 'POST', + data: param, + }); + }, + add: async (param: WsDorisTemplateAddParam) => { return request>(`${WsDorisTemplateService.url}`, { method: 'PUT', @@ -47,4 +54,95 @@ export const WsDorisTemplateService = { data: params, }); }, + + formatData: (data: WsDorisTemplate, value: Record) => { + const admin: Record = { + name: value['admin.name'], + password: value['admin.password'], + } + data.admin = admin + + const feSpec: Record = { + replicas: value['fe.replicas'], + image: value['fe.image'] + } + const feSpecRequests: Record = { + cpu: value['fe.requests.cpu'], + memory: value['fe.requests.memory'] + } + const feSpecLimits: Record = { + cpu: value['fe.limits.cpu'], + memory: value['fe.limits.memory'] + } + feSpec.requests = feSpecRequests + feSpec.limits = feSpecLimits + data.feSpec = feSpec + + const beSpec: Record = { + replicas: value['be.replicas'], + image: value['be.image'] + } + const beSpecRequests: Record = { + cpu: value['be.requests.cpu'], + memory: value['be.requests.memory'] + } + const beSpecLimits: Record = { + cpu: value['be.limits.cpu'], + memory: value['be.limits.memory'] + } + beSpec.requests = beSpecRequests + beSpec.limits = beSpecLimits + data.beSpec = beSpec + + const cnSpec: Record = { + replicas: value['cn.replicas'], + image: value['cn.image'] + } + const cnSpecRequests: Record = { + cpu: value['cn.requests.cpu'], + memory: value['cn.requests.memory'] + } + const cnSpecLimits: Record = { + cpu: value['cn.limits.cpu'], + memory: value['cn.limits.memory'] + } + cnSpec.requests = cnSpecRequests + cnSpec.limits = cnSpecLimits + data.cnSpec = cnSpec + return data + }, + + parseData: (data: WsDorisTemplate) => { + const value: Record = { + 'name': data.name, + 'namespace': data.namespace, + 'remark': data.remark, + + 'admin.name': data.admin?.name, + 'admin.password': data.admin?.password, + + 'fe.replicas': data.feSpec?.replicas, + 'fe.image': data.feSpec?.image, + 'fe.requests.cpu': data.feSpec?.requests?.cpu, + 'fe.requests.memory': data.feSpec?.requests?.memory, + 'fe.limits.cpu': data.feSpec?.limits?.cpu, + 'fe.limits.memory': data.feSpec?.limits?.memory, + + 'be.replicas': data.beSpec?.replicas, + 'be.image': data.beSpec?.image, + 'be.requests.cpu': data.beSpec?.requests?.cpu, + 'be.requests.memory': data.beSpec?.requests?.memory, + 'be.limits.cpu': data.beSpec?.limits?.cpu, + 'be.limits.memory': data.beSpec?.limits?.memory, + + 'cn.replicas': data.cnSpec?.replicas, + 'cn.image': data.cnSpec?.image, + 'cn.requests.cpu': data.cnSpec?.requests?.cpu, + 'cn.requests.memory': data.cnSpec?.requests?.memory, + 'cn.limits.cpu': data.cnSpec?.limits?.cpu, + 'cn.limits.memory': data.cnSpec?.limits?.memory, + } + + return value + } }; diff --git a/scaleph-ui-react/src/services/project/typings.d.ts b/scaleph-ui-react/src/services/project/typings.d.ts index f85c0a133..24a32088b 100644 --- a/scaleph-ui-react/src/services/project/typings.d.ts +++ b/scaleph-ui-react/src/services/project/typings.d.ts @@ -452,6 +452,11 @@ export type WsDorisTemplateAddParam = { projectId: number; name: string; namespace: string; + admin?: Record; + feSpec?: Record; + beSpec?: Record; + cnSpec?: Record; + brokerSpec?: Record; remark?: string; }; @@ -459,5 +464,10 @@ export type WsDorisTemplateUpdateParam = { id: number; name: string; namespace: string; + admin?: Record; + feSpec?: Record; + beSpec?: Record; + cnSpec?: Record; + brokerSpec?: Record; remark?: string; }; diff --git a/tools/docker/mysql/init.d/scaleph-ws-mysql.sql b/tools/docker/mysql/init.d/scaleph-ws-mysql.sql index 319ac3e70..59e38a789 100644 --- a/tools/docker/mysql/init.d/scaleph-ws-mysql.sql +++ b/tools/docker/mysql/init.d/scaleph-ws-mysql.sql @@ -70,7 +70,7 @@ create table ws_flink_artifact_jar editor varchar(32) comment '修改人', update_time timestamp default current_timestamp on update current_timestamp comment '修改时间', primary key (id), - key idx_flink_artifact (flink_artifact_id) + key idx_flink_artifact (flink_artifact_id) ) engine = innodb comment = 'flink artifact jar'; DROP TABLE IF EXISTS ws_flink_artifact_sql; @@ -86,7 +86,7 @@ CREATE TABLE ws_flink_artifact_sql editor varchar(32), update_time datetime not null default current_timestamp on update current_timestamp, PRIMARY KEY (id), - key idx_flink_artifact (flink_artifact_id) + key idx_flink_artifact (flink_artifact_id) ) ENGINE = INNODB COMMENT = 'flink artifact sql'; INSERT INTO `ws_flink_artifact_sql` (`id`, `flink_artifact_id`, `flink_version`, `script`, `current`, `creator`, @@ -139,7 +139,7 @@ create table ws_di_job editor varchar(32) comment '修改人', update_time timestamp default current_timestamp on update current_timestamp comment '修改时间', primary key (id), - key idx_flink_artifact (flink_artifact_id) + key idx_flink_artifact (flink_artifact_id) ) engine = innodb comment '数据集成-作业信息'; INSERT INTO ws_di_job (id, flink_artifact_id, job_engine, job_id, current, creator, editor) VALUES (1, 4, 'seatunnel', 'b8e16c94-258c-4487-a88c-8aad40a38b35', 1, 'sys', 'sys'); @@ -471,7 +471,7 @@ create table ws_flink_custom_artifact editor varchar(32) comment '修改人', update_time timestamp default current_timestamp on update current_timestamp comment '修改时间', primary key (id), - key idx_custom (flink_version, type, file_name) + key idx_custom (flink_version, type, file_name) ) engine = innodb comment = 'flink custom artifact'; drop table if exists ws_flink_custom_factory; @@ -487,7 +487,7 @@ create table ws_flink_custom_factory editor varchar(32) comment '修改人', update_time timestamp default current_timestamp on update current_timestamp comment '修改时间', primary key (id), - key idx_custom (flink_custom_artifact_id, factory_class, `name`) + key idx_custom (flink_custom_artifact_id, factory_class, `name`) ) engine = innodb comment = 'flink custom factory'; drop table if exists ws_flink_sql_gateway_session; @@ -564,7 +564,8 @@ create table ws_doris_template INSERT INTO `ws_doris_template`(`id`, `project_id`, `name`, `template_id`, `namespace`, `admin`, `fe_spec`, `be_spec`, `cn_spec`, `broker_spec`, `remark`, `creator`, `editor`) -VALUES (1, 1, 'simple-doriscluster-sample', 'zexbfaf0eba4ce824787a9bed88148eb233f', 'default', NULL, +VALUES (1, 1, 'simple-doriscluster-sample', 'zexbfaf0eba4ce824787a9bed88148eb233f', 'default', + '{"name":"admin","password":"Admin123"}', '{\"replicas\":1,\"image\":\"selectdb/doris.fe-ubuntu:2.0.2\",\"limits\":{\"cpu\":4,\"memory\":\"8Gi\"},\"requests\":{\"cpu\":4,\"memory\":\"8Gi\"}}', '{\"replicas\":1,\"image\":\"selectdb/doris.be-ubuntu:2.0.2\",\"limits\":{\"cpu\":4,\"memory\":\"8Gi\"},\"requests\":{\"cpu\":4,\"memory\":\"8Gi\"}}', NULL, NULL, NULL, 'sys', 'sys'); \ No newline at end of file