Skip to content

Commit 0c4069f

Browse files
authored
Merge pull request apolloconfig#1277 from nobodyiam/delete-appnamespace-api
add delete app namespace api
2 parents d23e60e + d1db52a commit 0c4069f

File tree

22 files changed

+227
-60
lines changed

22 files changed

+227
-60
lines changed

apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppNamespaceController.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.springframework.web.bind.annotation.RequestBody;
1818
import org.springframework.web.bind.annotation.RequestMapping;
1919
import org.springframework.web.bind.annotation.RequestMethod;
20+
import org.springframework.web.bind.annotation.RequestParam;
2021
import org.springframework.web.bind.annotation.RestController;
2122

2223
import java.util.List;
@@ -46,7 +47,16 @@ public AppNamespaceDTO create(@RequestBody AppNamespaceDTO appNamespace) {
4647
entity = appNamespaceService.createAppNamespace(entity);
4748

4849
return BeanUtils.transfrom(AppNamespaceDTO.class, entity);
50+
}
4951

52+
@RequestMapping(value = "/apps/{appId}/appnamespaces/{namespaceName:.+}", method = RequestMethod.DELETE)
53+
public void delete(@PathVariable("appId") String appId, @PathVariable("namespaceName") String namespaceName,
54+
@RequestParam String operator) {
55+
AppNamespace entity = appNamespaceService.findOne(appId, namespaceName);
56+
if (entity == null) {
57+
throw new BadRequestException("app namespace not found for appId: " + appId + " namespace: " + namespaceName);
58+
}
59+
appNamespaceService.deleteAppNamespace(entity, operator);
5060
}
5161

5262
@RequestMapping(value = "/appnamespaces/{publicNamespaceName}/namespaces", method = RequestMethod.GET)

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,8 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNa
2929
@Modifying
3030
@Query("UPDATE AppNamespace SET IsDeleted=1,DataChange_LastModifiedBy = ?2 WHERE AppId=?1")
3131
int batchDeleteByAppId(String appId, String operator);
32+
33+
@Modifying
34+
@Query("UPDATE AppNamespace SET IsDeleted=1,DataChange_LastModifiedBy = ?3 WHERE AppId=?1 and Name = ?2")
35+
int delete(String appId, String namespaceName, String operator);
3236
}

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/GrayReleaseRuleRepository.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,4 @@ List<GrayReleaseRule> findByAppIdAndClusterNameAndNamespaceName(String appId,
1919

2020
List<GrayReleaseRule> findFirst500ByIdGreaterThanOrderByIdAsc(Long id);
2121

22-
@Modifying
23-
@Query("UPDATE GrayReleaseRule SET IsDeleted=1, DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3")
24-
int batchDelete(String appId, String clusterName, String namespaceName, String operator);
2522
}

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/NamespaceRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public interface NamespaceRepository extends PagingAndSortingRepository<Namespac
1919
@Query("update Namespace set isdeleted=1,DataChange_LastModifiedBy = ?3 where appId=?1 and clusterName=?2")
2020
int batchDelete(String appId, String clusterName, String operator);
2121

22-
List<Namespace> findByAppIdAndNamespaceName(String appId, String namespaceName);
22+
List<Namespace> findByAppIdAndNamespaceNameOrderByIdAsc(String appId, String namespaceName);
2323

2424
List<Namespace> findByNamespaceName(String namespaceName, Pageable page);
2525

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AdminService.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.ctrip.framework.apollo.biz.entity.Cluster;
44
import com.ctrip.framework.apollo.common.entity.App;
5-
import com.ctrip.framework.apollo.common.exception.NotFoundException;
65
import com.ctrip.framework.apollo.core.ConfigConsts;
76

87
import org.slf4j.Logger;

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
1515
import com.ctrip.framework.apollo.core.utils.StringUtils;
1616

17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
1719
import org.springframework.beans.factory.annotation.Autowired;
1820
import org.springframework.stereotype.Service;
1921
import org.springframework.transaction.annotation.Transactional;
@@ -26,6 +28,8 @@
2628
@Service
2729
public class AppNamespaceService {
2830

31+
private static final Logger logger = LoggerFactory.getLogger(AppNamespaceService.class);
32+
2933
@Autowired
3034
private AppNamespaceRepository appNamespaceRepository;
3135
@Autowired
@@ -142,4 +146,24 @@ private void instanceOfAppNamespaceInAllCluster(String appId, String namespaceNa
142146
public void batchDelete(String appId, String operator) {
143147
appNamespaceRepository.batchDeleteByAppId(appId, operator);
144148
}
149+
150+
@Transactional
151+
public void deleteAppNamespace(AppNamespace appNamespace, String operator) {
152+
String appId = appNamespace.getAppId();
153+
String namespaceName = appNamespace.getName();
154+
155+
logger.info("{} is deleting AppNamespace, appId: {}, namespace: {}", operator, appId, namespaceName);
156+
157+
// 1. delete namespaces
158+
List<Namespace> namespaces = namespaceService.findByAppIdAndNamespaceName(appId, namespaceName);
159+
160+
if (namespaces != null) {
161+
for (Namespace namespace : namespaces) {
162+
namespaceService.deleteNamespace(namespace, operator);
163+
}
164+
}
165+
166+
// 2. delete app namespace
167+
appNamespaceRepository.delete(appId, namespaceName, operator);
168+
}
145169
}

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ClusterService.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ public List<Cluster> findChildClusters(String appId, String parentClusterName) {
138138
}
139139

140140
public List<Cluster> findClusters(String appId) {
141-
return clusterRepository.findByAppId(appId);
141+
List<Cluster> clusters = clusterRepository.findByAppId(appId);
142+
143+
if (clusters == null) {
144+
return Collections.emptyList();
145+
}
146+
147+
// to make sure parent cluster is ahead of branch cluster
148+
Collections.sort(clusters);
149+
150+
return clusters;
142151
}
143152
}

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/GrayReleaseRuleService.java

Lines changed: 0 additions & 18 deletions
This file was deleted.

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

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ public class NamespaceService {
5959
@Autowired
6060
private ReleaseHistoryService releaseHistoryService;
6161
@Autowired
62-
private GrayReleaseRuleService grayReleaseRuleService;
63-
@Autowired
6462
private NamespaceLockService namespaceLockService;
6563
@Autowired
6664
private InstanceService instanceService;
@@ -177,7 +175,7 @@ public List<Namespace> findNamespaces(String appId, String clusterName) {
177175
}
178176

179177
public List<Namespace> findByAppIdAndNamespaceName(String appId, String namespaceName) {
180-
return namespaceRepository.findByAppIdAndNamespaceName(appId, namespaceName);
178+
return namespaceRepository.findByAppIdAndNamespaceNameOrderByIdAsc(appId, namespaceName);
181179
}
182180

183181
public Namespace findChildNamespace(String appId, String parentClusterName, String namespaceName) {
@@ -266,17 +264,14 @@ public Namespace deleteNamespace(Namespace namespace, String operator) {
266264
commitService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator);
267265

268266
releaseService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator);
269-
grayReleaseRuleService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator);
270-
271-
if (!isChildNamespace(namespace)) {
272-
//delete child namespace
273-
Namespace childNamespace = findChildNamespace(namespace);
274-
if (childNamespace != null) {
275-
namespaceBranchService.deleteBranch(appId, clusterName, namespaceName,
276-
childNamespace.getClusterName(), NamespaceBranchStatus.DELETED, operator);
277-
//delete child namespace's releases. Notice: delete child namespace will not delete child namespace's releases
278-
releaseService.batchDelete(appId, childNamespace.getClusterName(), namespaceName, operator);
279-
}
267+
268+
//delete child namespace
269+
Namespace childNamespace = findChildNamespace(namespace);
270+
if (childNamespace != null) {
271+
namespaceBranchService.deleteBranch(appId, clusterName, namespaceName,
272+
childNamespace.getClusterName(), NamespaceBranchStatus.DELETED, operator);
273+
//delete child namespace's releases. Notice: delete child namespace will not delete child namespace's releases
274+
releaseService.batchDelete(appId, childNamespace.getClusterName(), namespaceName, operator);
280275
}
281276

282277
releaseHistoryService.batchDelete(appId, clusterName, namespaceName, operator);
@@ -397,4 +392,6 @@ private boolean isNamespaceNotPublished(Namespace namespace) {
397392

398393
return false;
399394
}
395+
396+
400397
}

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ public int countPublicAppNamespaceAssociatedNamespaces(Env env, String publicNam
132132
return count == null ? 0 : count;
133133
}
134134

135+
public void deleteAppNamespace(Env env, String appId, String namespaceName, String operator) {
136+
restTemplate.delete(env, "/apps/{appId}/appnamespaces/{namespaceName}?operator={operator}", appId, namespaceName,
137+
operator);
138+
}
135139
}
136140

137141
@Service

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceController.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.ctrip.framework.apollo.portal.controller;
22

3+
import com.ctrip.framework.apollo.portal.listener.AppNamespaceDeletionEvent;
34
import com.google.common.collect.Sets;
45

56
import com.ctrip.framework.apollo.common.dto.NamespaceDTO;
@@ -132,6 +133,17 @@ public ResponseEntity<Void> deleteNamespace(@PathVariable String appId, @PathVar
132133
return ResponseEntity.ok().build();
133134
}
134135

136+
@PreAuthorize(value = "@permissionValidator.isSuperAdmin()")
137+
@RequestMapping(value = "/apps/{appId}/appnamespaces/{namespaceName:.+}", method = RequestMethod.DELETE)
138+
public ResponseEntity<Void> deleteAppNamespace(@PathVariable String appId, @PathVariable String namespaceName) {
139+
140+
AppNamespace appNamespace = appNamespaceService.deleteAppNamespace(appId, namespaceName);
141+
142+
publisher.publishEvent(new AppNamespaceDeletionEvent(appNamespace));
143+
144+
return ResponseEntity.ok().build();
145+
}
146+
135147
@PreAuthorize(value = "@permissionValidator.hasCreateAppNamespacePermission(#appId, #appNamespace)")
136148
@RequestMapping(value = "/apps/{appId}/appnamespaces", method = RequestMethod.POST)
137149
public AppNamespace createAppNamespace(@PathVariable String appId, @RequestBody AppNamespace appNamespace) {

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,4 @@ public void onAppInfoChange(AppInfoChangedEvent event) {
4040
}
4141
}
4242
}
43-
44-
@EventListener
45-
public void onAppDelete(AppDeletionEvent event) {
46-
AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp());
47-
String appId = appDTO.getAppId();
48-
String operator = appDTO.getDataChangeLastModifiedBy();
49-
50-
List<Env> envs = portalSettings.getActiveEnvs();
51-
for (Env env : envs) {
52-
try {
53-
appAPI.deleteApp(env, appId, operator);
54-
} catch (Throwable e) {
55-
logger.error("Delete app failed. Env = {}, AppId = {}", env, appId, e);
56-
Tracer.logError(String.format("Delete app failed. Env = %s, AppId = %s", env, appId), e);
57-
}
58-
}
59-
}
6043
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.ctrip.framework.apollo.portal.listener;
2+
3+
import com.ctrip.framework.apollo.common.entity.AppNamespace;
4+
import com.google.common.base.Preconditions;
5+
import org.springframework.context.ApplicationEvent;
6+
7+
public class AppNamespaceDeletionEvent extends ApplicationEvent {
8+
9+
public AppNamespaceDeletionEvent(Object source) {
10+
super(source);
11+
}
12+
13+
public AppNamespace getAppNamespace() {
14+
Preconditions.checkState(source != null);
15+
return (AppNamespace) this.source;
16+
}
17+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.ctrip.framework.apollo.portal.listener;
2+
3+
import com.ctrip.framework.apollo.common.dto.AppDTO;
4+
import com.ctrip.framework.apollo.common.dto.AppNamespaceDTO;
5+
import com.ctrip.framework.apollo.common.utils.BeanUtils;
6+
import com.ctrip.framework.apollo.core.enums.Env;
7+
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
8+
import com.ctrip.framework.apollo.portal.component.PortalSettings;
9+
import com.ctrip.framework.apollo.tracer.Tracer;
10+
import java.util.List;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
import org.springframework.beans.factory.annotation.Autowired;
14+
import org.springframework.context.event.EventListener;
15+
import org.springframework.stereotype.Component;
16+
17+
@Component
18+
public class DeletionListener {
19+
20+
private static final Logger logger = LoggerFactory.getLogger(DeletionListener.class);
21+
22+
@Autowired
23+
private PortalSettings portalSettings;
24+
@Autowired
25+
private AdminServiceAPI.AppAPI appAPI;
26+
@Autowired
27+
private AdminServiceAPI.NamespaceAPI namespaceAPI;
28+
29+
@EventListener
30+
public void onAppDeletionEvent(AppDeletionEvent event) {
31+
AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp());
32+
String appId = appDTO.getAppId();
33+
String operator = appDTO.getDataChangeLastModifiedBy();
34+
35+
List<Env> envs = portalSettings.getActiveEnvs();
36+
for (Env env : envs) {
37+
try {
38+
appAPI.deleteApp(env, appId, operator);
39+
} catch (Throwable e) {
40+
logger.error("Delete app failed. Env = {}, AppId = {}", env, appId, e);
41+
Tracer.logError(String.format("Delete app failed. Env = %s, AppId = %s", env, appId), e);
42+
}
43+
}
44+
}
45+
46+
@EventListener
47+
public void onAppNamespaceDeletionEvent(AppNamespaceDeletionEvent event) {
48+
AppNamespaceDTO appNamespace = BeanUtils.transfrom(AppNamespaceDTO.class, event.getAppNamespace());
49+
List<Env> envs = portalSettings.getActiveEnvs();
50+
String appId = appNamespace.getAppId();
51+
String namespaceName = appNamespace.getName();
52+
String operator = appNamespace.getDataChangeLastModifiedBy();
53+
54+
for (Env env : envs) {
55+
try {
56+
namespaceAPI.deleteAppNamespace(env, appId, namespaceName, operator);
57+
} catch (Throwable e) {
58+
logger.error("Delete appNamespace failed. appId = {}, namespace = {}, env = {}", appId, namespaceName, env, e);
59+
Tracer.logError(String
60+
.format("Delete appNamespace failed. appId = %s, namespace = %s, env = %s", appId, namespaceName, env), e);
61+
}
62+
}
63+
}
64+
}

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppNamespaceRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNa
1919
@Modifying
2020
@Query("UPDATE AppNamespace SET IsDeleted=1,DataChange_LastModifiedBy=?2 WHERE AppId=?1")
2121
int batchDeleteByAppId(String appId, String operator);
22+
23+
@Modifying
24+
@Query("UPDATE AppNamespace SET IsDeleted=1,DataChange_LastModifiedBy = ?3 WHERE AppId=?1 and Name = ?2")
25+
int delete(String appId, String namespaceName, String operator);
2226
}

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/PermissionRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ List<Permission> findByPermissionTypeInAndTargetId(Collection<String> permission
2828
@Query("SELECT p.id from Permission p where p.targetId = ?1 or p.targetId like CONCAT(?1, '+%'))")
2929
List<Long> findPermissionIdsByAppId(String appId);
3030

31+
@Query("SELECT p.id from Permission p where p.targetId = CONCAT(?1, '+', ?2)")
32+
List<Long> findPermissionIdsByAppIdAndNamespace(String appId, String namespaceName);
33+
3134
@Modifying
3235
@Query("UPDATE Permission SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE Id in ?1")
3336
Integer batchDelete(List<Long> permissionIds, String operator);

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RoleRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ public interface RoleRepository extends PagingAndSortingRepository<Role, Long> {
2222
+ "OR r.roleName like CONCAT('ReleaseNamespace+', ?1, '+%'))")
2323
List<Long> findRoleIdsByAppId(String appId);
2424

25+
@Query("SELECT r.id from Role r where (r.roleName = CONCAT('ModifyNamespace+', ?1, '+', ?2) "
26+
+ "OR r.roleName = CONCAT('ReleaseNamespace+', ?1, '+', ?2))")
27+
List<Long> findRoleIdsByAppIdAndNamespace(String appId, String namespaceName);
28+
2529
@Modifying
2630
@Query("UPDATE Role SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE Id in ?1")
2731
Integer batchDelete(List<Long> roleIds, String operator);

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppNamespaceService.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public class AppNamespaceService {
2727
private RoleInitializationService roleInitializationService;
2828
@Autowired
2929
private AppService appService;
30+
@Autowired
31+
private RolePermissionService rolePermissionService;
3032

3133
/**
3234
* 公共的app ns,能被其它项目关联到的app ns
@@ -118,6 +120,28 @@ public AppNamespace createAppNamespaceInLocal(AppNamespace appNamespace) {
118120
return createdAppNamespace;
119121
}
120122

123+
@Transactional
124+
public AppNamespace deleteAppNamespace(String appId, String namespaceName) {
125+
AppNamespace appNamespace = appNamespaceRepository.findByAppIdAndName(appId, namespaceName);
126+
if (appNamespace == null) {
127+
throw new BadRequestException(
128+
String.format("AppNamespace not exists. AppId = %s, NamespaceName = %s", appId, namespaceName));
129+
}
130+
131+
String operator = userInfoHolder.getUser().getUserId();
132+
133+
// this operator is passed to com.ctrip.framework.apollo.portal.listener.DeletionListener.onAppNamespaceDeletionEvent
134+
appNamespace.setDataChangeLastModifiedBy(operator);
135+
136+
// delete app namespace in portal db
137+
appNamespaceRepository.delete(appId, namespaceName, operator);
138+
139+
// delete Permission and Role related data
140+
rolePermissionService.deleteRolePermissionsByAppIdAndNamespace(appId, namespaceName, operator);
141+
142+
return appNamespace;
143+
}
144+
121145
public void batchDeleteByAppId(String appId, String operator) {
122146
appNamespaceRepository.batchDeleteByAppId(appId, operator);
123147
}

0 commit comments

Comments
 (0)