Commit 31fe0649 by 张乐 Committed by GitHub

Merge pull request #304 from lepdou/0627_0701

namespace 一次发布只能被一个人修改
parents 1b550c48 41bfee44
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"));
}
}
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 {
}
...@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestMethod; ...@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; 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.Commit;
import com.ctrip.framework.apollo.biz.entity.Item; import com.ctrip.framework.apollo.biz.entity.Item;
import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.entity.Namespace;
...@@ -32,6 +33,7 @@ public class ItemController { ...@@ -32,6 +33,7 @@ public class ItemController {
@Autowired @Autowired
private CommitService commitService; private CommitService commitService;
@PreAcquireNamespaceLock
@RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.POST) @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.POST)
public ItemDTO createOrUpdate(@PathVariable("appId") String appId, public ItemDTO createOrUpdate(@PathVariable("appId") String appId,
@PathVariable("clusterName") String clusterName, @PathVariable("clusterName") String clusterName,
...@@ -70,6 +72,7 @@ public class ItemController { ...@@ -70,6 +72,7 @@ public class ItemController {
return dto; return dto;
} }
@PreAcquireNamespaceLock
@RequestMapping(path = "/items/{itemId}", method = RequestMethod.DELETE) @RequestMapping(path = "/items/{itemId}", method = RequestMethod.DELETE)
public void delete(@PathVariable("itemId") long itemId, @RequestParam String operator) { public void delete(@PathVariable("itemId") long itemId, @RequestParam String operator) {
Item entity = itemService.findOne(itemId); Item entity = itemService.findOne(itemId);
......
...@@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestMapping; ...@@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; 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.biz.service.ItemSetService;
import com.ctrip.framework.apollo.core.dto.ItemChangeSets; import com.ctrip.framework.apollo.core.dto.ItemChangeSets;
...@@ -18,6 +19,7 @@ public class ItemSetController { ...@@ -18,6 +19,7 @@ public class ItemSetController {
@Autowired @Autowired
private ItemSetService itemSetService; private ItemSetService itemSetService;
@PreAcquireNamespaceLock
@RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset", method = RequestMethod.POST) @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset", method = RequestMethod.POST)
public ResponseEntity<Void> create(@PathVariable String appId, @PathVariable String clusterName, public ResponseEntity<Void> create(@PathVariable String appId, @PathVariable String clusterName,
@PathVariable String namespaceName, @RequestBody ItemChangeSets changeSet) { @PathVariable String namespaceName, @RequestBody ItemChangeSets changeSet) {
......
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);
}
}
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;
}
}
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);
}
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);
}
}
...@@ -26,6 +26,7 @@ import java.util.Map; ...@@ -26,6 +26,7 @@ import java.util.Map;
*/ */
@Service @Service
public class ReleaseService { public class ReleaseService {
private Gson gson = new Gson();
@Autowired @Autowired
private ReleaseRepository releaseRepository; private ReleaseRepository releaseRepository;
...@@ -36,7 +37,9 @@ public class ReleaseService { ...@@ -36,7 +37,9 @@ public class ReleaseService {
@Autowired @Autowired
private AuditService auditService; private AuditService auditService;
private Gson gson = new Gson(); @Autowired
private NamespaceLockService namespaceLockService;
public Release findOne(long releaseId) { public Release findOne(long releaseId) {
Release release = releaseRepository.findOne(releaseId); Release release = releaseRepository.findOne(releaseId);
...@@ -54,6 +57,7 @@ public class ReleaseService { ...@@ -54,6 +57,7 @@ public class ReleaseService {
@Transactional @Transactional
public Release buildRelease(String name, String comment, Namespace namespace, String owner) { public Release buildRelease(String name, String comment, Namespace namespace, String owner) {
List<Item> items = itemRepository.findByNamespaceIdOrderByLineNumAsc(namespace.getId()); List<Item> items = itemRepository.findByNamespaceIdOrderByLineNumAsc(namespace.getId());
Map<String, String> configurations = new HashMap<String, String>(); Map<String, String> configurations = new HashMap<String, String>();
for (Item item : items) { for (Item item : items) {
...@@ -76,6 +80,7 @@ public class ReleaseService { ...@@ -76,6 +80,7 @@ public class ReleaseService {
release.setConfigurations(gson.toJson(configurations)); release.setConfigurations(gson.toJson(configurations));
release = releaseRepository.save(release); release = releaseRepository.save(release);
namespaceLockService.unlock(namespace.getId());
auditService.audit(Release.class.getSimpleName(), release.getId(), Audit.OP.INSERT, auditService.audit(Release.class.getSimpleName(), release.getId(), Audit.OP.INSERT,
release.getDataChangeCreatedBy()); release.getDataChangeCreatedBy());
......
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;
}
}
...@@ -10,7 +10,6 @@ import org.springframework.context.ConfigurableApplicationContext; ...@@ -10,7 +10,6 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableAspectJAutoProxy @EnableAspectJAutoProxy
......
...@@ -3,6 +3,7 @@ package com.ctrip.framework.apollo.portal.api; ...@@ -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.AppNamespaceDTO;
import com.ctrip.framework.apollo.core.dto.CommitDTO; 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.enums.Env;
import com.ctrip.framework.apollo.core.dto.AppDTO; import com.ctrip.framework.apollo.core.dto.AppDTO;
import com.ctrip.framework.apollo.core.dto.ClusterDTO; import com.ctrip.framework.apollo.core.dto.ClusterDTO;
...@@ -193,4 +194,15 @@ public class AdminServiceAPI { ...@@ -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);
}
}
} }
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);
}
}
}
...@@ -16,7 +16,6 @@ import com.ctrip.framework.apollo.core.dto.ItemDTO; ...@@ -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.NamespaceDTO;
import com.ctrip.framework.apollo.core.dto.ReleaseDTO; import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.exception.BadRequestException; 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.exception.ServiceException;
import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
...@@ -67,14 +66,8 @@ public class ConfigService { ...@@ -67,14 +66,8 @@ public class ConfigService {
return; return;
} }
try {
changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId()); changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId());
itemAPI.updateItems(appId, env, clusterName, namespaceName, changeSets); 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());
}
} }
......
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);
}
}
...@@ -90,13 +90,13 @@ ...@@ -90,13 +90,13 @@
<div class="panel"> <div class="panel">
<header class="panel-heading"> <header class="panel-heading">
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-5">
<b ng-bind="namespace.namespace.namespaceName" style="font-size: 20px;"></b> <b ng-bind="namespace.namespace.namespaceName" style="font-size: 20px;"></b>
<span class="label label-primary" ng-show="namespace.itemModifiedCnt > 0">有修改 <span class="label label-primary" ng-show="namespace.itemModifiedCnt > 0">有修改
<span class="badge label" ng-bind="namespace.itemModifiedCnt"></span></span> <span class="badge label" ng-bind="namespace.itemModifiedCnt"></span></span>
<span class="label label-warning" ng-show="namespace.lockOwner">当前修改者:{{namespace.lockOwner}}</span>
</div> </div>
<div class="col-md-8 text-right"> <div class="col-md-7 text-right">
<button type="button" <button type="button"
class="btn btn-success btn-sm J_tableview_btn" class="btn btn-success btn-sm J_tableview_btn"
ng-show="namespace.hasReleasePermission || namespace.hasModifyPermission" ng-show="namespace.hasReleasePermission || namespace.hasModifyPermission"
...@@ -124,7 +124,7 @@ ...@@ -124,7 +124,7 @@
授权 授权
</a> </a>
<a type="button" class="btn btn-default btn-sm J_tableview_btn" <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"> ng-show="namespace.hasModifyPermission">
<img src="img/sync.png"> <img src="img/sync.png">
同步配置 同步配置
...@@ -179,7 +179,6 @@ ...@@ -179,7 +179,6 @@
<button type="button" class="btn btn-primary btn-sm" <button type="button" class="btn btn-primary btn-sm"
ng-show="namespace.viewType == 'table' && namespace.hasModifyPermission" ng-show="namespace.viewType == 'table' && namespace.hasModifyPermission"
data-toggle="modal" data-target="#itemModal"
ng-click="createItem(namespace)"> ng-click="createItem(namespace)">
<img src="img/plus.png"> <img src="img/plus.png">
新增配置 新增配置
...@@ -252,11 +251,9 @@ ...@@ -252,11 +251,9 @@
<td width="10%"> <td width="10%">
<img src="img/edit.png" data-tooltip="tooltip" data-placement="bottom" title="修改" <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-click="editItem(namespace, config.item)"
ng-show="namespace.hasModifyPermission"> ng-show="namespace.hasModifyPermission">
<img style="margin-left: 5px;" src="img/cancel.png" data-toggle="modal" <img style="margin-left: 5px;" src="img/cancel.png"
data-target="#deleteConfirmDialog"
data-tooltip="tooltip" data-placement="bottom" title="删除" data-tooltip="tooltip" data-placement="bottom" title="删除"
ng-click="preDeleteItem(namespace, config.item.id)" ng-click="preDeleteItem(namespace, config.item.id)"
ng-show="namespace.hasModifyPermission"> ng-show="namespace.hasModifyPermission">
...@@ -385,6 +382,13 @@ ...@@ -385,6 +382,13 @@
apollo-detail="'您没有发布权限哦~ 请找 ' + masterUsers + ' 分配权限'" apollo-detail="'您没有发布权限哦~ 请找 ' + masterUsers + ' 分配权限'"
apollo-show-cancel-btn="false"></apolloconfirmdialog> 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--> <!--create release modal-->
<form class="modal fade form-horizontal" id="releaseModal" tabindex="-1" role="dialog" <form class="modal fade form-horizontal" id="releaseModal" tabindex="-1" role="dialog"
ng-submit="release()"> ng-submit="release()">
...@@ -604,6 +608,7 @@ ...@@ -604,6 +608,7 @@
<script type="application/javascript" src="scripts/services/ConfigService.js"></script> <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/PermissionService.js"></script>
<script type="application/javascript" src="scripts/services/CommitService.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> <script type="application/javascript" src="scripts/AppUtils.js"></script>
......
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% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment