/** * 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.controller.internal; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createNiceMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.powermock.api.easymock.PowerMock.createStrictMock; import static org.powermock.api.easymock.PowerMock.replay; import static org.powermock.api.easymock.PowerMock.reset; import java.lang.reflect.Field; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.apache.ambari.server.controller.spi.ResourceProvider; import org.apache.ambari.server.topology.Blueprint; import org.apache.ambari.server.topology.BlueprintFactory; import org.apache.ambari.server.topology.Configuration; import org.apache.ambari.server.topology.HostGroup; import org.apache.ambari.server.topology.HostGroupInfo; import org.apache.ambari.server.topology.InvalidTopologyTemplateException; import org.apache.ambari.server.topology.TopologyRequest; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * Unit tests for ScaleClusterRequest. */ @SuppressWarnings("unchecked") public class ScaleClusterRequestTest { private static final String CLUSTER_NAME = "cluster_name"; private static final String BLUEPRINT_NAME = "blueprint_name"; private static final String HOST1_NAME = "host1.test.com"; private static final String HOST2_NAME = "host2.test.com"; private static final String GROUP1_NAME = "group1"; private static final String GROUP2_NAME = "group2"; private static final String GROUP3_NAME = "group3"; private static final String PREDICATE = "test/prop=foo"; private static final BlueprintFactory blueprintFactory = createStrictMock(BlueprintFactory.class); private static final Blueprint blueprint = createNiceMock(Blueprint.class); private static final ResourceProvider hostResourceProvider = createMock(ResourceProvider.class); private static final HostGroup hostGroup1 = createNiceMock(HostGroup.class); private static final Configuration blueprintConfig = new Configuration( Collections.<String, Map<String, String>>emptyMap(), Collections.<String, Map<String, Map<String, String>>>emptyMap()); @Before public void setUp() throws Exception { ScaleClusterRequest.init(blueprintFactory); // set host resource provider field Class clazz = BaseClusterRequest.class; Field f = clazz.getDeclaredField("hostResourceProvider"); f.setAccessible(true); f.set(null, hostResourceProvider); expect(blueprintFactory.getBlueprint(BLUEPRINT_NAME)).andReturn(blueprint).anyTimes(); expect(blueprint.getConfiguration()).andReturn(blueprintConfig).anyTimes(); expect(blueprint.getHostGroup(GROUP1_NAME)).andReturn(hostGroup1).anyTimes(); expect(blueprint.getHostGroup(GROUP2_NAME)).andReturn(hostGroup1).anyTimes(); expect(blueprint.getHostGroup(GROUP3_NAME)).andReturn(hostGroup1).anyTimes(); expect(blueprint.getName()).andReturn(BLUEPRINT_NAME).anyTimes(); expect(hostResourceProvider.checkPropertyIds(Collections.singleton("test/prop"))). andReturn(Collections.<String>emptySet()).once(); replay(blueprintFactory, blueprint, hostResourceProvider, hostGroup1); } @After public void tearDown() { verify(blueprintFactory, blueprint, hostResourceProvider, hostGroup1); reset(blueprintFactory, blueprint, hostResourceProvider, hostGroup1); } @Test public void test_basic_hostName() throws Exception { // reset default host resource provider expectations to none since no host predicate is used reset(hostResourceProvider); replay(hostResourceProvider); ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(Collections.singleton( createScaleClusterPropertiesGroup1_HostName(CLUSTER_NAME, BLUEPRINT_NAME))); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); assertEquals(String.format("Scale Cluster '%s' (+%s hosts)", CLUSTER_NAME, "1"), scaleClusterRequest.getDescription()); assertEquals(CLUSTER_NAME, scaleClusterRequest.getClusterName()); assertSame(blueprint, scaleClusterRequest.getBlueprint()); Map<String, HostGroupInfo> hostGroupInfo = scaleClusterRequest.getHostGroupInfo(); assertEquals(1, hostGroupInfo.size()); // group1 // host info HostGroupInfo group1Info = hostGroupInfo.get(GROUP1_NAME); assertEquals(GROUP1_NAME, group1Info.getHostGroupName()); assertEquals(1, group1Info.getHostNames().size()); assertTrue(group1Info.getHostNames().contains(HOST1_NAME)); assertEquals(1, group1Info.getRequestedHostCount()); assertNull(group1Info.getPredicate()); } @Test public void testMultipleHostNames() throws Exception { // reset default host resource provider expectations to none since no host predicate is used reset(hostResourceProvider); replay(hostResourceProvider); Set<Map<String, Object>> propertySet = new HashSet<>(); propertySet.add(createScaleClusterPropertiesGroup1_HostName(CLUSTER_NAME, BLUEPRINT_NAME)); propertySet.add(createScaleClusterPropertiesGroup1_HostName2(CLUSTER_NAME, BLUEPRINT_NAME)); ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(propertySet); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); assertEquals(String.format("Scale Cluster '%s' (+%s hosts)", CLUSTER_NAME, "2"), scaleClusterRequest.getDescription()); assertEquals(CLUSTER_NAME, scaleClusterRequest.getClusterName()); assertSame(blueprint, scaleClusterRequest.getBlueprint()); Map<String, HostGroupInfo> hostGroupInfo = scaleClusterRequest.getHostGroupInfo(); assertEquals(1, hostGroupInfo.size()); // group1 // host info HostGroupInfo group1Info = hostGroupInfo.get(GROUP1_NAME); assertEquals(GROUP1_NAME, group1Info.getHostGroupName()); assertEquals(2, group1Info.getHostNames().size()); assertTrue(group1Info.getHostNames().contains(HOST1_NAME)); assertTrue(group1Info.getHostNames().contains(HOST2_NAME)); assertEquals(2, group1Info.getRequestedHostCount()); assertNull(group1Info.getPredicate()); } @Test public void test_basic_hostCount() throws Exception { // reset default host resource provider expectations to none since no host predicate is used reset(hostResourceProvider); replay(hostResourceProvider); ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(Collections.singleton( createScaleClusterPropertiesGroup1_HostCount(CLUSTER_NAME, BLUEPRINT_NAME))); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); assertEquals(String.format("Scale Cluster '%s' (+%s hosts)", CLUSTER_NAME, "1"), scaleClusterRequest.getDescription()); assertEquals(CLUSTER_NAME, scaleClusterRequest.getClusterName()); assertSame(blueprint, scaleClusterRequest.getBlueprint()); Map<String, HostGroupInfo> hostGroupInfo = scaleClusterRequest.getHostGroupInfo(); assertEquals(1, hostGroupInfo.size()); // group2 // host info HostGroupInfo group2Info = hostGroupInfo.get(GROUP2_NAME); assertEquals(GROUP2_NAME, group2Info.getHostGroupName()); assertEquals(0, group2Info.getHostNames().size()); assertEquals(1, group2Info.getRequestedHostCount()); assertNull(group2Info.getPredicate()); } @Test public void test_basic_hostCount2() throws Exception { // reset default host resource provider expectations to none since no host predicate is used reset(hostResourceProvider); replay(hostResourceProvider); ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(Collections.singleton( createScaleClusterPropertiesGroup1_HostCount2(CLUSTER_NAME, BLUEPRINT_NAME))); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); assertEquals(String.format("Scale Cluster '%s' (+%s hosts)", CLUSTER_NAME, "2"), scaleClusterRequest.getDescription()); assertEquals(CLUSTER_NAME, scaleClusterRequest.getClusterName()); assertSame(blueprint, scaleClusterRequest.getBlueprint()); Map<String, HostGroupInfo> hostGroupInfo = scaleClusterRequest.getHostGroupInfo(); assertEquals(1, hostGroupInfo.size()); // group2 // host info HostGroupInfo group2Info = hostGroupInfo.get(GROUP3_NAME); assertEquals(GROUP3_NAME, group2Info.getHostGroupName()); assertEquals(0, group2Info.getHostNames().size()); assertEquals(2, group2Info.getRequestedHostCount()); assertNull(group2Info.getPredicate()); } @Test public void test_basic_hostCountAndPredicate() throws Exception { ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(Collections.singleton( createScaleClusterPropertiesGroup1_HostCountAndPredicate(CLUSTER_NAME, BLUEPRINT_NAME))); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); assertEquals(String.format("Scale Cluster '%s' (+%s hosts)", CLUSTER_NAME, "1"), scaleClusterRequest.getDescription()); assertEquals(CLUSTER_NAME, scaleClusterRequest.getClusterName()); assertSame(blueprint, scaleClusterRequest.getBlueprint()); Map<String, HostGroupInfo> hostGroupInfo = scaleClusterRequest.getHostGroupInfo(); assertEquals(1, hostGroupInfo.size()); // group3 // host info HostGroupInfo group3Info = hostGroupInfo.get(GROUP3_NAME); assertEquals(GROUP3_NAME, group3Info.getHostGroupName()); assertEquals(0, group3Info.getHostNames().size()); assertEquals(1, group3Info.getRequestedHostCount()); assertEquals(PREDICATE, group3Info.getPredicateString()); } @Test public void testMultipleHostGroups() throws Exception { Set<Map<String, Object>> propertySet = new HashSet<>(); propertySet.add(createScaleClusterPropertiesGroup1_HostCountAndPredicate(CLUSTER_NAME, BLUEPRINT_NAME)); propertySet.add(createScaleClusterPropertiesGroup1_HostCount(CLUSTER_NAME, BLUEPRINT_NAME)); propertySet.add(createScaleClusterPropertiesGroup1_HostName(CLUSTER_NAME, BLUEPRINT_NAME)); ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(propertySet); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); assertEquals(String.format("Scale Cluster '%s' (+%s hosts)", CLUSTER_NAME, "3"), scaleClusterRequest.getDescription()); assertEquals(CLUSTER_NAME, scaleClusterRequest.getClusterName()); assertSame(blueprint, scaleClusterRequest.getBlueprint()); Map<String, HostGroupInfo> hostGroupInfo = scaleClusterRequest.getHostGroupInfo(); assertEquals(3, hostGroupInfo.size()); // group // host info HostGroupInfo group1Info = hostGroupInfo.get(GROUP1_NAME); assertEquals(GROUP1_NAME, group1Info.getHostGroupName()); assertEquals(1, group1Info.getHostNames().size()); assertTrue(group1Info.getHostNames().contains(HOST1_NAME)); assertEquals(1, group1Info.getRequestedHostCount()); assertNull(group1Info.getPredicate()); // group2 // host info HostGroupInfo group2Info = hostGroupInfo.get(GROUP2_NAME); assertEquals(GROUP2_NAME, group2Info.getHostGroupName()); assertEquals(0, group2Info.getHostNames().size()); assertEquals(1, group2Info.getRequestedHostCount()); assertNull(group2Info.getPredicate()); // group3 // host info HostGroupInfo group3Info = hostGroupInfo.get(GROUP3_NAME); assertEquals(GROUP3_NAME, group3Info.getHostGroupName()); assertEquals(0, group3Info.getHostNames().size()); assertEquals(1, group3Info.getRequestedHostCount()); assertEquals(PREDICATE, group3Info.getPredicateString()); } @Test(expected = InvalidTopologyTemplateException.class) public void test_GroupInfoMissingName() throws Exception { Map<String, Object> properties = createScaleClusterPropertiesGroup1_HostName(CLUSTER_NAME, BLUEPRINT_NAME); // remove host group name properties.remove("host_group"); // reset default host resource provider expectations to none reset(hostResourceProvider); replay(hostResourceProvider); // should result in an exception new ScaleClusterRequest(Collections.singleton(properties)); } @Test(expected = InvalidTopologyTemplateException.class) public void test_NoHostNameOrHostCount() throws Exception { Map<String, Object> properties = createScaleClusterPropertiesGroup1_HostName(CLUSTER_NAME, BLUEPRINT_NAME); // remove host name properties.remove("host_name"); // reset default host resource provider expectations to none reset(hostResourceProvider); replay(hostResourceProvider); // should result in an exception because neither host name or host count are specified new ScaleClusterRequest(Collections.singleton(properties)); } @Test(expected = InvalidTopologyTemplateException.class) public void testInvalidPredicateProperty() throws Exception { reset(hostResourceProvider); // checkPropertyIds() returns invalid property names expect(hostResourceProvider.checkPropertyIds(Collections.singleton("test/prop"))). andReturn(Collections.singleton("test/prop")); replay(hostResourceProvider); // should result in an exception due to invalid property in host predicate new ScaleClusterRequest(Collections.singleton( createScaleClusterPropertiesGroup1_HostCountAndPredicate(CLUSTER_NAME, BLUEPRINT_NAME))); } @Test(expected = InvalidTopologyTemplateException.class) public void testMultipleBlueprints() throws Exception { reset(hostResourceProvider); replay(hostResourceProvider); Set<Map<String, Object>> propertySet = new LinkedHashSet<>(); propertySet.add(createScaleClusterPropertiesGroup1_HostName(CLUSTER_NAME, BLUEPRINT_NAME)); propertySet.add(createScaleClusterPropertiesGroup1_HostName2(CLUSTER_NAME, "OTHER_BLUEPRINT")); // should result in an exception due to different blueprints being specified new ScaleClusterRequest(propertySet); } public static Map<String, Object> createScaleClusterPropertiesGroup1_HostName(String clusterName, String blueprintName) { Map<String, Object> properties = new LinkedHashMap<>(); properties.put(HostResourceProvider.HOST_CLUSTER_NAME_PROPERTY_ID, clusterName); properties.put(HostResourceProvider.BLUEPRINT_PROPERTY_ID, blueprintName); properties.put(HostResourceProvider.HOSTGROUP_PROPERTY_ID, GROUP1_NAME); properties.put(HostResourceProvider.HOST_NAME_NO_CATEGORY_PROPERTY_ID, HOST1_NAME); return properties; } public static Map<String, Object> createScaleClusterPropertiesGroup1_HostCount(String clusterName, String blueprintName) { Map<String, Object> properties = new LinkedHashMap<>(); properties.put(HostResourceProvider.HOST_CLUSTER_NAME_PROPERTY_ID, clusterName); properties.put(HostResourceProvider.BLUEPRINT_PROPERTY_ID, blueprintName); properties.put(HostResourceProvider.HOSTGROUP_PROPERTY_ID, GROUP2_NAME); properties.put(HostResourceProvider.HOST_COUNT_PROPERTY_ID, 1); return properties; } public static Map<String, Object> createScaleClusterPropertiesGroup1_HostCountAndPredicate(String clusterName, String blueprintName) { Map<String, Object> properties = new LinkedHashMap<>(); properties.put(HostResourceProvider.HOST_CLUSTER_NAME_PROPERTY_ID, clusterName); properties.put(HostResourceProvider.BLUEPRINT_PROPERTY_ID, blueprintName); properties.put(HostResourceProvider.HOSTGROUP_PROPERTY_ID, GROUP3_NAME); properties.put(HostResourceProvider.HOST_COUNT_PROPERTY_ID, 1); properties.put(HostResourceProvider.HOST_PREDICATE_PROPERTY_ID, PREDICATE); return properties; } public static Map<String, Object> createScaleClusterPropertiesGroup1_HostCount2(String clusterName, String blueprintName) { Map<String, Object> properties = new LinkedHashMap<>(); properties.put(HostResourceProvider.HOST_CLUSTER_NAME_PROPERTY_ID, clusterName); properties.put(HostResourceProvider.BLUEPRINT_PROPERTY_ID, blueprintName); properties.put(HostResourceProvider.HOSTGROUP_PROPERTY_ID, GROUP3_NAME); properties.put(HostResourceProvider.HOST_COUNT_PROPERTY_ID, 2); return properties; } public static Map<String, Object> createScaleClusterPropertiesGroup1_HostName2(String clusterName, String blueprintName) { Map<String, Object> properties = new LinkedHashMap<>(); properties.put(HostResourceProvider.HOST_CLUSTER_NAME_PROPERTY_ID, clusterName); properties.put(HostResourceProvider.BLUEPRINT_PROPERTY_ID, blueprintName); properties.put(HostResourceProvider.HOSTGROUP_PROPERTY_ID, GROUP1_NAME); properties.put(HostResourceProvider.HOST_NAME_NO_CATEGORY_PROPERTY_ID, HOST2_NAME); return properties; } }