浏览代码

Merge pull request #461 from lepdou/namespace_delete

 improve delete namespace
Jason Song 8 年之前
父节点
当前提交
0b6022c7db

+ 5 - 0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/InstanceConfigRepository.java

@@ -4,6 +4,7 @@ import com.ctrip.framework.apollo.biz.entity.InstanceConfig;
 
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.PagingAndSortingRepository;
 import org.springframework.data.repository.query.Param;
@@ -26,6 +27,10 @@ public interface InstanceConfigRepository extends PagingAndSortingRepository<Ins
   List<InstanceConfig> findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfterAndReleaseKeyNotIn(
       String appId, String clusterName, String namespaceName, Date validDate, Set<String> releaseKey);
 
+  @Modifying
+  @Query("delete from InstanceConfig  where ConfigAppId=?1 and ConfigClusterName=?2 and ConfigNamespaceName = ?3")
+  int batchDelete(String appId, String clusterName, String namespaceName);
+
   @Query(
       value = "select b.Id from `InstanceConfig` a inner join `Instance` b on b.Id =" +
           " a.`InstanceId` where a.`ConfigAppId` = :configAppId and a.`ConfigClusterName` = " +

+ 7 - 0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ReleaseHistoryRepository.java

@@ -4,6 +4,8 @@ import com.ctrip.framework.apollo.biz.entity.ReleaseHistory;
 
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.PagingAndSortingRepository;
 
 import java.util.List;
@@ -16,4 +18,9 @@ public interface ReleaseHistoryRepository extends PagingAndSortingRepository<Rel
       clusterName, String namespaceName, Pageable pageable);
 
   List<ReleaseHistory> findByReleaseId(long releaseId);
+
+  @Modifying
+  @Query("update ReleaseHistory set isdeleted=1,DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3")
+  int batchDelete(String appId, String clusterName, String namespaceName, String operator);
+
 }

+ 1 - 3
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppNamespaceService.java

@@ -34,9 +34,7 @@ public class AppNamespaceService {
   private ClusterService clusterService;
   @Autowired
   private AuditService auditService;
-  @Autowired
-  private ServerConfigService serverConfigService;
-  
+
   public boolean isAppNamespaceNameUnique(String appId, String namespaceName) {
     Objects.requireNonNull(appId, "AppId must not be null");
     Objects.requireNonNull(namespaceName, "Namespace must not be null");

+ 5 - 0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/InstanceService.java

@@ -172,4 +172,9 @@ public class InstanceService {
 
     return instanceConfigRepository.save(existedInstanceConfig);
   }
+
+  @Transactional
+  public int batchDeleteInstanceConfig(String configAppId, String configClusterName, String configNamespaceName){
+    return instanceConfigRepository.batchDelete(configAppId, configClusterName, configNamespaceName);
+  }
 }

+ 43 - 19
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java

@@ -1,8 +1,6 @@
 package com.ctrip.framework.apollo.biz.service;
 
 import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -17,6 +15,7 @@ import com.ctrip.framework.apollo.biz.entity.Audit;
 import com.ctrip.framework.apollo.biz.entity.Cluster;
 import com.ctrip.framework.apollo.biz.entity.Namespace;
 import com.ctrip.framework.apollo.biz.repository.NamespaceRepository;
+import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;
 import com.ctrip.framework.apollo.common.entity.AppNamespace;
 import com.ctrip.framework.apollo.common.utils.BeanUtils;
 import com.ctrip.framework.apollo.common.exception.ServiceException;
@@ -38,6 +37,15 @@ public class NamespaceService {
   private ReleaseService releaseService;
   @Autowired
   private ClusterService clusterService;
+  @Autowired
+  private NamespaceBranchService namespaceBranchService;
+  @Autowired
+  private ReleaseHistoryService releaseHistoryService;
+  @Autowired
+  private NamespaceLockService namespaceLockService;
+  @Autowired
+  private InstanceService instanceService;
+
 
 
   public Namespace findOne(Long namespaceId) {
@@ -57,25 +65,25 @@ public class NamespaceService {
     return namespaces;
   }
 
-  public List<Namespace> findByAppIdAndNamespaceName(String appId, String namespaceName){
+  public List<Namespace> findByAppIdAndNamespaceName(String appId, String namespaceName) {
     return namespaceRepository.findByAppIdAndNamespaceName(appId, namespaceName);
   }
 
-  public Namespace findChildNamespace(String appId, String parentClusterName, String namespaceName){
+  public Namespace findChildNamespace(String appId, String parentClusterName, String namespaceName) {
     List<Namespace> namespaces = findByAppIdAndNamespaceName(appId, namespaceName);
-    if (CollectionUtils.isEmpty(namespaces) || namespaces.size() == 1){
+    if (CollectionUtils.isEmpty(namespaces) || namespaces.size() == 1) {
       return null;
     }
 
     List<Cluster> childClusters = clusterService.findChildClusters(appId, parentClusterName);
-    if (CollectionUtils.isEmpty(childClusters)){
+    if (CollectionUtils.isEmpty(childClusters)) {
       return null;
     }
 
     Set<String> childClusterNames = childClusters.stream().map(Cluster::getName).collect(Collectors.toSet());
     //the child namespace is the intersection of the child clusters and child namespaces
-    for (Namespace namespace: namespaces){
-      if (childClusterNames.contains(namespace.getClusterName())){
+    for (Namespace namespace : namespaces) {
+      if (childClusterNames.contains(namespace.getClusterName())) {
         return namespace;
       }
     }
@@ -83,7 +91,7 @@ public class NamespaceService {
     return null;
   }
 
-  public Namespace findChildNamespace(Namespace parentNamespace){
+  public Namespace findChildNamespace(Namespace parentNamespace) {
     String appId = parentNamespace.getAppId();
     String parentClusterName = parentNamespace.getClusterName();
     String namespaceName = parentNamespace.getNamespaceName();
@@ -92,12 +100,12 @@ public class NamespaceService {
 
   }
 
-  public Namespace findParentNamespace(Namespace namespace){
+  public Namespace findParentNamespace(Namespace namespace) {
     String appId = namespace.getAppId();
     String namespaceName = namespace.getNamespaceName();
 
     Cluster cluster = clusterService.findOne(appId, namespace.getClusterName());
-    if (cluster != null && cluster.getParentClusterId() > 0){
+    if (cluster != null && cluster.getParentClusterId() > 0) {
       Cluster parentCluster = clusterService.findOne(cluster.getParentClusterId());
       return findOne(appId, parentCluster.getName(), namespaceName);
     }
@@ -105,7 +113,7 @@ public class NamespaceService {
     return null;
   }
 
-  public boolean isChildNamespace(Namespace namespace){
+  public boolean isChildNamespace(Namespace namespace) {
     return findParentNamespace(namespace) != null;
   }
 
@@ -118,11 +126,11 @@ public class NamespaceService {
   }
 
   @Transactional
-  public void deleteByAppIdAndClusterName(String appId, String clusterName, String operator){
+  public void deleteByAppIdAndClusterName(String appId, String clusterName, String operator) {
 
     List<Namespace> toDeleteNamespaces = findNamespaces(appId, clusterName);
 
-    for (Namespace namespace: toDeleteNamespaces){
+    for (Namespace namespace : toDeleteNamespaces) {
 
       deleteNamespace(namespace, operator);
 
@@ -130,17 +138,33 @@ public class NamespaceService {
   }
 
   @Transactional
-  public Namespace deleteNamespace(Namespace namespace, String operator){
+  public Namespace deleteNamespace(Namespace namespace, String operator) {
     String appId = namespace.getAppId();
     String clusterName = namespace.getClusterName();
+    String namespaceName = namespace.getNamespaceName();
 
     itemService.batchDelete(namespace.getId(), operator);
     commitService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator);
 
-    if (!isChildNamespace(namespace)){
+    if (!isChildNamespace(namespace)) {
       releaseService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator);
     }
 
+    //delete child namespace
+    Namespace childNamespace = findChildNamespace(namespace);
+    if (childNamespace != null) {
+      namespaceBranchService.deleteBranch(appId, clusterName, namespaceName,
+                                          childNamespace.getClusterName(), NamespaceBranchStatus.DELETED, operator);
+      //delete child namespace's releases. Notice: delete child namespace will not delete child namespace's releases
+      releaseService.batchDelete(appId, childNamespace.getClusterName(), namespaceName, operator);
+    }
+
+    releaseHistoryService.batchDelete(appId, clusterName, namespaceName, operator);
+
+    instanceService.batchDeleteInstanceConfig(appId, clusterName, namespaceName);
+
+    namespaceLockService.unlock(namespace.getId());
+
     namespace.setDeleted(true);
     namespace.setDataChangeLastModifiedBy(operator);
 
@@ -158,7 +182,7 @@ public class NamespaceService {
     Namespace namespace = namespaceRepository.save(entity);
 
     auditService.audit(Namespace.class.getSimpleName(), namespace.getId(), Audit.OP.INSERT,
-        namespace.getDataChangeCreatedBy());
+                       namespace.getDataChangeCreatedBy());
 
     return namespace;
   }
@@ -171,7 +195,7 @@ public class NamespaceService {
     managedNamespace = namespaceRepository.save(managedNamespace);
 
     auditService.audit(Namespace.class.getSimpleName(), managedNamespace.getId(), Audit.OP.UPDATE,
-        managedNamespace.getDataChangeLastModifiedBy());
+                       managedNamespace.getDataChangeLastModifiedBy());
 
     return managedNamespace;
   }
@@ -182,7 +206,7 @@ public class NamespaceService {
     //load all private app namespace
     List<AppNamespace> privateAppNamespaces = appNamespaceService.findPrivateAppNamespace(appId);
     //create all private namespace
-    for (AppNamespace appNamespace: privateAppNamespaces){
+    for (AppNamespace appNamespace : privateAppNamespaces) {
       Namespace ns = new Namespace();
       ns.setAppId(appId);
       ns.setClusterName(clusterName);

+ 4 - 3
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseHistoryService.java

@@ -24,9 +24,6 @@ public class ReleaseHistoryService {
   @Autowired
   private ReleaseHistoryRepository releaseHistoryRepository;
 
-  @Autowired
-  private ReleaseService releaseService;
-
   @Autowired
   private AuditService auditService;
 
@@ -72,4 +69,8 @@ public class ReleaseHistoryService {
     return releaseHistory;
   }
 
+  @Transactional
+  public int batchDelete(String appId, String clusterName, String namespaceName, String operator){
+    return releaseHistoryRepository.batchDelete(appId, clusterName, namespaceName, operator);
+  }
 }

+ 94 - 0
apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/NamespaceServiceTest.java

@@ -0,0 +1,94 @@
+package com.ctrip.framework.apollo.biz.service;
+
+import com.ctrip.framework.apollo.biz.AbstractIntegrationTest;
+import com.ctrip.framework.apollo.biz.entity.Cluster;
+import com.ctrip.framework.apollo.biz.entity.Commit;
+import com.ctrip.framework.apollo.biz.entity.InstanceConfig;
+import com.ctrip.framework.apollo.biz.entity.Item;
+import com.ctrip.framework.apollo.biz.entity.Namespace;
+import com.ctrip.framework.apollo.biz.entity.Release;
+import com.ctrip.framework.apollo.biz.entity.ReleaseHistory;
+import com.ctrip.framework.apollo.biz.repository.InstanceConfigRepository;
+import com.ctrip.framework.apollo.common.entity.AppNamespace;
+
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.test.context.jdbc.Sql;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author lepdou 2016-11-28
+ */
+public class NamespaceServiceTest extends AbstractIntegrationTest {
+
+
+  @Autowired
+  private NamespaceService namespaceService;
+  @Autowired
+  private ItemService itemService;
+  @Autowired
+  private CommitService commitService;
+  @Autowired
+  private AppNamespaceService appNamespaceService;
+  @Autowired
+  private ClusterService clusterService;
+  @Autowired
+  private ReleaseService releaseService;
+  @Autowired
+  private ReleaseHistoryService releaseHistoryService;
+  @Autowired
+  private InstanceConfigRepository instanceConfigRepository;
+
+  private String testApp = "testApp";
+  private String testCluster = "default";
+  private String testChildCluster = "child-cluster";
+  private String testPrivateNamespace = "application";
+  private String testUser = "apollo";
+
+  @Test
+  @Sql(scripts = "/sql/namespace-test.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
+  @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
+  public void testDeleteNamespace() {
+
+    Namespace namespace = new Namespace();
+    namespace.setAppId(testApp);
+    namespace.setClusterName(testCluster);
+    namespace.setNamespaceName(testPrivateNamespace);
+    namespace.setId(1);
+
+    namespaceService.deleteNamespace(namespace, testUser);
+
+    List<Item> items = itemService.findItems(testApp, testCluster, testPrivateNamespace);
+    List<Commit> commits = commitService.find(testApp, testCluster, testPrivateNamespace, new PageRequest(0, 10));
+    AppNamespace appNamespace = appNamespaceService.findOne(testApp, testPrivateNamespace);
+    List<Cluster> childClusters = clusterService.findChildClusters(testApp, testCluster);
+    InstanceConfig instanceConfig = instanceConfigRepository.findOne(1L);
+    List<Release> parentNamespaceReleases = releaseService.findActiveReleases(testApp, testCluster,
+                                                                              testPrivateNamespace,
+                                                                              new PageRequest(0, 10));
+    List<Release> childNamespaceReleases = releaseService.findActiveReleases(testApp, testChildCluster,
+                                                                             testPrivateNamespace,
+                                                                             new PageRequest(0, 10));
+    Page<ReleaseHistory> releaseHistories =
+        releaseHistoryService
+            .findReleaseHistoriesByNamespace(testApp, testCluster, testPrivateNamespace, new PageRequest(0, 10));
+
+    assertEquals(0, items.size());
+    assertEquals(0, commits.size());
+    assertNotNull(appNamespace);
+    assertEquals(0, childClusters.size());
+    assertEquals(0, parentNamespaceReleases.size());
+    assertEquals(0, childNamespaceReleases.size());
+    assertTrue(!releaseHistories.hasContent());
+    assertNull(instanceConfig);
+  }
+
+}

+ 3 - 0
apollo-biz/src/test/resources/sql/clean.sql

@@ -1,4 +1,5 @@
 DELETE FROM App;
+DELETE FROM AppNamespace;
 DELETE FROM Cluster;
 DELETE FROM namespace;
 DELETE FROM grayreleaserule;
@@ -6,3 +7,5 @@ DELETE FROM release;
 DELETE FROM item;
 DELETE FROM releasemessage;
 DELETE FROM releasehistory;
+DELETE FROM namespacelock;
+DELETE FROM `commit`;

+ 32 - 0
apollo-biz/src/test/resources/sql/namespace-test.sql

@@ -0,0 +1,32 @@
+INSERT INTO `app` ( `AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('testApp', 'test', 'default', 'default', 'default', 'default', 0, 'default', 'default');
+
+INSERT INTO `cluster` (`ID`, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (1, 'default', 'testApp', 0, 0, 'default', 'default');
+INSERT INTO `cluster` (`Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('child-cluster', 'testApp', 1, 0, 'default', 'default');
+
+INSERT INTO `appnamespace` (`Name`, `AppId`, `Format`, `IsPublic`) VALUES ( 'application', 'testApp', 'properties', 0);
+
+INSERT INTO `namespace` (`ID`, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1,'testApp', 'default', 'application', 0, 'apollo', 'apollo');
+INSERT INTO `namespace` (`AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('testApp', 'child-cluster', 'application', 0, 'apollo', 'apollo');
+
+INSERT INTO `commit` (`ChangeSets`, `AppId`, `ClusterName`, `NamespaceName`)VALUES('{}', 'testApp', 'default', 'application');
+
+INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `LineNum`)VALUES(1, 'k1', 'v1', '', 1);
+
+INSERT INTO `namespacelock` (`NamespaceId`)VALUES(1);
+
+INSERT INTO `release` (`AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES('branch-test', 'default', 'application', '{}', 0);
+INSERT INTO `release` (`AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES('branch-test', 'child-cluster', 'application', '{}', 0);
+
+INSERT INTO `releasehistory` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `ReleaseId`, `PreviousReleaseId`, `Operation`, `OperationContext`)VALUES('branch-test', 'default', 'application', 'default', 0, 0, 7, '{}');
+
+INSERT INTO `instanceconfig` (`ID`, `InstanceId`, `ConfigAppId`, `ConfigClusterName`, `ConfigNamespaceName`, `ReleaseKey`, `ReleaseDeliveryTime`, `DataChange_CreatedTime`, `DataChange_LastTime`)
+VALUES
+	(1, 90, 'testApp', 'default', 'application', '20160829134524-dee271ddf9fced58', '2016-08-29 13:45:24', '2016-08-30 17:03:32', '2016-10-19 11:13:47');
+
+
+
+
+
+
+
+

+ 1 - 1
apollo-configservice/src/main/resources/logback.xml

@@ -7,4 +7,4 @@
 	<root level="INFO">
 		<appender-ref ref="FILE" />
 	</root>
-</configuration>
+</configuration>

+ 1 - 0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RolePermissionRepository.java

@@ -16,4 +16,5 @@ public interface RolePermissionRepository extends PagingAndSortingRepository<Rol
    * find role permissions by role ids
    */
   List<RolePermission> findByRoleIdIn(Collection<Long> roleId);
+
 }

+ 1 - 0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/UserRoleRepository.java

@@ -25,4 +25,5 @@ public interface UserRoleRepository extends PagingAndSortingRepository<UserRole,
    * find user roles by userIds and roleId
    */
   List<UserRole> findByUserIdInAndRoleId(Collection<String> userId, long roleId);
+
 }

+ 17 - 5
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java

@@ -22,6 +22,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.lang.reflect.Type;
 import java.util.HashMap;
@@ -57,15 +58,26 @@ public class NamespaceService {
     NamespaceDTO createdNamespace = namespaceAPI.createNamespace(env, namespace);
 
     Cat.logEvent(CatEventType.CREATE_NAMESPACE,
-        String.format("%s+%s+%s+%s", namespace.getAppId(), env, namespace.getClusterName(),
-            namespace.getNamespaceName()));
+                 String.format("%s+%s+%s+%s", namespace.getAppId(), env, namespace.getClusterName(),
+                               namespace.getNamespaceName()));
     return createdNamespace;
   }
 
-  public void deleteNamespace(String appId, Env env,  String clusterName, String namespaceName){
-    namespaceAPI.deleteNamespace(env, appId, clusterName, namespaceName, userInfoHolder.getUser().getUserId());
+
+  @Transactional
+  public void deleteNamespace(String appId, Env env, String clusterName, String namespaceName) {
+
+    AppNamespace appNamespace = appNamespaceService.findByAppIdAndName(appId, namespaceName);
+    if (appNamespace != null && !appNamespace.isPublic()){
+      throw new BadRequestException("private namespace can not be deleted");
+    }
+
+    String operator = userInfoHolder.getUser().getUserId();
+
+    namespaceAPI.deleteNamespace(env, appId, clusterName, namespaceName, operator);
   }
 
+
   public NamespaceDTO loadNamespaceBaseInfo(String appId, Env env, String clusterName, String namespaceName) {
     NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);
     if (namespace == null) {
@@ -93,7 +105,7 @@ public class NamespaceService {
         namespaceVOs.add(namespaceVO);
       } catch (Exception e) {
         logger.error("parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}",
-            appId, env, clusterName, namespace.getNamespaceName(), e);
+                     appId, env, clusterName, namespace.getNamespaceName(), e);
         throw e;
       }
     }

+ 2 - 4
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RolePermissionService.java

@@ -36,21 +36,19 @@ import java.util.Set;
  */
 @Service
 public class RolePermissionService implements InitializingBean {
+
   @Autowired
   private RoleRepository roleRepository;
-
   @Autowired
   private RolePermissionRepository rolePermissionRepository;
-
   @Autowired
   private UserRoleRepository userRoleRepository;
-
   @Autowired
   private PermissionRepository permissionRepository;
-
   @Autowired
   private ServerConfigService serverConfigService;
 
+
   private List<String> superAdminUsers;
   private Splitter configSplitter;
 

+ 1 - 1
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/service/NamespaceServiceTest.java

@@ -41,6 +41,7 @@ public class NamespaceServiceTest {
   @InjectMocks
   private NamespaceService namespaceService;
 
+
   @Before
   public void setup() {
   }
@@ -98,5 +99,4 @@ public class NamespaceServiceTest {
 
   }
 
-
 }