This is an automated email from the ASF dual-hosted git repository. adoroszlai pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push: new 5a8af96 AMBARI-24774. Wrong settings in exported blueprint (#2475) 5a8af96 is described below commit 5a8af96159fe1fe43d2569d847a88de44dcf59c6 Author: Doroszlai, Attila <6454655+adorosz...@users.noreply.github.com> AuthorDate: Wed Oct 17 15:53:35 2018 +0200 AMBARI-24774. Wrong settings in exported blueprint (#2475) --- .../api/query/render/ClusterBlueprintRenderer.java | 189 +++--------- .../query/render/ClusterBlueprintRendererTest.java | 333 +++++++++++---------- 2 files changed, 227 insertions(+), 295 deletions(-) diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java index 9713a59..7ac240a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java @@ -56,6 +56,7 @@ import org.apache.ambari.server.controller.spi.SystemException; import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; import org.apache.ambari.server.controller.utilities.PredicateBuilder; import org.apache.ambari.server.state.SecurityType; +import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.topology.AmbariContext; import org.apache.ambari.server.topology.ClusterTopology; import org.apache.ambari.server.topology.ClusterTopologyImpl; @@ -69,23 +70,27 @@ import org.apache.ambari.server.topology.SecurityConfigurationFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; + /** * Renderer which renders a cluster resource as a blueprint. */ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer { + private final static Logger LOG = LoggerFactory.getLogger(ClusterBlueprintRenderer.class); + + static final String SERVICE_SETTINGS = "service_settings"; + static final String COMPONENT_SETTINGS = "component_settings"; + static final String CREDENTIAL_STORE_ENABLED = "credential_store_enabled"; + static final String RECOVERY_ENABLED = "recovery_enabled"; + static final String TRUE = Boolean.TRUE.toString(); + static final String FALSE = Boolean.FALSE.toString(); + /** * Management Controller used to get stack information. */ - private AmbariManagementController controller = AmbariServer.getController(); - -// /** -// * Map of configuration type to configuration properties which are required that a user -// * input. These properties will be stripped from the exported blueprint. -// */ -// private Map<String, Collection<String>> propertiesToStrip = new HashMap<String, Collection<String>>(); - - private final static Logger LOG = LoggerFactory.getLogger(ClusterBlueprintRenderer.class); + private final AmbariManagementController controller = AmbariServer.getController(); // ----- Renderer ---------------------------------------------------------- @@ -189,7 +194,6 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer { try { topology = createClusterTopology(clusterNode); } catch (InvalidTopologyTemplateException | InvalidTopologyException e) { - //todo throw new RuntimeException("Unable to process blueprint export request: " + e, e); } @@ -206,8 +210,7 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer { try { String clusterName = topology.getAmbariContext().getClusterName(topology.getClusterId()); - Map<String, Object> kerberosDescriptor = getKerberosDescriptor(topology.getAmbariContext() - .getClusterController(), clusterName); + Map<String, Object> kerberosDescriptor = getKerberosDescriptor(AmbariContext.getClusterController(), clusterName); if (kerberosDescriptor != null) { securityConfigMap.put(SecurityConfigurationFactory.KERBEROS_DESCRIPTOR_PROPERTY_ID, kerberosDescriptor); } @@ -220,13 +223,10 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer { List<Map<String, Object>> groupList = formatGroupsAsList(topology); blueprintResource.setProperty("host_groups", groupList); - //todo: ensure that this is properly handled in config processor - //determinePropertiesToStrip(topology); - blueprintResource.setProperty("configurations", processConfigurations(topology)); //Fetch settings section for blueprint - blueprintResource.setProperty("settings", getSettings(clusterNode)); + blueprintResource.setProperty("settings", getSettings(clusterNode, stack)); return blueprintResource; } @@ -258,80 +258,57 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer { "recovery_enabled": "true" } ] } ] * - * @param clusterNode * @return A Collection<Map<String, Object>> which represents the Setting Object */ - private Collection<Map<String, Object>> getSettings(TreeNode<Resource> clusterNode) { - LOG.info("ClusterBlueprintRenderer: getSettings()"); - + @VisibleForTesting + static Collection<Map<String, Object>> getSettings(TreeNode<Resource> clusterNode, Stack stack) { //Initialize collections to create appropriate json structure Collection<Map<String, Object>> blueprintSetting = new ArrayList<>(); - Set<Map<String, String>> recoverySettingValue = new HashSet<>(); - Set<Map<String, String>> serviceSettingValue = new HashSet<>(); - Set<Map<String, String>> componentSettingValue = new HashSet<>(); - - HashMap<String, String> property; - HashMap<String, String> componentProperty = new HashMap<>(); - Boolean globalRecoveryEnabled = false; + Set<Map<String, String>> serviceSettings = new HashSet<>(); + Set<Map<String, String>> componentSettings = new HashSet<>(); //Fetch the services, to obtain ServiceInfo and ServiceComponents Collection<TreeNode<Resource>> serviceChildren = clusterNode.getChild("services").getChildren(); - for (TreeNode serviceNode : serviceChildren) { + for (TreeNode<Resource> serviceNode : serviceChildren) { ResourceImpl service = (ResourceImpl) serviceNode.getObject(); - Map<String, Object> ServiceInfoMap = service.getPropertiesMap().get("ServiceInfo"); + Map<String, Object> serviceInfoMap = service.getPropertiesMap().get("ServiceInfo"); //service_settings population - property = new HashMap<>(); - if (ServiceInfoMap.get("credential_store_enabled").equals("true")) { - property.put("name", ServiceInfoMap.get("service_name").toString()); - property.put("credential_store_enabled", "true"); + Map<String, String> serviceSetting = new HashMap<>(); + String serviceName = serviceInfoMap.get("service_name").toString(); + ServiceInfo serviceInfo = stack.getServiceInfo(serviceName).orElseThrow(IllegalStateException::new); + boolean serviceDefaultCredentialStoreEnabled = serviceInfo.isCredentialStoreEnabled(); + String credentialStoreEnabledString = String.valueOf(serviceInfoMap.get(CREDENTIAL_STORE_ENABLED)); + boolean credentialStoreEnabled = Boolean.parseBoolean(credentialStoreEnabledString); + if (credentialStoreEnabled != serviceDefaultCredentialStoreEnabled) { + serviceSetting.put(CREDENTIAL_STORE_ENABLED, credentialStoreEnabledString); + serviceSetting.put("name", serviceName); + serviceSettings.add(serviceSetting); } //Fetch the service Components to obtain ServiceComponentInfo Collection<TreeNode<Resource>> componentChildren = serviceNode.getChild("components").getChildren(); for (TreeNode componentNode : componentChildren) { ResourceImpl component = (ResourceImpl) componentNode.getObject(); - Map<String, Object> ServiceComponentInfoMap = component.getPropertiesMap().get("ServiceComponentInfo"); - - if (ServiceComponentInfoMap.get("recovery_enabled").equals("true")) { - globalRecoveryEnabled = true; - property.put("name", ServiceInfoMap.get("service_name").toString()); - property.put("recovery_enabled", "true"); - - //component_settings population - componentProperty = new HashMap<>(); - componentProperty.put("name", ServiceComponentInfoMap.get("component_name").toString()); - componentProperty.put("recovery_enabled", "true"); + Map<String, Object> serviceComponentInfoMap = component.getPropertiesMap().get("ServiceComponentInfo"); + String componentName = serviceComponentInfoMap.get("component_name").toString(); + boolean componentDefaultRecoveryEnabled = serviceInfo.getComponentByName(componentName).isRecoveryEnabled(); + + if (serviceComponentInfoMap.containsKey(RECOVERY_ENABLED)) { + String recoveryEnabledString = String.valueOf(serviceComponentInfoMap.get(RECOVERY_ENABLED)); + boolean recoveryEnabled = Boolean.parseBoolean(recoveryEnabledString); + if (recoveryEnabled != componentDefaultRecoveryEnabled) { + componentSettings.add(ImmutableMap.of( + "name", componentName, + RECOVERY_ENABLED, recoveryEnabledString + )); + } } } - - if (!property.isEmpty()) - serviceSettingValue.add(property); - if (!componentProperty.isEmpty()) - componentSettingValue.add(componentProperty); - } - //recovery_settings population - property = new HashMap<>(); - if (globalRecoveryEnabled) { - property.put("recovery_enabled", "true"); - } else { - property.put("recovery_enabled", "false"); } - recoverySettingValue.add(property); - - //Add all the different setting values. - Map<String, Object> settingMap = new HashMap<>(); - settingMap.put("recovery_settings", recoverySettingValue); - blueprintSetting.add(settingMap); - - settingMap = new HashMap<>(); - settingMap.put("service_settings", serviceSettingValue); - blueprintSetting.add(settingMap); - - settingMap = new HashMap<>(); - settingMap.put("component_settings", componentSettingValue); - blueprintSetting.add(settingMap); + blueprintSetting.add(ImmutableMap.of(SERVICE_SETTINGS, serviceSettings)); + blueprintSetting.add(ImmutableMap.of(COMPONENT_SETTINGS, componentSettings)); return blueprintSetting; } @@ -348,7 +325,7 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer { org.apache.ambari.server.controller.spi.Request request = new RequestImpl(Collections.emptySet(), Collections.emptySet(), Collections.emptyMap(), null); - Set<Resource> response = null; + Set<Resource> response; try { response = artifactProvider.getResources(request, predicate); } catch (SystemException | UnsupportedPropertyException | NoSuchResourceException | NoSuchParentResourceException @@ -480,76 +457,6 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer { return controller; } - - // /** -// * Determine which configuration properties need to be stripped from the configuration prior to exporting. -// * Stripped properties are any property which are marked as required in the stack definition. For example, -// * all passwords are required properties and are therefore not exported. -// * -// * @param servicesNode services node -// * @param stackName stack name -// * @param stackVersion stack version -// */ -// private void determinePropertiesToStrip(TreeNode<Resource> servicesNode, String stackName, String stackVersion) { -// AmbariMetaInfo ambariMetaInfo = getController().getAmbariMetaInfo(); -// StackInfo stack; -// try { -// stack = ambariMetaInfo.getStack(stackName, stackVersion); -// } catch (AmbariException e) { -// // shouldn't ever happen. -// // Exception indicates that stack is not defined -// // but we are getting the stack name from a running cluster. -// throw new RuntimeException("Unexpected exception occurred while generating a blueprint. " + -// "The stack '" + stackName + ":" + stackVersion + "' does not exist"); -// } -// Map<String, PropertyInfo> requiredStackProperties = stack.getRequiredProperties(); -// updatePropertiesToStrip(requiredStackProperties); -// -// for (TreeNode<Resource> serviceNode : servicesNode.getChildren()) { -// String name = (String) serviceNode.getObject().getPropertyValue("ServiceInfo/service_name"); -// ServiceInfo service; -// try { -// service = ambariMetaInfo.getService(stackName, stackVersion, name); -// } catch (AmbariException e) { -// // shouldn't ever happen. -// // Exception indicates that service is not in the stack -// // but we are getting the name from a running cluster. -// throw new RuntimeException("Unexpected exception occurred while generating a blueprint. The service '" + -// name + "' was not found in the stack: '" + stackName + ":" + stackVersion); -// } -// -// Map<String, PropertyInfo> requiredProperties = service.getRequiredProperties(); -// updatePropertiesToStrip(requiredProperties); -// } -// } - -// /** -// * Helper method to update propertiesToStrip with properties that are marked as required -// * -// * @param requiredProperties Properties marked as required -// */ -// private void updatePropertiesToStrip(Map<String, PropertyInfo> requiredProperties) { -// -// for (Map.Entry<String, PropertyInfo> entry : requiredProperties.entrySet()) { -// String propertyName = entry.getKey(); -// PropertyInfo propertyInfo = entry.getValue(); -// String configCategory = propertyInfo.getFilename(); -// if (configCategory.endsWith(".xml")) { -// configCategory = configCategory.substring(0, configCategory.indexOf(".xml")); -// } -// Collection<String> categoryProperties = propertiesToStrip.get(configCategory); -// if (categoryProperties == null) { -// categoryProperties = new ArrayList<String>(); -// propertiesToStrip.put(configCategory, categoryProperties); -// } -// categoryProperties.add(propertyName); -// } -// } - - - - - // ----- Blueprint Post Processor inner class ------------------------------ /** diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java index b47a25d..b9ef9c9 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java @@ -34,14 +34,15 @@ import static org.junit.Assert.assertTrue; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import org.apache.ambari.server.api.query.QueryInfo; @@ -68,6 +69,7 @@ import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.ResourceProvider; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; +import org.apache.ambari.server.state.ComponentInfo; import org.apache.ambari.server.state.DesiredConfig; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.state.cluster.ClustersImpl; @@ -79,8 +81,6 @@ import org.apache.ambari.server.topology.Component; 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.InvalidTopologyException; -import org.apache.ambari.server.topology.InvalidTopologyTemplateException; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -89,6 +89,11 @@ import org.powermock.api.easymock.PowerMock; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; + /** * ClusterBlueprintRenderer unit tests. */ @@ -137,10 +142,6 @@ public class ClusterBlueprintRendererTest { Collection<Component> group2Components = Arrays.asList(new Component("TASKTRACKER"), new Component("DATANODE")); - Map<String, Configuration> hostGroupConfigs = new HashMap<>(); - hostGroupConfigs.put("host_group_1", emptyConfiguration); - hostGroupConfigs.put("host_group_2", emptyConfiguration); - Map<String, HostGroup> hostGroups = new HashMap<>(); hostGroups.put("host_group_1", group1); hostGroups.put("host_group_2", group2); @@ -211,7 +212,7 @@ public class ClusterBlueprintRendererTest { expect(topology.getConfiguration()).andReturn(clusterConfig).anyTimes(); expect(topology.getBlueprint()).andReturn(blueprint).anyTimes(); expect(topology.getHostGroupInfo()).andReturn(groupInfoMap).anyTimes(); - expect(topology.getClusterId()).andReturn(new Long(1)).anyTimes(); + expect(topology.getClusterId()).andReturn(1L).anyTimes(); expect(topology.getAmbariContext()).andReturn(ambariContext).anyTimes(); expect(topology.isClusterKerberosEnabled()).andReturn(true).anyTimes(); @@ -221,8 +222,7 @@ public class ClusterBlueprintRendererTest { Resource resource = createStrictMock(Resource.class); Set<Resource> result = Collections.singleton(resource); - expect(resourceProvider.getResources((Request) anyObject(Request.class), - (Predicate) anyObject(Predicate.class))).andReturn(result).once(); + expect(resourceProvider.getResources(anyObject(Request.class), anyObject(Predicate.class))).andReturn(result).once(); Map<String, Map<String, Object>> resourcePropertiesMap = new HashMap<>(); resourcePropertiesMap.put(ArtifactResourceProvider.ARTIFACT_DATA_PROPERTY, Collections.emptyMap()); @@ -268,146 +268,185 @@ public class ClusterBlueprintRendererTest { assertTrue(propertyTree.getChild("Host/HostComponent").getObject().contains("HostRoles/component_name")); } - public TreeNode<Resource> createResultTreeSettingsObject(TreeNode<Resource> resultTree){ - Resource clusterResource = new ResourceImpl(Resource.Type.Cluster); + @Test + public void clusterWithDefaultSettings() { + Stack stack = stackForSettingsTest(); + TreeNode<Resource> clusterNode = clusterWith(stack, + stack.getComponents(), + defaultCredentialStoreSettings(), + defaultRecoverySettings()); + + Collection<Map<String, Object>> settings = ClusterBlueprintRenderer.getSettings(clusterNode, stack); + + assertEquals(Lists.newArrayList( + ImmutableMap.of(ClusterBlueprintRenderer.SERVICE_SETTINGS, ImmutableSet.of()), + ImmutableMap.of(ClusterBlueprintRenderer.COMPONENT_SETTINGS, ImmutableSet.of()) + ), settings); + } - clusterResource.setProperty("Clusters/cluster_name", "testCluster"); - clusterResource.setProperty("Clusters/version", "HDP-1.3.3"); + @Test + public void clusterWithCustomSettings() { + Stack stack = stackForSettingsTest(); + TreeNode<Resource> clusterNode = clusterWith(stack, + stack.getComponents(), + customCredentialStoreSettingFor(stack, "service1", "service2"), + customRecoverySettingsFor(stack, "component1", "component2")); + + Collection<Map<String, Object>> settings = ClusterBlueprintRenderer.getSettings(clusterNode, stack); + + assertEquals(Lists.newArrayList( + ImmutableMap.of(ClusterBlueprintRenderer.SERVICE_SETTINGS, ImmutableSet.of( + ImmutableMap.of( + "name", "service1", + ClusterBlueprintRenderer.CREDENTIAL_STORE_ENABLED, ClusterBlueprintRenderer.FALSE + ), + ImmutableMap.of( + "name", "service2", + ClusterBlueprintRenderer.CREDENTIAL_STORE_ENABLED, ClusterBlueprintRenderer.TRUE + ) + )), + ImmutableMap.of(ClusterBlueprintRenderer.COMPONENT_SETTINGS, ImmutableSet.of( + ImmutableMap.of("name", "component1", ClusterBlueprintRenderer.RECOVERY_ENABLED, ClusterBlueprintRenderer.FALSE), + ImmutableMap.of("name", "component2", ClusterBlueprintRenderer.RECOVERY_ENABLED, ClusterBlueprintRenderer.TRUE) + )) + ), settings); + } - TreeNode<Resource> clusterTree = resultTree.addChild(clusterResource, "Cluster:1"); + @Test + public void clusterWithRecoveryDisabled() { + Stack stack = stackForSettingsTest(); + TreeNode<Resource> clusterNode = clusterWith(stack, + stack.getComponents(), + defaultCredentialStoreSettings(), + customRecoverySettingsFor(stack, "component1")); + + Collection<Map<String, Object>> settings = ClusterBlueprintRenderer.getSettings(clusterNode, stack); + + assertEquals(Lists.newArrayList( + ImmutableMap.of(ClusterBlueprintRenderer.SERVICE_SETTINGS, ImmutableSet.of()), + ImmutableMap.of(ClusterBlueprintRenderer.COMPONENT_SETTINGS, ImmutableSet.of( + ImmutableMap.of("name", "component1", ClusterBlueprintRenderer.RECOVERY_ENABLED, ClusterBlueprintRenderer.FALSE) + )) + ), settings); + } + + private static TreeNode<Resource> clusterWith(Stack stack, + Map<String, Collection<String>> componentsByService, + Map<String, Map<String, String>> serviceSettings, + Map<String, Map<String, Map<String, String>>> componentSettings + ) { + TreeNode<Resource> clusterTree = new ResultImpl(true).getResultTree(); TreeNode<Resource> servicesTree = clusterTree.addChild(null, "services"); servicesTree.setProperty("isCollection", "true"); - //Scenario 1 : Service with Credential Store enabled, Recovery enabled for Component:1 and not for Component:2 - Resource serviceResource1 = new ResourceImpl(Resource.Type.Service); - serviceResource1.setProperty("ServiceInfo/service_name","Service:1"); - serviceResource1.setProperty("ServiceInfo/credential_store_supported","true"); - serviceResource1.setProperty("ServiceInfo/credential_store_enabled","true"); - TreeNode<Resource> serviceTree = servicesTree.addChild(serviceResource1, "Service:1"); - - Resource ttComponentResource = new ResourceImpl(Resource.Type.Component); - ttComponentResource.setProperty("ServiceComponentInfo/component_name", "Component:1"); - ttComponentResource.setProperty("ServiceComponentInfo/cluster_name", "testCluster"); - ttComponentResource.setProperty("ServiceComponentInfo/service_name", "Service:1"); - ttComponentResource.setProperty("ServiceComponentInfo/recovery_enabled", "true"); - - Resource dnComponentResource = new ResourceImpl(Resource.Type.Component); - dnComponentResource.setProperty("ServiceComponentInfo/component_name", "Component:2"); - dnComponentResource.setProperty("ServiceComponentInfo/cluster_name", "testCluster"); - dnComponentResource.setProperty("ServiceComponentInfo/service_name", "Service:1"); - dnComponentResource.setProperty("ServiceComponentInfo/recovery_enabled", "false"); - - TreeNode<Resource> componentsTree1 = serviceTree.addChild(null, "components"); - componentsTree1.setProperty("isCollection", "true"); - - componentsTree1.addChild(ttComponentResource, "Component:1"); - componentsTree1.addChild(dnComponentResource, "Component:2"); - - //Scenario 2 :Service with Credential Store disabled, Recovery enabled for Component:1 - Resource serviceResource2 = new ResourceImpl(Resource.Type.Service); - serviceResource2.setProperty("ServiceInfo/service_name","Service:2"); - serviceResource2.setProperty("ServiceInfo/credential_store_supported","true"); - serviceResource2.setProperty("ServiceInfo/credential_store_enabled","false"); - serviceTree = servicesTree.addChild(serviceResource2, "Service:2"); - - ttComponentResource = new ResourceImpl(Resource.Type.Component); - ttComponentResource.setProperty("ServiceComponentInfo/component_name", "Component:1"); - ttComponentResource.setProperty("ServiceComponentInfo/cluster_name", "testCluster"); - ttComponentResource.setProperty("ServiceComponentInfo/service_name", "Service:2"); - ttComponentResource.setProperty("ServiceComponentInfo/recovery_enabled", "true"); - - TreeNode<Resource> componentsTree2 = serviceTree.addChild(null, "components"); - componentsTree2.setProperty("isCollection", "true"); - - componentsTree2.addChild(ttComponentResource, "Component:1"); - - //Scenario 3 :Service with both Credential Store and Recovery enabled as false - Resource serviceResource3 = new ResourceImpl(Resource.Type.Service); - serviceResource3.setProperty("ServiceInfo/service_name","Service:3"); - serviceResource3.setProperty("ServiceInfo/credential_store_supported","false"); - serviceResource3.setProperty("ServiceInfo/credential_store_enabled","false"); - serviceTree = servicesTree.addChild(serviceResource3, "Service:3"); - - ttComponentResource = new ResourceImpl(Resource.Type.Component); - ttComponentResource.setProperty("ServiceComponentInfo/component_name", "Component:1"); - ttComponentResource.setProperty("ServiceComponentInfo/cluster_name", "testCluster"); - ttComponentResource.setProperty("ServiceComponentInfo/service_name", "Service:3"); - ttComponentResource.setProperty("ServiceComponentInfo/recovery_enabled", "false"); - - TreeNode<Resource> componentsTree3 = serviceTree.addChild(null, "components"); - componentsTree3.setProperty("isCollection", "true"); - - componentsTree3.addChild(ttComponentResource, "Component:1"); - - //Add empty configurations - Resource configurationsResource = new ResourceImpl(Resource.Type.Configuration); - clusterTree.addChild(configurationsResource, "configurations"); + for (Map.Entry<String, Collection<String>> serviceEntry : componentsByService.entrySet()) { + String serviceName = serviceEntry.getKey(); + Optional<ServiceInfo> serviceInfo = stack.getServiceInfo(serviceName); + if (serviceInfo.isPresent()) { + Resource serviceResource = new ResourceImpl(Resource.Type.Service); + serviceResource.setProperty("ServiceInfo/service_name", serviceName); + serviceResource.setProperty("ServiceInfo/credential_store_supported", serviceInfo.get().isCredentialStoreSupported()); + serviceResource.setProperty("ServiceInfo/credential_store_enabled", + serviceSettings + .getOrDefault(serviceName, ImmutableMap.of()) + .getOrDefault(ClusterBlueprintRenderer.CREDENTIAL_STORE_ENABLED, String.valueOf(serviceInfo.get().isCredentialStoreEnabled()))); + TreeNode<Resource> serviceTree = servicesTree.addChild(serviceResource, serviceName); + TreeNode<Resource> componentsTree = serviceTree.addChild(null, "components"); + componentsTree.setProperty("isCollection", "true"); + + for (String componentName : serviceEntry.getValue()) { + ComponentInfo componentInfo = serviceInfo.get().getComponentByName(componentName); + Resource componentResource = new ResourceImpl(Resource.Type.Component); + componentResource.setProperty("ServiceComponentInfo/component_name", componentName); + componentResource.setProperty("ServiceComponentInfo/cluster_name", "testCluster"); + componentResource.setProperty("ServiceComponentInfo/service_name", serviceName); + componentResource.setProperty("ServiceComponentInfo/recovery_enabled", + componentSettings + .getOrDefault(serviceName, ImmutableMap.of()) + .getOrDefault(componentName, ImmutableMap.of()) + .getOrDefault(ClusterBlueprintRenderer.RECOVERY_ENABLED, String.valueOf(componentInfo.isRecoveryEnabled()))); + componentsTree.addChild(componentResource, componentName); + } + } + } - //Add empty hosts - Resource hostResource = new ResourceImpl(Resource.Type.Host); - clusterTree.addChild(hostResource, "hosts"); + return clusterTree; + } - return resultTree; + private static Map<String, Map<String, String>> defaultCredentialStoreSettings() { + return ImmutableMap.of(); } - @Test - public void testGetSettings_instance(){ - Result result = new ResultImpl(true); + private static Map<String, Map<String, String>> customCredentialStoreSettingFor(Stack stack, String... services) { + Map<String, Map<String, String>> result = new LinkedHashMap<>(); + for (String service : services) { + ServiceInfo serviceInfo = stack.getServiceInfo(service).orElseThrow(IllegalStateException::new); + result.put(service, ImmutableMap.of( + ClusterBlueprintRenderer.CREDENTIAL_STORE_ENABLED, String.valueOf(!serviceInfo.isCredentialStoreEnabled()) + )); + } + return result; + } - TreeNode<Resource> resultTree = createResultTreeSettingsObject(result.getResultTree()); + private static Map<String, Map<String, Map<String, String>>> defaultRecoverySettings() { + return ImmutableMap.of(); + } - ClusterBlueprintRenderer renderer = new TestBlueprintRenderer(topology); - Result blueprintResult = renderer.finalizeResult(result); - TreeNode<Resource> blueprintTree = blueprintResult.getResultTree(); - TreeNode<Resource> blueprintNode = blueprintTree.getChildren().iterator().next(); - Resource blueprintResource = blueprintNode.getObject(); - Map<String, Map<String, Object>> propertiesMap = blueprintResource.getPropertiesMap(); - Map<String,Object> children = propertiesMap.get(""); + private static Map<String, Map<String, Map<String, String>>> customRecoverySettingsFor(Stack stack, String... components) { + Map<String, Map<String, Map<String, String>>> result = new LinkedHashMap<>(); + for (String component : components) { + ComponentInfo componentInfo = stack.getComponentInfo(component); + String service = stack.getServiceForComponent(component); + result + .computeIfAbsent(service, __ -> new HashMap<>()) + .put(component, ImmutableMap.of( + ClusterBlueprintRenderer.RECOVERY_ENABLED, String.valueOf(!componentInfo.isRecoveryEnabled()) + )); + } + return result; + } - //Verify if required information is present in actual result - assertTrue(children.containsKey("settings")); + private static Stack stackForSettingsTest() { + Stack stack = createNiceMock(Stack.class); - List<Map<String,Object>> settingValues = (ArrayList)children.get("settings"); - Boolean isRecoverySettings = false; - Boolean isComponentSettings = false; - Boolean isServiceSettings = false; + ServiceInfo service1 = createNiceMock(ServiceInfo.class); + expect(service1.isCredentialStoreEnabled()).andReturn(true).anyTimes(); + expect(stack.getServiceInfo("service1")).andReturn(Optional.of(service1)).anyTimes(); - //Verify actual values - for(Map<String,Object> settingProp : settingValues){ - if(settingProp.containsKey("recovery_settings")){ - isRecoverySettings = true; - HashSet<Map<String,String>> checkPropSize = (HashSet)settingProp.get("recovery_settings"); - assertEquals(1,checkPropSize.size()); - assertEquals("true",checkPropSize.iterator().next().get("recovery_enabled")); + ComponentInfo component1 = createNiceMock(ComponentInfo.class); + expect(component1.isRecoveryEnabled()).andReturn(true).anyTimes(); + expect(service1.getComponentByName("component1")).andReturn(component1).anyTimes(); + expect(stack.getServiceForComponent("component1")).andReturn("service1").anyTimes(); + expect(stack.getComponentInfo("component1")).andReturn(component1).anyTimes(); - } - if(settingProp.containsKey("component_settings")){ - isComponentSettings = true; - HashSet<Map<String,String>> checkPropSize = (HashSet)settingProp.get("component_settings"); - assertEquals(1,checkPropSize.size()); - Map<String, String> finalProp = checkPropSize.iterator().next(); - assertEquals("Component:1",finalProp.get("name")); - assertEquals("true",finalProp.get("recovery_enabled")); - } - if(settingProp.containsKey("service_settings")){ - isServiceSettings = true; - HashSet<Map<String,String>> checkPropSize = (HashSet)settingProp.get("service_settings"); - assertEquals(2,checkPropSize.size()); - for(Map<String,String> finalProp : checkPropSize){ - if(finalProp.containsKey("credential_store_enabled")){ - assertEquals("Service:1",finalProp.get("name")); - assertEquals("true",finalProp.get("recovery_enabled")); - } - assertFalse(finalProp.get("name").equals("Service:3")); - } - } - } - //Verify if required information is present in actual result - assertTrue(isRecoverySettings); - assertTrue(isComponentSettings); - assertTrue(isServiceSettings); + ComponentInfo component2 = createNiceMock(ComponentInfo.class); + expect(component2.isRecoveryEnabled()).andReturn(false).anyTimes(); + expect(service1.getComponentByName("component2")).andReturn(component2).anyTimes(); + expect(stack.getServiceForComponent("component2")).andReturn("service1").anyTimes(); + expect(stack.getComponentInfo("component2")).andReturn(component2).anyTimes(); + + expect(service1.getComponents()).andReturn(ImmutableList.of(component1, component2)).anyTimes(); + + ServiceInfo service2 = createNiceMock(ServiceInfo.class); + expect(service2.isCredentialStoreEnabled()).andReturn(false).anyTimes(); + expect(stack.getServiceInfo("service2")).andReturn(Optional.of(service2)).anyTimes(); + ComponentInfo component3 = createNiceMock(ComponentInfo.class); + expect(component3.isRecoveryEnabled()).andReturn(false).anyTimes(); + expect(service2.getComponentByName("component3")).andReturn(component3).anyTimes(); + expect(stack.getServiceForComponent("component3")).andReturn("service2").anyTimes(); + expect(stack.getComponentInfo("component3")).andReturn(component3).anyTimes(); + expect(service2.getComponents()).andReturn(ImmutableList.of(component3)).anyTimes(); + + expect(stack.getComponents()).andReturn(ImmutableMap.of( + "service1", ImmutableSet.of("component1", "component2"), + "service2", ImmutableSet.of("component3") + )).anyTimes(); + + replay(stack, service1, service2, component1, component2, component3); + + return stack; } @Test @@ -490,12 +529,9 @@ public class ClusterBlueprintRendererTest { // 4 specified components and ambari server assertEquals(5, components.size()); - Set<String> expectedValues = new HashSet<>( - Arrays.asList("JOBTRACKER", "TASKTRACKER", "NAMENODE", "DATANODE", "AMBARI_SERVER")); - + Set<String> expectedValues = ImmutableSet.of("JOBTRACKER", "TASKTRACKER", "NAMENODE", "DATANODE", "AMBARI_SERVER"); Set<String> actualValues = new HashSet<>(); - for (Map<String, String> componentProperties : components) { assertEquals(1, componentProperties.size()); actualValues.add(componentProperties.get("name")); @@ -508,12 +544,9 @@ public class ClusterBlueprintRendererTest { Collection<Map<String, String>> components = (Collection<Map<String, String>>) hostGroupProperties.get("components"); assertEquals(2, components.size()); - Set<String> expectedValues = new HashSet<>( - Arrays.asList("TASKTRACKER", "DATANODE")); - + Set<String> expectedValues = ImmutableSet.of("TASKTRACKER", "DATANODE"); Set<String> actualValues = new HashSet<>(); - for (Map<String, String> componentProperties : components) { assertEquals(1, componentProperties.size()); actualValues.add(componentProperties.get("name")); @@ -569,12 +602,9 @@ public class ClusterBlueprintRendererTest { // 4 specified components and ambari server assertEquals(5, components.size()); - Set<String> expectedValues = new HashSet<>( - Arrays.asList("JOBTRACKER", "TASKTRACKER", "NAMENODE", "DATANODE", "AMBARI_SERVER")); - + Set<String> expectedValues = ImmutableSet.of("JOBTRACKER", "TASKTRACKER", "NAMENODE", "DATANODE", "AMBARI_SERVER"); Set<String> actualValues = new HashSet<>(); - for (Map<String, String> componentProperties : components) { assertEquals(1, componentProperties.size()); actualValues.add(componentProperties.get("name")); @@ -587,12 +617,9 @@ public class ClusterBlueprintRendererTest { Collection<Map<String, String>> components = (Collection<Map<String, String>>) hostGroupProperties.get("components"); assertEquals(2, components.size()); - Set<String> expectedValues = new HashSet<>( - Arrays.asList("TASKTRACKER", "DATANODE")); - + Set<String> expectedValues = ImmutableSet.of("TASKTRACKER", "DATANODE"); Set<String> actualValues = new HashSet<>(); - for (Map<String, String> componentProperties : components) { assertEquals(1, componentProperties.size()); actualValues.add(componentProperties.get("name")); @@ -650,7 +677,7 @@ public class ClusterBlueprintRendererTest { } @Test - public void testClusterRendererDefaults() throws Exception { + public void testClusterRendererDefaults() { Renderer clusterBlueprintRenderer = new ClusterBlueprintRenderer(); @@ -800,14 +827,12 @@ public class ClusterBlueprintRendererTest { private ClusterTopology topology; - public TestBlueprintRenderer(ClusterTopology topology) { + TestBlueprintRenderer(ClusterTopology topology) { this.topology = topology; } @Override - protected ClusterTopology createClusterTopology(TreeNode<Resource> clusterNode) - throws InvalidTopologyTemplateException, InvalidTopologyException { - + protected ClusterTopology createClusterTopology(TreeNode<Resource> clusterNode) { return topology; } }