Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wrr-cat
apollo
提交
31fe0649
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,发现更多精彩内容 >>
提交
31fe0649
编写于
6月 29, 2016
作者:
张
张乐
提交者:
GitHub
6月 29, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #304 from lepdou/0627_0701
namespace 一次发布只能被一个人修改
上级
1b550c48
41bfee44
变更
18
隐藏空白更改
内联
并排
Showing
18 changed file
with
477 addition
and
43 deletion
+477
-43
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/NamespaceLockAspect.java
...ramework/apollo/adminservice/aop/NamespaceLockAspect.java
+129
-0
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/PreAcquireNamespaceLock.java
...work/apollo/adminservice/aop/PreAcquireNamespaceLock.java
+15
-0
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemController.java
...mework/apollo/adminservice/controller/ItemController.java
+3
-0
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemSetController.java
...ork/apollo/adminservice/controller/ItemSetController.java
+2
-0
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceLockController.java
...ollo/adminservice/controller/NamespaceLockController.java
+43
-0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/NamespaceLock.java
.../com/ctrip/framework/apollo/biz/entity/NamespaceLock.java
+26
-0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/NamespaceLockRepository.java
...mework/apollo/biz/repository/NamespaceLockRepository.java
+13
-0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceLockService.java
...ip/framework/apollo/biz/service/NamespaceLockService.java
+27
-0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseService.java
...om/ctrip/framework/apollo/biz/service/ReleaseService.java
+6
-1
apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/NamespaceLockDTO.java
...com/ctrip/framework/apollo/core/dto/NamespaceLockDTO.java
+14
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/PortalApplication.java
.../com/ctrip/framework/apollo/portal/PortalApplication.java
+0
-1
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java
...om/ctrip/framework/apollo/portal/api/AdminServiceAPI.java
+12
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceLockController.java
...ork/apollo/portal/controller/NamespaceLockController.java
+36
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ConfigService.java
.../ctrip/framework/apollo/portal/service/ConfigService.java
+2
-9
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceLockService.java
...framework/apollo/portal/service/NamespaceLockService.java
+22
-0
apollo-portal/src/main/resources/static/config.html
apollo-portal/src/main/resources/static/config.html
+13
-8
apollo-portal/src/main/resources/static/scripts/controller/app/ConfigNamespaceController.js
...tatic/scripts/controller/app/ConfigNamespaceController.js
+90
-24
apollo-portal/src/main/resources/static/scripts/services/NamespaceLockService.js
...resources/static/scripts/services/NamespaceLockService.js
+24
-0
未找到文件。
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/NamespaceLockAspect.java
0 → 100644
浏览文件 @
31fe0649
package
com.ctrip.framework.apollo.adminservice.aop
;
import
com.ctrip.framework.apollo.biz.entity.Item
;
import
com.ctrip.framework.apollo.biz.entity.Namespace
;
import
com.ctrip.framework.apollo.biz.entity.NamespaceLock
;
import
com.ctrip.framework.apollo.biz.service.ItemService
;
import
com.ctrip.framework.apollo.biz.service.NamespaceLockService
;
import
com.ctrip.framework.apollo.biz.service.NamespaceService
;
import
com.ctrip.framework.apollo.biz.service.ServerConfigService
;
import
com.ctrip.framework.apollo.core.dto.ItemChangeSets
;
import
com.ctrip.framework.apollo.core.dto.ItemDTO
;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Before
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.dao.DataIntegrityViolationException
;
import
org.springframework.stereotype.Component
;
/**
* 一个namespace在一次发布中只能允许一个人修改配置
* 通过数据库lock表来实现
*/
@Aspect
@Component
public
class
NamespaceLockAspect
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
NamespaceLockAspect
.
class
);
private
static
final
String
NAMESPACE_LOCK_SWITCH_CONFIG_KEY
=
"namespace.lock.switch"
;
@Autowired
private
ServerConfigService
serverConfigService
;
@Autowired
private
NamespaceLockService
namespaceLockService
;
@Autowired
private
NamespaceService
namespaceService
;
@Autowired
private
ItemService
itemService
;
@Before
(
"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, item, ..)"
)
public
void
requireLockAdvice
(
String
appId
,
String
clusterName
,
String
namespaceName
,
ItemDTO
item
)
{
acquireLock
(
appId
,
clusterName
,
namespaceName
,
item
.
getDataChangeLastModifiedBy
());
}
@Before
(
"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, changeSet, ..)"
)
public
void
requireLockAdvice
(
String
appId
,
String
clusterName
,
String
namespaceName
,
ItemChangeSets
changeSet
)
{
acquireLock
(
appId
,
clusterName
,
namespaceName
,
changeSet
.
getDataChangeLastModifiedBy
());
}
@Before
(
"@annotation(PreAcquireNamespaceLock) && args(itemId, operator, ..)"
)
public
void
requireLockAdvice
(
long
itemId
,
String
operator
)
{
Item
item
=
itemService
.
findOne
(
itemId
);
acquireLock
(
item
.
getNamespaceId
(),
operator
);
}
private
void
acquireLock
(
String
appId
,
String
clusterName
,
String
namespaceName
,
String
currentUser
)
{
if
(
isNamespaceLockSwitchOff
())
{
return
;
}
Namespace
namespace
=
namespaceService
.
findOne
(
appId
,
clusterName
,
namespaceName
);
acquireLock
(
namespace
,
currentUser
);
}
private
void
acquireLock
(
long
namespaceId
,
String
currentUser
)
{
Namespace
namespace
=
namespaceService
.
findOne
(
namespaceId
);
acquireLock
(
namespace
,
currentUser
);
}
private
void
acquireLock
(
Namespace
namespace
,
String
currentUser
)
{
if
(
namespace
==
null
)
{
throw
new
BadRequestException
(
"namespace not exist."
);
}
long
namespaceId
=
namespace
.
getId
();
NamespaceLock
namespaceLock
=
namespaceLockService
.
findLock
(
namespaceId
);
if
(
namespaceLock
==
null
)
{
try
{
tryLock
(
namespaceId
,
currentUser
);
//lock success
}
catch
(
DataIntegrityViolationException
e
)
{
//lock fail
acquireLockFail
(
namespace
,
currentUser
);
}
catch
(
Exception
e
){
logger
.
error
(
"try lock error"
,
e
);
throw
e
;
}
}
else
{
//check lock owner is current user
String
lockOwner
=
namespaceLock
.
getDataChangeCreatedBy
();
if
(!
lockOwner
.
equals
(
currentUser
))
{
acquireLockFail
(
namespace
,
currentUser
);
}
}
}
private
void
tryLock
(
long
namespaceId
,
String
user
)
{
NamespaceLock
lock
=
new
NamespaceLock
();
lock
.
setNamespaceId
(
namespaceId
);
lock
.
setDataChangeCreatedBy
(
user
);
lock
.
setDataChangeLastModifiedBy
(
user
);
namespaceLockService
.
tryLock
(
lock
);
}
private
void
acquireLockFail
(
Namespace
namespace
,
String
currentUser
){
NamespaceLock
namespaceLock
=
namespaceLockService
.
findLock
(
namespace
.
getId
());
if
(
namespaceLock
==
null
){
acquireLock
(
namespace
,
currentUser
);
}
String
lockOwner
=
namespaceLock
.
getDataChangeCreatedBy
();
throw
new
BadRequestException
(
"namespace:"
+
namespace
.
getNamespaceName
()
+
" is modifying by "
+
lockOwner
);
}
private
boolean
isNamespaceLockSwitchOff
()
{
return
!
"true"
.
equals
(
serverConfigService
.
getValue
(
NAMESPACE_LOCK_SWITCH_CONFIG_KEY
,
"false"
));
}
}
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/PreAcquireNamespaceLock.java
0 → 100644
浏览文件 @
31fe0649
package
com.ctrip.framework.apollo.adminservice.aop
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* 标识方法需要获取到namespace的lock才能执行
*/
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
PreAcquireNamespaceLock
{
}
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemController.java
浏览文件 @
31fe0649
...
...
@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
import
com.ctrip.framework.apollo.adminservice.aop.PreAcquireNamespaceLock
;
import
com.ctrip.framework.apollo.biz.entity.Commit
;
import
com.ctrip.framework.apollo.biz.entity.Item
;
import
com.ctrip.framework.apollo.biz.entity.Namespace
;
...
...
@@ -32,6 +33,7 @@ public class ItemController {
@Autowired
private
CommitService
commitService
;
@PreAcquireNamespaceLock
@RequestMapping
(
path
=
"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items"
,
method
=
RequestMethod
.
POST
)
public
ItemDTO
createOrUpdate
(
@PathVariable
(
"appId"
)
String
appId
,
@PathVariable
(
"clusterName"
)
String
clusterName
,
...
...
@@ -70,6 +72,7 @@ public class ItemController {
return
dto
;
}
@PreAcquireNamespaceLock
@RequestMapping
(
path
=
"/items/{itemId}"
,
method
=
RequestMethod
.
DELETE
)
public
void
delete
(
@PathVariable
(
"itemId"
)
long
itemId
,
@RequestParam
String
operator
)
{
Item
entity
=
itemService
.
findOne
(
itemId
);
...
...
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemSetController.java
浏览文件 @
31fe0649
...
...
@@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RestController
;
import
com.ctrip.framework.apollo.adminservice.aop.PreAcquireNamespaceLock
;
import
com.ctrip.framework.apollo.biz.service.ItemSetService
;
import
com.ctrip.framework.apollo.core.dto.ItemChangeSets
;
...
...
@@ -18,6 +19,7 @@ public class ItemSetController {
@Autowired
private
ItemSetService
itemSetService
;
@PreAcquireNamespaceLock
@RequestMapping
(
path
=
"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset"
,
method
=
RequestMethod
.
POST
)
public
ResponseEntity
<
Void
>
create
(
@PathVariable
String
appId
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
,
@RequestBody
ItemChangeSets
changeSet
)
{
...
...
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceLockController.java
0 → 100644
浏览文件 @
31fe0649
package
com.ctrip.framework.apollo.adminservice.controller
;
import
com.ctrip.framework.apollo.biz.entity.Namespace
;
import
com.ctrip.framework.apollo.biz.entity.NamespaceLock
;
import
com.ctrip.framework.apollo.biz.service.NamespaceLockService
;
import
com.ctrip.framework.apollo.biz.service.NamespaceService
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.core.dto.NamespaceLockDTO
;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
com.ctrip.framework.apollo.core.exception.NotFoundException
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
@RestController
public
class
NamespaceLockController
{
@Autowired
private
NamespaceLockService
namespaceLockService
;
@Autowired
private
NamespaceService
namespaceService
;
@RequestMapping
(
"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock"
)
public
NamespaceLockDTO
getNamespaceLockOwner
(
@PathVariable
String
appId
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
){
Namespace
namespace
=
namespaceService
.
findOne
(
appId
,
clusterName
,
namespaceName
);
if
(
namespace
==
null
){
throw
new
BadRequestException
(
"namespace not exist."
);
}
NamespaceLock
lock
=
namespaceLockService
.
findLock
(
namespace
.
getId
());
if
(
lock
==
null
){
throw
new
NotFoundException
(
namespaceName
+
" is not locked"
);
}
return
BeanUtils
.
transfrom
(
NamespaceLockDTO
.
class
,
lock
);
}
}
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/NamespaceLock.java
0 → 100644
浏览文件 @
31fe0649
package
com.ctrip.framework.apollo.biz.entity
;
import
com.ctrip.framework.apollo.common.entity.BaseEntity
;
import
org.hibernate.annotations.Where
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.Table
;
@Entity
@Table
(
name
=
"NamespaceLock"
)
@Where
(
clause
=
"isDeleted = 0"
)
public
class
NamespaceLock
extends
BaseEntity
{
@Column
(
name
=
"NamespaceId"
)
private
long
namespaceId
;
public
long
getNamespaceId
()
{
return
namespaceId
;
}
public
void
setNamespaceId
(
long
namespaceId
)
{
this
.
namespaceId
=
namespaceId
;
}
}
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/NamespaceLockRepository.java
0 → 100644
浏览文件 @
31fe0649
package
com.ctrip.framework.apollo.biz.repository
;
import
com.ctrip.framework.apollo.biz.entity.NamespaceLock
;
import
org.springframework.data.repository.PagingAndSortingRepository
;
public
interface
NamespaceLockRepository
extends
PagingAndSortingRepository
<
NamespaceLock
,
Long
>
{
NamespaceLock
findByNamespaceId
(
Long
namespaceId
);
Long
deleteByNamespaceId
(
Long
namespaceId
);
}
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceLockService.java
0 → 100644
浏览文件 @
31fe0649
package
com.ctrip.framework.apollo.biz.service
;
import
com.ctrip.framework.apollo.biz.entity.NamespaceLock
;
import
com.ctrip.framework.apollo.biz.repository.NamespaceLockRepository
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
@Service
public
class
NamespaceLockService
{
@Autowired
private
NamespaceLockRepository
namespaceLockRepository
;
public
NamespaceLock
findLock
(
Long
namespaceId
){
return
namespaceLockRepository
.
findByNamespaceId
(
namespaceId
);
}
public
NamespaceLock
tryLock
(
NamespaceLock
lock
){
return
namespaceLockRepository
.
save
(
lock
);
}
public
void
unlock
(
Long
namespaceId
){
namespaceLockRepository
.
deleteByNamespaceId
(
namespaceId
);
}
}
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseService.java
浏览文件 @
31fe0649
...
...
@@ -26,6 +26,7 @@ import java.util.Map;
*/
@Service
public
class
ReleaseService
{
private
Gson
gson
=
new
Gson
();
@Autowired
private
ReleaseRepository
releaseRepository
;
...
...
@@ -36,7 +37,9 @@ public class ReleaseService {
@Autowired
private
AuditService
auditService
;
private
Gson
gson
=
new
Gson
();
@Autowired
private
NamespaceLockService
namespaceLockService
;
public
Release
findOne
(
long
releaseId
)
{
Release
release
=
releaseRepository
.
findOne
(
releaseId
);
...
...
@@ -54,6 +57,7 @@ public class ReleaseService {
@Transactional
public
Release
buildRelease
(
String
name
,
String
comment
,
Namespace
namespace
,
String
owner
)
{
List
<
Item
>
items
=
itemRepository
.
findByNamespaceIdOrderByLineNumAsc
(
namespace
.
getId
());
Map
<
String
,
String
>
configurations
=
new
HashMap
<
String
,
String
>();
for
(
Item
item
:
items
)
{
...
...
@@ -76,6 +80,7 @@ public class ReleaseService {
release
.
setConfigurations
(
gson
.
toJson
(
configurations
));
release
=
releaseRepository
.
save
(
release
);
namespaceLockService
.
unlock
(
namespace
.
getId
());
auditService
.
audit
(
Release
.
class
.
getSimpleName
(),
release
.
getId
(),
Audit
.
OP
.
INSERT
,
release
.
getDataChangeCreatedBy
());
...
...
apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/NamespaceLockDTO.java
0 → 100644
浏览文件 @
31fe0649
package
com.ctrip.framework.apollo.core.dto
;
public
class
NamespaceLockDTO
extends
BaseDTO
{
private
long
namespaceId
;
public
long
getNamespaceId
()
{
return
namespaceId
;
}
public
void
setNamespaceId
(
long
namespaceId
)
{
this
.
namespaceId
=
namespaceId
;
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/PortalApplication.java
浏览文件 @
31fe0649
...
...
@@ -10,7 +10,6 @@ import org.springframework.context.ConfigurableApplicationContext;
import
org.springframework.context.annotation.ComponentScan
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.EnableAspectJAutoProxy
;
import
org.springframework.context.annotation.PropertySource
;
import
org.springframework.transaction.annotation.EnableTransactionManagement
;
@EnableAspectJAutoProxy
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java
浏览文件 @
31fe0649
...
...
@@ -3,6 +3,7 @@ package com.ctrip.framework.apollo.portal.api;
import
com.ctrip.framework.apollo.core.dto.AppNamespaceDTO
;
import
com.ctrip.framework.apollo.core.dto.CommitDTO
;
import
com.ctrip.framework.apollo.core.dto.NamespaceLockDTO
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.core.dto.AppDTO
;
import
com.ctrip.framework.apollo.core.dto.ClusterDTO
;
...
...
@@ -193,4 +194,15 @@ public class AdminServiceAPI {
}
}
@Service
public
static
class
NamespaceLockAPI
extends
API
{
public
NamespaceLockDTO
getNamespaceLockOwner
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
return
restTemplate
.
getForObject
(
"{host}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock"
,
NamespaceLockDTO
.
class
,
getAdminServiceHost
(
env
),
appId
,
clusterName
,
namespaceName
);
}
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceLockController.java
0 → 100644
浏览文件 @
31fe0649
package
com.ctrip.framework.apollo.portal.controller
;
import
com.ctrip.framework.apollo.core.dto.NamespaceLockDTO
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.core.exception.ServiceException
;
import
com.ctrip.framework.apollo.portal.service.NamespaceLockService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.client.HttpClientErrorException
;
@RestController
public
class
NamespaceLockController
{
@Autowired
private
NamespaceLockService
namespaceLockService
;
@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
){
try
{
return
namespaceLockService
.
getNamespaceLock
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
);
}
catch
(
HttpClientErrorException
e
){
if
(
e
.
getStatusCode
()
==
HttpStatus
.
NOT_FOUND
){
return
null
;
}
throw
new
ServiceException
(
"service error"
,
e
);
}
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ConfigService.java
浏览文件 @
31fe0649
...
...
@@ -16,7 +16,6 @@ import com.ctrip.framework.apollo.core.dto.ItemDTO;
import
com.ctrip.framework.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.framework.apollo.core.dto.ReleaseDTO
;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
com.ctrip.framework.apollo.core.exception.NotFoundException
;
import
com.ctrip.framework.apollo.core.exception.ServiceException
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
...
...
@@ -67,14 +66,8 @@ public class ConfigService {
return
;
}
try
{
changeSets
.
setDataChangeLastModifiedBy
(
userInfoHolder
.
getUser
().
getUserId
());
itemAPI
.
updateItems
(
appId
,
env
,
clusterName
,
namespaceName
,
changeSets
);
}
catch
(
Exception
e
)
{
logger
.
error
(
"itemAPI.updateItems error. appId{},env:{},clusterName:{},namespaceName:{}"
,
appId
,
env
,
clusterName
,
namespaceName
);
throw
new
ServiceException
(
e
.
getMessage
());
}
changeSets
.
setDataChangeLastModifiedBy
(
userInfoHolder
.
getUser
().
getUserId
());
itemAPI
.
updateItems
(
appId
,
env
,
clusterName
,
namespaceName
,
changeSets
);
}
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceLockService.java
0 → 100644
浏览文件 @
31fe0649
package
com.ctrip.framework.apollo.portal.service
;
import
com.ctrip.framework.apollo.core.dto.NamespaceLockDTO
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
@Service
public
class
NamespaceLockService
{
@Autowired
private
AdminServiceAPI
.
NamespaceLockAPI
namespaceLockAPI
;
public
NamespaceLockDTO
getNamespaceLock
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
){
return
namespaceLockAPI
.
getNamespaceLockOwner
(
appId
,
env
,
clusterName
,
namespaceName
);
}
}
apollo-portal/src/main/resources/static/config.html
浏览文件 @
31fe0649
...
...
@@ -90,13 +90,13 @@
<div
class=
"panel"
>
<header
class=
"panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-
4
"
>
<div
class=
"col-md-
5
"
>
<b
ng-bind=
"namespace.namespace.namespaceName"
style=
"font-size: 20px;"
></b>
<span
class=
"label label-primary"
ng-show=
"namespace.itemModifiedCnt > 0"
>
有修改
<span
class=
"badge label"
ng-bind=
"namespace.itemModifiedCnt"
></span></span>
<span
class=
"label label-warning"
ng-show=
"namespace.lockOwner"
>
当前修改者:{{namespace.lockOwner}}
</span>
</div>
<div
class=
"col-md-
8
text-right"
>
<div
class=
"col-md-
7
text-right"
>
<button
type=
"button"
class=
"btn btn-success btn-sm J_tableview_btn"
ng-show=
"namespace.hasReleasePermission || namespace.hasModifyPermission"
...
...
@@ -124,7 +124,7 @@
授权
</a>
<a
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
href=
"config/sync.html?#/appid={{pageContext.appId}}&env={{pageContext.env}}&clusterName={{pageContext.clusterName}}&namespaceName={{namespace.namespace.namespaceName}}
"
ng-click=
"goToSyncPage(namespace)
"
ng-show=
"namespace.hasModifyPermission"
>
<img
src=
"img/sync.png"
>
同步配置
...
...
@@ -179,7 +179,6 @@
<button
type=
"button"
class=
"btn btn-primary btn-sm"
ng-show=
"namespace.viewType == 'table' && namespace.hasModifyPermission"
data-toggle=
"modal"
data-target=
"#itemModal"
ng-click=
"createItem(namespace)"
>
<img
src=
"img/plus.png"
>
新增配置
...
...
@@ -252,11 +251,9 @@
<td
width=
"10%"
>
<img
src=
"img/edit.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改"
data-toggle=
"modal"
data-target=
"#itemModal"
ng-click=
"editItem(namespace, config.item)"
ng-show=
"namespace.hasModifyPermission"
>
<img
style=
"margin-left: 5px;"
src=
"img/cancel.png"
data-toggle=
"modal"
data-target=
"#deleteConfirmDialog"
<img
style=
"margin-left: 5px;"
src=
"img/cancel.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除"
ng-click=
"preDeleteItem(namespace, config.item.id)"
ng-show=
"namespace.hasModifyPermission"
>
...
...
@@ -385,6 +382,13 @@
apollo-detail=
"'您没有发布权限哦~ 请找 ' + masterUsers + ' 分配权限'"
apollo-show-cancel-btn=
"false"
></apolloconfirmdialog>
<apolloconfirmdialog
apollo-dialog-id=
"'namespaceLockedDialog'"
apollo-title=
"'编辑受限'"
apollo-detail=
"'当前namespace正在被 ' + lockOwner + ' 编辑, 一次发布只能被一个人修改.'"
apollo-show-cancel-btn=
"false"
></apolloconfirmdialog>
<apolloconfirmdialog
apollo-dialog-id=
"'releaseDenyDialog'"
apollo-title=
"'发布受限'"
apollo-detail=
"'您不能发布哟~ 编辑和发布不能为同一个人'"
apollo-show-cancel-btn=
"false"
></apolloconfirmdialog>
<!--create release modal-->
<form
class=
"modal fade form-horizontal"
id=
"releaseModal"
tabindex=
"-1"
role=
"dialog"
ng-submit=
"release()"
>
...
...
@@ -604,6 +608,7 @@
<script
type=
"application/javascript"
src=
"scripts/services/ConfigService.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/services/PermissionService.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/services/CommitService.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/services/NamespaceLockService.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/AppUtils.js"
></script>
...
...
apollo-portal/src/main/resources/static/scripts/controller/app/ConfigNamespaceController.js
浏览文件 @
31fe0649
application_module
.
controller
(
"
ConfigNamespaceController
"
,
[
'
$rootScope
'
,
'
$scope
'
,
'
$location
'
,
'
toastr
'
,
'
AppUtil
'
,
'
ConfigService
'
,
'
PermissionService
'
,
'
CommitService
'
,
function
(
$rootScope
,
$scope
,
$location
,
toastr
,
AppUtil
,
ConfigService
,
PermissionService
,
CommitService
)
{
[
'
$rootScope
'
,
'
$scope
'
,
'
$window
'
,
'
$location
'
,
'
toastr
'
,
'
AppUtil
'
,
'
ConfigService
'
,
'
PermissionService
'
,
'
CommitService
'
,
'
NamespaceLockService
'
,
'
UserService
'
,
function
(
$rootScope
,
$scope
,
$window
,
$location
,
toastr
,
AppUtil
,
ConfigService
,
PermissionService
,
CommitService
,
NamespaceLockService
,
UserService
)
{
var
namespace_view_type
=
{
TEXT
:
'
text
'
,
...
...
@@ -31,21 +34,39 @@ application_module.controller("ConfigNamespaceController",
}
namespace
.
isTextEditing
=
false
;
//permission
PermissionService
.
has_modify_namespace_permission
(
$rootScope
.
pageContext
.
appId
,
namespace
.
namespace
.
namespaceName
)
PermissionService
.
has_modify_namespace_permission
(
$rootScope
.
pageContext
.
appId
,
namespace
.
namespace
.
namespaceName
)
.
then
(
function
(
result
)
{
namespace
.
hasModifyPermission
=
result
.
hasPermission
;
namespace
.
hasModifyPermission
=
result
.
hasPermission
;
},
function
(
result
)
{
});
PermissionService
.
has_release_namespace_permission
(
$rootScope
.
pageContext
.
appId
,
namespace
.
namespace
.
namespaceName
)
PermissionService
.
has_release_namespace_permission
(
$rootScope
.
pageContext
.
appId
,
namespace
.
namespace
.
namespaceName
)
.
then
(
function
(
result
)
{
namespace
.
hasReleasePermission
=
result
.
hasPermission
;
},
function
(
result
)
{
});
//lock
NamespaceLockService
.
get_namespace_lock
(
$rootScope
.
pageContext
.
appId
,
$rootScope
.
pageContext
.
env
,
$rootScope
.
pageContext
.
clusterName
,
namespace
.
namespace
.
namespaceName
)
.
then
(
function
(
result
)
{
if
(
result
.
dataChangeCreatedBy
){
namespace
.
lockOwner
=
result
.
dataChangeCreatedBy
;
}
else
{
namespace
.
lockOwner
=
""
;
}
});
});
}
setInterval
(
function
()
{
...
...
@@ -67,17 +88,30 @@ application_module.controller("ConfigNamespaceController",
});
};
UserService
.
load_user
().
then
(
function
(
result
)
{
$scope
.
currentUser
=
result
.
userId
;
});
function
lockCheck
(
namespace
)
{
if
(
namespace
.
lockOwner
&&
$scope
.
currentUser
!=
namespace
.
lockOwner
)
{
$scope
.
lockOwner
=
namespace
.
lockOwner
;
$
(
'
#namespaceLockedDialog
'
).
modal
(
'
show
'
);
return
false
;
}
return
true
;
}
PermissionService
.
get_app_role_users
(
$rootScope
.
pageContext
.
appId
)
.
then
(
function
(
result
)
{
var
masterUsers
=
''
;
result
.
masterUsers
.
forEach
(
function
(
user
)
{
masterUsers
+=
user
.
userId
+
'
,
'
;
});
result
.
masterUsers
.
forEach
(
function
(
user
)
{
masterUsers
+=
user
.
userId
+
'
,
'
;
});
$scope
.
masterUsers
=
masterUsers
.
substring
(
0
,
masterUsers
.
length
-
1
);
},
function
(
result
)
{
});
$scope
.
switchView
=
function
(
namespace
,
viewType
)
{
namespace
.
viewType
=
viewType
;
if
(
namespace_view_type
.
TEXT
==
viewType
)
{
...
...
@@ -89,8 +123,8 @@ application_module.controller("ConfigNamespaceController",
}
};
$scope
.
loadCommitHistory
=
function
(
namespace
)
{
if
(
!
namespace
.
commits
){
$scope
.
loadCommitHistory
=
function
(
namespace
)
{
if
(
!
namespace
.
commits
)
{
namespace
.
commits
=
[];
namespace
.
commitPage
=
0
;
}
...
...
@@ -100,7 +134,7 @@ application_module.controller("ConfigNamespaceController",
namespace
.
namespace
.
namespaceName
,
namespace
.
commitPage
)
.
then
(
function
(
result
)
{
if
(
result
.
length
==
0
){
if
(
result
.
length
==
0
)
{
namespace
.
hasLoadAllCommit
=
true
;
}
for
(
var
i
=
0
;
i
<
result
.
length
;
i
++
)
{
...
...
@@ -126,12 +160,12 @@ application_module.controller("ConfigNamespaceController",
var
itemCnt
=
0
;
namespace
.
items
.
forEach
(
function
(
item
)
{
//deleted key
if
(
!
item
.
item
.
lastModifiedBy
){
if
(
!
item
.
item
.
lastModifiedBy
)
{
return
;
}
if
(
item
.
item
.
key
)
{
//use string \n to display as new line
var
itemValue
=
item
.
item
.
value
.
replace
(
/
\n
/g
,
"
\\
n
"
);
var
itemValue
=
item
.
item
.
value
.
replace
(
/
\n
/g
,
"
\\
n
"
);
result
+=
item
.
item
.
key
+
"
=
"
+
itemValue
+
"
\n
"
;
...
...
@@ -169,6 +203,9 @@ application_module.controller("ConfigNamespaceController",
//文本编辑框状态切换
$scope
.
toggleTextEditStatus
=
function
(
namespace
)
{
if
(
!
lockCheck
(
namespace
)){
return
;
}
namespace
.
isTextEditing
=
!
namespace
.
isTextEditing
;
if
(
namespace
.
isTextEditing
)
{
//切换为编辑状态
namespace
.
commited
=
false
;
...
...
@@ -186,10 +223,13 @@ application_module.controller("ConfigNamespaceController",
$scope
.
toReleaseNamespace
=
{};
$scope
.
prepareReleaseNamespace
=
function
(
namespace
)
{
if
(
!
namespace
.
hasReleasePermission
){
if
(
!
namespace
.
hasReleasePermission
)
{
$
(
'
#releaseNoPermissionDialog
'
).
modal
(
'
show
'
);
return
;
}
else
{
}
else
if
(
namespace
.
lockOwner
&&
$scope
.
currentUser
==
namespace
.
lockOwner
){
//自己修改不能自己发布
$
(
'
#releaseDenyDialog
'
).
modal
(
'
show
'
);
}
else
{
$
(
'
#releaseModal
'
).
modal
(
'
show
'
);
}
$scope
.
releaseTitle
=
new
Date
().
Format
(
"
yyyy-MM-dd hh:mm:ss
"
);
...
...
@@ -236,8 +276,14 @@ application_module.controller("ConfigNamespaceController",
var
toDeleteItemId
=
0
,
toDeleteNamespace
=
{};
$scope
.
preDeleteItem
=
function
(
namespace
,
itemId
)
{
if
(
!
lockCheck
(
namespace
)){
return
;
}
toDeleteNamespace
=
namespace
;
toDeleteItemId
=
itemId
;
$
(
"
#deleteConfirmDialog
"
).
modal
(
"
show
"
);
};
$scope
.
deleteItem
=
function
()
{
...
...
@@ -257,16 +303,26 @@ application_module.controller("ConfigNamespaceController",
var
toOperationNamespaceName
=
''
;
//修改配置
$scope
.
editItem
=
function
(
namespace
,
item
)
{
if
(
!
lockCheck
(
namespace
)){
return
;
}
switchTableViewOperType
(
TABLE_VIEW_OPER_TYPE
.
UPDATE
);
$scope
.
item
=
item
;
toOperationNamespaceName
=
namespace
.
namespace
.
namespaceName
;
$
(
"
#itemModal
"
).
modal
(
"
show
"
);
};
//新增配置
$scope
.
createItem
=
function
(
namespace
)
{
if
(
!
lockCheck
(
namespace
)){
return
;
}
switchTableViewOperType
(
TABLE_VIEW_OPER_TYPE
.
CREATE
);
$scope
.
item
=
{};
toOperationNamespaceName
=
namespace
.
namespace
.
namespaceName
;
$
(
'
#itemModal
'
).
modal
(
'
show
'
);
};
$scope
.
switchToEdit
=
function
()
{
...
...
@@ -306,10 +362,10 @@ application_module.controller("ConfigNamespaceController",
});
}
else
if
(
$scope
.
tableViewOperType
==
TABLE_VIEW_OPER_TYPE
.
UPDATE
)
{
if
(
!
$scope
.
item
.
value
){
if
(
!
$scope
.
item
.
value
)
{
$scope
.
item
.
value
=
""
;
}
if
(
!
$scope
.
item
.
comment
){
if
(
!
$scope
.
item
.
comment
)
{
$scope
.
item
.
comment
=
""
;
}
ConfigService
.
update_item
(
$rootScope
.
pageContext
.
appId
,
...
...
@@ -329,15 +385,25 @@ application_module.controller("ConfigNamespaceController",
}
};
//permission
PermissionService
.
has_assign_user_permission
(
$rootScope
.
pageContext
.
appId
)
.
then
(
function
(
result
)
{
$scope
.
hasAssignUserPermission
=
result
.
hasPermission
;
},
function
(
result
)
{
});
$scope
.
goToSyncPage
=
function
(
namespace
)
{
if
(
!
lockCheck
(
namespace
)){
return
false
;
}
$window
.
location
.
href
=
"
config/sync.html?#/appid=
"
+
$rootScope
.
pageContext
.
appId
+
"
&env=
"
+
$rootScope
.
pageContext
.
env
+
"
&clusterName=
"
+
$rootScope
.
pageContext
.
clusterName
+
"
&namespaceName=
"
+
namespace
.
namespace
.
namespaceName
;
};
$
(
'
.config-item-container
'
).
removeClass
(
'
hide
'
);
}]);
apollo-portal/src/main/resources/static/scripts/services/NamespaceLockService.js
0 → 100644
浏览文件 @
31fe0649
appService
.
service
(
'
NamespaceLockService
'
,
[
'
$resource
'
,
'
$q
'
,
function
(
$resource
,
$q
)
{
var
resource
=
$resource
(
''
,
{},
{
get_namespace_lock
:
{
method
:
'
GET
'
,
url
:
'
apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/lock
'
}
});
return
{
get_namespace_lock
:
function
(
appId
,
env
,
clusterName
,
namespaceName
)
{
var
d
=
$q
.
defer
();
resource
.
get_namespace_lock
({
appId
:
appId
,
env
:
env
,
clusterName
:
clusterName
,
namespaceName
:
namespaceName
},
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
d
.
reject
(
result
);
});
return
d
.
promise
;
}
}
}]);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录