Commit 6c7e3c4c by lepdou

add delete cluster and namespace rest api

parent 92a90e90
......@@ -88,7 +88,11 @@ public class ItemController {
Item beforeUpdateItem = BeanUtils.transfrom(Item.class, managedEntity);
BeanUtils.copyEntityProperties(entity, managedEntity);
//protect. only value,comment,lastModifiedBy can be modified
managedEntity.setValue(entity.getValue());
managedEntity.setComment(entity.getComment());
managedEntity.setDataChangeLastModifiedBy(entity.getDataChangeLastModifiedBy());
entity = itemService.update(managedEntity);
builder.updateItem(beforeUpdateItem, entity);
itemDTO = BeanUtils.transfrom(ItemDTO.class, entity);
......
......@@ -49,7 +49,8 @@ public class NamespaceController {
Namespace entity = namespaceService.findOne(appId, clusterName, namespaceName);
if (entity == null) throw new NotFoundException(
String.format("namespace not found for %s %s %s", appId, clusterName, namespaceName));
namespaceService.delete(entity.getId(), operator);
namespaceService.deleteNamespace(entity, operator);
}
@RequestMapping("/apps/{appId}/clusters/{clusterName}/namespaces")
......
......@@ -4,7 +4,9 @@
<property name="LOG_FILE"
value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}apollo-assembly.log}" />
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="FILE" />
<appender-ref ref="CONSOLE" />
</root>
</configuration>
......@@ -10,8 +10,8 @@ import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "commit")
@SQLDelete(sql = "Update commit set isDeleted = 1 where id = ?")
@Table(name = "Commit")
@SQLDelete(sql = "Update Commit set isDeleted = 1 where id = ?")
@Where(clause = "isDeleted = 0")
public class Commit extends BaseEntity {
......
......@@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.biz.repository;
import com.ctrip.framework.apollo.biz.entity.Commit;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
......@@ -12,4 +14,8 @@ public interface CommitRepository extends PagingAndSortingRepository<Commit, Lon
List<Commit> findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(String appId, String clusterName,
String namespaceName, Pageable pageable);
@Modifying
@Query("update Commit set isdeleted=1,DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3")
int batchDelete(String appId, String clusterName, String namespaceName, String operator);
}
......@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.biz.repository;
import java.util.List;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.ctrip.framework.apollo.biz.entity.Item;
......@@ -14,4 +16,8 @@ public interface ItemRepository extends PagingAndSortingRepository<Item, Long> {
Item findFirst1ByNamespaceIdOrderByLineNumDesc(Long namespaceId);
@Modifying
@Query("update Item set isdeleted=1,DataChange_LastModifiedBy = ?2 where namespaceId = ?1")
int deleteByNamespaceId(long namespaceId, String operator);
}
......@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.biz.repository;
import java.util.List;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.ctrip.framework.apollo.biz.entity.Namespace;
......@@ -11,4 +13,9 @@ public interface NamespaceRepository extends PagingAndSortingRepository<Namespac
List<Namespace> findByAppIdAndClusterNameOrderByIdAsc(String appId, String clusterName);
Namespace findByAppIdAndClusterNameAndNamespaceName(String appId, String clusterName, String namespaceName);
@Modifying
@Query("update Namespace set isdeleted=1,DataChange_LastModifiedBy = ?3 where appId=?1 and clusterName=?2")
int batchDelete(String appId, String clusterName, String operator);
}
......@@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.biz.repository;
import java.util.List;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
......@@ -19,4 +21,8 @@ public interface ReleaseRepository extends PagingAndSortingRepository<Release, L
List<Release> findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(String appId, String clusterName, String namespaceName, Pageable page);
List<Release> findByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseOrderByIdDesc(String appId, String clusterName, String namespaceName, Pageable page);
@Modifying
@Query("update Release set isdeleted=1,DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3")
int batchDelete(String appId, String clusterName, String namespaceName, String operator);
}
......@@ -11,6 +11,7 @@ import org.springframework.transaction.annotation.Transactional;
import com.ctrip.framework.apollo.biz.entity.Audit;
import com.ctrip.framework.apollo.biz.entity.Cluster;
import com.ctrip.framework.apollo.biz.repository.ClusterRepository;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.common.exception.ServiceException;
......@@ -26,8 +27,6 @@ public class ClusterService {
private AuditService auditService;
@Autowired
private NamespaceService namespaceService;
@Autowired
private AppNamespaceService appNamespaceService;
public boolean isClusterNameUnique(String appId, String clusterName) {
......@@ -75,9 +74,12 @@ public class ClusterService {
public void delete(long id, String operator) {
Cluster cluster = clusterRepository.findOne(id);
if (cluster == null) {
return;
throw new BadRequestException("cluster not exist");
}
//delete linked namespaces
namespaceService.deleteByAppIdAndClusterName(cluster.getAppId(), cluster.getName(), operator);
cluster.setDeleted(true);
cluster.setDataChangeLastModifiedBy(operator);
clusterRepository.save(cluster);
......
......@@ -26,4 +26,9 @@ public class CommitService {
return commitRepository.findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(appId, clusterName, namespaceName, page);
}
@Transactional
public int batchDelete(String appId, String clusterName, String namespaceName, String operator){
return commitRepository.batchDelete(appId, clusterName, namespaceName, operator);
}
}
......@@ -47,6 +47,12 @@ public class ItemService {
return deletedItem;
}
@Transactional
public int batchDelete(long namespaceId, String operator) {
return itemRepository.deleteByNamespaceId(namespaceId, operator);
}
public Item findOne(String appId, String clusterName, String namespaceName, String key) {
Namespace namespace = namespaceRepository.findByAppIdAndClusterNameAndNamespaceName(appId,
clusterName, namespaceName);
......
......@@ -13,7 +13,6 @@ import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.common.dto.ItemChangeSets;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.common.exception.NotFoundException;
import com.ctrip.framework.apollo.core.utils.StringUtils;
@Service
......@@ -50,14 +49,19 @@ public class ItemSetService {
for (ItemDTO item : changeSet.getUpdateItems()) {
Item entity = BeanUtils.transfrom(Item.class, item);
Item beforeUpdateItem = itemService.findOne(entity.getId());
if (beforeUpdateItem == null) {
Item managedItem = itemService.findOne(entity.getId());
if (managedItem == null) {
throw new NotFoundException(String.format("item not found.(key=%s)", entity.getKey()));
}
beforeUpdateItem = BeanUtils.transfrom(Item.class, beforeUpdateItem);
Item beforeUpdateItem = BeanUtils.transfrom(Item.class, managedItem);
//protect. only value,comment,lastModifiedBy,lineNum can be modified
managedItem.setValue(entity.getValue());
managedItem.setComment(entity.getComment());
managedItem.setLineNum(entity.getLineNum());
entity.setDataChangeLastModifiedBy(operator);
Item updatedItem = itemService.update(entity);
Item updatedItem = itemService.update(managedItem);
configChangeContentBuilder.updateItem(beforeUpdateItem, updatedItem);
}
......@@ -72,8 +76,7 @@ public class ItemSetService {
auditService.audit("ItemSet", null, Audit.OP.DELETE, operator);
}
String configChangeContent = configChangeContentBuilder.build();
if (!StringUtils.isEmpty(configChangeContent)) {
if (configChangeContentBuilder.hasContent()){
createCommit(appId, clusterName, namespaceName, configChangeContentBuilder.build(),
changeSet.getDataChangeLastModifiedBy());
}
......
......@@ -24,6 +24,13 @@ public class NamespaceService {
private AuditService auditService;
@Autowired
private AppNamespaceService appNamespaceService;
@Autowired
private ItemService itemService;
@Autowired
private CommitService commitService;
@Autowired
private ReleaseService releaseService;
public boolean isNamespaceUnique(String appId, String cluster, String namespace) {
Objects.requireNonNull(appId, "AppId must not be null");
......@@ -34,17 +41,32 @@ public class NamespaceService {
}
@Transactional
public void delete(long id, String operator) {
Namespace namespace = namespaceRepository.findOne(id);
if (namespace == null) {
return;
public void deleteByAppIdAndClusterName(String appId, String clusterName, String operator){
List<Namespace> toDeleteNamespaces = findNamespaces(appId, clusterName);
for (Namespace namespace: toDeleteNamespaces){
deleteNamespace(namespace, operator);
}
}
@Transactional
public Namespace deleteNamespace(Namespace namespace, String operator){
String appId = namespace.getAppId();
String clusterName = namespace.getClusterName();
itemService.batchDelete(namespace.getId(), operator);
commitService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator);
releaseService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator);
namespace.setDeleted(true);
namespace.setDataChangeLastModifiedBy(operator);
namespaceRepository.save(namespace);
auditService.audit(Namespace.class.getSimpleName(), id, Audit.OP.DELETE, operator);
auditService.audit(Namespace.class.getSimpleName(), namespace.getId(), Audit.OP.DELETE, operator);
return namespaceRepository.save(namespace);
}
public Namespace findOne(Long namespaceId) {
......
......@@ -142,4 +142,9 @@ public class ReleaseService {
return releaseRepository.save(release);
}
@Transactional
public int batchDelete(String appId, String clusterName, String namespaceName, String operator){
return releaseRepository.batchDelete(appId, clusterName, namespaceName, operator);
}
}
......@@ -4,7 +4,9 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ctrip.framework.apollo.biz.entity.Item;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
......@@ -20,7 +22,9 @@ public class ConfigChangeContentBuilder {
public ConfigChangeContentBuilder createItem(Item item) {
if (!StringUtils.isEmpty(item.getKey())){
createItems.add(item);
}
return this;
}
......@@ -33,10 +37,16 @@ public class ConfigChangeContentBuilder {
}
public ConfigChangeContentBuilder deleteItem(Item item) {
if (!StringUtils.isEmpty(item.getKey())) {
deleteItems.add(item);
}
return this;
}
public boolean hasContent(){
return !createItems.isEmpty() || !updateItems.isEmpty() || !deleteItems.isEmpty();
}
public String build() {
//因为事务第一段提交并没有更新时间,所以build时统一更新
for (Item item : createItems) {
......
......@@ -78,6 +78,11 @@ public class AdminServiceAPI {
.post(env, "apps/{appId}/appnamespaces", appNamespace, AppNamespaceDTO.class, appNamespace.getAppId());
}
public void deleteNamespace(Env env, String appId, String clusterName, String namespaceName, String operator) {
restTemplate.delete(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}?operator={operator}", appId, clusterName,
namespaceName, operator);
}
}
@Service
......@@ -143,6 +148,10 @@ public class AdminServiceAPI {
return restTemplate.post(env, "apps/{appId}/clusters", cluster, ClusterDTO.class,
cluster.getAppId());
}
public void delete(Env env, String appId, String clusterName, String operator) {
restTemplate.delete(env, "apps/{appId}/clusters/{clusterName}?operator={operator}", appId, clusterName, operator);
}
}
@Service
......
......@@ -45,4 +45,12 @@ public class ClusterController {
return clusterService.createCluster(Env.valueOf(env), cluster);
}
@PreAuthorize(value = "@permissionValidator.isSuperAdmin()")
@RequestMapping(value = "apps/{appId}/envs/{env}/clusters/{clusterName:.+}", method = RequestMethod.DELETE)
public void deleteCluster(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName){
clusterService.deleteCluster(Env.valueOf(env), appId, clusterName);
}
}
......@@ -43,7 +43,6 @@ public class NamespaceController {
@Autowired
private AppService appService;
@Autowired
private ApplicationEventPublisher publisher;
@Autowired
......@@ -86,6 +85,14 @@ public class NamespaceController {
return ResponseEntity.ok().build();
}
@PreAuthorize(value = "@permissionValidator.isSuperAdmin()")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName:.+}", method = RequestMethod.DELETE)
public ResponseEntity<Void> deleteNamespace(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName){
namespaceService.deleteNamespace(appId, Env.valueOf(env), clusterName, namespaceName);
return ResponseEntity.ok().build();
}
@PreAuthorize(value = "@permissionValidator.hasCreateAppNamespacePermission(#appId, #appNamespace)")
@RequestMapping(value = "/apps/{appId}/appnamespaces", method = RequestMethod.POST)
public AppNamespace createAppNamespace(@PathVariable String appId, @RequestBody AppNamespace appNamespace) {
......
......@@ -4,6 +4,7 @@ import com.ctrip.framework.apollo.common.dto.ClusterDTO;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.constant.CatEventType;
import com.dianping.cat.Cat;
......@@ -16,6 +17,8 @@ import java.util.List;
public class ClusterService {
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private AdminServiceAPI.ClusterAPI clusterAPI;
public List<ClusterDTO> findClusters(Env env, String appId) {
......@@ -33,4 +36,8 @@ public class ClusterService {
return clusterDTO;
}
public void deleteCluster(Env env, String appId, String clusterName){
clusterAPI.delete(env, appId, clusterName, userInfoHolder.getUser().getUserId());
}
}
package com.ctrip.framework.apollo.portal.service;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.common.dto.NamespaceDTO;
......@@ -22,6 +23,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
......@@ -32,6 +34,8 @@ public class NamespaceService {
private Logger logger = LoggerFactory.getLogger(NamespaceService.class);
private Gson gson = new Gson();
private static Type mapType = new TypeToken<Map<String, String>>() {
}.getType();
@Autowired
private UserInfoHolder userInfoHolder;
......@@ -58,6 +62,10 @@ public class NamespaceService {
return createdNamespace;
}
public void deleteNamespace(String appId, Env env, String clusterName, String namespaceName){
namespaceAPI.deleteNamespace(env, appId, clusterName, namespaceName, userInfoHolder.getUser().getUserId());
}
public NamespaceDTO loadNamespaceBaseInfo(String appId, Env env, String clusterName, String namespaceName) {
NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);
if (namespace == null) {
......@@ -101,7 +109,6 @@ public class NamespaceService {
return parseNamespace(appId, env, clusterName, namespace);
}
@SuppressWarnings("unchecked")
private NamespaceVO parseNamespace(String appId, Env env, String clusterName, NamespaceDTO namespace) {
NamespaceVO namespaceVO = new NamespaceVO();
namespaceVO.setBaseInfo(namespace);
......@@ -118,7 +125,7 @@ public class NamespaceService {
Map<String, String> releaseItems = new HashMap<>();
latestRelease = releaseService.loadLatestRelease(appId, env, clusterName, namespaceName);
if (latestRelease != null) {
releaseItems = gson.fromJson(latestRelease.getConfigurations(), Map.class);
releaseItems = gson.fromJson(latestRelease.getConfigurations(), mapType);
}
//not Release config items
......
......@@ -24,9 +24,6 @@
</header>
<div class="panel-body">
<div class="alert alert-info" role="alert">
apollo系统目前正在框架部门内测阶段,如非框架项目接入请先联系song_s@ctrip.com,zhanglea@ctrip.com
</div>
<form class="form-horizontal" name="appForm" ng-controller="CreateAppController" valdr-type="App"
ng-submit="create()">
<div class="form-group">
......
......@@ -17,6 +17,7 @@ $(document).ready(function () {
$('[data-tooltip="tooltip"]').tooltip();
$("textarea").niceScroll({styler: "fb", cursorcolor: "#fff"});
$("pre").niceScroll({styler: "fb", cursorcolor: "#fff"});
}, 2500);
});
......
......@@ -13,7 +13,6 @@ application_module.controller("ConfigNamespaceController",
};
var TABLE_VIEW_OPER_TYPE = {
RETRIEVE: 'retrieve',
CREATE: 'create',
UPDATE: 'update'
};
......@@ -26,20 +25,22 @@ application_module.controller("ConfigNamespaceController",
$scope.release = release;
$scope.switchReleaseChangeViewType = switchReleaseChangeViewType;
$scope.showRollbackAlertDialog = showRollbackAlertDialog;
$scope.preRollback = preRollback;
$scope.rollback = rollback;
$scope.retrieveItem = retrieveItem;
$scope.preDeleteItem = preDeleteItem;
$scope.deleteItem = deleteItem;
$scope.editItem = editItem;
$scope.cancelEdit = cancelEdit;
$scope.createItem = createItem;
$scope.doItem = doItem;
......@@ -153,6 +154,11 @@ application_module.controller("ConfigNamespaceController",
);
}
$scope.releaseChangeViewType = 'change';
function switchReleaseChangeViewType(type) {
$scope.releaseChangeViewType = type;
}
function showRollbackAlertDialog() {
$("#rollbackModal").modal('hide');
$("#rollbackAlertDialog").modal('show');
......@@ -209,15 +215,6 @@ application_module.controller("ConfigNamespaceController",
$scope.tableViewOperType = '', $scope.item = {};
var toOperationNamespace;
//查看配置
function retrieveItem(namespace, item, oldValue) {
switchTableViewOperType(TABLE_VIEW_OPER_TYPE.RETRIEVE);
$scope.item = item;
$scope.item.oldValue = oldValue;
toOperationNamespace = namespace;
$scope.hasModifyPermission = namespace.hasModifyPermission;
}
var toDeleteItemId = 0;
function preDeleteItem(namespace, itemId) {
......@@ -245,6 +242,7 @@ application_module.controller("ConfigNamespaceController",
});
}
var backupItem = {};
//修改配置
function editItem(namespace, item) {
if (!lockCheck(namespace)) {
......@@ -252,11 +250,20 @@ application_module.controller("ConfigNamespaceController",
}
switchTableViewOperType(TABLE_VIEW_OPER_TYPE.UPDATE);
$scope.item = item;
backupItem.value = item.value;
backupItem.comment = item.comment;
toOperationNamespace = namespace;
$("#itemModal").modal("show");
}
function cancelEdit() {
if($scope.tableViewOperType = TABLE_VIEW_OPER_TYPE.UPDATE){
$scope.item.value = backupItem.value;
$scope.item.comment = backupItem.comment;
}
}
//新增配置
function createItem(namespace) {
if (!lockCheck(namespace)) {
......
directive_module.directive('apollodiff',
function ($compile, $window) {
return {
restrict: 'E',
templateUrl: '../../views/component/diff.html',
transclude: true,
replace: true,
scope: {
oldStr: '=',
newStr: '=',
apolloId: '='
},
link: function (scope, element, attrs) {
scope.$watch('oldStr', makeDiff);
scope.$watch('newStr', makeDiff);
function makeDiff() {
var displayArea = document.getElementById(scope.apolloId);
if (!displayArea){
return;
}
//clear
displayArea.innerHTML = '';
var color = '',
span = null,
pre = '';
var diff = JsDiff.diffLines(scope.oldStr, scope.newStr),
fragment = document.createDocumentFragment();
diff.forEach(function (part) {
// green for additions, red for deletions
// grey for common parts
color = part.added ? 'green' :
part.removed ? 'red' : 'grey';
span = document.createElement('span');
span.style.color = color;
pre = part.added ? '+' :
part.removed ? '-' : '';
span.appendChild(document.createTextNode(pre + part.value));
fragment.appendChild(span);
});
displayArea.appendChild(fragment);
}
}
}
});
......@@ -232,8 +232,8 @@
</thead>
<tbody>
<tr ng-repeat="item in commits.changeSets.createItems"
ng-show="item.key || item.comment">
<!--兼容老数据,不显示item类型为空行和注释的item-->
<tr ng-repeat="item in commits.changeSets.createItems" ng-show="item.key">
<td width="2%">
新增
</td>
......
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