Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
superrain51
apollo
提交
4f3dd644
apollo
项目概览
superrain51
/
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,发现更多精彩内容 >>
提交
4f3dd644
编写于
1月 19, 2017
作者:
J
Jason Song
提交者:
GitHub
1月 19, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #520 from lepdou/emergency_publish
emergency publish
上级
ddbd9448
db65452d
变更
29
隐藏空白更改
内联
并排
Showing
29 changed file
with
358 addition
and
138 deletion
+358
-138
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ReleaseController.java
...ork/apollo/adminservice/controller/ReleaseController.java
+18
-14
apollo-adminservice/src/test/java/com/ctrip/framework/apollo/adminservice/controller/ReleaseControllerTest.java
...apollo/adminservice/controller/ReleaseControllerTest.java
+1
-1
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseService.java
...om/ctrip/framework/apollo/biz/service/ReleaseService.java
+55
-48
apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/ReleaseCreationTest.java
...rip/framework/apollo/biz/service/ReleaseCreationTest.java
+8
-9
apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/ReleaseOperationContext.java
...work/apollo/common/constants/ReleaseOperationContext.java
+1
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java
...om/ctrip/framework/apollo/portal/api/AdminServiceAPI.java
+8
-7
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/components/config/PortalConfig.java
...amework/apollo/portal/components/config/PortalConfig.java
+14
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/components/emailbuilder/ConfigPublishEmailBuilder.java
...al/components/emailbuilder/ConfigPublishEmailBuilder.java
+17
-1
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceBranchController.java
...k/apollo/portal/controller/NamespaceBranchController.java
+10
-1
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceLockController.java
...ork/apollo/portal/controller/NamespaceLockController.java
+11
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ReleaseController.java
...framework/apollo/portal/controller/ReleaseController.java
+12
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceReleaseModel.java
...ork/apollo/portal/entity/model/NamespaceReleaseModel.java
+9
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/LockInfo.java
...com/ctrip/framework/apollo/portal/entity/vo/LockInfo.java
+23
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceBranchService.java
...amework/apollo/portal/service/NamespaceBranchService.java
+5
-4
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceLockService.java
...framework/apollo/portal/service/NamespaceLockService.java
+16
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ReleaseService.java
...ctrip/framework/apollo/portal/service/ReleaseService.java
+12
-9
apollo-portal/src/main/resources/static/config.html
apollo-portal/src/main/resources/static/config.html
+2
-4
apollo-portal/src/main/resources/static/config/history.html
apollo-portal/src/main/resources/static/config/history.html
+2
-1
apollo-portal/src/main/resources/static/scripts/directive/merge-and-publish-modal-directive.js
...ic/scripts/directive/merge-and-publish-modal-directive.js
+8
-3
apollo-portal/src/main/resources/static/scripts/directive/namespace-panel-directive.js
...ces/static/scripts/directive/namespace-panel-directive.js
+15
-14
apollo-portal/src/main/resources/static/scripts/directive/publish-deny-modal-directive.js
.../static/scripts/directive/publish-deny-modal-directive.js
+44
-0
apollo-portal/src/main/resources/static/scripts/directive/release-modal-directive.js
...urces/static/scripts/directive/release-modal-directive.js
+10
-3
apollo-portal/src/main/resources/static/scripts/services/EventManager.js
...rc/main/resources/static/scripts/services/EventManager.js
+2
-1
apollo-portal/src/main/resources/static/scripts/services/NamespaceBranchService.js
...sources/static/scripts/services/NamespaceBranchService.js
+3
-2
apollo-portal/src/main/resources/static/scripts/services/NamespaceLockService.js
...resources/static/scripts/services/NamespaceLockService.js
+1
-1
apollo-portal/src/main/resources/static/scripts/services/ReleaseService.js
.../main/resources/static/scripts/services/ReleaseService.js
+16
-14
apollo-portal/src/main/resources/static/scripts/services/ServerConfigService.js
.../resources/static/scripts/services/ServerConfigService.js
+1
-1
apollo-portal/src/main/resources/static/styles/common-style.css
...-portal/src/main/resources/static/styles/common-style.css
+6
-0
apollo-portal/src/main/resources/static/views/component/publish-deny-modal.html
.../resources/static/views/component/publish-deny-modal.html
+28
-0
未找到文件。
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ReleaseController.java
浏览文件 @
4f3dd644
...
...
@@ -33,6 +33,7 @@ import java.util.stream.Collectors;
@RestController
public
class
ReleaseController
{
private
static
final
Splitter
RELEASES_SPLITTER
=
Splitter
.
on
(
","
).
omitEmptyStrings
()
.
trimResults
();
...
...
@@ -57,7 +58,7 @@ public class ReleaseController {
}
@RequestMapping
(
"/releases"
)
public
List
<
ReleaseDTO
>
findReleaseByIds
(
@RequestParam
(
"releaseIds"
)
String
releaseIds
){
public
List
<
ReleaseDTO
>
findReleaseByIds
(
@RequestParam
(
"releaseIds"
)
String
releaseIds
)
{
Set
<
Long
>
releaseIdSet
=
RELEASES_SPLITTER
.
splitToList
(
releaseIds
).
stream
().
map
(
Long:
:
parseLong
)
.
collect
(
Collectors
.
toSet
());
...
...
@@ -99,13 +100,14 @@ public class ReleaseController {
@PathVariable
(
"namespaceName"
)
String
namespaceName
,
@RequestParam
(
"name"
)
String
releaseName
,
@RequestParam
(
name
=
"comment"
,
required
=
false
)
String
releaseComment
,
@RequestParam
(
"operator"
)
String
operator
)
{
@RequestParam
(
"operator"
)
String
operator
,
@RequestParam
(
name
=
"isEmergencyPublish"
,
defaultValue
=
"false"
)
boolean
isEmergencyPublish
)
{
Namespace
namespace
=
namespaceService
.
findOne
(
appId
,
clusterName
,
namespaceName
);
if
(
namespace
==
null
)
{
throw
new
NotFoundException
(
String
.
format
(
"Could not find namespace for %s %s %s"
,
appId
,
clusterName
,
namespaceName
));
}
Release
release
=
releaseService
.
publish
(
namespace
,
releaseName
,
releaseComment
,
operator
);
Release
release
=
releaseService
.
publish
(
namespace
,
releaseName
,
releaseComment
,
operator
,
isEmergencyPublish
);
//send release message
Namespace
parentNamespace
=
namespaceService
.
findParentNamespace
(
namespace
);
...
...
@@ -122,31 +124,33 @@ public class ReleaseController {
/**
*merge branch items to master and publish master
* merge branch items to master and publish master
*
* @return published result
*/
@Transactional
@RequestMapping
(
path
=
"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish"
,
method
=
RequestMethod
.
POST
)
public
ReleaseDTO
updateAndPublish
(
@PathVariable
(
"appId"
)
String
appId
,
@PathVariable
(
"clusterName"
)
String
clusterName
,
@PathVariable
(
"namespaceName"
)
String
namespaceName
,
@RequestParam
(
"releaseName"
)
String
releaseName
,
@RequestParam
(
"branchName"
)
String
branchName
,
@RequestParam
(
value
=
"deleteBranch"
,
defaultValue
=
"true"
)
boolean
deleteBranch
,
@RequestParam
(
name
=
"releaseComment"
,
required
=
false
)
String
releaseComment
,
@RequestBody
ItemChangeSets
changeSets
)
{
@PathVariable
(
"clusterName"
)
String
clusterName
,
@PathVariable
(
"namespaceName"
)
String
namespaceName
,
@RequestParam
(
"releaseName"
)
String
releaseName
,
@RequestParam
(
"branchName"
)
String
branchName
,
@RequestParam
(
value
=
"deleteBranch"
,
defaultValue
=
"true"
)
boolean
deleteBranch
,
@RequestParam
(
name
=
"releaseComment"
,
required
=
false
)
String
releaseComment
,
@RequestParam
(
name
=
"isEmergencyPublish"
,
defaultValue
=
"false"
)
boolean
isEmergencyPublish
,
@RequestBody
ItemChangeSets
changeSets
)
{
Namespace
namespace
=
namespaceService
.
findOne
(
appId
,
clusterName
,
namespaceName
);
if
(
namespace
==
null
)
{
throw
new
NotFoundException
(
String
.
format
(
"Could not find namespace for %s %s %s"
,
appId
,
clusterName
,
namespaceName
));
}
Release
release
=
releaseService
.
mergeBranchChangeSetsAndRelease
(
namespace
,
branchName
,
releaseName
,
releaseComment
,
changeSets
);
Release
release
=
releaseService
.
mergeBranchChangeSetsAndRelease
(
namespace
,
branchName
,
releaseName
,
releaseComment
,
isEmergencyPublish
,
changeSets
);
if
(
deleteBranch
)
{
namespaceBranchService
.
deleteBranch
(
appId
,
clusterName
,
namespaceName
,
branchName
,
NamespaceBranchStatus
.
MERGED
,
changeSets
.
getDataChangeLastModifiedBy
());
NamespaceBranchStatus
.
MERGED
,
changeSets
.
getDataChangeLastModifiedBy
());
}
messageSender
.
sendMessage
(
ReleaseMessageKeyGenerator
.
generate
(
appId
,
clusterName
,
namespaceName
),
...
...
apollo-adminservice/src/test/java/com/ctrip/framework/apollo/adminservice/controller/ReleaseControllerTest.java
浏览文件 @
4f3dd644
...
...
@@ -121,7 +121,7 @@ public class ReleaseControllerTest extends AbstractControllerTest {
.
thenReturn
(
someNamespace
);
releaseController
.
publish
(
someAppId
,
someCluster
,
someNamespaceName
,
someName
,
someComment
,
"test"
);
.
publish
(
someAppId
,
someCluster
,
someNamespaceName
,
someName
,
someComment
,
"test"
,
false
);
verify
(
someMessageSender
,
times
(
1
))
.
sendMessage
(
Joiner
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
)
...
...
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseService.java
浏览文件 @
4f3dd644
...
...
@@ -13,6 +13,7 @@ import com.ctrip.framework.apollo.biz.entity.NamespaceLock;
import
com.ctrip.framework.apollo.biz.entity.Release
;
import
com.ctrip.framework.apollo.biz.repository.ReleaseRepository
;
import
com.ctrip.framework.apollo.biz.utils.ReleaseKeyGenerator
;
import
com.ctrip.framework.apollo.common.constants.GsonType
;
import
com.ctrip.framework.apollo.common.constants.ReleaseOperation
;
import
com.ctrip.framework.apollo.common.constants.ReleaseOperationContext
;
import
com.ctrip.framework.apollo.common.dto.ItemChangeSets
;
...
...
@@ -43,12 +44,10 @@ import java.util.Set;
*/
@Service
public
class
ReleaseService
{
private
static
final
FastDateFormat
TIMESTAMP_FORMAT
=
FastDateFormat
.
getInstance
(
"yyyyMMddHHmmss"
);
private
Gson
gson
=
new
Gson
();
private
Type
configurationTypeReference
=
new
TypeToken
<
Map
<
String
,
String
>>()
{
}.
getType
();
@Autowired
private
ReleaseRepository
releaseRepository
;
@Autowired
...
...
@@ -123,12 +122,11 @@ public class ReleaseService {
}
@Transactional
public
Release
mergeBranchChangeSetsAndRelease
(
Namespace
namespace
,
String
branchName
,
String
releaseName
,
String
releaseComment
,
ItemChangeSets
changeSets
)
{
NamespaceLock
lock
=
namespaceLockService
.
findLock
(
namespace
.
getId
());
if
(
lock
!=
null
&&
lock
.
getDataChangeCreatedBy
().
equals
(
changeSets
.
getDataChangeLastModifiedBy
()))
{
throw
new
BadRequestException
(
"config can not be published by yourself."
);
}
public
Release
mergeBranchChangeSetsAndRelease
(
Namespace
namespace
,
String
branchName
,
String
releaseName
,
String
releaseComment
,
boolean
isEmergencyPublish
,
ItemChangeSets
changeSets
)
{
checkLock
(
namespace
,
isEmergencyPublish
,
changeSets
.
getDataChangeLastModifiedBy
());
itemSetService
.
updateSet
(
namespace
,
changeSets
);
...
...
@@ -141,22 +139,19 @@ public class ReleaseService {
Map
<
String
,
Object
>
operationContext
=
Maps
.
newHashMap
();
operationContext
.
put
(
ReleaseOperationContext
.
SOURCE_BRANCH
,
branchName
);
operationContext
.
put
(
ReleaseOperationContext
.
BASE_RELEASE_ID
,
branchReleaseId
);
operationContext
.
put
(
ReleaseOperationContext
.
IS_EMERGENCY_PUBLISH
,
isEmergencyPublish
);
Release
release
=
masterRelease
(
namespace
,
releaseName
,
releaseComment
,
operateNamespaceItems
,
changeSets
.
getDataChangeLastModifiedBy
(),
ReleaseOperation
.
GRAY_RELEASE_MERGE_TO_MASTER
,
operationContext
);
return
masterRelease
(
namespace
,
releaseName
,
releaseComment
,
operateNamespaceItems
,
changeSets
.
getDataChangeLastModifiedBy
(),
ReleaseOperation
.
GRAY_RELEASE_MERGE_TO_MASTER
,
operationContext
);
return
release
;
}
@Transactional
public
Release
publish
(
Namespace
namespace
,
String
releaseName
,
String
releaseComment
,
String
operator
)
{
String
operator
,
boolean
isEmergencyPublish
)
{
NamespaceLock
lock
=
namespaceLockService
.
findLock
(
namespace
.
getId
());
if
(
lock
!=
null
&&
lock
.
getDataChangeCreatedBy
().
equals
(
operator
))
{
throw
new
BadRequestException
(
"config can not be published by yourself."
);
}
checkLock
(
namespace
,
isEmergencyPublish
,
operator
);
Map
<
String
,
String
>
operateNamespaceItems
=
getNamespaceItems
(
namespace
);
...
...
@@ -165,7 +160,7 @@ public class ReleaseService {
//branch release
if
(
parentNamespace
!=
null
)
{
return
publishBranchNamespace
(
parentNamespace
,
namespace
,
operateNamespaceItems
,
releaseName
,
releaseComment
,
operator
);
releaseName
,
releaseComment
,
operator
,
isEmergencyPublish
);
}
Namespace
childNamespace
=
namespaceService
.
findChildNamespace
(
namespace
);
...
...
@@ -176,31 +171,43 @@ public class ReleaseService {
}
//master release
Map
<
String
,
Object
>
operationContext
=
Maps
.
newHashMap
();
operationContext
.
put
(
ReleaseOperationContext
.
IS_EMERGENCY_PUBLISH
,
isEmergencyPublish
);
Release
release
=
masterRelease
(
namespace
,
releaseName
,
releaseComment
,
operateNamespaceItems
,
operator
,
ReleaseOperation
.
NORMAL_RELEASE
,
null
);
operator
,
ReleaseOperation
.
NORMAL_RELEASE
,
operationContext
);
//merge to branch and auto release
if
(
childNamespace
!=
null
)
{
mergeFromMasterAndPublishBranch
(
namespace
,
childNamespace
,
operateNamespaceItems
,
releaseName
,
releaseComment
,
operator
,
previousRelease
,
release
);
releaseName
,
releaseComment
,
operator
,
previousRelease
,
release
,
isEmergencyPublish
);
}
return
release
;
}
private
void
checkLock
(
Namespace
namespace
,
boolean
isEmergencyPublish
,
String
operator
)
{
if
(!
isEmergencyPublish
)
{
NamespaceLock
lock
=
namespaceLockService
.
findLock
(
namespace
.
getId
());
if
(
lock
!=
null
&&
lock
.
getDataChangeCreatedBy
().
equals
(
operator
))
{
throw
new
BadRequestException
(
"Config can not be published by yourself."
);
}
}
}
private
void
mergeFromMasterAndPublishBranch
(
Namespace
parentNamespace
,
Namespace
childNamespace
,
Map
<
String
,
String
>
parentNamespaceItems
,
String
releaseName
,
String
releaseComment
,
String
operator
,
Release
masterPreviousRelease
,
Release
parentRelease
)
{
// //create release for child namespace
String
operator
,
Release
masterPreviousRelease
,
Release
parentRelease
,
boolean
isEmergencyPublish
)
{
//create release for child namespace
Map
<
String
,
String
>
childReleaseConfiguration
=
getNamespaceReleaseConfiguration
(
childNamespace
);
Map
<
String
,
String
>
parentNamespaceOldConfiguration
=
masterPreviousRelease
==
null
?
null
:
gson
.
fromJson
(
masterPreviousRelease
.
getConfigurations
(),
configurationTypeReference
);
Map
<
String
,
String
>
parentNamespaceOldConfiguration
=
masterPreviousRelease
==
null
?
null
:
gson
.
fromJson
(
masterPreviousRelease
.
getConfigurations
(),
GsonType
.
CONFIG
);
Map
<
String
,
String
>
childNamespaceToPublishConfigs
=
Map
<
String
,
String
>
childNamespaceToPublishConfigs
=
calculateChildNamespaceToPublishConfiguration
(
parentNamespaceOldConfiguration
,
parentNamespaceItems
,
childNamespace
);
...
...
@@ -208,27 +215,27 @@ public class ReleaseService {
if
(!
childNamespaceToPublishConfigs
.
equals
(
childReleaseConfiguration
))
{
branchRelease
(
parentNamespace
,
childNamespace
,
releaseName
,
releaseComment
,
childNamespaceToPublishConfigs
,
parentRelease
.
getId
(),
operator
,
ReleaseOperation
.
MASTER_NORMAL_RELEASE_MERGE_TO_GRAY
);
ReleaseOperation
.
MASTER_NORMAL_RELEASE_MERGE_TO_GRAY
,
isEmergencyPublish
);
}
}
private
Release
publishBranchNamespace
(
Namespace
parentNamespace
,
Namespace
childNamespace
,
Map
<
String
,
String
>
childNamespaceItems
,
String
releaseName
,
String
releaseComment
,
String
operator
)
{
String
releaseName
,
String
releaseComment
,
String
operator
,
boolean
isEmergencyPublish
)
{
Release
parentLatestRelease
=
findLatestActiveRelease
(
parentNamespace
);
Map
<
String
,
String
>
parentConfigurations
=
parentLatestRelease
!=
null
?
gson
.
fromJson
(
parentLatestRelease
.
getConfigurations
(),
configurationTypeReference
)
:
new
HashMap
<>();
GsonType
.
CONFIG
)
:
new
HashMap
<>();
long
baseReleaseId
=
parentLatestRelease
==
null
?
0
:
parentLatestRelease
.
getId
();
Map
<
String
,
String
>
childNamespaceToPublishConfigs
=
mergeConfiguration
(
parentConfigurations
,
childNamespaceItems
);
Release
release
=
branchRelease
(
parentNamespace
,
childNamespace
,
releaseName
,
releaseComment
,
childNamespaceToPublishConfigs
,
baseReleaseId
,
operator
,
ReleaseOperation
.
GRAY_RELEASE
);
return
release
;
return
branchRelease
(
parentNamespace
,
childNamespace
,
releaseName
,
releaseComment
,
childNamespaceToPublishConfigs
,
baseReleaseId
,
operator
,
ReleaseOperation
.
GRAY_RELEASE
,
isEmergencyPublish
);
}
private
Release
masterRelease
(
Namespace
namespace
,
String
releaseName
,
String
releaseComment
,
...
...
@@ -241,8 +248,8 @@ public class ReleaseService {
releaseHistoryService
.
createReleaseHistory
(
namespace
.
getAppId
(),
namespace
.
getClusterName
(),
namespace
.
getNamespaceName
(),
namespace
.
getClusterName
(),
release
.
getId
(),
previousReleaseId
,
releaseOperation
,
operationContext
,
operator
);
release
.
getId
(),
previousReleaseId
,
releaseOperation
,
operationContext
,
operator
);
return
release
;
}
...
...
@@ -250,7 +257,7 @@ public class ReleaseService {
private
Release
branchRelease
(
Namespace
parentNamespace
,
Namespace
childNamespace
,
String
releaseName
,
String
releaseComment
,
Map
<
String
,
String
>
configurations
,
long
baseReleaseId
,
String
operator
,
int
releaseOperation
)
{
String
operator
,
int
releaseOperation
,
boolean
isEmergencyPublish
)
{
Release
previousRelease
=
findLatestActiveRelease
(
childNamespace
.
getAppId
(),
childNamespace
.
getClusterName
(),
childNamespace
.
getNamespaceName
());
...
...
@@ -258,6 +265,7 @@ public class ReleaseService {
Map
<
String
,
Object
>
releaseOperationContext
=
Maps
.
newHashMap
();
releaseOperationContext
.
put
(
ReleaseOperationContext
.
BASE_RELEASE_ID
,
baseReleaseId
);
releaseOperationContext
.
put
(
ReleaseOperationContext
.
IS_EMERGENCY_PUBLISH
,
isEmergencyPublish
);
Release
release
=
createRelease
(
childNamespace
,
releaseName
,
releaseComment
,
configurations
,
operator
);
...
...
@@ -316,8 +324,7 @@ public class ReleaseService {
Release
release
=
findLatestActiveRelease
(
namespace
);
Map
<
String
,
String
>
configuration
=
new
HashMap
<>();
if
(
release
!=
null
)
{
configuration
=
new
Gson
().
fromJson
(
release
.
getConfigurations
(),
configurationTypeReference
);
configuration
=
new
Gson
().
fromJson
(
release
.
getConfigurations
(),
GsonType
.
CONFIG
);
}
return
configuration
;
}
...
...
@@ -395,12 +402,11 @@ public class ReleaseService {
Release
parentNamespaceNewLatestRelease
=
parentNamespaceTwoLatestActiveRelease
.
get
(
1
);
Map
<
String
,
String
>
parentNamespaceAbandonedConfiguration
=
gson
.
fromJson
(
abandonedRelease
.
getConfigurations
(),
configurationTypeReference
);
GsonType
.
CONFIG
);
Map
<
String
,
String
>
parentNamespaceNewLatestConfiguration
=
gson
.
fromJson
(
parentNamespaceNewLatestRelease
.
getConfigurations
(),
configurationTypeReference
);
gson
.
fromJson
(
parentNamespaceNewLatestRelease
.
getConfigurations
(),
GsonType
.
CONFIG
);
Map
<
String
,
String
>
childNamespaceNewConfiguration
=
...
...
@@ -408,9 +414,10 @@ public class ReleaseService {
parentNamespaceNewLatestConfiguration
,
childNamespace
);
branchRelease
(
parentNamespace
,
childNamespace
,
TIMESTAMP_FORMAT
.
format
(
new
Date
())
+
"-master-rollback-merge-to-gray"
,
""
,
branchRelease
(
parentNamespace
,
childNamespace
,
TIMESTAMP_FORMAT
.
format
(
new
Date
())
+
"-master-rollback-merge-to-gray"
,
""
,
childNamespaceNewConfiguration
,
parentNamespaceNewLatestRelease
.
getId
(),
operator
,
ReleaseOperation
.
MATER_ROLLBACK_MERGE_TO_GRAY
);
ReleaseOperation
.
MATER_ROLLBACK_MERGE_TO_GRAY
,
false
);
}
private
Map
<
String
,
String
>
calculateChildNamespaceToPublishConfiguration
(
...
...
@@ -423,7 +430,7 @@ public class ReleaseService {
Map
<
String
,
String
>
childNamespaceLatestActiveConfiguration
=
childNamespaceLatestActiveRelease
==
null
?
null
:
gson
.
fromJson
(
childNamespaceLatestActiveRelease
.
getConfigurations
(),
configurationTypeReference
);
GsonType
.
CONFIG
);
Map
<
String
,
String
>
childNamespaceModifiedConfiguration
=
calculateBranchModifiedItemsAccordingToRelease
(
parentNamespaceOldConfiguration
,
childNamespaceLatestActiveConfiguration
);
...
...
apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/ReleaseCreationTest.java
浏览文件 @
4f3dd644
...
...
@@ -8,6 +8,7 @@ import com.ctrip.framework.apollo.biz.entity.GrayReleaseRule;
import
com.ctrip.framework.apollo.biz.entity.Namespace
;
import
com.ctrip.framework.apollo.biz.entity.Release
;
import
com.ctrip.framework.apollo.biz.entity.ReleaseHistory
;
import
com.ctrip.framework.apollo.common.constants.GsonType
;
import
com.ctrip.framework.apollo.common.constants.ReleaseOperation
;
import
org.junit.Assert
;
...
...
@@ -24,8 +25,6 @@ import java.util.Map;
public
class
ReleaseCreationTest
extends
AbstractIntegrationTest
{
private
Gson
gson
=
new
Gson
();
private
Type
configurationTypeReference
=
new
TypeToken
<
Map
<
String
,
String
>>()
{
}.
getType
();
@Autowired
private
ReleaseService
releaseService
;
...
...
@@ -47,7 +46,7 @@ public class ReleaseCreationTest extends AbstractIntegrationTest {
String
clusterName
=
"only-master"
;
Namespace
namespace
=
instanceNamespace
(
namespaceId
,
clusterName
);
releaseService
.
publish
(
namespace
,
""
,
""
,
operator
);
releaseService
.
publish
(
namespace
,
""
,
""
,
operator
,
false
);
Release
latestRelease
=
releaseService
.
findLatestActiveRelease
(
namespace
);
...
...
@@ -92,7 +91,7 @@ public class ReleaseCreationTest extends AbstractIntegrationTest {
String
childClusterName
=
"child-cluster1"
;
Namespace
parentNamespace
=
instanceNamespace
(
parentNamespaceId
,
parentClusterName
);
releaseService
.
publish
(
parentNamespace
,
""
,
""
,
operator
);
releaseService
.
publish
(
parentNamespace
,
""
,
""
,
operator
,
false
);
Release
latestParentNamespaceRelease
=
releaseService
.
findLatestActiveRelease
(
parentNamespace
);
...
...
@@ -166,7 +165,7 @@ public class ReleaseCreationTest extends AbstractIntegrationTest {
String
childClusterName
=
"child-cluster2"
;
Namespace
parentNamespace
=
instanceNamespace
(
parentNamespaceId
,
parentClusterName
);
releaseService
.
publish
(
parentNamespace
,
""
,
""
,
operator
);
releaseService
.
publish
(
parentNamespace
,
""
,
""
,
operator
,
false
);
Release
latestParentNamespaceRelease
=
releaseService
.
findLatestActiveRelease
(
parentNamespace
);
...
...
@@ -237,7 +236,7 @@ public class ReleaseCreationTest extends AbstractIntegrationTest {
String
childClusterName
=
"child-cluster3"
;
Namespace
parentNamespace
=
instanceNamespace
(
parentNamespaceId
,
parentClusterName
);
releaseService
.
publish
(
parentNamespace
,
""
,
""
,
operator
);
releaseService
.
publish
(
parentNamespace
,
""
,
""
,
operator
,
false
);
Release
latestParentNamespaceRelease
=
releaseService
.
findLatestActiveRelease
(
parentNamespace
);
...
...
@@ -306,7 +305,7 @@ public class ReleaseCreationTest extends AbstractIntegrationTest {
String
childClusterName
=
"child-cluster4"
;
//assert child namespace
Namespace
childNamespace
=
instanceNamespace
(
childNamespaceId
,
childClusterName
);
releaseService
.
publish
(
childNamespace
,
""
,
""
,
operator
);
releaseService
.
publish
(
childNamespace
,
""
,
""
,
operator
,
false
);
Release
latestChildNamespaceRelease
=
releaseService
.
findLatestActiveRelease
(
childNamespace
);
...
...
@@ -377,7 +376,7 @@ public class ReleaseCreationTest extends AbstractIntegrationTest {
String
childClusterName
=
"child-cluster5"
;
//assert child namespace
Namespace
childNamespace
=
instanceNamespace
(
childNamespaceId
,
childClusterName
);
releaseService
.
publish
(
childNamespace
,
""
,
""
,
operator
);
releaseService
.
publish
(
childNamespace
,
""
,
""
,
operator
,
false
);
Release
latestChildNamespaceRelease
=
releaseService
.
findLatestActiveRelease
(
childNamespace
);
...
...
@@ -495,7 +494,7 @@ public class ReleaseCreationTest extends AbstractIntegrationTest {
}
private
Map
<
String
,
String
>
parseConfiguration
(
String
configuration
)
{
return
gson
.
fromJson
(
configuration
,
configurationTypeReference
);
return
gson
.
fromJson
(
configuration
,
GsonType
.
CONFIG
);
}
}
apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/ReleaseOperationContext.java
浏览文件 @
4f3dd644
...
...
@@ -8,4 +8,5 @@ public interface ReleaseOperationContext {
String
RULES
=
"rules"
;
String
OLD_RULES
=
"oldRules"
;
String
BASE_RELEASE_ID
=
"baseReleaseId"
;
String
IS_EMERGENCY_PUBLISH
=
"isEmergencyPublish"
;
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java
浏览文件 @
4f3dd644
...
...
@@ -230,31 +230,32 @@ public class AdminServiceAPI {
}
public
ReleaseDTO
createRelease
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespace
,
String
releaseName
,
String
releaseComment
,
String
operator
)
{
String
releaseName
,
String
releaseComment
,
String
operator
,
boolean
isEmergencyPublish
)
{
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
parseMediaType
(
MediaType
.
APPLICATION_FORM_URLENCODED_VALUE
+
";charset=UTF-8"
));
MultiValueMap
<
String
,
String
>
parameters
=
new
LinkedMultiValueMap
<>();
parameters
.
add
(
"name"
,
releaseName
);
parameters
.
add
(
"comment"
,
releaseComment
);
parameters
.
add
(
"operator"
,
operator
);
parameters
.
add
(
"isEmergencyPublish"
,
String
.
valueOf
(
isEmergencyPublish
));
HttpEntity
<
MultiValueMap
<
String
,
String
>>
entity
=
new
HttpEntity
<>(
parameters
,
headers
);
ReleaseDTO
response
=
restTemplate
.
post
(
env
,
"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases"
,
entity
,
ReleaseDTO
.
class
,
appId
,
clusterName
,
namespace
);
ReleaseDTO
.
class
,
appId
,
clusterName
,
namespace
);
return
response
;
}
public
ReleaseDTO
updateAndPublish
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespace
,
String
releaseName
,
String
releaseComment
,
String
branchName
,
boolean
deleteBranch
,
ItemChangeSets
changeSets
)
{
boolean
isEmergencyPublish
,
boolean
deleteBranch
,
ItemChangeSets
changeSets
)
{
return
restTemplate
.
post
(
env
,
"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish?"
+
"releaseName={releaseName}&releaseComment={releaseComment}&branchName={branchName}&deleteBranch={deleteBranch}"
,
changeSets
,
ReleaseDTO
.
class
,
appId
,
clusterName
,
namespace
,
releaseName
,
releaseComment
,
branchName
,
deleteBranch
);
+
"releaseName={releaseName}&releaseComment={releaseComment}&branchName={branchName}"
+
"&deleteBranch={deleteBranch}&isEmergencyPublish={isEmergencyPublish}"
,
changeSets
,
ReleaseDTO
.
class
,
appId
,
clusterName
,
namespace
,
releaseName
,
releaseComment
,
branchName
,
deleteBranch
,
isEmergencyPublish
);
}
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/components/config/PortalConfig.java
浏览文件 @
4f3dd644
...
...
@@ -20,6 +20,7 @@ import org.springframework.util.StringUtils;
import
java.lang.reflect.Type
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Set
;
@Component
...
...
@@ -97,6 +98,19 @@ public class PortalConfig extends RefreshableConfig {
return
getValue
(
"apollo.portal.address"
);
}
public
boolean
isEmergencyPublishAllowed
(
Env
env
)
{
String
targetEnv
=
env
.
name
();
String
[]
emergencyPublishSupportedEnvs
=
getArrayProperty
(
"emergencyPublish.supported.envs"
,
new
String
[
0
]);
for
(
String
supportedEnv:
emergencyPublishSupportedEnvs
)
{
if
(
Objects
.
equals
(
targetEnv
,
supportedEnv
.
toUpperCase
().
trim
()))
{
return
true
;
}
}
return
false
;
}
/***
* Level: low
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/components/emailbuilder/ConfigPublishEmailBuilder.java
浏览文件 @
4f3dd644
...
...
@@ -4,6 +4,7 @@ package com.ctrip.framework.apollo.portal.components.emailbuilder;
import
com.google.common.collect.Lists
;
import
com.ctrip.framework.apollo.common.constants.ReleaseOperation
;
import
com.ctrip.framework.apollo.common.constants.ReleaseOperationContext
;
import
com.ctrip.framework.apollo.common.dto.ReleaseDTO
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
...
...
@@ -29,12 +30,15 @@ import java.util.ArrayList;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.regex.Matcher
;
public
abstract
class
ConfigPublishEmailBuilder
{
private
static
final
String
EMERGENCY_PUBLISH_TAG
=
"<span style='color:red'>(紧急发布)</span>"
;
//email content common field placeholder
private
static
final
String
EMAIL_CONTENT_FIELD_APPID
=
"#\\{appId\\}"
;
private
static
final
String
EMAIL_CONTENT_FIELD_ENV
=
"#\\{env}"
;
...
...
@@ -48,6 +52,7 @@ public abstract class ConfigPublishEmailBuilder {
private
static
final
String
EMAIL_CONTENT_FIELD_RELEASE_COMMENT
=
"#\\{releaseComment}"
;
private
static
final
String
EMAIL_CONTENT_FIELD_APOLLO_SERVER_ADDRESS
=
"#\\{apollo.portal.address}"
;
private
static
final
String
EMAIL_CONTENT_FIELD_DIFF_CONTENT
=
"#\\{diffContent}"
;
private
static
final
String
EMAIL_CONTENT_FIELD_EMERGENCY_PUBLISH
=
"#\\{emergencyPublish}"
;
private
static
final
String
EMAIL_CONTENT_DIFF_MODULE
=
"#\\{diffModule}"
;
protected
static
final
String
EMAIL_CONTENT_GRAY_RULES_MODULE
=
"#\\{rulesModule}"
;
...
...
@@ -118,7 +123,18 @@ public abstract class ConfigPublishEmailBuilder {
}
private
String
renderReleaseBasicInfo
(
String
template
,
Env
env
,
ReleaseHistoryBO
releaseHistory
)
{
String
renderResult
=
template
.
replaceAll
(
EMAIL_CONTENT_FIELD_APPID
,
Matcher
.
quoteReplacement
(
releaseHistory
.
getAppId
()));
String
renderResult
=
template
;
Map
<
String
,
Object
>
operationContext
=
releaseHistory
.
getOperationContext
();
boolean
isEmergencyPublish
=
operationContext
.
containsKey
(
ReleaseOperationContext
.
IS_EMERGENCY_PUBLISH
)
&&
(
boolean
)
operationContext
.
get
(
ReleaseOperationContext
.
IS_EMERGENCY_PUBLISH
);
if
(
isEmergencyPublish
)
{
renderResult
=
renderResult
.
replaceAll
(
EMAIL_CONTENT_FIELD_EMERGENCY_PUBLISH
,
Matcher
.
quoteReplacement
(
EMERGENCY_PUBLISH_TAG
));
}
else
{
renderResult
=
renderResult
.
replaceAll
(
EMAIL_CONTENT_FIELD_EMERGENCY_PUBLISH
,
""
);
}
renderResult
=
renderResult
.
replaceAll
(
EMAIL_CONTENT_FIELD_APPID
,
Matcher
.
quoteReplacement
(
releaseHistory
.
getAppId
()));
renderResult
=
renderResult
.
replaceAll
(
EMAIL_CONTENT_FIELD_ENV
,
Matcher
.
quoteReplacement
(
env
.
toString
()));
renderResult
=
renderResult
.
replaceAll
(
EMAIL_CONTENT_FIELD_CLUSTER
,
Matcher
.
quoteReplacement
(
releaseHistory
.
getClusterName
()));
renderResult
=
renderResult
.
replaceAll
(
EMAIL_CONTENT_FIELD_NAMESPACE
,
Matcher
.
quoteReplacement
(
releaseHistory
.
getNamespaceName
()));
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceBranchController.java
浏览文件 @
4f3dd644
...
...
@@ -3,8 +3,10 @@ package com.ctrip.framework.apollo.portal.controller;
import
com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO
;
import
com.ctrip.framework.apollo.common.dto.NamespaceDTO
;
import
com.ctrip.framework.apollo.common.dto.ReleaseDTO
;
import
com.ctrip.framework.apollo.common.exception.BadRequestException
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.components.PermissionValidator
;
import
com.ctrip.framework.apollo.portal.components.config.PortalConfig
;
import
com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel
;
import
com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO
;
import
com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent
;
...
...
@@ -33,6 +35,8 @@ public class NamespaceBranchController {
private
NamespaceBranchService
namespaceBranchService
;
@Autowired
private
ApplicationEventPublisher
publisher
;
@Autowired
private
PortalConfig
portalConfig
;
@RequestMapping
(
"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches"
)
public
NamespaceBO
findBranch
(
@PathVariable
String
appId
,
...
...
@@ -84,8 +88,13 @@ public class NamespaceBranchController {
@PathVariable
String
branchName
,
@RequestParam
(
value
=
"deleteBranch"
,
defaultValue
=
"true"
)
boolean
deleteBranch
,
@RequestBody
NamespaceReleaseModel
model
)
{
if
(
model
.
isEmergencyPublish
()
&&
!
portalConfig
.
isEmergencyPublishAllowed
(
Env
.
fromString
(
env
)))
{
throw
new
BadRequestException
(
String
.
format
(
"Env: %s is not supported emergency publish now"
,
env
));
}
ReleaseDTO
createdRelease
=
namespaceBranchService
.
merge
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
,
branchName
,
model
.
getReleaseTitle
(),
model
.
getReleaseComment
(),
deleteBranch
);
model
.
getReleaseTitle
(),
model
.
getReleaseComment
(),
model
.
isEmergencyPublish
(),
deleteBranch
);
ConfigPublishEvent
event
=
ConfigPublishEvent
.
instance
();
event
.
withAppId
(
appId
)
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceLockController.java
浏览文件 @
4f3dd644
...
...
@@ -2,6 +2,7 @@ package com.ctrip.framework.apollo.portal.controller;
import
com.ctrip.framework.apollo.common.dto.NamespaceLockDTO
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.entity.vo.LockInfo
;
import
com.ctrip.framework.apollo.portal.service.NamespaceLockService
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -15,6 +16,7 @@ public class NamespaceLockController {
@Autowired
private
NamespaceLockService
namespaceLockService
;
@Deprecated
@RequestMapping
(
"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/lock"
)
public
NamespaceLockDTO
getNamespaceLock
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
)
{
...
...
@@ -22,4 +24,13 @@ public class NamespaceLockController {
return
namespaceLockService
.
getNamespaceLock
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
);
}
@RequestMapping
(
"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/lock-info"
)
public
LockInfo
getNamespaceLockInfo
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
)
{
return
namespaceLockService
.
getNamespaceLockInfo
(
appId
,
Env
.
fromString
(
env
),
clusterName
,
namespaceName
);
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ReleaseController.java
浏览文件 @
4f3dd644
package
com.ctrip.framework.apollo.portal.controller
;
import
com.ctrip.framework.apollo.common.dto.ReleaseDTO
;
import
com.ctrip.framework.apollo.common.exception.BadRequestException
;
import
com.ctrip.framework.apollo.common.utils.RequestPrecondition
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.components.config.PortalConfig
;
import
com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel
;
import
com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult
;
import
com.ctrip.framework.apollo.portal.entity.bo.ReleaseBO
;
...
...
@@ -30,6 +32,8 @@ public class ReleaseController {
private
ReleaseService
releaseService
;
@Autowired
private
ApplicationEventPublisher
publisher
;
@Autowired
private
PortalConfig
portalConfig
;
@PreAuthorize
(
value
=
"@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)"
)
@RequestMapping
(
value
=
"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases"
,
method
=
RequestMethod
.
POST
)
...
...
@@ -43,6 +47,10 @@ public class ReleaseController {
model
.
setClusterName
(
clusterName
);
model
.
setNamespaceName
(
namespaceName
);
if
(
model
.
isEmergencyPublish
()
&&
!
portalConfig
.
isEmergencyPublishAllowed
(
Env
.
valueOf
(
env
)))
{
throw
new
BadRequestException
(
String
.
format
(
"Env: %s is not supported emergency publish now"
,
env
));
}
ReleaseDTO
createdRelease
=
releaseService
.
publish
(
model
);
ConfigPublishEvent
event
=
ConfigPublishEvent
.
instance
();
...
...
@@ -72,6 +80,10 @@ public class ReleaseController {
model
.
setClusterName
(
branchName
);
model
.
setNamespaceName
(
namespaceName
);
if
(
model
.
isEmergencyPublish
()
&&
!
portalConfig
.
isEmergencyPublishAllowed
(
Env
.
valueOf
(
env
)))
{
throw
new
BadRequestException
(
String
.
format
(
"Env: %s is not supported emergency publish now"
,
env
));
}
ReleaseDTO
createdRelease
=
releaseService
.
publish
(
model
);
ConfigPublishEvent
event
=
ConfigPublishEvent
.
instance
();
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceReleaseModel.java
浏览文件 @
4f3dd644
...
...
@@ -13,6 +13,7 @@ public class NamespaceReleaseModel implements Verifiable {
private
String
releaseTitle
;
private
String
releaseComment
;
private
String
releasedBy
;
private
boolean
isEmergencyPublish
;
@Override
public
boolean
isInvalid
()
{
...
...
@@ -74,4 +75,12 @@ public class NamespaceReleaseModel implements Verifiable {
public
void
setReleasedBy
(
String
releasedBy
)
{
this
.
releasedBy
=
releasedBy
;
}
public
boolean
isEmergencyPublish
()
{
return
isEmergencyPublish
;
}
public
void
setEmergencyPublish
(
boolean
emergencyPublish
)
{
isEmergencyPublish
=
emergencyPublish
;
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/LockInfo.java
0 → 100644
浏览文件 @
4f3dd644
package
com.ctrip.framework.apollo.portal.entity.vo
;
public
class
LockInfo
{
private
String
lockOwner
;
private
boolean
isEmergencyPublishAllowed
;
public
String
getLockOwner
()
{
return
lockOwner
;
}
public
void
setLockOwner
(
String
lockOwner
)
{
this
.
lockOwner
=
lockOwner
;
}
public
boolean
isEmergencyPublishAllowed
()
{
return
isEmergencyPublishAllowed
;
}
public
void
setEmergencyPublishAllowed
(
boolean
emergencyPublishAllowed
)
{
isEmergencyPublishAllowed
=
emergencyPublishAllowed
;
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceBranchService.java
浏览文件 @
4f3dd644
...
...
@@ -84,13 +84,14 @@ public class NamespaceBranchService {
public
ReleaseDTO
merge
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
,
String
branchName
,
String
title
,
String
comment
,
boolean
deleteBranch
)
{
String
branchName
,
String
title
,
String
comment
,
boolean
isEmergencyPublish
,
boolean
deleteBranch
)
{
ItemChangeSets
changeSets
=
calculateBranchChangeSet
(
appId
,
env
,
clusterName
,
namespaceName
,
branchName
);
ReleaseDTO
mergedResult
=
releaseService
.
updateAndPublish
(
appId
,
env
,
clusterName
,
namespaceName
,
title
,
comment
,
branchName
,
deleteBranch
,
changeSets
);
ReleaseDTO
mergedResult
=
releaseService
.
updateAndPublish
(
appId
,
env
,
clusterName
,
namespaceName
,
title
,
comment
,
branchName
,
isEmergencyPublish
,
deleteBranch
,
changeSets
);
Tracer
.
logEvent
(
CatEventType
.
MERGE_GRAY_RELEASE
,
String
.
format
(
"%s+%s+%s+%s"
,
appId
,
env
,
clusterName
,
namespaceName
));
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceLockService.java
浏览文件 @
4f3dd644
...
...
@@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.portal.service;
import
com.ctrip.framework.apollo.common.dto.NamespaceLockDTO
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.framework.apollo.portal.components.config.PortalConfig
;
import
com.ctrip.framework.apollo.portal.entity.vo.LockInfo
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
...
...
@@ -12,10 +14,24 @@ public class NamespaceLockService {
@Autowired
private
AdminServiceAPI
.
NamespaceLockAPI
namespaceLockAPI
;
@Autowired
private
PortalConfig
portalConfig
;
public
NamespaceLockDTO
getNamespaceLock
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
return
namespaceLockAPI
.
getNamespaceLockOwner
(
appId
,
env
,
clusterName
,
namespaceName
);
}
public
LockInfo
getNamespaceLockInfo
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
LockInfo
lockInfo
=
new
LockInfo
();
NamespaceLockDTO
namespaceLockDTO
=
namespaceLockAPI
.
getNamespaceLockOwner
(
appId
,
env
,
clusterName
,
namespaceName
);
String
lockOwner
=
namespaceLockDTO
==
null
?
""
:
namespaceLockDTO
.
getDataChangeCreatedBy
();
lockInfo
.
setLockOwner
(
lockOwner
);
lockInfo
.
setEmergencyPublishAllowed
(
portalConfig
.
isEmergencyPublishAllowed
(
env
));
return
lockInfo
;
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ReleaseService.java
浏览文件 @
4f3dd644
...
...
@@ -42,27 +42,30 @@ public class ReleaseService {
private
AdminServiceAPI
.
ReleaseAPI
releaseAPI
;
public
ReleaseDTO
publish
(
NamespaceReleaseModel
model
)
{
String
appId
=
model
.
getAppId
();
Env
env
=
model
.
getEnv
();
boolean
isEmergencyPublish
=
model
.
isEmergencyPublish
();
String
appId
=
model
.
getAppId
();
String
clusterName
=
model
.
getClusterName
();
String
namespaceName
=
model
.
getNamespaceName
();
String
releaseBy
=
StringUtils
.
isEmpty
(
model
.
getReleasedBy
())
?
userInfoHolder
.
getUser
().
getUserId
()
:
model
.
getReleasedBy
();
String
releaseBy
=
StringUtils
.
isEmpty
(
model
.
getReleasedBy
())
?
userInfoHolder
.
getUser
().
getUserId
()
:
model
.
getReleasedBy
();
ReleaseDTO
releaseDTO
=
releaseAPI
.
createRelease
(
appId
,
env
,
clusterName
,
namespaceName
,
model
.
getReleaseTitle
(),
model
.
getReleaseComment
(),
releaseBy
,
isEmergencyPublish
);
ReleaseDTO
releaseDTO
=
releaseAPI
.
createRelease
(
appId
,
env
,
clusterName
,
namespaceName
,
model
.
getReleaseTitle
(),
model
.
getReleaseComment
()
,
releaseBy
);
Tracer
.
logEvent
(
CatEventType
.
RELEASE_NAMESPACE
,
String
.
format
(
"%s+%s+%s+%s"
,
appId
,
env
,
clusterName
,
namespaceName
));
Tracer
.
logEvent
(
CatEventType
.
RELEASE_NAMESPACE
,
String
.
format
(
"%s+%s+%s+%s"
,
appId
,
env
,
clusterName
,
namespaceName
));
return
releaseDTO
;
}
public
ReleaseDTO
updateAndPublish
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
,
String
releaseTitle
,
String
releaseComment
,
String
branchName
,
boolean
deleteBranch
,
ItemChangeSets
changeSets
)
{
boolean
isEmergencyPublish
,
boolean
deleteBranch
,
ItemChangeSets
changeSets
)
{
return
releaseAPI
.
updateAndPublish
(
appId
,
env
,
clusterName
,
namespaceName
,
releaseTitle
,
releaseComment
,
branchName
,
deleteBranch
,
changeSets
);
isEmergencyPublish
,
deleteBranch
,
changeSets
);
}
public
List
<
ReleaseBO
>
findAllReleases
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
,
int
page
,
...
...
apollo-portal/src/main/resources/static/config.html
浏览文件 @
4f3dd644
...
...
@@ -229,6 +229,7 @@
cluster=
"pageContext.clusterName"
>
</mergeandpublishmodal>
<publishdenymodal></publishdenymodal>
<apolloconfirmdialog
apollo-dialog-id=
"'deleteConfirmDialog'"
apollo-title=
"'删除配置'"
apollo-detail=
"'确定要删除配置吗?'"
...
...
@@ -251,10 +252,6 @@
apollo-detail=
"'当前namespace正在被 ' + lockOwner + ' 编辑,一次发布只能被一个人修改.'"
apollo-show-cancel-btn=
"false"
></apolloconfirmdialog>
<apolloconfirmdialog
apollo-dialog-id=
"'releaseDenyDialog'"
apollo-title=
"'发布受限'"
apollo-detail=
"'您不能发布哟~ ' + pageContext.env + '环境配置的编辑和发布必须为不同的人,请找另一个具有当前namespace发布权的人操作发布~'"
apollo-show-cancel-btn=
"false"
></apolloconfirmdialog>
<apolloconfirmdialog
apollo-dialog-id=
"'rollbackAlertDialog'"
apollo-title=
"'回滚'"
apollo-detail=
"'确定要回滚吗?'"
apollo-show-cancel-btn=
"true"
apollo-confirm=
"rollback"
></apolloconfirmdialog>
...
...
@@ -373,6 +370,7 @@
<script
type=
"application/javascript"
src=
"scripts/directive/rollback-modal-directive.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive/gray-release-rules-modal-directive.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive/merge-and-publish-modal-directive.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive/publish-deny-modal-directive.js"
></script>
<!--controller-->
<script
type=
"application/javascript"
src=
"scripts/controller/config/ConfigNamespaceController.js"
></script>
...
...
apollo-portal/src/main/resources/static/config/history.html
浏览文件 @
4f3dd644
...
...
@@ -75,7 +75,8 @@
<h5
class=
"col-md-7 word-break"
ng-show=
"releaseHistory.operation == 8"
>
删除灰度(全量发布)
</h5>
<h6
class=
"col-md-5 text-right"
ng-bind=
"releaseHistory.releaseTimeFormatted"
></h6>
<span
class=
"label label-warning no-radius emergency-publish"
ng-if=
"releaseHistory.operationContext.isEmergencyPublish"
>
紧急发布
</span>
</div>
</div>
...
...
apollo-portal/src/main/resources/static/scripts/directive/merge-and-publish-modal-directive.js
浏览文件 @
4f3dd644
...
...
@@ -20,17 +20,22 @@ function mergeAndPublishDirective(AppUtil, EventManager) {
var
branch
=
context
.
branch
;
scope
.
toReleaseNamespace
=
branch
;
scope
.
toDeleteBranch
=
branch
;
scope
.
isEmergencyPublish
=
context
.
isEmergencyPublish
?
context
.
isEmergencyPublish
:
false
;
var
branchStatusMerge
=
2
;
branch
.
branchStatus
=
branchStatusMerge
;
branch
.
mergeAndPublish
=
true
;
AppUtil
.
showModal
(
'
#mergeAndPublishModal
'
);
});
function
showReleaseModal
()
{
EventManager
.
emit
(
EventManager
.
EventType
.
PUBLISH_NAMESPACE
,
{
namespace
:
scope
.
toReleaseNamespace
});
EventManager
.
emit
(
EventManager
.
EventType
.
PUBLISH_NAMESPACE
,
{
namespace
:
scope
.
toReleaseNamespace
,
isEmergencyPublish
:
scope
.
isEmergencyPublish
});
}
}
...
...
apollo-portal/src/main/resources/static/scripts/directive/namespace-panel-directive.js
浏览文件 @
4f3dd644
...
...
@@ -279,16 +279,12 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
}
function
initNamespaceLock
(
namespace
)
{
NamespaceLockService
.
get_namespace_lock
(
scope
.
appId
,
scope
.
env
,
namespace
.
baseInfo
.
clusterName
,
namespace
.
baseInfo
.
namespaceName
)
NamespaceLockService
.
get_namespace_lock
(
scope
.
appId
,
scope
.
env
,
namespace
.
baseInfo
.
clusterName
,
namespace
.
baseInfo
.
namespaceName
)
.
then
(
function
(
result
)
{
if
(
result
.
dataChangeCreatedBy
)
{
namespace
.
lockOwner
=
result
.
dataChangeCreatedBy
;
}
else
{
namespace
.
lockOwner
=
""
;
}
namespace
.
lockOwner
=
result
.
lockOwner
;
namespace
.
isEmergencyPublishAllowed
=
result
.
isEmergencyPublishAllowed
;
});
}
...
...
@@ -748,7 +744,10 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
return
;
}
else
if
(
namespace
.
lockOwner
&&
scope
.
user
==
namespace
.
lockOwner
)
{
//can not publish if config modified by himself
AppUtil
.
showModal
(
'
#releaseDenyDialog
'
);
EventManager
.
emit
(
EventManager
.
EventType
.
PUBLISH_DENY
,
{
namespace
:
namespace
,
mergeAndPublish
:
false
});
return
;
}
...
...
@@ -766,12 +765,14 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
var
parentNamespace
=
branch
.
parentNamespace
;
if
(
!
parentNamespace
.
hasReleasePermission
)
{
AppUtil
.
showModal
(
'
#releaseNoPermissionDialog
'
);
}
else
if
(
branch
.
lockOwner
&&
scope
.
user
==
branch
.
lockOwner
)
{
AppUtil
.
showModal
(
'
#releaseDenyDialog
'
);
}
else
if
(
parentNamespace
.
itemModifiedCnt
>
0
)
{
AppUtil
.
showModal
(
'
#mergeAndReleaseDenyDialog
'
);
}
else
{
}
else
if
(
branch
.
lockOwner
&&
scope
.
user
==
branch
.
lockOwner
)
{
EventManager
.
emit
(
EventManager
.
EventType
.
PUBLISH_DENY
,
{
namespace
:
branch
,
mergeAndPublish
:
true
});
}
else
{
EventManager
.
emit
(
EventManager
.
EventType
.
MERGE_AND_PUBLISH_NAMESPACE
,
{
branch
:
branch
});
}
}
...
...
apollo-portal/src/main/resources/static/scripts/directive/publish-deny-modal-directive.js
0 → 100644
浏览文件 @
4f3dd644
directive_module
.
directive
(
'
publishdenymodal
'
,
publishDenyDirective
);
function
publishDenyDirective
(
AppUtil
,
EventManager
)
{
return
{
restrict
:
'
E
'
,
templateUrl
:
'
../../views/component/publish-deny-modal.html
'
,
transclude
:
true
,
replace
:
true
,
scope
:
{
},
link
:
function
(
scope
)
{
var
MODAL_ID
=
"
#publishDenyModal
"
;
EventManager
.
subscribe
(
EventManager
.
EventType
.
PUBLISH_DENY
,
function
(
context
)
{
scope
.
toReleaseNamespace
=
context
.
namespace
;
scope
.
mergeAndPublish
=
!!
context
.
mergeAndPublish
;
AppUtil
.
showModal
(
MODAL_ID
);
});
scope
.
emergencyPublish
=
emergencyPublish
;
function
emergencyPublish
()
{
AppUtil
.
hideModal
(
MODAL_ID
);
if
(
scope
.
mergeAndPublish
)
{
EventManager
.
emit
(
EventManager
.
EventType
.
MERGE_AND_PUBLISH_NAMESPACE
,
{
branch
:
scope
.
toReleaseNamespace
,
isEmergencyPublish
:
true
});
}
else
{
EventManager
.
emit
(
EventManager
.
EventType
.
PUBLISH_NAMESPACE
,
{
namespace
:
scope
.
toReleaseNamespace
,
isEmergencyPublish
:
true
});
}
}
}
}
}
apollo-portal/src/main/resources/static/scripts/directive/release-modal-directive.js
浏览文件 @
4f3dd644
...
...
@@ -19,12 +19,14 @@ function releaseModalDirective(toastr, AppUtil, EventManager, ReleaseService, Na
scope
.
releaseBtnDisabled
=
false
;
scope
.
releaseChangeViewType
=
'
change
'
;
scope
.
releaseComment
=
''
;
scope
.
isEmergencyPublish
=
false
;
EventManager
.
subscribe
(
EventManager
.
EventType
.
PUBLISH_NAMESPACE
,
function
(
context
)
{
var
namespace
=
context
.
namespace
;
scope
.
toReleaseNamespace
=
context
.
namespace
;
scope
.
isEmergencyPublish
=
!!
context
.
isEmergencyPublish
;
var
date
=
new
Date
().
Format
(
"
yyyyMMddhhmmss
"
);
if
(
namespace
.
mergeAndPublish
)
{
...
...
@@ -55,7 +57,8 @@ function releaseModalDirective(toastr, AppUtil, EventManager, ReleaseService, Na
scope
.
toReleaseNamespace
.
baseInfo
.
clusterName
,
scope
.
toReleaseNamespace
.
baseInfo
.
namespaceName
,
scope
.
toReleaseNamespace
.
releaseTitle
,
scope
.
releaseComment
).
then
(
scope
.
releaseComment
,
scope
.
isEmergencyPublish
).
then
(
function
(
result
)
{
AppUtil
.
hideModal
(
'
#releaseModal
'
);
toastr
.
success
(
"
发布成功
"
);
...
...
@@ -83,7 +86,8 @@ function releaseModalDirective(toastr, AppUtil, EventManager, ReleaseService, Na
scope
.
toReleaseNamespace
.
baseInfo
.
namespaceName
,
scope
.
toReleaseNamespace
.
baseInfo
.
clusterName
,
scope
.
toReleaseNamespace
.
releaseTitle
,
scope
.
releaseComment
).
then
(
scope
.
releaseComment
,
scope
.
isEmergencyPublish
).
then
(
function
(
result
)
{
AppUtil
.
hideModal
(
'
#releaseModal
'
);
toastr
.
success
(
"
灰度发布成功
"
);
...
...
@@ -98,7 +102,9 @@ function releaseModalDirective(toastr, AppUtil, EventManager, ReleaseService, Na
item
.
isModified
=
false
;
}
});
//reset namespace status
scope
.
toReleaseNamespace
.
itemModifiedCnt
=
0
;
scope
.
toReleaseNamespace
.
lockOwner
=
undefined
;
//check rules
if
(
!
scope
.
toReleaseNamespace
.
rules
...
...
@@ -125,6 +131,7 @@ function releaseModalDirective(toastr, AppUtil, EventManager, ReleaseService, Na
scope
.
toReleaseNamespace
.
baseInfo
.
clusterName
,
scope
.
toReleaseNamespace
.
releaseTitle
,
scope
.
releaseComment
,
scope
.
isEmergencyPublish
,
scope
.
toReleaseNamespace
.
mergeAfterDeleteBranch
)
.
then
(
function
(
result
)
{
...
...
apollo-portal/src/main/resources/static/scripts/services/EventManager.js
浏览文件 @
4f3dd644
...
...
@@ -131,7 +131,8 @@ appService.service('EventManager', [function () {
PRE_ROLLBACK_NAMESPACE
:
'
pre_rollback_namespace
'
,
ROLLBACK_NAMESPACE
:
'
rollback_namespace
'
,
EDIT_GRAY_RELEASE_RULES
:
'
edit_gray_release_rules
'
,
UPDATE_GRAY_RELEASE_RULES
:
'
update_gray_release_rules
'
UPDATE_GRAY_RELEASE_RULES
:
'
update_gray_release_rules
'
,
PUBLISH_DENY
:
'
publish_deny
'
}
}
...
...
apollo-portal/src/main/resources/static/scripts/services/NamespaceBranchService.js
浏览文件 @
4f3dd644
...
...
@@ -83,7 +83,7 @@ appService.service('NamespaceBranchService', ['$resource', '$q', function ($reso
}
function
merge_and_release_branch
(
appId
,
env
,
clusterName
,
namespaceName
,
branchName
,
title
,
comment
,
deleteBranch
)
{
branchName
,
title
,
comment
,
isEmergencyPublish
,
deleteBranch
)
{
var
d
=
$q
.
defer
();
resource
.
merge_and_release_branch
({
appId
:
appId
,
...
...
@@ -94,7 +94,8 @@ appService.service('NamespaceBranchService', ['$resource', '$q', function ($reso
deleteBranch
:
deleteBranch
},
{
releaseTitle
:
title
,
releaseComment
:
comment
releaseComment
:
comment
,
isEmergencyPublish
:
isEmergencyPublish
},
function
(
result
)
{
d
.
resolve
(
result
);
...
...
apollo-portal/src/main/resources/static/scripts/services/NamespaceLockService.js
浏览文件 @
4f3dd644
...
...
@@ -2,7 +2,7 @@ appService.service('NamespaceLockService', ['$resource', '$q', function ($resour
var
resource
=
$resource
(
''
,
{},
{
get_namespace_lock
:
{
method
:
'
GET
'
,
url
:
'
apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/lock
'
url
:
'
apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/lock
-info
'
}
});
...
...
apollo-portal/src/main/resources/static/scripts/services/ReleaseService.js
浏览文件 @
4f3dd644
...
...
@@ -28,7 +28,7 @@ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q
}
});
function
createRelease
(
appId
,
env
,
clusterName
,
namespaceName
,
releaseTitle
,
comment
)
{
function
createRelease
(
appId
,
env
,
clusterName
,
namespaceName
,
releaseTitle
,
comment
,
isEmergencyPublish
)
{
var
d
=
$q
.
defer
();
resource
.
release
({
appId
:
appId
,
...
...
@@ -37,7 +37,8 @@ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q
namespaceName
:
namespaceName
},
{
releaseTitle
:
releaseTitle
,
releaseComment
:
comment
releaseComment
:
comment
,
isEmergencyPublish
:
isEmergencyPublish
},
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
...
...
@@ -46,18 +47,19 @@ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q
return
d
.
promise
;
}
function
createGrayRelease
(
appId
,
env
,
clusterName
,
namespaceName
,
branchName
,
releaseTitle
,
comment
)
{
function
createGrayRelease
(
appId
,
env
,
clusterName
,
namespaceName
,
branchName
,
releaseTitle
,
comment
,
isEmergencyPublish
)
{
var
d
=
$q
.
defer
();
resource
.
gray_release
({
appId
:
appId
,
env
:
env
,
clusterName
:
clusterName
,
namespaceName
:
namespaceName
,
branchName
:
branchName
},
{
releaseTitle
:
releaseTitle
,
releaseComment
:
comment
},
function
(
result
)
{
appId
:
appId
,
env
:
env
,
clusterName
:
clusterName
,
namespaceName
:
namespaceName
,
branchName
:
branchName
},
{
releaseTitle
:
releaseTitle
,
releaseComment
:
comment
,
isEmergencyPublish
:
isEmergencyPublish
},
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
d
.
reject
(
result
);
...
...
@@ -98,7 +100,7 @@ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q
});
return
d
.
promise
;
}
function
findLatestActiveRelease
(
appId
,
env
,
clusterName
,
namespaceName
)
{
var
d
=
$q
.
defer
();
resource
.
find_active_releases
({
...
...
@@ -109,7 +111,7 @@ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q
page
:
0
,
size
:
1
},
function
(
result
)
{
if
(
result
&&
result
.
length
){
if
(
result
&&
result
.
length
)
{
d
.
resolve
(
result
[
0
]);
}
...
...
apollo-portal/src/main/resources/static/scripts/services/ServerConfigService.js
浏览文件 @
4f3dd644
...
...
@@ -2,7 +2,7 @@ appService.service('ServerConfigService', ['$resource', '$q', function ($resourc
var
server_config_resource
=
$resource
(
''
,
{},
{
create_server_config
:
{
method
:
'
POST
'
,
url
:
'
/server/config
'
url
:
'
/server/config
'
}
});
return
{
...
...
apollo-portal/src/main/resources/static/styles/common-style.css
浏览文件 @
4f3dd644
...
...
@@ -607,6 +607,12 @@ table th {
padding
:
0
;
}
.release-history
.release-history-list
.emergency-publish
{
position
:
absolute
;
left
:
0
;
top
:
0
;
}
.release-history
.release-history-list
.load-more
{
height
:
45px
;
background
:
#f5f5f5
;
...
...
apollo-portal/src/main/resources/static/views/component/publish-deny-modal.html
0 → 100644
浏览文件 @
4f3dd644
<div
class=
"modal fade"
id=
"publishDenyModal"
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>
</div>
<div
class=
"modal-body"
>
您不能发布哟~{{env}}环境配置的编辑和发布必须为不同的人,请找另一个具有当前namespace发布权的人操作发布~
<span
ng-if=
"toReleaseNamespace.isEmergencyPublishAllowed"
>
<br><br><small>
(如果是非工作时间或者特殊情况,您可以通过点击
<mark>
紧急发布
</mark>
按钮进行发布)
</small>
</span>
</div>
<div
class=
"modal-footer"
>
<button
type=
"button"
class=
"btn btn-danger"
data-dismiss=
"modal"
ng-if=
"toReleaseNamespace.isEmergencyPublishAllowed"
ng-click=
"emergencyPublish()"
>
紧急发布
</button>
<button
type=
"button"
class=
"btn btn-primary"
data-dismiss=
"modal"
>
关闭
</button>
</div>
</div>
</div>
</div>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录