Commit 59e0850c authored by qianjie's avatar qianjie

1st PR -> feature: add gray operation on Open API

2nd PR -> bugfix: fix and reformat for the code review
parent 8d66ee61
...@@ -176,4 +176,35 @@ public class ReleaseController { ...@@ -176,4 +176,35 @@ public class ReleaseController {
Topics.APOLLO_RELEASE_TOPIC); Topics.APOLLO_RELEASE_TOPIC);
} }
@Transactional
@RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/gray-del-releases", method = RequestMethod.POST)
public ReleaseDTO publish(@PathVariable("appId") String appId,
@PathVariable("clusterName") String clusterName,
@PathVariable("namespaceName") String namespaceName,
@RequestParam("operator") String operator,
@RequestParam("releaseName") String releaseName,
@RequestParam(name = "comment", required = false) String releaseComment,
@RequestParam(name = "isEmergencyPublish", defaultValue = "false") boolean isEmergencyPublish,
@RequestParam(name = "grayDelKeys") Set<String> grayDelKeys){
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.grayDeletionPublish(namespace, releaseName, releaseComment, operator, isEmergencyPublish, grayDelKeys);
//send release message
Namespace parentNamespace = namespaceService.findParentNamespace(namespace);
String messageCluster;
if (parentNamespace != null) {
messageCluster = parentNamespace.getClusterName();
} else {
messageCluster = clusterName;
}
messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, messageCluster, namespaceName),
Topics.APOLLO_RELEASE_TOPIC);
return BeanUtils.transfrom(ReleaseDTO.class, release);
}
} }
...@@ -185,6 +185,49 @@ public class ReleaseService { ...@@ -185,6 +185,49 @@ public class ReleaseService {
return release; return release;
} }
private Release publishBranchNamespace(Namespace parentNamespace, Namespace childNamespace,
Map<String, String> childNamespaceItems,
String releaseName, String releaseComment,
String operator, boolean isEmergencyPublish, Set<String> grayDelKeys) {
Release parentLatestRelease = findLatestActiveRelease(parentNamespace);
Map<String, String> parentConfigurations = parentLatestRelease != null ?
gson.fromJson(parentLatestRelease.getConfigurations(),
GsonType.CONFIG) : new HashMap<>();
long baseReleaseId = parentLatestRelease == null ? 0 : parentLatestRelease.getId();
Map<String, String> configsToPublish = mergeConfiguration(parentConfigurations, childNamespaceItems);
if(!(grayDelKeys == null || grayDelKeys.size()==0)){
for (String key : grayDelKeys){
configsToPublish.remove(key);
}
}
return branchRelease(parentNamespace, childNamespace, releaseName, releaseComment,
configsToPublish, baseReleaseId, operator,
ReleaseOperation.GRAY_RELEASE, isEmergencyPublish);
}
@Transactional
public Release grayDeletionPublish(Namespace namespace, String releaseName, String releaseComment,
String operator, boolean isEmergencyPublish, Set<String> grayDelKeys) {
checkLock(namespace, isEmergencyPublish, operator);
Map<String, String> operateNamespaceItems = getNamespaceItems(namespace);
Namespace parentNamespace = namespaceService.findParentNamespace(namespace);
//branch release
if (parentNamespace != null) {
return publishBranchNamespace(parentNamespace, namespace, operateNamespaceItems,
releaseName, releaseComment, operator, isEmergencyPublish, grayDelKeys);
}else {
throw new NotFoundException("Parent namespace not found");
}
}
private void checkLock(Namespace namespace, boolean isEmergencyPublish, String operator) { private void checkLock(Namespace namespace, boolean isEmergencyPublish, String operator) {
if (!isEmergencyPublish) { if (!isEmergencyPublish) {
NamespaceLock lock = namespaceLockService.findLock(namespace.getId()); NamespaceLock lock = namespaceLockService.findLock(namespace.getId());
...@@ -222,17 +265,8 @@ public class ReleaseService { ...@@ -222,17 +265,8 @@ public class ReleaseService {
Map<String, String> childNamespaceItems, Map<String, String> childNamespaceItems,
String releaseName, String releaseComment, String releaseName, String releaseComment,
String operator, boolean isEmergencyPublish) { String operator, boolean isEmergencyPublish) {
Release parentLatestRelease = findLatestActiveRelease(parentNamespace); return publishBranchNamespace(parentNamespace, childNamespace, childNamespaceItems, releaseName, releaseComment,
Map<String, String> parentConfigurations = parentLatestRelease != null ? operator, isEmergencyPublish, null);
gson.fromJson(parentLatestRelease.getConfigurations(),
GsonType.CONFIG) : new HashMap<>();
long baseReleaseId = parentLatestRelease == null ? 0 : parentLatestRelease.getId();
Map<String, String> childNamespaceToPublishConfigs = mergeConfiguration(parentConfigurations, childNamespaceItems);
return branchRelease(parentNamespace, childNamespace, releaseName, releaseComment,
childNamespaceToPublishConfigs, baseReleaseId, operator,
ReleaseOperation.GRAY_RELEASE, isEmergencyPublish);
} }
......
package com.ctrip.framework.apollo.openapi.dto;
import java.util.Set;
public class NamespaceGrayDelReleaseDTO extends NamespaceReleaseDTO {
private Set<String> grayDelKeys;
public Set<String> getGrayDelKeys() {
return grayDelKeys;
}
public void setGrayDelKeys(Set<String> grayDelKeys) {
this.grayDelKeys = grayDelKeys;
}
}
package com.ctrip.framework.apollo.openapi.dto;
import java.util.Set;
public class OpenGrayReleaseRuleDTO extends BaseDTO{
private String appId;
private String clusterName;
private String namespaceName;
private String branchName;
private Set<OpenGrayReleaseRuleItemDTO> ruleItems;
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public String getNamespaceName() {
return namespaceName;
}
public void setNamespaceName(String namespaceName) {
this.namespaceName = namespaceName;
}
public String getBranchName() {
return branchName;
}
public void setBranchName(String branchName) {
this.branchName = branchName;
}
public Set<OpenGrayReleaseRuleItemDTO> getRuleItems() {
return ruleItems;
}
public void setRuleItems(Set<OpenGrayReleaseRuleItemDTO> ruleItems) {
this.ruleItems = ruleItems;
}
}
package com.ctrip.framework.apollo.openapi.dto;
import java.util.Set;
public class OpenGrayReleaseRuleItemDTO {
private String clientAppId;
private Set<String> clientIpList;
public String getClientAppId() {
return clientAppId;
}
public void setClientAppId(String clientAppId) {
this.clientAppId = clientAppId;
}
public Set<String> getClientIpList() {
return clientIpList;
}
public void setClientIpList(Set<String> clientIpList) {
this.clientIpList = clientIpList;
}
}
package com.ctrip.framework.apollo.openapi.util; package com.ctrip.framework.apollo.openapi.util;
import com.ctrip.framework.apollo.common.dto.*;
import com.ctrip.framework.apollo.openapi.dto.*;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.common.dto.NamespaceLockDTO;
import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.openapi.dto.OpenAppNamespaceDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO;
import com.ctrip.framework.apollo.portal.entity.bo.ItemBO; import com.ctrip.framework.apollo.portal.entity.bo.ItemBO;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO; import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Collections; import java.util.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class OpenApiBeanUtils { public class OpenApiBeanUtils {
...@@ -116,4 +107,43 @@ public class OpenApiBeanUtils { ...@@ -116,4 +107,43 @@ public class OpenApiBeanUtils {
return lock; return lock;
} }
public static OpenGrayReleaseRuleDTO transformFromGrayReleaseRuleDTO(GrayReleaseRuleDTO grayReleaseRuleDTO){
OpenGrayReleaseRuleDTO openGrayReleaseRuleDTO = new OpenGrayReleaseRuleDTO();
openGrayReleaseRuleDTO.setAppId(grayReleaseRuleDTO.getAppId());
openGrayReleaseRuleDTO.setBranchName(grayReleaseRuleDTO.getBranchName());
openGrayReleaseRuleDTO.setClusterName(grayReleaseRuleDTO.getClusterName());
openGrayReleaseRuleDTO.setNamespaceName(grayReleaseRuleDTO.getNamespaceName());
Set<GrayReleaseRuleItemDTO> grayReleaseRuleItemDTOSet = grayReleaseRuleDTO.getRuleItems();
Set<OpenGrayReleaseRuleItemDTO> ruleItems = new HashSet<>();
grayReleaseRuleItemDTOSet.forEach(grayReleaseRuleItemDTO -> {
OpenGrayReleaseRuleItemDTO item = new OpenGrayReleaseRuleItemDTO();
item.setClientAppId(grayReleaseRuleItemDTO.getClientAppId());
item.setClientIpList(grayReleaseRuleItemDTO.getClientIpList());
ruleItems.add(item);
});
openGrayReleaseRuleDTO.setRuleItems(ruleItems);
return openGrayReleaseRuleDTO;
}
public static GrayReleaseRuleDTO transformToGrayReleaseRuleDTO(OpenGrayReleaseRuleDTO openGrayReleaseRuleDTO){
String appId = openGrayReleaseRuleDTO.getAppId();
String branchName = openGrayReleaseRuleDTO.getBranchName();
String clusterName = openGrayReleaseRuleDTO.getClusterName();
String namespaceName = openGrayReleaseRuleDTO.getNamespaceName();
GrayReleaseRuleDTO grayReleaseRuleDTO = new GrayReleaseRuleDTO(appId,clusterName,namespaceName,branchName);
Set<OpenGrayReleaseRuleItemDTO> openGrayReleaseRuleItemDTOSet = openGrayReleaseRuleDTO.getRuleItems();
openGrayReleaseRuleItemDTOSet.forEach(openGrayReleaseRuleItemDTO ->{
String clientAppId = openGrayReleaseRuleItemDTO.getClientAppId();
Set<String> clientIpList = openGrayReleaseRuleItemDTO.getClientIpList();
GrayReleaseRuleItemDTO ruleItem = new GrayReleaseRuleItemDTO(clientAppId, clientIpList);
grayReleaseRuleDTO.addRuleItem(ruleItem);
});
return grayReleaseRuleDTO;
}
} }
package com.ctrip.framework.apollo.openapi.v1.controller;
/**
* Created by qianjie on 8/10/17.
*/
import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO;
import com.ctrip.framework.apollo.common.dto.NamespaceDTO;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.openapi.auth.ConsumerPermissionValidator;
import com.ctrip.framework.apollo.openapi.dto.OpenGrayReleaseRuleDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO;
import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils;
import com.ctrip.framework.apollo.portal.component.PermissionValidator;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
import com.ctrip.framework.apollo.portal.service.NamespaceBranchService;
import com.ctrip.framework.apollo.portal.service.ReleaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController("openapiNamespaceBranchController")
@RequestMapping("/openapi/v1/envs/{env}")
public class NamespaceBranchController {
@Autowired
private ConsumerPermissionValidator consumerPermissionValidator;
@Autowired
private ReleaseService releaseService;
@Autowired
private NamespaceBranchService namespaceBranchService;
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches", method = RequestMethod.GET)
public OpenNamespaceDTO findBranch(@PathVariable String appId,
@PathVariable String env,
@PathVariable String clusterName,
@PathVariable String namespaceName) {
NamespaceBO namespaceBO = namespaceBranchService.findBranch(appId, Env.valueOf(env.toUpperCase()), clusterName, namespaceName);
if (namespaceBO == null) {
return null;
}
return OpenApiBeanUtils.transformFromNamespaceBO(namespaceBO);
}
@PreAuthorize(value = "@consumerPermissionValidator.hasCreateNamespacePermission(#request, #appId)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches", method = RequestMethod.POST)
public OpenNamespaceDTO createBranch(@PathVariable String appId,
@PathVariable String env,
@PathVariable String clusterName,
@PathVariable String namespaceName,
@RequestParam("operator") String operator,
HttpServletRequest request) {
NamespaceDTO namespaceDTO = namespaceBranchService.createBranch(appId, Env.valueOf(env.toUpperCase()), clusterName, namespaceName, operator);
if (namespaceDTO == null) {
return null;
}
return BeanUtils.transfrom(OpenNamespaceDTO.class, namespaceDTO);
}
@PreAuthorize(value = "@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName, #env)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}", method = RequestMethod.DELETE)
public void deleteBranch(@PathVariable String appId,
@PathVariable String env,
@PathVariable String clusterName,
@PathVariable String namespaceName,
@PathVariable String branchName,
@RequestParam("operator") String operator,
HttpServletRequest request) {
boolean canDelete = consumerPermissionValidator.hasReleaseNamespacePermission(request, appId, namespaceName, env) ||
(consumerPermissionValidator.hasModifyNamespacePermission(request, appId, namespaceName, env) &&
releaseService.loadLatestRelease(appId, Env.valueOf(env), branchName, namespaceName) == null);
if (!canDelete) {
throw new AccessDeniedException("Forbidden operation. "
+ "Caused by: 1.you don't have release permission "
+ "or 2. you don't have modification permission "
+ "or 3. you have modification permission but branch has been released");
}
namespaceBranchService.deleteBranch(appId, Env.valueOf(env.toUpperCase()), clusterName, namespaceName, branchName, operator);
}
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", method = RequestMethod.GET)
public OpenGrayReleaseRuleDTO getBranchGrayRules(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName,
@PathVariable String namespaceName,
@PathVariable String branchName) {
GrayReleaseRuleDTO grayReleaseRuleDTO = namespaceBranchService.findBranchGrayRules(appId, Env.valueOf(env.toUpperCase()), clusterName, namespaceName, branchName);
if (grayReleaseRuleDTO == null) {
return null;
}
return OpenApiBeanUtils.transformFromGrayReleaseRuleDTO(grayReleaseRuleDTO);
}
@PreAuthorize(value = "@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName, #env)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", method = RequestMethod.PUT)
public void updateBranchRules(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName,
@PathVariable String branchName, @RequestBody OpenGrayReleaseRuleDTO rules,
@RequestParam("operator") String operator,
HttpServletRequest request) {
GrayReleaseRuleDTO grayReleaseRuleDTO = OpenApiBeanUtils.transformToGrayReleaseRuleDTO(rules);
namespaceBranchService
.updateBranchGrayRules(appId, Env.valueOf(env.toUpperCase()), clusterName, namespaceName, branchName, grayReleaseRuleDTO, operator);
}
}
...@@ -6,10 +6,13 @@ import com.ctrip.framework.apollo.common.utils.BeanUtils; ...@@ -6,10 +6,13 @@ import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.openapi.dto.NamespaceGrayDelReleaseDTO;
import com.ctrip.framework.apollo.openapi.dto.NamespaceReleaseDTO; import com.ctrip.framework.apollo.openapi.dto.NamespaceReleaseDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO; import com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO;
import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils; import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils;
import com.ctrip.framework.apollo.portal.entity.model.NamespaceGrayDelReleaseModel;
import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel; import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.service.NamespaceBranchService;
import com.ctrip.framework.apollo.portal.service.ReleaseService; import com.ctrip.framework.apollo.portal.service.ReleaseService;
import com.ctrip.framework.apollo.portal.spi.UserService; import com.ctrip.framework.apollo.portal.spi.UserService;
...@@ -19,6 +22,7 @@ import org.springframework.web.bind.annotation.PathVariable; ...@@ -19,6 +22,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; 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.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
...@@ -33,6 +37,8 @@ public class ReleaseController { ...@@ -33,6 +37,8 @@ public class ReleaseController {
private ReleaseService releaseService; private ReleaseService releaseService;
@Autowired @Autowired
private UserService userService; private UserService userService;
@Autowired
private NamespaceBranchService namespaceBranchService;
@PreAuthorize(value = "@consumerPermissionValidator.hasReleaseNamespacePermission(#request, #appId, #namespaceName, #env)") @PreAuthorize(value = "@consumerPermissionValidator.hasReleaseNamespacePermission(#request, #appId, #namespaceName, #env)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases", method = RequestMethod.POST) @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases", method = RequestMethod.POST)
...@@ -74,4 +80,82 @@ public class ReleaseController { ...@@ -74,4 +80,82 @@ public class ReleaseController {
return OpenApiBeanUtils.transformFromReleaseDTO(releaseDTO); return OpenApiBeanUtils.transformFromReleaseDTO(releaseDTO);
} }
@PreAuthorize(value = "@consumerPermissionValidator.hasReleaseNamespacePermission(#request, #appId, #namespaceName, #env)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/merge", method = RequestMethod.POST)
public OpenReleaseDTO merge(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName,
@PathVariable String branchName, @RequestParam(value = "deleteBranch", defaultValue = "true") boolean deleteBranch,
@RequestBody NamespaceReleaseDTO model, HttpServletRequest request) {
checkModel(model != null);
RequestPrecondition.checkArguments(!StringUtils.isContainEmpty(model.getReleasedBy(), model
.getReleaseTitle()),
"Params(releaseTitle and releasedBy) can not be empty");
if (userService.findByUserId(model.getReleasedBy()) == null) {
throw new BadRequestException("user(releaseBy) not exists");
}
ReleaseDTO mergedRelease = namespaceBranchService.merge(appId, Env.valueOf(env.toUpperCase()), clusterName, namespaceName, branchName,
model.getReleaseTitle(), model.getReleaseComment(),
model.isEmergencyPublish(), deleteBranch, model.getReleasedBy());
return OpenApiBeanUtils.transformFromReleaseDTO(mergedRelease);
}
@PreAuthorize(value = "@consumerPermissionValidator.hasReleaseNamespacePermission(#request, #appId, #namespaceName, #env)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/releases",
method = RequestMethod.POST)
public OpenReleaseDTO createGrayRelease(@PathVariable String appId,
@PathVariable String env, @PathVariable String clusterName,
@PathVariable String namespaceName, @PathVariable String branchName,
@RequestBody NamespaceReleaseDTO model,
HttpServletRequest request) {
checkModel(model != null);
RequestPrecondition.checkArguments(!StringUtils.isContainEmpty(model.getReleasedBy(), model
.getReleaseTitle()),
"Params(releaseTitle and releasedBy) can not be empty");
if (userService.findByUserId(model.getReleasedBy()) == null) {
throw new BadRequestException("user(releaseBy) not exists");
}
NamespaceReleaseModel releaseModel = BeanUtils.transfrom(NamespaceReleaseModel.class, model);
releaseModel.setAppId(appId);
releaseModel.setEnv(Env.fromString(env).toString());
releaseModel.setClusterName(branchName);
releaseModel.setNamespaceName(namespaceName);
return OpenApiBeanUtils.transformFromReleaseDTO(releaseService.publish(releaseModel));
}
@PreAuthorize(value = "@consumerPermissionValidator.hasReleaseNamespacePermission(#request, #appId, #namespaceName, #env)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/gray-del-releases",
method = RequestMethod.POST)
public OpenReleaseDTO createGrayDelRelease(@PathVariable String appId,
@PathVariable String env, @PathVariable String clusterName,
@PathVariable String namespaceName, @PathVariable String branchName,
@RequestBody NamespaceGrayDelReleaseDTO model,
HttpServletRequest request) {
checkModel(model != null);
RequestPrecondition.checkArguments(!StringUtils.isContainEmpty(model.getReleasedBy(), model
.getReleaseTitle()),
"Params(releaseTitle and releasedBy) can not be empty");
RequestPrecondition.checkArguments(model.getGrayDelKeys() != null,
"Params(grayDelKeys) can not be null");
if (userService.findByUserId(model.getReleasedBy()) == null) {
throw new BadRequestException("user(releaseBy) not exists");
}
NamespaceGrayDelReleaseModel releaseModel = BeanUtils.transfrom(NamespaceGrayDelReleaseModel.class, model);
releaseModel.setAppId(appId);
releaseModel.setEnv(env.toUpperCase());
releaseModel.setClusterName(branchName);
releaseModel.setNamespaceName(namespaceName);
return OpenApiBeanUtils.transformFromReleaseDTO(releaseService.publish(releaseModel, releaseModel.getReleasedBy()));
}
} }
...@@ -274,6 +274,27 @@ public class AdminServiceAPI { ...@@ -274,6 +274,27 @@ public class AdminServiceAPI {
return response; return response;
} }
public ReleaseDTO createGrayDeletionRelease(String appId, Env env, String clusterName, String namespace,
String releaseName, String releaseComment, String operator,
boolean isEmergencyPublish, Set<String> grayDelKeys) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"));
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("releaseName", releaseName);
parameters.add("comment", releaseComment);
parameters.add("operator", operator);
parameters.add("isEmergencyPublish", String.valueOf(isEmergencyPublish));
grayDelKeys.forEach(key ->{
parameters.add("grayDelKeys",key);
});
HttpEntity<MultiValueMap<String, String>> entity =
new HttpEntity<>(parameters, headers);
ReleaseDTO response = restTemplate.post(
env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/gray-del-releases", entity,
ReleaseDTO.class, appId, clusterName, namespace);
return response;
}
public ReleaseDTO updateAndPublish(String appId, Env env, String clusterName, String namespace, public ReleaseDTO updateAndPublish(String appId, Env env, String clusterName, String namespace,
String releaseName, String releaseComment, String branchName, String releaseName, String releaseComment, String branchName,
boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) { boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) {
......
package com.ctrip.framework.apollo.portal.entity.model;
import java.util.Set;
public class NamespaceGrayDelReleaseModel extends NamespaceReleaseModel implements Verifiable {
private Set<String> grayDelKeys;
public Set<String> getGrayDelKeys() {
return grayDelKeys;
}
public void setGrayDelKeys(Set<String> grayDelKeys) {
this.grayDelKeys = grayDelKeys;
}
}
...@@ -40,11 +40,17 @@ public class NamespaceBranchService { ...@@ -40,11 +40,17 @@ public class NamespaceBranchService {
@Transactional @Transactional
public NamespaceDTO createBranch(String appId, Env env, String parentClusterName, String namespaceName) { public NamespaceDTO createBranch(String appId, Env env, String parentClusterName, String namespaceName) {
String operator = userInfoHolder.getUser().getUserId();
return createBranch(appId, env, parentClusterName, namespaceName, operator);
}
@Transactional
public NamespaceDTO createBranch(String appId, Env env, String parentClusterName, String namespaceName, String operator) {
NamespaceDTO createdBranch = namespaceBranchAPI.createBranch(appId, env, parentClusterName, namespaceName, NamespaceDTO createdBranch = namespaceBranchAPI.createBranch(appId, env, parentClusterName, namespaceName,
userInfoHolder.getUser().getUserId()); operator);
Tracer.logEvent(TracerEventType.CREATE_GRAY_RELEASE, String.format("%s+%s+%s+%s", appId, env, parentClusterName, Tracer.logEvent(TracerEventType.CREATE_GRAY_RELEASE, String.format("%s+%s+%s+%s", appId, env, parentClusterName,
namespaceName)); namespaceName));
return createdBranch; return createdBranch;
} }
...@@ -59,45 +65,61 @@ public class NamespaceBranchService { ...@@ -59,45 +65,61 @@ public class NamespaceBranchService {
String branchName, GrayReleaseRuleDTO rules) { String branchName, GrayReleaseRuleDTO rules) {
String operator = userInfoHolder.getUser().getUserId(); String operator = userInfoHolder.getUser().getUserId();
updateBranchGrayRules(appId, env, clusterName, namespaceName, branchName, rules, operator);
}
public void updateBranchGrayRules(String appId, Env env, String clusterName, String namespaceName,
String branchName, GrayReleaseRuleDTO rules, String operator) {
rules.setDataChangeCreatedBy(operator); rules.setDataChangeCreatedBy(operator);
rules.setDataChangeLastModifiedBy(operator); rules.setDataChangeLastModifiedBy(operator);
namespaceBranchAPI.updateBranchGrayRules(appId, env, clusterName, namespaceName, branchName, rules); namespaceBranchAPI.updateBranchGrayRules(appId, env, clusterName, namespaceName, branchName, rules);
Tracer.logEvent(TracerEventType.UPDATE_GRAY_RELEASE_RULE, Tracer.logEvent(TracerEventType.UPDATE_GRAY_RELEASE_RULE,
String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName));
} }
public void deleteBranch(String appId, Env env, String clusterName, String namespaceName, public void deleteBranch(String appId, Env env, String clusterName, String namespaceName,
String branchName) { String branchName) {
String operator = userInfoHolder.getUser().getUserId(); String operator = userInfoHolder.getUser().getUserId();
deleteBranch(appId, env, clusterName, namespaceName, branchName, operator);
}
public void deleteBranch(String appId, Env env, String clusterName, String namespaceName,
String branchName, String operator) {
namespaceBranchAPI.deleteBranch(appId, env, clusterName, namespaceName, branchName, operator); namespaceBranchAPI.deleteBranch(appId, env, clusterName, namespaceName, branchName, operator);
Tracer.logEvent(TracerEventType.DELETE_GRAY_RELEASE, Tracer.logEvent(TracerEventType.DELETE_GRAY_RELEASE,
String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName));
} }
public ReleaseDTO merge(String appId, Env env, String clusterName, String namespaceName, public ReleaseDTO merge(String appId, Env env, String clusterName, String namespaceName,
String branchName, String title, String comment, String branchName, String title, String comment,
boolean isEmergencyPublish, boolean deleteBranch) { boolean isEmergencyPublish, boolean deleteBranch) {
String operator = userInfoHolder.getUser().getUserId();
return merge(appId, env, clusterName, namespaceName, branchName, title, comment, isEmergencyPublish, deleteBranch, operator);
}
public ReleaseDTO merge(String appId, Env env, String clusterName, String namespaceName,
String branchName, String title, String comment,
boolean isEmergencyPublish, boolean deleteBranch, String operator) {
ItemChangeSets changeSets = calculateBranchChangeSet(appId, env, clusterName, namespaceName, branchName); ItemChangeSets changeSets = calculateBranchChangeSet(appId, env, clusterName, namespaceName, branchName, operator);
ReleaseDTO mergedResult = ReleaseDTO mergedResult =
releaseService.updateAndPublish(appId, env, clusterName, namespaceName, title, comment, releaseService.updateAndPublish(appId, env, clusterName, namespaceName, title, comment,
branchName, isEmergencyPublish, deleteBranch, changeSets); branchName, isEmergencyPublish, deleteBranch, changeSets);
Tracer.logEvent(TracerEventType.MERGE_GRAY_RELEASE, Tracer.logEvent(TracerEventType.MERGE_GRAY_RELEASE,
String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName));
return mergedResult; return mergedResult;
} }
private ItemChangeSets calculateBranchChangeSet(String appId, Env env, String clusterName, String namespaceName, private ItemChangeSets calculateBranchChangeSet(String appId, Env env, String clusterName, String namespaceName,
String branchName) { String branchName, String operator) {
NamespaceBO parentNamespace = namespaceService.loadNamespaceBO(appId, env, clusterName, namespaceName); NamespaceBO parentNamespace = namespaceService.loadNamespaceBO(appId, env, clusterName, namespaceName);
if (parentNamespace == null) { if (parentNamespace == null) {
...@@ -115,7 +137,7 @@ public class NamespaceBranchService { ...@@ -115,7 +137,7 @@ public class NamespaceBranchService {
ItemChangeSets changeSets = itemsComparator.compareIgnoreBlankAndCommentItem(parentNamespace.getBaseInfo().getId(), ItemChangeSets changeSets = itemsComparator.compareIgnoreBlankAndCommentItem(parentNamespace.getBaseInfo().getId(),
masterItems, branchItems); masterItems, branchItems);
changeSets.setDeleteItems(Collections.emptyList()); changeSets.setDeleteItems(Collections.emptyList());
changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId()); changeSets.setDataChangeLastModifiedBy(operator);
return changeSets; return changeSets;
} }
......
package com.ctrip.framework.apollo.portal.service; package com.ctrip.framework.apollo.portal.service;
import com.ctrip.framework.apollo.portal.entity.model.NamespaceGrayDelReleaseModel;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.gson.Gson; import com.google.gson.Gson;
...@@ -60,6 +61,24 @@ public class ReleaseService { ...@@ -60,6 +61,24 @@ public class ReleaseService {
return releaseDTO; return releaseDTO;
} }
//gray deletion release
public ReleaseDTO publish(NamespaceGrayDelReleaseModel model, String releaseBy) {
Env env = model.getEnv();
boolean isEmergencyPublish = model.isEmergencyPublish();
String appId = model.getAppId();
String clusterName = model.getClusterName();
String namespaceName = model.getNamespaceName();
ReleaseDTO releaseDTO = releaseAPI.createGrayDeletionRelease(appId, env, clusterName, namespaceName,
model.getReleaseTitle(), model.getReleaseComment(),
releaseBy, isEmergencyPublish, model.getGrayDelKeys());
Tracer.logEvent(TracerEventType.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, public ReleaseDTO updateAndPublish(String appId, Env env, String clusterName, String namespaceName,
String releaseTitle, String releaseComment, String branchName, String releaseTitle, String releaseComment, String branchName,
boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) { boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) {
......
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