Commit 1ea8697c by lepdou

create app namespace

parent 5b7bcc20
......@@ -38,7 +38,7 @@ public class AdminServiceAPI {
return restTemplate.getForObject(getAdminServiceHost(env) + APP_API + "/" + appId, AppDTO.class);
}
public AppDTO save(Env env, AppDTO app) {
public AppDTO createApp(Env env, AppDTO app) {
return restTemplate.postForEntity(getAdminServiceHost(env) + APP_API, app, AppDTO.class)
.getBody();
}
......@@ -70,14 +70,14 @@ public class AdminServiceAPI {
return Arrays.asList(appNamespaceDTOs);
}
public NamespaceDTO saveNamespace(Env env, NamespaceDTO namespace) {
public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) {
return restTemplate.postForEntity(getAdminServiceHost(env) +
String.format("/apps/%s/clusters/%s/namespaces", namespace.getAppId(),
namespace.getClusterName()), namespace, NamespaceDTO.class)
.getBody();
}
public AppNamespaceDTO saveAppNamespace(Env env, AppNamespaceDTO appNamespace) {
public AppNamespaceDTO createAppNamespace(Env env, AppNamespaceDTO appNamespace) {
return restTemplate.postForEntity(getAdminServiceHost(env) +
String.format("/apps/%s/appnamespaces", appNamespace.getAppId()), appNamespace, AppNamespaceDTO.class)
.getBody();
......
......@@ -49,9 +49,9 @@ public class AppController {
throw new BadRequestException("request payload contains empty");
}
if ("ALL".equals(env)){
appService.save(app);
appService.createAppInAllEnvs(app);
} else {
appService.save(Env.valueOf(env), app);
appService.createApp(Env.valueOf(env), app);
}
return ResponseEntity.ok().build();
}
......
......@@ -9,7 +9,6 @@ import com.ctrip.apollo.core.utils.StringUtils;
import com.ctrip.apollo.portal.entity.ItemDiffs;
import com.ctrip.apollo.portal.entity.form.NamespaceSyncModel;
import com.ctrip.apollo.portal.entity.form.NamespaceTextModel;
import com.ctrip.apollo.portal.entity.NamespaceVO;
import com.ctrip.apollo.portal.entity.form.NamespaceReleaseModel;
import com.ctrip.apollo.portal.service.ConfigService;
......
......@@ -29,20 +29,20 @@ public class NamespaceController {
}
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces", method = RequestMethod.POST)
public NamespaceDTO saveNamespace(@PathVariable String env, @RequestBody NamespaceDTO namespace){
public NamespaceDTO createNamespace(@PathVariable String env, @RequestBody NamespaceDTO namespace){
if (StringUtils.isContainEmpty(env, namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName())){
throw new BadRequestException("request payload contains empty");
}
return namespaceService.saveNamespace(Env.valueOf(env), namespace);
return namespaceService.createNamespace(Env.valueOf(env), namespace);
}
@RequestMapping(value = "/apps/{appId}/appnamespaces", method = RequestMethod.POST)
public void saveAppNamespace(@PathVariable String appId, @RequestBody AppNamespaceDTO appNamespace){
public void createAppNamespace(@PathVariable String appId, @RequestBody AppNamespaceDTO appNamespace){
if (StringUtils.isContainEmpty(appId, appNamespace.getAppId(), appNamespace.getName())){
throw new BadRequestException("request payload contains empty");
}
namespaceService.saveAppNamespace(appNamespace);
namespaceService.createAppNamespace(appNamespace);
}
@RequestMapping("/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces")
......
package com.ctrip.apollo.portal.service;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
......@@ -84,11 +83,11 @@ public class AppService {
return tree;
}
public void save(AppDTO app) {
public void createAppInAllEnvs(AppDTO app) {
List<Env> envs = portalSettings.getEnvs();
for (Env env : envs) {
try {
appAPI.save(env, app);
appAPI.createApp(env, app);
} catch (HttpStatusCodeException e) {
logger.error(ExceptionUtils.toString(e));
throw e;
......@@ -96,9 +95,9 @@ public class AppService {
}
}
public void save(Env env, AppDTO app) {
public void createApp(Env env, AppDTO app) {
try {
appAPI.save(env, app);
appAPI.createApp(env, app);
} catch (HttpStatusCodeException e) {
logger.error(ExceptionUtils.toString(e));
throw e;
......
......@@ -51,14 +51,14 @@ public class NamespaceService {
return namespaceAPI.findPublicAppNamespaces(portalSettings.getFirstEnv());
}
public NamespaceDTO saveNamespace(Env env, NamespaceDTO namespace){
return namespaceAPI.saveNamespace(env, namespace);
public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace){
return namespaceAPI.createNamespace(env, namespace);
}
public void saveAppNamespace(AppNamespaceDTO appNamespace) {
public void createAppNamespace(AppNamespaceDTO appNamespace) {
for (Env env : portalSettings.getEnvs()) {
try {
namespaceAPI.saveAppNamespace(env, appNamespace);
namespaceAPI.createAppNamespace(env, appNamespace);
} catch (HttpStatusCodeException e) {
logger.error(ExceptionUtils.toString(e));
throw e;
......
......@@ -83,7 +83,7 @@
<!--</div>-->
<!--</a>-->
<a class="list-group-item" target="_blank" href="namespace.html?#/appid={{pageContext.appId}}">
<a class="list-group-item" href="namespace.html?#/appid={{pageContext.appId}}&type=link">
<div class="row">
<div class="col-md-2"><img src="img/plus.png" class="i-20"></div>
<div class="col-md-7 hidden-xs">
......@@ -294,7 +294,7 @@
{{watch.value}}
<div ng-show="watch.oldValue">
<hr>
老的值:{{watch.oldValue}}
<b>已发布的值:</b>{{watch.oldValue}}
</div>
</div>
<div class="modal-footer">
......
......@@ -33,7 +33,7 @@
</button>
<button type="button" class="btn btn-success" ng-show="syncItemStep == 2 && hasDiff" ng-click="syncItems()">同步
</button>
<button type="button" class="btn btn-primary" data-dismiss="modal" ng-show="syncItemStep == 3"
<button type="button" class="btn btn-success" data-dismiss="modal" ng-show="syncItemStep == 3"
ng-click="backToAppHomePage()">返回
</button>
</div>
......
......@@ -5,8 +5,8 @@
<!-- 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" href="vendor/select2/select2.min.css">
<link rel="stylesheet" type="text/css" media='all' href="vendor/angular/loading-bar.min.css">
<link href="http://cdn.bootcss.com/select2/4.0.2-rc.1/css/select2.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="styles/common-style.css">
<title>新建Namespace</title>
</head>
......@@ -15,26 +15,32 @@
<div ng-include="'views/common/nav.html'"></div>
<div class="container-fluid apollo-container">
<div class="container-fluid apollo-container" ng-controller="LinkNamespaceController">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel">
<header class="panel-heading">
新建Namespace
<div class="row">
<div class="col-md-6">新建Namespace</div>
<div class="col-md-6 text-right">
<button type="button" class="btn btn-success" ng-show="step == 2" ng-click="back()">返回</button>
</div>
</div>
</header>
<div class="panel-body">
<form class="form-horizontal" ng-controller="LinkNamespaceController" ng-submit="saveNamespace()">
<form class="form-horizontal" ng-show="step == 1" ng-submit="createNamespace()">
<div class="form-group">
<label class="col-sm-3 control-label">应用ID</label>
<div class="col-sm-6">
{{appId}}
</div>
</div>
<div class="form-horizontal">
<div class="form-horizontal" ng-show="type == 'link'">
<div class="form-group">
<label class="col-sm-3 control-label">选择集群</label>
<label class="col-sm-3 control-label"><font style="color: red">*</font>选择集群</label>
<div class="col-sm-6">
<table class="table table-hover">
<thead>
......@@ -57,24 +63,19 @@
</div>
</div>
</div>
<div class="form-group" ng-show="isRootUser">
<label class="col-sm-3 control-label"><font style="color: red">*</font>namespace类型</label>
<div class="form-group" ng-show="type == 'create'">
<label class="col-sm-3 control-label"><font style="color: red">*</font>名称</label>
<div class="col-sm-4">
<label class="radio-inline">
<input type="radio" name="x" ng-checked="namespaceType == 1" ng-click="selectNamespaceType(1)"> 关联
</label>
<label class="radio-inline">
<input type="radio" name="x" ng-checked="namespaceType == 2" ng-click="selectNamespaceType(2)"> 新建
</label>
<input type="text" class="form-control" ng-model="appNamespace.name" ng-required="type == 'create'">
</div>
</div>
<div class="form-group" ng-show="namespaceType == 2">
<label class="col-sm-3 control-label"><font style="color: red">*</font>namespace</label>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="输入namespace名称">
<div class="form-group" ng-show="type == 'create'">
<label class="col-sm-3 control-label">备注</label>
<div class="col-sm-7">
<textarea class="form-control" rows="3" ng-model="appNamespace.comment"></textarea>
</div>
</div>
<div class="form-group" ng-show="namespaceType == 1">
<div class="form-group" ng-show="type == 'link'">
<label class="col-sm-3 control-label"><font style="color: red">*</font>namespace</label>
<div class="col-sm-4">
<select id="namespaces">
......@@ -84,11 +85,16 @@
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="col-sm-offset-3 col-sm-10">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
</form>
<div class="row text-center" ng-show="step == 2">
<img src="img/sync-succ.png" style="height: 100px; width: 100px">
<h3>创建成功!</h3>
</div>
</div>
</div>
</div>
......@@ -107,7 +113,8 @@
<!-- jquery.js -->
<script src="vendor/jquery.js" type="text/javascript"></script>
<script src="http://cdn.bootcss.com/select2/4.0.2-rc.1/js/select2.min.js"></script>
<script src="vendor/select2/select2.min.js" type="text/javascript"></script>
<!-- bootstrap.js -->
<script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
......@@ -117,7 +124,7 @@
<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/controller/LinkNamespaceController.js"></script>
<script type="application/javascript" src="scripts/controller/NamespaceController.js"></script>
</body>
......
......@@ -22,13 +22,6 @@ appUtil.service('AppUtil', [function () {
result[kv[0]] = kv[1];
});
return result;
},
cutOffString: function (str, maxLength) {
if (!str || maxLength <= 0) {
return '';
}
return str.length > maxLength ? str.substr(0, maxLength) : str;
}
}
}]);
......@@ -4,7 +4,9 @@ application_module.controller("LinkNamespaceController",
var params = AppUtil.parseParams($location.$$url);
$scope.appId = params.appid;
$scope.isRootUser = params.root ? true : false;
$scope.type = params.type;
$scope.step = 1;
////// load env //////
AppService.load_nav_tree($scope.appId).then(function (result) {
......@@ -36,26 +38,50 @@ application_module.controller("LinkNamespaceController",
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "load public namespace error");
});
$scope.saveNamespace = function () {
var selectedClusters = collectSelectedClusters();
if (selectedClusters.length == 0){
toastr.warning("请选择集群");
return;
}
var namespaceName = $('#namespaces').select2('data')[0].id;
selectedClusters.forEach(function (cluster) {
NamespaceService.save($scope.appId, cluster.env, cluster.clusterName,
namespaceName).then(function (result) {
toastr.success(
cluster.env + "_" + result.clusterName + "_" + result.namespaceName
+ "创建成功");
$scope.appNamespace = {
appId:$scope.appId,
name:'',
comment:''
};
$scope.createNamespace = function () {
if ($scope.type == 'link'){
var selectedClusters = collectSelectedClusters();
if (selectedClusters.length == 0){
toastr.warning("请选择集群");
return;
}
var selectedClustersSize = selectedClusters.length;
if ($scope.namespaceType == 1){
$scope.namespaceName = $('#namespaces').select2('data')[0].id;
}
var hasCreatedClusterCnt = 0;
selectedClusters.forEach(function (cluster) {
NamespaceService.createNamespace($scope.appId, cluster.env, cluster.clusterName,
$scope.namespaceName).then(function (result) {
toastr.success(
cluster.env + "_" + result.clusterName + "_" + result.namespaceName
+ "创建成功");
hasCreatedClusterCnt ++;
if (hasCreatedClusterCnt == selectedClustersSize){
$scope.step = 2;
}
}, function (result) {
toastr.error(AppUtil.errorMsg(result),
cluster.env + "_" + cluster.clusterName + "_"
+ $scope.namespaceName + "创建失败");
});
});
}else {
NamespaceService.createAppNamespace($scope.appId, $scope.appNamespace).then(function (result) {
$scope.step = 2;
}, function (result) {
toastr.error(AppUtil.errorMsg(result),
cluster.env + "_" + cluster.clusterName + "_"
+ namespaceName + "创建失败");
toastr.error(AppUtil.errorMsg(result), "创建失败");
});
})
}
};
var envAllSelected = false;
......@@ -85,6 +111,10 @@ application_module.controller("LinkNamespaceController",
$scope.switchSelect = function (o) {
o.checked = !o.checked;
}
};
$scope.back = function () {
$window.location.href = '/config.html?#appid=' + $scope.appId;
};
}]);
......@@ -121,6 +121,7 @@ application_module.controller("AppConfigController",
namespace.viewType = viewType;
};
var MAX_ROW_SIZE = 30;
//把表格内容解析成文本
function parseModel2Text(namespace) {
......@@ -139,8 +140,7 @@ application_module.controller("AppConfigController",
itemCnt ++;
});
itemCnt = itemCnt > 30 ? 30 : itemCnt;
namespace.itemCnt = itemCnt + 3;
namespace.itemCnt = itemCnt > MAX_ROW_SIZE ? MAX_ROW_SIZE : itemCnt + 3;
return result;
}
......
......@@ -5,10 +5,15 @@ appService.service("NamespaceService", ['$resource', '$q', function ($resource,
isArray: true,
url: '/appnamespaces/public'
},
save: {
createNamespace: {
method: 'POST',
url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces',
isArray: false
},
createAppNamespace: {
method: 'POST',
url: '/apps/:appId/appnamespaces',
isArray: false
}
});
......@@ -22,9 +27,9 @@ appService.service("NamespaceService", ['$resource', '$q', function ($resource,
});
return d.promise;
},
save: function (appId, env, clusterName, namespaceName) {
createNamespace: function (appId, env, clusterName, namespaceName) {
var d = $q.defer();
namespace_source.save({
namespace_source.createNamespace({
appId: appId,
env: env,
clusterName: clusterName
......@@ -38,6 +43,17 @@ appService.service("NamespaceService", ['$resource', '$q', function ($resource,
d.reject(result);
});
return d.promise;
},
createAppNamespace: function (appId, appnamespace) {
var d = $q.defer();
namespace_source.createAppNamespace({
appId: appId
}, appnamespace, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
}
......
......@@ -7,7 +7,6 @@ body {
padding: 0px !important;
margin: 0px !important;
font-size: 13px;
/*min-height: 650px;*/
background: #f1f2f7;
font-family: 'Open Sans', sans-serif;
}
......
......@@ -2,6 +2,7 @@
<hr>
<p class="text-center">
<span class="glyphicon glyphicon-copyright-mark" aria-hidden="true"></span>携程 框架研发部<br>
<a href="http://conf.ctripcorp.com/display/FRAM/Apollo" target="_blank">wiki</a>
</p>
</div>
......
......@@ -71,9 +71,9 @@ public class AppServiceTest {
// appDTO.setOwnerEmail("qq@qq.com");
// appDTO.setOwnerName("zz");
//
// when(appService.save(appDTO)).thenReturn(appDTO);
// when(appService.createApp(appDTO)).thenReturn(appDTO);
//
// AppDTO createApp = appService.save(appDTO);
// AppDTO createApp = appService.createApp(appDTO);
//
// assertEquals(appId, createApp.getAppId());
// assertEquals(appName, createApp.getName());
......
......@@ -60,7 +60,7 @@ public class ServiceExceptionTest extends AbstractPortalTest {
HttpStatusCodeException adminException =
new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "admin server error",
new Gson().toJson(errorAttributes).getBytes(), Charset.defaultCharset());
when(appAPI.save(any(Env.class), any(AppDTO.class))).thenThrow(adminException);
when(appAPI.createApp(any(Env.class), any(AppDTO.class))).thenThrow(adminException);
AppDTO dto = generateSampleDTOData();
try {
......
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