Blueprint V2 data model (benyoka)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b45710fb Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b45710fb Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b45710fb Branch: refs/heads/branch-feature-AMBARI-14714-tmp-bence Commit: b45710fb2248df539017ca2963c36c39baf24dea Parents: 5ddb07c Author: Balazs Bence Sari <beny...@apache.org> Authored: Wed Oct 18 17:39:59 2017 +0200 Committer: Balazs Bence Sari <beny...@apache.org> Committed: Wed Oct 18 17:39:59 2017 +0200 ---------------------------------------------------------------------- .../ambari/server/controller/StackV2.java | 417 +++++-------------- .../server/controller/StackV2Factory.java | 219 ++++++++++ .../ambari/server/orm/dao/BlueprintV2DAO.java | 136 ++++++ .../server/orm/entities/BlueprintEntity.java | 1 - .../server/orm/entities/BlueprintV2Entity.java | 119 ++++++ .../orm/entities/HostGroupComponentEntity.java | 17 +- .../ambari/server/orm/entities/StackEntity.java | 11 +- .../ambari/server/topology/BlueprintImplV2.java | 242 +++++++++-- .../ambari/server/topology/BlueprintV2.java | 58 +-- .../server/topology/BlueprintV2Factory.java | 170 ++++++++ .../server/topology/BlueprintValidatorV2.java | 43 ++ .../ambari/server/topology/ComponentV2.java | 85 +++- .../ambari/server/topology/Configurable.java | 40 ++ .../ambari/server/topology/Configuration.java | 7 + .../ambari/server/topology/HostGroupImpl.java | 2 - .../ambari/server/topology/HostGroupV2.java | 15 +- .../ambari/server/topology/HostGroupV2Impl.java | 124 ++++++ .../server/topology/RepositoryVersion.java | 71 ++++ .../server/topology/SecurityConfiguration.java | 7 +- .../apache/ambari/server/topology/Service.java | 82 ++-- .../ambari/server/topology/ServiceGroup.java | 41 +- .../ambari/server/topology/ServiceId.java | 52 +++ .../validators/BlueprintImplV2Test.java | 9 + 23 files changed, 1513 insertions(+), 455 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2.java index 8a2208d..6f0b606 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2.java @@ -25,10 +25,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.apache.ambari.server.AmbariException; -import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.state.AutoDeployInfo; -import org.apache.ambari.server.state.ComponentInfo; import org.apache.ambari.server.state.DependencyInfo; import org.apache.ambari.server.state.PropertyDependencyInfo; import org.apache.ambari.server.state.PropertyInfo; @@ -40,43 +37,27 @@ import org.apache.ambari.server.topology.Configuration; * Encapsulates stack information. */ public class StackV2 { - /** - * Stack name - */ - private String name; - /** - * Stack version - */ - private String version; + /** Stack name */ + private final String name; - /** - * Repo version - */ - private String repoVersion; + /** Stack version */ + private final String version; - /** - * Map of service name to components - */ - private Map<String, Collection<String>> serviceComponents = - new HashMap<>(); + /** Repo version */ + private final String repoVersion; - /** - * Map of component to service - */ - private Map<String, String> componentService = new HashMap<>(); + /** Map of service name to components */ + private final Map<String, Collection<String>> serviceComponents; - /** - * Map of component to dependencies - */ - private Map<String, Collection<DependencyInfo>> dependencies = - new HashMap<>(); + /** Map of component to service */ + private final Map<String, String> componentService; - /** - * Map of dependency to conditional service - */ - private Map<DependencyInfo, String> dependencyConditionalServiceMap = - new HashMap<>(); + /** Map of component to dependencies */ + private final Map<String, Collection<DependencyInfo>> dependencies; + + /** Map of dependency to conditional service */ + private final Map<DependencyInfo, String> dependencyConditionalServiceMap; /** * Map of database component name to configuration property which indicates whether @@ -84,129 +65,87 @@ public class StackV2 { * If the value of the config property starts with 'New', the database is determined * to be managed, otherwise it is non-managed. */ - private Map<String, String> dbDependencyInfo = new HashMap<>(); + private final Map<String, String> dbDependencyInfo; - /** - * Map of component to required cardinality - */ - private Map<String, String> cardinalityRequirements = new HashMap<>(); + /** Map of component to required cardinality */ + private final Map<String, String> cardinalityRequirements = new HashMap<>(); //todo: instead of all these maps from component -> * , //todo: we should use a Component object with all of these attributes private Set<String> masterComponents = new HashSet<>(); - /** - * Map of component to auto-deploy information - */ - private Map<String, AutoDeployInfo> componentAutoDeployInfo = - new HashMap<>(); - - /** - * Map of service to config type properties - */ - private Map<String, Map<String, Map<String, ConfigProperty>>> serviceConfigurations = - new HashMap<>(); - - /** - * Map of service to required type properties - */ - private Map<String, Map<String, Map<String, ConfigProperty>>> requiredServiceConfigurations = - new HashMap<>(); + /** Map of component to auto-deploy information */ + private final Map<String, AutoDeployInfo> componentAutoDeployInfo; - /** - * Map of service to config type properties - */ - private Map<String, Map<String, ConfigProperty>> stackConfigurations = - new HashMap<>(); - - /** - * Map of service to set of excluded config types - */ - private Map<String, Set<String>> excludedConfigurationTypes = - new HashMap<>(); + /** Map of service to config type properties */ + private final Map<String, Map<String, Map<String, ConfigProperty>>> serviceConfigurations; - /** - * Ambari Management Controller, used to obtain Stack definitions - */ - private final AmbariManagementController controller; + /** Map of service to required type properties */ + private final Map<String, Map<String, Map<String, ConfigProperty>>> requiredServiceConfigurations; + /** Map of service to config type properties */ + private final Map<String, Map<String, ConfigProperty>> stackConfigurations; - /** - * Constructor. - * - * @param stack - * the stack (not {@code null}). - * @param ambariManagementController - * the management controller (not {@code null}). - * @throws AmbariException - */ - public StackV2(StackEntity stack, AmbariManagementController ambariManagementController) throws AmbariException { - this(stack.getStackName(), stack.getStackVersion(), ambariManagementController); - } + /** Map of service to set of excluded config types */ + private final Map<String, Set<String>> excludedConfigurationTypes; - /** - * Constructor. - * - * @param name stack name - * @param version stack version - * - * @throws AmbariException an exception occurred getting stack information - * for the specified name and version - */ - //todo: don't pass management controller in constructor - public StackV2(String name, String version, AmbariManagementController controller) throws AmbariException { + public StackV2(String name, + String version, + String repoVersion, + Map<String, Collection<String>> serviceComponents, + Map<String, Collection<DependencyInfo>> dependencies, + Map<String, String> dbDependencyInfo, + Map<String, AutoDeployInfo> componentAutoDeployInfo, + Map<String, Map<String, Map<String, ConfigProperty>>> serviceConfigurations, + Map<String, Map<String, Map<String, ConfigProperty>>> requiredServiceConfigurations, + Map<String, Map<String, ConfigProperty>> stackConfigurations, + Map<String, Set<String>> excludedConfigurationTypes) { this.name = name; this.version = version; - this.controller = controller; + this.repoVersion = repoVersion; - Set<StackServiceResponse> stackServices = controller.getStackServices( - Collections.singleton(new StackServiceRequest(name, version, null))); + this.serviceComponents = serviceComponents; + this.componentService = new HashMap<>(); + for (Map.Entry<String, Collection<String>> entry: serviceComponents.entrySet()) { + for (String comp: entry.getValue()) { + componentService.put(comp, entry.getKey()); + } + } - for (StackServiceResponse stackService : stackServices) { - String serviceName = stackService.getServiceName(); - parseComponents(serviceName); - parseExcludedConfigurations(stackService); - parseConfigurations(stackService); - registerConditionalDependencies(); + this.dependencies = dependencies; + this.dependencyConditionalServiceMap = new HashMap<>(); + for (Map.Entry<String, Collection<DependencyInfo>> entry: dependencies.entrySet()) { + for (DependencyInfo di: entry.getValue()) { + dependencyConditionalServiceMap.put(di, entry.getKey()); + } } - //todo: already done for each service - parseStackConfigurations(); + this.dbDependencyInfo = dbDependencyInfo; + this.componentAutoDeployInfo = componentAutoDeployInfo; + this.serviceConfigurations = serviceConfigurations; + this.requiredServiceConfigurations = requiredServiceConfigurations; + this.stackConfigurations = stackConfigurations; + this.excludedConfigurationTypes = excludedConfigurationTypes; } - /** - * Obtain stack name. - * - * @return stack name - */ + /** @return stack name */ public String getName() { return name; } - /** - * Obtain stack version. - * - * @return stack version - */ + /** @return stack version */ public String getVersion() { return version; } - /** - * Obtain repo version. - * @return - */ + /** @return repo version */ public String getRepoVersion() { return repoVersion; } Map<DependencyInfo, String> getDependencyConditionalServiceMap() { return dependencyConditionalServiceMap; } - /** - * Get services contained in the stack. - * - * @return collection of all services for the stack - */ + /** @return collection of all services for the stack */ public Collection<String> getServices() { return serviceComponents.keySet(); } @@ -215,49 +154,39 @@ public class StackV2 { * Get components contained in the stack for the specified service. * * @param service service name - * * @return collection of component names for the specified service */ public Collection<String> getComponents(String service) { return serviceComponents.get(service); } - /** - * Get all service components - * - * @return map of service to associated components - */ + /** @return map of service to associated components */ public Map<String, Collection<String>> getComponents() { - Map<String, Collection<String>> serviceComponents = new HashMap<>(); - for (String service : getServices()) { - Collection<String> components = new HashSet<>(); - components.addAll(getComponents(service)); - serviceComponents.put(service, components); - } return serviceComponents; } - /** - * Get info for the specified component. - * - * @param component component name - * - * @return component information for the requested component - * or null if the component doesn't exist in the stack - */ - public ComponentInfo getComponentInfo(String component) { - ComponentInfo componentInfo = null; - String service = getServiceForComponent(component); - if (service != null) { - try { - componentInfo = controller.getAmbariMetaInfo().getComponent( - getName(), getVersion(), service, component); - } catch (AmbariException e) { - // just return null if component doesn't exist - } - } - return componentInfo; - } +// /** +// * Get info for the specified component. +// * +// * @param component component name +// * +// * @return component information for the requested component +// * or null if the component doesn't exist in the stack +// */ +// @Deprecated +// public ComponentInfo getComponentInfo(String component) { +// ComponentInfo componentInfo = null; +// String service = getServiceForComponent(component); +// if (service != null) { +// try { +// componentInfo = controller.getAmbariMetaInfo().getComponent( +// getName(), getVersion(), service, component); +// } catch (AmbariException e) { +// // just return null if component doesn't exist +// } +// } +// return componentInfo; +// } /** * Get all configuration types, including excluded types for the specified service. @@ -281,7 +210,6 @@ public class StackV2 { public Collection<String> getConfigurationTypes(String service) { Set<String> serviceTypes = new HashSet<>(serviceConfigurations.get(service).keySet()); serviceTypes.removeAll(getExcludedConfigurationTypes(service)); - return serviceTypes; } @@ -357,7 +285,6 @@ public class StackV2 { matchingProperties.add(configProperty); } } - } } return matchingProperties; @@ -411,11 +338,7 @@ public class StackV2 { String attributeName = propertyAttribute.getKey(); String attributeValue = propertyAttribute.getValue(); if (attributeValue != null) { - Map<String, String> attributes = attributesMap.get(attributeName); - if (attributes == null) { - attributes = new HashMap<>(); - attributesMap.put(attributeName, attributes); - } + Map<String, String> attributes = getWithEmptyDefault(attributesMap, attributeName); attributes.put(propertyName, attributeValue); } } @@ -437,11 +360,7 @@ public class StackV2 { for (Map.Entry<String, String> propertyAttribute : propertyAttributes.entrySet()) { String attributeName = propertyAttribute.getKey(); String attributeValue = propertyAttribute.getValue(); - Map<String, String> attributes = attributesMap.get(attributeName); - if (attributes == null) { - attributes = new HashMap<>(); - attributesMap.put(attributeName, attributes); - } + Map<String, String> attributes = getWithEmptyDefault(attributesMap, attributeName); attributes.put(propertyName, attributeValue); } } @@ -550,11 +469,7 @@ public class StackV2 { for (String service : services) { Collection<String> serviceConfigTypes = getConfigurationTypes(service); for (String type : serviceConfigTypes) { - Map<String, String> typeProps = properties.get(type); - if (typeProps == null) { - typeProps = new HashMap<>(); - properties.put(type, typeProps); - } + Map<String, String> typeProps = getWithEmptyDefault(properties, type); typeProps.putAll(getConfigurationProperties(service, type)); Map<String, Map<String, String>> stackTypeAttributes = getConfigurationAttributes(service, type); @@ -565,11 +480,7 @@ public class StackV2 { Map<String, Map<String, String>> typeAttributes = attributes.get(type); for (Map.Entry<String, Map<String, String>> attribute : stackTypeAttributes.entrySet()) { String attributeName = attribute.getKey(); - Map<String, String> attributeProps = typeAttributes.get(attributeName); - if (attributeProps == null) { - attributeProps = new HashMap<>(); - typeAttributes.put(attributeName, attributeProps); - } + Map<String, String> attributeProps = getWithEmptyDefault(typeAttributes, attributeName); attributeProps.putAll(attribute.getValue()); } } @@ -584,11 +495,7 @@ public class StackV2 { for (String service : getServices()) { for (String type : getAllConfigurationTypes(service)) { - Map<String, String> typeProps = stackConfigs.get(type); - if (typeProps == null) { - typeProps = new HashMap<>(); - stackConfigs.put(type, typeProps); - } + Map<String, String> typeProps = getWithEmptyDefault(stackConfigs, type); typeProps.putAll(getConfigurationProperties(service, type)); Map<String, Map<String, String>> stackTypeAttributes = getConfigurationAttributes(service, type); @@ -599,11 +506,7 @@ public class StackV2 { Map<String, Map<String, String>> typeAttrs = stackAttributes.get(type); for (Map.Entry<String, Map<String, String>> attribute : stackTypeAttributes.entrySet()) { String attributeName = attribute.getKey(); - Map<String, String> attributes = typeAttrs.get(attributeName); - if (attributes == null) { - attributes = new HashMap<>(); - typeAttrs.put(attributeName, attributes); - } + Map<String, String> attributes = getWithEmptyDefault(typeAttrs, attributeName); attributes.putAll(attribute.getValue()); } } @@ -612,139 +515,15 @@ public class StackV2 { return new Configuration(stackConfigs, stackAttributes); } - /** - * Parse components for the specified service from the stack definition. - * - * @param service service name - * - * @throws AmbariException an exception occurred getting components from the stack definition - */ - private void parseComponents(String service) throws AmbariException{ - Collection<String> componentSet = new HashSet<>(); - - Set<StackServiceComponentResponse> components = controller.getStackComponents( - Collections.singleton(new StackServiceComponentRequest(name, version, service, null))); - - // stack service components - for (StackServiceComponentResponse component : components) { - String componentName = component.getComponentName(); - componentSet.add(componentName); - componentService.put(componentName, service); - String cardinality = component.getCardinality(); - if (cardinality != null) { - cardinalityRequirements.put(componentName, cardinality); - } - AutoDeployInfo autoDeploy = component.getAutoDeploy(); - if (autoDeploy != null) { - componentAutoDeployInfo.put(componentName, autoDeploy); - } - - // populate component dependencies - //todo: remove usage of AmbariMetaInfo - Collection<DependencyInfo> componentDependencies = controller.getAmbariMetaInfo().getComponentDependencies( - name, version, service, componentName); - - if (componentDependencies != null && ! componentDependencies.isEmpty()) { - dependencies.put(componentName, componentDependencies); - } - if (component.isMaster()) { - masterComponents.add(componentName); - } + static <OK, IK, IV> Map<IK, IV> getWithEmptyDefault(Map<OK, Map<IK, IV>> outerMap, OK outerKey) { + Map<IK, IV> innerMap = outerMap.get(outerKey); + if (null == innerMap) { + innerMap = new HashMap<>(); + outerMap.put(outerKey, innerMap); } - serviceComponents.put(service, componentSet); + return innerMap; } - /** - * Parse configurations for the specified service from the stack definition. - * - * @param stackService service to parse the stack configuration for - * - * @throws AmbariException an exception occurred getting configurations from the stack definition - */ - private void parseConfigurations(StackServiceResponse stackService) throws AmbariException { - String service = stackService.getServiceName(); - Map<String, Map<String, ConfigProperty>> mapServiceConfig = new HashMap<>(); - Map<String, Map<String, ConfigProperty>> mapRequiredServiceConfig = new HashMap<>(); - - - serviceConfigurations.put(service, mapServiceConfig); - requiredServiceConfigurations.put(service, mapRequiredServiceConfig); - - Set<StackConfigurationResponse> serviceConfigs = controller.getStackConfigurations( - Collections.singleton(new StackConfigurationRequest(name, version, service, null))); - Set<StackConfigurationResponse> stackLevelConfigs = controller.getStackLevelConfigurations( - Collections.singleton(new StackLevelConfigurationRequest(name, version, null))); - serviceConfigs.addAll(stackLevelConfigs); - - // shouldn't have any required properties in stack level configuration - for (StackConfigurationResponse config : serviceConfigs) { - ConfigProperty configProperty = new ConfigProperty(config); - String type = configProperty.getType(); - - Map<String, ConfigProperty> mapTypeConfig = mapServiceConfig.get(type); - if (mapTypeConfig == null) { - mapTypeConfig = new HashMap<>(); - mapServiceConfig.put(type, mapTypeConfig); - } - - mapTypeConfig.put(config.getPropertyName(), configProperty); - if (config.isRequired()) { - Map<String, ConfigProperty> requiredTypeConfig = mapRequiredServiceConfig.get(type); - if (requiredTypeConfig == null) { - requiredTypeConfig = new HashMap<>(); - mapRequiredServiceConfig.put(type, requiredTypeConfig); - } - requiredTypeConfig.put(config.getPropertyName(), configProperty); - } - } - - // So far we added only config types that have properties defined - // in stack service definition. Since there might be config types - // with no properties defined we need to add those separately - Set<String> configTypes = stackService.getConfigTypes().keySet(); - for (String configType: configTypes) { - if (!mapServiceConfig.containsKey(configType)) { - mapServiceConfig.put(configType, Collections.emptyMap()); - } - } - } - - private void parseStackConfigurations () throws AmbariException { - - Set<StackConfigurationResponse> stackLevelConfigs = controller.getStackLevelConfigurations( - Collections.singleton(new StackLevelConfigurationRequest(name, version, null))); - - for (StackConfigurationResponse config : stackLevelConfigs) { - ConfigProperty configProperty = new ConfigProperty(config); - String type = configProperty.getType(); - - Map<String, ConfigProperty> mapTypeConfig = stackConfigurations.get(type); - if (mapTypeConfig == null) { - mapTypeConfig = new HashMap<>(); - stackConfigurations.put(type, mapTypeConfig); - } - - mapTypeConfig.put(config.getPropertyName(), - configProperty); - } - } - - /** - * Obtain the excluded configuration types from the StackServiceResponse - * - * @param stackServiceResponse the response object associated with this stack service - */ - private void parseExcludedConfigurations(StackServiceResponse stackServiceResponse) { - excludedConfigurationTypes.put(stackServiceResponse.getServiceName(), stackServiceResponse.getExcludedConfigTypes()); - } - - /** - * Register conditional dependencies. - */ - //todo: This information should be specified in the stack definition. - void registerConditionalDependencies() { - dbDependencyInfo.put("MYSQL_SERVER", "global/hive_database"); - } /** * Contains a configuration property's value and attributes. http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java new file mode 100644 index 0000000..54e1e62 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java @@ -0,0 +1,219 @@ +/* + * 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; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.orm.entities.StackEntity; +import org.apache.ambari.server.state.AutoDeployInfo; +import org.apache.ambari.server.state.DependencyInfo; +import org.apache.ambari.server.state.StackId; + +public class StackV2Factory { + + private AmbariManagementController controller; + + public StackV2Factory(AmbariManagementController controller) { + this.controller = controller; + } + + public StackV2 create(StackEntity stack) throws AmbariException { + return create(stack.getStackName(), stack.getStackVersion()); + } + + public StackV2 create(String stackId) throws AmbariException { + StackId id = new StackId(stackId); + return create(id.getStackName(), id.getStackVersion()); + } + + public StackV2 create(String name, String version) throws AmbariException { + Set<StackServiceResponse> stackServices = controller.getStackServices( + Collections.singleton(new StackServiceRequest(name, version, null))); + + StackData stackData = new StackData(name, version); + for (StackServiceResponse stackService : stackServices) { + String serviceName = stackService.getServiceName(); + parseComponents(stackData, serviceName); + parseExcludedConfigurations(stackData, stackService); + parseConfigurations(stackData, stackService); + registerConditionalDependencies(stackData); + } + + //todo: already done for each service + parseStackConfigurations(stackData); + + return new StackV2(name, version, stackData.repoVersion /* TODO */, stackData.serviceComponents, stackData.dependencies, + stackData.dbDependencyInfo, stackData.componentAutoDeployInfo, stackData.serviceConfigurations, + stackData.requiredServiceConfigurations, stackData.stackConfigurations, stackData.excludedConfigurationTypes); + } + + /** + * Parse configurations for the specified service from the stack definition. + * + * @param stackService service to parse the stack configuration for + * + * @throws AmbariException an exception occurred getting configurations from the stack definition + */ + private void parseConfigurations(StackData stackData, + StackServiceResponse stackService) throws AmbariException { + String service = stackService.getServiceName(); + Map<String, Map<String, StackV2.ConfigProperty>> mapServiceConfig = new HashMap<>(); + Map<String, Map<String, StackV2.ConfigProperty>> mapRequiredServiceConfig = new HashMap<>(); + + stackData.serviceConfigurations.put(service, mapServiceConfig); + stackData.requiredServiceConfigurations.put(service, mapRequiredServiceConfig); + + Set<StackConfigurationResponse> serviceConfigs = controller.getStackConfigurations( + Collections.singleton(new StackConfigurationRequest(stackData.stackName, stackData.stackVersion, service, null))); + Set<StackConfigurationResponse> stackLevelConfigs = controller.getStackLevelConfigurations( + Collections.singleton(new StackLevelConfigurationRequest(stackData.stackName, stackData.stackVersion, null))); + serviceConfigs.addAll(stackLevelConfigs); + + // shouldn't have any required properties in stack level configuration + for (StackConfigurationResponse config : serviceConfigs) { + StackV2.ConfigProperty configProperty = new StackV2.ConfigProperty(config); + String type = configProperty.getType(); + + Map<String, StackV2.ConfigProperty> mapTypeConfig = StackV2.getWithEmptyDefault(mapServiceConfig, type); + + mapTypeConfig.put(config.getPropertyName(), configProperty); + if (config.isRequired()) { + Map<String, StackV2.ConfigProperty> requiredTypeConfig = + StackV2.getWithEmptyDefault(mapRequiredServiceConfig, type); + requiredTypeConfig.put(config.getPropertyName(), configProperty); + } + } + + // So far we added only config types that have properties defined + // in stack service definition. Since there might be config types + // with no properties defined we need to add those separately + Set<String> configTypes = stackService.getConfigTypes().keySet(); + for (String configType: configTypes) { + if (!mapServiceConfig.containsKey(configType)) { + mapServiceConfig.put(configType, Collections.emptyMap()); + } + } + } + + private void parseStackConfigurations (StackData stackData) throws AmbariException { + Set<StackConfigurationResponse> stackLevelConfigs = controller.getStackLevelConfigurations( + Collections.singleton(new StackLevelConfigurationRequest(stackData.stackName, stackData.stackVersion, null))); + + for (StackConfigurationResponse config : stackLevelConfigs) { + StackV2.ConfigProperty configProperty = new StackV2.ConfigProperty(config); + String type = configProperty.getType(); + + Map<String, StackV2.ConfigProperty> mapTypeConfig = + StackV2.getWithEmptyDefault(stackData.stackConfigurations, type); + + mapTypeConfig.put(config.getPropertyName(), + configProperty); + } + } + + /** + * Parse components for the specified service from the stack definition. + * + * @param service service name + * + * @throws AmbariException an exception occurred getting components from the stack definition + */ + private void parseComponents(StackData stackData, String service) throws AmbariException{ + Collection<String> componentSet = new HashSet<>(); + + Set<StackServiceComponentResponse> components = controller.getStackComponents( + Collections.singleton(new StackServiceComponentRequest(stackData.stackName, stackData.stackVersion, service, null))); + + // stack service components + for (StackServiceComponentResponse component : components) { + String componentName = component.getComponentName(); + componentSet.add(componentName); + stackData.componentService.put(componentName, service); + String cardinality = component.getCardinality(); + if (cardinality != null) { + stackData.cardinalityRequirements.put(componentName, cardinality); + } + AutoDeployInfo autoDeploy = component.getAutoDeploy(); + if (autoDeploy != null) { + stackData.componentAutoDeployInfo.put(componentName, autoDeploy); + } + + // populate component dependencies + //todo: remove usage of AmbariMetaInfo + Collection<DependencyInfo> componentDependencies = controller.getAmbariMetaInfo().getComponentDependencies( + stackData.stackName, stackData.stackVersion, service, componentName); + + if (componentDependencies != null && ! componentDependencies.isEmpty()) { + stackData.dependencies.put(componentName, componentDependencies); + } + if (component.isMaster()) { + stackData.masterComponents.add(componentName); + } + } + stackData.serviceComponents.put(service, componentSet); + } + + + /** + * Obtain the excluded configuration types from the StackServiceResponse + * + * @param stackServiceResponse the response object associated with this stack service + */ + private void parseExcludedConfigurations(StackData stackData, StackServiceResponse stackServiceResponse) { + stackData.excludedConfigurationTypes.put(stackServiceResponse.getServiceName(), stackServiceResponse.getExcludedConfigTypes()); + } + + /** + * Register conditional dependencies. + */ + //todo: This information should be specified in the stack definition. + void registerConditionalDependencies(StackData stackData) { + stackData.dbDependencyInfo.put("MYSQL_SERVER", "global/hive_database"); + } + + + private static final class StackData { + final String stackName; + final String stackVersion; + + public StackData(String stackName, String stackVersion) { + this.stackName = stackName; + this.stackVersion = stackVersion; + } + + String repoVersion; + final Map<String, String> componentService = new HashMap<>(); + final Set<String> masterComponents = new HashSet<>(); + final Map<String, AutoDeployInfo> componentAutoDeployInfo = new HashMap<>(); + final Map<String, String> cardinalityRequirements = new HashMap<>(); + final Map<String, Collection<DependencyInfo>> dependencies = new HashMap<>(); + final Map<String, Collection<String>> serviceComponents = new HashMap<>(); + final Map<String, Map<String, Map<String, StackV2.ConfigProperty>>> serviceConfigurations = new HashMap<>(); + final Map<String, Map<String, Map<String, StackV2.ConfigProperty>>> requiredServiceConfigurations = new HashMap<>(); + final Map<String, String> dbDependencyInfo = new HashMap<>(); + final Map<String, Set<String>> excludedConfigurationTypes = new HashMap<>(); + final Map<String, Map<String, StackV2.ConfigProperty>> stackConfigurations = new HashMap<>(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintV2DAO.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintV2DAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintV2DAO.java new file mode 100644 index 0000000..8a21dc1 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/BlueprintV2DAO.java @@ -0,0 +1,136 @@ +/* + * 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.orm.dao; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; + +import org.apache.ambari.server.orm.RequiresSession; +import org.apache.ambari.server.orm.entities.BlueprintV2Entity; +import org.apache.ambari.server.orm.entities.StackEntity; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import com.google.inject.persist.Transactional; + +/** + * Blueprint V2 Data Access Object. + */ +@Singleton +public class BlueprintV2DAO { + + /** + * JPA entity manager + */ + @Inject + Provider<EntityManager> entityManagerProvider; + + @Inject + StackDAO stackDAO; + + /** + * Find a blueprint with a given name. + * + * @param blueprint_name name of blueprint to find + * + * @return a matching blueprint or null + */ + @RequiresSession + public BlueprintV2Entity findByName(String blueprint_name) { + return entityManagerProvider.get().find(BlueprintV2Entity.class, blueprint_name); + } + + /** + * Find all blueprints. + * + * @return all blueprints or an empty List + */ + @RequiresSession + public List<BlueprintV2Entity> findAll() { + TypedQuery<BlueprintV2Entity> query = entityManagerProvider.get(). + createNamedQuery("allBlueprintsv2", BlueprintV2Entity.class); + return query.getResultList(); + } + + /** + * Refresh the state of the instance from the database, + * overwriting changes made to the entity, if any. + * + * @param blueprintEntity entity to refresh + */ + @Transactional + public void refresh(BlueprintV2Entity blueprintEntity) { + ensureStackIdSet(blueprintEntity); + entityManagerProvider.get().refresh(blueprintEntity); + } + + /** + * Make an instance managed and persistent. + * + * @param blueprintEntity entity to persist + */ + @Transactional + public void create(BlueprintV2Entity blueprintEntity) { + ensureStackIdSet(blueprintEntity); + entityManagerProvider.get().persist(blueprintEntity); + } + + /** + * Merge the state of the given entity into the current persistence context. + * + * @param blueprintEntity entity to merge + * @return the merged entity + */ + @Transactional + public BlueprintV2Entity merge(BlueprintV2Entity blueprintEntity) { + ensureStackIdSet(blueprintEntity); + return entityManagerProvider.get().merge(blueprintEntity); + } + + /** + * Remove the entity instance. + * + * @param blueprintEntity entity to remove + */ + @Transactional + public void remove(BlueprintV2Entity blueprintEntity) { + ensureStackIdSet(blueprintEntity); + entityManagerProvider.get().remove(merge(blueprintEntity)); + } + + /** + * Remove entity instance by primary key + * @param blueprint_name Primary key: blueprint name + */ + @Transactional + public void removeByName(String blueprint_name) { + entityManagerProvider.get().remove(findByName(blueprint_name)); + } + + private void ensureStackIdSet(BlueprintV2Entity entity) { + StackEntity stack = entity.getStack(); + if (stack != null && stack.getStackId() == null) { + entity.setStack(stackDAO.find(stack.getStackName(), stack.getStackVersion())); + } + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java index bab393a..8141f07 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java @@ -75,7 +75,6 @@ public class BlueprintEntity { @OneToMany(cascade = CascadeType.ALL, mappedBy = "blueprint") private Collection<BlueprintSettingEntity> settings; - /** * Get the blueprint name. * http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintV2Entity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintV2Entity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintV2Entity.java new file mode 100644 index 0000000..046c2e5 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintV2Entity.java @@ -0,0 +1,119 @@ +/* + * 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.orm.entities; + +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.NamedQuery; +import javax.persistence.OneToOne; +import javax.persistence.Table; + +import org.apache.ambari.server.state.SecurityType; + +/** + * Entity representing a Blueprint. + */ +@Table(name = "blueprintv2") +@NamedQuery(name = "allBlueprintsv2", + query = "SELECT blueprint FROM BlueprintV2Entity blueprint") +@Entity +public class BlueprintV2Entity { + + @Id + @Column(name = "blueprint_name", nullable = false, insertable = true, + updatable = false, unique = true, length = 100) + private String blueprintName; + + @Basic + @Enumerated(value = EnumType.STRING) + @Column(name = "security_type", nullable = false, insertable = true, updatable = true) + private SecurityType securityType = SecurityType.NONE; + + @Basic + @Column(name = "security_descriptor_reference", nullable = true, insertable = true, updatable = true) + private String securityDescriptorReference; + + @Basic + @Column(name = "content", nullable = false, insertable = true, updatable = true) + private String content; + + /** + * Unidirectional one-to-one association to {@link StackEntity} + */ + @OneToOne + @JoinColumn(name = "stack_id", unique = false, nullable = false, insertable = true, updatable = false) + private StackEntity stack; + + /** + * Gets the blueprint's stack. + * + * @return the stack. + */ + public StackEntity getStack() { + return stack; + } + + /** + * Sets the blueprint's stack. + * + * @param stack + * the stack to set for the blueprint (not {@code null}). + */ + public void setStack(StackEntity stack) { + this.stack = stack; + } + + + public String getBlueprintName() { + return blueprintName; + } + + public void setBlueprintName(String blueprintName) { + this.blueprintName = blueprintName; + } + + public SecurityType getSecurityType() { + return securityType; + } + + public void setSecurityType(SecurityType securityType) { + this.securityType = securityType; + } + + public String getSecurityDescriptorReference() { + return securityDescriptorReference; + } + + public void setSecurityDescriptorReference(String securityDescriptorReference) { + this.securityDescriptorReference = securityDescriptorReference; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java index 6b75df7..186180b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java @@ -44,9 +44,22 @@ public class HostGroupComponentEntity { private String blueprintName; @Id - @Column(name = "name", nullable = false, insertable = true, updatable = false) + @Column(name = "service_group", nullable = true, insertable = true, updatable = false) + private String serviceGroup; + + @Id + @Column(name = "service_name", nullable = true, insertable = true, updatable = false) + private String serviceName; + + @Id + @Column(name = "instance_name", nullable = true, insertable = true, updatable = false) private String name; + + @Id + @Column(name = "type", nullable = false, insertable = true, updatable = false) + private String type; + @Column(name = "provision_action", nullable = true, insertable = true, updatable = false) private String provisionAction; @@ -130,6 +143,8 @@ public class HostGroupComponentEntity { this.blueprintName = blueprintName; } + + /** * Get the provision action associated with this * component. http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StackEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StackEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StackEntity.java index bee53b6..c479cdd 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StackEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StackEntity.java @@ -60,11 +60,12 @@ public class StackEntity { @Column(name = "stack_version", length = 255, nullable = false) private String stackVersion; + @Column(name = "repo_version", length = 255, nullable = false) + private String repoVersion; @Column(name = "current_mpack_id") private Long currentMpackId; - public Long getCurrentMpackId() { return currentMpackId; } @@ -127,6 +128,14 @@ public class StackEntity { this.stackVersion = stackVersion; } + public String getRepoVersion() { + return repoVersion; + } + + public void setRepoVersion(String repoVersion) { + this.repoVersion = repoVersion; + } + /** * */ http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java index 9bde795..776cb4a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java @@ -19,116 +19,296 @@ package org.apache.ambari.server.topology; +import java.io.File; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.annotation.Nonnull; import org.apache.ambari.server.controller.StackV2; import org.apache.ambari.server.orm.entities.BlueprintEntity; +import org.apache.ambari.server.state.ConfigHelper; +import org.apache.ambari.server.state.StackId; +import org.apache.commons.lang.StringUtils; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; +import com.fasterxml.jackson.databind.module.SimpleModule; /** * Blueprint implementation. */ public class BlueprintImplV2 implements BlueprintV2 { + private String name; + private SecurityConfiguration securityConfiguration; + private Collection<RepositoryVersion> repositoryVersions; + private Collection<ServiceGroup> serviceGroups; + private Collection<? extends HostGroupV2> hostGroups; + private Setting setting; + + // Transient fields + @JsonIgnore + private Map<String, HostGroupV2> hostGroupMap = new HashMap<>(); + + + @JsonIgnore + private Map<StackId, StackV2> stacks; + + @JsonIgnore + private List<RepositorySetting> repoSettings; + + public void setStacks(Map<StackId, StackV2> stacks) { + this.stacks = stacks; + } + + @JsonProperty("Blueprints") + public void setBlueprints(Blueprints blueprints) { + this.name = blueprints.name; + this.securityConfiguration = blueprints.securityConfiguration; + } + + public void setName(String name) { + this.name = name; + } + + public void setSecurityConfiguration(SecurityConfiguration securityConfiguration) { + this.securityConfiguration = securityConfiguration; + } + + @JsonProperty("repository_versions") + public void setRepositoryVersions(Collection<RepositoryVersion> repositoryVersions) { + this.repositoryVersions = repositoryVersions; + } + + @JsonProperty("service_groups") + public void setServiceGroups(Collection<ServiceGroup> serviceGroups) { + this.serviceGroups = serviceGroups; + } + + @JsonProperty("host_groups") + public void setHostGroups(Collection<HostGroupV2Impl> hostGroups) { + this.hostGroups = hostGroups; + this.hostGroupMap = hostGroups.stream().collect(Collectors.toMap( + hg -> hg.getName(), + hg -> hg + )); + } + + @JsonProperty("cluster-settings") + public void setClusterSettings(Map<String, Set<HashMap<String, String>>> properties) { + this.setting = new Setting(properties); + } @Override public String getName() { - return null; + return name; } @Override public HostGroupV2 getHostGroup(String name) { - return null; + return hostGroupMap.get(name); } @Override public Map<String, HostGroupV2> getHostGroups() { - return null; + return hostGroupMap; } @Override public Collection<StackV2> getStacks() { - return null; + return stacks.values(); + } + + @Override + public Collection<String> getStackIds() { + return repositoryVersions.stream().map(rv -> rv.getStackId()).collect(Collectors.toList()); } @Override public Collection<ServiceGroup> getServiceGroups() { - return null; + return serviceGroups; } @Override - public Collection<Service> getAllServices() { - return null; + @JsonIgnore + public Collection<ServiceId> getAllServices() { + return hostGroups.stream().flatMap(hg -> hg.getServices().stream()).collect(Collectors.toSet()); } @Override - public Collection<ComponentV2> getComponents(Service service) { - return null; + @JsonIgnore + public Collection<ComponentV2> getComponents(ServiceId serviceId) { + return getHostGroupsForService(serviceId).stream().flatMap(hg -> hg.getComponents().stream()).collect(Collectors.toSet()); } @Override - public Collection<HostGroupV2> getHostGroupsForService(Service service) { - return null; + @JsonIgnore + public Collection<HostGroupV2> getHostGroupsForService(ServiceId serviceId) { + return hostGroups.stream().filter(hg -> !hg.getComponents(serviceId).isEmpty()).collect(Collectors.toList()); } @Override + @JsonIgnore public Collection<HostGroupV2> getHostGroupsForComponent(ComponentV2 component) { - return null; + return hostGroups.stream().filter(hg -> hg.getComponents().contains(component)).collect(Collectors.toList()); } @Override - public Configuration getConfiguration() { - return null; + public Setting getSetting() { + return this.setting; } + @Nonnull @Override - public Setting getSetting() { - return null; + @JsonIgnore + public Collection<String> getAllServiceNames() { + return getAllServices().stream().map(s -> s.getName()).collect(Collectors.toList()); } + @Nonnull @Override - public String getRecoveryEnabled(String serviceName, String componentName) { - return null; + public Collection<String> getComponentNames(ServiceId serviceId) { + return getComponents(serviceId).stream().map(c -> c.getName()).collect(Collectors.toList()); } @Override - public String getCredentialStoreEnabled(String serviceName) { + public String getRecoveryEnabled(String serviceName, String componentName) { + // If component name was specified in the list of "component_settings", + // determine if recovery_enabled is true or false and return it. + Optional<String> recoveryEnabled = getSettingValue(Setting.SETTING_NAME_COMPONENT_SETTINGS, + Setting.SETTING_NAME_RECOVERY_ENABLED, + Optional.of(componentName)); + if (recoveryEnabled.isPresent()) { + return recoveryEnabled.get(); + } + + // If component name was specified in the list of "component_settings", + // determine if recovery_enabled is true or false and return it. + recoveryEnabled = getSettingValue(Setting.SETTING_NAME_SERVICE_SETTINGS, + Setting.SETTING_NAME_RECOVERY_ENABLED, + Optional.of(serviceName)); + if (recoveryEnabled.isPresent()) { + return recoveryEnabled.get(); + } + + // If service name is not specified, look up the cluster setting. + recoveryEnabled = getSettingValue(Setting.SETTING_NAME_RECOVERY_SETTINGS, + Setting.SETTING_NAME_RECOVERY_ENABLED, + Optional.empty()); + if (recoveryEnabled.isPresent()) { + return recoveryEnabled.get(); + } + return null; } - @Override - public boolean shouldSkipFailure() { - return false; + private Optional<String> getSettingValue(String settingCategory, String settingName, Optional<String> nameFilter) { + if (this.setting != null) { + Set<HashMap<String, String>> settingValue = this.setting.getSettingValue(settingCategory); + for (Map<String, String> setting : settingValue) { + String name = setting.get(Setting.SETTING_NAME_NAME); + if (!nameFilter.isPresent() || StringUtils.equals(name, nameFilter.get())) { + String value = setting.get(settingName); + if (!StringUtils.isEmpty(value)) { + return Optional.of(value); + } + } + } + } + return Optional.empty(); } @Override - public SecurityConfiguration getSecurity() { - return null; + public String getCredentialStoreEnabled(String serviceName) { + // Look up the service and return the credential_store_enabled value. + Optional<String> credentialStoreEnabled = getSettingValue(Setting.SETTING_NAME_SERVICE_SETTINGS, + Setting.SETTING_NAME_CREDENTIAL_STORE_ENABLED, + Optional.of(serviceName)); + return credentialStoreEnabled.isPresent() ? credentialStoreEnabled.get() : null; } @Override - public void validateTopology() throws InvalidTopologyException { - + public boolean shouldSkipFailure() { + Optional<String> shouldSkipFailure = getSettingValue(Setting.SETTING_NAME_DEPLOYMENT_SETTINGS, + Setting.SETTING_NAME_SKIP_FAILURE, + Optional.empty()); + return shouldSkipFailure.isPresent() ? shouldSkipFailure.get().equalsIgnoreCase("true") : false; } @Override - public void validateRequiredProperties() throws InvalidTopologyException { - + public SecurityConfiguration getSecurity() { + return this.securityConfiguration; } + @Override public boolean isValidConfigType(String configType) { - return false; + if (ConfigHelper.CLUSTER_ENV.equals(configType) || "global".equals(configType)) { + return true; + } + final Set<String> serviceNames = + getAllServices().stream().map(s -> s.getName()).collect(Collectors.toSet()); + return getStacks().stream().anyMatch( + stack -> { + String service = stack.getServiceForConfigType(configType); + return serviceNames.contains(service); + } + ); } @Override public BlueprintEntity toEntity() { - return null; + throw new UnsupportedOperationException("This is not supported here and will be removed. Pls. use BlueprintConverter"); } @Override public List<RepositorySetting> getRepositorySettings() { - return null; + return repoSettings; + } + + /** + * Class to support Jackson data binding. Instances are used only temporarily during serialization + */ + public class Blueprints { + @JsonProperty("blueprint_name") + public String name; + @JsonProperty("security") + public SecurityConfiguration securityConfiguration; + + public Blueprints() { } } + + public static void main(String[] args) throws Exception { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("CustomModel", Version.unknownVersion()); + SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver(); + resolver.addMapping(HostGroupV2.class, HostGroupV2Impl.class); + module.setAbstractTypes(resolver); + mapper.registerModule(module); + mapper.enable(SerializationFeature.INDENT_OUTPUT); + BlueprintImplV2 bp = mapper.readValue(new File("/Users/bsari/develop/blueprints/blueprintv2.json"), BlueprintImplV2.class); + String bpJson = mapper.writeValueAsString(bp); + System.out.println(bpJson); + System.out.println("\n\n====================================================================================\n\n"); + Map<String, Object> map = mapper.readValue(new File("/Users/bsari/develop/blueprints/blueprintv2.json"), HashMap.class); + System.out.println(map); + System.out.println("\n\n====================================================================================\n\n"); + String bpJson2 = mapper.writeValueAsString(map); + System.out.println(bpJson2); + System.out.println("\n\n====================================================================================\n\n"); + BlueprintImplV2 bp2 = mapper.readValue(bpJson2, BlueprintImplV2.class); + System.out.println(bp2); + } + + } http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java index 1fea966..4688f30 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java @@ -22,6 +22,8 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import javax.annotation.Nonnull; + import org.apache.ambari.server.controller.StackV2; import org.apache.ambari.server.orm.entities.BlueprintEntity; @@ -59,6 +61,10 @@ public interface BlueprintV2 { */ Collection<StackV2> getStacks(); + /** + * @return associated stack ids + **/ + public Collection<String> getStackIds(); Collection<ServiceGroup> getServiceGroups(); @@ -67,27 +73,47 @@ public interface BlueprintV2 { * * @return collection of all represented service names */ - Collection<Service> getAllServices(); + Collection<ServiceId> getAllServices(); + + /** + * Get the names of all the services represented in the blueprint. + * + * @return collection of all represented service names + */ + @Nonnull + Collection<String> getAllServiceNames(); + /** * Get the components that are included in the blueprint for the specified service. * - * @param service service name + * @param serviceId serviceId * * @return collection of component names for the service. Will not return null. */ - Collection<ComponentV2> getComponents(Service service); + @Nonnull + Collection<String> getComponentNames(ServiceId serviceId); + + /** + * Get the component names s that are included in the blueprint for the specified service. + * + * @param serviceId serviceId + * + * @return collection of component names for the service. Will not return null. + */ + Collection<ComponentV2> getComponents(ServiceId serviceId); + /** * Get the host groups which contain components for the specified service. * - * @param service service name + * @param serviceId service Id * * @return collection of host groups containing components for the specified service; * will not return null */ - Collection<HostGroupV2> getHostGroupsForService(Service service); + Collection<HostGroupV2> getHostGroupsForService(ServiceId serviceId); /** * Get the host groups which contain the give component. @@ -98,15 +124,6 @@ public interface BlueprintV2 { */ Collection<HostGroupV2> getHostGroupsForComponent(ComponentV2 component); - /** - * Get the Blueprint cluster scoped configuration. - * The blueprint cluster scoped configuration has the stack - * configuration with the config types associated with the blueprint - * set as it's parent. - * - * @return blueprint cluster scoped configuration - */ - Configuration getConfiguration(); /** * Get the Blueprint cluster scoped setting. @@ -146,19 +163,6 @@ public interface BlueprintV2 { SecurityConfiguration getSecurity(); - /** - * Validate the blueprint topology. - * - * @throws InvalidTopologyException if the topology is invalid - */ - void validateTopology() throws InvalidTopologyException; - - /** - * Validate that the blueprint contains all of the required properties. - * - * @throws InvalidTopologyException if the blueprint doesn't contain all required properties - */ - void validateRequiredProperties() throws InvalidTopologyException; /** * http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java new file mode 100644 index 0000000..a8c5b4c --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java @@ -0,0 +1,170 @@ +/* + * 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 distribut + * ed 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.topology; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.ObjectNotFoundException; +import org.apache.ambari.server.StackAccessException; +import org.apache.ambari.server.controller.StackV2; +import org.apache.ambari.server.controller.StackV2Factory; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.apache.ambari.server.orm.dao.BlueprintV2DAO; +import org.apache.ambari.server.orm.dao.StackDAO; +import org.apache.ambari.server.orm.entities.BlueprintV2Entity; +import org.apache.ambari.server.orm.entities.StackEntity; +import org.apache.ambari.server.stack.NoSuchStackException; +import org.apache.ambari.server.state.StackId; + +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.google.inject.Inject; + +public class BlueprintV2Factory { + // Blueprints + protected static final String BLUEPRINT_NAME_PROPERTY_ID = + PropertyHelper.getPropertyId("Blueprints", "blueprint_name"); + protected static final String STACK_NAME_PROPERTY_ID = + PropertyHelper.getPropertyId("Blueprints", "stack_name"); + protected static final String STACK_VERSION_PROPERTY_ID = + PropertyHelper.getPropertyId("Blueprints", "stack_version"); + + // Host Groups + protected static final String HOST_GROUP_PROPERTY_ID = "host_groups"; + protected static final String HOST_GROUP_NAME_PROPERTY_ID = "name"; + protected static final String HOST_GROUP_CARDINALITY_PROPERTY_ID = "cardinality"; + + // Host Group Components + protected static final String COMPONENT_PROPERTY_ID ="components"; + protected static final String COMPONENT_NAME_PROPERTY_ID ="name"; + protected static final String COMPONENT_PROVISION_ACTION_PROPERTY_ID = "provision_action"; + + // Configurations + protected static final String CONFIGURATION_PROPERTY_ID = "configurations"; + protected static final String PROPERTIES_PROPERTY_ID = "properties"; + protected static final String PROPERTIES_ATTRIBUTES_PROPERTY_ID = "properties_attributes"; + + protected static final String SETTINGS_PROPERTY_ID = "settings"; + + private static BlueprintV2DAO blueprintDAO; + private static StackDAO stackDao; + private ConfigurationFactory configFactory = new ConfigurationFactory(); + + private final StackV2Factory stackFactory; + + protected BlueprintV2Factory(StackV2Factory stackFactory) { + this.stackFactory = stackFactory; + } + + public BlueprintV2 getBlueprint(String blueprintName) throws NoSuchStackException, NoSuchBlueprintException, IOException { + BlueprintV2Entity entity = + Optional.ofNullable(blueprintDAO.findByName(blueprintName)).orElseThrow(() -> new NoSuchBlueprintException(blueprintName)); + return convertFromEntity(entity); + } + + public BlueprintV2 convertFromEntity(BlueprintV2Entity blueprintEntity) throws NoSuchStackException, IOException { + BlueprintImplV2 blueprintV2 = createObjectMapper().readValue(blueprintEntity.getContent(), BlueprintImplV2.class); + Map<StackId, StackV2> stacks = new HashMap<>(); + for (String stackIdString: blueprintV2.getStackIds()) { + StackId stackId = new StackId(stackIdString); + stacks.put(stackId, parseStack(stackDao.find(stackId))); + } + blueprintV2.setStacks(stacks); + return blueprintV2; + } + + + private StackV2 parseStack(StackEntity stackEntity) throws NoSuchStackException { + try { + return stackFactory.create(stackEntity.getStackName(), stackEntity.getStackVersion()); + } catch (StackAccessException e) { + throw new NoSuchStackException(stackEntity.getStackName(), stackEntity.getStackVersion()); + } catch (AmbariException e) { + //todo: + throw new RuntimeException("An error occurred parsing the stack information.", e); + } + } + + /** + * Convert a map of properties to a blueprint entity. + * + * @param properties property map + * @param securityConfiguration security related properties + * @return new blueprint entity + */ + @SuppressWarnings("unchecked") + public BlueprintV2 createBlueprint(Map<String, Object> properties, SecurityConfiguration securityConfiguration) throws NoSuchStackException, IOException { + String name = String.valueOf(properties.get(BLUEPRINT_NAME_PROPERTY_ID)); + // String.valueOf() will return "null" if value is null + if (name.equals("null") || name.isEmpty()) { + //todo: should throw a checked exception from here + throw new IllegalArgumentException("Blueprint name must be provided"); + } + ObjectMapper om = createObjectMapper(); + String json = om.writeValueAsString(properties); + BlueprintImplV2 blueprint = om.readValue(json, BlueprintImplV2.class); + Map<String, StackV2> stacks = new HashMap<>(); + for (String stackId: blueprint.getStackIds()) { + stacks.put(stackId, stackFactory.create(stackId)); + } + blueprint.setSecurityConfiguration(securityConfiguration); + return blueprint; + } + + protected StackV2 createStack(Map<String, Object> properties) throws NoSuchStackException { + String stackName = String.valueOf(properties.get(STACK_NAME_PROPERTY_ID)); + String stackVersion = String.valueOf(properties.get(STACK_VERSION_PROPERTY_ID)); + try { + //todo: don't pass in controller + return stackFactory.create(stackName, stackVersion); + } catch (ObjectNotFoundException e) { + throw new NoSuchStackException(stackName, stackVersion); + } catch (AmbariException e) { + //todo: + throw new RuntimeException("An error occurred parsing the stack information.", e); + } + } + + static ObjectMapper createObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("CustomModel", Version.unknownVersion()); + SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver(); + resolver.addMapping(HostGroupV2.class, HostGroupV2Impl.class); + module.setAbstractTypes(resolver); + mapper.registerModule(module); + return mapper; + } + + /** + * Static initialization. + * + * @param dao blueprint data access object + */ + @Inject + public static void init(BlueprintV2DAO dao) { + blueprintDAO = dao; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorV2.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorV2.java new file mode 100644 index 0000000..cfe083e --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorV2.java @@ -0,0 +1,43 @@ +/* + * 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 distribut + * ed 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.topology; + +public interface BlueprintValidatorV2 { + + /** + * Validate blueprint topology. + * + * @param blueprint The blueprint to validate + * + * @throws InvalidTopologyException if the topology is invalid + */ + void validateTopology(BlueprintV2 blueprint) throws InvalidTopologyException; + + /** + * Validate that required properties are provided. + * This doesn't include password properties. + * + * @param blueprint The blueprint to validate + * + * @throws InvalidTopologyException if required properties are not set in blueprint + */ + void validateRequiredProperties(BlueprintV2 blueprint) throws InvalidTopologyException; + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java index 175fe99..43dda1b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java @@ -18,30 +18,28 @@ package org.apache.ambari.server.topology; - +import org.apache.ambari.server.controller.StackV2; import org.apache.ambari.server.controller.internal.ProvisionAction; -public class ComponentV2 { +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; - private final String name; +public class ComponentV2 implements Configurable { - private final Service service; + private String type; - private final ProvisionAction provisionAction; + private String name; - private final Configuration configuration; + private ServiceId serviceId = new ServiceId(); + private ProvisionAction provisionAction = ProvisionAction.INSTALL_AND_START; - public ComponentV2(String name, Service service) { - this(name, service, null, null); - } + private Configuration configuration; + + private boolean masterComponent = false; + + public ComponentV2() { } - public ComponentV2(String name, Service service, ProvisionAction provisionAction, Configuration configuration) { - this.name = name; - this.service = service; - this.provisionAction = provisionAction; - this.configuration = configuration; - } /** * Gets the name of this component @@ -52,6 +50,11 @@ public class ComponentV2 { return this.name; } + /** @return the masterComponent flag */ + public boolean isMasterComponent() { + return masterComponent; + } + /** * Gets the provision action associated with this component. * @@ -62,11 +65,59 @@ public class ComponentV2 { return this.provisionAction; } - public Service getService() { - return service; + public ServiceId getServiceId() { + return serviceId; } public Configuration getConfiguration() { return configuration; } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + if (null == this.name) { + this.name = type; + } + } + + public void setName(String name) { + this.name = name; + } + + public String getServiceGroup() { + return serviceId.getServiceGroup(); + } + + @JsonProperty("service_group") + public void setServiceGroup(String serviceGroup) { + serviceId.setServiceGroup(serviceGroup); + } + + @JsonProperty("service_name") + public void setServiceName(String serviceName) { + serviceId.setName(serviceName); + } + + public String getServiceName() { + return serviceId.getName(); + } + + @JsonProperty("provision_action") + public void setProvisionAction(ProvisionAction provisionAction) { + this.provisionAction = provisionAction; + } + + public void setConfiguration(Configuration configuration) { + this.configuration = configuration; + } + + @JsonIgnore + public void setMasterComponent(StackV2 stack) { + this.masterComponent = stack.isMasterComponent(this.type); + } + } http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/Configurable.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Configurable.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Configurable.java new file mode 100644 index 0000000..74308ab --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Configurable.java @@ -0,0 +1,40 @@ +/* + * 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.topology; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public interface Configurable { + void setConfiguration(Configuration configuration); + + @JsonProperty("configurations") + default void setConfigs(Collection<Map<String, Map<String, Map<String, String>>>> configs) { + Map<String, Map<String, String>> allProps = configs.stream().collect(Collectors.toMap( + config -> config.keySet().iterator().next(), + config -> config.values().iterator().next().get("properties") + )); + setConfiguration(new Configuration(allProps, new HashMap<>())); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/Configuration.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Configuration.java index 28b62bc..28dbbaa 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/Configuration.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Configuration.java @@ -24,6 +24,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import com.fasterxml.jackson.annotation.JsonIgnore; + /** * Configuration for a topology entity such as a blueprint, hostgroup or cluster. */ @@ -98,6 +100,7 @@ public class Configuration { * * @return complete map of merged properties keyed by config type */ + @JsonIgnore public Map<String, Map<String, String>> getFullProperties() { return getFullProperties(Integer.MAX_VALUE); } @@ -113,6 +116,7 @@ public class Configuration { * * @return map of merged properties keyed by config type */ + @JsonIgnore public Map<String, Map<String, String>> getFullProperties(int depthLimit) { if (depthLimit == 0) { HashMap<String, Map<String, String>> propertiesCopy = new HashMap<>(); @@ -156,6 +160,7 @@ public class Configuration { * * @return complete map of merged attributes {configType -> {attributeName -> {propName, attributeValue}}} */ + @JsonIgnore public Map<String, Map<String, Map<String, String>>> getFullAttributes() { Map<String, Map<String, Map<String, String>>> mergedAttributeMap = parentConfiguration == null ? new HashMap<>() : @@ -314,6 +319,7 @@ public class Configuration { * * @return collection of all represented configuration types */ + @JsonIgnore public Collection<String> getAllConfigTypes() { Collection<String> allTypes = new HashSet<>(); for (String type : getFullProperties().keySet()) { @@ -332,6 +338,7 @@ public class Configuration { * * @return the parent configuration or null if no parent is set */ + @JsonIgnore public Configuration getParentConfiguration() { return parentConfiguration; } http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupImpl.java index 9aeadd1..9d3a1b8 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupImpl.java @@ -255,8 +255,6 @@ public class HostGroupImpl implements HostGroup { } else { addComponent(componentEntity.getName()); } - - } } http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2.java index df26b68..7a91770 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2.java @@ -83,11 +83,11 @@ public interface HostGroupV2 { /** * Get the host group components which belong to the specified service. * - * @param service service name + * @param serviceId service id * * @return collection of component names for the specified service; will not return null */ - Collection<ComponentV2> getComponents(Service service); + Collection<ComponentV2> getComponents(ServiceId serviceId); /** * Determine if the host group contains a master component. @@ -97,11 +97,14 @@ public interface HostGroupV2 { boolean containsMasterComponent(); /** - * Get all of the services associated with the host group components. - * - * @return collection of service names + * @return collection of service ids associated with the host group components. + */ + Collection<ServiceId> getServices(); + + /** + * @return collection of service names associated with the host group components. */ - Collection<Service> getServices(); + Collection<String> getServiceNames(); /** * Get the configuration associated with the host group. http://git-wip-us.apache.org/repos/asf/ambari/blob/b45710fb/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java new file mode 100644 index 0000000..351351b --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java @@ -0,0 +1,124 @@ +package org.apache.ambari.server.topology; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import javax.annotation.Nullable; + +import org.apache.ambari.server.controller.internal.ProvisionAction; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.google.common.base.Function; +import com.google.common.base.Predicates; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +public class HostGroupV2Impl implements HostGroupV2, Configurable { + + private String name; + private String blueprintName; + private List<ComponentV2> components; + private List<ServiceId> services; + private Configuration configuration; + private String cardinality; + private boolean containsMasterComponent; + + public HostGroupV2Impl() { } + + @Override + public String getName() { + return name; + } + + @Override + public String getBlueprintName() { + return blueprintName; + } + + @Override + public String getFullyQualifiedName() { + return blueprintName + ":" + name; + } + + @Override + public Collection<ComponentV2> getComponents() { + return components; + } + + @Override + public Collection<String> getComponentNames() { + return getComponentNames(components); + } + + private Collection<String> getComponentNames(List<ComponentV2> components) { + return Lists.transform(components, + new Function<ComponentV2, String>() { + @Override public String apply(@Nullable ComponentV2 input) { return input.getName(); } + }); + } + + @Override + public Collection<String> getComponentNames(ProvisionAction provisionAction) { + List<ComponentV2> filtered = + ImmutableList.copyOf(Collections2.filter(components, Predicates.equalTo(provisionAction))); + return getComponentNames(filtered); + } + + @Override + public Collection<ComponentV2> getComponents(ServiceId serviceId) { + return components.stream().filter(c -> c.getServiceId().equals(serviceId)).collect(Collectors.toList()); + } + + @Override + public boolean containsMasterComponent() { + return containsMasterComponent; + } + + @Override + @JsonIgnore + public Collection<ServiceId> getServices() { + return services; + } + + @Override + @JsonIgnore + public Collection<String> getServiceNames() { + return services.stream().map(s -> s.getName()).collect(Collectors.toList()); + } + + @Override + public Configuration getConfiguration() { + return configuration; + } + + @Override + public String getCardinality() { + return cardinality; + } + + public void setName(String name) { + this.name = name; + } + + public void setBlueprintName(String blueprintName) { + this.blueprintName = blueprintName; + } + + public void setComponents(List<ComponentV2> components) { + this.components = components; + this.containsMasterComponent = components.stream().anyMatch(c -> c.isMasterComponent()); + this.services = components.stream().map(c -> c.getServiceId()).collect(Collectors.toList()); + } + + public void setConfiguration(Configuration configuration) { + this.configuration = configuration; + } + + public void setCardinality(String cardinality) { + this.cardinality = cardinality; + } + +} +