You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by js...@apache.org on 2014/05/07 16:17:00 UTC
git commit: AMBARI-5690. Add blueprint validation for required
properties.
Repository: ambari
Updated Branches:
refs/heads/branch-1.6.0 369e0d369 -> 4651447c2
AMBARI-5690. Add blueprint validation for required properties.
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4651447c
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4651447c
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4651447c
Branch: refs/heads/branch-1.6.0
Commit: 4651447c2d74e30b26445bc57b84a4f65a74d2b8
Parents: 369e0d3
Author: John Speidel <js...@hortonworks.com>
Authored: Tue May 6 16:35:43 2014 -0400
Committer: John Speidel <js...@hortonworks.com>
Committed: Wed May 7 09:56:01 2014 -0400
----------------------------------------------------------------------
.../server/api/services/AmbariMetaInfo.java | 53 +-
.../server/api/util/StackExtensionHelper.java | 18 -
.../ambari/server/controller/AmbariServer.java | 2 +-
.../internal/BlueprintResourceProvider.java | 26 +-
.../internal/ClusterResourceProvider.java | 161 +++++-
.../server/orm/entities/BlueprintEntity.java | 110 ++++
.../internal/BlueprintResourceProviderTest.java | 20 +-
.../internal/ClusterResourceProviderTest.java | 569 ++++++++++++++++++-
.../orm/entities/BlueprintEntityTest.java | 188 ++++++
9 files changed, 1096 insertions(+), 51 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/4651447c/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
index 1d2e5cc..e896b52 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
@@ -25,6 +25,7 @@ import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -126,8 +127,8 @@ public class AmbariMetaInfo {
@Inject
private MetainfoDAO metainfoDAO;
// Required properties by stack version
- private final Map<StackId, Map<String, PropertyInfo>> requiredProperties =
- new HashMap<StackId, Map<String, PropertyInfo>>();
+ private final Map<StackId, Map<String, Map<String, PropertyInfo>>> requiredProperties =
+ new HashMap<StackId, Map<String, Map<String, PropertyInfo>>>();
/**
* Ambari Meta Info Object
@@ -814,13 +815,16 @@ public class AmbariMetaInfo {
List<ServiceInfo> services = stackExtensionHelper.getAllApplicableServices(stack);
stack.setServices(services);
+ Map<String, Map<String, PropertyInfo>> stackRequiredProps = new HashMap<String, Map<String, PropertyInfo>>();
+ requiredProperties.put(new StackId(stack.getName(), stack.getVersion()), stackRequiredProps);
+ for (ServiceInfo service : services) {
+ // Set required config properties
+ stackRequiredProps.put(service.getName(), getAllRequiredProperties(service));
+ }
+
// Resolve hooks folder
String stackHooksToUse = stackExtensionHelper.resolveHooksFolder(stack);
stack.setStackHooksFolder(stackHooksToUse);
-
- // Set required config properties
- requiredProperties.put(new StackId(stack.getName(), stack.getVersion()),
- stackExtensionHelper.getAllRequiredPropertiesForStack(stack));
}
es.invokeAll(lookupList);
@@ -830,12 +834,22 @@ public class AmbariMetaInfo {
/**
* Get properties with require_input attribute set to true.
- * @param stackName Name of the stack, e.g.: HDP
- * @param stackVersion Version of the stack
- * @return Map of config type to Properties
+ *
+ * @param stackName name of the stack, e.g.: HDP
+ * @param stackVersion version of the stack
+ * @return Map of property name to PropertyInfo
*/
- public Map<String, PropertyInfo> getRequiredPropertiesForStack(String stackName, String stackVersion) {
- return requiredProperties.get(new StackId(stackName, stackVersion));
+ public Map<String, PropertyInfo> getRequiredProperties(String stackName, String stackVersion, String service) {
+
+ Map<String, Map<String, PropertyInfo>> requiredStackProps =
+ requiredProperties.get(new StackId(stackName, stackVersion));
+
+ if (requiredStackProps != null) {
+ Map<String, PropertyInfo> requiredServiceProperties = requiredStackProps.get(service);
+ return requiredServiceProperties == null ? Collections.<String, PropertyInfo>emptyMap() :
+ requiredServiceProperties;
+ }
+ return Collections.emptyMap();
}
public String getServerVersion() {
@@ -1001,4 +1015,21 @@ public class AmbariMetaInfo {
return null;
}
+ /**
+ * Get all required properties for the given service.
+ *
+ * @param service associated service
+ * @return map of property name to PropertyInfo containing all required properties for service
+ */
+ private Map<String, PropertyInfo> getAllRequiredProperties(ServiceInfo service) {
+ Map<String, PropertyInfo> requiredProperties = new HashMap<String, PropertyInfo>();
+ List<PropertyInfo> properties = service.getProperties();
+ for (PropertyInfo propertyInfo : properties) {
+ if (propertyInfo.isRequireInput()) {
+ requiredProperties.put(propertyInfo.getName(), propertyInfo);
+ }
+ }
+ return requiredProperties;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4651447c/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
index 89afb14..18e8659 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
@@ -631,24 +631,6 @@ public class StackExtensionHelper {
}
}
}
-
- /**
- * Get all properties with require-input attribute set to true.
- * @param stackInfo StackInfo object.
- */
- public Map<String, PropertyInfo> getAllRequiredPropertiesForStack(StackInfo stackInfo) {
- Map<String, PropertyInfo> requiredProperties = new HashMap<String, PropertyInfo>();
- for (ServiceInfo serviceInfo : stackInfo.getServices()) {
- List<PropertyInfo> properties = serviceInfo.getProperties();
- for (PropertyInfo propertyInfo : properties) {
- if (propertyInfo.isRequireInput()) {
- requiredProperties.put(propertyInfo.getName(), propertyInfo);
- }
- }
- }
- return requiredProperties;
- }
-
public static <T> T unmarshal(Class<T> clz, File file) throws JAXBException {
Unmarshaller u = _jaxbContexts.get(clz).createUnmarshaller();
http://git-wip-us.apache.org/repos/asf/ambari/blob/4651447c/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 6c072db..12c92a9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -512,7 +512,7 @@ public class AmbariServer {
BlueprintResourceProvider.init(injector.getInstance(BlueprintDAO.class),
injector.getInstance(Gson.class), ambariMetaInfo);
StackDependencyResourceProvider.init(ambariMetaInfo);
- ClusterResourceProvider.injectBlueprintDAO(injector.getInstance(BlueprintDAO.class));
+ ClusterResourceProvider.init(injector.getInstance(BlueprintDAO.class), ambariMetaInfo);
ViewRegistry.init(injector.getInstance(ViewDAO.class), injector.getInstance(ViewInstanceDAO.class));
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4651447c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
index 353b58f..003590f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
@@ -42,6 +42,7 @@ import org.apache.ambari.server.orm.entities.HostGroupConfigEntity;
import org.apache.ambari.server.orm.entities.HostGroupEntity;
import org.apache.ambari.server.state.ComponentInfo;
import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.state.PropertyInfo;
import java.util.ArrayList;
import java.util.Arrays;
@@ -53,6 +54,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+
/**
* Resource Provider for Blueprint resources.
*/
@@ -342,8 +344,8 @@ public class BlueprintResourceProvider extends AbstractResourceProvider {
createHostGroupEntities(blueprint,
(HashSet<HashMap<String, Object>>) properties.get(HOST_GROUP_PROPERTY_ID));
- createBlueprintConfigEntities((Collection<Map<String,
- String>>) properties.get(CONFIGURATION_PROPERTY_ID), blueprint);
+ createBlueprintConfigEntities((Collection<Map<String, String>>)
+ properties.get(CONFIGURATION_PROPERTY_ID), blueprint);
return blueprint;
}
@@ -554,8 +556,8 @@ public class BlueprintResourceProvider extends AbstractResourceProvider {
* @param configuration property map
* @param configEntity config entity to populate
*/
- private void populateConfigurationEntity(String blueprintName, Map<String, String> configuration,
- BlueprintConfiguration configEntity) {
+ private void populateConfigurationEntity(String blueprintName, Map<String, String> configuration,
+ BlueprintConfiguration configEntity) {
configEntity.setBlueprintName(blueprintName);
Map<String, String> configData = new HashMap<String, String>();
@@ -585,15 +587,23 @@ public class BlueprintResourceProvider extends AbstractResourceProvider {
public Void invoke() throws AmbariException {
BlueprintEntity blueprint = toBlueprintEntity(properties);
- if (LOG.isDebugEnabled()) {
- LOG.debug("Creating Blueprint, name=" + blueprint.getBlueprintName());
- }
-
if (dao.findByName(blueprint.getBlueprintName()) != null) {
throw new DuplicateResourceException(
"Attempted to create a Blueprint which already exists, blueprint_name=" +
blueprint.getBlueprintName());
}
+
+ Map<String, Map<String, Collection<String>>> missingProperties = blueprint.validateConfigurations(
+ stackInfo, PropertyInfo.PropertyType.DEFAULT);
+
+ if (! missingProperties.isEmpty()) {
+ throw new IllegalArgumentException("Required configurations are missing from the specified host groups: " +
+ missingProperties);
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Creating Blueprint, name=" + blueprint.getBlueprintName());
+ }
dao.create(blueprint);
return null;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4651447c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
index e884e97..f459f3c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
@@ -20,6 +20,7 @@ package org.apache.ambari.server.controller.internal;
import com.google.gson.Gson;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.StackAccessException;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.api.services.PersistKeyValueService;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.ClusterRequest;
@@ -52,11 +53,14 @@ import org.apache.ambari.server.orm.entities.HostGroupConfigEntity;
import org.apache.ambari.server.orm.entities.HostGroupEntity;
import org.apache.ambari.server.state.Config;
import org.apache.ambari.server.state.ConfigImpl;
+import org.apache.ambari.server.state.PropertyInfo;
+
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -84,6 +88,11 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
private static BlueprintDAO blueprintDAO;
/**
+ * Stack related information.
+ */
+ private static AmbariMetaInfo stackInfo;
+
+ /**
* Maps properties to updaters which update the property when provisioning a cluster via a blueprint
*/
private Map<String, PropertyUpdater> propertyUpdaters =
@@ -114,12 +123,13 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
}
/**
- * Inject the blueprint data access object which is used to obtain blueprint entities
+ * Inject the blueprint data access object which is used to obtain blueprint entities.
*
* @param dao blueprint data access object
*/
- public static void injectBlueprintDAO(BlueprintDAO dao) {
+ public static void init(BlueprintDAO dao, AmbariMetaInfo metaInfo) {
blueprintDAO = dao;
+ stackInfo = metaInfo;
}
@@ -247,6 +257,8 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
// extract to own method
baseUnsupported.remove("blueprint");
baseUnsupported.remove("host_groups");
+ baseUnsupported.remove("default_password");
+ baseUnsupported.remove("configurations");
return checkConfigPropertyIds(baseUnsupported, "Clusters");
}
@@ -316,7 +328,9 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
Map<String, HostGroup> blueprintHostGroups = parseBlueprintHostGroups(blueprint, stack);
applyRequestInfoToHostGroups(properties, blueprintHostGroups);
- processConfigurations(processBlueprintConfigurations(blueprint), stack, blueprintHostGroups);
+ processConfigurations(processBlueprintConfigurations(blueprint, (Collection<Map<String, String>>)
+ properties.get("configurations")), stack, blueprintHostGroups);
+ validatePasswordProperties(blueprint, blueprintHostGroups, (String) properties.get("default_password"));
String clusterName = (String) properties.get(CLUSTER_NAME_PROPERTY_ID);
createClusterResource(buildClusterResourceProperties(stack, clusterName));
@@ -335,6 +349,131 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
}
/**
+ * Validate that all required password properties have been set or that 'default_password' is specified.
+ *
+ * @param blueprint associated blueprint entity
+ * @param hostGroups host groups in blueprint
+ * @param defaultPassword specified default password, may be null
+ *
+ * @throws IllegalArgumentException if required password properties are missing and no
+ * default is specified via 'default_password'
+ */
+ private void validatePasswordProperties(BlueprintEntity blueprint, Map<String, HostGroup> hostGroups,
+ String defaultPassword) {
+
+ Map<String, Map<String, Collection<String>>> missingPasswords = blueprint.validateConfigurations(
+ stackInfo, PropertyInfo.PropertyType.PASSWORD);
+
+ Iterator<Map.Entry<String, Map<String, Collection<String>>>> iter;
+ for(iter = missingPasswords.entrySet().iterator(); iter.hasNext(); ) {
+ Map.Entry<String, Map<String, Collection<String>>> entry = iter.next();
+ Map<String, Collection<String>> missingProps = entry.getValue();
+ Iterator<Map.Entry<String, Collection<String>>> propIter;
+ for (propIter = missingProps.entrySet().iterator(); propIter.hasNext(); ) {
+ Map.Entry<String, Collection<String>> propEntry = propIter.next();
+ String configType = propEntry.getKey();
+ Collection<String> propertySet = propEntry.getValue();
+
+ for (String property : propertySet) {
+ if (setDefaultPassword(defaultPassword, configType, property)) {
+ propIter.remove();
+ } else if (isPropertyInConfiguration(mapClusterConfigurations.get(configType), property)){
+ propIter.remove();
+ } else {
+ HostGroup hostgroup = hostGroups.get(entry.getKey());
+ if (hostgroup != null) {
+ if (isPropertyInConfiguration(hostgroup.getConfigurations().get(configType), property)) {
+ propIter.remove();
+ }
+ }
+ }
+ }
+ }
+ if (entry.getValue().isEmpty()) {
+ iter.remove();
+ }
+ }
+
+ if (! missingPasswords.isEmpty()) {
+ throw new IllegalArgumentException("Missing required password properties. Specify a value for these " +
+ "properties in the cluster or host group configurations or include 'default_password' field in request. " +
+ missingPasswords);
+ }
+ }
+
+ /**
+ * Attempt to set the default password in cluster configuration for missing password property.
+ *
+ * @param defaultPassword default password specified in request, may be null
+ * @param configType configuration type
+ * @param property password property name
+ *
+ * @return true if password was set, otherwise false. Currently the password will always be set
+ * unless it is null
+ */
+ private boolean setDefaultPassword(String defaultPassword, String configType, String property) {
+ boolean setDefaultPassword = false;
+ Map<String, String> typeProps = mapClusterConfigurations.get(configType);
+ if (defaultPassword != null && ! defaultPassword.trim().isEmpty()) {
+ // set default password in cluster config
+ if (typeProps == null) {
+ typeProps = new HashMap<String, String>();
+ mapClusterConfigurations.put(configType, typeProps);
+ }
+ typeProps.put(property, defaultPassword);
+ setDefaultPassword = true;
+ }
+ return setDefaultPassword;
+ }
+
+ /**
+ * Determine if a specific property is in a configuration.
+ *
+ * @param props property map to check
+ * @param property property to check for
+ *
+ * @return true if the property is contained in the configuration, otherwise false
+ */
+ private boolean isPropertyInConfiguration(Map<String, String> props, String property) {
+ boolean foundProperty = false;
+ if (props != null) {
+ String val = props.get(property);
+ foundProperty = (val != null && ! val.trim().isEmpty());
+ }
+ return foundProperty;
+ }
+
+ /**
+ * Override existing properties or add new.
+ *
+ * @param existingProperties property overrides
+ * @param configOverrides current property values
+ */
+ private void overrideExistingProperties(Map<String, Map<String, String>> existingProperties,
+ Collection<Map<String, String>> configOverrides) {
+ if (configOverrides != null) {
+ for (Map<String, String> properties : configOverrides) {
+ String category = null;
+ int propertyOffset = -1;
+ for (Map.Entry<String, String> entry : properties.entrySet()) {
+ String absolutePropName = entry.getKey();
+ if (category == null) {
+ propertyOffset = absolutePropName.indexOf('/');
+ category = absolutePropName.substring(0, propertyOffset);
+ }
+ Map<String, String> existingCategoryProperties = existingProperties.get(category);
+ if (existingCategoryProperties == null) {
+ existingCategoryProperties = new HashMap<String, String>();
+ existingProperties.put(category, existingCategoryProperties);
+ }
+ //override existing property or add new
+ existingCategoryProperties.put(absolutePropName.substring(propertyOffset + 1), entry.getValue());
+ }
+ }
+ }
+ }
+
+ /**
* Obtain a blueprint entity based on name.
*
* @param blueprintName name of blueprint to obtain
@@ -534,8 +673,8 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
*
* @throws IllegalArgumentException a host-group in the request doesn't match a host-group in the blueprint
*/
- private void applyRequestInfoToHostGroups(Map<String, Object> properties, Map<String,
- HostGroup> blueprintHostGroups)
+ private void applyRequestInfoToHostGroups(Map<String, Object> properties,
+ Map<String, HostGroup> blueprintHostGroups)
throws IllegalArgumentException {
@SuppressWarnings("unchecked")
@@ -548,7 +687,7 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
HostGroup hostGroup = blueprintHostGroups.get(name);
if (hostGroup == null) {
- throw new IllegalArgumentException("Invalid host-group specified: " + name +
+ throw new IllegalArgumentException("Invalid host_group specified: " + name +
". All request host groups must have a corresponding host group in the specified blueprint");
}
@@ -559,6 +698,10 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
//add host information to host group
hostGroup.addHostInfo(mapHostProperties.get("fqdn"));
}
+ Map<String, Map<String, String>> existingConfigurations = hostGroup.getConfigurations();
+ overrideExistingProperties(existingConfigurations, (Collection<Map<String, String>>)
+ hostGroupProperties.get("configurations"));
+
}
validateHostMappings(blueprintHostGroups);
}
@@ -648,14 +791,18 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
*
* @return configuration properties contained within in blueprint
*/
- private Map<String, Map<String, String>> processBlueprintConfigurations(BlueprintEntity blueprint) {
+ private Map<String, Map<String, String>> processBlueprintConfigurations(BlueprintEntity blueprint,
+ Collection<Map<String, String>> configOverrides) {
Map<String, Map<String, String>> mapConfigurations = new HashMap<String, Map<String, String>>();
Collection<BlueprintConfigEntity> configs = blueprint.getConfigurations();
Gson jsonSerializer = new Gson();
+
for (BlueprintConfigEntity config : configs) {
mapConfigurations.put(config.getType(), jsonSerializer.<Map<String, String>> fromJson(
config.getConfigData(), Map.class));
}
+ overrideExistingProperties(mapConfigurations, configOverrides);
+
return mapConfigurations;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4651447c/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 b02c723..cd764ec 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
@@ -18,6 +18,11 @@
package org.apache.ambari.server.orm.entities;
+import com.google.gson.Gson;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.state.PropertyInfo;
+
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -26,7 +31,12 @@ import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
+import javax.persistence.Transient;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
/**
* Entity representing a Blueprint.
@@ -56,6 +66,9 @@ public class BlueprintEntity {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "blueprint")
private Collection<BlueprintConfigEntity> configurations;
+ @Transient
+ private Gson jsonSerializer = new Gson();
+
/**
* Get the blueprint name.
@@ -146,4 +159,101 @@ public class BlueprintEntity {
public void setConfigurations(Collection<BlueprintConfigEntity> configurations) {
this.configurations = configurations;
}
+
+ /**
+ * Validate all configurations. Validation is done on the operational configuration of each
+ * host group. An operational configuration is achieved by overlaying host group configuration
+ * on top of cluster configuration which overlays the default stack configurations.
+ *
+ * @param stackInfo stack information
+ * @param type type of required property to check (PASSWORD|DEFAULT)
+ * @return map of required properties which are missing. Empty map if none are missing.
+ *
+ * @throws IllegalArgumentException if blueprint contains invalid information
+ */
+ public Map<String, Map<String, Collection<String>>> validateConfigurations(
+ AmbariMetaInfo stackInfo, PropertyInfo.PropertyType type) {
+
+ String stackName = getStackName();
+ String stackVersion = getStackVersion();
+
+ Map<String, Map<String, Collection<String>>> missingProperties =
+ new HashMap<String, Map<String, Collection<String>>>();
+ Map<String, Map<String, String>> clusterConfigurations = getConfigurationAsMap(getConfigurations());
+
+ for (HostGroupEntity hostGroup : getHostGroups()) {
+ Collection<String> processedServices = new HashSet<String>();
+ Map<String, Collection<String>> allRequiredProperties = new HashMap<String, Collection<String>>();
+ Map<String, Map<String, String>> operationalConfiguration =
+ new HashMap<String, Map<String, String>>(clusterConfigurations);
+
+ operationalConfiguration.putAll(getConfigurationAsMap(hostGroup.getConfigurations()));
+ for (HostGroupComponentEntity component : hostGroup.getComponents()) {
+ //for now, AMBARI is not recognized as a service in Stacks
+ if (! component.getName().equals("AMBARI_SERVER")) {
+ String service;
+ try {
+ service = stackInfo.getComponentToService(stackName, stackVersion, component.getName());
+ } catch (AmbariException e) {
+ throw new IllegalArgumentException("Unable to determine the service associated with the" +
+ " component: " + component.getName());
+ }
+ if (processedServices.add(service)) {
+ Map<String, PropertyInfo> serviceRequirements = stackInfo.getRequiredProperties(
+ stackName, stackVersion, service);
+
+ for (PropertyInfo propertyInfo : serviceRequirements.values()) {
+ if (propertyInfo.getType() == type) {
+ String configCategory = propertyInfo.getFilename();
+ if (configCategory.endsWith(".xml")) {
+ configCategory = configCategory.substring(0, configCategory.indexOf(".xml"));
+ }
+ Collection<String> typeRequirements = allRequiredProperties.get(configCategory);
+ if (typeRequirements == null) {
+ typeRequirements = new HashSet<String>();
+ allRequiredProperties.put(configCategory, typeRequirements);
+ }
+ typeRequirements.add(propertyInfo.getName());
+ }
+ }
+ }
+ }
+ }
+ for (Map.Entry<String, Collection<String>> requiredTypeProperties : allRequiredProperties.entrySet()) {
+ String requiredCategory = requiredTypeProperties.getKey();
+ Collection<String> requiredProperties = requiredTypeProperties.getValue();
+ Collection<String> operationalTypeProps = operationalConfiguration.containsKey(requiredCategory) ?
+ operationalConfiguration.get(requiredCategory).keySet() :
+ Collections.<String>emptyList();
+
+ requiredProperties.removeAll(operationalTypeProps);
+ if (! requiredProperties.isEmpty()) {
+ Map<String, Collection<String>> hostGroupMissingProps = new HashMap<String, Collection<String>>();
+ hostGroupMissingProps.put(requiredCategory, requiredProperties);
+ missingProperties.put(hostGroup.getName(), hostGroupMissingProps);
+ }
+ }
+ }
+ return missingProperties;
+ }
+
+ /**
+ * Obtain configuration as a map of config type to corresponding properties.
+ *
+ * @param configurations configuration to include in map
+ *
+ * @return map of config type to map of properties
+ */
+ private Map<String, Map<String, String>> getConfigurationAsMap(
+ Collection<? extends BlueprintConfiguration> configurations) {
+
+ Map<String, Map<String, String>> properties = new HashMap<String, Map<String, String>>();
+ for (BlueprintConfiguration config : configurations) {
+ String type = config.getType();
+ Map<String, String> typeProperties = jsonSerializer.<Map<String, String>>fromJson(
+ config.getConfigData(), Map.class);
+ properties.put(type, typeProperties);
+ }
+ return properties;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4651447c/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java
index f046b00..b611551 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java
@@ -83,7 +83,7 @@ public class BlueprintResourceProviderTest {
private final static BlueprintDAO dao = createStrictMock(BlueprintDAO.class);
private final static Gson gson = new Gson();
- private final static AmbariMetaInfo metaInfo = createStrictMock(AmbariMetaInfo.class);
+ private final static AmbariMetaInfo metaInfo = createMock(AmbariMetaInfo.class);
@BeforeClass
public static void initClass() {
@@ -125,6 +125,12 @@ public class BlueprintResourceProviderTest {
expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
andReturn(serviceComponents).anyTimes();
+ expect(metaInfo.getComponentToService("test-stack-name", "test-stack-version", "component1")).
+ andReturn("test-service").anyTimes();
+ expect(metaInfo.getComponentToService("test-stack-name", "test-stack-version", "component2")).
+ andReturn("test-service").anyTimes();
+ expect(metaInfo.getRequiredProperties("test-stack-name", "test-stack-version", "test-service")).andReturn(
+ Collections.<String, org.apache.ambari.server.state.PropertyInfo>emptyMap()).anyTimes();
dao.create(capture(entityCapture));
replay(dao, metaInfo, request);
@@ -177,6 +183,12 @@ public class BlueprintResourceProviderTest {
expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
andReturn(serviceComponents).anyTimes();
+ expect(metaInfo.getComponentToService("test-stack-name", "test-stack-version", "component1")).
+ andReturn("test-service").anyTimes();
+ expect(metaInfo.getComponentToService("test-stack-name", "test-stack-version", "component2")).
+ andReturn("test-service").anyTimes();
+ expect(metaInfo.getRequiredProperties("test-stack-name", "test-stack-version", "test-service")).andReturn(
+ Collections.<String, org.apache.ambari.server.state.PropertyInfo>emptyMap()).anyTimes();
dao.create(capture(entityCapture));
replay(dao, metaInfo, request);
@@ -500,7 +512,6 @@ public class BlueprintResourceProviderTest {
BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID)).iterator().next().get("components")).
iterator().next().put("name", "AMBARI_SERVER");
-
Capture<BlueprintEntity> entityCapture = new Capture<BlueprintEntity>();
// set expectations
@@ -509,6 +520,11 @@ public class BlueprintResourceProviderTest {
expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
andReturn(serviceComponents).anyTimes();
+ expect(metaInfo.getComponentToService("test-stack-name", "test-stack-version", "component1")).
+ andReturn("test-service").anyTimes();
+ expect(metaInfo.getRequiredProperties("test-stack-name", "test-stack-version", "test-service")).andReturn(
+ Collections.<String, org.apache.ambari.server.state.PropertyInfo>emptyMap()).anyTimes();
+
dao.create(capture(entityCapture));
replay(dao, metaInfo, request);
http://git-wip-us.apache.org/repos/asf/ambari/blob/4651447c/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
index fe5734a..e644b08 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
@@ -19,6 +19,7 @@
package org.apache.ambari.server.controller.internal;
import com.google.gson.Gson;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.api.services.PersistKeyValueImpl;
import org.apache.ambari.server.api.services.PersistKeyValueService;
import org.apache.ambari.server.controller.AmbariManagementController;
@@ -47,6 +48,7 @@ import org.apache.ambari.server.orm.entities.HostGroupComponentEntity;
import org.apache.ambari.server.orm.entities.HostGroupConfigEntity;
import org.apache.ambari.server.orm.entities.HostGroupEntity;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.ambari.server.state.PropertyInfo;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.junit.Assert;
@@ -156,6 +158,7 @@ public class ClusterResourceProviderTest {
String clusterName = "c1";
BlueprintDAO blueprintDAO = createStrictMock(BlueprintDAO.class);
+ AmbariMetaInfo metaInfo = createMock(AmbariMetaInfo.class);
AmbariManagementController managementController = createStrictMock(AmbariManagementController.class);
Request request = createNiceMock(Request.class);
RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
@@ -269,6 +272,8 @@ public class ClusterResourceProviderTest {
expect(blueprint.getStackName()).andReturn(stackName);
expect(blueprint.getStackVersion()).andReturn(stackVersion);
expect(blueprint.getConfigurations()).andReturn(Collections.<BlueprintConfigEntity>singletonList(blueprintConfig));
+ expect(blueprint.validateConfigurations(metaInfo, PropertyInfo.PropertyType.PASSWORD)).andReturn(
+ Collections.<String, Map<String, Collection<String>>>emptyMap());
expect(managementController.getStackServices(capture(stackServiceRequestCapture))).andReturn(stackServiceResponses);
expect(stackServiceResponse1.getServiceName()).andReturn("service1");
@@ -345,10 +350,10 @@ public class ClusterResourceProviderTest {
stackConfigurationResponse1, stackConfigurationResponse2, stackConfigurationResponse3, stackConfigurationResponse4,
blueprintConfig, hostGroup, hostGroupComponent1, hostGroupComponent2, hostGroupComponent3, hostGroupConfig,
serviceResourceProvider, componentResourceProvider, hostResourceProvider, hostComponentResourceProvider,
- configGroupResourceProvider, persistKeyValue);
+ configGroupResourceProvider, persistKeyValue, metaInfo);
// test
- ClusterResourceProvider.injectBlueprintDAO(blueprintDAO);
+ ClusterResourceProvider.init(blueprintDAO, metaInfo);
PersistKeyValueService.init(persistKeyValue);
ResourceProvider provider = new TestClusterResourceProvider(
managementController, serviceResourceProvider, componentResourceProvider,
@@ -500,6 +505,561 @@ public class ClusterResourceProviderTest {
}
@Test
+ public void testCreateResource_blueprint__missingPasswords() throws Exception {
+ String blueprintName = "test-blueprint";
+ String stackName = "test";
+ String stackVersion = "1.23";
+ String clusterName = "c1";
+
+ BlueprintDAO blueprintDAO = createStrictMock(BlueprintDAO.class);
+ AmbariMetaInfo metaInfo = createMock(AmbariMetaInfo.class);
+ AmbariManagementController managementController = createStrictMock(AmbariManagementController.class);
+ Request request = createNiceMock(Request.class);
+ RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
+ BlueprintEntity blueprint = createNiceMock(BlueprintEntity.class);
+ StackServiceResponse stackServiceResponse1 = createNiceMock(StackServiceResponse.class);
+ StackServiceResponse stackServiceResponse2 = createNiceMock(StackServiceResponse.class);
+ Capture<Set<StackServiceRequest>> stackServiceRequestCapture = new Capture<Set<StackServiceRequest>>();
+
+ StackServiceComponentResponse stackServiceComponentResponse1 = createNiceMock(StackServiceComponentResponse.class);
+ StackServiceComponentResponse stackServiceComponentResponse2 = createNiceMock(StackServiceComponentResponse.class);
+ StackServiceComponentResponse stackServiceComponentResponse3 = createNiceMock(StackServiceComponentResponse.class);
+ Capture<Set<StackServiceComponentRequest>> serviceComponentRequestCapture1 = new Capture<Set<StackServiceComponentRequest>>();
+ Capture<Set<StackServiceComponentRequest>> serviceComponentRequestCapture2 = new Capture<Set<StackServiceComponentRequest>>();
+
+ StackConfigurationResponse stackConfigurationResponse1 = createNiceMock(StackConfigurationResponse.class);
+ StackConfigurationResponse stackConfigurationResponse2 = createNiceMock(StackConfigurationResponse.class);
+ StackConfigurationResponse stackConfigurationResponse3 = createNiceMock(StackConfigurationResponse.class);
+ StackConfigurationResponse stackConfigurationResponse4 = createNiceMock(StackConfigurationResponse.class);
+ Capture<Set<StackConfigurationRequest>> serviceConfigurationRequestCapture1 = new Capture<Set<StackConfigurationRequest>>();
+ Capture<Set<StackConfigurationRequest>> serviceConfigurationRequestCapture2 = new Capture<Set<StackConfigurationRequest>>();
+
+ BlueprintConfigEntity blueprintConfig = createNiceMock(BlueprintConfigEntity.class);
+
+ HostGroupEntity hostGroup = createNiceMock(HostGroupEntity.class);
+ HostGroupComponentEntity hostGroupComponent1 = createNiceMock(HostGroupComponentEntity.class);
+ HostGroupComponentEntity hostGroupComponent2 = createNiceMock(HostGroupComponentEntity.class);
+ HostGroupComponentEntity hostGroupComponent3 = createNiceMock(HostGroupComponentEntity.class);
+
+ HostGroupConfigEntity hostGroupConfig = createNiceMock(HostGroupConfigEntity.class);
+
+ ServiceResourceProvider serviceResourceProvider = createStrictMock(ServiceResourceProvider.class);
+ ResourceProvider componentResourceProvider = createStrictMock(ResourceProvider.class);
+ ResourceProvider hostResourceProvider = createStrictMock(ResourceProvider.class);
+ ResourceProvider hostComponentResourceProvider = createStrictMock(ResourceProvider.class);
+ ConfigGroupResourceProvider configGroupResourceProvider = createStrictMock(ConfigGroupResourceProvider.class);
+ PersistKeyValueImpl persistKeyValue = createNiceMock(PersistKeyValueImpl.class);
+
+ Set<StackServiceResponse> stackServiceResponses = new LinkedHashSet<StackServiceResponse>();
+ stackServiceResponses.add(stackServiceResponse1);
+ stackServiceResponses.add(stackServiceResponse2);
+
+ // service1 has 2 components
+ Set<StackServiceComponentResponse> stackServiceComponentResponses1 = new LinkedHashSet<StackServiceComponentResponse>();
+ stackServiceComponentResponses1.add(stackServiceComponentResponse1);
+ stackServiceComponentResponses1.add(stackServiceComponentResponse2);
+
+ // service2 has 1 components
+ Set<StackServiceComponentResponse> stackServiceComponentResponses2 = new LinkedHashSet<StackServiceComponentResponse>();
+ stackServiceComponentResponses2.add(stackServiceComponentResponse3);
+
+ // service1 has 1 config
+ Set<StackConfigurationResponse> stackConfigurationResponses1 = new LinkedHashSet<StackConfigurationResponse>();
+ stackConfigurationResponses1.add(stackConfigurationResponse1);
+
+ // service2 has 3 config
+ Set<StackConfigurationResponse> stackConfigurationResponses2 = new LinkedHashSet<StackConfigurationResponse>();
+ stackConfigurationResponses2.add(stackConfigurationResponse2);
+ stackConfigurationResponses2.add(stackConfigurationResponse3);
+ stackConfigurationResponses2.add(stackConfigurationResponse4);
+
+ Collection<HostGroupComponentEntity> hostGroupComponents = new LinkedHashSet<HostGroupComponentEntity>();
+ hostGroupComponents.add(hostGroupComponent1);
+ hostGroupComponents.add(hostGroupComponent2);
+ hostGroupComponents.add(hostGroupComponent3);
+
+ // request properties
+ Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
+ Map<String, Object> properties = new LinkedHashMap<String, Object>();
+
+ properties.put(ClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID, clusterName);
+ properties.put(ClusterResourceProvider.BLUEPRINT_PROPERTY_ID, blueprintName);
+ propertySet.add(properties);
+
+ Collection<Map<String, Object>> hostGroups = new ArrayList<Map<String, Object>>();
+ Map<String, Object> hostGroupProperties = new HashMap<String, Object>();
+ hostGroups.add(hostGroupProperties);
+ hostGroupProperties.put("name", "group1");
+ Collection<Map<String, String>> hostGroupHosts = new ArrayList<Map<String, String>>();
+ hostGroupProperties.put("hosts", hostGroupHosts);
+ Map<String, String> hostGroupHostProperties = new HashMap<String, String>();
+ hostGroupHostProperties.put("fqdn", "host.domain");
+ hostGroupHosts.add(hostGroupHostProperties);
+ properties.put("host_groups", hostGroups);
+
+ Map<String, String> mapGroupConfigProperties = new HashMap<String, String>();
+ mapGroupConfigProperties.put("myGroupProp", "awesomeValue");
+
+ // blueprint cluster configuration properties
+ Map<String, String> blueprintConfigProperties = new HashMap<String, String>();
+ blueprintConfigProperties.put("property1", "value2");
+ blueprintConfigProperties.put("new.property", "new.property.value");
+
+ Map<String, Map<String, Collection<String>>> allMissingPasswords = new HashMap<String, Map<String, Collection<String>>>();
+ Map<String, Collection<String>> missingHGPasswords = new HashMap<String, Collection<String>>();
+ Collection<String> missingPasswords = new ArrayList<String>();
+ missingPasswords.add("my.missing.password");
+ missingHGPasswords.put("core-site", missingPasswords);
+ allMissingPasswords.put("group1", missingHGPasswords);
+
+ // expectations
+ expect(request.getProperties()).andReturn(propertySet).anyTimes();
+ expect(blueprintDAO.findByName(blueprintName)).andReturn(blueprint);
+ expect(blueprint.getStackName()).andReturn(stackName);
+ expect(blueprint.getStackVersion()).andReturn(stackVersion);
+ expect(blueprint.getConfigurations()).andReturn(Collections.<BlueprintConfigEntity>singletonList(blueprintConfig));
+ expect(blueprint.validateConfigurations(metaInfo, PropertyInfo.PropertyType.PASSWORD)).andReturn(allMissingPasswords);
+
+ expect(managementController.getStackServices(capture(stackServiceRequestCapture))).andReturn(stackServiceResponses);
+ expect(stackServiceResponse1.getServiceName()).andReturn("service1");
+ expect(stackServiceResponse2.getServiceName()).andReturn("service2");
+
+ expect(managementController.getStackComponents(capture(serviceComponentRequestCapture1))).
+ andReturn(stackServiceComponentResponses1);
+ expect(stackServiceComponentResponse1.getComponentName()).andReturn("component1");
+ expect(stackServiceComponentResponse2.getComponentName()).andReturn("component2");
+
+ expect(managementController.getStackConfigurations(capture(serviceConfigurationRequestCapture1))).
+ andReturn(stackConfigurationResponses1);
+ expect(stackConfigurationResponse1.getType()).andReturn("core-site.xml");
+ expect(stackConfigurationResponse1.getPropertyName()).andReturn("property1");
+ expect(stackConfigurationResponse1.getPropertyValue()).andReturn("value1");
+
+ expect(managementController.getStackComponents(capture(serviceComponentRequestCapture2))).
+ andReturn(stackServiceComponentResponses2);
+ expect(stackServiceComponentResponse3.getComponentName()).andReturn("component3");
+
+ expect(managementController.getStackConfigurations(capture(serviceConfigurationRequestCapture2))).
+ andReturn(stackConfigurationResponses2);
+ expect(stackConfigurationResponse2.getType()).andReturn("hdfs-site.xml");
+ expect(stackConfigurationResponse2.getPropertyName()).andReturn("property2");
+ expect(stackConfigurationResponse2.getPropertyValue()).andReturn("value2");
+
+ expect(stackConfigurationResponse3.getType()).andReturn("global.xml");
+ expect(stackConfigurationResponse3.getPropertyName()).andReturn("oozie_user");
+ expect(stackConfigurationResponse3.getPropertyValue()).andReturn("oozie");
+
+ expect(stackConfigurationResponse4.getType()).andReturn("core-site.xml");
+ expect(stackConfigurationResponse4.getPropertyName()).andReturn("property3");
+ expect(stackConfigurationResponse4.getPropertyValue()).andReturn("value3");
+
+ expect(blueprintConfig.getBlueprintName()).andReturn("test-blueprint").anyTimes();
+ expect(blueprintConfig.getType()).andReturn("core-site").anyTimes();
+ expect(blueprintConfig.getConfigData()).andReturn(new Gson().toJson(blueprintConfigProperties));
+
+ expect(blueprint.getHostGroups()).andReturn(Collections.singleton(hostGroup)).anyTimes();
+ expect(hostGroup.getName()).andReturn("group1").anyTimes();
+ expect(hostGroup.getComponents()).andReturn(hostGroupComponents).anyTimes();
+ expect(hostGroupComponent1.getName()).andReturn("component1").anyTimes();
+ expect(hostGroupComponent2.getName()).andReturn("component2").anyTimes();
+ expect(hostGroupComponent3.getName()).andReturn("component3").anyTimes();
+ expect(hostGroup.getConfigurations()).andReturn(
+ Collections.<HostGroupConfigEntity>singleton(hostGroupConfig)).anyTimes();
+
+ expect(hostGroupConfig.getType()).andReturn("core-site").anyTimes();
+ expect(hostGroupConfig.getConfigData()).andReturn(new Gson().toJson(mapGroupConfigProperties)).anyTimes();
+
+ replay(blueprintDAO, managementController, request, response, blueprint, stackServiceResponse1, stackServiceResponse2,
+ stackServiceComponentResponse1, stackServiceComponentResponse2, stackServiceComponentResponse3,
+ stackConfigurationResponse1, stackConfigurationResponse2, stackConfigurationResponse3, stackConfigurationResponse4,
+ blueprintConfig, hostGroup, hostGroupComponent1, hostGroupComponent2, hostGroupComponent3, hostGroupConfig,
+ serviceResourceProvider, componentResourceProvider, hostResourceProvider, hostComponentResourceProvider,
+ configGroupResourceProvider, persistKeyValue, metaInfo);
+
+ // test
+ ClusterResourceProvider.init(blueprintDAO, metaInfo);
+ ResourceProvider provider = new TestClusterResourceProvider(
+ managementController, serviceResourceProvider, componentResourceProvider,
+ hostResourceProvider, hostComponentResourceProvider, configGroupResourceProvider);
+
+ try {
+ provider.createResources(request);
+ fail("Expected exception for missing password property");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ verify(blueprintDAO, managementController, request, response, blueprint, stackServiceResponse1, stackServiceResponse2,
+ stackServiceComponentResponse1, stackServiceComponentResponse2, stackServiceComponentResponse3,
+ stackConfigurationResponse1, stackConfigurationResponse2, stackConfigurationResponse3, stackConfigurationResponse4,
+ blueprintConfig, hostGroup, hostGroupComponent1, hostGroupComponent2, hostGroupComponent3, hostGroupConfig,
+ serviceResourceProvider, componentResourceProvider, hostResourceProvider, hostComponentResourceProvider,
+ configGroupResourceProvider, persistKeyValue);
+ }
+
+ @Test
+ public void testCreateResource_blueprint__defaultPassword() throws Exception {
+ String blueprintName = "test-blueprint";
+ String stackName = "test";
+ String stackVersion = "1.23";
+ String clusterName = "c1";
+
+ BlueprintDAO blueprintDAO = createStrictMock(BlueprintDAO.class);
+ AmbariMetaInfo metaInfo = createMock(AmbariMetaInfo.class);
+ AmbariManagementController managementController = createStrictMock(AmbariManagementController.class);
+ Request request = createNiceMock(Request.class);
+ RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
+ BlueprintEntity blueprint = createNiceMock(BlueprintEntity.class);
+ StackServiceResponse stackServiceResponse1 = createNiceMock(StackServiceResponse.class);
+ StackServiceResponse stackServiceResponse2 = createNiceMock(StackServiceResponse.class);
+ Capture<Set<StackServiceRequest>> stackServiceRequestCapture = new Capture<Set<StackServiceRequest>>();
+
+ StackServiceComponentResponse stackServiceComponentResponse1 = createNiceMock(StackServiceComponentResponse.class);
+ StackServiceComponentResponse stackServiceComponentResponse2 = createNiceMock(StackServiceComponentResponse.class);
+ StackServiceComponentResponse stackServiceComponentResponse3 = createNiceMock(StackServiceComponentResponse.class);
+ Capture<Set<StackServiceComponentRequest>> serviceComponentRequestCapture1 = new Capture<Set<StackServiceComponentRequest>>();
+ Capture<Set<StackServiceComponentRequest>> serviceComponentRequestCapture2 = new Capture<Set<StackServiceComponentRequest>>();
+
+ StackConfigurationResponse stackConfigurationResponse1 = createNiceMock(StackConfigurationResponse.class);
+ StackConfigurationResponse stackConfigurationResponse2 = createNiceMock(StackConfigurationResponse.class);
+ StackConfigurationResponse stackConfigurationResponse3 = createNiceMock(StackConfigurationResponse.class);
+ StackConfigurationResponse stackConfigurationResponse4 = createNiceMock(StackConfigurationResponse.class);
+ Capture<Set<StackConfigurationRequest>> serviceConfigurationRequestCapture1 = new Capture<Set<StackConfigurationRequest>>();
+ Capture<Set<StackConfigurationRequest>> serviceConfigurationRequestCapture2 = new Capture<Set<StackConfigurationRequest>>();
+
+ BlueprintConfigEntity blueprintConfig = createNiceMock(BlueprintConfigEntity.class);
+
+ HostGroupEntity hostGroup = createNiceMock(HostGroupEntity.class);
+ HostGroupComponentEntity hostGroupComponent1 = createNiceMock(HostGroupComponentEntity.class);
+ HostGroupComponentEntity hostGroupComponent2 = createNiceMock(HostGroupComponentEntity.class);
+ HostGroupComponentEntity hostGroupComponent3 = createNiceMock(HostGroupComponentEntity.class);
+
+ HostGroupConfigEntity hostGroupConfig = createNiceMock(HostGroupConfigEntity.class);
+
+ ServiceResourceProvider serviceResourceProvider = createStrictMock(ServiceResourceProvider.class);
+ ResourceProvider componentResourceProvider = createStrictMock(ResourceProvider.class);
+ ResourceProvider hostResourceProvider = createStrictMock(ResourceProvider.class);
+ ResourceProvider hostComponentResourceProvider = createStrictMock(ResourceProvider.class);
+ ConfigGroupResourceProvider configGroupResourceProvider = createStrictMock(ConfigGroupResourceProvider.class);
+ PersistKeyValueImpl persistKeyValue = createNiceMock(PersistKeyValueImpl.class);
+
+ Capture<ClusterRequest> createClusterRequestCapture = new Capture<ClusterRequest>();
+ Capture<Set<ClusterRequest>> updateClusterRequestCapture = new Capture<Set<ClusterRequest>>();
+ Capture<Map<String, String>> updateClusterPropertyMapCapture = new Capture<Map<String, String>>();
+ Capture<Set<ClusterRequest>> updateClusterRequestCapture2 = new Capture<Set<ClusterRequest>>();
+ Capture<Map<String, String>> updateClusterPropertyMapCapture2 = new Capture<Map<String, String>>();
+ Capture<Set<ClusterRequest>> updateClusterRequestCapture3 = new Capture<Set<ClusterRequest>>();
+ Capture<Map<String, String>> updateClusterPropertyMapCapture3 = new Capture<Map<String, String>>();
+
+ Capture<Request> serviceRequestCapture = new Capture<Request>();
+ Capture<Request> componentRequestCapture = new Capture<Request>();
+ Capture<Request> componentRequestCapture2 = new Capture<Request>();
+ Capture<Request> hostRequestCapture = new Capture<Request>();
+ Capture<Request> hostComponentRequestCapture = new Capture<Request>();
+ Capture<Set<ConfigGroupRequest>> configGroupRequestCapture = new Capture<Set<ConfigGroupRequest>>();
+
+ Set<StackServiceResponse> stackServiceResponses = new LinkedHashSet<StackServiceResponse>();
+ stackServiceResponses.add(stackServiceResponse1);
+ stackServiceResponses.add(stackServiceResponse2);
+
+ // service1 has 2 components
+ Set<StackServiceComponentResponse> stackServiceComponentResponses1 = new LinkedHashSet<StackServiceComponentResponse>();
+ stackServiceComponentResponses1.add(stackServiceComponentResponse1);
+ stackServiceComponentResponses1.add(stackServiceComponentResponse2);
+
+ // service2 has 1 components
+ Set<StackServiceComponentResponse> stackServiceComponentResponses2 = new LinkedHashSet<StackServiceComponentResponse>();
+ stackServiceComponentResponses2.add(stackServiceComponentResponse3);
+
+ // service1 has 1 config
+ Set<StackConfigurationResponse> stackConfigurationResponses1 = new LinkedHashSet<StackConfigurationResponse>();
+ stackConfigurationResponses1.add(stackConfigurationResponse1);
+
+ // service2 has 3 config
+ Set<StackConfigurationResponse> stackConfigurationResponses2 = new LinkedHashSet<StackConfigurationResponse>();
+ stackConfigurationResponses2.add(stackConfigurationResponse2);
+ stackConfigurationResponses2.add(stackConfigurationResponse3);
+ stackConfigurationResponses2.add(stackConfigurationResponse4);
+
+ Collection<HostGroupComponentEntity> hostGroupComponents = new LinkedHashSet<HostGroupComponentEntity>();
+ hostGroupComponents.add(hostGroupComponent1);
+ hostGroupComponents.add(hostGroupComponent2);
+ hostGroupComponents.add(hostGroupComponent3);
+
+ // request properties
+ Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
+ Map<String, Object> properties = new LinkedHashMap<String, Object>();
+
+ properties.put(ClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID, clusterName);
+ properties.put(ClusterResourceProvider.BLUEPRINT_PROPERTY_ID, blueprintName);
+ properties.put("default_password", "foo");
+ propertySet.add(properties);
+
+ Collection<Map<String, Object>> hostGroups = new ArrayList<Map<String, Object>>();
+ Map<String, Object> hostGroupProperties = new HashMap<String, Object>();
+ hostGroups.add(hostGroupProperties);
+ hostGroupProperties.put("name", "group1");
+ Collection<Map<String, String>> hostGroupHosts = new ArrayList<Map<String, String>>();
+ hostGroupProperties.put("hosts", hostGroupHosts);
+ Map<String, String> hostGroupHostProperties = new HashMap<String, String>();
+ hostGroupHostProperties.put("fqdn", "host.domain");
+ hostGroupHosts.add(hostGroupHostProperties);
+ properties.put("host_groups", hostGroups);
+
+ Map<String, String> mapGroupConfigProperties = new HashMap<String, String>();
+ mapGroupConfigProperties.put("myGroupProp", "awesomeValue");
+
+ // blueprint cluster configuration properties
+ Map<String, String> blueprintConfigProperties = new HashMap<String, String>();
+ blueprintConfigProperties.put("property1", "value2");
+ blueprintConfigProperties.put("new.property", "new.property.value");
+
+ Map<String, Map<String, Collection<String>>> allMissingPasswords = new HashMap<String, Map<String, Collection<String>>>();
+ Map<String, Collection<String>> missingHGPasswords = new HashMap<String, Collection<String>>();
+ Collection<String> missingPasswords = new ArrayList<String>();
+ missingPasswords.add("my.missing.password");
+ missingHGPasswords.put("core-site", missingPasswords);
+ allMissingPasswords.put("group1", missingHGPasswords);
+
+ // expectations
+ expect(request.getProperties()).andReturn(propertySet).anyTimes();
+ expect(blueprintDAO.findByName(blueprintName)).andReturn(blueprint);
+ expect(blueprint.getStackName()).andReturn(stackName);
+ expect(blueprint.getStackVersion()).andReturn(stackVersion);
+ expect(blueprint.getConfigurations()).andReturn(Collections.<BlueprintConfigEntity>singletonList(blueprintConfig));
+ expect(blueprint.validateConfigurations(metaInfo, PropertyInfo.PropertyType.PASSWORD)).andReturn(allMissingPasswords);
+
+ expect(managementController.getStackServices(capture(stackServiceRequestCapture))).andReturn(stackServiceResponses);
+ expect(stackServiceResponse1.getServiceName()).andReturn("service1");
+ expect(stackServiceResponse2.getServiceName()).andReturn("service2");
+
+ expect(managementController.getStackComponents(capture(serviceComponentRequestCapture1))).
+ andReturn(stackServiceComponentResponses1);
+ expect(stackServiceComponentResponse1.getComponentName()).andReturn("component1");
+ expect(stackServiceComponentResponse2.getComponentName()).andReturn("component2");
+
+ expect(managementController.getStackConfigurations(capture(serviceConfigurationRequestCapture1))).
+ andReturn(stackConfigurationResponses1);
+ expect(stackConfigurationResponse1.getType()).andReturn("core-site.xml");
+ expect(stackConfigurationResponse1.getPropertyName()).andReturn("property1");
+ expect(stackConfigurationResponse1.getPropertyValue()).andReturn("value1");
+
+ expect(managementController.getStackComponents(capture(serviceComponentRequestCapture2))).
+ andReturn(stackServiceComponentResponses2);
+ expect(stackServiceComponentResponse3.getComponentName()).andReturn("component3");
+
+ expect(managementController.getStackConfigurations(capture(serviceConfigurationRequestCapture2))).
+ andReturn(stackConfigurationResponses2);
+ expect(stackConfigurationResponse2.getType()).andReturn("hdfs-site.xml");
+ expect(stackConfigurationResponse2.getPropertyName()).andReturn("property2");
+ expect(stackConfigurationResponse2.getPropertyValue()).andReturn("value2");
+
+ expect(stackConfigurationResponse3.getType()).andReturn("global.xml");
+ expect(stackConfigurationResponse3.getPropertyName()).andReturn("oozie_user");
+ expect(stackConfigurationResponse3.getPropertyValue()).andReturn("oozie");
+
+ expect(stackConfigurationResponse4.getType()).andReturn("core-site.xml");
+ expect(stackConfigurationResponse4.getPropertyName()).andReturn("property3");
+ expect(stackConfigurationResponse4.getPropertyValue()).andReturn("value3");
+
+ expect(blueprintConfig.getBlueprintName()).andReturn("test-blueprint").anyTimes();
+ expect(blueprintConfig.getType()).andReturn("core-site").anyTimes();
+ expect(blueprintConfig.getConfigData()).andReturn(new Gson().toJson(blueprintConfigProperties));
+
+ expect(blueprint.getHostGroups()).andReturn(Collections.singleton(hostGroup)).anyTimes();
+ expect(hostGroup.getName()).andReturn("group1").anyTimes();
+ expect(hostGroup.getComponents()).andReturn(hostGroupComponents).anyTimes();
+ expect(hostGroupComponent1.getName()).andReturn("component1").anyTimes();
+ expect(hostGroupComponent2.getName()).andReturn("component2").anyTimes();
+ expect(hostGroupComponent3.getName()).andReturn("component3").anyTimes();
+ expect(hostGroup.getConfigurations()).andReturn(
+ Collections.<HostGroupConfigEntity>singleton(hostGroupConfig)).anyTimes();
+
+ expect(hostGroupConfig.getType()).andReturn("core-site").anyTimes();
+ expect(hostGroupConfig.getConfigData()).andReturn(new Gson().toJson(mapGroupConfigProperties)).anyTimes();
+
+ managementController.createCluster(capture(createClusterRequestCapture));
+ expect(managementController.updateClusters(capture(updateClusterRequestCapture),
+ capture(updateClusterPropertyMapCapture))).andReturn(null);
+ expect(managementController.updateClusters(capture(updateClusterRequestCapture2),
+ capture(updateClusterPropertyMapCapture2))).andReturn(null);
+ expect(managementController.updateClusters(capture(updateClusterRequestCapture3),
+ capture(updateClusterPropertyMapCapture3))).andReturn(null);
+
+ expect(serviceResourceProvider.createResources(capture(serviceRequestCapture))).andReturn(null);
+ expect(componentResourceProvider.createResources(capture(componentRequestCapture))).andReturn(null);
+ expect(componentResourceProvider.createResources(capture(componentRequestCapture2))).andReturn(null);
+ expect(hostResourceProvider.createResources(capture(hostRequestCapture))).andReturn(null);
+ expect(hostComponentResourceProvider.createResources(capture(hostComponentRequestCapture))).andReturn(null);
+
+ expect(serviceResourceProvider.installAndStart(clusterName)).andReturn(response);
+
+ expect(configGroupResourceProvider.createResources(
+ capture(configGroupRequestCapture))).andReturn(null);
+
+ persistKeyValue.put("CLUSTER_CURRENT_STATUS", "{\"clusterState\":\"CLUSTER_STARTED_5\"}");
+
+ replay(blueprintDAO, managementController, request, response, blueprint, stackServiceResponse1, stackServiceResponse2,
+ stackServiceComponentResponse1, stackServiceComponentResponse2, stackServiceComponentResponse3,
+ stackConfigurationResponse1, stackConfigurationResponse2, stackConfigurationResponse3, stackConfigurationResponse4,
+ blueprintConfig, hostGroup, hostGroupComponent1, hostGroupComponent2, hostGroupComponent3, hostGroupConfig,
+ serviceResourceProvider, componentResourceProvider, hostResourceProvider, hostComponentResourceProvider,
+ configGroupResourceProvider, persistKeyValue, metaInfo);
+
+ // test
+ ClusterResourceProvider.init(blueprintDAO, metaInfo);
+ PersistKeyValueService.init(persistKeyValue);
+ ResourceProvider provider = new TestClusterResourceProvider(
+ managementController, serviceResourceProvider, componentResourceProvider,
+ hostResourceProvider, hostComponentResourceProvider, configGroupResourceProvider);
+
+ RequestStatus requestStatus = provider.createResources(request);
+
+ assertEquals(RequestStatus.Status.InProgress, requestStatus.getStatus());
+
+ Set<StackServiceRequest> stackServiceRequests = stackServiceRequestCapture.getValue();
+ assertEquals(1, stackServiceRequests.size());
+ StackServiceRequest ssr = stackServiceRequests.iterator().next();
+ assertNull(ssr.getServiceName());
+ assertEquals("test", ssr.getStackName());
+ assertEquals("1.23", ssr.getStackVersion());
+
+ Set<StackServiceComponentRequest> stackServiceComponentRequests1 = serviceComponentRequestCapture1.getValue();
+ Set<StackServiceComponentRequest> stackServiceComponentRequests2 = serviceComponentRequestCapture2.getValue();
+ assertEquals(1, stackServiceComponentRequests1.size());
+ assertEquals(1, stackServiceComponentRequests2.size());
+ StackServiceComponentRequest scr1 = stackServiceComponentRequests1.iterator().next();
+ StackServiceComponentRequest scr2 = stackServiceComponentRequests2.iterator().next();
+ assertNull(scr1.getComponentName());
+ assertNull(scr2.getComponentName());
+ assertEquals("1.23", scr1.getStackVersion());
+ assertEquals("1.23", scr2.getStackVersion());
+ assertEquals("test", scr1.getStackName());
+ assertEquals("test", scr2.getStackName());
+ assertTrue(scr1.getServiceName().equals("service1") || scr1.getServiceName().equals("service2"));
+ assertTrue(scr2.getServiceName().equals("service1") || scr2.getServiceName().equals("service2") &&
+ ! scr2.getServiceName().equals(scr1.getServiceName()));
+
+ Set<StackConfigurationRequest> serviceConfigurationRequest1 = serviceConfigurationRequestCapture1.getValue();
+ Set<StackConfigurationRequest> serviceConfigurationRequest2 = serviceConfigurationRequestCapture2.getValue();
+ assertEquals(1, serviceConfigurationRequest1.size());
+ assertEquals(1, serviceConfigurationRequest2.size());
+ StackConfigurationRequest configReq1 = serviceConfigurationRequest1.iterator().next();
+ StackConfigurationRequest configReq2 = serviceConfigurationRequest2.iterator().next();
+ assertNull(configReq1.getPropertyName());
+ assertNull(configReq2.getPropertyName());
+ assertEquals("1.23", configReq1.getStackVersion());
+ assertEquals("1.23", configReq2.getStackVersion());
+ assertEquals("test", configReq1.getStackName());
+ assertEquals("test", configReq2.getStackName());
+ assertTrue(configReq1.getServiceName().equals("service1") || configReq1.getServiceName().equals("service2"));
+ assertTrue(configReq2.getServiceName().equals("service1") || configReq2.getServiceName().equals("service2") &&
+ ! configReq2.getServiceName().equals(configReq1.getServiceName()));
+
+ ClusterRequest clusterRequest = createClusterRequestCapture.getValue();
+ assertEquals(clusterName, clusterRequest.getClusterName());
+ assertEquals("test-1.23", clusterRequest.getStackVersion());
+
+ Set<ClusterRequest> updateClusterRequest1 = updateClusterRequestCapture.getValue();
+ Set<ClusterRequest> updateClusterRequest2 = updateClusterRequestCapture2.getValue();
+ Set<ClusterRequest> updateClusterRequest3 = updateClusterRequestCapture3.getValue();
+ assertEquals(1, updateClusterRequest1.size());
+ assertEquals(1, updateClusterRequest2.size());
+ assertEquals(1, updateClusterRequest3.size());
+ ClusterRequest ucr1 = updateClusterRequest1.iterator().next();
+ ClusterRequest ucr2 = updateClusterRequest2.iterator().next();
+ ClusterRequest ucr3 = updateClusterRequest3.iterator().next();
+ assertEquals(clusterName, ucr1.getClusterName());
+ assertEquals(clusterName, ucr2.getClusterName());
+ assertEquals(clusterName, ucr3.getClusterName());
+ ConfigurationRequest cr1 = ucr1.getDesiredConfig();
+ ConfigurationRequest cr2 = ucr2.getDesiredConfig();
+ ConfigurationRequest cr3 = ucr3.getDesiredConfig();
+ assertEquals("1", cr1.getVersionTag());
+ assertEquals("1", cr2.getVersionTag());
+ assertEquals("1", cr3.getVersionTag());
+ Map<String, ConfigurationRequest> mapConfigRequests = new HashMap<String, ConfigurationRequest>();
+ mapConfigRequests.put(cr1.getType(), cr1);
+ mapConfigRequests.put(cr2.getType(), cr2);
+ mapConfigRequests.put(cr3.getType(), cr3);
+ assertEquals(3, mapConfigRequests.size());
+ ConfigurationRequest globalConfigRequest = mapConfigRequests.get("global");
+ assertEquals(5, globalConfigRequest.getProperties().size());
+ assertEquals("hadoop", globalConfigRequest.getProperties().get("user_group"));
+ assertEquals("ambari-qa", globalConfigRequest.getProperties().get("smokeuser"));
+ assertEquals("default@REPLACEME.NOWHERE", globalConfigRequest.getProperties().get("nagios_contact"));
+ assertEquals("admin", globalConfigRequest.getProperties().get("nagios_web_password"));
+ assertEquals("oozie", globalConfigRequest.getProperties().get("oozie_user"));
+ ConfigurationRequest hdfsConfigRequest = mapConfigRequests.get("hdfs-site");
+ assertEquals(1, hdfsConfigRequest.getProperties().size());
+ assertEquals("value2", hdfsConfigRequest.getProperties().get("property2"));
+ ConfigurationRequest coreConfigRequest = mapConfigRequests.get("core-site");
+ assertEquals(6, coreConfigRequest.getProperties().size());
+ assertEquals("value2", coreConfigRequest.getProperties().get("property1"));
+ assertEquals("value3", coreConfigRequest.getProperties().get("property3"));
+ assertEquals("*", coreConfigRequest.getProperties().get("hadoop.proxyuser.oozie.hosts"));
+ assertEquals("users", coreConfigRequest.getProperties().get("hadoop.proxyuser.oozie.groups"));
+ assertEquals("new.property.value", coreConfigRequest.getProperties().get("new.property"));
+ assertEquals("foo", coreConfigRequest.getProperties().get("my.missing.password"));
+ assertNull(updateClusterPropertyMapCapture.getValue());
+ assertNull(updateClusterPropertyMapCapture2.getValue());
+ assertNull(updateClusterPropertyMapCapture3.getValue());
+
+ Request serviceRequest = serviceRequestCapture.getValue();
+ assertEquals(2, serviceRequest.getProperties().size());
+ Request componentRequest = componentRequestCapture.getValue();
+ Request componentRequest2 = componentRequestCapture2.getValue();
+ assertEquals(2, componentRequest.getProperties().size());
+ Set<String> componentRequest1Names = new HashSet<String>();
+ for (Map<String, Object> componentRequest1Properties : componentRequest.getProperties()) {
+ assertEquals(3, componentRequest1Properties.size());
+ assertEquals(clusterName, componentRequest1Properties.get("ServiceComponentInfo/cluster_name"));
+ assertEquals("service1", componentRequest1Properties.get("ServiceComponentInfo/service_name"));
+ componentRequest1Names.add((String) componentRequest1Properties.get("ServiceComponentInfo/component_name"));
+ }
+ assertTrue(componentRequest1Names.contains("component1") && componentRequest1Names.contains("component2"));
+ assertEquals(1, componentRequest2.getProperties().size());
+ Map<String, Object> componentRequest2Properties = componentRequest2.getProperties().iterator().next();
+ assertEquals(clusterName, componentRequest2Properties.get("ServiceComponentInfo/cluster_name"));
+ assertEquals("service2", componentRequest2Properties.get("ServiceComponentInfo/service_name"));
+ assertEquals("component3", componentRequest2Properties.get("ServiceComponentInfo/component_name"));
+ Request hostRequest = hostRequestCapture.getValue();
+ assertEquals(1, hostRequest.getProperties().size());
+ assertEquals(clusterName, hostRequest.getProperties().iterator().next().get("Hosts/cluster_name"));
+ assertEquals("host.domain", hostRequest.getProperties().iterator().next().get("Hosts/host_name"));
+ Request hostComponentRequest = hostComponentRequestCapture.getValue();
+ assertEquals(3, hostComponentRequest.getProperties().size());
+ Set<String> componentNames = new HashSet<String>();
+ for (Map<String, Object> hostComponentProperties : hostComponentRequest.getProperties()) {
+ assertEquals(3, hostComponentProperties.size());
+ assertEquals(clusterName, hostComponentProperties.get("HostRoles/cluster_name"));
+ assertEquals("host.domain", hostComponentProperties.get("HostRoles/host_name"));
+ componentNames.add((String) hostComponentProperties.get("HostRoles/component_name"));
+ }
+ assertTrue(componentNames.contains("component1") && componentNames.contains("component2") &&
+ componentNames.contains("component3"));
+
+ Set<ConfigGroupRequest> configGroupRequests = configGroupRequestCapture.getValue();
+ assertEquals(1, configGroupRequests.size());
+ ConfigGroupRequest configGroupRequest = configGroupRequests.iterator().next();
+ assertEquals(clusterName, configGroupRequest.getClusterName());
+ assertEquals("group1", configGroupRequest.getGroupName());
+ assertEquals("service1", configGroupRequest.getTag());
+ assertEquals("Host Group Configuration", configGroupRequest.getDescription());
+ Set<String> hosts = configGroupRequest.getHosts();
+ assertEquals(1, hosts.size());
+ assertEquals("host.domain", hosts.iterator().next());
+ assertEquals(1, configGroupRequest.getConfigs().size());
+
+ verify(blueprintDAO, managementController, request, response, blueprint, stackServiceResponse1, stackServiceResponse2,
+ stackServiceComponentResponse1, stackServiceComponentResponse2, stackServiceComponentResponse3,
+ stackConfigurationResponse1, stackConfigurationResponse2, stackConfigurationResponse3, stackConfigurationResponse4,
+ blueprintConfig, hostGroup, hostGroupComponent1, hostGroupComponent2, hostGroupComponent3, hostGroupConfig,
+ serviceResourceProvider, componentResourceProvider, hostResourceProvider, hostComponentResourceProvider,
+ configGroupResourceProvider, persistKeyValue);
+ }
+
+ @Test
public void testCreateResource_blueprint_hostMappedToMultipleHG() throws Exception {
String blueprintName = "test-blueprint";
String stackName = "test";
@@ -700,7 +1260,7 @@ public class ClusterResourceProviderTest {
configGroupResourceProvider);
// test
- ClusterResourceProvider.injectBlueprintDAO(blueprintDAO);
+ ClusterResourceProvider.init(blueprintDAO, null);
ResourceProvider provider = new TestClusterResourceProvider(
managementController, serviceResourceProvider, componentResourceProvider,
hostResourceProvider, hostComponentResourceProvider, configGroupResourceProvider);
@@ -786,7 +1346,8 @@ public class ClusterResourceProviderTest {
entry = multiHostProperty2.entrySet().iterator().next();
newValue = propertyUpdaterMap.get(entry.getKey()).update(hostGroups, entry.getValue());
- Assert.assertEquals("['h1','h2']", newValue);
+ // no ordering guarantee
+ Assert.assertTrue(newValue.equals("['h1','h2']") || newValue.equals("['h2','h1']"));
entry = mProperty.entrySet().iterator().next();
newValue = propertyUpdaterMap.get(entry.getKey()).update(hostGroups, entry.getValue());
http://git-wip-us.apache.org/repos/asf/ambari/blob/4651447c/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java
index c61c109..cff9aad 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java
@@ -18,13 +18,24 @@
package org.apache.ambari.server.orm.entities;
+import com.google.gson.Gson;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.state.PropertyInfo;
import org.junit.Test;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
/**
* BlueprintEntity unit tests
@@ -67,4 +78,181 @@ public class BlueprintEntityTest {
assertSame(configurations, entity.getConfigurations());
}
+ @Test
+ public void testValidateConfigurations_clusterConfig() throws Exception {
+ AmbariMetaInfo metaInfo = createMock(AmbariMetaInfo.class);
+
+ Map<String, PropertyInfo> requiredProps = new HashMap<String, PropertyInfo>();
+ PropertyInfo prop = new PropertyInfo();
+ prop.setFilename("core-site.xml");
+ prop.setName("super.secret.password");
+ prop.setRequireInput(true);
+ prop.setType(PropertyInfo.PropertyType.PASSWORD);
+ prop.setValue(null);
+ requiredProps.put("service1", prop);
+
+ BlueprintEntity entity = new BlueprintEntity();
+ entity.setStackName("stackName");
+ entity.setStackVersion("version");
+
+ Collection<BlueprintConfigEntity> configurations = new HashSet<BlueprintConfigEntity>();
+ BlueprintConfigEntity configEntity = new BlueprintConfigEntity();
+ configEntity.setBlueprintEntity(entity);
+ configEntity.setBlueprintName("blueprint");
+ configEntity.setType("core-site");
+
+ Map<String, String> configData = new HashMap<String, String>();
+ configData.put("foo", "val1");
+ configData.put("bar", "val2");
+ configData.put("super.secret.password", "password");
+ configEntity.setConfigData(new Gson().toJson(configData));
+
+ configurations.add(configEntity);
+ entity.setConfigurations(configurations);
+
+ Collection<HostGroupEntity> hostGroupEntities = new HashSet<HostGroupEntity>();
+ HostGroupEntity hostGroupEntity = new HostGroupEntity();
+ Collection<HostGroupComponentEntity> hostGroupComponents = new HashSet<HostGroupComponentEntity>();
+ HostGroupComponentEntity componentEntity = new HostGroupComponentEntity();
+ componentEntity.setName("component1");
+ componentEntity.setBlueprintName("blueprint");
+ componentEntity.setHostGroupEntity(hostGroupEntity);
+ componentEntity.setHostGroupName("group1");
+ hostGroupComponents.add(componentEntity);
+ hostGroupEntity.setComponents(hostGroupComponents);
+ hostGroupEntity.setConfigurations(Collections.<HostGroupConfigEntity>emptyList());
+ hostGroupEntities.add(hostGroupEntity);
+ entity.setHostGroups(hostGroupEntities);
+
+ expect(metaInfo.getComponentToService("stackName", "version", "component1")).andReturn("service1");
+ expect(metaInfo.getRequiredProperties("stackName", "version", "service1")).andReturn(requiredProps);
+
+ replay(metaInfo);
+
+ Map<String, Map<String, Collection<String>>> missingProps = entity.validateConfigurations(
+ metaInfo, PropertyInfo.PropertyType.PASSWORD);
+
+ assertTrue(missingProps.isEmpty());
+
+ verify(metaInfo);
+ }
+
+ @Test
+ public void testValidateConfigurations_hostGroupConfig() throws Exception {
+ AmbariMetaInfo metaInfo = createMock(AmbariMetaInfo.class);
+
+ Map<String, PropertyInfo> requiredProps = new HashMap<String, PropertyInfo>();
+ PropertyInfo prop = new PropertyInfo();
+ prop.setFilename("core-site.xml");
+ prop.setName("super.secret.password");
+ prop.setRequireInput(true);
+ prop.setType(PropertyInfo.PropertyType.PASSWORD);
+ prop.setValue(null);
+ requiredProps.put("service1", prop);
+
+ BlueprintEntity entity = new BlueprintEntity();
+ entity.setStackName("stackName");
+ entity.setStackVersion("version");
+
+ entity.setConfigurations(Collections.<BlueprintConfigEntity>emptyList());
+
+ Collection<HostGroupEntity> hostGroupEntities = new HashSet<HostGroupEntity>();
+ HostGroupEntity hostGroupEntity = new HostGroupEntity();
+ Collection<HostGroupComponentEntity> hostGroupComponents = new HashSet<HostGroupComponentEntity>();
+ HostGroupComponentEntity componentEntity = new HostGroupComponentEntity();
+ componentEntity.setName("component1");
+ componentEntity.setBlueprintName("blueprint");
+ componentEntity.setHostGroupEntity(hostGroupEntity);
+ componentEntity.setHostGroupName("group1");
+ hostGroupComponents.add(componentEntity);
+ hostGroupEntity.setComponents(hostGroupComponents);
+
+ Collection<HostGroupConfigEntity> configurations = new HashSet<HostGroupConfigEntity>();
+ HostGroupConfigEntity configEntity = new HostGroupConfigEntity();
+ configEntity.setHostGroupEntity(hostGroupEntity);
+ configEntity.setBlueprintName("blueprint");
+ configEntity.setType("core-site");
+
+ Map<String, String> configData = new HashMap<String, String>();
+ configData.put("foo", "val1");
+ configData.put("bar", "val2");
+ configData.put("super.secret.password", "password");
+ configEntity.setConfigData(new Gson().toJson(configData));
+ configurations.add(configEntity);
+
+ hostGroupEntity.setConfigurations(configurations);
+ hostGroupEntities.add(hostGroupEntity);
+ entity.setHostGroups(hostGroupEntities);
+
+ expect(metaInfo.getComponentToService("stackName", "version", "component1")).andReturn("service1");
+ expect(metaInfo.getRequiredProperties("stackName", "version", "service1")).andReturn(requiredProps);
+
+ replay(metaInfo);
+
+ Map<String, Map<String, Collection<String>>> missingProps = entity.validateConfigurations(
+ metaInfo, PropertyInfo.PropertyType.PASSWORD);
+
+ assertTrue(missingProps.isEmpty());
+
+ verify(metaInfo);
+ }
+
+ @Test
+ public void testValidateConfigurations_negative() throws Exception {
+ AmbariMetaInfo metaInfo = createMock(AmbariMetaInfo.class);
+
+ Map<String, PropertyInfo> requiredProps = new HashMap<String, PropertyInfo>();
+ PropertyInfo prop = new PropertyInfo();
+ prop.setFilename("core-site.xml");
+ prop.setName("super.secret.password");
+ prop.setRequireInput(true);
+ prop.setType(PropertyInfo.PropertyType.PASSWORD);
+ prop.setValue(null);
+ requiredProps.put("service1", prop);
+
+ BlueprintEntity entity = new BlueprintEntity();
+ entity.setStackName("stackName");
+ entity.setStackVersion("version");
+
+ Collection<BlueprintConfigEntity> configurations = new HashSet<BlueprintConfigEntity>();
+ BlueprintConfigEntity configEntity = new BlueprintConfigEntity();
+ configEntity.setBlueprintEntity(entity);
+ configEntity.setBlueprintName("blueprint");
+ configEntity.setType("core-site");
+
+ Map<String, String> configData = new HashMap<String, String>();
+ configData.put("foo", "val1");
+ configData.put("bar", "val2");
+ configData.put("some.other.secret.password", "password");
+ configEntity.setConfigData(new Gson().toJson(configData));
+
+ configurations.add(configEntity);
+ entity.setConfigurations(configurations);
+
+ Collection<HostGroupEntity> hostGroupEntities = new HashSet<HostGroupEntity>();
+ HostGroupEntity hostGroupEntity = new HostGroupEntity();
+ Collection<HostGroupComponentEntity> hostGroupComponents = new HashSet<HostGroupComponentEntity>();
+ HostGroupComponentEntity componentEntity = new HostGroupComponentEntity();
+ componentEntity.setName("component1");
+ componentEntity.setBlueprintName("blueprint");
+ componentEntity.setHostGroupEntity(hostGroupEntity);
+ componentEntity.setHostGroupName("group1");
+ hostGroupComponents.add(componentEntity);
+ hostGroupEntity.setComponents(hostGroupComponents);
+ hostGroupEntity.setConfigurations(Collections.<HostGroupConfigEntity>emptyList());
+ hostGroupEntities.add(hostGroupEntity);
+ entity.setHostGroups(hostGroupEntities);
+
+ expect(metaInfo.getComponentToService("stackName", "version", "component1")).andReturn("service1");
+ expect(metaInfo.getRequiredProperties("stackName", "version", "service1")).andReturn(requiredProps);
+
+ replay(metaInfo);
+
+ Map<String, Map<String, Collection<String>>> missingProps = entity.validateConfigurations(
+ metaInfo, PropertyInfo.PropertyType.PASSWORD);
+
+ assertEquals(1, missingProps.size());
+
+ verify(metaInfo);
+ }
}