You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by dm...@apache.org on 2015/09/17 13:42:50 UTC
ambari git commit: AMBARI-13100. Stop-and-Start Upgrade: Apply
configs from multiple major stack versions. (dlysnichenko)
Repository: ambari
Updated Branches:
refs/heads/branch-dev-stop-all-upgrade df0d238a1 -> b9b708e6c
AMBARI-13100. Stop-and-Start Upgrade: Apply configs from multiple major stack versions. (dlysnichenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b9b708e6
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b9b708e6
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b9b708e6
Branch: refs/heads/branch-dev-stop-all-upgrade
Commit: b9b708e6c2f603c306eff14b3c303b6daa18655c
Parents: df0d238
Author: Lisnichenko Dmitro <dl...@hortonworks.com>
Authored: Thu Sep 17 14:37:52 2015 +0300
Committer: Lisnichenko Dmitro <dl...@hortonworks.com>
Committed: Thu Sep 17 14:37:52 2015 +0300
----------------------------------------------------------------------
.../internal/UpgradeResourceProvider.java | 24 ++-
.../server/state/stack/ConfigUpgradePack.java | 67 ++++++--
.../ambari/server/state/stack/UpgradePack.java | 21 +++
.../HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml | 5 +
.../checks/UpgradeCheckStackVersionTest.java | 170 -------------------
.../state/stack/ConfigUpgradePackTest.java | 148 ++++++++++++++++
6 files changed, 249 insertions(+), 186 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/b9b708e6/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
index 8f4870c..a2f642c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
@@ -582,10 +582,24 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
applyStackAndProcessConfigurations(targetStackId.getStackName(), cluster, version, direction, pack);
}
- // TODO: for cross-stack upgrade, merge a new config upgrade pack from all
- // target stacks involved into upgrade and pass it into method
- ConfigUpgradePack configUpgradePack = s_metaProvider.get().getConfigUpgradePack(
- targetStackId.getStackName(), targetStackId.getStackVersion());
+ // Resolve or build a proper config upgrade pack
+ List<UpgradePack.IntermediateStack> intermediateStacks = pack.getIntermediateStacks();
+ ConfigUpgradePack configUpgradePack;
+ if (intermediateStacks == null || intermediateStacks.isEmpty()) { // No intermediate stacks
+ configUpgradePack = s_metaProvider.get().getConfigUpgradePack(
+ targetStackId.getStackName(), targetStackId.getStackVersion());
+ } else {
+ // For cross-stack upgrade, follow all major stacks and merge a new config upgrade pack from all
+ // target stacks involved into upgrade
+ ArrayList<ConfigUpgradePack> intermediateConfigUpgradePacks = new ArrayList<>();
+ for (UpgradePack.IntermediateStack intermediateStack : intermediateStacks) {
+ ConfigUpgradePack intermediateConfigUpgradePack = s_metaProvider.get().getConfigUpgradePack(
+ targetStackId.getStackName(), intermediateStack.version);
+ intermediateConfigUpgradePacks.add(intermediateConfigUpgradePack);
+ }
+ configUpgradePack = ConfigUpgradePack.merge(intermediateConfigUpgradePacks);
+ }
+
for (UpgradeGroupHolder group : groups) {
UpgradeGroupEntity groupEntity = new UpgradeGroupEntity();
groupEntity.setName(group.name);
@@ -724,7 +738,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
Map<String, Map<String, String>> newConfigurationsByType = null;
ConfigHelper configHelper = getManagementController().getConfigHelper();
- // TODO AMBARI-12698, handle jumping across several stacks and applying configs.
+ // TODO AMBARI-12698, handle jumping across several stacks
if (direction == Direction.UPGRADE) {
// populate a map of default configurations for the old stack (this is
// used when determining if a property has been customized and should be
http://git-wip-us.apache.org/repos/asf/ambari/blob/b9b708e6/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigUpgradePack.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigUpgradePack.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigUpgradePack.java
index 2896255..f2e2e61 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigUpgradePack.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigUpgradePack.java
@@ -27,6 +27,9 @@ import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -34,18 +37,22 @@ import java.util.Map;
/**
* Represents a pack of changes that should be applied to configs
* when upgrading from a previous stack. In other words, it's a config delta
- * from prev stack
+ * from prev stack.
+ *
+ * After first call of enumerateConfigChangesByID() method, instance contains
+ * a cache of data, so it should not be modified in runtime (otherwise
+ * the cache will become outdated).
*/
@XmlRootElement(name="upgrade-config-changes")
@XmlAccessorType(XmlAccessType.FIELD)
public class ConfigUpgradePack {
/**
- * Defines per-service config changes
+ * Defines per-service config changes.
*/
@XmlElementWrapper(name="services")
@XmlElement(name="service")
- private List<AffectedService> services;
+ public List<AffectedService> services;
/**
* Contains a cached mapping of <change id, change definition>.
@@ -65,14 +72,6 @@ public class ConfigUpgradePack {
}
/**
- * @return a list of per-service config changes. List should not be modified
- * in runtime, since it will make cache stale.
- */
- public List<AffectedService> getServices() {
- return services;
- }
-
- /**
* @return a map of <service name, AffectedService>.
*/
public Map<String, AffectedService> getServiceMap() {
@@ -109,6 +108,52 @@ public class ConfigUpgradePack {
}
/**
+ * Merges few config upgrade packs into one and returs result. During merge,
+ * a deep copy of AffectedService and AffectedComponent lists is added to resulting
+ * config upgrade pack. The only level that is not copied deeply is a list of
+ * per-component config changes.
+ * @param cups list of source config upgrade packs
+ * @return merged config upgrade pack that is a deep copy of source
+ * config upgrade packs
+ */
+ public static ConfigUpgradePack merge(ArrayList<ConfigUpgradePack> cups) {
+ // Map <service_name, <component_name, component_changes>>
+ Map<String, Map<String, AffectedComponent>> mergedServiceMap = new HashMap<>();
+
+ for (ConfigUpgradePack configUpgradePack : cups) {
+ for (AffectedService service : configUpgradePack.services) {
+ if (! mergedServiceMap.containsKey(service.name)) {
+ mergedServiceMap.put(service.name, new HashMap<String, AffectedComponent>());
+ }
+ Map<String, AffectedComponent> mergedComponentMap = mergedServiceMap.get(service.name);
+
+ for (AffectedComponent component : service.components) {
+ if (! mergedComponentMap.containsKey(component.name)) {
+ AffectedComponent mergedComponent = new AffectedComponent();
+ mergedComponent.name = component.name;
+ mergedComponent.changes = new ArrayList<>();
+ mergedComponentMap.put(component.name, mergedComponent);
+ }
+ AffectedComponent mergedComponent = mergedComponentMap.get(component.name);
+ mergedComponent.changes.addAll(component.changes);
+ }
+
+ }
+ }
+ // Convert merged maps into new ConfigUpgradePack
+ ArrayList<AffectedService> mergedServices = new ArrayList<>();
+ for (String serviceName : mergedServiceMap.keySet()) {
+ AffectedService mergedService = new AffectedService();
+ Map<String, AffectedComponent> mergedComponentMap = mergedServiceMap.get(serviceName);
+ mergedService.name = serviceName;
+ mergedService.components = new ArrayList<>(mergedComponentMap.values());
+ mergedServices.add(mergedService);
+ }
+
+ return new ConfigUpgradePack(mergedServices);
+ }
+
+ /**
* A service definition in the 'services' element.
*/
public static class AffectedService {
http://git-wip-us.apache.org/repos/asf/ambari/blob/b9b708e6/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java
index 6ae0a15..aa207f1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java
@@ -60,6 +60,10 @@ public class UpgradePack {
@XmlElement(name="type", defaultValue="rolling")
private UpgradeType type;
+ @XmlElementWrapper(name="upgrade-path")
+ @XmlElement(name="intermediate-stack")
+ private List<IntermediateStack> intermediateStacks;
+
@XmlElementWrapper(name="order")
@XmlElement(name="group")
private List<Grouping> groups;
@@ -120,6 +124,13 @@ public class UpgradePack {
}
/**
+ * @return a list for intermediate stacks for cross-stack upgrade, or null if no any
+ */
+ public List<IntermediateStack> getIntermediateStacks() {
+ return intermediateStacks;
+ }
+
+ /**
* Gets the groups defined for the upgrade pack. If a direction is defined
* for a group, it must match the supplied direction to be returned
* @param direction the direction to return the ordered groups
@@ -310,4 +321,14 @@ public class UpgradePack {
@XmlElement(name="task")
public List<Task> postDowngradeTasks;
}
+
+ /**
+ * An intermediate stack definition in
+ * upgrade/upgrade-path/intermediate-stack path
+ */
+ public static class IntermediateStack {
+
+ @XmlAttribute
+ public String version;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/b9b708e6/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml b/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml
index 743204c0..1da05c2 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.1/upgrades/nonrolling-upgrade-2.3.xml
@@ -22,6 +22,11 @@
<target-stack>HDP-2.3</target-stack>
<type>NON_ROLLING</type>
+ <upgrade-path>
+ <intermediate-stack version="2.2"/>
+ <intermediate-stack version="2.3"/>
+ </upgrade-path>
+
<order>
<group xsi:type="cluster" name="PRE_CLUSTER" title="Prepare Upgrade">
<skippable>true</skippable>
http://git-wip-us.apache.org/repos/asf/ambari/blob/b9b708e6/ambari-server/src/test/java/org/apache/ambari/server/checks/UpgradeCheckStackVersionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/UpgradeCheckStackVersionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/UpgradeCheckStackVersionTest.java
deleted file mode 100644
index 8d8b08f..0000000
--- a/ambari-server/src/test/java/org/apache/ambari/server/checks/UpgradeCheckStackVersionTest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.ambari.server.checks;
-
-import junit.framework.Assert;
-
-import org.apache.ambari.server.controller.PrereqCheckRequest;
-import org.apache.ambari.server.state.StackId;
-import org.easymock.EasyMock;
-import org.junit.Test;
-
-
-/**
- * Tests that the {@link AbstractCheckDescriptor} instances will return the
- * correct values for
- * {@link AbstractCheckDescriptor#isApplicable(org.apache.ambari.server.controller.PrereqCheckRequest)}
- * when different stack versions are present.
- */
-public class UpgradeCheckStackVersionTest {
-
- @Test
- public void testUpgradeCheckForMoreRecentStack() throws Exception {
- AbstractCheckDescriptor invalidCheck = EasyMock.createMockBuilder(AbstractCheckDescriptor.class).addMockedMethods(
- "getSourceStack", "getTargetStack").createMock();
-
- EasyMock.expect(invalidCheck.getSourceStack()).andReturn(new StackId("HDP-2.3"));
- EasyMock.expect(invalidCheck.getTargetStack()).andReturn(new StackId("HDP-2.3"));
-
- EasyMock.replay(invalidCheck);
-
- PrereqCheckRequest checkRequest = new PrereqCheckRequest("c1");
- checkRequest.setRepositoryVersion("HDP-2.2.0.0");
- checkRequest.setSourceStackId(new StackId("HDP", "2.2"));
- checkRequest.setTargetStackId(new StackId("HDP", "2.2"));
-
- // false because the upgrade is for 2.2->2.2 and the check starts at 2.3
- Assert.assertFalse(invalidCheck.isApplicable(checkRequest));
-
- EasyMock.verify(invalidCheck);
- }
-
- @Test
- public void testUpgradeCheckForOlderStack() throws Exception {
- AbstractCheckDescriptor invalidCheck = EasyMock.createMockBuilder(AbstractCheckDescriptor.class).addMockedMethods(
- "getSourceStack", "getTargetStack").createMock();
-
- EasyMock.expect(invalidCheck.getSourceStack()).andReturn(new StackId("HDP-2.2"));
- EasyMock.expect(invalidCheck.getTargetStack()).andReturn(new StackId("HDP-2.2"));
-
- EasyMock.replay(invalidCheck);
-
- PrereqCheckRequest checkRequest = new PrereqCheckRequest("c1");
- checkRequest.setRepositoryVersion("HDP-2.3.0.0");
- checkRequest.setSourceStackId(new StackId("HDP", "2.3"));
- checkRequest.setTargetStackId(new StackId("HDP", "2.3"));
-
- // false because the upgrade is for 2.3->2.3 and the check is only for 2.2
- Assert.assertFalse(invalidCheck.isApplicable(checkRequest));
-
- EasyMock.verify(invalidCheck);
- }
-
- @Test
- public void testUpgradeCheckForWithinStackOnly() throws Exception {
- AbstractCheckDescriptor invalidCheck = EasyMock.createMockBuilder(AbstractCheckDescriptor.class).addMockedMethods(
- "getSourceStack", "getTargetStack").createMock();
-
- EasyMock.expect(invalidCheck.getSourceStack()).andReturn(new StackId("HDP-2.2"));
- EasyMock.expect(invalidCheck.getTargetStack()).andReturn(new StackId("HDP-2.2"));
-
- EasyMock.replay(invalidCheck);
-
- PrereqCheckRequest checkRequest = new PrereqCheckRequest("c1");
- checkRequest.setRepositoryVersion("HDP-2.3.0.0");
- checkRequest.setSourceStackId(new StackId("HDP", "2.2"));
- checkRequest.setTargetStackId(new StackId("HDP", "2.3"));
-
- // false because the upgrade is for 2.2->2.3 and the check is only for 2.2
- // to 2.2
- Assert.assertFalse(invalidCheck.isApplicable(checkRequest));
-
- EasyMock.verify(invalidCheck);
- }
-
- @Test
- public void testUpgradeCheckMatchesExactly() throws Exception {
- AbstractCheckDescriptor invalidCheck = EasyMock.createMockBuilder(AbstractCheckDescriptor.class).addMockedMethods(
- "getSourceStack", "getTargetStack").createMock();
-
- EasyMock.expect(invalidCheck.getSourceStack()).andReturn(new StackId("HDP-2.2"));
- EasyMock.expect(invalidCheck.getTargetStack()).andReturn(new StackId("HDP-2.2"));
-
- EasyMock.replay(invalidCheck);
-
- PrereqCheckRequest checkRequest = new PrereqCheckRequest("c1");
- checkRequest.setRepositoryVersion("HDP-2.2.0.0");
- checkRequest.setSourceStackId(new StackId("HDP", "2.2"));
- checkRequest.setTargetStackId(new StackId("HDP", "2.2"));
-
- // pass because the upgrade is for 2.2->2.2 and the check is only for 2.2
- // to 2.2
- Assert.assertTrue(invalidCheck.isApplicable(checkRequest));
-
- EasyMock.verify(invalidCheck);
- }
-
- @Test
- public void testNoUpgradeStacksDefined() throws Exception {
- AbstractCheckDescriptor invalidCheck = EasyMock.createMockBuilder(AbstractCheckDescriptor.class).addMockedMethods(
- "getSourceStack", "getTargetStack").createMock();
-
- EasyMock.expect(invalidCheck.getSourceStack()).andReturn(null);
- EasyMock.expect(invalidCheck.getTargetStack()).andReturn(null);
-
- EasyMock.replay(invalidCheck);
-
- PrereqCheckRequest checkRequest = new PrereqCheckRequest("c1");
- checkRequest.setRepositoryVersion("HDP-2.3.0.0");
- checkRequest.setSourceStackId(new StackId("HDP", "2.2"));
- checkRequest.setTargetStackId(new StackId("HDP", "2.3"));
-
- // pass because there are no restrictions
- Assert.assertTrue(invalidCheck.isApplicable(checkRequest));
-
- EasyMock.verify(invalidCheck);
- }
-
- @Test
- public void testUpgradeStartsAtSpecifiedStackVersion() throws Exception {
- AbstractCheckDescriptor invalidCheck = EasyMock.createMockBuilder(AbstractCheckDescriptor.class).addMockedMethods(
- "getSourceStack", "getTargetStack").createMock();
-
- EasyMock.expect(invalidCheck.getSourceStack()).andReturn(new StackId("HDP-2.3")).atLeastOnce();
- EasyMock.expect(invalidCheck.getTargetStack()).andReturn(null).atLeastOnce();
-
- EasyMock.replay(invalidCheck);
-
- PrereqCheckRequest checkRequest = new PrereqCheckRequest("c1");
- checkRequest.setRepositoryVersion("HDP-2.2.0.0");
- checkRequest.setSourceStackId(new StackId("HDP", "2.2"));
- checkRequest.setTargetStackId(new StackId("HDP", "2.2"));
-
- // false because this check starts at 2.3 and the upgrade is 2.2 -> 2.2
- Assert.assertFalse(invalidCheck.isApplicable(checkRequest));
-
- checkRequest.setRepositoryVersion("HDP-2.3.0.0");
- checkRequest.setSourceStackId(new StackId("HDP", "2.2"));
- checkRequest.setTargetStackId(new StackId("HDP", "2.3"));
-
- // false because this check starts at 2.3 and the upgrade is 2.2 -> 2.3
- Assert.assertFalse(invalidCheck.isApplicable(checkRequest));
-
- EasyMock.verify(invalidCheck);
- }
-}
http://git-wip-us.apache.org/repos/asf/ambari/blob/b9b708e6/ambari-server/src/test/java/org/apache/ambari/server/state/stack/ConfigUpgradePackTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/ConfigUpgradePackTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/ConfigUpgradePackTest.java
new file mode 100644
index 0000000..da5c0ab
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/ConfigUpgradePackTest.java
@@ -0,0 +1,148 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.state.stack;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.state.stack.upgrade.ClusterGrouping;
+import org.apache.ambari.server.state.stack.upgrade.ClusterGrouping.ExecuteStage;
+import org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition;
+import org.apache.ambari.server.state.stack.upgrade.Direction;
+import org.apache.ambari.server.state.stack.upgrade.Grouping;
+import org.apache.ambari.server.state.stack.upgrade.RestartGrouping;
+import org.apache.ambari.server.state.stack.upgrade.StopGrouping;
+import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import static org.apache.ambari.server.state.stack.ConfigUpgradePack.AffectedService;
+import static org.apache.ambari.server.state.stack.ConfigUpgradePack.AffectedComponent;
+
+/**
+ * Tests for the config upgrade pack
+ */
+public class ConfigUpgradePackTest {
+
+ @Test
+ public void testMerge() {
+
+ // Generate test data - 3 config upgrade packs, 2 services, 2 components, 2 config changes each
+ ArrayList<ConfigUpgradePack> cups = new ArrayList<>();
+ for (int cupIndex = 0; cupIndex < 3; cupIndex++) {
+
+ ArrayList<AffectedService> services = new ArrayList<>();
+ for (int serviceIndex = 0; serviceIndex < 2; serviceIndex++) {
+ String serviceName;
+ if (serviceIndex == 0) {
+ serviceName = "HDFS"; // For checking merge of existing services
+ } else {
+ serviceName = String.format("SOME_SERVICE_%s", cupIndex);
+ }
+ ArrayList<AffectedComponent> components = new ArrayList<>();
+ for (int componentIndex = 0; componentIndex < 2; componentIndex++) {
+ String componentName;
+ if (componentIndex == 0) {
+ componentName = "NAMENODE"; // For checking merge of existing components
+ } else {
+ componentName = "SOME_COMPONENT_" + cupIndex;
+ }
+
+ ArrayList<ConfigUpgradeChangeDefinition> changeDefinitions = new ArrayList<>();
+ for (int changeIndex = 0; changeIndex < 2; changeIndex++) {
+ String change_id = String.format(
+ "CHANGE_%s_%s_%s_%s", cupIndex, serviceIndex, componentIndex, changeIndex);
+ ConfigUpgradeChangeDefinition changeDefinition = new ConfigUpgradeChangeDefinition();
+ changeDefinition.id = change_id;
+ changeDefinitions.add(changeDefinition);
+ }
+ AffectedComponent component = new AffectedComponent();
+ component.name = componentName;
+ component.changes = changeDefinitions;
+ components.add(component);
+ }
+ AffectedService service = new AffectedService();
+ service.name = serviceName;
+ service.components = components;
+ services.add(service);
+ }
+ ConfigUpgradePack cupI = new ConfigUpgradePack();
+ cupI.services = services;
+ cups.add(cupI);
+ }
+
+ // Merge
+
+ ConfigUpgradePack result = ConfigUpgradePack.merge(cups);
+
+
+ // Check test results
+
+ assertEquals(result.enumerateConfigChangesByID().entrySet().size(), 24);
+
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("NAMENODE").changes.get(0).id, "CHANGE_0_0_0_0");
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("NAMENODE").changes.get(1).id, "CHANGE_0_0_0_1");
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("NAMENODE").changes.get(2).id, "CHANGE_1_0_0_0");
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("NAMENODE").changes.get(3).id, "CHANGE_1_0_0_1");
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("NAMENODE").changes.get(4).id, "CHANGE_2_0_0_0");
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("NAMENODE").changes.get(5).id, "CHANGE_2_0_0_1");
+
+
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("SOME_COMPONENT_0").changes.get(0).id, "CHANGE_0_0_1_0");
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("SOME_COMPONENT_0").changes.get(1).id, "CHANGE_0_0_1_1");
+
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("SOME_COMPONENT_1").changes.get(0).id, "CHANGE_1_0_1_0");
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("SOME_COMPONENT_1").changes.get(1).id, "CHANGE_1_0_1_1");
+
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("SOME_COMPONENT_2").changes.get(0).id, "CHANGE_2_0_1_0");
+ assertEquals(result.getServiceMap().get("HDFS").getComponentMap().get("SOME_COMPONENT_2").changes.get(1).id, "CHANGE_2_0_1_1");
+
+
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_0").getComponentMap().get("NAMENODE").changes.get(0).id, "CHANGE_0_1_0_0");
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_0").getComponentMap().get("NAMENODE").changes.get(1).id, "CHANGE_0_1_0_1");
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_0").getComponentMap().get("SOME_COMPONENT_0").changes.get(0).id, "CHANGE_0_1_1_0");
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_0").getComponentMap().get("SOME_COMPONENT_0").changes.get(1).id, "CHANGE_0_1_1_1");
+
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_1").getComponentMap().get("NAMENODE").changes.get(0).id, "CHANGE_1_1_0_0");
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_1").getComponentMap().get("NAMENODE").changes.get(1).id, "CHANGE_1_1_0_1");
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_1").getComponentMap().get("SOME_COMPONENT_1").changes.get(0).id, "CHANGE_1_1_1_0");
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_1").getComponentMap().get("SOME_COMPONENT_1").changes.get(1).id, "CHANGE_1_1_1_1");
+
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_2").getComponentMap().get("NAMENODE").changes.get(0).id, "CHANGE_2_1_0_0");
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_2").getComponentMap().get("NAMENODE").changes.get(1).id, "CHANGE_2_1_0_1");
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_2").getComponentMap().get("SOME_COMPONENT_2").changes.get(0).id, "CHANGE_2_1_1_0");
+ assertEquals(result.getServiceMap().get("SOME_SERVICE_2").getComponentMap().get("SOME_COMPONENT_2").changes.get(1).id, "CHANGE_2_1_1_1");
+
+ }
+
+}