/**
* 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.stack;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.createStrictMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.state.CommandScriptDefinition;
import org.apache.ambari.server.state.ComponentInfo;
import org.apache.ambari.server.state.CredentialStoreInfo;
import org.apache.ambari.server.state.CustomCommandDefinition;
import org.apache.ambari.server.state.PropertyInfo;
import org.apache.ambari.server.state.ServiceInfo;
import org.apache.ambari.server.state.ServiceOsSpecific;
import org.apache.ambari.server.state.ServicePropertyInfo;
import org.junit.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
/**
* ServiceModule unit tests.
*/
public class ServiceModuleTest {
@Test
public void testResolve_Comment() throws Exception {
String comment = "test comment";
// comment specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setComment(comment);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(comment, service.getModuleInfo().getComment());
// comment specified in parent only
info.setComment(null);
parentInfo.setComment(comment);
service = resolveService(info, parentInfo);
assertEquals(comment, service.getModuleInfo().getComment());
// set in both
info.setComment(comment);
parentInfo.setComment("other comment");
service = resolveService(info, parentInfo);
assertEquals(comment, service.getModuleInfo().getComment());
}
@Test
public void testResolve_DisplayName() throws Exception {
String displayName = "test_display_name";
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setDisplayName(displayName);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(displayName, service.getModuleInfo().getDisplayName());
// specified in parent only
info.setDisplayName(null);
parentInfo.setDisplayName(displayName);
service = resolveService(info, parentInfo);
assertEquals(displayName, service.getModuleInfo().getDisplayName());
// specified in both
info.setDisplayName(displayName);
parentInfo.setDisplayName("other display name");
service = resolveService(info, parentInfo);
assertEquals(displayName, service.getModuleInfo().getDisplayName());
}
@Test
public void testResolve_Version() throws Exception {
String version = "1.1";
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setVersion(version);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(version, service.getModuleInfo().getVersion());
// specified in parent only
info.setVersion(null);
parentInfo.setVersion(version);
service = resolveService(info, parentInfo);
assertEquals(version, service.getModuleInfo().getVersion());
// specified in both
info.setVersion(version);
parentInfo.setVersion("1.0");
service = resolveService(info, parentInfo);
assertEquals(version, service.getModuleInfo().getVersion());
}
@Test
public void testResolve_RequiredServices() throws Exception {
List<String> requiredServices = new ArrayList<>();
requiredServices.add("foo");
requiredServices.add("bar");
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setRequiredServices(requiredServices);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(requiredServices, service.getModuleInfo().getRequiredServices());
// specified in parent only
info.setRequiredServices(null);
parentInfo.setRequiredServices(requiredServices);
service = resolveService(info, parentInfo);
assertEquals(requiredServices, service.getModuleInfo().getRequiredServices());
// specified in both
info.setRequiredServices(requiredServices);
parentInfo.setRequiredServices(Collections.singletonList("other"));
service = resolveService(info, parentInfo);
assertEquals(requiredServices, service.getModuleInfo().getRequiredServices());
// not set in either
info.setRequiredServices(null);
parentInfo.setRequiredServices(null);
service = resolveService(info, parentInfo);
assertTrue(service.getModuleInfo().getRequiredServices().isEmpty());
}
@Test
public void testResolve_RestartRequiredAfterChange() throws Exception {
Boolean isRestartRequired = true;
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setRestartRequiredAfterChange(isRestartRequired);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(isRestartRequired, service.getModuleInfo().isRestartRequiredAfterChange());
// specified in parent only
info.setRestartRequiredAfterChange(null);
parentInfo.setRestartRequiredAfterChange(isRestartRequired);
service = resolveService(info, parentInfo);
assertEquals(isRestartRequired, service.getModuleInfo().isRestartRequiredAfterChange());
// specified in both
info.setRestartRequiredAfterChange(isRestartRequired);
parentInfo.setRestartRequiredAfterChange(false);
service = resolveService(info, parentInfo);
assertEquals(isRestartRequired, service.getModuleInfo().isRestartRequiredAfterChange());
}
@Test
public void testResolve_MonitoringService() throws Exception {
Boolean isMonitoringService = true;
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setMonitoringService(isMonitoringService);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(isMonitoringService, service.getModuleInfo().isMonitoringService());
// specified in parent only
info.setMonitoringService(null);
parentInfo.setMonitoringService(isMonitoringService);
service = resolveService(info, parentInfo);
assertEquals(isMonitoringService, service.getModuleInfo().isMonitoringService());
// specified in both
info.setMonitoringService(isMonitoringService);
parentInfo.setMonitoringService(false);
service = resolveService(info, parentInfo);
assertEquals(isMonitoringService, service.getModuleInfo().isMonitoringService());
}
@Test
public void testResolve_OsSpecifics() throws Exception {
Map<String, ServiceOsSpecific> osSpecifics = new HashMap<>();
osSpecifics.put("foo", new ServiceOsSpecific());
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setOsSpecifics(osSpecifics);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(osSpecifics, service.getModuleInfo().getOsSpecifics());
// specified in parent only
info.setOsSpecifics(null);
parentInfo.setOsSpecifics(osSpecifics);
service = resolveService(info, parentInfo);
assertEquals(osSpecifics, service.getModuleInfo().getOsSpecifics());
// specified in both
Map<String, ServiceOsSpecific> osSpecifics2 = new HashMap<>();
osSpecifics.put("bar", new ServiceOsSpecific());
info.setOsSpecifics(osSpecifics);
parentInfo.setOsSpecifics(osSpecifics2);
service = resolveService(info, parentInfo);
assertEquals(osSpecifics, service.getModuleInfo().getOsSpecifics());
}
@Test
public void testResolve_CommandScript() throws Exception {
CommandScriptDefinition commandScript = new CommandScriptDefinition();
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setCommandScript(commandScript);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(commandScript, service.getModuleInfo().getCommandScript());
// specified in parent only
info.setCommandScript(null);
parentInfo.setCommandScript(commandScript);
service = resolveService(info, parentInfo);
assertEquals(commandScript, service.getModuleInfo().getCommandScript());
// specified in both
CommandScriptDefinition commandScript2 = new CommandScriptDefinition();
info.setCommandScript(commandScript);
parentInfo.setCommandScript(commandScript2);
service = resolveService(info, parentInfo);
assertEquals(commandScript, service.getModuleInfo().getCommandScript());
}
@Test
public void testResolve_ServicePackageFolder() throws Exception {
String servicePackageFolder = "packageDir";
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
ServiceModule child = createServiceModule(info);
ServiceModule parent = createServiceModule(parentInfo);
// set in the module constructor from a value obtained from service directory
assertEquals("packageDir", child.getModuleInfo().getServicePackageFolder());
parent.getModuleInfo().setServicePackageFolder(null);
resolveService(child, parent);
assertEquals(servicePackageFolder, child.getModuleInfo().getServicePackageFolder());
// specified in parent only
child = createServiceModule(info);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setServicePackageFolder(servicePackageFolder);
child.getModuleInfo().setServicePackageFolder(null);
resolveService(child, parent);
assertEquals(servicePackageFolder, child.getModuleInfo().getServicePackageFolder());
// specified in both
child = createServiceModule(info);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setServicePackageFolder("someOtherDir");
child.getModuleInfo().setServicePackageFolder(servicePackageFolder);
resolveService(child, parent);
assertEquals(servicePackageFolder, child.getModuleInfo().getServicePackageFolder());
}
@Test
public void testResolve_MetricsFile() throws Exception {
File metricsFile = new File("testMetricsFile");
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
ServiceModule child = createServiceModule(info);
ServiceModule parent = createServiceModule(parentInfo);
// set in the module constructor from a value obtained from service directory which is mocked
assertEquals(metricsFile, child.getModuleInfo().getMetricsFile());
parent.getModuleInfo().setMetricsFile(null);
resolveService(child, parent);
assertEquals(metricsFile, child.getModuleInfo().getMetricsFile());
// specified in parent only
child = createServiceModule(info);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setMetricsFile(metricsFile);
child.getModuleInfo().setMetricsFile(null);
resolveService(child, parent);
assertEquals(metricsFile, child.getModuleInfo().getMetricsFile());
// specified in both
child = createServiceModule(info);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setMetricsFile(new File("someOtherDir"));
child.getModuleInfo().setMetricsFile(metricsFile);
resolveService(child, parent);
assertEquals(metricsFile, child.getModuleInfo().getMetricsFile());
}
@Test
public void testResolve_AlertsFile() throws Exception {
File alertsFile = new File("testAlertsFile");
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
ServiceModule child = createServiceModule(info);
ServiceModule parent = createServiceModule(parentInfo);
// set in the module constructor from a value obtained from service directory which is mocked
assertEquals(alertsFile, child.getModuleInfo().getAlertsFile());
parent.getModuleInfo().setAlertsFile(null);
resolveService(child, parent);
assertEquals(alertsFile, child.getModuleInfo().getAlertsFile());
// specified in parent only
child = createServiceModule(info);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setAlertsFile(alertsFile);
child.getModuleInfo().setAlertsFile(null);
resolveService(child, parent);
assertEquals(alertsFile, child.getModuleInfo().getAlertsFile());
// specified in both
child = createServiceModule(info);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setAlertsFile(new File("someOtherDir"));
child.getModuleInfo().setAlertsFile(alertsFile);
resolveService(child, parent);
assertEquals(alertsFile, child.getModuleInfo().getAlertsFile());
}
@Test
public void testResolve_KerberosDescriptorFile() throws Exception {
File kerberosDescriptorFile = new File("testKerberosDescriptorFile");
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
ServiceModule child = createServiceModule(info);
ServiceModule parent = createServiceModule(parentInfo);
// set in the module constructor from a value obtained from service directory which is mocked
assertEquals(kerberosDescriptorFile, child.getModuleInfo().getKerberosDescriptorFile());
parent.getModuleInfo().setKerberosDescriptorFile(null);
resolveService(child, parent);
assertEquals(kerberosDescriptorFile, child.getModuleInfo().getKerberosDescriptorFile());
// specified in parent only
child = createServiceModule(info);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setKerberosDescriptorFile(kerberosDescriptorFile);
child.getModuleInfo().setKerberosDescriptorFile(null);
resolveService(child, parent);
assertEquals(kerberosDescriptorFile, child.getModuleInfo().getKerberosDescriptorFile());
// specified in both
child = createServiceModule(info);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setKerberosDescriptorFile(new File("someOtherDir"));
child.getModuleInfo().setKerberosDescriptorFile(kerberosDescriptorFile);
resolveService(child, parent);
assertEquals(kerberosDescriptorFile, child.getModuleInfo().getKerberosDescriptorFile());
}
@Test
public void testResolve_UpgradeCheckDirectory() throws Exception {
File checks = new File("checks");
// check directory specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
ServiceModule child = createServiceModule(info);
ServiceModule parent = createServiceModule(parentInfo);
child.getModuleInfo().setChecksFolder(checks);
resolveService(child, parent);
assertEquals(checks.getPath(), child.getModuleInfo().getChecksFolder().getPath());
// check directory specified in parent only
child = createServiceModule(info);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setChecksFolder(checks);
resolveService(child, parent);
assertEquals(checks.getPath(), child.getModuleInfo().getChecksFolder().getPath());
// check directory set in both
info.setChecksFolder(checks);
child = createServiceModule(info);
child.getModuleInfo().setChecksFolder(checks);
parent = createServiceModule(parentInfo);
parent.getModuleInfo().setChecksFolder(new File("other"));
resolveService(child, parent);
assertEquals(checks.getPath(), child.getModuleInfo().getChecksFolder().getPath());
}
@Test
public void testResolve_CustomCommands() throws Exception {
List<CustomCommandDefinition> customCommands = new ArrayList<>();
CustomCommandDefinition cmd1 = new CustomCommandDefinition();
setPrivateField(cmd1, "name", "cmd1");
setPrivateField(cmd1, "background", false);
CustomCommandDefinition cmd2 = new CustomCommandDefinition();
setPrivateField(cmd2, "name", "cmd2");
customCommands.add(cmd1);
customCommands.add(cmd2);
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setCustomCommands(customCommands);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(customCommands, service.getModuleInfo().getCustomCommands());
// specified in parent only
info.setCustomCommands(null);
parentInfo.setCustomCommands(customCommands);
service = resolveService(info, parentInfo);
assertEquals(customCommands, service.getModuleInfo().getCustomCommands());
// specified in both
List<CustomCommandDefinition> parentCustomCommands = new ArrayList<>();
CustomCommandDefinition cmd3 = new CustomCommandDefinition();
setPrivateField(cmd3, "name", "cmd1");
setPrivateField(cmd3, "background", true);
CustomCommandDefinition cmd4 = new CustomCommandDefinition();
setPrivateField(cmd4, "name", "cmd4");
parentCustomCommands.add(cmd3);
parentCustomCommands.add(cmd4);
info.setCustomCommands(customCommands);
parentInfo.setCustomCommands(parentCustomCommands);
service = resolveService(info, parentInfo);
Collection<CustomCommandDefinition> mergedCommands = service.getModuleInfo().getCustomCommands();
assertEquals(3, mergedCommands.size());
assertTrue(mergedCommands.contains(cmd2));
assertTrue(mergedCommands.contains(cmd3));
assertTrue(mergedCommands.contains(cmd4));
// not set in either
info.setCustomCommands(null);
parentInfo.setCustomCommands(null);
service = resolveService(info, parentInfo);
assertTrue(service.getModuleInfo().getCustomCommands().isEmpty());
}
@Test
public void testResolve_ConfigDependencies() throws Exception {
List<String> configDependencies = new ArrayList<>();
configDependencies.add("foo");
configDependencies.add("bar");
// specified in child only
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
info.setConfigDependencies(configDependencies);
ServiceModule service = resolveService(info, parentInfo);
assertEquals(configDependencies, service.getModuleInfo().getConfigDependencies());
// specified in parent only
info.setConfigDependencies(null);
parentInfo.setConfigDependencies(configDependencies);
service = resolveService(info, parentInfo);
assertEquals(configDependencies, service.getModuleInfo().getConfigDependencies());
// specified in both
List<String> parentCustomCommands = new ArrayList<>();
parentCustomCommands.add("bar");
parentCustomCommands.add("other");
info.setConfigDependencies(configDependencies);
parentInfo.setConfigDependencies(parentCustomCommands);
service = resolveService(info, parentInfo);
Collection<String> mergedConfigDependencies = service.getModuleInfo().getConfigDependencies();
assertEquals(3, mergedConfigDependencies.size());
assertTrue(mergedConfigDependencies.contains("foo"));
assertTrue(mergedConfigDependencies.contains("bar"));
assertTrue(mergedConfigDependencies.contains("other"));
// not set in either
info.setConfigDependencies(null);
parentInfo.setConfigDependencies(null);
service = resolveService(info, parentInfo);
assertTrue(service.getModuleInfo().getConfigDependencies().isEmpty());
}
@Test
public void testResolve_Components() throws Exception {
// resolve should merge the child component collections
// components 1, 2 and XX are set on the parent
// components 1, 4 and XX are set on the child
// component XX is marked for delete on the child and shouldn't be included
// component 1 should be merged
// both non-intersecting components 2 and 4 should be included
ComponentInfo info1 = new ComponentInfo();
info1.setName("1");
ComponentInfo info2 = new ComponentInfo();
info2.setName("2");
ComponentInfo XX = new ComponentInfo();
XX.setName("XX");
ComponentInfo info3 = new ComponentInfo();
// overlaps with info1
info3.setName("1");
info3.setCardinality("ALL");
info3.setCategory("category");
ComponentInfo info4 = new ComponentInfo();
info4.setName("4");
ComponentInfo info5 = new ComponentInfo();
// overlaps with componentToBeDeleted
info5.setName("XX");
info5.setDeleted(true);
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
//todo: getComponents() should return a protective copy, but for now there is no set/add method
List<ComponentInfo> childComponents = info.getComponents();
childComponents.add(info3);
childComponents.add(info4);
childComponents.add(info5);
List<ComponentInfo> parentComponents = parentInfo.getComponents();
parentComponents.add(info1);
parentComponents.add(info2);
ServiceModule child = createServiceModule(info);
ServiceModule parent = createServiceModule(parentInfo);
resolveService(child, parent);
List<ComponentInfo> components = child.getModuleInfo().getComponents();
assertEquals(3, components.size());
Map<String, ComponentInfo> mergedComponents = new HashMap<>();
for (ComponentInfo component : components) {
mergedComponents.put(component.getName(), component);
}
assertTrue(mergedComponents.containsKey("1"));
assertTrue(mergedComponents.containsKey("2"));
assertTrue(mergedComponents.containsKey("4"));
// ensure that overlapping components were merged.
//don't test all properties, this is done in ComponentModuleTest
assertEquals("ALL", mergedComponents.get("1").getCardinality());
assertEquals("category", mergedComponents.get("1").getCategory());
}
@Test
public void testResolve_Configuration__properties() throws Exception {
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
// child configurations
//FOO
Collection<PropertyInfo> childFooProperties = new ArrayList<>();
PropertyInfo childProp1 = new PropertyInfo();
childProp1.setName("childName1");
childProp1.setValue("childVal1");
childFooProperties.add(childProp1);
//BAR : Doesn't inherit parents BAR due to attribute Supports.DO_NOT_EXTEND
Collection<PropertyInfo> childBarProperties = new ArrayList<>();
PropertyInfo childProp2 = new PropertyInfo();
childProp2.setName("childName2");
childProp2.setValue("childVal2");
childBarProperties.add(childProp2);
// add attributes for BAR
Map<String, String> attributes = new HashMap<>();
attributes.put(ConfigurationInfo.Supports.DO_NOT_EXTEND.getXmlAttributeName(), "true");
// create child config modules
ConfigurationModule childConfigModule1 = createConfigurationModule("FOO", childFooProperties);
ConfigurationModule childConfigModule2 = createConfigurationModule("BAR", childBarProperties, attributes);
Collection<ConfigurationModule> childModules = new ArrayList<>();
childModules.add(childConfigModule1);
childModules.add(childConfigModule2);
// parent configurations
//FOO
Collection<PropertyInfo> parentFooProperties = new ArrayList<>();
PropertyInfo parentProp1 = new PropertyInfo();
parentProp1.setName("parentName1");
parentProp1.setValue("parentVal1");
parentFooProperties.add(parentProp1);
PropertyInfo parentProp12 = new PropertyInfo();
// overwritten by child
parentProp12.setName("childName1");
parentProp12.setValue("parentVal1");
parentFooProperties.add(parentProp12);
//BAR
Collection<PropertyInfo> parentBarProperties = new ArrayList<>();
PropertyInfo parentProp2 = new PropertyInfo();
parentProp2.setName("parentName2");
parentProp2.setValue("parentVal2");
parentBarProperties.add(parentProp2);
//OTHER
Collection<PropertyInfo> parentOtherProperties = new ArrayList<>();
PropertyInfo parentProp3 = new PropertyInfo();
parentProp3.setName("parentName3");
parentProp3.setValue("parentVal3");
parentOtherProperties.add(parentProp3);
// create parent config modules
ConfigurationModule parentConfigModule1 = createConfigurationModule("FOO", parentFooProperties);
ConfigurationModule parentConfigModule2 = createConfigurationModule("BAR", parentBarProperties);
ConfigurationModule parentConfigModule3 = createConfigurationModule("OTHER", parentOtherProperties);
Collection<ConfigurationModule> parentModules = new ArrayList<>();
parentModules.add(parentConfigModule1);
parentModules.add(parentConfigModule2);
parentModules.add(parentConfigModule3);
// create service modules
ServiceModule child = createServiceModule(info, childModules);
ServiceModule parent = createServiceModule(parentInfo, parentModules);
// resolve child with parent
resolveService(child, parent);
// assertions
List<PropertyInfo> mergedProperties = child.getModuleInfo().getProperties();
assertEquals(4, mergedProperties.size());
Map<String, PropertyInfo> mergedPropertyMap = new HashMap<>();
for (PropertyInfo prop : mergedProperties) {
mergedPropertyMap.put(prop.getName(), prop);
}
// filename is null for all props because that is set in ConfigurationDirectory which is mocked
assertEquals("childVal1", mergedPropertyMap.get("childName1").getValue());
assertEquals("childVal2", mergedPropertyMap.get("childName2").getValue());
assertEquals("parentVal1", mergedPropertyMap.get("parentName1").getValue());
assertEquals("parentVal3", mergedPropertyMap.get("parentName3").getValue());
Map<String, Map<String, Map<String, String>>> childAttributes = child.getModuleInfo().getConfigTypeAttributes();
Map<String, Map<String, Map<String, String>>> parentAttributes = parent.getModuleInfo().getConfigTypeAttributes();
assertEquals(3, childAttributes.size());
assertAttributes(childAttributes.get("FOO"), Collections.<String, String>emptyMap());
assertAttributes(childAttributes.get("BAR"), attributes);
assertAttributes(childAttributes.get("OTHER"), Collections.<String, String>emptyMap());
assertEquals(3, parentAttributes.size());
assertAttributes(parentAttributes.get("FOO"), Collections.<String, String>emptyMap());
assertAttributes(parentAttributes.get("BAR"), Collections.<String, String>emptyMap());
assertAttributes(parentAttributes.get("OTHER"), Collections.<String, String>emptyMap());
}
@Test
public void testResolve_Service__selection() throws Exception {
ServiceInfo firstInfo = new ServiceInfo();
ServiceInfo secondInfo = new ServiceInfo();
ServiceInfo thirdInfo = new ServiceInfo();
firstInfo.setSelection(ServiceInfo.Selection.MANDATORY);
resolveService(secondInfo, firstInfo);
assertEquals(secondInfo.getSelection(), ServiceInfo.Selection.MANDATORY);
thirdInfo.setSelection(ServiceInfo.Selection.TECH_PREVIEW);
resolveService(thirdInfo, secondInfo);
assertEquals(thirdInfo.getSelection(), ServiceInfo.Selection.TECH_PREVIEW);
}
@Test
public void testResolve_Configuration__attributes() throws Exception {
ServiceInfo info = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
// child configurations
//FOO
Collection<PropertyInfo> childFooProperties = new ArrayList<>();
PropertyInfo childProp1 = new PropertyInfo();
childProp1.setName("childName1");
childProp1.setValue("childVal1");
childFooProperties.add(childProp1);
// add attributes for parent FOO
Map<String, String> childFooAttributes = new HashMap<>();
// override parents value
childFooAttributes.put(ConfigurationInfo.Supports.ADDING_FORBIDDEN.getXmlAttributeName(), "false");
// create child config modules
ConfigurationModule childConfigModule1 = createConfigurationModule("FOO", childFooProperties, childFooAttributes);
Collection<ConfigurationModule> childModules = new ArrayList<>();
childModules.add(childConfigModule1);
// parent configurations
//FOO
Collection<PropertyInfo> parentFooProperties = new ArrayList<>();
PropertyInfo parentProp1 = new PropertyInfo();
parentProp1.setName("parentName1");
parentProp1.setValue("parentVal1");
parentFooProperties.add(parentProp1);
// add attributes for parent FOO
Map<String, String> parentFooAttributes = new HashMap<>();
// child will inherit
parentFooAttributes.put(ConfigurationInfo.Supports.FINAL.getXmlAttributeName(), "true");
// child will override
parentFooAttributes.put(ConfigurationInfo.Supports.ADDING_FORBIDDEN.getXmlAttributeName(), "true");
//BAR
Collection<PropertyInfo> parentBarProperties = new ArrayList<>();
PropertyInfo parentProp2 = new PropertyInfo();
parentProp2.setName("parentName2");
parentProp2.setValue("parentVal2");
parentBarProperties.add(parentProp2);
// create parent config modules
ConfigurationModule parentConfigModule1 = createConfigurationModule("FOO", parentFooProperties, parentFooAttributes);
ConfigurationModule parentConfigModule2 = createConfigurationModule("BAR", parentBarProperties);
Collection<ConfigurationModule> parentModules = new ArrayList<>();
parentModules.add(parentConfigModule1);
parentModules.add(parentConfigModule2);
// create service modules
ServiceModule child = createServiceModule(info, childModules);
ServiceModule parent = createServiceModule(parentInfo, parentModules);
// resolve child with parent
resolveService(child, parent);
// assertions
Map<String, Map<String, Map<String, String>>> childTypeAttributes = child.getModuleInfo().getConfigTypeAttributes();
Map<String, Map<String, Map<String, String>>> parentTypeAttributes = parent.getModuleInfo().getConfigTypeAttributes();
assertTrue(childTypeAttributes.containsKey("FOO"));
Map<String, Map<String, String>> mergedChildFooAttributes = childTypeAttributes.get("FOO");
assertTrue(mergedChildFooAttributes.containsKey(ConfigurationInfo.Supports.KEYWORD));
// inherited value
assertEquals("true", mergedChildFooAttributes.get(ConfigurationInfo.Supports.KEYWORD).
get(ConfigurationInfo.Supports.valueOf("FINAL").getPropertyName()));
// overridden value
assertEquals("false", mergedChildFooAttributes.get(ConfigurationInfo.Supports.KEYWORD).
get(ConfigurationInfo.Supports.valueOf("ADDING_FORBIDDEN").getPropertyName()));
assertEquals(2, childTypeAttributes.size());
assertEquals(2, parentTypeAttributes.size());
assertAttributes(parentTypeAttributes.get("FOO"), parentFooAttributes);
assertAttributes(parentTypeAttributes.get("BAR"), Collections.<String, String>emptyMap());
}
@Test
public void testResolve_Configuration__ExcludedTypes() throws Exception {
ServiceInfo info = new ServiceInfo();
info.setExcludedConfigTypes(Collections.singleton("BAR"));
//FOO
Collection<PropertyInfo> fooProperties = new ArrayList<>();
PropertyInfo prop1 = new PropertyInfo();
prop1.setName("name1");
prop1.setValue("val1");
fooProperties.add(prop1);
PropertyInfo prop2 = new PropertyInfo();
prop2.setName("name2");
prop2.setValue("val2");
fooProperties.add(prop2);
//BAR
Collection<PropertyInfo> barProperties = new ArrayList<>();
PropertyInfo prop3 = new PropertyInfo();
prop3.setName("name1");
prop3.setValue("val3");
barProperties.add(prop3);
//OTHER
Collection<PropertyInfo> otherProperties = new ArrayList<>();
PropertyInfo prop4 = new PropertyInfo();
prop4.setName("name1");
prop4.setValue("val4");
otherProperties.add(prop4);
ConfigurationModule configModule1 = createConfigurationModule("FOO", fooProperties);
ConfigurationModule configModule2 = createConfigurationModule("BAR", barProperties);
ConfigurationModule configModule3 = createConfigurationModule("OTHER", otherProperties);
Collection<ConfigurationModule> configModules = new ArrayList<>();
configModules.add(configModule1);
configModules.add(configModule2);
configModules.add(configModule3);
ServiceModule service = createServiceModule(info, configModules);
List<PropertyInfo> properties = service.getModuleInfo().getProperties();
assertEquals(4, properties.size());
Map<String, Map<String, Map<String, String>>> attributes = service.getModuleInfo().getConfigTypeAttributes();
assertEquals(2, attributes.size());
assertTrue(attributes.containsKey("FOO"));
assertTrue(attributes.containsKey("OTHER"));
}
@Test
public void testResolve_Configuration__ExcludedTypes__ParentType() throws Exception {
// child
ServiceInfo info = new ServiceInfo();
info.setExcludedConfigTypes(Collections.singleton("BAR"));
//FOO
Collection<PropertyInfo> fooProperties = new ArrayList<>();
PropertyInfo prop1 = new PropertyInfo();
prop1.setName("name1");
prop1.setValue("val1");
fooProperties.add(prop1);
PropertyInfo prop2 = new PropertyInfo();
prop2.setName("name2");
prop2.setValue("val2");
fooProperties.add(prop2);
ConfigurationModule childConfigModule = createConfigurationModule("FOO", fooProperties);
Collection<ConfigurationModule> childConfigModules = new ArrayList<>();
childConfigModules.add(childConfigModule);
// parent
ServiceInfo parentInfo = new ServiceInfo();
//BAR
Collection<PropertyInfo> barProperties = new ArrayList<>();
PropertyInfo prop3 = new PropertyInfo();
prop3.setName("name1");
prop3.setValue("val3");
barProperties.add(prop3);
ConfigurationModule parentConfigModule = createConfigurationModule("BAR", barProperties);
Collection<ConfigurationModule> parentConfigModules = new ArrayList<>();
parentConfigModules.add(parentConfigModule);
// create service modules
ServiceModule service = createServiceModule(info, childConfigModules);
ServiceModule parentService = createServiceModule(parentInfo, parentConfigModules);
// resolve child with parent
resolveService(service, parentService);
// assertions
List<PropertyInfo> properties = service.getModuleInfo().getProperties();
assertEquals(2, properties.size());
Map<String, Map<String, Map<String, String>>> attributes = service.getModuleInfo().getConfigTypeAttributes();
assertEquals(1, attributes.size());
assertTrue(attributes.containsKey("FOO"));
Map<String, Map<String, Map<String, String>>> parentAttributes = parentService.getModuleInfo().getConfigTypeAttributes();
assertEquals(1, parentAttributes.size());
assertTrue(parentAttributes.containsKey("BAR"));
}
@Test
public void testMerge_Configuration__ExcludedTypes() throws Exception {
// child
ServiceInfo info = new ServiceInfo();
Set<String> childExcludedConfigTypes = new HashSet<>();
childExcludedConfigTypes.add("FOO");
info.setExcludedConfigTypes(childExcludedConfigTypes);
//FOO
Collection<PropertyInfo> fooProperties = new ArrayList<>();
ConfigurationModule childConfigModule = createConfigurationModule("FOO", fooProperties);
Collection<ConfigurationModule> childConfigModules = new ArrayList<>();
childConfigModules.add(childConfigModule);
// parent
ServiceInfo parentInfo = new ServiceInfo();
Set<String> parentExcludedConfigTypes = new HashSet<>();
childExcludedConfigTypes.add("BAR");
info.setExcludedConfigTypes(childExcludedConfigTypes);
parentInfo.setExcludedConfigTypes(parentExcludedConfigTypes);
//BAR
Collection<PropertyInfo> barProperties = new ArrayList<>();
ConfigurationModule parentConfigModule = createConfigurationModule("BAR", barProperties);
Collection<ConfigurationModule> parentConfigModules = new ArrayList<>();
parentConfigModules.add(parentConfigModule);
// create service modules
ServiceModule service = createServiceModule(info, childConfigModules);
ServiceModule parentService = createServiceModule(parentInfo, parentConfigModules);
// resolve child with parent
resolveService(service, parentService);
//resolveService(service, parentService);
assertEquals(2, service.getModuleInfo().getExcludedConfigTypes().size());
}
/**
* Verify stack resolution for credential-store
*
* @throws Exception
*/
@Test
public void testResolve_CredentialStoreInfo() throws Exception {
CredentialStoreInfo credentialStoreInfoChild = new CredentialStoreInfo(true /* supported */, false /* enabled */, true /*required*/);
CredentialStoreInfo credentialStoreInfoParent = new CredentialStoreInfo(true /* supported */, true /* enabled */, false /*required*/);
ServiceInfo childInfo = new ServiceInfo();
ServiceInfo parentInfo = new ServiceInfo();
ServiceModule service;
// specified in child only, child wins
childInfo.setCredentialStoreInfo(credentialStoreInfoChild);
parentInfo.setCredentialStoreInfo(null);
service = resolveService(childInfo, parentInfo);
assertEquals(credentialStoreInfoChild.isSupported(), service.getModuleInfo().isCredentialStoreSupported());
assertEquals(credentialStoreInfoChild.isEnabled(), service.getModuleInfo().isCredentialStoreEnabled());
assertEquals(credentialStoreInfoChild.isRequired(), service.getModuleInfo().isCredentialStoreRequired());
// specified in parent only, parent wins
childInfo.setCredentialStoreInfo(null);
parentInfo.setCredentialStoreInfo(credentialStoreInfoParent);
service = resolveService(childInfo, parentInfo);
assertEquals(credentialStoreInfoParent.isSupported(), service.getModuleInfo().isCredentialStoreSupported());
assertEquals(credentialStoreInfoParent.isEnabled(), service.getModuleInfo().isCredentialStoreEnabled());
assertEquals(credentialStoreInfoParent.isRequired(), service.getModuleInfo().isCredentialStoreRequired());
// specified in both, child wins
childInfo.setCredentialStoreInfo(credentialStoreInfoChild);
parentInfo.setCredentialStoreInfo(credentialStoreInfoParent);
service = resolveService(childInfo, parentInfo);
assertEquals(credentialStoreInfoChild.isSupported(), service.getModuleInfo().isCredentialStoreSupported());
assertEquals(credentialStoreInfoChild.isEnabled(), service.getModuleInfo().isCredentialStoreEnabled());
assertEquals(credentialStoreInfoChild.isRequired(), service.getModuleInfo().isCredentialStoreRequired());
}
@Test
public void testServiceCheckRegistered() throws Exception {
ServiceInfo info = new ServiceInfo();
info.setName("service1");
info.setCommandScript(createNiceMock(CommandScriptDefinition.class));
StackContext context = createStackContext(info.getName(), true);
ServiceModule service = createServiceModule(info, Collections.<ConfigurationModule>emptySet(), context);
service.finalizeModule();
verify(context);
}
@Test
public void testServiceCheckNotRegisteredForDeletedService() throws Exception {
ServiceInfo info = new ServiceInfo();
info.setName("service1");
info.setCommandScript(createNiceMock(CommandScriptDefinition.class));
info.setDeleted(true);
StackContext context = createStackContext(info.getName(), false);
ServiceModule service = createServiceModule(info, Collections.<ConfigurationModule>emptySet(), context);
service.finalizeModule();
verify(context);
}
@Test
public void testInvalidServiceInfo() {
// Given
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setName("TEST_SERVICE");
serviceInfo.setVersion("1.0.0");
serviceInfo.setValid(false);
serviceInfo.addError("Test error message");
// When
ServiceModule serviceModule = createServiceModule(serviceInfo);
// Then
assertFalse("Service module should be invalid due to the service info being invalid !", serviceModule.isValid());
assertTrue("Service module error collection should contain error message that caused service info being invalid !", serviceModule.getErrors().contains("Test error message"));
}
@Test
public void testMergeServicePropertiesInheritFromParent() throws Exception {
// Given
ServiceInfo serviceInfo = new ServiceInfo();
ServiceInfo parentServiceInfo = new ServiceInfo();
ServicePropertyInfo p1 = new ServicePropertyInfo();
p1.setName("P1");
p1.setValue("V1");
ServicePropertyInfo p2 = new ServicePropertyInfo();
p2.setName("P2");
p2.setValue("V2");
List<ServicePropertyInfo> parentServicePropertyList = Lists.newArrayList(p1, p2);
parentServiceInfo.setServicePropertyList(parentServicePropertyList);
// When
ServiceModule serviceModule = resolveService(serviceInfo, parentServiceInfo);
// Then
Map<String, String> parentServiceProperties = ImmutableMap.<String, String>builder()
.put("P1", "V1")
.put("P2", "V2")
.put(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY)
.put(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY)
.put(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY)
.build();
assertEquals(parentServicePropertyList, serviceModule.getModuleInfo().getServicePropertyList());
assertEquals(parentServiceProperties, serviceModule.getModuleInfo().getServiceProperties());
}
@Test
public void testMergeServicePropertiesInheritFromEmptyParent() throws Exception {
// Parent has no properties defined thus no service properties inherited
// Given
ServiceInfo serviceInfo = new ServiceInfo();
ServiceInfo parentServiceInfo = new ServiceInfo();
ServicePropertyInfo p1 = new ServicePropertyInfo();
p1.setName("P1");
p1.setValue("V1");
ServicePropertyInfo p2 = new ServicePropertyInfo();
p2.setName("P2");
p2.setValue("V2");
List<ServicePropertyInfo> servicePropertyList = Lists.newArrayList(p1, p2);
serviceInfo.setServicePropertyList(servicePropertyList);
// When
ServiceModule serviceModule = resolveService(serviceInfo, parentServiceInfo);
// Then
Map<String, String> serviceProperties = ImmutableMap.<String, String>builder()
.put("P1", "V1")
.put("P2", "V2")
.put(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY)
.put(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY)
.put(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY)
.build();
assertEquals(servicePropertyList, serviceModule.getModuleInfo().getServicePropertyList());
assertEquals(serviceProperties, serviceModule.getModuleInfo().getServiceProperties());
}
@Test
public void testMergeServiceProperties() throws Exception {
// Given
ServiceInfo serviceInfo = new ServiceInfo();
ServiceInfo parentServiceInfo = new ServiceInfo();
ServicePropertyInfo p1 = new ServicePropertyInfo();
p1.setName("P1");
p1.setValue("V1");
ServicePropertyInfo p2 = new ServicePropertyInfo();
p2.setName("P2");
p2.setValue("V2");
ServicePropertyInfo p2Override = new ServicePropertyInfo();
p2Override.setName("P2");
p2Override.setValue("V2_OVERRIDE");
ServicePropertyInfo p3 = new ServicePropertyInfo();
p3.setName("P3");
p3.setValue("V3");
List<ServicePropertyInfo> parentServicePropertyList = Lists.newArrayList(p1, p2);
parentServiceInfo.setServicePropertyList(parentServicePropertyList);
List<ServicePropertyInfo> servicePropertyList = Lists.newArrayList(p2Override, p3);
serviceInfo.setServicePropertyList(servicePropertyList);
// When
ServiceModule serviceModule = resolveService(serviceInfo, parentServiceInfo);
// Then
List<ServicePropertyInfo> expectedPropertyList = Lists.newArrayList(p1, p2Override, p3);
Map<String, String> expectedServiceProperties = ImmutableMap.<String, String>builder()
.put("P1", "V1")
.put("P2", "V2_OVERRIDE")
.put("P3", "V3")
.put(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY)
.put(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY)
.put(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY)
.build();
List<ServicePropertyInfo> actualPropertyList = serviceModule.getModuleInfo().getServicePropertyList();
assertTrue(actualPropertyList.containsAll(expectedPropertyList) && expectedPropertyList.containsAll(actualPropertyList));
assertEquals(expectedServiceProperties, serviceModule.getModuleInfo().getServiceProperties());
}
private ServiceModule createServiceModule(ServiceInfo serviceInfo) {
String configType = "type1";
if (serviceInfo.getName() == null) {
serviceInfo.setName("service1");
}
StackContext context = createStackContext(serviceInfo.getName(), true);
// no config props
ConfigurationInfo configInfo = createConfigurationInfo(Collections.<PropertyInfo>emptyList(),
Collections.<String, String>emptyMap());
ConfigurationModule module = createConfigurationModule(configType, configInfo);
ConfigurationDirectory configDirectory = createConfigurationDirectory(Collections.singletonList(module));
ServiceDirectory serviceDirectory = createServiceDirectory(serviceInfo.getConfigDir(), configDirectory);
return createServiceModule(context, serviceInfo, serviceDirectory);
}
private ServiceModule createServiceModule(ServiceInfo serviceInfo,
Collection<ConfigurationModule> configurations,
StackContext context) {
if (serviceInfo.getName() == null) {
serviceInfo.setName("service1");
}
ConfigurationDirectory configDirectory = createConfigurationDirectory(configurations);
ServiceDirectory serviceDirectory = createServiceDirectory(serviceInfo.getConfigDir(), configDirectory);
return createServiceModule(context, serviceInfo, serviceDirectory);
}
private ServiceModule createServiceModule(ServiceInfo serviceInfo, Collection<ConfigurationModule> configurations) {
String serviceName = serviceInfo.getName();
if (serviceInfo.getName() == null) {
serviceInfo.setName("service1");
}
return createServiceModule(serviceInfo, configurations, createStackContext(serviceName, true));
}
private ServiceModule createServiceModule(StackContext context, ServiceInfo serviceInfo,
ServiceDirectory serviceDirectory) {
return new ServiceModule(context, serviceInfo, serviceDirectory);
}
private ServiceDirectory createServiceDirectory(String dir, ConfigurationDirectory configDir) {
ServiceDirectory serviceDirectory = createNiceMock(ServiceDirectory.class);
expect(serviceDirectory.getConfigurationDirectory(dir, AmbariMetaInfo.SERVICE_PROPERTIES_FOLDER_NAME)).andReturn(configDir).anyTimes();
expect(serviceDirectory.getMetricsFile(anyObject(String.class))).andReturn(new File("testMetricsFile")).anyTimes();
expect(serviceDirectory.getWidgetsDescriptorFile(anyObject(String.class))).andReturn(new File("testWidgetsFile")).anyTimes();
expect(serviceDirectory.getAlertsFile()).andReturn(new File("testAlertsFile")).anyTimes();
expect(serviceDirectory.getKerberosDescriptorFile()).andReturn(new File("testKerberosDescriptorFile")).anyTimes();
expect(serviceDirectory.getPackageDir()).andReturn("packageDir").anyTimes();
replay(serviceDirectory);
return serviceDirectory;
}
private ConfigurationDirectory createConfigurationDirectory(Collection<ConfigurationModule> modules) {
ConfigurationDirectory configDir = createNiceMock(ConfigurationDirectory.class);
expect(configDir.getConfigurationModules()).andReturn(modules).anyTimes();
replay(configDir);
return configDir;
}
private ConfigurationModule createConfigurationModule(String configType, ConfigurationInfo info) {
return new ConfigurationModule(configType, info);
}
private ConfigurationModule createConfigurationModule(String configType, Collection<PropertyInfo> properties) {
ConfigurationInfo info = new ConfigurationInfo(properties, Collections.<String, String>emptyMap());
return new ConfigurationModule(configType, info);
}
private ConfigurationModule createConfigurationModule(String configType,
Collection<PropertyInfo> properties,
Map<String, String> attributes) {
ConfigurationInfo info = new ConfigurationInfo(properties, attributes);
return new ConfigurationModule(configType, info);
}
private ConfigurationInfo createConfigurationInfo(Collection<PropertyInfo> properties,
Map<String, String> attributes) {
return new ConfigurationInfo(properties, attributes);
}
private StackContext createStackContext(String serviceName, boolean expectServiceRegistration) {
StackContext context = createStrictMock(StackContext.class);
if (expectServiceRegistration) {
context.registerServiceCheck(serviceName);
}
replay(context);
return context;
}
private ServiceModule resolveService(ServiceInfo info, ServiceInfo parentInfo) throws AmbariException {
ServiceModule service = createServiceModule(info);
ServiceModule parentService = createServiceModule(parentInfo);
resolveService(service, parentService);
return service;
}
private void resolveService(ServiceModule service, ServiceModule parent) throws AmbariException {
service.resolve(parent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap(), Collections.<String, ExtensionModule>emptyMap());
// during runtime this would be called by the Stack module when it's resolve completed
service.finalizeModule();
parent.finalizeModule();
}
private void assertAttributes(Map<String, Map<String, String>> mergedAttributes, Map<String, String> specifiedAttributes) {
assertEquals(1, mergedAttributes.size()); // only supports
Map<String, String> supportsAttributes = mergedAttributes.get(ConfigurationInfo.Supports.KEYWORD);
assertEquals(ConfigurationInfo.Supports.values().length, supportsAttributes.size());
for (Map.Entry<String, String> attribute : supportsAttributes.entrySet()) {
String attributeName = attribute.getKey();
String attributeValue = attribute.getValue();
//need to call toUpper() because propertyName is name().toLowerCase()
ConfigurationInfo.Supports s = ConfigurationInfo.Supports.valueOf(attributeName.toUpperCase());
String specifiedVal = specifiedAttributes.get(s.getXmlAttributeName());
if (specifiedVal != null) {
assertEquals(specifiedVal, attributeValue);
} else {
assertEquals(s.getDefaultValue(), attributeValue);
}
}
}
private void setPrivateField(Object o, String field, Object value) throws Exception{
Class<?> c = o.getClass();
Field f = c.getDeclaredField(field);
f.setAccessible(true);
f.set(o, value); }
}