Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
nobodyiam committed Nov 17, 2018
1 parent c121a9e commit f753bb9
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.ctrip.framework.apollo.biz.entity.ReleaseHistory;

import java.util.Set;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Modifying;
Expand All @@ -19,6 +20,8 @@ Page<ReleaseHistory> findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(Stri

Page<ReleaseHistory> findByPreviousReleaseIdAndOperationOrderByIdDesc(long previousReleaseId, int operation, Pageable pageable);

Page<ReleaseHistory> findByReleaseIdAndOperationInOrderByIdDesc(long releaseId, Set<Integer> operations, Pageable pageable);

@Modifying
@Query("update ReleaseHistory 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.ctrip.framework.apollo.biz.entity.ReleaseHistory;
import com.ctrip.framework.apollo.biz.repository.ReleaseHistoryRepository;

import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -43,6 +44,10 @@ public Page<ReleaseHistory> findByPreviousReleaseIdAndOperation(long previousRel
return releaseHistoryRepository.findByPreviousReleaseIdAndOperationOrderByIdDesc(previousReleaseId, operation, page);
}

public Page<ReleaseHistory> findByReleaseIdAndOperationInOrderByIdDesc(long releaseId, Set<Integer> operations, Pageable page) {
return releaseHistoryRepository.findByReleaseIdAndOperationInOrderByIdDesc(releaseId, operations, page);
}

@Transactional
public ReleaseHistory createReleaseHistory(String appId, String clusterName, String
namespaceName, String branchName, long releaseId, long previousReleaseId, int operation,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.ctrip.framework.apollo.biz.service;

import com.ctrip.framework.apollo.biz.entity.ReleaseHistory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.Gson;

import com.ctrip.framework.apollo.biz.entity.Audit;
Expand All @@ -21,8 +23,12 @@
import com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer;
import com.ctrip.framework.apollo.core.utils.StringUtils;

import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collection;
import org.apache.commons.lang.time.FastDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
Expand All @@ -44,7 +50,12 @@
public class ReleaseService {

private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance("yyyyMMddHHmmss");
private Gson gson = new Gson();
private static final Gson gson = new Gson();
private static final Set<Integer> BRANCH_RELEASE_OPERATIONS = Sets
.newHashSet(ReleaseOperation.GRAY_RELEASE, ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY,
ReleaseOperation.MATER_ROLLBACK_MERGE_TO_GRAY);
private static final Pageable FIRST_ITEM = PageRequest.of(0, 1);
private static final Type OPERATION_CONTEXT_TYPE_REFERENCE = new TypeToken<Map<String, Object>>() { }.getType();

@Autowired
private ReleaseRepository releaseRepository;
Expand Down Expand Up @@ -204,8 +215,8 @@ private Release publishBranchNamespace(Namespace parentNamespace, Namespace chil
}

return branchRelease(parentNamespace, childNamespace, releaseName, releaseComment,
configsToPublish, baseReleaseId, operator,
ReleaseOperation.GRAY_RELEASE, isEmergencyPublish);
configsToPublish, baseReleaseId, operator, ReleaseOperation.GRAY_RELEASE, isEmergencyPublish,
childNamespaceItems.keySet());

}

Expand Down Expand Up @@ -243,22 +254,51 @@ private void mergeFromMasterAndPublishBranch(Namespace parentNamespace, Namespac
String operator, Release masterPreviousRelease,
Release parentRelease, boolean isEmergencyPublish) {
//create release for child namespace
Map<String, String> childReleaseConfiguration = getNamespaceReleaseConfiguration(childNamespace);
Release childNamespaceLatestActiveRelease = findLatestActiveRelease(childNamespace);

Map<String, String> childReleaseConfiguration;
Collection<String> branchReleaseKeys;
if (childNamespaceLatestActiveRelease != null) {
childReleaseConfiguration = gson.fromJson(childNamespaceLatestActiveRelease.getConfigurations(), GsonType.CONFIG);
branchReleaseKeys = getBranchReleaseKeys(childNamespaceLatestActiveRelease.getId());
} else {
childReleaseConfiguration = Collections.emptyMap();
branchReleaseKeys = null;
}

Map<String, String> parentNamespaceOldConfiguration = masterPreviousRelease == null ?
null : gson.fromJson(masterPreviousRelease.getConfigurations(),
GsonType.CONFIG);

Map<String, String> childNamespaceToPublishConfigs =
calculateChildNamespaceToPublishConfiguration(parentNamespaceOldConfiguration,
parentNamespaceItems,
childNamespace);
calculateChildNamespaceToPublishConfiguration(parentNamespaceOldConfiguration, parentNamespaceItems,
childReleaseConfiguration, branchReleaseKeys);

//compare
if (!childNamespaceToPublishConfigs.equals(childReleaseConfiguration)) {
branchRelease(parentNamespace, childNamespace, releaseName, releaseComment,
childNamespaceToPublishConfigs, parentRelease.getId(), operator,
ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY, isEmergencyPublish);
ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY, isEmergencyPublish, branchReleaseKeys);
}

}

private Collection<String> getBranchReleaseKeys(long releaseId) {
Page<ReleaseHistory> releaseHistories = releaseHistoryService
.findByReleaseIdAndOperationInOrderByIdDesc(releaseId, BRANCH_RELEASE_OPERATIONS, FIRST_ITEM);

if (!releaseHistories.hasContent()) {
return null;
}

Map<String, Object> operationContext = gson
.fromJson(releaseHistories.getContent().get(0).getOperationContext(), OPERATION_CONTEXT_TYPE_REFERENCE);

if (operationContext == null || !operationContext.containsKey(ReleaseOperationContext.BRANCH_RELEASE_KEYS)) {
return null;
}

return (Collection<String>) operationContext.get(ReleaseOperationContext.BRANCH_RELEASE_KEYS);
}

private Release publishBranchNamespace(Namespace parentNamespace, Namespace childNamespace,
Expand Down Expand Up @@ -289,7 +329,7 @@ private Release masterRelease(Namespace namespace, String releaseName, String re
private Release branchRelease(Namespace parentNamespace, Namespace childNamespace,
String releaseName, String releaseComment,
Map<String, String> configurations, long baseReleaseId,
String operator, int releaseOperation, boolean isEmergencyPublish) {
String operator, int releaseOperation, boolean isEmergencyPublish, Collection<String> branchReleaseKeys) {
Release previousRelease = findLatestActiveRelease(childNamespace.getAppId(),
childNamespace.getClusterName(),
childNamespace.getNamespaceName());
Expand All @@ -298,6 +338,7 @@ private Release branchRelease(Namespace parentNamespace, Namespace childNamespac
Map<String, Object> releaseOperationContext = Maps.newHashMap();
releaseOperationContext.put(ReleaseOperationContext.BASE_RELEASE_ID, baseReleaseId);
releaseOperationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish);
releaseOperationContext.put(ReleaseOperationContext.BRANCH_RELEASE_KEYS, branchReleaseKeys);

Release release =
createRelease(childNamespace, releaseName, releaseComment, configurations, operator);
Expand Down Expand Up @@ -352,15 +393,6 @@ private Map<String, String> getNamespaceItems(Namespace namespace) {
return configurations;
}

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(), GsonType.CONFIG);
}
return configuration;
}

private Release createRelease(Namespace namespace, String name, String comment,
Map<String, String> configurations, String operator) {
Release release = new Release();
Expand Down Expand Up @@ -430,6 +462,17 @@ private void rollbackChildNamespace(String appId, String clusterName, String nam
return;
}

Release childNamespaceLatestActiveRelease = findLatestActiveRelease(childNamespace);
Map<String, String> childReleaseConfiguration;
Collection<String> branchReleaseKeys;
if (childNamespaceLatestActiveRelease != null) {
childReleaseConfiguration = gson.fromJson(childNamespaceLatestActiveRelease.getConfigurations(), GsonType.CONFIG);
branchReleaseKeys = getBranchReleaseKeys(childNamespaceLatestActiveRelease.getId());
} else {
childReleaseConfiguration = Collections.emptyMap();
branchReleaseKeys = null;
}

Release abandonedRelease = parentNamespaceTwoLatestActiveRelease.get(0);
Release parentNamespaceNewLatestRelease = parentNamespaceTwoLatestActiveRelease.get(1);

Expand All @@ -443,44 +486,51 @@ private void rollbackChildNamespace(String appId, String clusterName, String nam
Map<String, String>
childNamespaceNewConfiguration =
calculateChildNamespaceToPublishConfiguration(parentNamespaceAbandonedConfiguration,
parentNamespaceNewLatestConfiguration,
childNamespace);
parentNamespaceNewLatestConfiguration, childReleaseConfiguration, branchReleaseKeys);

branchRelease(parentNamespace, childNamespace,
TIMESTAMP_FORMAT.format(new Date()) + "-master-rollback-merge-to-gray", "",
childNamespaceNewConfiguration, parentNamespaceNewLatestRelease.getId(), operator,
ReleaseOperation.MATER_ROLLBACK_MERGE_TO_GRAY, false);
//compare
if (!childNamespaceNewConfiguration.equals(childReleaseConfiguration)) {
branchRelease(parentNamespace, childNamespace,
TIMESTAMP_FORMAT.format(new Date()) + "-master-rollback-merge-to-gray", "",
childNamespaceNewConfiguration, parentNamespaceNewLatestRelease.getId(), operator,
ReleaseOperation.MATER_ROLLBACK_MERGE_TO_GRAY, false, branchReleaseKeys);
}
}

private Map<String, String> calculateChildNamespaceToPublishConfiguration(
Map<String, String> parentNamespaceOldConfiguration,
Map<String, String> parentNamespaceNewConfiguration,
Namespace childNamespace) {
Map<String, String> parentNamespaceOldConfiguration, Map<String, String> parentNamespaceNewConfiguration,
Map<String, String> childNamespaceLatestActiveConfiguration, Collection<String> branchReleaseKeys) {
//first. calculate child namespace modified configs
Release childNamespaceLatestActiveRelease = findLatestActiveRelease(childNamespace);

Map<String, String> childNamespaceLatestActiveConfiguration = childNamespaceLatestActiveRelease == null ? null :
gson.fromJson(childNamespaceLatestActiveRelease
.getConfigurations(),
GsonType.CONFIG);

Map<String, String> childNamespaceModifiedConfiguration = calculateBranchModifiedItemsAccordingToRelease(
parentNamespaceOldConfiguration, childNamespaceLatestActiveConfiguration);
parentNamespaceOldConfiguration, childNamespaceLatestActiveConfiguration, branchReleaseKeys);

//second. append child namespace modified configs to parent namespace new latest configuration
return mergeConfiguration(parentNamespaceNewConfiguration, childNamespaceModifiedConfiguration);
}

private Map<String, String> calculateBranchModifiedItemsAccordingToRelease(
Map<String, String> masterReleaseConfigs,
Map<String, String> branchReleaseConfigs) {
Map<String, String> masterReleaseConfigs, Map<String, String> branchReleaseConfigs,
Collection<String> branchReleaseKeys) {

Map<String, String> modifiedConfigs = new HashMap<>();

if (CollectionUtils.isEmpty(branchReleaseConfigs)) {
return modifiedConfigs;
}

// new logic, retrieve modified configurations based on branch release keys
if (branchReleaseKeys != null) {
for (String branchReleaseKey : branchReleaseKeys) {
if (branchReleaseConfigs.containsKey(branchReleaseKey)) {
modifiedConfigs.put(branchReleaseKey, branchReleaseConfigs.get(branchReleaseKey));
}
}

return modifiedConfigs;
}

// old logic, retrieve modified configurations by comparing branchReleaseConfigs with masterReleaseConfigs
if (CollectionUtils.isEmpty(masterReleaseConfigs)) {
return branchReleaseConfigs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,4 @@ INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted

INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(6, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default6', 'application', '{"k1":"v1-1","k2":"v2-1","k3":"v3"}', 0);
INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(7, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default6', 'application', '{"k1":"v1","k2":"v2"}', 0);
INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(8, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'child-cluster6', 'application', '{"k1":"v1-2","k2":"v2-1","k3":"v3"}', 0);
INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(8, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'child-cluster6', 'application', '{"k1":"v1-2","k2":"v2","k3":"v3"}', 0);
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.ctrip.framework.apollo;

import java.io.File;
import com.ctrip.framework.apollo.core.ConfigConsts;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.TimeUnit;
Expand All @@ -16,6 +16,7 @@
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;

Expand All @@ -25,9 +26,7 @@
import com.ctrip.framework.apollo.core.utils.ClassLoaderUtil;
import com.ctrip.framework.apollo.internals.DefaultInjector;
import com.ctrip.framework.apollo.util.ConfigUtil;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import com.google.gson.Gson;

/**
Expand All @@ -49,9 +48,12 @@ public abstract class BaseIntegrationTest{

@BeforeClass
public static void beforeClass() throws Exception {
File apolloEnvPropertiesFile = new File(ClassLoaderUtil.getClassPath(), "apollo-env.properties");
Files.write("dev.meta=" + metaServiceUrl, apolloEnvPropertiesFile, Charsets.UTF_8);
apolloEnvPropertiesFile.deleteOnExit();
System.setProperty(ConfigConsts.APOLLO_META_KEY, metaServiceUrl);
}

@AfterClass
public static void afterClass() throws Exception {
System.clearProperty(ConfigConsts.APOLLO_META_KEY);
}

@Before
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,4 @@ public void testWithSystemProperty() throws Exception {
assertEquals(someMetaAddress, defaultMetaServerProvider.getMetaServerAddress(someEnv));
}

@Test
public void testWithNoSystemProperty() throws Exception {
Env someEnv = Env.DEV;

DefaultMetaServerProvider defaultMetaServerProvider = new DefaultMetaServerProvider();

assertNull(defaultMetaServerProvider.getMetaServerAddress(someEnv));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public interface ReleaseOperationContext {
String OLD_RULES = "oldRules";
String BASE_RELEASE_ID = "baseReleaseId";
String IS_EMERGENCY_PUBLISH = "isEmergencyPublish";
String BRANCH_RELEASE_KEYS = "branchReleaseKeys";
}

0 comments on commit f753bb9

Please sign in to comment.