This is an automated email from the ASF dual-hosted git repository.

wuzhiguo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/bigtop-manager.git


The following commit(s) were added to refs/heads/main by this push:
     new 24d33371 BIGTOP-4265: Refactor APIs for Service Config & Snapshot 
(#104)
24d33371 is described below

commit 24d3337136dc9a9f8ac6e37e8a8ef791ef7b32b6
Author: Zhiguo Wu <[email protected]>
AuthorDate: Tue Nov 19 17:03:29 2024 +0800

    BIGTOP-4265: Refactor APIs for Service Config & Snapshot (#104)
---
 .../bigtop/manager/dao/po/ServiceConfigPO.java     |  26 ++-
 ...eConfigPO.java => ServiceConfigSnapshotPO.java} |  23 ++-
 .../manager/dao/repository/ServiceConfigDao.java   |   7 +-
 ...onfigDao.java => ServiceConfigSnapshotDao.java} |  11 +-
 .../resources/mapper/mysql/ServiceConfigMapper.xml |  98 ++---------
 .../mapper/mysql/ServiceConfigSnapshotMapper.xml   |  40 +++++
 .../mapper/postgresql/ServiceConfigMapper.xml      |  99 ++---------
 .../postgresql/ServiceConfigSnapshotMapper.xml     |  40 +++++
 .../server/command/job/ServiceInstallJob.java      |   6 +-
 .../server/command/task/CacheFileUpdateTask.java   |  30 +---
 .../server/controller/ConfigController.java        |  59 -------
 .../server/controller/ServiceController.java       |  50 +++++-
 .../model/converter/ServiceConfigConverter.java    |  10 +-
 ...er.java => ServiceConfigSnapshotConverter.java} |  29 ++--
 .../manager/server/model/dto/ServiceConfigDTO.java |   8 +-
 ...onfigDTO.java => ServiceConfigSnapshotDTO.java} |  11 +-
 .../manager/server/model/dto/ServiceDTO.java       |   2 +-
 .../model/dto/command/ServiceCommandDTO.java       |   4 +-
 .../manager/server/model/req/ServiceConfigReq.java |  11 +-
 .../ServiceConfigSnapshotReq.java}                 |   9 +-
 .../manager/server/model/req/TypeConfigReq.java    |  42 -----
 .../model/req/command/ServiceCommandReq.java       |   4 +-
 ...eConfigVO.java => ServiceConfigSnapshotVO.java} |  12 +-
 .../manager/server/model/vo/ServiceConfigVO.java   |  12 +-
 .../bigtop/manager/server/model/vo/ServiceVO.java  |   2 +-
 .../manager/server/service/ConfigService.java      |  43 -----
 .../manager/server/service/ServiceService.java     |  16 ++
 .../server/service/impl/ConfigServiceImpl.java     | 150 ----------------
 .../server/service/impl/ServiceServiceImpl.java    | 100 ++++++++++-
 .../server/service/impl/StackServiceImpl.java      |   4 +-
 .../bigtop/manager/server/utils/StackUtils.java    |  19 +-
 .../src/main/resources/ddl/MySQL-DDL-CREATE.sql    | 175 +++++++++----------
 .../main/resources/ddl/PostgreSQL-DDL-CREATE.sql   | 192 +++++++++++----------
 .../server/controller/ConfigControllerTest.java    | 111 ------------
 .../server/controller/ServiceControllerTest.java   |   6 +-
 .../manager/server/service/ConfigServiceTest.java  |  90 ----------
 36 files changed, 573 insertions(+), 978 deletions(-)

diff --git 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ServiceConfigPO.java
 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ServiceConfigPO.java
index 4c622cea..4a16fa8d 100644
--- 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ServiceConfigPO.java
+++ 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ServiceConfigPO.java
@@ -20,14 +20,12 @@ package org.apache.bigtop.manager.dao.po;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
-import lombok.ToString;
 
 import jakarta.persistence.Column;
 import jakarta.persistence.Id;
 import jakarta.persistence.Table;
 import jakarta.persistence.Transient;
 import java.io.Serializable;
-import java.util.List;
 
 @Data
 @EqualsAndHashCode(callSuper = true)
@@ -38,24 +36,24 @@ public class ServiceConfigPO extends BasePO implements 
Serializable {
     @Column(name = "id")
     private Long id;
 
-    @Column(name = "config_desc")
-    private String configDesc;
+    /**
+     * Config file name, eg: zookeeper-env, hdfs-site
+     */
+    @Column(name = "name")
+    private String name;
 
-    @Column(name = "version")
-    private Integer version;
+    /**
+     * Properties json, represents by key-value pair belongs to a config file
+     */
+    @Column(name = "properties_json")
+    private String propertiesJson;
 
-    @Column(name = "selected")
-    private Boolean selected;
-
-    @ToString.Exclude
-    private List<TypeConfigPO> configs;
+    @Column(name = "cluster_id")
+    private Long clusterId;
 
     @Column(name = "service_id")
     private Long serviceId;
 
-    @Column(name = "cluster_id")
-    private Long clusterId;
-
     @Transient
     @Column(name = "service_name")
     private String serviceName;
diff --git 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/TypeConfigPO.java
 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ServiceConfigSnapshotPO.java
similarity index 68%
rename from 
bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/TypeConfigPO.java
rename to 
bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ServiceConfigSnapshotPO.java
index 1fb21bf3..e0aa53ff 100644
--- 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/TypeConfigPO.java
+++ 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ServiceConfigSnapshotPO.java
@@ -28,19 +28,26 @@ import java.io.Serializable;
 
 @Data
 @EqualsAndHashCode(callSuper = true)
-@Table(name = "type_config")
-public class TypeConfigPO extends BasePO implements Serializable {
+@Table(name = "service_config_snapshot")
+public class ServiceConfigSnapshotPO extends BasePO implements Serializable {
 
     @Id
     @Column(name = "id")
     private Long id;
 
-    @Column(name = "type_name")
-    private String typeName;
+    @Column(name = "name")
+    private String name;
 
-    @Column(name = "properties_json")
-    private String propertiesJson;
+    @Column(name = "desc")
+    private String desc;
 
-    @Column(name = "service_config_id")
-    private Long serviceConfigId;
+    /**
+     * Config json, not like properties json in {@link ServiceConfigPO}
+     * this is json for a service, which contains all config file name and 
it's properties
+     */
+    @Column(name = "config_json")
+    private String configJson;
+
+    @Column(name = "service_id")
+    private Long serviceId;
 }
diff --git 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ServiceConfigDao.java
 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ServiceConfigDao.java
index ddfd24c9..e3cf5151 100644
--- 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ServiceConfigDao.java
+++ 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ServiceConfigDao.java
@@ -27,10 +27,7 @@ import java.util.List;
 
 public interface ServiceConfigDao extends BaseDao<ServiceConfigPO> {
 
-    List<ServiceConfigPO> findAllByClusterId(@Param("clusterId") Long 
clusterId);
+    List<ServiceConfigPO> findByServiceId(@Param("serviceId") Long serviceId);
 
-    ServiceConfigPO findByClusterIdAndServiceIdAndSelectedIsTrue(
-            @Param("clusterId") Long clusterId, @Param("serviceId") Long 
serviceId);
-
-    List<ServiceConfigPO> 
findAllByClusterIdAndSelectedIsTrue(@Param("clusterId") Long clusterId);
+    List<ServiceConfigPO> findByClusterId(@Param("clusterId") Long clusterId);
 }
diff --git 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/TypeConfigDao.java
 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ServiceConfigSnapshotDao.java
similarity index 73%
rename from 
bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/TypeConfigDao.java
rename to 
bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ServiceConfigSnapshotDao.java
index 0dd4b478..3adb2c0c 100644
--- 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/TypeConfigDao.java
+++ 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ServiceConfigSnapshotDao.java
@@ -19,6 +19,13 @@
 
 package org.apache.bigtop.manager.dao.repository;
 
-import org.apache.bigtop.manager.dao.po.TypeConfigPO;
+import org.apache.bigtop.manager.dao.po.ServiceConfigSnapshotPO;
 
-public interface TypeConfigDao extends BaseDao<TypeConfigPO> {}
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface ServiceConfigSnapshotDao extends 
BaseDao<ServiceConfigSnapshotPO> {
+
+    List<ServiceConfigSnapshotPO> findByServiceId(@Param("serviceId") Long 
serviceId);
+}
diff --git 
a/bigtop-manager-dao/src/main/resources/mapper/mysql/ServiceConfigMapper.xml 
b/bigtop-manager-dao/src/main/resources/mapper/mysql/ServiceConfigMapper.xml
index 52a30d61..f9d488fc 100644
--- a/bigtop-manager-dao/src/main/resources/mapper/mysql/ServiceConfigMapper.xml
+++ b/bigtop-manager-dao/src/main/resources/mapper/mysql/ServiceConfigMapper.xml
@@ -24,95 +24,33 @@
 <mapper namespace="org.apache.bigtop.manager.dao.repository.ServiceConfigDao">
 
     <sql id="baseColumns">
-        id, config_desc, version, selected, service_id, cluster_id, 
create_time, update_time
+        id, name, properties_json, cluster_id, service_id, create_time, 
update_time
     </sql>
 
     <sql id="baseColumnsV2">
-        ${alias}.id, ${alias}.config_desc, ${alias}.version, 
${alias}.selected, ${alias}.service_id, ${alias}.cluster_id, 
${alias}.create_time, ${alias}.update_time
+        ${alias}.id, ${alias}.name, ${alias}.properties_json, 
${alias}.cluster_id, ${alias}.service_id, ${alias}.create_time, 
${alias}.update_time
     </sql>
 
-    <resultMap id="serviceConfigMap" 
type="org.apache.bigtop.manager.dao.po.ServiceConfigPO">
-        <id column="id" property="id"/>
-        <result column="config_desc" property="configDesc"/>
-        <result column="version" property="version"/>
-        <result column="selected" property="selected"/>
-        <result column="service_id" property="serviceId"/>
-        <result column="cluster_id" property="clusterId"/>
-        <result column="create_time" property="createTime"/>
-        <result column="update_time" property="updateTime"/>
-        <result column="service_name" property="serviceName"/>
-        <collection property="configs" 
ofType="org.apache.bigtop.manager.dao.po.TypeConfigPO">
-            <id column="tc_id" property="id"/>
-            <result column="type_name" property="typeName"/>
-            <result column="properties_json" property="propertiesJson"/>
-        </collection>
-    </resultMap>
-
-    <select id="findAllByClusterId" parameterType="java.lang.Long" 
resultMap="serviceConfigMap">
-        select
-        <include refid="baseColumnsV2">
-            <property name="alias" value="r"/>
-        </include>
-        , s.service_name, tc.type_name, tc.properties_json, tc.id as tc_id
-        from
-        (select * from service_config
-        <where>
-            <if test="clusterId != 0">
-                cluster_id = #{clusterId}
-            </if>
-        </where>
-        ) r
-        inner join service s
-        on r.service_id = s.id
-        inner join type_config tc
-        on r.id = tc.service_config_id
-        order by version desc
-    </select>
-
-    <select id="findByClusterIdAndServiceIdAndSelectedIsTrue" 
resultMap="serviceConfigMap">
-        select
+    <select id="findByServiceId" 
resultType="org.apache.bigtop.manager.dao.po.ServiceConfigPO">
+        SELECT
         <include refid="baseColumnsV2">
-            <property name="alias" value="r"/>
-        </include>
-        , s.service_name, tc.type_name, tc.properties_json
-        from
-        (select * from service_config
-        <where>
-            selected = 1
-            <if test="clusterId != 0">
-                and cluster_id = #{clusterId}
-            </if>
-            <if test="serviceId != 0">
-                and service_id = #{serviceId}
-            </if>
-        </where>
-        ) r
-        inner join service s
-        on r.service_id = s.id
-        inner join type_config tc
-        on r.id = tc.service_config_id
-        limit 1
+            <property name="alias" value="sc"/>
+        </include>, s.service_name
+        FROM service_config sc
+        LEFT JOIN service s
+        ON sc.service_id = s.id
+        WHERE sc.service_id = #{serviceId}
     </select>
 
-    <select id="findAllByClusterIdAndSelectedIsTrue" 
resultMap="serviceConfigMap">
-        select
+    <select id="findByClusterId" 
resultType="org.apache.bigtop.manager.dao.po.ServiceConfigPO">
+        SELECT
         <include refid="baseColumnsV2">
-            <property name="alias" value="r"/>
-        </include>
-        , s.service_name, tc.type_name, tc.properties_json
-        from
-        (select * from service_config
-        <where>
-        selected = 1
-            <if test="clusterId != 0">
-                and cluster_id = #{clusterId}
-            </if>
-        </where>
-        ) r
-        inner join service s
-        on r.service_id = s.id
-        inner join type_config tc
-        on r.id = tc.service_config_id
+            <property name="alias" value="sc"/>
+        </include>, s.service_name
+        FROM service_config sc
+        LEFT JOIN service s
+        ON sc.service_id = s.id
+        WHERE sc.cluster_id = #{clusterId}
     </select>
 
 </mapper>
\ No newline at end of file
diff --git 
a/bigtop-manager-dao/src/main/resources/mapper/mysql/ServiceConfigSnapshotMapper.xml
 
b/bigtop-manager-dao/src/main/resources/mapper/mysql/ServiceConfigSnapshotMapper.xml
new file mode 100644
index 00000000..5aec1335
--- /dev/null
+++ 
b/bigtop-manager-dao/src/main/resources/mapper/mysql/ServiceConfigSnapshotMapper.xml
@@ -0,0 +1,40 @@
+<?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.bigtop.manager.dao.repository.ServiceConfigSnapshotDao">
+
+    <sql id="baseColumns">
+        id, name, `desc`, config_json, service_id, create_time, update_time
+    </sql>
+
+    <sql id="baseColumnsV2">
+        ${alias}.id, ${alias}.name, ${alias}.`desc`, ${alias}.config_json, 
${alias}.service_id, ${alias}.create_time, ${alias}.update_time
+    </sql>
+
+    <select id="findByServiceId" 
resultType="org.apache.bigtop.manager.dao.po.ServiceConfigSnapshotPO">
+        SELECT
+        <include refid="baseColumns" />
+        FROM service_config_snapshot
+        WHERE service_id = #{serviceId}
+    </select>
+</mapper>
\ No newline at end of file
diff --git 
a/bigtop-manager-dao/src/main/resources/mapper/postgresql/ServiceConfigMapper.xml
 
b/bigtop-manager-dao/src/main/resources/mapper/postgresql/ServiceConfigMapper.xml
index e40c4f9e..7917eccf 100644
--- 
a/bigtop-manager-dao/src/main/resources/mapper/postgresql/ServiceConfigMapper.xml
+++ 
b/bigtop-manager-dao/src/main/resources/mapper/postgresql/ServiceConfigMapper.xml
@@ -24,95 +24,32 @@
 <mapper namespace="org.apache.bigtop.manager.dao.repository.ServiceConfigDao">
 
     <sql id="baseColumns">
-        id, config_desc, version, selected, service_id, cluster_id, 
create_time, update_time
+        id, name, properties_json, cluster_id, service_id, create_time, 
update_time
     </sql>
 
     <sql id="baseColumnsV2">
-        ${alias}.id, ${alias}.config_desc, ${alias}.version, 
${alias}.selected, ${alias}.service_id, ${alias}.cluster_id, 
${alias}.create_time, ${alias}.update_time
+        ${alias}.id, ${alias}.name, ${alias}.properties_json, 
${alias}.cluster_id, ${alias}.service_id, ${alias}.create_time, 
${alias}.update_time
     </sql>
 
-    <resultMap id="serviceConfigMap" 
type="org.apache.bigtop.manager.dao.po.ServiceConfigPO">
-        <id column="id" property="id"/>
-        <result column="config_desc" property="configDesc"/>
-        <result column="version" property="version"/>
-        <result column="selected" property="selected"/>
-        <result column="service_id" property="serviceId"/>
-        <result column="cluster_id" property="clusterId"/>
-        <result column="create_time" property="createTime"/>
-        <result column="update_time" property="updateTime"/>
-        <result column="service_name" property="serviceName"/>
-        <collection property="configs" 
ofType="org.apache.bigtop.manager.dao.po.TypeConfigPO">
-            <id column="tc_id" property="id"/>
-            <result column="type_name" property="typeName"/>
-            <result column="properties_json" property="propertiesJson"/>
-        </collection>
-    </resultMap>
-
-    <select id="findAllByClusterId" parameterType="java.lang.Long" 
resultMap="serviceConfigMap">
-        select
+    <select id="findByServiceId" 
resultType="org.apache.bigtop.manager.dao.po.ServiceConfigPO">
+        SELECT
         <include refid="baseColumnsV2">
-            <property name="alias" value="r"/>
-        </include>
-        , s.service_name, tc.type_name, tc.properties_json, tc.id as tc_id
-        from
-        (select * from service_config
-        <where>
-            <if test="clusterId != 0">
-                cluster_id = #{clusterId}
-            </if>
-        </where>
-        ) r
-        inner join service s
-        on r.service_id = s.id
-        inner join type_config tc
-        on r.id = tc.service_config_id
-        order by version desc
+            <property name="alias" value="sc"/>
+        </include>, s.service_name
+        FROM service_config sc
+        LEFT JOIN service s
+        ON sc.service_id = s.id
+        WHERE sc.service_id = #{serviceId}
     </select>
 
-    <select id="findByClusterIdAndServiceIdAndSelectedIsTrue" 
resultMap="serviceConfigMap">
-        select
+    <select id="findByClusterId" 
resultType="org.apache.bigtop.manager.dao.po.ServiceConfigPO">
+        SELECT
         <include refid="baseColumnsV2">
-            <property name="alias" value="r"/>
-        </include>
-        , s.service_name, tc.type_name, tc.properties_json
-        from
-        (select * from service_config
-        <where>
-            selected is true
-            <if test="clusterId != 0">
-                and cluster_id = #{clusterId}
-            </if>
-            <if test="serviceId != 0">
-                and service_id = #{serviceId}
-            </if>
-        </where>
-        ) r
-        inner join service s
-        on r.service_id = s.id
-        inner join type_config tc
-        on r.id = tc.service_config_id
-        limit 1
+            <property name="alias" value="sc"/>
+        </include>, s.service_name
+        FROM service_config sc
+        LEFT JOIN service s
+        ON sc.service_id = s.id
+        WHERE sc.cluster_id = #{clusterId}
     </select>
-
-    <select id="findAllByClusterIdAndSelectedIsTrue" 
resultMap="serviceConfigMap">
-        select
-        <include refid="baseColumnsV2">
-            <property name="alias" value="r"/>
-        </include>
-        , s.service_name, tc.type_name, tc.properties_json
-        from
-        (select * from service_config
-        <where>
-        selected is true
-            <if test="clusterId != 0">
-                and cluster_id = #{clusterId}
-            </if>
-        </where>
-        ) r
-        inner join service s
-        on r.service_id = s.id
-        inner join type_config tc
-        on r.id = tc.service_config_id
-    </select>
-
 </mapper>
\ No newline at end of file
diff --git 
a/bigtop-manager-dao/src/main/resources/mapper/postgresql/ServiceConfigSnapshotMapper.xml
 
b/bigtop-manager-dao/src/main/resources/mapper/postgresql/ServiceConfigSnapshotMapper.xml
new file mode 100644
index 00000000..1419def5
--- /dev/null
+++ 
b/bigtop-manager-dao/src/main/resources/mapper/postgresql/ServiceConfigSnapshotMapper.xml
@@ -0,0 +1,40 @@
+<?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.bigtop.manager.dao.repository.ServiceConfigSnapshotDao">
+
+    <sql id="baseColumns">
+        id, name, "desc", config_json, service_id, create_time, update_time
+    </sql>
+
+    <sql id="baseColumnsV2">
+        ${alias}.id, ${alias}.name, ${alias}."desc", ${alias}.config_json, 
${alias}.service_id, ${alias}.create_time, ${alias}.update_time
+    </sql>
+
+    <select id="findByServiceId" 
resultType="org.apache.bigtop.manager.dao.po.ServiceConfigSnapshotPO">
+        SELECT
+        <include refid="baseColumns" />
+        FROM service_config_snapshot
+        WHERE service_id = #{serviceId}
+    </select>
+</mapper>
\ No newline at end of file
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ServiceInstallJob.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ServiceInstallJob.java
index 4cf3107c..1cd1119d 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ServiceInstallJob.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ServiceInstallJob.java
@@ -34,7 +34,6 @@ import 
org.apache.bigtop.manager.server.model.dto.ComponentDTO;
 import org.apache.bigtop.manager.server.model.dto.ComponentHostDTO;
 import org.apache.bigtop.manager.server.model.dto.ServiceDTO;
 import org.apache.bigtop.manager.server.model.dto.command.ServiceCommandDTO;
-import org.apache.bigtop.manager.server.service.ConfigService;
 import org.apache.bigtop.manager.server.utils.StackUtils;
 
 import java.util.ArrayList;
@@ -42,7 +41,6 @@ import java.util.List;
 
 public class ServiceInstallJob extends AbstractServiceJob {
 
-    private ConfigService configService;
     private ServiceDao serviceDao;
     private HostDao hostDao;
 
@@ -54,7 +52,6 @@ public class ServiceInstallJob extends AbstractServiceJob {
     protected void injectBeans() {
         super.injectBeans();
 
-        this.configService = SpringContextHolder.getBean(ConfigService.class);
         this.serviceDao = SpringContextHolder.getBean(ServiceDao.class);
         this.hostDao = SpringContextHolder.getBean(HostDao.class);
     }
@@ -146,8 +143,7 @@ public class ServiceInstallJob extends AbstractServiceJob {
             serviceDao.save(servicePO);
         }
 
-        // 2. Update configs
-        configService.upsert(clusterId, servicePO.getId(), 
serviceCommand.getConfigs());
+        // TODO 2. Update configs
 
         for (ComponentHostDTO componentHostDTO : 
serviceCommand.getComponentHosts()) {
             String componentName = componentHostDTO.getComponentName();
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/task/CacheFileUpdateTask.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/task/CacheFileUpdateTask.java
index e484f5d8..90f1a82c 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/task/CacheFileUpdateTask.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/task/CacheFileUpdateTask.java
@@ -32,7 +32,6 @@ import org.apache.bigtop.manager.dao.po.RepoPO;
 import org.apache.bigtop.manager.dao.po.ServiceConfigPO;
 import org.apache.bigtop.manager.dao.po.ServicePO;
 import org.apache.bigtop.manager.dao.po.SettingPO;
-import org.apache.bigtop.manager.dao.po.TypeConfigPO;
 import org.apache.bigtop.manager.dao.repository.ClusterDao;
 import org.apache.bigtop.manager.dao.repository.ComponentDao;
 import org.apache.bigtop.manager.dao.repository.HostComponentDao;
@@ -45,10 +44,6 @@ import 
org.apache.bigtop.manager.grpc.generated.CommandRequest;
 import org.apache.bigtop.manager.grpc.generated.CommandType;
 import org.apache.bigtop.manager.server.holder.SpringContextHolder;
 import org.apache.bigtop.manager.server.model.converter.RepoConverter;
-import org.apache.bigtop.manager.server.model.dto.PropertyDTO;
-import org.apache.bigtop.manager.server.utils.StackConfigUtils;
-
-import com.fasterxml.jackson.core.type.TypeReference;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -118,8 +113,7 @@ public class CacheFileUpdateTask extends AbstractTask {
         Long clusterId = clusterPO.getId();
 
         List<ServicePO> servicePOList = 
serviceDao.findAllByClusterId(clusterId);
-        List<ServiceConfigPO> serviceConfigPOList =
-                
serviceConfigDao.findAllByClusterIdAndSelectedIsTrue(clusterPO.getId());
+        List<ServiceConfigPO> serviceConfigPOList = 
serviceConfigDao.findByClusterId(clusterPO.getId());
         List<HostComponentPO> hostComponentPOList = 
hostComponentDao.findAllByClusterId(clusterId);
         List<RepoPO> repoPOList = 
repoDao.findAllByClusterId(clusterPO.getId());
         Iterable<SettingPO> settings = settingDao.findAll();
@@ -131,20 +125,14 @@ public class CacheFileUpdateTask extends AbstractTask {
 
         serviceConfigMap = new HashMap<>();
         for (ServiceConfigPO serviceConfigPO : serviceConfigPOList) {
-            for (TypeConfigPO typeConfigPO : serviceConfigPO.getConfigs()) {
-                List<PropertyDTO> properties =
-                        
JsonUtils.readFromString(typeConfigPO.getPropertiesJson(), new 
TypeReference<>() {});
-                String configMapStr = 
JsonUtils.writeAsString(StackConfigUtils.extractConfigMap(properties));
-
-                if 
(serviceConfigMap.containsKey(serviceConfigPO.getServiceName())) {
-                    serviceConfigMap
-                            .get(serviceConfigPO.getServiceName())
-                            .put(typeConfigPO.getTypeName(), configMapStr);
-                } else {
-                    Map<String, Object> hashMap = new HashMap<>();
-                    hashMap.put(typeConfigPO.getTypeName(), configMapStr);
-                    serviceConfigMap.put(serviceConfigPO.getServiceName(), 
hashMap);
-                }
+            if 
(serviceConfigMap.containsKey(serviceConfigPO.getServiceName())) {
+                serviceConfigMap
+                        .get(serviceConfigPO.getServiceName())
+                        .put(serviceConfigPO.getName(), 
serviceConfigPO.getPropertiesJson());
+            } else {
+                Map<String, Object> hashMap = new HashMap<>();
+                hashMap.put(serviceConfigPO.getName(), 
serviceConfigPO.getPropertiesJson());
+                serviceConfigMap.put(serviceConfigPO.getServiceName(), 
hashMap);
             }
         }
 
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/controller/ConfigController.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/controller/ConfigController.java
deleted file mode 100644
index e82cc573..00000000
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/controller/ConfigController.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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
- *
- *    https://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.bigtop.manager.server.controller;
-
-import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO;
-import org.apache.bigtop.manager.server.service.ConfigService;
-import org.apache.bigtop.manager.server.utils.ResponseEntity;
-
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.extern.slf4j.Slf4j;
-
-import jakarta.annotation.Resource;
-import java.util.List;
-
-@Slf4j
-@Tag(name = "Cluster Configuration Controller")
-@Validated
-@RestController
-@RequestMapping("/clusters/{clusterId}/configurations")
-public class ConfigController {
-
-    @Resource
-    private ConfigService configService;
-
-    @Operation(summary = "list", description = "list all version 
configurations")
-    @GetMapping
-    public ResponseEntity<List<ServiceConfigVO>> list(@PathVariable Long 
clusterId) {
-        return ResponseEntity.success(configService.list(clusterId));
-    }
-
-    @Operation(summary = "list", description = "list all latest 
configurations")
-    @GetMapping("/latest")
-    public ResponseEntity<List<ServiceConfigVO>> latest(@PathVariable Long 
clusterId) {
-        return ResponseEntity.success(configService.latest(clusterId));
-    }
-}
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/controller/ServiceController.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/controller/ServiceController.java
index 24ba7da6..c8e1cfcd 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/controller/ServiceController.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/controller/ServiceController.java
@@ -18,12 +18,19 @@
  */
 package org.apache.bigtop.manager.server.controller;
 
+import org.apache.bigtop.manager.server.model.req.ServiceConfigReq;
+import org.apache.bigtop.manager.server.model.req.ServiceConfigSnapshotReq;
+import org.apache.bigtop.manager.server.model.vo.ServiceConfigSnapshotVO;
+import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO;
 import org.apache.bigtop.manager.server.model.vo.ServiceVO;
 import org.apache.bigtop.manager.server.service.ServiceService;
 import org.apache.bigtop.manager.server.utils.ResponseEntity;
 
+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.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -51,7 +58,48 @@ public class ServiceController {
 
     @Operation(summary = "get", description = "Get a service")
     @GetMapping("/{id}")
-    public ResponseEntity<ServiceVO> get(@PathVariable Long id) {
+    public ResponseEntity<ServiceVO> get(@PathVariable Long clusterId, 
@PathVariable Long id) {
         return ResponseEntity.success(serviceService.get(id));
     }
+
+    @Operation(summary = "list service configs", description = "List service 
configs")
+    @GetMapping("/{id}/configs")
+    public ResponseEntity<List<ServiceConfigVO>> listConf(@PathVariable Long 
clusterId, @PathVariable Long id) {
+        return ResponseEntity.success(serviceService.listConf(clusterId, id));
+    }
+
+    @Operation(summary = "update service configs", description = "Update 
service configs")
+    @PostMapping("/{id}/configs")
+    public ResponseEntity<List<ServiceConfigVO>> updateConf(
+            @PathVariable Long clusterId, @PathVariable Long id, @RequestBody 
List<ServiceConfigReq> reqs) {
+        return ResponseEntity.success(serviceService.updateConf(clusterId, id, 
reqs));
+    }
+
+    @Operation(summary = "list config snapshots", description = "List config 
snapshots")
+    @GetMapping("/{id}/config-snapshots")
+    public ResponseEntity<List<ServiceConfigSnapshotVO>> listConfSnapshot(
+            @PathVariable Long clusterId, @PathVariable Long id) {
+        return 
ResponseEntity.success(serviceService.listConfSnapshots(clusterId, id));
+    }
+
+    @Operation(summary = "take config snapshot", description = "Take config 
snapshot")
+    @PostMapping("/{id}/config-snapshots")
+    public ResponseEntity<ServiceConfigSnapshotVO> takeConfSnapshot(
+            @PathVariable Long clusterId, @PathVariable Long id, @RequestBody 
ServiceConfigSnapshotReq req) {
+        return 
ResponseEntity.success(serviceService.takeConfSnapshot(clusterId, id, req));
+    }
+
+    @Operation(summary = "recovery config snapshot", description = "Recovery 
config snapshot")
+    @PostMapping("/{id}/config-snapshots/{snapshotId}")
+    public ResponseEntity<List<ServiceConfigVO>> recoveryConfSnapshot(
+            @PathVariable Long clusterId, @PathVariable Long id, @PathVariable 
Long snapshotId) {
+        return 
ResponseEntity.success(serviceService.recoveryConfSnapshot(clusterId, id, 
snapshotId));
+    }
+
+    @Operation(summary = "delete config snapshot", description = "Delete 
config snapshot")
+    @DeleteMapping("/{id}/config-snapshots/{snapshotId}")
+    public ResponseEntity<Boolean> deleteConfSnapshot(
+            @PathVariable Long clusterId, @PathVariable Long id, @PathVariable 
Long snapshotId) {
+        return 
ResponseEntity.success(serviceService.deleteConfSnapshot(clusterId, id, 
snapshotId));
+    }
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigConverter.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigConverter.java
index 6a163a09..37d2574d 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigConverter.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigConverter.java
@@ -20,20 +20,28 @@ package org.apache.bigtop.manager.server.model.converter;
 
 import org.apache.bigtop.manager.dao.po.ServiceConfigPO;
 import org.apache.bigtop.manager.server.config.MapStructSharedConfig;
+import org.apache.bigtop.manager.server.model.dto.ServiceConfigDTO;
 import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO;
 
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
 
 @Mapper(
-        uses = {TypeConfigConverter.class},
+        uses = {ConverterTool.class},
         config = MapStructSharedConfig.class)
 public interface ServiceConfigConverter {
 
     ServiceConfigConverter INSTANCE = 
Mappers.getMapper(ServiceConfigConverter.class);
 
+    @Mapping(target = "properties", source = "propertiesJson", qualifiedByName 
= "json2PropertyDTOList")
+    ServiceConfigDTO fromPO2DTO(ServiceConfigPO serviceConfigPO);
+
+    List<ServiceConfigDTO> fromPO2DTO(List<ServiceConfigPO> 
serviceConfigPOList);
+
+    @Mapping(target = "properties", source = "propertiesJson", qualifiedByName 
= "json2PropertyVOList")
     ServiceConfigVO fromPO2VO(ServiceConfigPO serviceConfigPO);
 
     List<ServiceConfigVO> fromPO2VO(List<ServiceConfigPO> serviceConfigPOList);
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/TypeConfigConverter.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigSnapshotConverter.java
similarity index 50%
rename from 
bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/TypeConfigConverter.java
rename to 
bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigSnapshotConverter.java
index 69712797..41fe4799 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/TypeConfigConverter.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/converter/ServiceConfigSnapshotConverter.java
@@ -18,35 +18,26 @@
  */
 package org.apache.bigtop.manager.server.model.converter;
 
-import org.apache.bigtop.manager.dao.po.TypeConfigPO;
+import org.apache.bigtop.manager.dao.po.ServiceConfigSnapshotPO;
 import org.apache.bigtop.manager.server.config.MapStructSharedConfig;
-import org.apache.bigtop.manager.server.model.dto.TypeConfigDTO;
-import org.apache.bigtop.manager.server.model.vo.TypeConfigVO;
+import org.apache.bigtop.manager.server.model.dto.ServiceConfigSnapshotDTO;
+import org.apache.bigtop.manager.server.model.vo.ServiceConfigSnapshotVO;
 
 import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
 
-@Mapper(
-        uses = {ConverterTool.class},
-        config = MapStructSharedConfig.class)
-public interface TypeConfigConverter {
+@Mapper(config = MapStructSharedConfig.class)
+public interface ServiceConfigSnapshotConverter {
 
-    TypeConfigConverter INSTANCE = 
Mappers.getMapper(TypeConfigConverter.class);
+    ServiceConfigSnapshotConverter INSTANCE = 
Mappers.getMapper(ServiceConfigSnapshotConverter.class);
 
-    @Mapping(target = "properties", source = "propertiesJson", qualifiedByName 
= "json2PropertyDTOList")
-    TypeConfigDTO fromPO2DTO(TypeConfigPO typeConfigPO);
+    ServiceConfigSnapshotDTO fromPO2DTO(ServiceConfigSnapshotPO 
serviceConfigSnapshotPO);
 
-    List<TypeConfigDTO> fromPO2DTO(List<TypeConfigPO> typeConfigPOList);
+    List<ServiceConfigSnapshotDTO> fromPO2DTO(List<ServiceConfigSnapshotPO> 
serviceConfigSnapshotPOList);
 
-    TypeConfigVO fromDTO2VO(TypeConfigDTO typeConfigDTO);
+    ServiceConfigSnapshotVO fromPO2VO(ServiceConfigSnapshotPO 
serviceConfigSnapshotPO);
 
-    List<TypeConfigVO> fromDTO2VO(List<TypeConfigDTO> typeConfigDTOList);
-
-    @Mapping(target = "properties", source = "propertiesJson", qualifiedByName 
= "json2PropertyVOList")
-    TypeConfigVO fromPO2VO(TypeConfigPO typeConfigPO);
-
-    List<TypeConfigVO> fromPO2VO(List<TypeConfigPO> typeConfigPOList);
+    List<ServiceConfigSnapshotVO> fromPO2VO(List<ServiceConfigSnapshotPO> 
serviceConfigSnapshotPOList);
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceConfigDTO.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceConfigDTO.java
index ae253b2f..8a96a47d 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceConfigDTO.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceConfigDTO.java
@@ -26,11 +26,9 @@ import java.util.List;
 @Data
 public class ServiceConfigDTO implements Serializable {
 
-    private String serviceName;
+    private Long id;
 
-    private String configDesc;
+    private String name;
 
-    private Integer version;
-
-    private List<TypeConfigDTO> configs;
+    private List<PropertyDTO> properties;
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/TypeConfigDTO.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceConfigSnapshotDTO.java
similarity index 84%
copy from 
bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/TypeConfigDTO.java
copy to 
bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceConfigSnapshotDTO.java
index 40b72b81..1131a4ab 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/TypeConfigDTO.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceConfigSnapshotDTO.java
@@ -21,12 +21,15 @@ package org.apache.bigtop.manager.server.model.dto;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.util.List;
 
 @Data
-public class TypeConfigDTO implements Serializable {
+public class ServiceConfigSnapshotDTO implements Serializable {
 
-    private String typeName;
+    private Long id;
 
-    private List<PropertyDTO> properties;
+    private String name;
+
+    private String desc;
+
+    private String configJson;
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceDTO.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceDTO.java
index f4440b4c..6c800f70 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceDTO.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/ServiceDTO.java
@@ -39,7 +39,7 @@ public class ServiceDTO {
 
     private List<ComponentDTO> components;
 
-    private List<TypeConfigDTO> configs;
+    private List<ServiceConfigDTO> configs;
 
     private List<String> requiredServices;
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/command/ServiceCommandDTO.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/command/ServiceCommandDTO.java
index 4ffa1e90..bce58fa9 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/command/ServiceCommandDTO.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/command/ServiceCommandDTO.java
@@ -19,7 +19,7 @@
 package org.apache.bigtop.manager.server.model.dto.command;
 
 import org.apache.bigtop.manager.server.model.dto.ComponentHostDTO;
-import org.apache.bigtop.manager.server.model.dto.TypeConfigDTO;
+import org.apache.bigtop.manager.server.model.dto.ServiceConfigDTO;
 
 import lombok.Data;
 
@@ -39,5 +39,5 @@ public class ServiceCommandDTO implements Serializable {
 
     private List<ComponentHostDTO> componentHosts;
 
-    private List<TypeConfigDTO> configs;
+    private List<ServiceConfigDTO> configs;
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/ServiceConfigReq.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/ServiceConfigReq.java
index 63a8b5b8..ed45f36f 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/ServiceConfigReq.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/ServiceConfigReq.java
@@ -18,21 +18,16 @@
  */
 package org.apache.bigtop.manager.server.model.req;
 
-import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
 import java.util.List;
 
 @Data
 public class ServiceConfigReq {
 
-    @NotBlank
-    @Schema(example = "ZOOKEEPER")
-    private String serviceName;
+    private Long id;
 
-    private String configDesc;
+    private String name;
 
-    private List<@Valid TypeConfigReq> configs;
+    private List<PropertyReq> properties;
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/TypeConfigDTO.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/ServiceConfigSnapshotReq.java
similarity index 81%
rename from 
bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/TypeConfigDTO.java
rename to 
bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/ServiceConfigSnapshotReq.java
index 40b72b81..d9c09382 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/TypeConfigDTO.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/ServiceConfigSnapshotReq.java
@@ -16,17 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.bigtop.manager.server.model.dto;
+package org.apache.bigtop.manager.server.model.req;
 
 import lombok.Data;
 
 import java.io.Serializable;
-import java.util.List;
 
 @Data
-public class TypeConfigDTO implements Serializable {
+public class ServiceConfigSnapshotReq implements Serializable {
 
-    private String typeName;
+    private String name;
 
-    private List<PropertyDTO> properties;
+    private String desc;
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/TypeConfigReq.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/TypeConfigReq.java
deleted file mode 100644
index f4824a1f..00000000
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/TypeConfigReq.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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
- *
- *    https://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.bigtop.manager.server.model.req;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotEmpty;
-import java.util.List;
-
-@Data
-public class TypeConfigReq {
-
-    @NotBlank
-    @Schema(example = "zoo.cfg", requiredMode = Schema.RequiredMode.REQUIRED)
-    private String typeName;
-
-    @Schema(example = "1", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
-    private Integer version;
-
-    @NotEmpty
-    @Schema(example = "{\"name\":\"clientPort\",\"value\": \"2181\"}")
-    private List<@Valid PropertyReq> properties;
-}
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/command/ServiceCommandReq.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/command/ServiceCommandReq.java
index 499c605f..bbd01b6c 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/command/ServiceCommandReq.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/command/ServiceCommandReq.java
@@ -20,7 +20,7 @@ package org.apache.bigtop.manager.server.model.req.command;
 
 import org.apache.bigtop.manager.server.config.CommandGroupSequenceProvider;
 import org.apache.bigtop.manager.server.model.req.ComponentHostReq;
-import org.apache.bigtop.manager.server.model.req.TypeConfigReq;
+import org.apache.bigtop.manager.server.model.req.ServiceConfigReq;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
@@ -51,5 +51,5 @@ public class ServiceCommandReq {
 
     @NotEmpty(groups = 
{CommandGroupSequenceProvider.ServiceInstallCommandGroup.class})
     @Schema(description = "Configs for service")
-    private List<@Valid TypeConfigReq> configs;
+    private List<@Valid ServiceConfigReq> configs;
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/TypeConfigVO.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceConfigSnapshotVO.java
similarity index 82%
rename from 
bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/TypeConfigVO.java
rename to 
bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceConfigSnapshotVO.java
index 87ad720f..dd7c4a2f 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/TypeConfigVO.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceConfigSnapshotVO.java
@@ -20,12 +20,16 @@ package org.apache.bigtop.manager.server.model.vo;
 
 import lombok.Data;
 
-import java.util.List;
+import java.io.Serializable;
 
 @Data
-public class TypeConfigVO {
+public class ServiceConfigSnapshotVO implements Serializable {
 
-    private String typeName;
+    private Long id;
 
-    private List<PropertyVO> properties;
+    private String name;
+
+    private String desc;
+
+    private String configJson;
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceConfigVO.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceConfigVO.java
index 8590eeb2..7b08588b 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceConfigVO.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceConfigVO.java
@@ -25,15 +25,9 @@ import java.util.List;
 @Data
 public class ServiceConfigVO {
 
-    private String serviceName;
+    private Long id;
 
-    private String configDesc;
+    private String name;
 
-    private Integer version;
-
-    private List<TypeConfigVO> configs;
-
-    private String createTime;
-
-    private String updateTime;
+    private List<PropertyVO> properties;
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceVO.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceVO.java
index e82787bf..99136b9e 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceVO.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/vo/ServiceVO.java
@@ -41,7 +41,7 @@ public class ServiceVO {
 
     private List<ComponentVO> components;
 
-    private List<TypeConfigVO> configs;
+    private List<ServiceConfigVO> configs;
 
     private List<String> requiredServices;
 
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/ConfigService.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/ConfigService.java
deleted file mode 100644
index 3869d344..00000000
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/ConfigService.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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
- *
- *    https://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.bigtop.manager.server.service;
-
-import org.apache.bigtop.manager.server.model.dto.TypeConfigDTO;
-import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO;
-
-import java.util.List;
-
-public interface ConfigService {
-
-    /**
-     * Get all version configurations.
-     *
-     * @return configurations
-     */
-    List<ServiceConfigVO> list(Long clusterId);
-
-    /**
-     * Get all latest configurations.
-     *
-     * @return configurations
-     */
-    List<ServiceConfigVO> latest(Long clusterId);
-
-    void upsert(Long clusterId, Long serviceId, List<TypeConfigDTO> configs);
-}
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/ServiceService.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/ServiceService.java
index 6f088f54..b88f933e 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/ServiceService.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/ServiceService.java
@@ -18,6 +18,10 @@
  */
 package org.apache.bigtop.manager.server.service;
 
+import org.apache.bigtop.manager.server.model.req.ServiceConfigReq;
+import org.apache.bigtop.manager.server.model.req.ServiceConfigSnapshotReq;
+import org.apache.bigtop.manager.server.model.vo.ServiceConfigSnapshotVO;
+import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO;
 import org.apache.bigtop.manager.server.model.vo.ServiceVO;
 
 import java.util.List;
@@ -37,4 +41,16 @@ public interface ServiceService {
      * @return service
      */
     ServiceVO get(Long id);
+
+    List<ServiceConfigVO> listConf(Long clusterId, Long serviceId);
+
+    List<ServiceConfigVO> updateConf(Long clusterId, Long serviceId, 
List<ServiceConfigReq> reqs);
+
+    List<ServiceConfigSnapshotVO> listConfSnapshots(Long clusterId, Long 
serviceId);
+
+    ServiceConfigSnapshotVO takeConfSnapshot(Long clusterId, Long serviceId, 
ServiceConfigSnapshotReq req);
+
+    List<ServiceConfigVO> recoveryConfSnapshot(Long clusterId, Long serviceId, 
Long snapshotId);
+
+    Boolean deleteConfSnapshot(Long clusterId, Long serviceId, Long 
snapshotId);
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ConfigServiceImpl.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ConfigServiceImpl.java
deleted file mode 100644
index 1db6526e..00000000
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ConfigServiceImpl.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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
- *
- *    https://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.bigtop.manager.server.service.impl;
-
-import org.apache.bigtop.manager.common.utils.JsonUtils;
-import org.apache.bigtop.manager.dao.po.ClusterPO;
-import org.apache.bigtop.manager.dao.po.ServiceConfigPO;
-import org.apache.bigtop.manager.dao.po.ServicePO;
-import org.apache.bigtop.manager.dao.po.TypeConfigPO;
-import org.apache.bigtop.manager.dao.repository.ClusterDao;
-import org.apache.bigtop.manager.dao.repository.ServiceConfigDao;
-import org.apache.bigtop.manager.dao.repository.ServiceDao;
-import org.apache.bigtop.manager.dao.repository.TypeConfigDao;
-import org.apache.bigtop.manager.server.model.converter.ServiceConfigConverter;
-import org.apache.bigtop.manager.server.model.converter.TypeConfigConverter;
-import org.apache.bigtop.manager.server.model.dto.PropertyDTO;
-import org.apache.bigtop.manager.server.model.dto.TypeConfigDTO;
-import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO;
-import org.apache.bigtop.manager.server.service.ConfigService;
-
-import org.springframework.stereotype.Service;
-
-import lombok.extern.slf4j.Slf4j;
-
-import jakarta.annotation.Resource;
-import java.util.List;
-
-@Slf4j
-@Service
-public class ConfigServiceImpl implements ConfigService {
-
-    @Resource
-    private ClusterDao clusterDao;
-
-    @Resource
-    private ServiceDao serviceDao;
-
-    @Resource
-    private ServiceConfigDao serviceConfigDao;
-
-    @Resource
-    private TypeConfigDao typeConfigDao;
-
-    @Override
-    public List<ServiceConfigVO> list(Long clusterId) {
-        List<ServiceConfigPO> list = 
serviceConfigDao.findAllByClusterId(clusterId);
-        return ServiceConfigConverter.INSTANCE.fromPO2VO(list);
-    }
-
-    @Override
-    public List<ServiceConfigVO> latest(Long clusterId) {
-        List<ServiceConfigPO> list = 
serviceConfigDao.findAllByClusterIdAndSelectedIsTrue(clusterId);
-        return ServiceConfigConverter.INSTANCE.fromPO2VO(list);
-    }
-
-    @Override
-    public void upsert(Long clusterId, Long serviceId, List<TypeConfigDTO> 
configs) {
-        // Save configs
-        ClusterPO clusterPO = clusterDao.findById(clusterId);
-        ServicePO servicePO = serviceDao.findById(serviceId);
-        ServiceConfigPO serviceCurrentConfig = 
findServiceCurrentConfig(clusterPO, servicePO);
-        if (serviceCurrentConfig == null) {
-            // Add config for new service
-            addServiceConfig(clusterPO, servicePO, configs);
-        } else {
-            // Upsert config for existing service
-            upsertServiceConfig(clusterPO, servicePO, serviceCurrentConfig, 
configs);
-        }
-    }
-
-    private ServiceConfigPO findServiceCurrentConfig(ClusterPO clusterPO, 
ServicePO servicePO) {
-        return 
serviceConfigDao.findByClusterIdAndServiceIdAndSelectedIsTrue(clusterPO.getId(),
 servicePO.getId());
-    }
-
-    private void upsertServiceConfig(
-            ClusterPO clusterPO, ServicePO servicePO, ServiceConfigPO 
currentConfig, List<TypeConfigDTO> configs) {
-        List<TypeConfigDTO> existConfigs = 
TypeConfigConverter.INSTANCE.fromPO2DTO(currentConfig.getConfigs());
-        if (shouldUpdateConfig(existConfigs, configs)) {
-            // Unselect current config
-            currentConfig.setSelected(false);
-            serviceConfigDao.partialUpdateById(currentConfig);
-
-            // Create a new config
-            String configDesc = "Update config for " + 
servicePO.getServiceName();
-            Integer version = currentConfig.getVersion() + 1;
-            addServiceConfig(clusterPO, servicePO, configs, configDesc, 
version);
-        }
-    }
-
-    private Boolean shouldUpdateConfig(List<TypeConfigDTO> existConfigs, 
List<TypeConfigDTO> newConfigs) {
-        if (existConfigs.size() != newConfigs.size()) {
-            return true;
-        }
-
-        for (TypeConfigDTO newConfig : newConfigs) {
-            for (TypeConfigDTO existConfig : existConfigs) {
-                if (existConfig.getTypeName().equals(newConfig.getTypeName())) 
{
-                    if 
(!existConfig.getProperties().equals(newConfig.getProperties())) {
-                        return true;
-                    }
-                }
-            }
-        }
-
-        return false;
-    }
-
-    private void addServiceConfig(ClusterPO clusterPO, ServicePO servicePO, 
List<TypeConfigDTO> configs) {
-        String configDesc = "Initial config for " + servicePO.getServiceName();
-        Integer version = 1;
-        addServiceConfig(clusterPO, servicePO, configs, configDesc, version);
-    }
-
-    private void addServiceConfig(
-            ClusterPO clusterPO, ServicePO servicePO, List<TypeConfigDTO> 
configs, String configDesc, Integer version) {
-        ServiceConfigPO serviceConfigPO = new ServiceConfigPO();
-        serviceConfigPO.setClusterId(clusterPO.getId());
-        serviceConfigPO.setServiceId(servicePO.getId());
-        serviceConfigPO.setConfigDesc(configDesc);
-        serviceConfigPO.setVersion(version);
-        serviceConfigPO.setSelected(true);
-        serviceConfigDao.save(serviceConfigPO);
-
-        for (TypeConfigDTO typeConfigDTO : configs) {
-            String typeName = typeConfigDTO.getTypeName();
-            List<PropertyDTO> properties = typeConfigDTO.getProperties();
-            TypeConfigPO typeConfigPO = new TypeConfigPO();
-            typeConfigPO.setTypeName(typeName);
-            
typeConfigPO.setPropertiesJson(JsonUtils.writeAsString(properties));
-            typeConfigPO.setServiceConfigId(serviceConfigPO.getId());
-            typeConfigDao.save(typeConfigPO);
-        }
-    }
-}
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ServiceServiceImpl.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ServiceServiceImpl.java
index 73df7858..47d898c3 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ServiceServiceImpl.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/ServiceServiceImpl.java
@@ -24,22 +24,29 @@ import org.apache.bigtop.manager.common.utils.JsonUtils;
 import org.apache.bigtop.manager.dao.po.ComponentPO;
 import org.apache.bigtop.manager.dao.po.HostComponentPO;
 import org.apache.bigtop.manager.dao.po.ServiceConfigPO;
+import org.apache.bigtop.manager.dao.po.ServiceConfigSnapshotPO;
 import org.apache.bigtop.manager.dao.po.ServicePO;
-import org.apache.bigtop.manager.dao.po.TypeConfigPO;
 import org.apache.bigtop.manager.dao.repository.HostComponentDao;
 import org.apache.bigtop.manager.dao.repository.ServiceConfigDao;
+import org.apache.bigtop.manager.dao.repository.ServiceConfigSnapshotDao;
 import org.apache.bigtop.manager.dao.repository.ServiceDao;
 import org.apache.bigtop.manager.server.enums.ApiExceptionEnum;
 import org.apache.bigtop.manager.server.exception.ApiException;
+import org.apache.bigtop.manager.server.model.converter.ServiceConfigConverter;
+import 
org.apache.bigtop.manager.server.model.converter.ServiceConfigSnapshotConverter;
 import org.apache.bigtop.manager.server.model.converter.ServiceConverter;
-import org.apache.bigtop.manager.server.model.converter.TypeConfigConverter;
 import org.apache.bigtop.manager.server.model.dto.PropertyDTO;
 import org.apache.bigtop.manager.server.model.dto.QuickLinkDTO;
-import org.apache.bigtop.manager.server.model.dto.TypeConfigDTO;
+import org.apache.bigtop.manager.server.model.dto.ServiceConfigDTO;
+import org.apache.bigtop.manager.server.model.req.ServiceConfigReq;
+import org.apache.bigtop.manager.server.model.req.ServiceConfigSnapshotReq;
 import org.apache.bigtop.manager.server.model.vo.QuickLinkVO;
+import org.apache.bigtop.manager.server.model.vo.ServiceConfigSnapshotVO;
+import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO;
 import org.apache.bigtop.manager.server.model.vo.ServiceVO;
 import org.apache.bigtop.manager.server.service.ServiceService;
 
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import org.springframework.stereotype.Service;
@@ -48,6 +55,7 @@ import lombok.extern.slf4j.Slf4j;
 
 import jakarta.annotation.Resource;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -65,6 +73,9 @@ public class ServiceServiceImpl implements ServiceService {
     @Resource
     private ServiceConfigDao serviceConfigDao;
 
+    @Resource
+    private ServiceConfigSnapshotDao serviceConfigSnapshotDao;
+
     @Override
     public List<ServiceVO> list(Long clusterId) {
         List<ServiceVO> res = new ArrayList<>();
@@ -117,21 +128,92 @@ public class ServiceServiceImpl implements ServiceService 
{
         return ServiceConverter.INSTANCE.fromPO2VO(servicePO);
     }
 
+    @Override
+    public List<ServiceConfigVO> listConf(Long clusterId, Long serviceId) {
+        List<ServiceConfigPO> list = 
serviceConfigDao.findByServiceId(serviceId);
+        if (CollectionUtils.isEmpty(list)) {
+            return List.of();
+        } else {
+            return ServiceConfigConverter.INSTANCE.fromPO2VO(list);
+        }
+    }
+
+    @Override
+    public List<ServiceConfigVO> updateConf(Long clusterId, Long serviceId, 
List<ServiceConfigReq> reqs) {
+        List<ServiceConfigPO> list = new ArrayList<>();
+        for (ServiceConfigReq req : reqs) {
+            ServiceConfigPO serviceConfigPO = new ServiceConfigPO();
+            serviceConfigPO.setId(req.getId());
+            
serviceConfigPO.setPropertiesJson(JsonUtils.writeAsString(req.getProperties()));
+            list.add(serviceConfigPO);
+        }
+
+        serviceConfigDao.partialUpdateByIds(list);
+        return listConf(clusterId, serviceId);
+    }
+
+    @Override
+    public List<ServiceConfigSnapshotVO> listConfSnapshots(Long clusterId, 
Long serviceId) {
+        List<ServiceConfigSnapshotPO> list = 
serviceConfigSnapshotDao.findByServiceId(serviceId);
+        if (CollectionUtils.isEmpty(list)) {
+            return List.of();
+        } else {
+            return ServiceConfigSnapshotConverter.INSTANCE.fromPO2VO(list);
+        }
+    }
+
+    @Override
+    public ServiceConfigSnapshotVO takeConfSnapshot(Long clusterId, Long 
serviceId, ServiceConfigSnapshotReq req) {
+        List<ServiceConfigPO> list = 
serviceConfigDao.findByServiceId(serviceId);
+        Map<String, String> confMap = new HashMap<>();
+        for (ServiceConfigPO serviceConfigPO : list) {
+            confMap.put(serviceConfigPO.getName(), 
serviceConfigPO.getPropertiesJson());
+        }
+
+        String confJson = JsonUtils.writeAsString(confMap);
+        ServiceConfigSnapshotPO serviceConfigSnapshotPO = new 
ServiceConfigSnapshotPO();
+        serviceConfigSnapshotPO.setName(req.getName());
+        serviceConfigSnapshotPO.setDesc(req.getDesc());
+        serviceConfigSnapshotPO.setConfigJson(confJson);
+        serviceConfigSnapshotPO.setServiceId(serviceId);
+        serviceConfigSnapshotDao.save(serviceConfigSnapshotPO);
+        return 
ServiceConfigSnapshotConverter.INSTANCE.fromPO2VO(serviceConfigSnapshotPO);
+    }
+
+    @Override
+    public List<ServiceConfigVO> recoveryConfSnapshot(Long clusterId, Long 
serviceId, Long snapshotId) {
+        ServiceConfigSnapshotPO serviceConfigSnapshotPO = 
serviceConfigSnapshotDao.findById(snapshotId);
+        Map<String, String> confMap = 
JsonUtils.readFromString(serviceConfigSnapshotPO.getConfigJson());
+        List<ServiceConfigPO> list = 
serviceConfigDao.findByServiceId(serviceId);
+        for (ServiceConfigPO serviceConfigPO : list) {
+            String value = confMap.get(serviceConfigPO.getName());
+            if (value != null) {
+                serviceConfigPO.setPropertiesJson(value);
+            }
+        }
+
+        serviceConfigDao.updateByIds(list);
+        return ServiceConfigConverter.INSTANCE.fromPO2VO(list);
+    }
+
+    @Override
+    public Boolean deleteConfSnapshot(Long clusterId, Long serviceId, Long 
snapshotId) {
+        return serviceConfigSnapshotDao.deleteById(snapshotId);
+    }
+
     private List<QuickLinkVO> resolveQuickLink(
             List<HostComponentPO> hostComponentPOList, String quickLinkJson, 
Long clusterId, Long serviceId) {
         List<QuickLinkVO> quickLinkVOList = new ArrayList<>();
 
         QuickLinkDTO quickLinkDTO = JsonUtils.readFromString(quickLinkJson, 
QuickLinkDTO.class);
 
-        ServiceConfigPO serviceConfigPO =
-                
serviceConfigDao.findByClusterIdAndServiceIdAndSelectedIsTrue(clusterId, 
serviceId);
-        List<TypeConfigPO> typeConfigPOList = serviceConfigPO.getConfigs();
+        List<ServiceConfigPO> serviceConfigPOList = 
serviceConfigDao.findByServiceId(serviceId);
 
         String httpPort = quickLinkDTO.getHttpPortDefault();
         // Use HTTP for now, need to handle https in the future
-        for (TypeConfigPO typeConfigPO : typeConfigPOList) {
-            TypeConfigDTO typeConfigDTO = 
TypeConfigConverter.INSTANCE.fromPO2DTO(typeConfigPO);
-            for (PropertyDTO propertyDTO : typeConfigDTO.getProperties()) {
+        for (ServiceConfigPO serviceConfigPO : serviceConfigPOList) {
+            ServiceConfigDTO serviceConfigDTO = 
ServiceConfigConverter.INSTANCE.fromPO2DTO(serviceConfigPO);
+            for (PropertyDTO propertyDTO : serviceConfigDTO.getProperties()) {
                 if 
(propertyDTO.getName().equals(quickLinkDTO.getHttpPortProperty())) {
 
                     httpPort = propertyDTO.getValue().contains(":")
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/StackServiceImpl.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/StackServiceImpl.java
index e6b421f3..9a5d26f7 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/StackServiceImpl.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/StackServiceImpl.java
@@ -22,7 +22,6 @@ import 
org.apache.bigtop.manager.server.model.converter.ServiceConverter;
 import org.apache.bigtop.manager.server.model.converter.StackConverter;
 import org.apache.bigtop.manager.server.model.dto.ServiceDTO;
 import org.apache.bigtop.manager.server.model.dto.StackDTO;
-import org.apache.bigtop.manager.server.model.dto.TypeConfigDTO;
 import org.apache.bigtop.manager.server.model.vo.StackVO;
 import org.apache.bigtop.manager.server.service.StackService;
 import org.apache.bigtop.manager.server.utils.StackUtils;
@@ -47,8 +46,7 @@ public class StackServiceImpl implements StackService {
             StackDTO stackDTO = entry.getKey();
             List<ServiceDTO> serviceDTOList = entry.getValue();
             for (ServiceDTO serviceDTO : serviceDTOList) {
-                List<TypeConfigDTO> configs = 
StackUtils.SERVICE_CONFIG_MAP.get(serviceDTO.getServiceName());
-                serviceDTO.setConfigs(configs);
+                
serviceDTO.setConfigs(StackUtils.SERVICE_CONFIG_MAP.get(serviceDTO.getServiceName()));
             }
 
             StackVO stackVO = StackConverter.INSTANCE.fromDTO2VO(stackDTO);
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackUtils.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackUtils.java
index b69d5b1a..0843463c 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackUtils.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackUtils.java
@@ -25,9 +25,9 @@ import 
org.apache.bigtop.manager.server.exception.ServerException;
 import org.apache.bigtop.manager.server.model.converter.ServiceConverter;
 import org.apache.bigtop.manager.server.model.dto.ComponentDTO;
 import org.apache.bigtop.manager.server.model.dto.PropertyDTO;
+import org.apache.bigtop.manager.server.model.dto.ServiceConfigDTO;
 import org.apache.bigtop.manager.server.model.dto.ServiceDTO;
 import org.apache.bigtop.manager.server.model.dto.StackDTO;
-import org.apache.bigtop.manager.server.model.dto.TypeConfigDTO;
 import org.apache.bigtop.manager.server.stack.dag.ComponentCommandWrapper;
 import org.apache.bigtop.manager.server.stack.dag.DAG;
 import org.apache.bigtop.manager.server.stack.dag.DagGraphEdge;
@@ -67,7 +67,7 @@ public class StackUtils {
 
     private static final String DEPENDENCY_FILE_NAME = "order.json";
 
-    public static final Map<String, List<TypeConfigDTO>> SERVICE_CONFIG_MAP = 
new HashMap<>();
+    public static final Map<String, List<ServiceConfigDTO>> SERVICE_CONFIG_MAP 
= new HashMap<>();
 
     public static final Map<StackDTO, List<ServiceDTO>> STACK_SERVICE_MAP = 
new HashMap<>();
 
@@ -131,26 +131,27 @@ public class StackUtils {
     }
 
     private static void parseServiceConfigurations(File file, String 
serviceName) {
-        List<TypeConfigDTO> typeConfigs = new ArrayList<>();
+        List<ServiceConfigDTO> configs = new ArrayList<>();
         File configFolder = new File(file.getAbsolutePath(), 
CONFIGURATION_FOLDER);
         if (configFolder.exists()) {
             for (File configFile : 
Optional.ofNullable(configFolder.listFiles()).orElse(new File[0])) {
                 String configPath = configFile.getAbsolutePath();
                 String fileExtension = 
configPath.substring(configPath.lastIndexOf(".") + 1);
                 if (fileExtension.equals(CONFIGURATION_FILE_EXTENSION)) {
-                    String typeName = configPath.substring(
+                    String configName = configPath.substring(
                             configPath.lastIndexOf(File.separator) + 1, 
configPath.lastIndexOf("."));
 
                     List<PropertyDTO> properties = 
StackConfigUtils.loadConfig(configPath);
-                    TypeConfigDTO typeConfigDTO = new TypeConfigDTO();
-                    typeConfigDTO.setTypeName(typeName);
-                    typeConfigDTO.setProperties(properties);
-                    typeConfigs.add(typeConfigDTO);
+
+                    ServiceConfigDTO serviceConfigDTO = new ServiceConfigDTO();
+                    serviceConfigDTO.setName(configName);
+                    serviceConfigDTO.setProperties(properties);
+                    configs.add(serviceConfigDTO);
                 }
             }
         }
 
-        SERVICE_CONFIG_MAP.put(serviceName, typeConfigs);
+        SERVICE_CONFIG_MAP.put(serviceName, configs);
     }
 
     private static void parseDag(File file) {
diff --git a/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql 
b/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql
index ca8134a4..6c236757 100644
--- a/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql
+++ b/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql
@@ -85,43 +85,6 @@ CREATE TABLE `cluster`
     UNIQUE KEY `uk_name` (`name`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-CREATE TABLE `component`
-(
-    `id`              BIGINT NOT NULL AUTO_INCREMENT,
-    `category`        VARCHAR(255),
-    `command_script`  VARCHAR(255),
-    `component_name`  VARCHAR(255),
-    `create_by`       BIGINT,
-    `create_time`     DATETIME,
-    `custom_commands` TEXT,
-    `display_name`    VARCHAR(255),
-    `quick_link`      VARCHAR(255),
-    `cardinality`     VARCHAR(255),
-    `update_by`       BIGINT,
-    `update_time`     DATETIME,
-    `cluster_id`      BIGINT,
-    `service_id`      BIGINT,
-    PRIMARY KEY (id),
-    KEY               `idx_component_cluster_id` (cluster_id),
-    KEY               `idx_component_service_id` (service_id),
-    UNIQUE KEY `uk_component_name` (`component_name`, `cluster_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
-CREATE TABLE `host_component`
-(
-    `id`           BIGINT NOT NULL AUTO_INCREMENT,
-    `create_by`    BIGINT,
-    `create_time`  DATETIME,
-    `state`        VARCHAR(255),
-    `update_by`    BIGINT,
-    `update_time`  DATETIME,
-    `component_id` BIGINT,
-    `host_id`      BIGINT,
-    PRIMARY KEY (id),
-    KEY            `idx_hc_component_id` (component_id),
-    KEY            `idx_hc_host_id` (host_id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
 CREATE TABLE `host`
 (
     `id`                   BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
@@ -170,6 +133,94 @@ CREATE TABLE `repo`
     PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
+CREATE TABLE `service`
+(
+    `id`                BIGINT NOT NULL AUTO_INCREMENT,
+    `display_name`      VARCHAR(255),
+    `package_specifics` VARCHAR(1024),
+    `required_services` VARCHAR(255),
+    `service_desc`      VARCHAR(1024),
+    `service_name`      VARCHAR(255),
+    `service_user`      VARCHAR(255),
+    `service_version`   VARCHAR(255),
+    `cluster_id`        BIGINT,
+    `create_time`       DATETIME    DEFAULT CURRENT_TIMESTAMP,
+    `update_time`       DATETIME    DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP,
+    `create_by`         BIGINT,
+    `update_by`         BIGINT,
+    PRIMARY KEY (id),
+    KEY                 idx_service_cluster_id (cluster_id),
+    UNIQUE KEY `uk_service_name` (`service_name`, `cluster_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `service_config`
+(
+    `id`                BIGINT NOT NULL AUTO_INCREMENT,
+    `name`              VARCHAR(255),
+    `properties_json`   TEXT,
+    `cluster_id`        BIGINT,
+    `service_id`        BIGINT,
+    `create_time`       DATETIME    DEFAULT CURRENT_TIMESTAMP,
+    `update_time`       DATETIME    DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP,
+    `create_by`         BIGINT,
+    `update_by`         BIGINT,
+    PRIMARY KEY (id),
+    KEY           idx_sc_cluster_id (cluster_id),
+    KEY           idx_sc_service_id (service_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `service_config_snapshot`
+(
+    `id`                BIGINT NOT NULL AUTO_INCREMENT,
+    `name`              VARCHAR(255),
+    `desc`              VARCHAR(255),
+    `config_json`       TEXT,
+    `service_id`        BIGINT,
+    `create_time`       DATETIME    DEFAULT CURRENT_TIMESTAMP,
+    `update_time`       DATETIME    DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP,
+    `create_by`         BIGINT,
+    `update_by`         BIGINT,
+    PRIMARY KEY (id),
+    KEY           idx_scs_service_id (service_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `component`
+(
+    `id`              BIGINT NOT NULL AUTO_INCREMENT,
+    `category`        VARCHAR(255),
+    `command_script`  VARCHAR(255),
+    `component_name`  VARCHAR(255),
+    `custom_commands` TEXT,
+    `display_name`    VARCHAR(255),
+    `quick_link`      VARCHAR(255),
+    `cardinality`     VARCHAR(255),
+    `cluster_id`      BIGINT,
+    `service_id`      BIGINT,
+    `create_time`     DATETIME    DEFAULT CURRENT_TIMESTAMP,
+    `update_time`     DATETIME    DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP,
+    `create_by`       BIGINT,
+    `update_by`       BIGINT,
+    PRIMARY KEY (id),
+    KEY               `idx_component_cluster_id` (cluster_id),
+    KEY               `idx_component_service_id` (service_id),
+    UNIQUE KEY `uk_component_name` (`component_name`, `cluster_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `host_component`
+(
+    `id`           BIGINT NOT NULL AUTO_INCREMENT,
+    `state`        VARCHAR(255),
+    `component_id` BIGINT,
+    `host_id`      BIGINT,
+    `create_time`  DATETIME    DEFAULT CURRENT_TIMESTAMP,
+    `update_time`  DATETIME    DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP,
+    `create_by`    BIGINT,
+    `update_by`    BIGINT,
+    PRIMARY KEY (id),
+    KEY            `idx_hc_component_id` (component_id),
+    KEY            `idx_hc_host_id` (host_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
 CREATE TABLE `job`
 (
     `id`          BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
@@ -231,56 +282,6 @@ CREATE TABLE `task`
     KEY               idx_task_stage_id (stage_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-CREATE TABLE `type_config`
-(
-    `id`                BIGINT NOT NULL AUTO_INCREMENT,
-    `create_by`         BIGINT,
-    `create_time`       DATETIME,
-    `properties_json`   TEXT,
-    `type_name`         VARCHAR(255),
-    `update_by`         BIGINT,
-    `update_time`       DATETIME,
-    `service_config_id` BIGINT,
-    PRIMARY KEY (id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
-CREATE TABLE `service`
-(
-    `id`                BIGINT NOT NULL AUTO_INCREMENT,
-    `create_by`         BIGINT,
-    `create_time`       DATETIME,
-    `display_name`      VARCHAR(255),
-    `package_specifics` VARCHAR(1024),
-    `required_services` VARCHAR(255),
-    `service_desc`      VARCHAR(1024),
-    `service_name`      VARCHAR(255),
-    `service_user`      VARCHAR(255),
-    `service_version`   VARCHAR(255),
-    `update_by`         BIGINT,
-    `update_time`       DATETIME,
-    `cluster_id`        BIGINT,
-    PRIMARY KEY (id),
-    KEY                 idx_service_cluster_id (cluster_id),
-    UNIQUE KEY `uk_service_name` (`service_name`, `cluster_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
-CREATE TABLE `service_config`
-(
-    `id`          BIGINT NOT NULL AUTO_INCREMENT,
-    `config_desc` VARCHAR(255),
-    `create_by`   BIGINT,
-    `create_time` DATETIME,
-    `selected`    TINYINT(1) default 0,
-    `update_by`   BIGINT,
-    `update_time` DATETIME,
-    `version`     INTEGER,
-    `cluster_id`  BIGINT,
-    `service_id`  BIGINT,
-    PRIMARY KEY (id),
-    KEY           idx_sc_cluster_id (cluster_id),
-    KEY           idx_sc_service_id (service_id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
 CREATE TABLE `setting`
 (
     `id`          BIGINT NOT NULL AUTO_INCREMENT,
diff --git 
a/bigtop-manager-server/src/main/resources/ddl/PostgreSQL-DDL-CREATE.sql 
b/bigtop-manager-server/src/main/resources/ddl/PostgreSQL-DDL-CREATE.sql
index f05d4ef5..f7590fda 100644
--- a/bigtop-manager-server/src/main/resources/ddl/PostgreSQL-DDL-CREATE.sql
+++ b/bigtop-manager-server/src/main/resources/ddl/PostgreSQL-DDL-CREATE.sql
@@ -75,49 +75,6 @@ COMMENT ON COLUMN cluster.status IS '1-healthy, 2-unhealthy, 
3-unknown';
 
 DROP INDEX IF EXISTS idx_cluster_stack_id;
 
-CREATE TABLE component
-(
-    id              BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
-    category        VARCHAR(255),
-    command_script  VARCHAR(255),
-    component_name  VARCHAR(255),
-    create_by       BIGINT,
-    create_time     TIMESTAMP(0),
-    custom_commands TEXT,
-    display_name    VARCHAR(255),
-    quick_link      VARCHAR(255),
-    cardinality     VARCHAR(255),
-    update_by       BIGINT,
-    update_time     TIMESTAMP(0),
-    cluster_id      BIGINT,
-    service_id      BIGINT,
-    PRIMARY KEY (id),
-    CONSTRAINT uk_component_name UNIQUE (component_name, cluster_id)
-);
-
-DROP INDEX IF EXISTS idx_component_cluster_id;
-DROP INDEX IF EXISTS idx_component_service_id;
-CREATE INDEX idx_component_cluster_id ON component (cluster_id);
-CREATE INDEX idx_component_service_id ON component (service_id);
-
-CREATE TABLE host_component
-(
-    id           BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
-    create_by    BIGINT,
-    create_time  TIMESTAMP(0),
-    state        VARCHAR(255),
-    update_by    BIGINT,
-    update_time  TIMESTAMP(0),
-    component_id BIGINT,
-    host_id      BIGINT,
-    PRIMARY KEY (id)
-);
-
-DROP INDEX IF EXISTS idx_hc_component_id;
-DROP INDEX IF EXISTS idx_hc_host_id;
-CREATE INDEX idx_hc_component_id ON host_component (component_id);
-CREATE INDEX idx_hc_host_id ON host_component (host_id);
-
 CREATE TABLE host
 (
     id                   BIGINT CHECK (id > 0)         NOT NULL GENERATED 
ALWAYS AS IDENTITY,
@@ -173,6 +130,103 @@ CREATE TABLE repo
 
 COMMENT ON COLUMN repo.type IS '1-services, 2-tools';
 
+CREATE TABLE service
+(
+    id                BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
+    display_name      VARCHAR(255),
+    package_specifics VARCHAR(1024),
+    required_services VARCHAR(255),
+    service_desc      VARCHAR(1024),
+    service_name      VARCHAR(255),
+    service_user      VARCHAR(255),
+    service_version   VARCHAR(255),
+    cluster_id        BIGINT,
+    create_time       TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    update_time       TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    create_by         BIGINT,
+    update_by         BIGINT,
+    PRIMARY KEY (id),
+    CONSTRAINT uk_service_name UNIQUE (service_name, cluster_id)
+);
+
+CREATE INDEX idx_service_cluster_id ON service (cluster_id);
+
+CREATE TABLE service_config
+(
+    id                BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
+    name              VARCHAR(255),
+    properties_json   TEXT,
+    cluster_id        BIGINT,
+    service_id        BIGINT,
+    create_time       TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    update_time       TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    create_by         BIGINT,
+    update_by         BIGINT,
+    PRIMARY KEY (id)
+);
+
+CREATE INDEX idx_sc_cluster_id ON service_config (cluster_id);
+CREATE INDEX idx_sc_service_id ON service_config (service_id);
+
+CREATE TABLE service_config_snapshot
+(
+    id                BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
+    name              VARCHAR(255),
+    "desc"            VARCHAR(255),
+    config_json       TEXT,
+    service_id        BIGINT,
+    create_time       TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    update_time       TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    create_by         BIGINT,
+    update_by         BIGINT,
+    PRIMARY KEY (id)
+);
+
+CREATE INDEX idx_scs_service_id ON service_config_snapshot (service_id);
+
+CREATE TABLE component
+(
+    id              BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
+    category        VARCHAR(255),
+    command_script  VARCHAR(255),
+    component_name  VARCHAR(255),
+    custom_commands TEXT,
+    display_name    VARCHAR(255),
+    quick_link      VARCHAR(255),
+    cardinality     VARCHAR(255),
+    cluster_id      BIGINT,
+    service_id      BIGINT,
+    create_time     TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    update_time     TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    create_by       BIGINT,
+    update_by       BIGINT,
+    PRIMARY KEY (id),
+    CONSTRAINT uk_component_name UNIQUE (component_name, cluster_id)
+);
+
+DROP INDEX IF EXISTS idx_component_cluster_id;
+DROP INDEX IF EXISTS idx_component_service_id;
+CREATE INDEX idx_component_cluster_id ON component (cluster_id);
+CREATE INDEX idx_component_service_id ON component (service_id);
+
+CREATE TABLE host_component
+(
+    id           BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
+    state        VARCHAR(255),
+    component_id BIGINT,
+    host_id      BIGINT,
+    create_time  TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    update_time  TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
+    create_by    BIGINT,
+    update_by    BIGINT,
+    PRIMARY KEY (id)
+);
+
+DROP INDEX IF EXISTS idx_hc_component_id;
+DROP INDEX IF EXISTS idx_hc_host_id;
+CREATE INDEX idx_hc_component_id ON host_component (component_id);
+CREATE INDEX idx_hc_host_id ON host_component (host_id);
+
 CREATE TABLE job
 (
     id          BIGINT CHECK (id > 0) NOT NULL GENERATED ALWAYS AS IDENTITY,
@@ -240,58 +294,6 @@ CREATE INDEX idx_task_cluster_id ON task (cluster_id);
 CREATE INDEX idx_task_job_id ON task (job_id);
 CREATE INDEX idx_task_stage_id ON task (stage_id);
 
-CREATE TABLE type_config
-(
-    id                BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
-    create_by         BIGINT,
-    create_time       TIMESTAMP(0),
-    properties_json   TEXT,
-    type_name         VARCHAR(255),
-    update_by         BIGINT,
-    update_time       TIMESTAMP(0),
-    service_config_id BIGINT,
-    PRIMARY KEY (id)
-);
-
-CREATE TABLE service
-(
-    id                BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
-    create_by         BIGINT,
-    create_time       TIMESTAMP(0),
-    display_name      VARCHAR(255),
-    package_specifics VARCHAR(1024),
-    required_services VARCHAR(255),
-    service_desc      VARCHAR(1024),
-    service_name      VARCHAR(255),
-    service_user      VARCHAR(255),
-    service_version   VARCHAR(255),
-    update_by         BIGINT,
-    update_time       TIMESTAMP(0),
-    cluster_id        BIGINT,
-    PRIMARY KEY (id),
-    CONSTRAINT uk_service_name UNIQUE (service_name, cluster_id)
-);
-
-CREATE INDEX idx_service_cluster_id ON service (cluster_id);
-
-CREATE TABLE service_config
-(
-    id          BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
-    config_desc VARCHAR(255),
-    create_by   BIGINT,
-    create_time TIMESTAMP(0),
-    selected    BOOLEAN default FALSE,
-    update_by   BIGINT,
-    update_time TIMESTAMP(0),
-    version     INTEGER,
-    cluster_id  BIGINT,
-    service_id  BIGINT,
-    PRIMARY KEY (id)
-);
-
-CREATE INDEX idx_sc_cluster_id ON service_config (cluster_id);
-CREATE INDEX idx_sc_service_id ON service_config (service_id);
-
 CREATE TABLE setting
 (
     id          BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
diff --git 
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/controller/ConfigControllerTest.java
 
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/controller/ConfigControllerTest.java
deleted file mode 100644
index 401ba0b3..00000000
--- 
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/controller/ConfigControllerTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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
- *
- *    https://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.bigtop.manager.server.controller;
-
-import org.apache.bigtop.manager.server.model.vo.ServiceConfigVO;
-import org.apache.bigtop.manager.server.service.ConfigService;
-import org.apache.bigtop.manager.server.utils.MessageSourceUtils;
-import org.apache.bigtop.manager.server.utils.ResponseEntity;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockedStatic;
-import org.mockito.Mockito;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-@ExtendWith(MockitoExtension.class)
-class ConfigControllerTest {
-
-    @Mock
-    private ConfigService configService;
-
-    @InjectMocks
-    private ConfigController configController;
-
-    private MockedStatic<MessageSourceUtils> mockedMessageSourceUtils;
-
-    @BeforeEach
-    void setUp() {
-        mockedMessageSourceUtils = 
Mockito.mockStatic(MessageSourceUtils.class);
-        when(MessageSourceUtils.getMessage(any())).thenReturn("Mocked 
message");
-    }
-
-    @AfterEach
-    void tearDown() {
-        mockedMessageSourceUtils.close();
-    }
-
-    @Test
-    void listReturnsAllConfigurations() {
-        Long clusterId = 1L;
-        List<ServiceConfigVO> configs = Arrays.asList(new ServiceConfigVO(), 
new ServiceConfigVO());
-        when(configService.list(clusterId)).thenReturn(configs);
-
-        ResponseEntity<List<ServiceConfigVO>> response = 
configController.list(clusterId);
-
-        assertTrue(response.isSuccess());
-        assertEquals(configs, response.getData());
-    }
-
-    @Test
-    void latestReturnsLatestConfigurations() {
-        Long clusterId = 1L;
-        List<ServiceConfigVO> latestConfigs = Arrays.asList(new 
ServiceConfigVO(), new ServiceConfigVO());
-        when(configService.latest(clusterId)).thenReturn(latestConfigs);
-
-        ResponseEntity<List<ServiceConfigVO>> response = 
configController.latest(clusterId);
-
-        assertTrue(response.isSuccess());
-        assertEquals(latestConfigs, response.getData());
-    }
-
-    @Test
-    void listReturnsEmptyForInvalidClusterId() {
-        Long clusterId = 999L;
-        when(configService.list(clusterId)).thenReturn(List.of());
-
-        ResponseEntity<List<ServiceConfigVO>> response = 
configController.list(clusterId);
-
-        assertTrue(response.isSuccess());
-        assertTrue(response.getData().isEmpty());
-    }
-
-    @Test
-    void latestReturnsEmptyForInvalidClusterId() {
-        Long clusterId = 999L;
-        when(configService.latest(clusterId)).thenReturn(List.of());
-
-        ResponseEntity<List<ServiceConfigVO>> response = 
configController.latest(clusterId);
-
-        assertTrue(response.isSuccess());
-        assertTrue(response.getData().isEmpty());
-    }
-}
diff --git 
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/controller/ServiceControllerTest.java
 
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/controller/ServiceControllerTest.java
index 7dabe079..87ab340d 100644
--- 
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/controller/ServiceControllerTest.java
+++ 
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/controller/ServiceControllerTest.java
@@ -78,10 +78,11 @@ class ServiceControllerTest {
     @Test
     void getReturnsServiceById() {
         Long id = 1L;
+        Long clusterId = 1L;
         ServiceVO service = new ServiceVO();
         when(serviceService.get(id)).thenReturn(service);
 
-        ResponseEntity<ServiceVO> response = serviceController.get(id);
+        ResponseEntity<ServiceVO> response = serviceController.get(clusterId, 
id);
 
         assertTrue(response.isSuccess());
         assertEquals(service, response.getData());
@@ -90,9 +91,10 @@ class ServiceControllerTest {
     @Test
     void getReturnsNotFoundForInvalidId() {
         Long id = 999L;
+        Long clusterId = 1L;
         when(serviceService.get(id)).thenReturn(null);
 
-        ResponseEntity<ServiceVO> response = serviceController.get(id);
+        ResponseEntity<ServiceVO> response = serviceController.get(clusterId, 
id);
 
         assertTrue(response.isSuccess());
         assertNull(response.getData());
diff --git 
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/service/ConfigServiceTest.java
 
b/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/service/ConfigServiceTest.java
deleted file mode 100644
index 80bbe653..00000000
--- 
a/bigtop-manager-server/src/test/java/org/apache/bigtop/manager/server/service/ConfigServiceTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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
- *
- *    https://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.bigtop.manager.server.service;
-
-import org.apache.bigtop.manager.dao.po.ClusterPO;
-import org.apache.bigtop.manager.dao.po.ServiceConfigPO;
-import org.apache.bigtop.manager.dao.po.ServicePO;
-import org.apache.bigtop.manager.dao.po.TypeConfigPO;
-import org.apache.bigtop.manager.dao.repository.ClusterDao;
-import org.apache.bigtop.manager.dao.repository.ServiceConfigDao;
-import org.apache.bigtop.manager.dao.repository.ServiceDao;
-import org.apache.bigtop.manager.dao.repository.TypeConfigDao;
-import org.apache.bigtop.manager.server.model.dto.PropertyDTO;
-import org.apache.bigtop.manager.server.model.dto.TypeConfigDTO;
-import org.apache.bigtop.manager.server.service.impl.ConfigServiceImpl;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import java.util.List;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-@ExtendWith(MockitoExtension.class)
-public class ConfigServiceTest {
-
-    @Mock
-    private ClusterDao clusterDao;
-
-    @Mock
-    private ServiceDao serviceDao;
-
-    @Mock
-    private ServiceConfigDao serviceConfigDao;
-
-    @Mock
-    private TypeConfigDao typeConfigDao;
-
-    @InjectMocks
-    private ConfigService configService = new ConfigServiceImpl();
-
-    @Test
-    public void testListAndLatest() {
-        configService.list(1L);
-        configService.latest(1L);
-    }
-
-    @Test
-    public void testUpsert() {
-        when(clusterDao.findById(1L)).thenReturn(new ClusterPO());
-        when(serviceDao.findById(1L)).thenReturn(new ServicePO());
-        TypeConfigDTO typeConfigDTO = new TypeConfigDTO();
-        typeConfigDTO.setTypeName("test");
-        PropertyDTO propertyDTO = new PropertyDTO();
-        propertyDTO.setName("test");
-        typeConfigDTO.setProperties(List.of(propertyDTO));
-        configService.upsert(1L, 1L, List.of(typeConfigDTO));
-
-        ServiceConfigPO serviceConfigPO = new ServiceConfigPO();
-        TypeConfigPO typeConfigPO = new TypeConfigPO();
-        typeConfigPO.setTypeName("test");
-        typeConfigPO.setPropertiesJson("[]");
-        serviceConfigPO.setConfigs(List.of(typeConfigPO));
-        serviceConfigPO.setVersion(1);
-        
when(serviceConfigDao.findByClusterIdAndServiceIdAndSelectedIsTrue(any(), 
any()))
-                .thenReturn(serviceConfigPO);
-        configService.upsert(1L, 1L, List.of(typeConfigDTO));
-    }
-}

Reply via email to