Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wrr-cat
apollo
提交
e8150525
apollo
项目概览
wrr-cat
/
apollo
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
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,发现更多精彩内容 >>
提交
e8150525
编写于
5月 03, 2016
作者:
L
lepdou
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
sync items
上级
8e6ac7c1
变更
24
隐藏空白更改
内联
并排
Showing
24 changed file
with
740 addition
and
82 deletion
+740
-82
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/ConfigController.java
.../com/ctrip/apollo/portal/controller/ConfigController.java
+27
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/ItemDiffs.java
...c/main/java/com/ctrip/apollo/portal/entity/ItemDiffs.java
+27
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/NamespaceIdentifer.java
...va/com/ctrip/apollo/portal/entity/NamespaceIdentifer.java
+50
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/SimpleMsg.java
...c/main/java/com/ctrip/apollo/portal/entity/SimpleMsg.java
+0
-18
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceReleaseModel.java
...trip/apollo/portal/entity/form/NamespaceReleaseModel.java
+1
-1
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceSyncModel.java
...m/ctrip/apollo/portal/entity/form/NamespaceSyncModel.java
+43
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceTextModel.java
...m/ctrip/apollo/portal/entity/form/NamespaceTextModel.java
+1
-1
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/Verifiable.java
.../java/com/ctrip/apollo/portal/entity/form/Verifiable.java
+1
-1
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/ConfigService.java
...n/java/com/ctrip/apollo/portal/service/ConfigService.java
+84
-0
apollo-portal/src/main/resources/application.yml
apollo-portal/src/main/resources/application.yml
+1
-1
apollo-portal/src/main/resources/static/img/sync-error.png
apollo-portal/src/main/resources/static/img/sync-error.png
+0
-0
apollo-portal/src/main/resources/static/img/sync-succ.png
apollo-portal/src/main/resources/static/img/sync-succ.png
+0
-0
apollo-portal/src/main/resources/static/img/sync.png
apollo-portal/src/main/resources/static/img/sync.png
+0
-0
apollo-portal/src/main/resources/static/index.html
apollo-portal/src/main/resources/static/index.html
+4
-0
apollo-portal/src/main/resources/static/scripts/AppUtils.js
apollo-portal/src/main/resources/static/scripts/AppUtils.js
+25
-3
apollo-portal/src/main/resources/static/scripts/PageCommon.js
...lo-portal/src/main/resources/static/scripts/PageCommon.js
+12
-0
apollo-portal/src/main/resources/static/scripts/app.js
apollo-portal/src/main/resources/static/scripts/app.js
+2
-0
apollo-portal/src/main/resources/static/scripts/controller/app/AppConfigController.js
...rces/static/scripts/controller/app/AppConfigController.js
+19
-15
apollo-portal/src/main/resources/static/scripts/controller/app/SyncConfigController.js
...ces/static/scripts/controller/app/SyncConfigController.js
+76
-0
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
...c/main/resources/static/scripts/services/ConfigService.js
+21
-2
apollo-portal/src/main/resources/static/styles/common-style.css
...-portal/src/main/resources/static/styles/common-style.css
+4
-0
apollo-portal/src/main/resources/static/views/app.html
apollo-portal/src/main/resources/static/views/app.html
+33
-40
apollo-portal/src/main/resources/static/views/sync.html
apollo-portal/src/main/resources/static/views/sync.html
+200
-0
apollo-portal/src/test/java/com/ctrip/apollo/portal/ConfigServiceTest.java
.../test/java/com/ctrip/apollo/portal/ConfigServiceTest.java
+109
-0
未找到文件。
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/ConfigController.java
浏览文件 @
e8150525
package
com.ctrip.apollo.portal.controller
;
import
com.ctrip.apollo.core.dto.ItemDTO
;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.core.dto.ReleaseDTO
;
import
com.ctrip.apollo.core.exception.BadRequestException
;
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
;
...
...
@@ -78,4 +81,28 @@ public class ConfigController {
}
@RequestMapping
(
value
=
"/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items"
)
public
List
<
ItemDTO
>
findItems
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
){
if
(
StringUtils
.
isContainEmpty
(
appId
,
env
,
clusterName
,
namespaceName
)){
throw
new
BadRequestException
(
"appid,env,cluster name,namespace name can not be null"
);
}
return
configService
.
findItems
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
);
}
@RequestMapping
(
value
=
"/namespaces/{namespaceName}/diff"
,
method
=
RequestMethod
.
POST
,
consumes
=
{
"application/json"
})
public
List
<
ItemDiffs
>
diff
(
@RequestBody
NamespaceSyncModel
model
){
if
(
model
==
null
){
throw
new
BadRequestException
(
"request payload shoud not be null"
);
}
if
(
model
.
isInvalid
())
{
throw
new
BadRequestException
(
"request model is invalid"
);
}
return
configService
.
compare
(
model
.
getSyncItems
(),
model
.
getSyncToNamespaces
());
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/ItemDiffs.java
0 → 100644
浏览文件 @
e8150525
package
com.ctrip.apollo.portal.entity
;
import
com.ctrip.apollo.core.dto.ItemChangeSets
;
public
class
ItemDiffs
{
private
NamespaceIdentifer
namespace
;
private
ItemChangeSets
diffs
;
public
ItemDiffs
(
NamespaceIdentifer
namespace
){
this
.
namespace
=
namespace
;
}
public
NamespaceIdentifer
getNamespace
()
{
return
namespace
;
}
public
void
setNamespace
(
NamespaceIdentifer
namespace
)
{
this
.
namespace
=
namespace
;
}
public
ItemChangeSets
getDiffs
()
{
return
diffs
;
}
public
void
setDiffs
(
ItemChangeSets
diffs
)
{
this
.
diffs
=
diffs
;
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/NamespaceIdentifer.java
0 → 100644
浏览文件 @
e8150525
package
com.ctrip.apollo.portal.entity
;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.core.utils.StringUtils
;
import
com.ctrip.apollo.portal.entity.form.Verifiable
;
public
class
NamespaceIdentifer
implements
Verifiable
{
private
String
appId
;
private
String
env
;
private
String
clusterName
;
private
String
namespaceName
;
public
String
getAppId
()
{
return
appId
;
}
public
void
setAppId
(
String
appId
)
{
this
.
appId
=
appId
;
}
public
Env
getEnv
()
{
return
Env
.
valueOf
(
env
);
}
public
void
setEnv
(
String
env
)
{
this
.
env
=
env
;
}
public
String
getClusterName
()
{
return
clusterName
;
}
public
void
setClusterName
(
String
clusterName
)
{
this
.
clusterName
=
clusterName
;
}
public
String
getNamespaceName
()
{
return
namespaceName
;
}
public
void
setNamespaceName
(
String
namespaceName
)
{
this
.
namespaceName
=
namespaceName
;
}
@Override
public
boolean
isInvalid
()
{
return
StringUtils
.
isContainEmpty
(
env
,
clusterName
,
namespaceName
);
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/SimpleMsg.java
已删除
100644 → 0
浏览文件 @
8e6ac7c1
package
com.ctrip.apollo.portal.entity
;
public
class
SimpleMsg
{
private
String
msg
;
public
SimpleMsg
(
String
msg
){
this
.
msg
=
msg
;
}
public
String
getMsg
()
{
return
msg
;
}
public
void
setMsg
(
String
msg
)
{
this
.
msg
=
msg
;
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceReleaseModel.java
浏览文件 @
e8150525
...
...
@@ -4,7 +4,7 @@ package com.ctrip.apollo.portal.entity.form;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.core.utils.StringUtils
;
public
class
NamespaceReleaseModel
implements
FormModel
{
public
class
NamespaceReleaseModel
implements
Verifiable
{
private
String
appId
;
private
String
env
;
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceSyncModel.java
0 → 100644
浏览文件 @
e8150525
package
com.ctrip.apollo.portal.entity.form
;
import
com.ctrip.apollo.core.dto.ItemDTO
;
import
com.ctrip.apollo.portal.entity.NamespaceIdentifer
;
import
org.springframework.util.CollectionUtils
;
import
java.util.List
;
public
class
NamespaceSyncModel
implements
Verifiable
{
private
List
<
NamespaceIdentifer
>
syncToNamespaces
;
private
List
<
ItemDTO
>
syncItems
;
@Override
public
boolean
isInvalid
()
{
if
(
CollectionUtils
.
isEmpty
(
syncToNamespaces
)
||
CollectionUtils
.
isEmpty
(
syncItems
)){
return
true
;
}
for
(
NamespaceIdentifer
namespaceIdentifer:
syncToNamespaces
){
if
(
namespaceIdentifer
.
isInvalid
()){
return
true
;
}
}
return
false
;
}
public
List
<
NamespaceIdentifer
>
getSyncToNamespaces
()
{
return
syncToNamespaces
;
}
public
void
setSyncToNamespaces
(
List
<
NamespaceIdentifer
>
syncToNamespaces
)
{
this
.
syncToNamespaces
=
syncToNamespaces
;
}
public
List
<
ItemDTO
>
getSyncItems
()
{
return
syncItems
;
}
public
void
setSyncItems
(
List
<
ItemDTO
>
syncItems
)
{
this
.
syncItems
=
syncItems
;
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceTextModel.java
浏览文件 @
e8150525
...
...
@@ -4,7 +4,7 @@ package com.ctrip.apollo.portal.entity.form;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.core.utils.StringUtils
;
public
class
NamespaceTextModel
implements
FormModel
{
public
class
NamespaceTextModel
implements
Verifiable
{
private
String
appId
;
private
String
env
;
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/
FormModel
.java
→
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/
Verifiable
.java
浏览文件 @
e8150525
package
com.ctrip.apollo.portal.entity.form
;
public
interface
FormModel
{
public
interface
Verifiable
{
boolean
isInvalid
();
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/ConfigService.java
浏览文件 @
e8150525
...
...
@@ -7,17 +7,23 @@ import org.slf4j.LoggerFactory;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.web.client.HttpClientErrorException
;
import
com.ctrip.apollo.common.utils.BeanUtils
;
import
com.ctrip.apollo.common.utils.ExceptionUtils
;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.core.dto.ItemChangeSets
;
import
com.ctrip.apollo.core.dto.ItemDTO
;
import
com.ctrip.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.apollo.core.dto.ReleaseDTO
;
import
com.ctrip.apollo.core.exception.BadRequestException
;
import
com.ctrip.apollo.core.exception.NotFoundException
;
import
com.ctrip.apollo.core.exception.ServiceException
;
import
com.ctrip.apollo.core.utils.StringUtils
;
import
com.ctrip.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.apollo.portal.entity.ItemDiffs
;
import
com.ctrip.apollo.portal.entity.NamespaceIdentifer
;
import
com.ctrip.apollo.portal.entity.form.NamespaceTextModel
;
import
com.ctrip.apollo.portal.entity.NamespaceVO
;
import
com.ctrip.apollo.portal.entity.form.NamespaceReleaseModel
;
...
...
@@ -172,4 +178,82 @@ public class ConfigService {
return
releaseAPI
.
release
(
model
.
getAppId
(),
model
.
getEnv
(),
model
.
getClusterName
(),
model
.
getNamespaceName
(),
model
.
getReleaseBy
(),
model
.
getReleaseComment
());
}
public
List
<
ItemDTO
>
findItems
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
){
return
itemAPI
.
findItems
(
appId
,
env
,
clusterName
,
namespaceName
);
}
public
List
<
ItemDiffs
>
compare
(
List
<
ItemDTO
>
sourceItems
,
List
<
NamespaceIdentifer
>
comparedNamespaces
){
List
<
ItemDiffs
>
result
=
new
LinkedList
<>();
String
appId
,
clusterName
,
namespaceName
;
Env
env
;
for
(
NamespaceIdentifer
namespace:
comparedNamespaces
){
appId
=
namespace
.
getAppId
();
clusterName
=
namespace
.
getClusterName
();
namespaceName
=
namespace
.
getNamespaceName
();
env
=
namespace
.
getEnv
();
NamespaceDTO
namespaceDTO
=
null
;
try
{
namespaceDTO
=
namespaceAPI
.
loadNamespace
(
appId
,
env
,
clusterName
,
namespaceName
);
}
catch
(
NotFoundException
e
){
logger
.
warn
(
"namespace not exist. appId:{}, env:{}, clusterName:{}, namespaceName:{}"
,
appId
,
env
,
clusterName
,
namespaceName
);
throw
new
BadRequestException
(
String
.
format
(
"namespace not exist. appId:%s, env:%s, clusterName:%s, namespaceName:%s"
,
appId
,
env
,
clusterName
,
namespaceName
));
}
ItemDiffs
itemDiffs
=
new
ItemDiffs
(
namespace
);
ItemChangeSets
changeSets
=
new
ItemChangeSets
();
itemDiffs
.
setDiffs
(
changeSets
);
List
<
ItemDTO
>
targetItems
=
itemAPI
.
findItems
(
namespace
.
getAppId
(),
namespace
.
getEnv
(),
namespace
.
getClusterName
(),
namespace
.
getNamespaceName
());
long
namespaceId
=
namespaceDTO
.
getId
();
if
(
CollectionUtils
.
isEmpty
(
targetItems
)){
//all source items is added
int
lineNum
=
1
;
for
(
ItemDTO
sourceItem:
sourceItems
){
changeSets
.
addCreateItem
(
buildItem
(
namespaceId
,
lineNum
++,
sourceItem
));
}
}
else
{
Map
<
String
,
ItemDTO
>
keyMapItem
=
BeanUtils
.
mapByKey
(
"key"
,
targetItems
);
String
key
,
sourceValue
,
sourceComment
;
ItemDTO
targetItem
=
null
;
int
maxLineNum
=
targetItems
.
size
();
//append to last
for
(
ItemDTO
sourceItem:
sourceItems
){
key
=
sourceItem
.
getKey
();
sourceValue
=
sourceItem
.
getValue
();
sourceComment
=
sourceItem
.
getComment
();
targetItem
=
keyMapItem
.
get
(
key
);
if
(
targetItem
==
null
)
{
//added items
changeSets
.
addCreateItem
(
buildItem
(
namespaceId
,
++
maxLineNum
,
sourceItem
));
}
else
if
(!
sourceValue
.
equals
(
targetItem
.
getValue
())
||
!
sourceComment
.
equals
(
targetItem
.
getComment
())){
//modified items
targetItem
.
setValue
(
sourceValue
);
targetItem
.
setComment
(
sourceComment
);
changeSets
.
addUpdateItem
(
targetItem
);
}
}
}
result
.
add
(
itemDiffs
);
}
return
result
;
}
private
ItemDTO
buildItem
(
long
namespaceId
,
int
lineNum
,
ItemDTO
sourceItem
){
ItemDTO
createdItem
=
new
ItemDTO
();
BeanUtils
.
copyEntityProperties
(
sourceItem
,
createdItem
);
createdItem
.
setLineNum
(
lineNum
++);
createdItem
.
setNamespaceId
(
namespaceId
);
return
createdItem
;
}
}
apollo-portal/src/main/resources/application.yml
浏览文件 @
e8150525
...
...
@@ -17,4 +17,4 @@ ctrip:
apollo
:
portal
:
env
:
local
,dev
env
:
local
apollo-portal/src/main/resources/static/img/sync-error.png
0 → 100644
浏览文件 @
e8150525
4.1 KB
apollo-portal/src/main/resources/static/img/sync-succ.png
0 → 100644
浏览文件 @
e8150525
3.9 KB
apollo-portal/src/main/resources/static/img/sync.png
0 → 100644
浏览文件 @
e8150525
2.9 KB
apollo-portal/src/main/resources/static/index.html
浏览文件 @
e8150525
...
...
@@ -76,10 +76,14 @@
<!-- bootstrap.js -->
<script
src=
"vendor/bootstrap/js/bootstrap.min.js"
type=
"text/javascript"
></script>
<!--nicescroll-->
<script
src=
"vendor/jquery.nicescroll.min.js"
></script>
<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/AppUtils.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/controller/IndexController.js"
></script>
</body>
</html>
apollo-portal/src/main/resources/static/scripts/AppUtils.js
浏览文件 @
e8150525
appUtil
.
service
(
'
AppUtil
'
,
[
function
()
{
return
{
errorMsg
:
function
(
response
)
{
var
msg
=
"
Code:
"
+
response
.
status
;
if
(
response
.
data
.
message
!=
null
){
var
msg
=
"
Code:
"
+
response
.
status
;
if
(
response
.
data
.
message
!=
null
)
{
msg
+=
"
Msg:
"
+
response
.
data
.
message
;
}
return
msg
;
},
parseParams
:
function
(
path
)
{
if
(
!
path
)
{
return
{};
}
if
(
path
.
startsWith
(
"
/
"
))
{
path
=
path
.
substring
(
1
,
path
.
length
);
}
var
params
=
path
.
split
(
"
&
"
);
var
result
=
{};
params
.
forEach
(
function
(
param
)
{
var
kv
=
param
.
split
(
"
=
"
);
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
;
}
}
}]);
apollo-portal/src/main/resources/static/scripts/PageCommon.js
0 → 100644
浏览文件 @
e8150525
$
(
document
).
ready
(
function
()
{
$
(
"
html
"
).
niceScroll
({
styler
:
"
fb
"
,
cursorcolor
:
"
#e8403f
"
,
cursorwidth
:
'
6
'
,
cursorborderradius
:
'
10px
'
,
background
:
'
#404040
'
,
spacebarenabled
:
false
,
cursorborder
:
''
,
zindex
:
'
1000
'
});
});
apollo-portal/src/main/resources/static/scripts/app.js
浏览文件 @
e8150525
...
...
@@ -11,6 +11,8 @@ var index_module = angular.module('index', ['toastr', 'app.service', 'app.util',
var
application_module
=
angular
.
module
(
'
application
'
,
[
'
app.service
'
,
'
app.util
'
,
'
toastr
'
,
'
angular-loading-bar
'
]);
//创建项目页面
var
create_app_module
=
angular
.
module
(
'
create_app
'
,
[
'
ngResource
'
,
'
toastr
'
,
'
app.service
'
,
'
app.util
'
,
'
angular-loading-bar
'
]);
//配置同步页面
var
sync_item_module
=
angular
.
module
(
'
sync_item
'
,
[
'
app.service
'
,
'
app.util
'
,
'
toastr
'
,
'
angular-loading-bar
'
]);
...
...
apollo-portal/src/main/resources/static/scripts/controller/app/AppConfigController.js
浏览文件 @
e8150525
...
...
@@ -2,7 +2,8 @@ application_module.controller("AppConfigController",
[
'
$scope
'
,
'
$location
'
,
'
toastr
'
,
'
AppService
'
,
'
AppUtil
'
,
'
ConfigService
'
,
function
(
$scope
,
$location
,
toastr
,
AppService
,
AppUtil
,
ConfigService
)
{
var
appId
=
$location
.
$$url
.
split
(
"
=
"
)[
1
];
var
appId
=
AppUtil
.
parseParams
(
$location
.
$$url
).
appid
;
var
currentUser
=
'
test_user
'
;
var
pageContext
=
{
appId
:
appId
,
...
...
@@ -92,16 +93,17 @@ application_module.controller("AppConfigController",
//初始化视图
if
(
$scope
.
namespaces
)
{
$scope
.
namespaces
.
forEach
(
function
(
item
)
{
item
.
isModify
=
false
;
if
(
!
viewType
){
//default text view
if
(
!
viewType
)
{
//default text view
$scope
.
switchView
(
item
,
namespace_view_type
.
TEXT
);
}
else
if
(
viewType
==
namespace_view_type
.
TABLE
)
{
}
else
if
(
viewType
==
namespace_view_type
.
TABLE
)
{
item
.
viewType
=
namespace_view_type
.
TABLE
;
}
item
.
isTextEditing
=
false
;
})
})
;
}
},
function
(
result
)
{
...
...
@@ -122,10 +124,12 @@ application_module.controller("AppConfigController",
//把表格内容解析成文本
function
parseModel2Text
(
namespace
)
{
if
(
!
namespace
.
items
)
{
return
"
无配置信息
"
;
}
var
result
=
""
;
var
itemCnt
=
0
;
namespace
.
items
.
forEach
(
function
(
item
)
{
if
(
item
.
item
.
key
)
{
result
+=
...
...
@@ -133,9 +137,12 @@ application_module.controller("AppConfigController",
}
else
{
result
+=
item
.
item
.
comment
+
"
\n
"
;
}
itemCnt
++
;
});
itemCnt
>
30
?
30
:
itemCnt
;
itemCnt
<
9
?
8
:
itemCnt
;
namespace
.
itemCnt
=
itemCnt
+
3
;
return
result
;
}
...
...
@@ -183,14 +190,12 @@ application_module.controller("AppConfigController",
////// table view oper //////
//查看旧值
$scope
.
queryOldValue
=
function
(
key
,
oldValue
)
{
$scope
.
queryKey
=
key
;
if
(
oldValue
==
''
)
{
$scope
.
OldValue
=
key
+
"
是新添加的key
"
;
}
else
{
$scope
.
OldValue
=
oldValue
;
}
$scope
.
watch
=
{};
//查看配置
$scope
.
watchItem
=
function
(
key
,
value
,
oldValue
)
{
$scope
.
watch
.
key
=
key
;
$scope
.
watch
.
value
=
value
;
$scope
.
watch
.
oldValue
=
oldValue
;
};
/////// release ///////
...
...
@@ -251,7 +256,6 @@ application_module.controller("AppConfigController",
});
});
};
}]);
apollo-portal/src/main/resources/static/scripts/controller/app/SyncConfigController.js
0 → 100644
浏览文件 @
e8150525
sync_item_module
.
controller
(
"
SyncItemController
"
,
[
'
$scope
'
,
'
$location
'
,
'
toastr
'
,
'
AppService
'
,
'
AppUtil
'
,
'
ConfigService
'
,
function
(
$scope
,
$location
,
toastr
,
AppService
,
AppUtil
,
ConfigService
)
{
var
params
=
AppUtil
.
parseParams
(
$location
.
$$url
);
var
currentUser
=
'
test_user
'
;
$scope
.
pageContext
=
{
appId
:
params
.
appid
,
env
:
params
.
env
,
clusterName
:
params
.
clusterName
,
namespaceName
:
params
.
namespaceName
};
////// load env //////
AppService
.
load_nav_tree
(
$scope
.
pageContext
.
appId
).
then
(
function
(
result
)
{
$scope
.
clusters
=
result
.
nodes
;
$scope
.
clusters
=
[];
result
.
nodes
.
forEach
(
function
(
node
)
{
var
env
=
node
.
env
;
node
.
clusters
.
forEach
(
function
(
cluster
)
{
cluster
.
env
=
env
;
cluster
.
checked
=
false
;
$scope
.
clusters
.
push
(
cluster
);
})
});
},
function
(
result
)
{
toastr
.
error
(
AppUtil
.
errorMsg
(
result
),
"
加载环境出错
"
);
});
var
envAllSelected
=
false
;
$scope
.
toggleEnvsCheckedStatus
=
function
()
{
envAllSelected
=
!
envAllSelected
;
$scope
.
clusters
.
forEach
(
function
(
cluster
)
{
cluster
.
checked
=
envAllSelected
;
})
};
////// load items //////
ConfigService
.
find_items
(
$scope
.
pageContext
.
appId
,
$scope
.
pageContext
.
env
,
$scope
.
pageContext
.
clusterName
,
$scope
.
pageContext
.
namespaceName
).
then
(
function
(
result
)
{
$scope
.
sourceItems
=
result
;
$scope
.
sourceItems
.
forEach
(
function
(
item
)
{
item
.
checked
=
false
;
})
},
function
(
result
)
{
toastr
.
error
(
AppUtil
.
errorMsg
(
result
),
"
加载配置出错
"
);
});
var
itemAllSelected
=
false
;
$scope
.
toggleItemsCheckedStatus
=
function
()
{
itemAllSelected
=
!
itemAllSelected
;
$scope
.
sourceItems
.
forEach
(
function
(
item
)
{
item
.
checked
=
itemAllSelected
;
})
};
////// flow control ///////
$scope
.
syncItemStep
=
1
;
$scope
.
syncItemNextStep
=
function
(
offset
)
{
$scope
.
syncItemStep
+=
offset
;
};
$scope
.
syncItems
=
function
()
{
$scope
.
syncItemStep
+=
1
;
};
$scope
.
destorySync
=
function
()
{
$scope
.
syncItemStep
=
1
;
}
}]);
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
浏览文件 @
e8150525
appService
.
service
(
"
ConfigService
"
,
[
'
$resource
'
,
'
$q
'
,
function
(
$resource
,
$q
)
{
var
config_source
=
$resource
(
""
,
{},
{
load_all_
group
s
:
{
load_all_
namespace
s
:
{
method
:
'
GET
'
,
isArray
:
true
,
url
:
'
/apps/:appId/env/:env/clusters/:clusterName/namespaces
'
},
find_items
:{
method
:
'
GET
'
,
isArray
:
true
,
url
:
'
/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/items
'
},
modify_items
:
{
method
:
'
PUT
'
,
url
:
'
/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/items
'
...
...
@@ -18,7 +23,7 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
return
{
load_all_namespaces
:
function
(
appId
,
env
,
clusterName
)
{
var
d
=
$q
.
defer
();
config_source
.
load_all_
group
s
({
config_source
.
load_all_
namespace
s
({
appId
:
appId
,
env
:
env
,
clusterName
:
clusterName
...
...
@@ -29,6 +34,20 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
});
return
d
.
promise
;
},
find_items
:
function
(
appId
,
env
,
clusterName
,
namespaceName
)
{
var
d
=
$q
.
defer
();
config_source
.
find_items
({
appId
:
appId
,
env
:
env
,
clusterName
:
clusterName
,
namespaceName
:
namespaceName
},
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
d
.
reject
(
result
);
});
return
d
.
promise
;
},
modify_items
:
function
(
appId
,
env
,
clusterName
,
namespaceName
,
configText
,
namespaceId
,
comment
,
modifyBy
)
{
var
d
=
$q
.
defer
();
...
...
apollo-portal/src/main/resources/static/styles/common-style.css
浏览文件 @
e8150525
...
...
@@ -197,6 +197,10 @@ table th {
table-layout
:
fixed
;
}
.namespace-view-table
tr
{
cursor
:
pointer
;
}
.namespace-view-table
td
{
word-wrap
:
break-word
;
}
...
...
apollo-portal/src/main/resources/static/views/app.html
浏览文件 @
e8150525
...
...
@@ -65,7 +65,16 @@
</div>
</section>
<a
class=
"list-group-item"
data-toggle=
"modal"
data-target=
"#createEnvModal"
ng-show=
"missEnvs.length > 0"
>
<a
class=
"list-group-item"
data-toggle=
"modal"
data-target=
"#syncItems"
>
<div
class=
"row"
>
<div
class=
"col-md-2"
><img
src=
"../img/sync.png"
class=
"i-20"
></div>
<div
class=
"col-md-7 hidden-xs"
>
<p
class=
"apps-description"
>
配置同步
</p>
</div>
</div>
</a>
<a
class=
"list-group-item"
data-toggle=
"modal"
data-target=
"#createEnvModal"
ng-show=
"missEnvs.length > 0"
>
<div
class=
"row"
>
<div
class=
"col-md-2"
><img
src=
"../img/plus.png"
class=
"i-20"
></div>
<div
class=
"col-md-7 hidden-xs"
>
...
...
@@ -126,9 +135,10 @@
<button
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
>
授权
</button>
<button
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
>
克隆
</button>
<a
type=
"button"
target=
"_blank"
href=
"sync.html?#/appid={{pageContext.appId}}&env={{pageContext.env}}&clusterName={{pageContext.clusterName}}&namespaceName={{namespace.namespace.namespaceName}}"
class=
"btn btn-default btn-sm J_tableview_btn"
>
同步
</a>
</div>
</div>
<div
class=
"btn-group"
role=
"group"
aria-label=
"..."
>
...
...
@@ -169,7 +179,7 @@
</header>
<!--text view-->
<textarea
class=
"form-control"
rows=
"
30
"
<textarea
class=
"form-control"
rows=
"
{{namespace.itemCnt}}
"
ng-show=
"namespace.viewType == 'text'"
ng-disabled=
"!namespace.isTextEditing"
ng-model=
"namespace.text"
>
{{namespace.text}}
...
...
@@ -177,7 +187,7 @@
<!--table view-->
<div
class=
"namespace-view-table"
>
<table
class=
"table table-bordered text-center table-hover"
<table
class=
"table table-bordered t
able-striped t
ext-center table-hover"
ng-show=
"namespace.viewType == 'table'"
>
<thead>
<tr>
...
...
@@ -200,21 +210,16 @@
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.items"
ng-class=
"{warning:config.modified}"
ng-if=
"config.item.key"
>
<tr
title=
"点击查看"
data-toggle=
"modal"
data-target=
"#oldValueModal"
ng-repeat=
"config in namespace.items"
ng-class=
"{warning:config.modified}"
ng-if=
"config.item.key"
ng-click=
"watchItem(config.item.key, config.item.value, config.oldValue)"
>
<td
width=
"25%"
>
{{config.item.key}}
{{config.item.key
| limitTo: 20}} {{config.item.key.length > 20 ? '...' : ''
}}
</td>
<td
width=
"30%"
>
<button
data-placement=
"top"
title=
"查看旧值"
class=
"glyphicon glyphicon-eye-open"
aria-hidden=
"true"
data-toggle=
"modal"
data-target=
"#oldValueModal"
ng-show=
"config.modified"
ng-click=
"queryOldValue(config.item.key, config.oldValue)"
></button>
{{config.item.value}}
{{config.item.value | limitTo: 20}} {{config.item.value.length > 20 ? '...' : ''}}
</td>
<td
width=
"20%"
>
{{config.item.comment}}
{{config.item.comment
| limitTo: 20}} {{config.item.comment.length > 20 ? '...' : ''
}}
</td>
<td
width=
"10%"
>
{{config.item.lastModifiedBy}}
...
...
@@ -282,19 +287,22 @@
</div>
<!-- view old value Modal -->
<div
class=
"modal fade
"
id=
"oldValueModal"
tabindex=
"-1"
role=
"dialog"
>
<div
class=
"modal-dialog
modal-sm
"
role=
"document"
>
<div
class=
"modal fade"
id=
"oldValueModal"
tabindex=
"-1"
role=
"dialog"
>
<div
class=
"modal-dialog"
role=
"document"
>
<div
class=
"modal-content"
>
<div
class=
"modal-header panel-primary"
>
<button
type=
"button"
class=
"close"
data-dismiss=
"modal"
aria-label=
"Close"
><span
aria-hidden=
"true"
>
×
</span></button>
<h4
class=
"modal-title"
>
旧值
</h4>
<h4
class=
"modal-title"
>
{{watch.key}}
</h4>
</div>
<div
class=
"modal-body"
>
{{OldValue}}
<div
class=
"modal-body"
style=
"word-wrap: break-word;"
>
{{watch.value}}
<div
ng-show=
"watch.oldValue"
>
<hr>
老的值:{{watch.oldValue}}
</div>
</div>
<div
class=
"modal-footer"
>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
关闭
</button>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
Close
</button>
</div>
</div>
...
...
@@ -375,6 +383,8 @@
</div>
</div>
</div>
</div>
</div>
</div>
...
...
@@ -414,24 +424,7 @@
<!--controller-->
<script
type=
"application/javascript"
src=
"../scripts/controller/app/AppConfigController.js"
></script>
<script
type=
"application/javascript"
>
$
(
document
).
ready
(
function
()
{
$
(
"
html
"
).
niceScroll
({
styler
:
"
fb
"
,
cursorcolor
:
"
#e8403f
"
,
cursorwidth
:
'
6
'
,
cursorborderradius
:
'
10px
'
,
background
:
'
#404040
'
,
spacebarenabled
:
false
,
cursorborder
:
''
,
zindex
:
'
1000
'
});
});
$
(
function
()
{
$
(
'
[data-toggle="tooltip"]
'
).
tooltip
()
});
</script>
<script
type=
"application/javascript"
src=
"../scripts/PageCommon.js"
></script>
</body>
</html>
apollo-portal/src/main/resources/static/views/sync.html
0 → 100644
浏览文件 @
e8150525
<!doctype html>
<html
ng-app=
"sync_item"
>
<head>
<meta
http-equiv=
"Content-Type"
content=
"text/html; charset=UTF-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"
media=
'all'
href=
"../vendor/angular/loading-bar.min.css"
>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"../styles/common-style.css"
>
<title>
同步配置
</title>
</head>
<body
ng-controller=
"SyncItemController"
>
<div
ng-include=
"'common/nav.html'"
></div>
<div
class=
"container-fluid apollo-container"
>
<section
class=
"panel col-md-offset-1 col-md-10"
>
<header
class=
"panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-3"
>
<h4
class=
"modal-title"
>
同步配置
<small
ng-show=
"syncItemStep == 1"
>
(第一步:选择同步信息)
</small>
<small
ng-show=
"syncItemStep == 2"
>
(第二步:检查Diff)
</small>
</h4>
</div>
<div
class=
"col-md-9 text-right"
>
<button
type=
"button"
class=
"btn btn-primary"
ng-show=
"syncItemStep > 1 && syncItemStep < 3"
ng-click=
"syncItemNextStep(-1)"
>
上一步
</button>
<button
type=
"button"
class=
"btn btn-primary"
ng-show=
"syncItemStep < 2"
ng-click=
"syncItemNextStep(1)"
>
下一步
</button>
<button
type=
"button"
class=
"btn btn-success"
ng-show=
"syncItemStep == 2"
ng-click=
"syncItems()"
>
同步
</button>
<button
type=
"button"
class=
"btn btn-primary"
data-dismiss=
"modal"
ng-show=
"syncItemStep == 3"
ng-click=
"destorySync()"
>
返回
</button>
</div>
</div>
</header>
<div
class=
"panel-body"
>
<div
class=
"row"
ng-show=
"syncItemStep == 1"
>
<div
class=
"form-horizontal"
>
<div
class=
"form-group"
>
<label
class=
"col-sm-2 control-label"
>
同步到那个集群
</label>
<div
class=
"col-sm-6"
>
<table
class=
"table table-hover"
>
<thead>
<tr>
<td><input
type=
"checkbox"
ng-click=
"toggleEnvsCheckedStatus()"
></td>
</td>
<td>
环境
</td>
<td>
集群
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"cluster in clusters"
>
<td
width=
"10%"
><input
type=
"checkbox"
ng-checked=
"cluster.checked"
></td>
<td
width=
"30%"
>
{{cluster.env}}
</td>
<td
width=
"60%"
>
{{cluster.name}}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<hr>
</div>
<div
class=
"row"
ng-show=
"syncItemStep == 1"
style=
"margin-top: 10px;"
>
<div
class=
"form-horizontal"
>
<div
class=
"col-sm-2 text-right"
>
<label
class=
"control-label"
>
需要同步的配置
</label>
</div>
<div
class=
"col-sm-10"
>
<table
class=
"table table-bordered table-striped table-hover"
>
<thead>
<tr>
<td><input
type=
"checkbox"
ng-click=
"toggleItemsCheckedStatus()"
></td>
<td>
key
</td>
<td>
value
</td>
<td>
comment
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"item in sourceItems"
>
<td
width=
"10%"
><input
type=
"checkbox"
ng-checked=
"item.checked"
></td>
<td
width=
"20%"
>
{{item.key}}
</td>
<td
width=
"50%"
>
{{item.value | limitTo: 36}} {{item.value.length > 36 ? '...' : ''}}
</td>
<td
width=
"20%"
>
{{item.comment | limitTo: 15}}{{item.comment.length > 15 ? '...' : ''}}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!--step 2-->
<div
class=
"row"
ng-show=
"syncItemStep == 2"
>
<h4
class=
"text-center"
>
环境:fat 集群:default
</h4>
<hr>
<div
class=
"row"
style=
"margin-top: 10px;"
>
<div
class=
"form-horizontal"
>
<label
class=
"col-sm-2 control-label"
>
新增的配置
</label>
<div
class=
"col-sm-9"
>
<table
class=
"table table-bordered table-hover"
>
<thead>
<tr>
<td>
key
</td>
<td>
value
</td>
</tr>
</thead>
<tbody>
<tr>
<td
width=
"30%"
>
k1
</td>
<td
width=
"60%"
>
v1
</td>
</tr>
<tr>
<td
width=
"30%"
>
k1
</td>
<td
width=
"60%"
>
v1
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div
class=
"row"
ng-show=
"syncItemStep == 2"
>
<div
class=
"row"
style=
"margin-top: 10px;"
>
<div
class=
"form-horizontal"
>
<label
class=
"col-sm-2 control-label"
>
更新的配置
</label>
<div
class=
"col-sm-9"
>
<table
class=
"table table-bordered table-striped table-hover"
>
<thead>
<tr>
<td>
key
</td>
<td>
value
</td>
</tr>
</thead>
<tbody>
<tr>
<td
width=
"30%"
>
k1
</td>
<td
width=
"60%"
>
v1
</td>
</tr>
<tr>
<td
width=
"30%"
>
k1
</td>
<td
width=
"60%"
>
v1
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!--step 3-->
<div
class=
"row text-center"
ng-show=
"syncItemStep == 3"
>
<img
src=
"../img/sync-succ.png"
style=
"height: 100px; width: 100px"
>
<h3>
同步成功!
</h3>
</div>
</div>
</section>
</div>
<div
ng-include=
"'common/footer.html'"
></div>
<!--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>
<!-- jquery.js -->
<script
src=
"../vendor/jquery.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>
<!--biz-->
<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/ConfigService.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/AppUtils.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/controller/app/SyncConfigController.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/PageCommon.js"
></script>
</body>
</html>
apollo-portal/src/test/java/com/ctrip/apollo/portal/ConfigServiceTest.java
浏览文件 @
e8150525
package
com.ctrip.apollo.portal
;
import
com.ctrip.apollo.core.ConfigConsts
;
import
com.ctrip.apollo.core.dto.ItemChangeSets
;
import
com.ctrip.apollo.core.dto.ItemDTO
;
import
com.ctrip.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.apollo.core.dto.ReleaseDTO
;
import
com.ctrip.apollo.core.enums.Env
;
import
com.ctrip.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.apollo.portal.entity.ItemDiffs
;
import
com.ctrip.apollo.portal.entity.NamespaceIdentifer
;
import
com.ctrip.apollo.portal.entity.NamespaceVO
;
import
com.ctrip.apollo.portal.entity.form.NamespaceTextModel
;
import
com.ctrip.apollo.portal.service.ConfigService
;
...
...
@@ -127,4 +130,110 @@ public class ConfigServiceTest {
return
Arrays
.
asList
(
item1
,
item2
,
item3
);
}
@Test
public
void
testCompareTargetNamespaceHasNoItems
(){
ItemDTO
sourceItem1
=
new
ItemDTO
(
"a"
,
"b"
,
"comment"
,
1
);
List
<
ItemDTO
>
sourceItems
=
Arrays
.
asList
(
sourceItem1
);
String
appId
=
"6666"
,
env
=
"LOCAL"
,
clusterName
=
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
namespaceName
=
ConfigConsts
.
NAMESPACE_DEFAULT
;
List
<
NamespaceIdentifer
>
namespaceIdentifers
=
generateNamespaceIdentifer
(
appId
,
env
,
clusterName
,
namespaceName
);
NamespaceDTO
namespaceDTO
=
generateNamespaceDTO
(
appId
,
clusterName
,
namespaceName
);
when
(
namespaceAPI
.
loadNamespace
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
)).
thenReturn
(
namespaceDTO
);
when
(
itemAPI
.
findItems
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
)).
thenReturn
(
null
);
List
<
ItemDiffs
>
itemDiffses
=
configService
.
compare
(
sourceItems
,
namespaceIdentifers
);
assertEquals
(
1
,
itemDiffses
.
size
());
ItemDiffs
itemDiffs
=
itemDiffses
.
get
(
0
);
ItemChangeSets
changeSets
=
itemDiffs
.
getDiffs
();
assertEquals
(
0
,
changeSets
.
getUpdateItems
().
size
());
assertEquals
(
0
,
changeSets
.
getDeleteItems
().
size
());
List
<
ItemDTO
>
createItems
=
changeSets
.
getCreateItems
();
ItemDTO
createItem
=
createItems
.
get
(
0
);
assertEquals
(
1
,
createItem
.
getLineNum
());
assertEquals
(
"a"
,
createItem
.
getKey
());
assertEquals
(
"b"
,
createItem
.
getValue
());
assertEquals
(
"comment"
,
createItem
.
getComment
());
}
@Test
public
void
testCompare
(){
ItemDTO
sourceItem1
=
new
ItemDTO
(
"a"
,
"b"
,
"comment"
,
1
);
//not modified
ItemDTO
sourceItem2
=
new
ItemDTO
(
"newKey"
,
"c"
,
"comment"
,
2
);
//new item
ItemDTO
sourceItem3
=
new
ItemDTO
(
"c"
,
"newValue"
,
"comment"
,
3
);
// update value
ItemDTO
sourceItem4
=
new
ItemDTO
(
"d"
,
"b"
,
"newComment"
,
4
);
// update comment
List
<
ItemDTO
>
sourceItems
=
Arrays
.
asList
(
sourceItem1
,
sourceItem2
,
sourceItem3
,
sourceItem4
);
ItemDTO
targetItem1
=
new
ItemDTO
(
"a"
,
"b"
,
"comment"
,
1
);
ItemDTO
targetItem2
=
new
ItemDTO
(
"c"
,
"oldValue"
,
"comment"
,
2
);
ItemDTO
targetItem3
=
new
ItemDTO
(
"d"
,
"b"
,
"oldComment"
,
3
);
List
<
ItemDTO
>
targetItems
=
Arrays
.
asList
(
targetItem1
,
targetItem2
,
targetItem3
);
String
appId
=
"6666"
,
env
=
"LOCAL"
,
clusterName
=
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
namespaceName
=
ConfigConsts
.
NAMESPACE_DEFAULT
;
List
<
NamespaceIdentifer
>
namespaceIdentifers
=
generateNamespaceIdentifer
(
appId
,
env
,
clusterName
,
namespaceName
);
NamespaceDTO
namespaceDTO
=
generateNamespaceDTO
(
appId
,
clusterName
,
namespaceName
);
when
(
namespaceAPI
.
loadNamespace
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
)).
thenReturn
(
namespaceDTO
);
when
(
itemAPI
.
findItems
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
)).
thenReturn
(
targetItems
);
List
<
ItemDiffs
>
itemDiffses
=
configService
.
compare
(
sourceItems
,
namespaceIdentifers
);
assertEquals
(
1
,
itemDiffses
.
size
());
ItemDiffs
itemDiffs
=
itemDiffses
.
get
(
0
);
ItemChangeSets
changeSets
=
itemDiffs
.
getDiffs
();
assertEquals
(
0
,
changeSets
.
getDeleteItems
().
size
());
assertEquals
(
2
,
changeSets
.
getUpdateItems
().
size
());
assertEquals
(
1
,
changeSets
.
getCreateItems
().
size
());
NamespaceIdentifer
namespaceIdentifer
=
itemDiffs
.
getNamespace
();
assertEquals
(
appId
,
namespaceIdentifer
.
getAppId
());
assertEquals
(
Env
.
valueOf
(
"LOCAL"
),
namespaceIdentifer
.
getEnv
());
assertEquals
(
clusterName
,
namespaceIdentifer
.
getClusterName
());
assertEquals
(
namespaceName
,
namespaceIdentifer
.
getNamespaceName
());
ItemDTO
createdItem
=
changeSets
.
getCreateItems
().
get
(
0
);
assertEquals
(
"newKey"
,
createdItem
.
getKey
());
assertEquals
(
"c"
,
createdItem
.
getValue
());
assertEquals
(
"comment"
,
createdItem
.
getComment
());
assertEquals
(
4
,
createdItem
.
getLineNum
());
List
<
ItemDTO
>
updateItems
=
changeSets
.
getUpdateItems
();
ItemDTO
updateItem1
=
updateItems
.
get
(
0
);
ItemDTO
updateItem2
=
updateItems
.
get
(
1
);
assertEquals
(
"c"
,
updateItem1
.
getKey
());
assertEquals
(
"newValue"
,
updateItem1
.
getValue
());
assertEquals
(
"comment"
,
updateItem1
.
getComment
());
assertEquals
(
2
,
updateItem1
.
getLineNum
());
assertEquals
(
"d"
,
updateItem2
.
getKey
());
assertEquals
(
"b"
,
updateItem2
.
getValue
());
assertEquals
(
"newComment"
,
updateItem2
.
getComment
());
assertEquals
(
3
,
updateItem2
.
getLineNum
());
}
private
NamespaceDTO
generateNamespaceDTO
(
String
appId
,
String
clusterName
,
String
namespaceName
){
NamespaceDTO
namespaceDTO
=
new
NamespaceDTO
();
namespaceDTO
.
setAppId
(
appId
);
namespaceDTO
.
setId
(
1
);
namespaceDTO
.
setClusterName
(
clusterName
);
namespaceDTO
.
setNamespaceName
(
namespaceName
);
return
namespaceDTO
;
}
private
List
<
NamespaceIdentifer
>
generateNamespaceIdentifer
(
String
appId
,
String
env
,
String
clusterName
,
String
namespaceName
){
NamespaceIdentifer
targetNamespace
=
new
NamespaceIdentifer
();
targetNamespace
.
setAppId
(
appId
);
targetNamespace
.
setEnv
(
env
);
targetNamespace
.
setClusterName
(
clusterName
);
targetNamespace
.
setNamespaceName
(
namespaceName
);
return
Arrays
.
asList
(
targetNamespace
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录