Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wrr-cat
apollo
提交
1cf49996
apollo
项目概览
wrr-cat
/
apollo
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
apollo
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
1cf49996
编写于
7月 23, 2018
作者:
J
Jason Song
提交者:
GitHub
7月 23, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1279 from nobodyiam/delete-app-cluster-namespace-page
add admin page to delete app, cluster and app namespace
上级
65da1611
44ce0e4e
变更
14
显示空白变更内容
内联
并排
Showing
14 changed file
with
492 addition
and
38 deletion
+492
-38
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ClusterController.java
...framework/apollo/portal/controller/ClusterController.java
+6
-1
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceController.java
...amework/apollo/portal/controller/NamespaceController.java
+14
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java
...rip/framework/apollo/portal/service/NamespaceService.java
+4
-8
apollo-portal/src/main/resources/static/config.html
apollo-portal/src/main/resources/static/config.html
+2
-4
apollo-portal/src/main/resources/static/delete_app_cluster_namespace.html
...c/main/resources/static/delete_app_cluster_namespace.html
+223
-0
apollo-portal/src/main/resources/static/scripts/app.js
apollo-portal/src/main/resources/static/scripts/app.js
+2
-3
apollo-portal/src/main/resources/static/scripts/controller/DeleteAppClusterNamespaceController.js
...scripts/controller/DeleteAppClusterNamespaceController.js
+132
-0
apollo-portal/src/main/resources/static/scripts/directive/delete-namespace-modal-directive.js
...tic/scripts/directive/delete-namespace-modal-directive.js
+4
-19
apollo-portal/src/main/resources/static/scripts/services/AppService.js
.../src/main/resources/static/scripts/services/AppService.js
+15
-0
apollo-portal/src/main/resources/static/scripts/services/ClusterService.js
.../main/resources/static/scripts/services/ClusterService.js
+36
-0
apollo-portal/src/main/resources/static/scripts/services/NamespaceService.js
...ain/resources/static/scripts/services/NamespaceService.js
+43
-1
apollo-portal/src/main/resources/static/views/common/nav.html
...lo-portal/src/main/resources/static/views/common/nav.html
+1
-0
apollo-portal/src/main/resources/static/views/component/delete-namespace-modal.html
...ources/static/views/component/delete-namespace-modal.html
+4
-1
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/service/NamespaceServiceTest.java
...framework/apollo/portal/service/NamespaceServiceTest.java
+6
-1
未找到文件。
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ClusterController.java
浏览文件 @
1cf49996
...
@@ -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
);
}
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceController.java
浏览文件 @
1cf49996
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
)
{
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java
浏览文件 @
1cf49996
...
@@ -74,26 +74,22 @@ public class NamespaceService {
...
@@ -74,26 +74,22 @@ public class NamespaceService {
@Transactional
@Transactional
public
void
deleteNamespace
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
public
void
deleteNamespace
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
//1. check private namespace
AppNamespace
appNamespace
=
appNamespaceService
.
findByAppIdAndName
(
appId
,
namespaceName
);
AppNamespace
appNamespace
=
appNamespaceService
.
findByAppIdAndName
(
appId
,
namespaceName
);
if
(
appNamespace
!=
null
&&
!
appNamespace
.
isPublic
())
{
throw
new
BadRequestException
(
"Private namespace can not be deleted"
);
}
//
2
. check parent namespace has not instances
//
1
. check parent namespace has not instances
if
(
namespaceHasInstances
(
appId
,
env
,
clusterName
,
namespaceName
))
{
if
(
namespaceHasInstances
(
appId
,
env
,
clusterName
,
namespaceName
))
{
throw
new
BadRequestException
(
"Can not delete namespace because namespace has active instances"
);
throw
new
BadRequestException
(
"Can not delete namespace because namespace has active instances"
);
}
}
//
3
. check child namespace has not instances
//
2
. check child namespace has not instances
NamespaceDTO
childNamespace
=
branchService
.
findBranchBaseInfo
(
appId
,
env
,
clusterName
,
namespaceName
);
NamespaceDTO
childNamespace
=
branchService
.
findBranchBaseInfo
(
appId
,
env
,
clusterName
,
namespaceName
);
if
(
childNamespace
!=
null
&&
if
(
childNamespace
!=
null
&&
namespaceHasInstances
(
appId
,
env
,
childNamespace
.
getClusterName
(),
namespaceName
))
{
namespaceHasInstances
(
appId
,
env
,
childNamespace
.
getClusterName
(),
namespaceName
))
{
throw
new
BadRequestException
(
"Can not delete namespace because namespace's branch has active instances"
);
throw
new
BadRequestException
(
"Can not delete namespace because namespace's branch has active instances"
);
}
}
//
4
. check public namespace has not associated namespace
//
3
. check public namespace has not associated namespace
if
(
appNamespace
!=
null
&&
publicAppNamespaceHasAssociatedNamespace
(
namespaceName
,
env
))
{
if
(
appNamespace
!=
null
&&
appNamespace
.
isPublic
()
&&
publicAppNamespaceHasAssociatedNamespace
(
namespaceName
,
env
))
{
throw
new
BadRequestException
(
"Can not delete public namespace which has associated namespaces"
);
throw
new
BadRequestException
(
"Can not delete public namespace which has associated namespaces"
);
}
}
...
...
apollo-portal/src/main/resources/static/config.html
浏览文件 @
1cf49996
...
@@ -288,8 +288,7 @@
...
@@ -288,8 +288,7 @@
apollo-detail=
"'发现有 <b>' + deleteNamespaceContext.namespace.instancesCount +
apollo-detail=
"'发现有 <b>' + deleteNamespaceContext.namespace.instancesCount +
'</b> 个实例正在使用Namespace(' + deleteNamespaceContext.namespace.baseInfo.namespaceName +
'</b> 个实例正在使用Namespace(' + deleteNamespaceContext.namespace.baseInfo.namespaceName +
'),删除Namespace将导致实例获取不到配置。<br>
'),删除Namespace将导致实例获取不到配置。<br>
请到 <ins>“实例列表”</ins> 确认实例信息,如已确认删除Namespace将不会导致实例异常,
请到 <ins>“实例列表”</ins> 确认实例信息,如确认相关实例都已经不再使用该Namespace配置,可以联系Apollo相关负责人删除实例信息(InstanceConfig)或等待实例24小时自动过期后再来删除。'"
请联系Apollo相关负责人删除Namespace'"
apollo-confirm=
"continueDeleteNamespace"
>
apollo-confirm=
"continueDeleteNamespace"
>
</apolloconfirmdialog>
</apolloconfirmdialog>
...
@@ -298,8 +297,7 @@
...
@@ -298,8 +297,7 @@
apollo-detail=
"'发现有 <b>' + deleteNamespaceContext.namespace.branch.latestReleaseInstances.total
apollo-detail=
"'发现有 <b>' + deleteNamespaceContext.namespace.branch.latestReleaseInstances.total
+ '</b> 个实例正在使用Namespace(' + deleteNamespaceContext.namespace.baseInfo.namespaceName +
+ '</b> 个实例正在使用Namespace(' + deleteNamespaceContext.namespace.baseInfo.namespaceName +
')灰度版本的配置,删除Namespace将导致实例获取不到配置。<br>
')灰度版本的配置,删除Namespace将导致实例获取不到配置。<br>
请到 <ins>“灰度版本” => “实例列表”</ins> 确认实例信息,如已确认删除Namespace将不会导致实例异常,
请到 <ins>“灰度版本” => “实例列表”</ins> 确认实例信息,如确认相关实例都已经不再使用该Namespace配置,可以联系Apollo相关负责人删除实例信息(InstanceConfig)或等待实例24小时自动过期后再来删除。'"
请联系Apollo相关负责人删除Namespace'"
apollo-confirm=
"continueDeleteNamespace"
>
apollo-confirm=
"continueDeleteNamespace"
>
</apolloconfirmdialog>
</apolloconfirmdialog>
...
...
apollo-portal/src/main/resources/static/delete_app_cluster_namespace.html
0 → 100644
浏览文件 @
1cf49996
<!doctype html>
<html
ng-app=
"delete_app_cluster_namespace"
>
<head>
<meta
http-equiv=
"Content-Type"
content=
"text/html; charset=UTF-8"
>
<link
rel=
"icon"
href=
"../img/config.png"
>
<!-- styles -->
<link
rel=
"stylesheet"
type=
"text/css"
href=
"../vendor/bootstrap/css/bootstrap.min.css"
>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"../vendor/angular/angular-toastr-1.4.1.min.css"
>
<link
rel=
"stylesheet"
type=
"text/css"
media=
'all'
href=
"../vendor/angular/loading-bar.min.css"
>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"../styles/common-style.css"
>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"../vendor/select2/select2.min.css"
>
<title>
删除应用、集群、AppNamespace
</title>
</head>
<body>
<apollonav></apollonav>
<div
class=
"container-fluid"
ng-controller=
"DeleteAppClusterNamespaceController"
>
<div
class=
"col-md-10 col-md-offset-1 panel"
>
<section
class=
"panel-body"
ng-show=
"isRootUser"
>
<!-- delete app -->
<section
class=
"row"
>
<h5>
删除应用
<small>
(由于删除应用影响面较大,所以现在暂时只允许系统管理员删除,请确保没有客户端读取该应用的配置后再做删除动作)
</small>
</h5>
<hr>
<form
class=
"form-horizontal"
>
<div
class=
"form-group"
valdr-form-group
>
<label
class=
"col-sm-2 control-label"
>
<apollorequiredfield></apollorequiredfield>
应用AppId
</label>
<div
class=
"col-sm-5"
>
<input
type=
"text"
class=
"form-control"
ng-model=
"app.appId"
>
<small>
(删除前请先查询应用信息)
</small>
</div>
<div
class=
"col-sm-1"
>
<button
class=
"btn btn-info"
ng-click=
"getAppInfo()"
>
查询
</button>
</div>
</div>
<div
class=
"form-group"
valdr-form-group
>
<label
class=
"col-sm-2 control-label"
>
应用信息
</label>
<div
class=
"col-sm-5"
>
<h5
ng-show=
"app.info"
ng-bind=
"app.info"
></h5>
</div>
</div>
<div
class=
"form-group"
>
<div
class=
"col-sm-offset-2 col-sm-9"
>
<button
type=
"submit"
class=
"btn btn-primary"
ng-disabled=
"deleteAppBtnDisabled"
ng-click=
"deleteApp()"
>
删除应用
</button>
</div>
</div>
</form>
</section>
<!-- delete cluster -->
<section
class=
"row"
>
<h5>
删除集群
<small>
(由于删除集群影响面较大,所以现在暂时只允许系统管理员删除,请确保没有客户端读取该集群的配置后再做删除动作)
</small>
</h5>
<hr>
<form
class=
"form-horizontal"
>
<div
class=
"form-group"
valdr-form-group
>
<label
class=
"col-sm-2 control-label"
>
<apollorequiredfield></apollorequiredfield>
应用AppId
</label>
<div
class=
"col-sm-5"
>
<input
type=
"text"
class=
"form-control"
ng-model=
"cluster.appId"
>
</div>
</div>
<div
class=
"form-group"
valdr-form-group
>
<label
class=
"col-sm-2 control-label"
>
<apollorequiredfield></apollorequiredfield>
环境名称
</label>
<div
class=
"col-sm-5"
>
<input
type=
"text"
class=
"form-control"
ng-model=
"cluster.env"
>
</div>
</div>
<div
class=
"form-group"
valdr-form-group
>
<label
class=
"col-sm-2 control-label"
>
<apollorequiredfield></apollorequiredfield>
集群名称
</label>
<div
class=
"col-sm-5"
>
<input
type=
"text"
class=
"form-control"
ng-model=
"cluster.name"
>
<small>
(删除前请先查询应用集群信息)
</small>
</div>
<div
class=
"col-sm-1"
>
<button
class=
"btn btn-info"
ng-click=
"getClusterInfo()"
>
查询
</button>
</div>
</div>
<div
class=
"form-group"
viv
clform-group
>
<label
class=
"col-sm-2 control-label"
>
集群信息
</label>
<div
class=
"col-sm-5"
>
<h5
ng-show=
"cluster.info"
ng-bind=
"cluster.info"
></h5>
</div>
</div>
<div
class=
"form-group"
>
<div
class=
"col-sm-offset-2 col-sm-9"
>
<button
type=
"submit"
class=
"btn btn-primary"
ng-disabled=
"deleteClusterBtnDisabled"
ng-click=
"deleteCluster()"
>
删除集群
</button>
</div>
</div>
</form>
</section>
<!-- delete app namespace -->
<section
class=
"row"
>
<h5>
删除AppNamespace
<small>
(注意,所有环境的Namespace和AppNamespace都会被删除!如果只是要删除某个环境的Namespace,让用户到项目页面中自行删除!)
</small>
</h5>
<small>
目前用户可以自行删除关联的Namespace和私有的Namespace,不过无法删除AppNamespace元信息,因为删除AppNamespace影响面较大,所以现在暂时只允许系统管理员删除,对于公共Namespace需要确保没有应用关联了该AppNamespace。
</small>
<hr>
<form
class=
"form-horizontal"
>
<div
class=
"form-group"
valdr-form-group
>
<label
class=
"col-sm-2 control-label"
>
<apollorequiredfield></apollorequiredfield>
应用AppId
</label>
<div
class=
"col-sm-5"
>
<input
type=
"text"
class=
"form-control"
ng-model=
"appNamespace.appId"
>
</div>
</div>
<div
class=
"form-group"
valdr-form-group
>
<label
class=
"col-sm-2 control-label"
>
<apollorequiredfield></apollorequiredfield>
AppNamespace名称
</label>
<div
class=
"col-sm-5"
>
<input
type=
"text"
class=
"form-control"
ng-model=
"appNamespace.name"
>
<small>
(非properties类型的namespace请加上类型后缀,例如apollo.xml)
</small>
</div>
<div
class=
"col-sm-1"
>
<button
class=
"btn btn-info"
ng-click=
"getAppNamespaceInfo()"
>
查询
</button>
</div>
</div>
<div
class=
"form-group"
viv
clform-group
>
<label
class=
"col-sm-2 control-label"
>
集群信息
</label>
<div
class=
"col-sm-5"
>
<h5
ng-show=
"appNamespace.info"
ng-bind=
"appNamespace.info"
></h5>
</div>
</div>
<div
class=
"form-group"
>
<div
class=
"col-sm-offset-2 col-sm-9"
>
<button
type=
"submit"
class=
"btn btn-primary"
ng-disabled=
"deleteAppNamespaceBtnDisabled"
ng-click=
"deleteAppNamespace()"
>
删除AppNamespace
</button>
</div>
</div>
</form>
</section>
</section>
<section
class=
"panel-body text-center"
ng-if=
"!isRootUser"
>
<h4>
当前页面只对Apollo管理员开放
</h4>
</section>
</div>
</div>
<div
ng-include=
"'../views/common/footer.html'"
></div>
<!-- jquery.js -->
<script
src=
"../vendor/jquery.min.js"
type=
"text/javascript"
></script>
<!--angular-->
<script
src=
"../vendor/angular/angular.min.js"
></script>
<script
src=
"../vendor/angular/angular-route.min.js"
></script>
<script
src=
"../vendor/angular/angular-resource.min.js"
></script>
<script
src=
"../vendor/angular/angular-toastr-1.4.1.tpls.min.js"
></script>
<script
src=
"../vendor/angular/loading-bar.min.js"
></script>
<!--valdr-->
<script
src=
"../vendor/valdr/valdr.min.js"
type=
"text/javascript"
></script>
<script
src=
"../vendor/valdr/valdr-message.min.js"
type=
"text/javascript"
></script>
<!-- bootstrap.js -->
<script
src=
"../vendor/bootstrap/js/bootstrap.min.js"
type=
"text/javascript"
></script>
<!--nicescroll-->
<script
src=
"../vendor/jquery.nicescroll.min.js"
></script>
<script
src=
"../vendor/lodash.min.js"
></script>
<script
src=
"../vendor/select2/select2.min.js"
type=
"text/javascript"
></script>
<!--biz-->
<!--must import-->
<script
type=
"application/javascript"
src=
"../scripts/app.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/services/AppService.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/services/EnvService.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/services/UserService.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/services/CommonService.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/services/PermissionService.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/services/ClusterService.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/services/NamespaceService.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/AppUtils.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/PageCommon.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/directive/directive.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/valdr.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/controller/DeleteAppClusterNamespaceController.js"
></script>
</body>
</html>
apollo-portal/src/main/resources/static/scripts/app.js
浏览文件 @
1cf49996
...
@@ -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
'
]);
apollo-portal/src/main/resources/static/scripts/controller/DeleteAppClusterNamespaceController.js
0 → 100644
浏览文件 @
1cf49996
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
);
})
}
}
}
apollo-portal/src/main/resources/static/scripts/directive/delete-namespace-modal-directive.js
浏览文件 @
1cf49996
...
@@ -18,25 +18,20 @@ function deleteNamespaceModalDirective($window, $q, toastr, AppUtil, EventManage
...
@@ -18,25 +18,20 @@ function deleteNamespaceModalDirective($window, $q, toastr, AppUtil, EventManage
var
toDeleteNamespace
=
context
.
namespace
;
var
toDeleteNamespace
=
context
.
namespace
;
scope
.
toDeleteNamespace
=
toDeleteNamespace
;
scope
.
toDeleteNamespace
=
toDeleteNamespace
;
//1. check namespace is not private
//1. check operator has master permission
if
(
!
checkNotPrivateNamespace
(
toDeleteNamespace
))
{
return
;
}
//2. check operator has master permission
checkPermission
(
toDeleteNamespace
).
then
(
function
()
{
checkPermission
(
toDeleteNamespace
).
then
(
function
()
{
//
3
. check namespace's master branch has not instances
//
2
. check namespace's master branch has not instances
if
(
!
checkMasterInstance
(
toDeleteNamespace
))
{
if
(
!
checkMasterInstance
(
toDeleteNamespace
))
{
return
;
return
;
}
}
//
4
. check namespace's gray branch has not instances
//
3
. check namespace's gray branch has not instances
if
(
!
checkBranchInstance
(
toDeleteNamespace
))
{
if
(
!
checkBranchInstance
(
toDeleteNamespace
))
{
return
;
return
;
}
}
if
(
toDeleteNamespace
.
isLinkedNamespace
)
{
if
(
!
toDeleteNamespace
.
isPublic
||
toDeleteNamespace
.
isLinkedNamespace
)
{
showDeleteNamespaceConfirmDialog
();
showDeleteNamespaceConfirmDialog
();
}
else
{
}
else
{
//5. check public namespace has not associated namespace
//5. check public namespace has not associated namespace
...
@@ -48,15 +43,6 @@ function deleteNamespaceModalDirective($window, $q, toastr, AppUtil, EventManage
...
@@ -48,15 +43,6 @@ function deleteNamespaceModalDirective($window, $q, toastr, AppUtil, EventManage
});
});
function
checkNotPrivateNamespace
(
namespace
)
{
if
(
!
namespace
.
isPublic
)
{
toastr
.
error
(
"
不能删除私有的Namespace
"
,
"
删除失败
"
);
return
false
;
}
return
true
;
}
function
checkPermission
(
namespace
)
{
function
checkPermission
(
namespace
)
{
var
d
=
$q
.
defer
();
var
d
=
$q
.
defer
();
...
@@ -153,7 +139,6 @@ function deleteNamespaceModalDirective($window, $q, toastr, AppUtil, EventManage
...
@@ -153,7 +139,6 @@ function deleteNamespaceModalDirective($window, $q, toastr, AppUtil, EventManage
function
showDeleteNamespaceConfirmDialog
()
{
function
showDeleteNamespaceConfirmDialog
()
{
AppUtil
.
showModal
(
'
#deleteNamespaceModal
'
);
AppUtil
.
showModal
(
'
#deleteNamespaceModal
'
);
}
}
function
doDeleteNamespace
()
{
function
doDeleteNamespace
()
{
...
...
apollo-portal/src/main/resources/static/scripts/services/AppService.js
浏览文件 @
1cf49996
...
@@ -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
;
}
}
}
}
}]);
}]);
apollo-portal/src/main/resources/static/scripts/services/ClusterService.js
浏览文件 @
1cf49996
...
@@ -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
;
}
}
}
}
}]);
}]);
apollo-portal/src/main/resources/static/scripts/services/NamespaceService.js
浏览文件 @
1cf49996
...
@@ -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
}
}
}]);
}]);
apollo-portal/src/main/resources/static/views/common/nav.html
浏览文件 @
1cf49996
...
@@ -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"
>
...
...
apollo-portal/src/main/resources/static/views/component/delete-namespace-modal.html
浏览文件 @
1cf49996
...
@@ -8,9 +8,12 @@
...
@@ -8,9 +8,12 @@
删除Namespace
删除Namespace
</h4>
</h4>
</div>
</div>
<div
class=
"modal-body form-horizontal"
>
<div
class=
"modal-body form-horizontal"
ng-show=
"toDeleteNamespace.isPublic"
>
删除Namespace将导致实例获取不到此Namespace的配置,确定要删除吗?
删除Namespace将导致实例获取不到此Namespace的配置,确定要删除吗?
</div>
</div>
<div
class=
"modal-body form-horizontal"
ng-show=
"!toDeleteNamespace.isPublic"
>
删除私有Namespace将导致实例获取不到此Namespace的配置,而且无法在当前集群重新创建该Namespace(除非使用管理员工具把所有环境的AppNamespace删除后重建),确定要删除吗?
</div>
<div
class=
"modal-footer"
>
<div
class=
"modal-footer"
>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
取消
取消
...
...
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/service/NamespaceServiceTest.java
浏览文件 @
1cf49996
...
@@ -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%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录