Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wrr-cat
apollo
提交
7a27efe2
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,发现更多精彩内容 >>
提交
7a27efe2
编写于
5月 04, 2016
作者:
J
Jason Song
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #167 from lepdou/lepdou_master
配置namespace之间同步
上级
47c4cd25
472f42bb
变更
11
显示空白变更内容
内联
并排
Showing
11 changed file
with
260 addition
and
149 deletion
+260
-149
apollo-adminservice/src/test/resources/data.sql
apollo-adminservice/src/test/resources/data.sql
+2
-1
apollo-portal/pom.xml
apollo-portal/pom.xml
+1
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/ConfigController.java
.../com/ctrip/apollo/portal/controller/ConfigController.java
+16
-1
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/NamespaceIdentifer.java
...va/com/ctrip/apollo/portal/entity/NamespaceIdentifer.java
+10
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/ConfigService.java
...n/java/com/ctrip/apollo/portal/service/ConfigService.java
+90
-73
apollo-portal/src/main/resources/static/scripts/AppUtils.js
apollo-portal/src/main/resources/static/scripts/AppUtils.js
+1
-1
apollo-portal/src/main/resources/static/scripts/controller/app/SyncConfigController.js
...ces/static/scripts/controller/app/SyncConfigController.js
+57
-17
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
...c/main/resources/static/scripts/services/ConfigService.js
+34
-0
apollo-portal/src/main/resources/static/views/app.html
apollo-portal/src/main/resources/static/views/app.html
+0
-8
apollo-portal/src/main/resources/static/views/sync.html
apollo-portal/src/main/resources/static/views/sync.html
+47
-46
apollo-portal/src/test/java/com/ctrip/apollo/portal/ConfigServiceTest.java
.../test/java/com/ctrip/apollo/portal/ConfigServiceTest.java
+2
-2
未找到文件。
apollo-adminservice/src/test/resources/data.sql
浏览文件 @
7a27efe2
...
...
@@ -20,6 +20,7 @@ INSERT INTO AppNamespace (AppId, Name) VALUES ('100003173', 'fx.apollo.portal');
INSERT
INTO
AppNamespace
(
AppID
,
Name
)
VALUES
(
'fxhermesproducer'
,
'fx.hermes.producer'
);
INSERT
INTO
Namespace
(
Id
,
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
1
,
'100003171'
,
'default'
,
'application'
);
INSERT
INTO
Namespace
(
Id
,
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
5
,
'100003171'
,
'cluster1'
,
'application'
);
INSERT
INTO
Namespace
(
Id
,
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
2
,
'fxhermesproducer'
,
'default'
,
'fx.hermes.producer'
);
INSERT
INTO
Namespace
(
Id
,
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
3
,
'100003172'
,
'default'
,
'application'
);
INSERT
INTO
Namespace
(
Id
,
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
4
,
'100003173'
,
'default'
,
'application'
);
...
...
@@ -27,7 +28,7 @@ INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (4, '100003
INSERT
INTO
Item
(
NamespaceId
,
`Key`
,
Value
,
Comment
)
VALUES
(
1
,
'k1'
,
'v1'
,
'comment1'
);
INSERT
INTO
Item
(
NamespaceId
,
`Key`
,
Value
,
Comment
)
VALUES
(
1
,
'k2'
,
'v2'
,
'comment2'
);
INSERT
INTO
Item
(
NamespaceId
,
`Key`
,
Value
,
Comment
)
VALUES
(
2
,
'k3'
,
'v3'
,
'comment3'
);
INSERT
INTO
Item
(
NamespaceId
,
`Key`
,
Value
,
Comment
)
VALUES
(
5
,
'k3'
,
'v4'
,
'comment4'
);
INSERT
INTO
Item
(
NamespaceId
,
`Key`
,
Value
,
Comment
,
LineNum
)
VALUES
(
5
,
'k1'
,
'v4'
,
'comment4'
,
1
);
INSERT
INTO
RELEASE
(
ReleaseKey
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
'TEST-RELEASE-KEY'
,
'REV1'
,
'First Release'
,
'100003171'
,
'default'
,
'application'
,
'{"k1":"v1"}'
);
apollo-portal/pom.xml
浏览文件 @
7a27efe2
...
...
@@ -24,6 +24,7 @@
<scope>
test
</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/ConfigController.java
浏览文件 @
7a27efe2
...
...
@@ -14,6 +14,8 @@ import com.ctrip.apollo.portal.entity.form.NamespaceReleaseModel;
import
com.ctrip.apollo.portal.service.ConfigService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
...
...
@@ -102,7 +104,20 @@ public class ConfigController {
throw
new
BadRequestException
(
"request model is invalid"
);
}
return
configService
.
compare
(
model
.
getSyncItems
(),
model
.
getSyncToNamespaces
());
return
configService
.
compare
(
model
.
getSyncToNamespaces
(),
model
.
getSyncItems
());
}
@RequestMapping
(
value
=
"/namespaces/{namespaceName}/items"
,
method
=
RequestMethod
.
PUT
,
consumes
=
{
"application/json"
})
public
ResponseEntity
<
Void
>
update
(
@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"
);
}
configService
.
syncItems
(
model
.
getSyncToNamespaces
(),
model
.
getSyncItems
());
return
ResponseEntity
.
status
(
HttpStatus
.
OK
).
build
();
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/NamespaceIdentifer.java
浏览文件 @
7a27efe2
...
...
@@ -47,4 +47,14 @@ public class NamespaceIdentifer implements Verifiable{
public
boolean
isInvalid
()
{
return
StringUtils
.
isContainEmpty
(
env
,
clusterName
,
namespaceName
);
}
@Override
public
String
toString
()
{
return
"NamespaceIdentifer{"
+
"appId='"
+
appId
+
'\''
+
", env='"
+
env
+
'\''
+
", clusterName='"
+
clusterName
+
'\''
+
", namespaceName='"
+
namespaceName
+
'\''
+
'}'
;
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/ConfigService.java
浏览文件 @
7a27efe2
...
...
@@ -54,11 +54,6 @@ public class ConfigService {
/**
* load cluster all namespace info with items
*
* @param appId
* @param env
* @param clusterName
* @return
*/
public
List
<
NamespaceVO
>
findNampspaces
(
String
appId
,
Env
env
,
String
clusterName
)
{
...
...
@@ -100,10 +95,10 @@ public class ConfigService {
try
{
release
=
releaseAPI
.
loadLatestRelease
(
appId
,
env
,
clusterName
,
namespaceName
);
releaseItems
=
gson
.
fromJson
(
release
.
getConfigurations
(),
Map
.
class
);
}
catch
(
HttpClientErrorException
e
)
{
if
(
e
.
getStatusCode
()
==
HttpStatus
.
NOT_FOUND
){
}
catch
(
HttpClientErrorException
e
)
{
if
(
e
.
getStatusCode
()
==
HttpStatus
.
NOT_FOUND
)
{
logger
.
warn
(
ExceptionUtils
.
toString
(
e
));
}
else
{
}
else
{
throw
e
;
}
}
...
...
@@ -155,7 +150,7 @@ public class ConfigService {
ItemChangeSets
changeSets
=
resolver
.
resolve
(
namespaceId
,
configText
,
itemAPI
.
findItems
(
appId
,
env
,
clusterName
,
namespaceName
));
if
(
changeSets
.
isEmpty
()){
if
(
changeSets
.
isEmpty
())
{
return
;
}
try
{
...
...
@@ -171,61 +166,85 @@ public class ConfigService {
/**
* createRelease config items
*
* @return
*/
public
ReleaseDTO
createRelease
(
NamespaceReleaseModel
model
)
{
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
){
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
){
public
void
syncItems
(
List
<
NamespaceIdentifer
>
comparedNamespaces
,
List
<
ItemDTO
>
sourceItems
){
List
<
ItemDiffs
>
itemDiffs
=
compare
(
comparedNamespaces
,
sourceItems
);
for
(
ItemDiffs
itemDiff:
itemDiffs
){
NamespaceIdentifer
namespaceIdentifer
=
itemDiff
.
getNamespace
();
try
{
itemAPI
.
updateItems
(
namespaceIdentifer
.
getAppId
(),
namespaceIdentifer
.
getEnv
(),
namespaceIdentifer
.
getClusterName
(),
namespaceIdentifer
.
getNamespaceName
(),
itemDiff
.
getDiffs
());
}
catch
(
HttpClientErrorException
e
)
{
logger
.
error
(
"sync items error. namespace:{}"
,
namespaceIdentifer
);
throw
new
ServiceException
(
String
.
format
(
"sync item error. env:%s, clusterName:%s"
,
namespaceIdentifer
.
getEnv
(),
namespaceIdentifer
.
getClusterName
()),
e
);
}
}
}
public
List
<
ItemDiffs
>
compare
(
List
<
NamespaceIdentifer
>
comparedNamespaces
,
List
<
ItemDTO
>
sourceItems
)
{
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
();
for
(
NamespaceIdentifer
namespace
:
comparedNamespaces
)
{
ItemDiffs
itemDiffs
=
new
ItemDiffs
(
namespace
);
itemDiffs
.
setDiffs
(
parseChangeSets
(
namespace
,
sourceItems
));
result
.
add
(
itemDiffs
);
}
return
result
;
}
private
long
getNamespaceId
(
NamespaceIdentifer
namespaceIdentifer
)
{
String
appId
=
namespaceIdentifer
.
getAppId
();
String
clusterName
=
namespaceIdentifer
.
getClusterName
();
String
namespaceName
=
namespaceIdentifer
.
getNamespaceName
();
Env
env
=
namespaceIdentifer
.
getEnv
();
NamespaceDTO
namespaceDTO
=
null
;
try
{
namespaceDTO
=
namespaceAPI
.
loadNamespace
(
appId
,
env
,
clusterName
,
namespaceName
);
}
catch
(
NotFoundException
e
)
{
}
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
));
}
return
namespaceDTO
.
getId
();
}
ItemDiffs
itemDiffs
=
new
ItemDiffs
(
namespace
);
private
ItemChangeSets
parseChangeSets
(
NamespaceIdentifer
namespace
,
List
<
ItemDTO
>
sourceItems
){
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
long
namespaceId
=
getNamespaceId
(
namespace
);
if
(
CollectionUtils
.
isEmpty
(
targetItems
))
{
//all source items is added
int
lineNum
=
1
;
for
(
ItemDTO
sourceItem:
sourceItems
)
{
for
(
ItemDTO
sourceItem
:
sourceItems
)
{
changeSets
.
addCreateItem
(
buildItem
(
namespaceId
,
lineNum
++,
sourceItem
));
}
}
else
{
}
else
{
Map
<
String
,
ItemDTO
>
keyMapItem
=
BeanUtils
.
mapByKey
(
"key"
,
targetItems
);
String
key
,
sourceValue
,
sourceComment
;
String
key
,
sourceValue
,
sourceComment
;
ItemDTO
targetItem
=
null
;
int
maxLineNum
=
targetItems
.
size
();
//append to last
for
(
ItemDTO
sourceItem:
sourceItems
)
{
for
(
ItemDTO
sourceItem
:
sourceItems
)
{
key
=
sourceItem
.
getKey
();
sourceValue
=
sourceItem
.
getValue
();
sourceComment
=
sourceItem
.
getComment
();
...
...
@@ -235,7 +254,8 @@ public class ConfigService {
changeSets
.
addCreateItem
(
buildItem
(
namespaceId
,
++
maxLineNum
,
sourceItem
));
}
else
if
(!
sourceValue
.
equals
(
targetItem
.
getValue
())
||
!
sourceComment
.
equals
(
targetItem
.
getComment
())){
//modified items
}
else
if
(!
sourceValue
.
equals
(
targetItem
.
getValue
())
||
!
sourceComment
.
equals
(
targetItem
.
getComment
()))
{
//modified items
targetItem
.
setValue
(
sourceValue
);
targetItem
.
setComment
(
sourceComment
);
changeSets
.
addUpdateItem
(
targetItem
);
...
...
@@ -243,13 +263,10 @@ public class ConfigService {
}
}
result
.
add
(
itemDiffs
);
}
return
result
;
return
changeSets
;
}
private
ItemDTO
buildItem
(
long
namespaceId
,
int
lineNum
,
ItemDTO
sourceItem
){
private
ItemDTO
buildItem
(
long
namespaceId
,
int
lineNum
,
ItemDTO
sourceItem
)
{
ItemDTO
createdItem
=
new
ItemDTO
();
BeanUtils
.
copyEntityProperties
(
sourceItem
,
createdItem
);
createdItem
.
setLineNum
(
lineNum
++);
...
...
apollo-portal/src/main/resources/static/scripts/AppUtils.js
浏览文件 @
7a27efe2
...
...
@@ -12,7 +12,7 @@ appUtil.service('AppUtil', [function () {
if
(
!
path
)
{
return
{};
}
if
(
path
.
startsWith
(
"
/
"
)
)
{
if
(
path
.
indexOf
(
'
/
'
)
==
0
)
{
path
=
path
.
substring
(
1
,
path
.
length
);
}
var
params
=
path
.
split
(
"
&
"
);
...
...
apollo-portal/src/main/resources/static/scripts/controller/app/SyncConfigController.js
浏览文件 @
7a27efe2
sync_item_module
.
controller
(
"
SyncItemController
"
,
[
'
$scope
'
,
'
$location
'
,
'
toastr
'
,
'
AppService
'
,
'
AppUtil
'
,
'
ConfigService
'
,
function
(
$scope
,
$location
,
toastr
,
AppService
,
AppUtil
,
ConfigService
)
{
[
'
$scope
'
,
'
$location
'
,
'
$window
'
,
'
toastr
'
,
'
AppService
'
,
'
AppUtil
'
,
'
ConfigService
'
,
function
(
$scope
,
$location
,
$window
,
toastr
,
AppService
,
AppUtil
,
ConfigService
)
{
var
params
=
AppUtil
.
parseParams
(
$location
.
$$url
);
var
currentUser
=
'
test_user
'
;
...
...
@@ -13,14 +13,15 @@ sync_item_module.controller("SyncItemController",
////// load env //////
AppService
.
load_nav_tree
(
$scope
.
pageContext
.
appId
).
then
(
function
(
result
)
{
$scope
.
clusters
=
result
.
nodes
;
$scope
.
clusters
=
[];
$scope
.
namespaceIdentifers
=
[];
result
.
nodes
.
forEach
(
function
(
node
)
{
var
env
=
node
.
env
;
node
.
clusters
.
forEach
(
function
(
cluster
)
{
cluster
.
env
=
env
;
cluster
.
checked
=
false
;
$scope
.
clusters
.
push
(
cluster
);
if
(
env
!=
$scope
.
pageContext
.
env
||
cluster
.
name
!=
$scope
.
pageContext
.
clusterName
){
$scope
.
namespaceIdentifers
.
push
(
cluster
);
}
})
});
},
function
(
result
)
{
...
...
@@ -30,8 +31,8 @@ sync_item_module.controller("SyncItemController",
var
envAllSelected
=
false
;
$scope
.
toggleEnvsCheckedStatus
=
function
()
{
envAllSelected
=
!
envAllSelected
;
$scope
.
clusters
.
forEach
(
function
(
clust
er
)
{
clust
er
.
checked
=
envAllSelected
;
$scope
.
namespaceIdentifers
.
forEach
(
function
(
namespaceIdentif
er
)
{
namespaceIdentif
er
.
checked
=
envAllSelected
;
})
};
...
...
@@ -39,9 +40,12 @@ sync_item_module.controller("SyncItemController",
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
)
{
$scope
.
sourceItems
=
[];
result
.
forEach
(
function
(
item
)
{
if
(
item
.
key
){
item
.
checked
=
false
;
$scope
.
sourceItems
.
push
(
item
);
}
})
},
function
(
result
)
{
...
...
@@ -56,6 +60,44 @@ sync_item_module.controller("SyncItemController",
})
};
$scope
.
diff
=
function
()
{
ConfigService
.
diff
(
$scope
.
pageContext
.
namespaceName
,
parseSyncSourceData
()).
then
(
function
(
result
)
{
$scope
.
diffs
=
result
;
$scope
.
syncItemNextStep
(
1
);
},
function
(
result
)
{
toastr
.
error
(
AppUtil
.
errorMsg
(
result
));
});
};
$scope
.
syncItems
=
function
()
{
ConfigService
.
sync_items
(
$scope
.
pageContext
.
namespaceName
,
parseSyncSourceData
()).
then
(
function
(
result
)
{
$scope
.
syncItemStep
+=
1
;
},
function
(
result
)
{
toastr
.
error
(
AppUtil
.
errorMsg
(
result
));
});
};
function
parseSyncSourceData
()
{
var
sourceData
=
{
syncToNamespaces
:
[],
syncItems
:
[]
};
var
namespaceName
=
$scope
.
pageContext
.
namespaceName
;
$scope
.
namespaceIdentifers
.
forEach
(
function
(
namespaceIdentifer
)
{
if
(
namespaceIdentifer
.
checked
){
namespaceIdentifer
.
clusterName
=
namespaceIdentifer
.
name
;
namespaceIdentifer
.
namespaceName
=
namespaceName
;
sourceData
.
syncToNamespaces
.
push
(
namespaceIdentifer
);
}
});
$scope
.
sourceItems
.
forEach
(
function
(
item
)
{
if
(
item
.
checked
)
{
sourceData
.
syncItems
.
push
(
item
);
}
});
return
sourceData
;
}
////// flow control ///////
$scope
.
syncItemStep
=
1
;
...
...
@@ -63,14 +105,12 @@ sync_item_module.controller("SyncItemController",
$scope
.
syncItemStep
+=
offset
;
};
$scope
.
syncItems
=
function
()
{
$
scope
.
syncItemStep
+=
1
;
$scope
.
backToAppHomePage
=
function
()
{
$
window
.
location
.
href
=
'
/views/app.html?#appid=
'
+
$scope
.
pageContext
.
appId
;
};
$scope
.
destorySync
=
function
(
)
{
$scope
.
syncItemStep
=
1
;
$scope
.
switchSelect
=
function
(
o
)
{
o
.
checked
=
!
o
.
checked
;
}
}]);
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
浏览文件 @
7a27efe2
...
...
@@ -17,6 +17,16 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
release
:
{
method
:
'
POST
'
,
url
:
'
/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/release
'
},
diff
:
{
method
:
'
POST
'
,
url
:
'
/namespaces/:namespaceName/diff
'
,
isArray
:
true
},
sync_item
:
{
method
:
'
PUT
'
,
url
:
'
/namespaces/:namespaceName/items
'
,
isArray
:
false
}
});
...
...
@@ -87,6 +97,30 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
d
.
reject
(
result
);
});
return
d
.
promise
;
},
diff
:
function
(
namespaceName
,
sourceData
)
{
var
d
=
$q
.
defer
();
config_source
.
diff
({
namespaceName
:
namespaceName
},
sourceData
,
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
d
.
reject
(
result
);
});
return
d
.
promise
;
},
sync_items
:
function
(
namespaceName
,
sourceData
)
{
var
d
=
$q
.
defer
();
config_source
.
sync_item
({
namespaceName
:
namespaceName
},
sourceData
,
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
d
.
reject
(
result
);
});
return
d
.
promise
;
}
}
...
...
apollo-portal/src/main/resources/static/views/app.html
浏览文件 @
7a27efe2
...
...
@@ -65,14 +65,6 @@
</div>
</section>
<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"
>
...
...
apollo-portal/src/main/resources/static/views/sync.html
浏览文件 @
7a27efe2
...
...
@@ -29,12 +29,12 @@
ng-click=
"syncItemNextStep(-1)"
>
上一步
</button>
<button
type=
"button"
class=
"btn btn-primary"
ng-show=
"syncItemStep < 2"
ng-click=
"
syncItemNextStep(1
)"
>
下一步
ng-click=
"
diff(
)"
>
下一步
</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
()"
>
返回
ng-click=
"
backToAppHomePage
()"
>
返回
</button>
</div>
</div>
...
...
@@ -55,10 +55,11 @@
</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
ng-repeat=
"namespaceIdentifer in namespaceIdentifers"
>
<td
width=
"10%"
><input
type=
"checkbox"
ng-checked=
"namespaceIdentifer.checked"
ng-click=
"switchSelect(namespaceIdentifer)"
></td>
<td
width=
"30%"
>
{{namespaceIdentifer.env}}
</td>
<td
width=
"60%"
>
{{namespaceIdentifer.name}}
</td>
</tr>
</tbody>
</table>
...
...
@@ -85,10 +86,14 @@
</thead>
<tbody>
<tr
ng-repeat=
"item in sourceItems"
>
<td
width=
"10%"
><input
type=
"checkbox"
ng-checked=
"item.checked"
></td>
<td
width=
"10%"
><input
type=
"checkbox"
ng-checked=
"item.checked"
ng-click=
"switchSelect(item)"
></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>
<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>
...
...
@@ -99,28 +104,29 @@
</div>
<!--step 2-->
<div
class=
"row"
ng-show=
"syncItemStep == 2"
>
<h4
class=
"text-center"
>
环境:
fat 集群:default
</h4>
<div
class=
"row"
ng-show=
"syncItemStep == 2"
ng-repeat=
"diff in diffs"
>
<h4
class=
"text-center"
>
环境:
{{diff.namespace.env}} 集群:{{diff.namespace.clusterName}}
</h4>
<hr>
<div
class=
"row"
style=
"margin-top: 10px;"
>
<div
class=
"row text-center"
style=
"margin-top: 10px;"
ng-show=
"diff.diffs.createItems.length == 0 && diff.diffs.updateItems.length == 0"
>
<h5>
无更新的配置
</h5>
</div>
<div
class=
"row"
style=
"margin-top: 10px;"
ng-show=
"diff.diffs.createItems.length > 0"
>
<div
class=
"form-horizontal"
>
<label
class=
"col-sm-2 control-label"
>
新增的配置
</label>
<div
class=
"col-sm-9"
>
<table
class=
"table table-bordered table-hover"
>
<table
class=
"table table-bordered table-
striped table-
hover"
>
<thead>
<tr>
<td>
key
</td>
<td>
value
</td>
<td>
comment
</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
ng-repeat=
"createItem in diff.diffs.createItems"
>
<td
width=
"30%"
>
{{createItem.key}}
</td>
<td
width=
"40%"
>
{{createItem.value}}
</td>
<td
width=
"30%"
>
{{createItem.comment}}
</td>
</tr>
</tbody>
</table>
...
...
@@ -128,8 +134,7 @@
</div>
</div>
</div>
<div
class=
"row"
ng-show=
"syncItemStep == 2"
>
<div
class=
"row"
style=
"margin-top: 10px;"
>
<div
class=
"row"
style=
"margin-top: 10px;"
ng-show=
"diff.diffs.updateItems.length > 0"
>
<div
class=
"form-horizontal"
>
<label
class=
"col-sm-2 control-label"
>
更新的配置
</label>
<div
class=
"col-sm-9"
>
...
...
@@ -138,24 +143,20 @@
<tr>
<td>
key
</td>
<td>
value
</td>
<td>
comment
</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
ng-repeat=
"updateItem in diff.diffs.updateItems"
>
<td
width=
"30%"
>
{{updateItem.key}}
</td>
<td
width=
"40%"
>
{{updateItem.value}}
</td>
<td
width=
"30%"
>
{{updateItem.comment}}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
...
...
apollo-portal/src/test/java/com/ctrip/apollo/portal/ConfigServiceTest.java
浏览文件 @
7a27efe2
...
...
@@ -143,7 +143,7 @@ public class ConfigServiceTest {
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
,
namespaceIdentifer
s
);
List
<
ItemDiffs
>
itemDiffses
=
configService
.
compare
(
namespaceIdentifers
,
sourceItem
s
);
assertEquals
(
1
,
itemDiffses
.
size
());
ItemDiffs
itemDiffs
=
itemDiffses
.
get
(
0
);
...
...
@@ -180,7 +180,7 @@ public class ConfigServiceTest {
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
,
namespaceIdentifer
s
);
List
<
ItemDiffs
>
itemDiffses
=
configService
.
compare
(
namespaceIdentifers
,
sourceItem
s
);
assertEquals
(
1
,
itemDiffses
.
size
());
ItemDiffs
itemDiffs
=
itemDiffses
.
get
(
0
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录