Commit cff5d8cd authored by nobodyiam's avatar nobodyiam

add admin page to delete app, cluster and app namespace

parent e9459a21
...@@ -52,9 +52,14 @@ public class ClusterController { ...@@ -52,9 +52,14 @@ public class ClusterController {
@RequestMapping(value = "apps/{appId}/envs/{env}/clusters/{clusterName:.+}", method = RequestMethod.DELETE) @RequestMapping(value = "apps/{appId}/envs/{env}/clusters/{clusterName:.+}", method = RequestMethod.DELETE)
public ResponseEntity<Void> deleteCluster(@PathVariable String appId, @PathVariable String env, public ResponseEntity<Void> deleteCluster(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName){ @PathVariable String clusterName){
clusterService.deleteCluster(Env.valueOf(env), appId, clusterName); clusterService.deleteCluster(Env.fromString(env), appId, clusterName);
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
@RequestMapping(value = "apps/{appId}/envs/{env}/clusters/{clusterName:.+}", method = RequestMethod.GET)
public ClusterDTO loadCluster(@PathVariable("appId") String appId, @PathVariable String env, @PathVariable("clusterName") String clusterName) {
return clusterService.loadCluster(appId, Env.fromString(env), clusterName);
}
} }
package com.ctrip.framework.apollo.portal.controller; package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.common.dto.AppNamespaceDTO;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.portal.listener.AppNamespaceDeletionEvent; import com.ctrip.framework.apollo.portal.listener.AppNamespaceDeletionEvent;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
...@@ -144,6 +146,18 @@ public class NamespaceController { ...@@ -144,6 +146,18 @@ public class NamespaceController {
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
@RequestMapping(value = "/apps/{appId}/appnamespaces/{namespaceName:.+}", method = RequestMethod.GET)
public AppNamespaceDTO findAppNamespace(@PathVariable String appId, @PathVariable String namespaceName) {
AppNamespace appNamespace = appNamespaceService.findByAppIdAndName(appId, namespaceName);
if (appNamespace == null) {
throw new BadRequestException(
String.format("AppNamespace not exists. AppId = %s, NamespaceName = %s", appId, namespaceName));
}
return BeanUtils.transfrom(AppNamespaceDTO.class, appNamespace);
}
@PreAuthorize(value = "@permissionValidator.hasCreateAppNamespacePermission(#appId, #appNamespace)") @PreAuthorize(value = "@permissionValidator.hasCreateAppNamespacePermission(#appId, #appNamespace)")
@RequestMapping(value = "/apps/{appId}/appnamespaces", method = RequestMethod.POST) @RequestMapping(value = "/apps/{appId}/appnamespaces", method = RequestMethod.POST)
public AppNamespace createAppNamespace(@PathVariable String appId, @RequestBody AppNamespace appNamespace) { public AppNamespace createAppNamespace(@PathVariable String appId, @RequestBody AppNamespace appNamespace) {
......
...@@ -34,6 +34,5 @@ var open_manage_module = angular.module('open_manage', ['app.service', 'apollo.d ...@@ -34,6 +34,5 @@ var open_manage_module = angular.module('open_manage', ['app.service', 'apollo.d
var user_module = angular.module('user', ['apollo.directive', 'toastr', 'app.service', 'app.util', 'angular-loading-bar', 'valdr']); var user_module = angular.module('user', ['apollo.directive', 'toastr', 'app.service', 'app.util', 'angular-loading-bar', 'valdr']);
//login //login
var login_module = angular.module('login', ['toastr', 'app.util']); var login_module = angular.module('login', ['toastr', 'app.util']);
//delete app cluster namespace
var delete_app_cluster_namespace_module = angular.module('delete_app_cluster_namespace', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
delete_app_cluster_namespace_module.controller('DeleteAppClusterNamespaceController',
['$scope', 'toastr', 'AppUtil', 'AppService', 'ClusterService', 'NamespaceService', 'PermissionService',
DeleteAppClusterNamespaceController]);
function DeleteAppClusterNamespaceController($scope, toastr, AppUtil, AppService, ClusterService, NamespaceService, PermissionService) {
$scope.app = {};
$scope.deleteAppBtnDisabled = true;
$scope.getAppInfo = getAppInfo;
$scope.deleteApp = deleteApp;
$scope.cluster = {};
$scope.deleteClusterBtnDisabled = true;
$scope.getClusterInfo = getClusterInfo;
$scope.deleteCluster = deleteCluster;
$scope.appNamespace = {};
$scope.deleteAppNamespaceBtnDisabled = true;
$scope.getAppNamespaceInfo = getAppNamespaceInfo;
$scope.deleteAppNamespace = deleteAppNamespace;
initPermission();
function initPermission() {
PermissionService.has_root_permission()
.then(function (result) {
$scope.isRootUser = result.hasPermission;
})
}
function getAppInfo() {
if (!$scope.app.appId) {
toastr.warning("请输入appId");
return;
}
$scope.app.info = "";
AppService.load($scope.app.appId).then(function (result) {
if (!result.appId) {
toastr.warning("AppId: " + $scope.app.appId + " 不存在!");
$scope.deleteAppBtnDisabled = true;
return;
}
$scope.app.info = "应用名:" + result.name + " 部门:" + result.orgName + '(' + result.orgId + ')' + " 负责人:" + result.ownerName;
$scope.deleteAppBtnDisabled = false;
}, function (result) {
AppUtil.showErrorMsg(result);
});
}
function deleteApp() {
if (!$scope.app.appId) {
toastr.warning("请输入appId");
return;
}
if (confirm("确认删除AppId: " + $scope.app.appId + "")) {
AppService.delete_app($scope.app.appId).then(function (result) {
toastr.success("删除成功");
$scope.deleteAppBtnDisabled = true;
}, function (result) {
AppUtil.showErrorMsg(result);
})
}
}
function getClusterInfo() {
if (!$scope.cluster.appId || !$scope.cluster.env || !$scope.cluster.name) {
toastr.warning("请输入appId、环境和集群名称");
return;
}
$scope.cluster.info = "";
ClusterService.load_cluster($scope.cluster.appId, $scope.cluster.env, $scope.cluster.name).then(function (result) {
$scope.cluster.info = "AppId:" + result.appId+ " 环境:" + $scope.cluster.env + " 集群名称:" + result.name;
$scope.deleteClusterBtnDisabled = false;
}, function (result) {
AppUtil.showErrorMsg(result);
});
}
function deleteCluster() {
if (!$scope.cluster.appId || !$scope.cluster.env || !$scope.cluster.name) {
toastr.warning("请输入appId、环境和集群名称");
return;
}
if (confirm("确认删除集群?appId: " + $scope.cluster.appId + " 环境:" + $scope.cluster.env + " 集群名称:" + $scope.cluster.name)) {
ClusterService.delete_cluster($scope.cluster.appId, $scope.cluster.env, $scope.cluster.name).then(function (result) {
toastr.success("删除成功");
$scope.deleteClusterBtnDisabled = true;
}, function (result) {
AppUtil.showErrorMsg(result);
})
}
}
function getAppNamespaceInfo() {
if (!$scope.appNamespace.appId || !$scope.appNamespace.name) {
toastr.warning("请输入appId和AppNamespace名称");
return;
}
$scope.appNamespace.info = "";
NamespaceService.loadAppNamespace($scope.appNamespace.appId, $scope.appNamespace.name).then(function (result) {
$scope.appNamespace.info = "AppId:" + result.appId+ " AppNamespace名称:" + result.name + " isPublic:" + result.isPublic;
$scope.deleteAppNamespaceBtnDisabled = false;
}, function (result) {
AppUtil.showErrorMsg(result);
});
}
function deleteAppNamespace() {
if (!$scope.appNamespace.appId || !$scope.appNamespace.name) {
toastr.warning("请输入appId和AppNamespace名称");
return;
}
if (confirm("确认删除所有环境的AppNamespace和Namespace?appId: " + $scope.appNamespace.appId + " 环境:所有环境" + " AppNamespace名称:" + $scope.appNamespace.name)) {
NamespaceService.deleteAppNamespace($scope.appNamespace.appId, $scope.appNamespace.name).then(function (result) {
toastr.success("删除成功");
$scope.deleteAppNamespaceBtnDisabled = true;
}, function (result) {
AppUtil.showErrorMsg(result);
})
}
}
}
...@@ -34,6 +34,10 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { ...@@ -34,6 +34,10 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
find_miss_envs: { find_miss_envs: {
method: 'GET', method: 'GET',
url: '/apps/:appId/miss_envs' url: '/apps/:appId/miss_envs'
},
delete_app: {
method: 'DELETE',
isArray: false
} }
}); });
return { return {
...@@ -123,6 +127,17 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { ...@@ -123,6 +127,17 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
d.reject(result); d.reject(result);
}); });
return d.promise; return d.promise;
},
delete_app: function (appId) {
var d = $q.defer();
app_resource.delete_app({
appId: appId
}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
} }
} }
}]); }]);
...@@ -3,6 +3,14 @@ appService.service('ClusterService', ['$resource', '$q', function ($resource, $q ...@@ -3,6 +3,14 @@ appService.service('ClusterService', ['$resource', '$q', function ($resource, $q
create_cluster: { create_cluster: {
method: 'POST', method: 'POST',
url: 'apps/:appId/envs/:env/clusters' url: 'apps/:appId/envs/:env/clusters'
},
load_cluster: {
method: 'GET',
url: 'apps/:appId/envs/:env/clusters/:clusterName'
},
delete_cluster: {
method: 'DELETE',
url: 'apps/:appId/envs/:env/clusters/:clusterName'
} }
}); });
return { return {
...@@ -18,6 +26,34 @@ appService.service('ClusterService', ['$resource', '$q', function ($resource, $q ...@@ -18,6 +26,34 @@ appService.service('ClusterService', ['$resource', '$q', function ($resource, $q
d.reject(result); d.reject(result);
}); });
return d.promise; return d.promise;
},
load_cluster: function (appId, env, clusterName) {
var d = $q.defer();
cluster_resource.load_cluster({
appId: appId,
env: env,
clusterName: clusterName
},
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
delete_cluster: function (appId, env, clusterName) {
var d = $q.defer();
cluster_resource.delete_cluster({
appId: appId,
env: env,
clusterName: clusterName
},
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
} }
} }
}]); }]);
...@@ -27,6 +27,14 @@ appService.service("NamespaceService", ['$resource', '$q', function ($resource, ...@@ -27,6 +27,14 @@ appService.service("NamespaceService", ['$resource', '$q', function ($resource,
method: 'GET', method: 'GET',
url: '/envs/:env/appnamespaces/:publicNamespaceName/namespaces', url: '/envs/:env/appnamespaces/:publicNamespaceName/namespaces',
isArray: true isArray: true
},
loadAppNamespace: {
method: 'GET',
url: '/apps/:appId/appnamespaces/:namespaceName'
},
deleteAppNamespace: {
method: 'DELETE',
url: '/apps/:appId/appnamespaces/:namespaceName'
} }
}); });
...@@ -112,13 +120,47 @@ appService.service("NamespaceService", ['$resource', '$q', function ($resource, ...@@ -112,13 +120,47 @@ appService.service("NamespaceService", ['$resource', '$q', function ($resource,
} }
function loadAppNamespace(appId, namespaceName) {
var d = $q.defer();
namespace_source.loadAppNamespace({
appId: appId,
namespaceName: namespaceName
},
function (result) {
d.resolve(result);
},
function (result) {
d.reject(result);
});
return d.promise;
}
function deleteAppNamespace(appId, namespaceName) {
var d = $q.defer();
namespace_source.deleteAppNamespace({
appId: appId,
namespaceName: namespaceName
},
function (result) {
d.resolve(result);
},
function (result) {
d.reject(result);
});
return d.promise;
}
return { return {
find_public_namespaces: find_public_namespaces, find_public_namespaces: find_public_namespaces,
createNamespace: createNamespace, createNamespace: createNamespace,
createAppNamespace: createAppNamespace, createAppNamespace: createAppNamespace,
getNamespacePublishInfo: getNamespacePublishInfo, getNamespacePublishInfo: getNamespacePublishInfo,
deleteNamespace: deleteNamespace, deleteNamespace: deleteNamespace,
getPublicAppNamespaceAllNamespaces: getPublicAppNamespaceAllNamespaces getPublicAppNamespaceAllNamespaces: getPublicAppNamespaceAllNamespaces,
loadAppNamespace: loadAppNamespace,
deleteAppNamespace: deleteAppNamespace
} }
}]); }]);
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
<li><a href="/user-manage.html" target="_blank">用户管理</a></li> <li><a href="/user-manage.html" target="_blank">用户管理</a></li>
<li><a href="/open/manage.html" target="_blank">开放平台授权管理</a></li> <li><a href="/open/manage.html" target="_blank">开放平台授权管理</a></li>
<li><a href="/server_config.html" target="_blank">系统参数</a></li> <li><a href="/server_config.html" target="_blank">系统参数</a></li>
<li><a href="/delete_app_cluster_namespace.html" target="_blank">删除应用、集群、AppNamespace</a></li>
</ul> </ul>
</li> </li>
<li class="dropdown"> <li class="dropdown">
......
...@@ -111,13 +111,18 @@ public class NamespaceServiceTest extends AbstractUnitTest { ...@@ -111,13 +111,18 @@ public class NamespaceServiceTest extends AbstractUnitTest {
} }
@Test(expected = BadRequestException.class) @Test
public void testDeletePrivateNamespace() { public void testDeletePrivateNamespace() {
String operator = "user";
AppNamespace privateNamespace = createAppNamespace(testAppId, testNamespaceName, false); AppNamespace privateNamespace = createAppNamespace(testAppId, testNamespaceName, false);
when(appNamespaceService.findByAppIdAndName(testAppId, testNamespaceName)).thenReturn(privateNamespace); when(appNamespaceService.findByAppIdAndName(testAppId, testNamespaceName)).thenReturn(privateNamespace);
when(userInfoHolder.getUser()).thenReturn(createUser(operator));
namespaceService.deleteNamespace(testAppId, testEnv, testClusterName, testNamespaceName); namespaceService.deleteNamespace(testAppId, testEnv, testClusterName, testNamespaceName);
verify(namespaceAPI, times(1)).deleteNamespace(testEnv, testAppId, testClusterName, testNamespaceName, operator);
} }
@Test(expected = BadRequestException.class) @Test(expected = BadRequestException.class)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment