Skip to content

Commit

Permalink
emergency publish
Browse files Browse the repository at this point in the history
  • Loading branch information
lepdou committed Jan 19, 2017
1 parent 4949eb5 commit db65452
Show file tree
Hide file tree
Showing 29 changed files with 358 additions and 138 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

@RestController
public class ReleaseController {

private static final Splitter RELEASES_SPLITTER = Splitter.on(",").omitEmptyStrings()
.trimResults();

Expand All @@ -57,7 +58,7 @@ public ReleaseDTO get(@PathVariable("releaseId") long releaseId) {
}

@RequestMapping("/releases")
public List<ReleaseDTO> findReleaseByIds(@RequestParam("releaseIds") String releaseIds){
public List<ReleaseDTO> findReleaseByIds(@RequestParam("releaseIds") String releaseIds) {
Set<Long> releaseIdSet = RELEASES_SPLITTER.splitToList(releaseIds).stream().map(Long::parseLong)
.collect(Collectors.toSet());

Expand Down Expand Up @@ -99,13 +100,14 @@ public ReleaseDTO publish(@PathVariable("appId") String appId,
@PathVariable("namespaceName") String namespaceName,
@RequestParam("name") String releaseName,
@RequestParam(name = "comment", required = false) String releaseComment,
@RequestParam("operator") String operator) {
@RequestParam("operator") String operator,
@RequestParam(name = "isEmergencyPublish", defaultValue = "false") boolean isEmergencyPublish) {
Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);
if (namespace == null) {
throw new NotFoundException(String.format("Could not find namespace for %s %s %s", appId,
clusterName, namespaceName));
}
Release release = releaseService.publish(namespace, releaseName, releaseComment, operator);
Release release = releaseService.publish(namespace, releaseName, releaseComment, operator, isEmergencyPublish);

//send release message
Namespace parentNamespace = namespaceService.findParentNamespace(namespace);
Expand All @@ -122,31 +124,33 @@ public ReleaseDTO publish(@PathVariable("appId") String appId,


/**
*merge branch items to master and publish master
* merge branch items to master and publish master
*
* @return published result
*/
@Transactional
@RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish", method = RequestMethod.POST)
public ReleaseDTO updateAndPublish(@PathVariable("appId") String appId,
@PathVariable("clusterName") String clusterName,
@PathVariable("namespaceName") String namespaceName,
@RequestParam("releaseName") String releaseName,
@RequestParam("branchName") String branchName,
@RequestParam(value = "deleteBranch", defaultValue = "true") boolean deleteBranch,
@RequestParam(name = "releaseComment", required = false) String releaseComment,
@RequestBody ItemChangeSets changeSets) {
@PathVariable("clusterName") String clusterName,
@PathVariable("namespaceName") String namespaceName,
@RequestParam("releaseName") String releaseName,
@RequestParam("branchName") String branchName,
@RequestParam(value = "deleteBranch", defaultValue = "true") boolean deleteBranch,
@RequestParam(name = "releaseComment", required = false) String releaseComment,
@RequestParam(name = "isEmergencyPublish", defaultValue = "false") boolean isEmergencyPublish,
@RequestBody ItemChangeSets changeSets) {
Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);
if (namespace == null) {
throw new NotFoundException(String.format("Could not find namespace for %s %s %s", appId,
clusterName, namespaceName));
}

Release release = releaseService.mergeBranchChangeSetsAndRelease(namespace, branchName,
releaseName, releaseComment, changeSets);
Release release = releaseService.mergeBranchChangeSetsAndRelease(namespace, branchName, releaseName,
releaseComment, isEmergencyPublish, changeSets);

if (deleteBranch) {
namespaceBranchService.deleteBranch(appId, clusterName, namespaceName, branchName,
NamespaceBranchStatus.MERGED, changeSets.getDataChangeLastModifiedBy());
NamespaceBranchStatus.MERGED, changeSets.getDataChangeLastModifiedBy());
}

messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public void testMessageSendAfterBuildRelease() throws Exception {
.thenReturn(someNamespace);

releaseController
.publish(someAppId, someCluster, someNamespaceName, someName, someComment, "test");
.publish(someAppId, someCluster, someNamespaceName, someName, someComment, "test", false);

verify(someMessageSender, times(1))
.sendMessage(Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.ctrip.framework.apollo.biz.entity.Release;
import com.ctrip.framework.apollo.biz.repository.ReleaseRepository;
import com.ctrip.framework.apollo.biz.utils.ReleaseKeyGenerator;
import com.ctrip.framework.apollo.common.constants.GsonType;
import com.ctrip.framework.apollo.common.constants.ReleaseOperation;
import com.ctrip.framework.apollo.common.constants.ReleaseOperationContext;
import com.ctrip.framework.apollo.common.dto.ItemChangeSets;
Expand Down Expand Up @@ -43,12 +44,10 @@
*/
@Service
public class ReleaseService {

private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance("yyyyMMddHHmmss");
private Gson gson = new Gson();

private Type configurationTypeReference = new TypeToken<Map<String, String>>() {
}.getType();

@Autowired
private ReleaseRepository releaseRepository;
@Autowired
Expand Down Expand Up @@ -123,12 +122,11 @@ public List<Release> findActiveReleases(String appId, String clusterName, String
}

@Transactional
public Release mergeBranchChangeSetsAndRelease(Namespace namespace, String branchName, String
releaseName, String releaseComment, ItemChangeSets changeSets) {
NamespaceLock lock = namespaceLockService.findLock(namespace.getId());
if (lock != null && lock.getDataChangeCreatedBy().equals(changeSets.getDataChangeLastModifiedBy())) {
throw new BadRequestException("config can not be published by yourself.");
}
public Release mergeBranchChangeSetsAndRelease(Namespace namespace, String branchName, String releaseName,
String releaseComment, boolean isEmergencyPublish,
ItemChangeSets changeSets) {

checkLock(namespace, isEmergencyPublish, changeSets.getDataChangeLastModifiedBy());

itemSetService.updateSet(namespace, changeSets);

Expand All @@ -141,22 +139,19 @@ public Release mergeBranchChangeSetsAndRelease(Namespace namespace, String branc
Map<String, Object> operationContext = Maps.newHashMap();
operationContext.put(ReleaseOperationContext.SOURCE_BRANCH, branchName);
operationContext.put(ReleaseOperationContext.BASE_RELEASE_ID, branchReleaseId);
operationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish);

Release release = masterRelease(namespace, releaseName, releaseComment, operateNamespaceItems,
changeSets.getDataChangeLastModifiedBy(),
ReleaseOperation.GRAY_RELEASE_MERGE_TO_MASTER, operationContext);
return masterRelease(namespace, releaseName, releaseComment, operateNamespaceItems,
changeSets.getDataChangeLastModifiedBy(),
ReleaseOperation.GRAY_RELEASE_MERGE_TO_MASTER, operationContext);

return release;
}

@Transactional
public Release publish(Namespace namespace, String releaseName, String releaseComment,
String operator) {
String operator, boolean isEmergencyPublish) {

NamespaceLock lock = namespaceLockService.findLock(namespace.getId());
if (lock != null && lock.getDataChangeCreatedBy().equals(operator)) {
throw new BadRequestException("config can not be published by yourself.");
}
checkLock(namespace, isEmergencyPublish, operator);

Map<String, String> operateNamespaceItems = getNamespaceItems(namespace);

Expand All @@ -165,7 +160,7 @@ public Release publish(Namespace namespace, String releaseName, String releaseCo
//branch release
if (parentNamespace != null) {
return publishBranchNamespace(parentNamespace, namespace, operateNamespaceItems,
releaseName, releaseComment, operator);
releaseName, releaseComment, operator, isEmergencyPublish);
}

Namespace childNamespace = namespaceService.findChildNamespace(namespace);
Expand All @@ -176,59 +171,71 @@ public Release publish(Namespace namespace, String releaseName, String releaseCo
}

//master release
Map<String, Object> operationContext = Maps.newHashMap();
operationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish);

Release release = masterRelease(namespace, releaseName, releaseComment, operateNamespaceItems,
operator, ReleaseOperation.NORMAL_RELEASE, null);
operator, ReleaseOperation.NORMAL_RELEASE, operationContext);

//merge to branch and auto release
if (childNamespace != null) {
mergeFromMasterAndPublishBranch(namespace, childNamespace, operateNamespaceItems,
releaseName, releaseComment, operator, previousRelease, release);
releaseName, releaseComment, operator, previousRelease,
release, isEmergencyPublish);
}

return release;
}

private void checkLock(Namespace namespace, boolean isEmergencyPublish, String operator) {
if (!isEmergencyPublish) {
NamespaceLock lock = namespaceLockService.findLock(namespace.getId());
if (lock != null && lock.getDataChangeCreatedBy().equals(operator)) {
throw new BadRequestException("Config can not be published by yourself.");
}
}
}

private void mergeFromMasterAndPublishBranch(Namespace parentNamespace, Namespace childNamespace,
Map<String, String> parentNamespaceItems,
String releaseName, String releaseComment,
String operator, Release masterPreviousRelease, Release parentRelease) {
// //create release for child namespace
String operator, Release masterPreviousRelease,
Release parentRelease, boolean isEmergencyPublish) {
//create release for child namespace
Map<String, String> childReleaseConfiguration = getNamespaceReleaseConfiguration(childNamespace);
Map<String, String> parentNamespaceOldConfiguration = masterPreviousRelease == null ? null :
gson.fromJson(
masterPreviousRelease.getConfigurations(),
configurationTypeReference);
Map<String, String> parentNamespaceOldConfiguration = masterPreviousRelease == null ?
null : gson.fromJson(masterPreviousRelease.getConfigurations(),
GsonType.CONFIG);

Map<String, String>
childNamespaceToPublishConfigs =
Map<String, String> childNamespaceToPublishConfigs =
calculateChildNamespaceToPublishConfiguration(parentNamespaceOldConfiguration,
parentNamespaceItems,
childNamespace);
//compare
if (!childNamespaceToPublishConfigs.equals(childReleaseConfiguration)) {
branchRelease(parentNamespace, childNamespace, releaseName, releaseComment,
childNamespaceToPublishConfigs, parentRelease.getId(), operator,
ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY);
ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY, isEmergencyPublish);
}

}

private Release publishBranchNamespace(Namespace parentNamespace, Namespace childNamespace,
Map<String, String> childNamespaceItems,
String releaseName, String releaseComment, String operator) {
String releaseName, String releaseComment,
String operator, boolean isEmergencyPublish) {
Release parentLatestRelease = findLatestActiveRelease(parentNamespace);
Map<String, String> parentConfigurations = parentLatestRelease != null ?
gson.fromJson(parentLatestRelease.getConfigurations(),
configurationTypeReference) : new HashMap<>();
GsonType.CONFIG) : new HashMap<>();
long baseReleaseId = parentLatestRelease == null ? 0 : parentLatestRelease.getId();

Map<String, String> childNamespaceToPublishConfigs = mergeConfiguration(parentConfigurations, childNamespaceItems);
Release release =
branchRelease(parentNamespace, childNamespace, releaseName, releaseComment,
childNamespaceToPublishConfigs, baseReleaseId, operator,
ReleaseOperation.GRAY_RELEASE);

return release;
return branchRelease(parentNamespace, childNamespace, releaseName, releaseComment,
childNamespaceToPublishConfigs, baseReleaseId, operator,
ReleaseOperation.GRAY_RELEASE, isEmergencyPublish);

}

private Release masterRelease(Namespace namespace, String releaseName, String releaseComment,
Expand All @@ -241,23 +248,24 @@ private Release masterRelease(Namespace namespace, String releaseName, String re

releaseHistoryService.createReleaseHistory(namespace.getAppId(), namespace.getClusterName(),
namespace.getNamespaceName(), namespace.getClusterName(),
release.getId(),
previousReleaseId, releaseOperation, operationContext, operator);
release.getId(), previousReleaseId, releaseOperation,
operationContext, operator);

return release;
}

private Release branchRelease(Namespace parentNamespace, Namespace childNamespace,
String releaseName, String releaseComment,
Map<String, String> configurations, long baseReleaseId,
String operator, int releaseOperation) {
String operator, int releaseOperation, boolean isEmergencyPublish) {
Release previousRelease = findLatestActiveRelease(childNamespace.getAppId(),
childNamespace.getClusterName(),
childNamespace.getNamespaceName());
long previousReleaseId = previousRelease == null ? 0 : previousRelease.getId();

Map<String, Object> releaseOperationContext = Maps.newHashMap();
releaseOperationContext.put(ReleaseOperationContext.BASE_RELEASE_ID, baseReleaseId);
releaseOperationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish);

Release release =
createRelease(childNamespace, releaseName, releaseComment, configurations, operator);
Expand Down Expand Up @@ -316,8 +324,7 @@ private Map<String, String> getNamespaceReleaseConfiguration(Namespace namespace
Release release = findLatestActiveRelease(namespace);
Map<String, String> configuration = new HashMap<>();
if (release != null) {
configuration = new Gson().fromJson(release.getConfigurations(),
configurationTypeReference);
configuration = new Gson().fromJson(release.getConfigurations(), GsonType.CONFIG);
}
return configuration;
}
Expand Down Expand Up @@ -395,22 +402,22 @@ private void rollbackChildNamespace(String appId, String clusterName, String nam
Release parentNamespaceNewLatestRelease = parentNamespaceTwoLatestActiveRelease.get(1);

Map<String, String> parentNamespaceAbandonedConfiguration = gson.fromJson(abandonedRelease.getConfigurations(),
configurationTypeReference);
GsonType.CONFIG);

Map<String, String>
parentNamespaceNewLatestConfiguration =
gson.fromJson(parentNamespaceNewLatestRelease.getConfigurations(),
configurationTypeReference);
gson.fromJson(parentNamespaceNewLatestRelease.getConfigurations(), GsonType.CONFIG);

Map<String, String>
childNamespaceNewConfiguration =
calculateChildNamespaceToPublishConfiguration(parentNamespaceAbandonedConfiguration,
parentNamespaceNewLatestConfiguration,
childNamespace);

branchRelease(parentNamespace, childNamespace, TIMESTAMP_FORMAT.format(new Date()) + "-master-rollback-merge-to-gray", "",
branchRelease(parentNamespace, childNamespace,
TIMESTAMP_FORMAT.format(new Date()) + "-master-rollback-merge-to-gray", "",
childNamespaceNewConfiguration, parentNamespaceNewLatestRelease.getId(), operator,
ReleaseOperation.MATER_ROLLBACK_MERGE_TO_GRAY);
ReleaseOperation.MATER_ROLLBACK_MERGE_TO_GRAY, false);
}

private Map<String, String> calculateChildNamespaceToPublishConfiguration(
Expand All @@ -423,7 +430,7 @@ private Map<String, String> calculateChildNamespaceToPublishConfiguration(
Map<String, String> childNamespaceLatestActiveConfiguration = childNamespaceLatestActiveRelease == null ? null :
gson.fromJson(childNamespaceLatestActiveRelease
.getConfigurations(),
configurationTypeReference);
GsonType.CONFIG);

Map<String, String> childNamespaceModifiedConfiguration = calculateBranchModifiedItemsAccordingToRelease(
parentNamespaceOldConfiguration, childNamespaceLatestActiveConfiguration);
Expand Down
Loading

0 comments on commit db65452

Please sign in to comment.