This is an automated email from the ASF dual-hosted git repository.
nicholasjiang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-webui.git
The following commit(s) were added to refs/heads/main by this push:
new 46c88c8 [Feature] Introduce cluster management interface (#200)
46c88c8 is described below
commit 46c88c8114e8fd75fdebd98fe2e9bb14e895a73e
Author: s7monk <[email protected]>
AuthorDate: Mon May 6 11:30:39 2024 +0800
[Feature] Introduce cluster management interface (#200)
---
.../web/server/controller/ClusterController.java | 97 +++++++++++
.../paimon/web/server/data/model/ClusterInfo.java | 48 ++++++
.../web/server/data/result/enums/Status.java | 7 +-
.../paimon/web/server/mapper/ClusterMapper.java | 35 ++++
.../paimon/web/server/service/ClusterService.java | 37 ++++
.../server/service/impl/ClusterServiceImpl.java | 57 +++++++
.../src/main/resources/i18n/messages.properties | 2 +
.../main/resources/i18n/messages_en_US.properties | 2 +
.../main/resources/i18n/messages_zh_CN.properties | 2 +
.../src/main/resources/mapper/ClusterMapper.xml | 67 ++++++++
.../server/controller/ClusterControllerTest.java | 189 +++++++++++++++++++++
scripts/sql/paimon-mysql.sql | 13 ++
12 files changed, 555 insertions(+), 1 deletion(-)
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/ClusterController.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/ClusterController.java
new file mode 100644
index 0000000..60c7918
--- /dev/null
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/ClusterController.java
@@ -0,0 +1,97 @@
+/*
+ * 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 org.apache.paimon.web.server.controller;
+
+import org.apache.paimon.web.server.data.model.ClusterInfo;
+import org.apache.paimon.web.server.data.result.PageR;
+import org.apache.paimon.web.server.data.result.R;
+import org.apache.paimon.web.server.data.result.enums.Status;
+import org.apache.paimon.web.server.service.ClusterService;
+import org.apache.paimon.web.server.util.PageSupport;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/** Cluster api controller. */
+@RestController
+@RequestMapping("/api/cluster")
+public class ClusterController {
+
+ @Autowired private ClusterService clusterService;
+
+ @SaCheckPermission("system:cluster:query")
+ @GetMapping("/{id}")
+ public R<ClusterInfo> getCluster(@PathVariable("id") Integer id) {
+ ClusterInfo clusterInfo = clusterService.getById(id);
+ if (clusterInfo == null) {
+ return R.failed(Status.CLUSTER_NOT_EXIST);
+ }
+ return R.succeed(clusterInfo);
+ }
+
+ @SaCheckPermission("system:cluster:list")
+ @GetMapping("/list")
+ public PageR<ClusterInfo> listClusters(ClusterInfo clusterInfo) {
+ IPage<ClusterInfo> page = PageSupport.startPage();
+ List<ClusterInfo> clusterInfos = clusterService.listUsers(page,
clusterInfo);
+ return PageR.<ClusterInfo>builder()
+ .success(true)
+ .total(page.getTotal())
+ .data(clusterInfos)
+ .build();
+ }
+
+ @SaCheckPermission("system:cluster:add")
+ @PostMapping
+ public R<Void> add(@Validated @RequestBody ClusterInfo clusterInfo) {
+ if (!clusterService.checkClusterNameUnique(clusterInfo)) {
+ return R.failed(Status.CLUSTER_NAME_ALREADY_EXISTS,
clusterInfo.getClusterName());
+ }
+
+ return clusterService.save(clusterInfo) ? R.succeed() : R.failed();
+ }
+
+ @SaCheckPermission("system:cluster:update")
+ @PutMapping
+ public R<Void> update(@Validated @RequestBody ClusterInfo clusterInfo) {
+ if (!clusterService.checkClusterNameUnique(clusterInfo)) {
+ return R.failed(Status.CLUSTER_NAME_ALREADY_EXISTS,
clusterInfo.getClusterName());
+ }
+
+ return clusterService.updateById(clusterInfo) ? R.succeed() :
R.failed();
+ }
+
+ @SaCheckPermission("system:cluster:delete")
+ @DeleteMapping("/{clusterIds}")
+ public R<Void> delete(@PathVariable Integer[] clusterIds) {
+ return clusterService.deleteClusterByIds(clusterIds) > 0 ? R.succeed()
: R.failed();
+ }
+}
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/ClusterInfo.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/ClusterInfo.java
new file mode 100644
index 0000000..edf319e
--- /dev/null
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/ClusterInfo.java
@@ -0,0 +1,48 @@
+/*
+ * 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 org.apache.paimon.web.server.data.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/** Cluster table model. */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@TableName("cluster")
+public class ClusterInfo extends BaseModel {
+
+ private static final long serialVersionUID = 1L;
+
+ private String clusterName;
+
+ private String host;
+
+ private Integer port;
+
+ private String type;
+
+ private Boolean enabled;
+}
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
index 0f6b314..29baaa1 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
@@ -77,8 +77,13 @@ public enum Status {
TABLE_DROP_ERROR(10510, "table.drop.error"),
TABLE_RENAME_ERROR(10511, "table.rename.error"),
+ /** ------------cdc-----------------. */
CDC_JOB_EXIST_ERROR(10601, "cdc.job.exist.error"),
- CDC_JOB_NO_EXIST_ERROR(10602, "cdc.job.not.exist.error");
+ CDC_JOB_NO_EXIST_ERROR(10602, "cdc.job.not.exist.error"),
+
+ /** ------------cluster-----------------. */
+ CLUSTER_NOT_EXIST(10701, "cluster.not.exist"),
+ CLUSTER_NAME_ALREADY_EXISTS(10702, "cluster.name.exist");
private final int code;
private final String msg;
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/ClusterMapper.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/ClusterMapper.java
new file mode 100644
index 0000000..d3dc649
--- /dev/null
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/ClusterMapper.java
@@ -0,0 +1,35 @@
+/*
+ * 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 org.apache.paimon.web.server.mapper;
+
+import org.apache.paimon.web.server.data.model.ClusterInfo;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/** Cluster mapper. */
+@Mapper
+public interface ClusterMapper extends BaseMapper<ClusterInfo> {
+
+ List<ClusterInfo> listClusters(IPage<ClusterInfo> page, @Param("cluster")
ClusterInfo cluster);
+}
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/ClusterService.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/ClusterService.java
new file mode 100644
index 0000000..0ed8e56
--- /dev/null
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/ClusterService.java
@@ -0,0 +1,37 @@
+/*
+ * 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 org.apache.paimon.web.server.service;
+
+import org.apache.paimon.web.server.data.model.ClusterInfo;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/** Cluster Service. */
+public interface ClusterService extends IService<ClusterInfo> {
+
+ List<ClusterInfo> listUsers(IPage<ClusterInfo> page, @Param("cluster")
ClusterInfo cluster);
+
+ boolean checkClusterNameUnique(ClusterInfo cluster);
+
+ int deleteClusterByIds(Integer[] clusterIds);
+}
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/ClusterServiceImpl.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/ClusterServiceImpl.java
new file mode 100644
index 0000000..45a389e
--- /dev/null
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/ClusterServiceImpl.java
@@ -0,0 +1,57 @@
+/*
+ * 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 org.apache.paimon.web.server.service.impl;
+
+import org.apache.paimon.web.server.data.model.ClusterInfo;
+import org.apache.paimon.web.server.mapper.ClusterMapper;
+import org.apache.paimon.web.server.service.ClusterService;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.List;
+
+/** The implementation of {@link ClusterService}. */
+@Service
+public class ClusterServiceImpl extends ServiceImpl<ClusterMapper, ClusterInfo>
+ implements ClusterService {
+
+ @Autowired private ClusterMapper clusterMapper;
+
+ @Override
+ public List<ClusterInfo> listUsers(IPage<ClusterInfo> page, ClusterInfo
cluster) {
+ return clusterMapper.listClusters(page, cluster);
+ }
+
+ @Override
+ public boolean checkClusterNameUnique(ClusterInfo cluster) {
+ int clusterId = cluster.getId() == null ? -1 : cluster.getId();
+ ClusterInfo info =
+ this.lambdaQuery().eq(ClusterInfo::getClusterName,
cluster.getClusterName()).one();
+ return info == null || info.getId() == clusterId;
+ }
+
+ @Override
+ public int deleteClusterByIds(Integer[] clusterIds) {
+ return clusterMapper.deleteBatchIds(Arrays.asList(clusterIds));
+ }
+}
diff --git a/paimon-web-server/src/main/resources/i18n/messages.properties
b/paimon-web-server/src/main/resources/i18n/messages.properties
index 35f3a68..96ae9d1 100644
--- a/paimon-web-server/src/main/resources/i18n/messages.properties
+++ b/paimon-web-server/src/main/resources/i18n/messages.properties
@@ -51,3 +51,5 @@ table.drop.error=Exception calling Paimon Catalog API to drop
a table.
table.rename.error=Exception calling Paimon Catalog API to rename a table.
cdc.job.exist.error=Paimon CDC job exists.
cdc.job.not.exist.error=Paimon CDC job is not exist.
+cluster.not.exist=This cluster is not exist.
+cluster.name.exist=This cluster name {0} already exists.
diff --git
a/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
b/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
index 35f3a68..96ae9d1 100644
--- a/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
+++ b/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
@@ -51,3 +51,5 @@ table.drop.error=Exception calling Paimon Catalog API to drop
a table.
table.rename.error=Exception calling Paimon Catalog API to rename a table.
cdc.job.exist.error=Paimon CDC job exists.
cdc.job.not.exist.error=Paimon CDC job is not exist.
+cluster.not.exist=This cluster is not exist.
+cluster.name.exist=This cluster name {0} already exists.
diff --git
a/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
b/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
index 96ca9fa..d61de0c 100644
--- a/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
+++ b/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
@@ -51,3 +51,5 @@ table.drop.error=\u8C03\u7528 Paimon API \u5220\u9664 Table
\u65F6\u53D1\u751F\u
table.rename.error=\u8C03\u7528 Paimon API \u91CD\u547D\u540D Table
\u65F6\u53D1\u751F\u5F02\u5E38
cdc.job.exist.error=paimon cdc\u4F5C\u4E1A\u5DF2\u5B58\u5728
cdc.job.not.exist.error=paimon cdc\u4F5C\u4E1A\u4E0D\u5B58\u5728
+cluster.not.exist=\u6B64\u96C6\u7FA4\u4E0D\u5B58\u5728
+cluster.name.exist=\u6B64\u96C6\u7FA4\u540D{0}\u5DF2\u7ECF\u5B58\u5728
diff --git a/paimon-web-server/src/main/resources/mapper/ClusterMapper.xml
b/paimon-web-server/src/main/resources/mapper/ClusterMapper.xml
new file mode 100644
index 0000000..3f4c9ca
--- /dev/null
+++ b/paimon-web-server/src/main/resources/mapper/ClusterMapper.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+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.
+-->
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.apache.paimon.web.server.mapper.ClusterMapper">
+
+ <resultMap id="SysClusterResult"
type="org.apache.paimon.web.server.data.model.ClusterInfo">
+ <id property="id" column="id" />
+ <result property="clusterName" column="cluster_name" />
+ <result property="host" column="host" />
+ <result property="port" column="port" />
+ <result property="type" column="type" />
+ <result property="enabled" column="enabled" />
+ <result property="createTime" column="create_time" />
+ <result property="updateTime" column="update_time" />
+ </resultMap>
+
+ <sql id="selectClusterVo">
+ select id, cluster_name, host, port, `type`, enabled, create_time,
update_time from cluster
+ </sql>
+
+ <select id="listClusters"
parameterType="org.apache.paimon.web.server.data.model.ClusterInfo"
resultMap="SysClusterResult">
+ <include refid="selectClusterVo"/>
+ <if test="cluster.id != null and cluster.id != 0">
+ AND id = #{cluster.id}
+ </if>
+ <if test="cluster.clusterName != null and cluster.clusterName != ''">
+ AND cluser_name like concat('%', #{cluster.clusterName}, '%')
+ </if>
+ <if test="cluster.host != null and cluster.host != ''">
+ AND host = #{cluster.host}
+ </if>
+ <if test="cluster.port != null">
+ AND port = #{cluster.port}
+ </if>
+ <if test="cluster.type != null and cluster.type != ''">
+ AND `type` = #{cluster.type}
+ </if>
+ <if test="cluster.enabled != null">
+ AND enabled = #{cluster.enabled}
+ </if>
+ <if test="cluster.params.beginTime != null and
cluster.params.beginTime != ''"><!-- Start time search -->
+ AND date_format(create_time,'%y%m%d') >=
date_format(#{cluster.params.beginTime},'%y%m%d')
+ </if>
+ <if test="cluster.params.endTime != null and cluster.params.endTime !=
''"><!-- End time search -->
+ AND date_format(create_time,'%y%m%d') <=
date_format(#{cluster.params.endTime},'%y%m%d')
+ </if>
+ </select>
+</mapper>
\ No newline at end of file
diff --git
a/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/ClusterControllerTest.java
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/ClusterControllerTest.java
new file mode 100644
index 0000000..3a816ca
--- /dev/null
+++
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/ClusterControllerTest.java
@@ -0,0 +1,189 @@
+/*
+ * 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 org.apache.paimon.web.server.controller;
+
+import org.apache.paimon.web.server.data.model.ClusterInfo;
+import org.apache.paimon.web.server.data.result.PageR;
+import org.apache.paimon.web.server.data.result.R;
+import org.apache.paimon.web.server.util.ObjectMapperUtils;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import
org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/** Test for {@link ClusterController}. */
+@SpringBootTest
+@AutoConfigureMockMvc
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class ClusterControllerTest extends ControllerTestBase {
+
+ private static final String clusterPath = "/api/cluster";
+
+ private static final int clusterId = 1;
+ private static final String clusterName = "flink_test_cluster";
+
+ @Test
+ @Order(1)
+ public void testAddCluster() throws Exception {
+ ClusterInfo cluster = new ClusterInfo();
+ cluster.setId(clusterId);
+ cluster.setClusterName(clusterName);
+ cluster.setHost("127.0.0.1");
+ cluster.setPort(8083);
+ cluster.setType("Flink");
+ cluster.setEnabled(true);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.post(clusterPath)
+ .cookie(cookie)
+ .content(ObjectMapperUtils.toJSON(cluster))
+ .contentType(MediaType.APPLICATION_JSON_VALUE)
+ .accept(MediaType.APPLICATION_JSON_VALUE))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andDo(MockMvcResultHandlers.print());
+ }
+
+ @Test
+ @Order(2)
+ public void testGetCluster() throws Exception {
+ String responseString =
+ mockMvc.perform(
+ MockMvcRequestBuilders.get(clusterPath + "/" +
clusterId)
+ .cookie(cookie)
+
.contentType(MediaType.APPLICATION_JSON_VALUE)
+
.accept(MediaType.APPLICATION_JSON_VALUE))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andDo(MockMvcResultHandlers.print())
+ .andReturn()
+ .getResponse()
+ .getContentAsString();
+
+ R<ClusterInfo> r =
+ ObjectMapperUtils.fromJSON(responseString, new
TypeReference<R<ClusterInfo>>() {});
+ assertEquals(200, r.getCode());
+ assertNotNull(r.getData());
+ assertEquals(clusterName, r.getData().getClusterName());
+ assertEquals("127.0.0.1", r.getData().getHost());
+ assertEquals(8083, r.getData().getPort());
+ assertEquals("Flink", r.getData().getType());
+ assertTrue(r.getData().getEnabled());
+ }
+
+ @Test
+ @Order(3)
+ public void testListClusters() throws Exception {
+ String responseString =
+ mockMvc.perform(
+ MockMvcRequestBuilders.get(clusterPath +
"/list")
+ .cookie(cookie)
+
.contentType(MediaType.APPLICATION_JSON_VALUE)
+
.accept(MediaType.APPLICATION_JSON_VALUE))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andDo(MockMvcResultHandlers.print())
+ .andReturn()
+ .getResponse()
+ .getContentAsString();
+
+ PageR<ClusterInfo> r =
+ ObjectMapperUtils.fromJSON(
+ responseString, new
TypeReference<PageR<ClusterInfo>>() {});
+ assertTrue(
+ r.getData() != null
+ && ((r.getTotal() > 0 && r.getData().size() > 0)
+ || (r.getTotal() == 0 && r.getData().size() ==
0)));
+
+ ClusterInfo clusterInfo = r.getData().get(0);
+ assertEquals(clusterName, clusterInfo.getClusterName());
+ assertEquals("127.0.0.1", clusterInfo.getHost());
+ assertEquals(8083, clusterInfo.getPort());
+ assertEquals("Flink", clusterInfo.getType());
+ assertTrue(clusterInfo.getEnabled());
+ }
+
+ @Test
+ @Order(4)
+ public void testUpdateCluster() throws Exception {
+ String newClusterName = clusterName + "-edit";
+ ClusterInfo cluster = new ClusterInfo();
+ cluster.setId(clusterId);
+ cluster.setClusterName(newClusterName);
+ cluster.setHost("127.0.0.1");
+ cluster.setPort(8083);
+ cluster.setType("Flink");
+ cluster.setEnabled(true);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.put(clusterPath)
+ .cookie(cookie)
+ .content(ObjectMapperUtils.toJSON(cluster))
+ .contentType(MediaType.APPLICATION_JSON_VALUE)
+ .accept(MediaType.APPLICATION_JSON_VALUE))
+ .andExpect(MockMvcResultMatchers.status().isOk());
+
+ String responseString =
+ mockMvc.perform(
+ MockMvcRequestBuilders.get(clusterPath + "/" +
clusterId)
+ .cookie(cookie)
+
.contentType(MediaType.APPLICATION_JSON_VALUE)
+
.accept(MediaType.APPLICATION_JSON_VALUE))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andDo(MockMvcResultHandlers.print())
+ .andReturn()
+ .getResponse()
+ .getContentAsString();
+
+ R<ClusterInfo> r =
+ ObjectMapperUtils.fromJSON(responseString, new
TypeReference<R<ClusterInfo>>() {});
+ assertEquals(200, r.getCode());
+ assertNotNull(r.getData());
+ assertEquals(r.getData().getClusterName(), newClusterName);
+ }
+
+ @Test
+ @Order(5)
+ public void testDeleteCluster() throws Exception {
+ String delResponseString =
+ mockMvc.perform(
+ MockMvcRequestBuilders.delete(
+ clusterPath + "/" + clusterId
+ "," + clusterId)
+ .cookie(cookie)
+
.contentType(MediaType.APPLICATION_JSON_VALUE)
+
.accept(MediaType.APPLICATION_JSON_VALUE))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andDo(MockMvcResultHandlers.print())
+ .andReturn()
+ .getResponse()
+ .getContentAsString();
+
+ R<?> result = ObjectMapperUtils.fromJSON(delResponseString, R.class);
+ assertEquals(200, result.getCode());
+ }
+}
diff --git a/scripts/sql/paimon-mysql.sql b/scripts/sql/paimon-mysql.sql
index db44cab..9c4b5b9 100644
--- a/scripts/sql/paimon-mysql.sql
+++ b/scripts/sql/paimon-mysql.sql
@@ -126,6 +126,19 @@ CREATE TABLE if not exists `catalog`
options varchar(512) null
) engine = innodb;
+DROP TABLE IF EXISTS `cluster`;
+CREATE TABLE if not exists `cluster`
+(
+ `id` int(11) not null auto_increment primary key comment 'id',
+ `cluster_name` varchar(100) comment 'cluster name',
+ `host` varchar(100) comment 'host',
+ `port` int(11) COMMENT 'port',
+ `enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'enabled',
+ `type` varchar(100) comment 'cluster type',
+ `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create
time',
+ `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'update
time'
+ ) ENGINE = InnoDB DEFAULT CHARSET=utf8;
+
DROP TABLE IF EXISTS `cdc_job_definition`;
CREATE TABLE if not exists `cdc_job_definition`
(