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/f82497d4 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f82497d4 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f82497d4 Branch: refs/heads/branch-feature-AMBARI-14714-ui Commit: f82497d4d5c8d96dbf5629578a0205de0807e422 Parents: 17e4330 Author: Balazs Bence Sari <beny...@apache.org> Authored: Wed Oct 18 17:39:59 2017 +0200 Committer: Sandor Magyari <smagy...@hortonworks.com> Committed: Thu Oct 19 14:30:14 2017 +0200 ---------------------------------------------------------------------- .../ambari/server/controller/StackV2.java | 605 +++++++++++++++++++ .../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 | 256 +++++++- .../ambari/server/topology/BlueprintV2.java | 55 +- .../server/topology/BlueprintV2Factory.java | 170 ++++++ .../server/topology/BlueprintValidatorV2.java | 43 ++ .../ambari/server/topology/ComponentV2.java | 88 ++- .../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 | 85 +-- .../ambari/server/topology/ServiceGroup.java | 42 +- .../ambari/server/topology/ServiceId.java | 52 ++ .../validators/BlueprintImplV2Test.java | 9 + 23 files changed, 2034 insertions(+), 140 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/f82497d4/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 new file mode 100644 index 0000000..8d7de5d --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2.java @@ -0,0 +1,605 @@ +/* + * 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.state.AutoDeployInfo; +import org.apache.ambari.server.state.DependencyInfo; +import org.apache.ambari.server.state.PropertyDependencyInfo; +import org.apache.ambari.server.state.PropertyInfo; +import org.apache.ambari.server.state.ValueAttributesInfo; +import org.apache.ambari.server.topology.Cardinality; +import org.apache.ambari.server.topology.Configuration; + +/** + * Encapsulates stack information. + */ +public class StackV2 { + + /** Stack name */ + private final String name; + + /** Stack version */ + private final String version; + + /** Repo version */ + private final String repoVersion; + + /** Map of service name to components */ + private final Map<String, Collection<String>> serviceComponents; + + /** Map of component to service */ + private final Map<String, String> componentService; + + /** 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 + * the database in to be managed or if it is an external non-managed instance. + * If the value of the config property starts with 'New', the database is determined + * to be managed, otherwise it is non-managed. + */ + private final Map<String, String> dbDependencyInfo; + + /** 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 final Map<String, AutoDeployInfo> componentAutoDeployInfo; + + /** Map of service to config type properties */ + private final Map<String, Map<String, Map<String, ConfigProperty>>> serviceConfigurations; + + /** 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; + + /** Map of service to set of excluded config types */ + private final Map<String, Set<String>> excludedConfigurationTypes; + + 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.repoVersion = repoVersion; + + 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()); + } + } + + 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()); + } + } + + this.dbDependencyInfo = dbDependencyInfo; + this.componentAutoDeployInfo = componentAutoDeployInfo; + this.serviceConfigurations = serviceConfigurations; + this.requiredServiceConfigurations = requiredServiceConfigurations; + this.stackConfigurations = stackConfigurations; + this.excludedConfigurationTypes = excludedConfigurationTypes; + } + + /** @return stack name */ + public String getName() { + return name; + } + + /** @return stack version */ + public String getVersion() { + return version; + } + + /** @return repo version */ + public String getRepoVersion() { return repoVersion; } + + Map<DependencyInfo, String> getDependencyConditionalServiceMap() { + return dependencyConditionalServiceMap; + } + + /** @return collection of all services for the stack */ + public Collection<String> getServices() { + return serviceComponents.keySet(); + } + + /** + * 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); + } + + /** @return map of service to associated components */ + public Map<String, Collection<String>> getComponents() { + 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 +// */ +// @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. + * + * @param service service name + * + * @return collection of all configuration types for the specified service + */ + public Collection<String> getAllConfigurationTypes(String service) { + return serviceConfigurations.get(service).keySet(); + } + + /** + * Get configuration types for the specified service. + * This doesn't include any service excluded types. + * + * @param service service name + * + * @return collection of all configuration types for the specified service + */ + public Collection<String> getConfigurationTypes(String service) { + Set<String> serviceTypes = new HashSet<>(serviceConfigurations.get(service).keySet()); + serviceTypes.removeAll(getExcludedConfigurationTypes(service)); + return serviceTypes; + } + + /** + * Get the set of excluded configuration types for this service. + * + * @param service service name + * + * @return Set of names of excluded config types. Will not return null. + */ + public Set<String> getExcludedConfigurationTypes(String service) { + return excludedConfigurationTypes.containsKey(service) ? + excludedConfigurationTypes.get(service) : + Collections.emptySet(); + } + + /** + * Get config properties for the specified service and configuration type. + * + * @param service service name + * @param type configuration type + * + * @return map of property names to values for the specified service and configuration type + */ + public Map<String, String> getConfigurationProperties(String service, String type) { + Map<String, String> configMap = new HashMap<>(); + Map<String, ConfigProperty> configProperties = serviceConfigurations.get(service).get(type); + if (configProperties != null) { + for (Map.Entry<String, ConfigProperty> configProperty : configProperties.entrySet()) { + configMap.put(configProperty.getKey(), configProperty.getValue().getValue()); + } + } + return configMap; + } + + public Map<String, ConfigProperty> getConfigurationPropertiesWithMetadata(String service, String type) { + return serviceConfigurations.get(service).get(type); + } + + /** + * Get all required config properties for the specified service. + * + * @param service service name + * + * @return collection of all required properties for the given service + */ + public Collection<ConfigProperty> getRequiredConfigurationProperties(String service) { + Collection<ConfigProperty> requiredConfigProperties = new HashSet<>(); + Map<String, Map<String, ConfigProperty>> serviceProperties = requiredServiceConfigurations.get(service); + if (serviceProperties != null) { + for (Map.Entry<String, Map<String, ConfigProperty>> typePropertiesEntry : serviceProperties.entrySet()) { + requiredConfigProperties.addAll(typePropertiesEntry.getValue().values()); + } + } + return requiredConfigProperties; + } + + /** + * Get required config properties for the specified service which belong to the specified property type. + * + * @param service service name + * @param propertyType property type + * + * @return collection of required properties for the given service and property type + */ + public Collection<ConfigProperty> getRequiredConfigurationProperties(String service, PropertyInfo.PropertyType propertyType) { + Collection<ConfigProperty> matchingProperties = new HashSet<>(); + Map<String, Map<String, ConfigProperty>> requiredProperties = requiredServiceConfigurations.get(service); + if (requiredProperties != null) { + for (Map.Entry<String, Map<String, ConfigProperty>> typePropertiesEntry : requiredProperties.entrySet()) { + for (ConfigProperty configProperty : typePropertiesEntry.getValue().values()) { + if (configProperty.getPropertyTypes().contains(propertyType)) { + matchingProperties.add(configProperty); + } + } + } + } + return matchingProperties; + } + + public boolean isPasswordProperty(String service, String type, String propertyName) { + return (serviceConfigurations.containsKey(service) && + serviceConfigurations.get(service).containsKey(type) && + serviceConfigurations.get(service).get(type).containsKey(propertyName) && + serviceConfigurations.get(service).get(type).get(propertyName).getPropertyTypes(). + contains(PropertyInfo.PropertyType.PASSWORD)); + } + + //todo + public Map<String, String> getStackConfigurationProperties(String type) { + Map<String, String> configMap = new HashMap<>(); + Map<String, ConfigProperty> configProperties = stackConfigurations.get(type); + if (configProperties != null) { + for (Map.Entry<String, ConfigProperty> configProperty : configProperties.entrySet()) { + configMap.put(configProperty.getKey(), configProperty.getValue().getValue()); + } + } + return configMap; + } + + public boolean isKerberosPrincipalNameProperty(String service, String type, String propertyName) { + return (serviceConfigurations.containsKey(service) && + serviceConfigurations.get(service).containsKey(type) && + serviceConfigurations.get(service).get(type).containsKey(propertyName) && + serviceConfigurations.get(service).get(type).get(propertyName).getPropertyTypes(). + contains(PropertyInfo.PropertyType.KERBEROS_PRINCIPAL)); + } + /** + * Get config attributes for the specified service and configuration type. + * + * @param service service name + * @param type configuration type + * + * @return map of attribute names to map of property names to attribute values + * for the specified service and configuration type + */ + public Map<String, Map<String, String>> getConfigurationAttributes(String service, String type) { + Map<String, Map<String, String>> attributesMap = new HashMap<>(); + Map<String, ConfigProperty> configProperties = serviceConfigurations.get(service).get(type); + if (configProperties != null) { + for (Map.Entry<String, ConfigProperty> configProperty : configProperties.entrySet()) { + String propertyName = configProperty.getKey(); + Map<String, String> propertyAttributes = configProperty.getValue().getAttributes(); + if (propertyAttributes != null) { + for (Map.Entry<String, String> propertyAttribute : propertyAttributes.entrySet()) { + String attributeName = propertyAttribute.getKey(); + String attributeValue = propertyAttribute.getValue(); + if (attributeValue != null) { + Map<String, String> attributes = getWithEmptyDefault(attributesMap, attributeName); + attributes.put(propertyName, attributeValue); + } + } + } + } + } + return attributesMap; + } + + //todo: + public Map<String, Map<String, String>> getStackConfigurationAttributes(String type) { + Map<String, Map<String, String>> attributesMap = new HashMap<>(); + Map<String, ConfigProperty> configProperties = stackConfigurations.get(type); + if (configProperties != null) { + for (Map.Entry<String, ConfigProperty> configProperty : configProperties.entrySet()) { + String propertyName = configProperty.getKey(); + Map<String, String> propertyAttributes = configProperty.getValue().getAttributes(); + if (propertyAttributes != null) { + for (Map.Entry<String, String> propertyAttribute : propertyAttributes.entrySet()) { + String attributeName = propertyAttribute.getKey(); + String attributeValue = propertyAttribute.getValue(); + Map<String, String> attributes = getWithEmptyDefault(attributesMap, attributeName); + attributes.put(propertyName, attributeValue); + } + } + } + } + return attributesMap; + } + + /** + * Get the service for the specified component. + * + * @param component component name + * + * @return service name that contains tha specified component + */ + public String getServiceForComponent(String component) { + return componentService.get(component); + } + + /** + * Get the names of the services which contains the specified components. + * + * @param components collection of components + * + * @return collection of services which contain the specified components + */ + public Collection<String> getServicesForComponents(Collection<String> components) { + Set<String> services = new HashSet<>(); + for (String component : components) { + services.add(getServiceForComponent(component)); + } + + return services; + } + + /** + * Obtain the service name which corresponds to the specified configuration. + * + * @param config configuration type + * + * @return name of service which corresponds to the specified configuration type + */ + public String getServiceForConfigType(String config) { + for (Map.Entry<String, Map<String, Map<String, ConfigProperty>>> entry : serviceConfigurations.entrySet()) { + Map<String, Map<String, ConfigProperty>> typeMap = entry.getValue(); + String serviceName = entry.getKey(); + if (typeMap.containsKey(config) && !getExcludedConfigurationTypes(serviceName).contains(config)) { + return serviceName; + } + } + throw new IllegalArgumentException( + "Specified configuration type is not associated with any service: " + config); + } + + /** + * Return the dependencies specified for the given component. + * + * @param component component to get dependency information for + * + * @return collection of dependency information for the specified component + */ + //todo: full dependency graph + public Collection<DependencyInfo> getDependenciesForComponent(String component) { + return dependencies.containsKey(component) ? dependencies.get(component) : + Collections.emptySet(); + } + + /** + * Get the service, if any, that a component dependency is conditional on. + * + * @param dependency dependency to get conditional service for + * + * @return conditional service for provided component or null if dependency + * is not conditional on a service + */ + public String getConditionalServiceForDependency(DependencyInfo dependency) { + return dependencyConditionalServiceMap.get(dependency); + } + + public String getExternalComponentConfig(String component) { + return dbDependencyInfo.get(component); + } + + /** + * Obtain the required cardinality for the specified component. + */ + public Cardinality getCardinality(String component) { + return new Cardinality(cardinalityRequirements.get(component)); + } + + /** + * Obtain auto-deploy information for the specified component. + */ + public AutoDeployInfo getAutoDeployInfo(String component) { + return componentAutoDeployInfo.get(component); + } + + public boolean isMasterComponent(String component) { + return masterComponents.contains(component); + } + + public Configuration getConfiguration(Collection<String> services) { + Map<String, Map<String, Map<String, String>>> attributes = new HashMap<>(); + Map<String, Map<String, String>> properties = new HashMap<>(); + + for (String service : services) { + Collection<String> serviceConfigTypes = getConfigurationTypes(service); + for (String type : serviceConfigTypes) { + Map<String, String> typeProps = getWithEmptyDefault(properties, type); + typeProps.putAll(getConfigurationProperties(service, type)); + + Map<String, Map<String, String>> stackTypeAttributes = getConfigurationAttributes(service, type); + if (!stackTypeAttributes.isEmpty()) { + if (! attributes.containsKey(type)) { + attributes.put(type, new HashMap<>()); + } + 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 = getWithEmptyDefault(typeAttributes, attributeName); + attributeProps.putAll(attribute.getValue()); + } + } + } + } + return new Configuration(properties, attributes); + } + + public Configuration getConfiguration() { + Map<String, Map<String, Map<String, String>>> stackAttributes = new HashMap<>(); + Map<String, Map<String, String>> stackConfigs = new HashMap<>(); + + for (String service : getServices()) { + for (String type : getAllConfigurationTypes(service)) { + Map<String, String> typeProps = getWithEmptyDefault(stackConfigs, type); + typeProps.putAll(getConfigurationProperties(service, type)); + + Map<String, Map<String, String>> stackTypeAttributes = getConfigurationAttributes(service, type); + if (!stackTypeAttributes.isEmpty()) { + if (! stackAttributes.containsKey(type)) { + stackAttributes.put(type, new HashMap<>()); + } + 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 = getWithEmptyDefault(typeAttrs, attributeName); + attributes.putAll(attribute.getValue()); + } + } + } + } + return new Configuration(stackConfigs, stackAttributes); + } + + 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); + } + return innerMap; + } + + + /** + * Contains a configuration property's value and attributes. + */ + public static class ConfigProperty { + private ValueAttributesInfo propertyValueAttributes = null; + private String name; + private String value; + private Map<String, String> attributes; + private Set<PropertyInfo.PropertyType> propertyTypes; + private String type; + private Set<PropertyDependencyInfo> dependsOnProperties = + Collections.emptySet(); + + public ConfigProperty(ReadOnlyConfigurationResponse config) { + this.name = config.getPropertyName(); + this.value = config.getPropertyValue(); + this.attributes = config.getPropertyAttributes(); + this.propertyTypes = config.getPropertyType(); + this.type = normalizeType(config.getType()); + this.dependsOnProperties = config.getDependsOnProperties(); + this.propertyValueAttributes = config.getPropertyValueAttributes(); + } + + public ConfigProperty(String type, String name, String value) { + this.type = type; + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getType() { + return type; + } + + public Set<PropertyInfo.PropertyType> getPropertyTypes() { + return propertyTypes; + } + + public void setPropertyTypes(Set<PropertyInfo.PropertyType> propertyTypes) { + this.propertyTypes = propertyTypes; + } + + public Map<String, String> getAttributes() { + return attributes; + } + + public void setAttributes(Map<String, String> attributes) { + this.attributes = attributes; + } + + Set<PropertyDependencyInfo> getDependsOnProperties() { + return this.dependsOnProperties; + } + + private String normalizeType(String type) { + //strip .xml from type + if (type.endsWith(".xml")) { + type = type.substring(0, type.length() - 4); + } + return type; + } + + public ValueAttributesInfo getPropertyValueAttributes() { + return propertyValueAttributes; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/f82497d4/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/f82497d4/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/f82497d4/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/f82497d4/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/f82497d4/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/f82497d4/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/f82497d4/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 26dc41d..827fa39 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,102 +19,196 @@ 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 org.apache.ambari.server.controller.internal.StackV2; +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 { - public BlueprintImplV2(BlueprintEntity e) { + + 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 + @JsonIgnore public Collection<String> getAllServiceTypes() { return null; } @Override + @JsonIgnore public Collection<Service> getServicesByType(String serviceType) { - return getAllServices().stream().filter( - service -> service.getType().equalsIgnoreCase(serviceType)).collect(Collectors.toList()); + return null; +// getAllServices().stream().filter( +// service -> service.getType().equalsIgnoreCase(serviceType)).collect(Collectors.toList()); } @Override + @JsonIgnore public Collection<Service> getServicesFromServiceGroup(ServiceGroup serviceGroup, String serviceType) { if (serviceType == null) { return serviceGroup.getServices(); } else { return serviceGroup.getServices().stream().filter( - service -> service.getType().equalsIgnoreCase(serviceType)).collect(Collectors.toList()); + service -> service.getType().equalsIgnoreCase(serviceType)).collect(Collectors.toList()); } } @Override + @JsonIgnore public Collection<ComponentV2> getComponents(Service service) { return null; } @Override + @JsonIgnore public Collection<ComponentV2> getComponentsByType(Service service, String componentType) { return getComponents(service).stream().filter( - compnoent -> compnoent.getType().equalsIgnoreCase(componentType)).collect(Collectors.toList()); + compnoent -> compnoent.getType().equalsIgnoreCase(componentType)).collect(Collectors.toList()); } @Override - public Collection<HostGroupV2> getHostGroupsForService(Service service) { - return null; + @JsonIgnore + public Collection<ComponentV2> getComponents(ServiceId serviceId) { + return getHostGroupsForService(serviceId).stream().flatMap(hg -> hg.getComponents().stream()).collect(Collectors.toSet()); + } + + @Override + @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 - @Deprecated public Configuration getConfiguration() { return null; } @Override public Setting getSetting() { - return null; + return this.setting; } @Override @@ -122,43 +216,147 @@ public class BlueprintImplV2 implements BlueprintV2 { return null; } + @Nonnull @Override - public String getCredentialStoreEnabled(String serviceName) { - return null; + @JsonIgnore + public Collection<String> getAllServiceNames() { + return getAllServices().stream().map(s -> s.getName()).collect(Collectors.toList()); } + @Nonnull @Override - public boolean shouldSkipFailure() { - return false; + public Collection<String> getComponentNames(ServiceId serviceId) { + return getComponents(serviceId).stream().map(c -> c.getName()).collect(Collectors.toList()); } @Override - public SecurityConfiguration getSecurity() { + 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 void validateTopology() throws InvalidTopologyException { + 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 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 validateRequiredProperties() 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 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/f82497d4/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 10fa2fa..ea17e90 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,7 +22,11 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import org.apache.ambari.server.controller.internal.StackV2; + +import javax.annotation.Nonnull; + +import org.apache.ambari.server.controller.StackV2; + import org.apache.ambari.server.orm.entities.BlueprintEntity; @@ -60,6 +64,10 @@ public interface BlueprintV2 { */ Collection<StackV2> getStacks(); + /** + * @return associated stack ids + **/ + public Collection<String> getStackIds(); Collection<ServiceGroup> getServiceGroups(); @@ -68,7 +76,16 @@ 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(); + /** @@ -96,11 +113,22 @@ public interface BlueprintV2 { /** * 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. + */ + @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(Service service); + Collection<ComponentV2> getComponents(ServiceId serviceId); + /** * Get components by type from a service. @@ -114,12 +142,12 @@ public interface BlueprintV2 { /** * 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. @@ -130,6 +158,7 @@ public interface BlueprintV2 { */ Collection<HostGroupV2> getHostGroupsForComponent(ComponentV2 component); + /** * Get the Blueprint cluster scoped configuration. * The blueprint cluster scoped configuration has the stack @@ -141,6 +170,7 @@ public interface BlueprintV2 { @Deprecated Configuration getConfiguration(); + /** * Get the Blueprint cluster scoped setting. * The blueprint cluster scoped setting has the setting properties @@ -178,19 +208,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/f82497d4/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/f82497d4/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/f82497d4/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 d7c08f4..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,37 +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 type; +public class ComponentV2 implements Configurable { - private final String name; + private String type; - private final Service service; + private String name; - private final ProvisionAction provisionAction; + private ServiceId serviceId = new ServiceId(); - private final Configuration configuration; + private ProvisionAction provisionAction = ProvisionAction.INSTALL_AND_START; - public ComponentV2(String type, Service service) { - this(type, type, service, null, null); - } + private Configuration configuration; + private boolean masterComponent = false; - public ComponentV2(String type, String name, Service service) { - this(type, name, service, null, null); - } + public ComponentV2() { } - public ComponentV2(String type, String name, Service service, ProvisionAction provisionAction, Configuration configuration) { - this.type = type; - this.name = name; - this.service = service; - this.provisionAction = provisionAction; - this.configuration = configuration; - } /** * Gets the name of this component @@ -59,8 +50,9 @@ public class ComponentV2 { return this.name; } - public String getType() { - return type; + /** @return the masterComponent flag */ + public boolean isMasterComponent() { + return masterComponent; } /** @@ -73,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/f82497d4/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/f82497d4/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/f82497d4/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/f82497d4/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 fd0f966..0922e74 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.