You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by be...@apache.org on 2018/05/07 08:58:43 UTC

[ambari] branch trunk updated: [AMBARI-23595] Generic method to replace HOSTGROUP variable in blueprints (#1074)

This is an automated email from the ASF dual-hosted git repository.

benyoka pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 01bdcc0  [AMBARI-23595] Generic method to replace HOSTGROUP variable in blueprints (#1074)
01bdcc0 is described below

commit 01bdcc0a8a90c777598cfca24ff0d3da88f135a6
Author: benyoka <be...@users.noreply.github.com>
AuthorDate: Mon May 7 10:58:40 2018 +0200

    [AMBARI-23595] Generic method to replace HOSTGROUP variable in blueprints (#1074)
    
    * AMBARI-23595 add default updater to replace %HOSTGROUP tokens (benyoka)
    
    * AMBARI-23595 changed the algorithm a bit (benyoka)
    
    * AMBARI-23595 fix review comments + update getRequiredHostGroups (benyoka)
    
    * AMBARI-23595 some minor fixes (benyoka)
    
    * AMBARI-23595 more review fixes (benyoka)
---
 .../internal/BlueprintConfigurationProcessor.java  | 656 +++++++++++++--------
 .../BlueprintConfigurationProcessorTest.java       | 641 ++++++++++++++------
 2 files changed, 872 insertions(+), 425 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
index c5399d0..24dcceb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
@@ -20,6 +20,7 @@ package org.apache.ambari.server.controller.internal;
 
 
 import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.toSet;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -53,9 +54,11 @@ import org.apache.ambari.server.topology.HostGroup;
 import org.apache.ambari.server.topology.HostGroupInfo;
 import org.apache.ambari.server.topology.validators.UnitValidatedProperty;
 import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Preconditions;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -96,6 +99,7 @@ public class BlueprintConfigurationProcessor {
   private final static String HDFS_STANDBY_NAMENODE_PROPERTY_NAME = "dfs_ha_initial_namenode_standby";
   private final static String HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME = "dfs_ha_initial_namenode_active_set";
   private final static String HDFS_STANDBY_NAMENODE_SET_PROPERTY_NAME = "dfs_ha_initial_namenode_standby_set";
+
   private final static String HDFS_HA_INITIAL_CLUSTER_ID_PROPERTY_NAME = "dfs_ha_initial_cluster_id";
   private final static Set<String> HDFS_HA_INITIAL_PROPERTIES = ImmutableSet.of(
       HDFS_ACTIVE_NAMENODE_PROPERTY_NAME, HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME,
@@ -192,29 +196,29 @@ public class BlueprintConfigurationProcessor {
    * could be extended in the future for more generic purposes.
    */
   private PropertyFilter[] getExportPropertyFilters (Map<Long, Set<String>> authToLocalPerClusterMap)
-    {
-      return new PropertyFilter[] {
-        new PasswordPropertyFilter(),
-        new SimplePropertyNameExportFilter("tez.tez-ui.history-url.base", "tez-site"),
-        new SimplePropertyNameExportFilter("admin_server_host", "kerberos-env"),
-        new SimplePropertyNameExportFilter("kdc_hosts", "kerberos-env"),
-        new SimplePropertyNameExportFilter("master_kdc", "kerberos-env"),
-        new SimplePropertyNameExportFilter("realm", "kerberos-env"),
-        new SimplePropertyNameExportFilter("kdc_type", "kerberos-env"),
-        new SimplePropertyNameExportFilter("ldap-url", "kerberos-env"),
-        new SimplePropertyNameExportFilter("container_dn", "kerberos-env"),
-        new SimplePropertyNameExportFilter("domains", "krb5-conf"),
-        new SimplePropertyNameExportFilter(HDFS_ACTIVE_NAMENODE_PROPERTY_NAME, HADOOP_ENV_CONFIG_TYPE_NAME),
-        new SimplePropertyNameExportFilter(HDFS_STANDBY_NAMENODE_PROPERTY_NAME, HADOOP_ENV_CONFIG_TYPE_NAME),
-        new SimplePropertyNameExportFilter(HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME, HADOOP_ENV_CONFIG_TYPE_NAME),
-        new SimplePropertyNameExportFilter(HDFS_STANDBY_NAMENODE_SET_PROPERTY_NAME, HADOOP_ENV_CONFIG_TYPE_NAME),
-        new SimplePropertyNameExportFilter(HDFS_ACTIVE_NAMENODE_PROPERTY_NAME, HDFS_HA_INITIAL_CONFIG_TYPE),
-        new SimplePropertyNameExportFilter(HDFS_STANDBY_NAMENODE_PROPERTY_NAME, HDFS_HA_INITIAL_CONFIG_TYPE),
-        new SimplePropertyNameExportFilter(HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME, HDFS_HA_INITIAL_CONFIG_TYPE),
-        new SimplePropertyNameExportFilter(HDFS_STANDBY_NAMENODE_SET_PROPERTY_NAME, HDFS_HA_INITIAL_CONFIG_TYPE),
-        new StackPropertyTypeFilter(),
-        new KerberosAuthToLocalRulesFilter(authToLocalPerClusterMap)};
-    }
+  {
+    return new PropertyFilter[] {
+      new PasswordPropertyFilter(),
+      new SimplePropertyNameExportFilter("tez.tez-ui.history-url.base", "tez-site"),
+      new SimplePropertyNameExportFilter("admin_server_host", "kerberos-env"),
+      new SimplePropertyNameExportFilter("kdc_hosts", "kerberos-env"),
+      new SimplePropertyNameExportFilter("master_kdc", "kerberos-env"),
+      new SimplePropertyNameExportFilter("realm", "kerberos-env"),
+      new SimplePropertyNameExportFilter("kdc_type", "kerberos-env"),
+      new SimplePropertyNameExportFilter("ldap-url", "kerberos-env"),
+      new SimplePropertyNameExportFilter("container_dn", "kerberos-env"),
+      new SimplePropertyNameExportFilter("domains", "krb5-conf"),
+      new SimplePropertyNameExportFilter(HDFS_ACTIVE_NAMENODE_PROPERTY_NAME, HADOOP_ENV_CONFIG_TYPE_NAME),
+      new SimplePropertyNameExportFilter(HDFS_STANDBY_NAMENODE_PROPERTY_NAME, HADOOP_ENV_CONFIG_TYPE_NAME),
+      new SimplePropertyNameExportFilter(HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME, HADOOP_ENV_CONFIG_TYPE_NAME),
+      new SimplePropertyNameExportFilter(HDFS_STANDBY_NAMENODE_SET_PROPERTY_NAME, HADOOP_ENV_CONFIG_TYPE_NAME),
+      new SimplePropertyNameExportFilter(HDFS_ACTIVE_NAMENODE_PROPERTY_NAME, HDFS_HA_INITIAL_CONFIG_TYPE),
+      new SimplePropertyNameExportFilter(HDFS_STANDBY_NAMENODE_PROPERTY_NAME, HDFS_HA_INITIAL_CONFIG_TYPE),
+      new SimplePropertyNameExportFilter(HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME, HDFS_HA_INITIAL_CONFIG_TYPE),
+      new SimplePropertyNameExportFilter(HDFS_STANDBY_NAMENODE_SET_PROPERTY_NAME, HDFS_HA_INITIAL_CONFIG_TYPE),
+      new StackPropertyTypeFilter(),
+      new KerberosAuthToLocalRulesFilter(authToLocalPerClusterMap)};
+  }
 
   /**
    * Statically-defined list of filters to apply on cluster config
@@ -323,10 +327,13 @@ public class BlueprintConfigurationProcessor {
     return false;
   }
 
-  public Collection<String> getRequiredHostGroups() {
-    Collection<String> requiredHostGroups = new HashSet<>();
+  public Set<String> getRequiredHostGroups() {
+    Set<String> requiredHostGroups = new HashSet<>();
+    Collection<Map<String, Map<String, PropertyUpdater>>> updaters = createCollectionOfUpdaters();
 
-    for (Map<String, Map<String, PropertyUpdater>> updaterMap : createCollectionOfUpdaters()) {
+    // Iterate all registered updaters and collect host groups referenced by related properties and
+    // extracted by the updaters
+    for (Map<String, Map<String, PropertyUpdater>> updaterMap : updaters) {
       for (Map.Entry<String, Map<String, PropertyUpdater>> entry : updaterMap.entrySet()) {
         String type = entry.getKey();
         for (Map.Entry<String, PropertyUpdater> updaterEntry : entry.getValue().entrySet()) {
@@ -338,7 +345,7 @@ public class BlueprintConfigurationProcessor {
           Map<String, String> typeMap = clusterProps.get(type);
           if (typeMap != null && typeMap.containsKey(propertyName) && typeMap.get(propertyName) != null) {
             requiredHostGroups.addAll(updater.getRequiredHostGroups(
-                propertyName, typeMap.get(propertyName), clusterProps, clusterTopology));
+              propertyName, typeMap.get(propertyName), clusterProps, clusterTopology));
           }
 
           // host group configs
@@ -347,25 +354,71 @@ public class BlueprintConfigurationProcessor {
             Map<String, String> hgTypeMap = hgConfigProps.get(type);
             if (hgTypeMap != null && hgTypeMap.containsKey(propertyName)) {
               requiredHostGroups.addAll(updater.getRequiredHostGroups(
-                  propertyName, hgTypeMap.get(propertyName), hgConfigProps, clusterTopology));
+                propertyName, hgTypeMap.get(propertyName), hgConfigProps, clusterTopology));
             }
           }
         }
       }
     }
+
+    // Iterate through all user defined properties (blueprint + cluster template only, no stack defaults) that do not
+    // have a registered updater. These properties can reference host groups too which should be extracted by the default
+    // updater
+    Set<Pair<String, String>> propertiesWithUpdaters = getAllPropertiesWithUpdaters(updaters);
+
+    // apply default updater on cluster config
+    Map<String, Map<String, String>> userDefinedClusterProperties = clusterTopology.getConfiguration().getFullProperties(1);
+    addRequiredHostgroupsByDefaultUpdater(userDefinedClusterProperties, propertiesWithUpdaters, requiredHostGroups);
+    // apply default updater on hostgroup configs
+    clusterTopology.getHostGroupInfo().values().stream().forEach(
+      hostGroup -> {
+        Configuration hostGroupConfig = hostGroup.getConfiguration();
+        Map<String, Map<String, String>> hostGroupConfigProps = hostGroupConfig.getFullProperties(1);
+        addRequiredHostgroupsByDefaultUpdater(hostGroupConfigProps, propertiesWithUpdaters, requiredHostGroups);
+      });
     return requiredHostGroups;
   }
 
   /**
+   * Adds required host groups based on user defined (in the blueprint or cluster template) configuration properties and
+   * the default property updaters. Only those properties are considered which don't have a configured updater.
+   * @param properties properties to scan for host group references
+   * @param propertiesWithUpdaters properties in (configType, propertyName) which have a configured updater
+   * @param hostGroupAccumulator collection to accumulate required host groups
+   */
+  private void addRequiredHostgroupsByDefaultUpdater(Map<String, Map<String, String>> properties,
+                                                     Set<Pair<String, String>> propertiesWithUpdaters,
+                                                     Set<String> hostGroupAccumulator) {
+    properties.entrySet().forEach(
+      configTypeEntry -> {
+        String configType = configTypeEntry.getKey();
+        configTypeEntry.getValue().entrySet().forEach(
+          propertyEntry -> {
+            String propertyName = propertyEntry.getKey();
+            String oldValue = propertyEntry.getValue();
+            if (!propertiesWithUpdaters.contains(Pair.of(configType, propertyName))) {
+              Collection<String> requiredHostGroups =
+                PropertyUpdater.defaultUpdater().getRequiredHostGroups(propertyName, oldValue, properties, clusterTopology);
+              if (!requiredHostGroups.isEmpty()) {
+                LOG.info("The following host groups are required by applying the default property updater on {}/{} property: {}",
+                  configType, propertyName, requiredHostGroups);
+              }
+              hostGroupAccumulator.addAll(requiredHostGroups);
+            }
+          });
+      });
+  }
+
+
+  /**
    * Update properties for cluster creation.  This involves updating topology related properties with
    * concrete topology information.
    *
    * @return Set of config type names that were updated by this update call
    */
   public Set<String> doUpdateForClusterCreate() throws ConfigurationTopologyException {
-      Set<String> configTypesUpdated = new HashSet<>();
+    Set<String> configTypesUpdated = new HashSet<>();
     Configuration clusterConfig = clusterTopology.getConfiguration();
-    Map<String, HostGroupInfo> groupInfoMap = clusterTopology.getHostGroupInfo();
 
     doRecommendConfigurations(clusterConfig, configTypesUpdated);
 
@@ -384,153 +437,248 @@ public class BlueprintConfigurationProcessor {
     // removes a property other than the property it is registered for then we will
     // have an issue as it won't be removed from the clusterProps map as it is a copy.
     Map<String, Map<String, String>> clusterProps = clusterConfig.getFullProperties();
+    doGeneralPropertyUpdatesForClusterCreate(clusterConfig, clusterProps, configTypesUpdated);
 
-    for (Map<String, Map<String, PropertyUpdater>> updaterMap : createCollectionOfUpdaters()) {
+    //todo: lots of hard coded HA rules included here
+    if (clusterTopology.isNameNodeHAEnabled()) {
+      doNameNodeHAUpdateOnClusterCreation(clusterConfig, clusterProps, configTypesUpdated);
+    }
+
+    // Explicitly set any properties that are required but not currently provided in the stack definition.
+    setStackToolsAndFeatures(clusterConfig, configTypesUpdated);
+    setRetryConfiguration(clusterConfig, configTypesUpdated);
+    setupHDFSProxyUsers(clusterConfig, configTypesUpdated);
+    addExcludedConfigProperties(clusterConfig, configTypesUpdated, clusterTopology.getBlueprint().getStack());
+
+    trimProperties(clusterConfig, clusterTopology);
+
+    return configTypesUpdated;
+  }
+
+  /**
+   * Update Namenode HA properties during cluster creation
+   * @throws ConfigurationTopologyException
+   */
+  private void doNameNodeHAUpdateOnClusterCreation(Configuration clusterConfig,
+                                                   Map<String, Map<String, String>> clusterProps,
+                                                   Set<String> configTypesUpdated) throws ConfigurationTopologyException {
+    // add "dfs.internal.nameservices" if it's not specified
+    Map<String, String> hdfsSiteConfig = clusterConfig.getFullProperties().get("hdfs-site");
+    String nameservices = hdfsSiteConfig.get("dfs.nameservices");
+    String int_nameservices = hdfsSiteConfig.get("dfs.internal.nameservices");
+    if(int_nameservices == null && nameservices != null) {
+      clusterConfig.setProperty("hdfs-site", "dfs.internal.nameservices", nameservices);
+    }
+
+    // parse out the nameservices value
+    String[] parsedNameServices = parseNameServices(hdfsSiteConfig);
+
+    // if a single nameservice is configured (default HDFS HA deployment)
+    if (parsedNameServices.length == 1) {
+      LOG.info("Processing a single HDFS NameService, which indicates a default HDFS NameNode HA deployment");
+      // if the active/standby namenodes are not specified, assign them automatically
+      if (! isNameNodeHAInitialActiveNodeSet(clusterProps) && ! isNameNodeHAInitialStandbyNodeSet(clusterProps)) {
+        Collection<String> nnHosts = clusterTopology.getHostAssignmentsForComponent("NAMENODE");
+        if (nnHosts.size() < 2) {
+          throw new ConfigurationTopologyException("NAMENODE HA requires at least 2 hosts running NAMENODE but there are: " +
+            nnHosts.size() + " Hosts: " + nnHosts);
+        }
+
+        // set the properties that configure which namenode is active,
+        // and which is a standby node in this HA deployment
+        Iterator<String> nnHostIterator = nnHosts.iterator();
+        clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_ACTIVE_NAMENODE_PROPERTY_NAME, nnHostIterator.next());
+        clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_STANDBY_NAMENODE_PROPERTY_NAME, nnHostIterator.next());
+
+        configTypesUpdated.add(HDFS_HA_INITIAL_CONFIG_TYPE);
+      }
+    } else {
+      if (!isPropertySet(clusterProps, HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME) && !isPropertySet(clusterProps, HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_STANDBY_NAMENODE_SET_PROPERTY_NAME)) {        // multiple nameservices indicates an HDFS NameNode Federation install
+        // process each nameservice to determine the active/standby nodes
+        LOG.info("Processing multiple HDFS NameService instances, which indicates a NameNode Federation deployment");
+        if (parsedNameServices.length > 1) {
+          Set<String> activeNameNodeHostnames = new HashSet<>();
+          Set<String> standbyNameNodeHostnames = new HashSet<>();
+
+          for (String nameService : parsedNameServices) {
+            List<String> hostNames = new ArrayList<>();
+            String[] nameNodes = parseNameNodes(nameService, hdfsSiteConfig);
+            for (String nameNode : nameNodes) {
+              // use the HA rpc-address property to obtain the NameNode hostnames
+              String propertyName = "dfs.namenode.rpc-address." + nameService + "." + nameNode;
+              String propertyValue = hdfsSiteConfig.get(propertyName);
+              if (propertyValue == null) {
+                throw new ConfigurationTopologyException("NameNode HA property = " + propertyName + " is not found in the cluster config.  This indicates an error in configuration for HA/Federated clusters.  " +
+                  "Please recheck the HDFS configuration and try this deployment again");
+              }
+
+              String hostName = propertyValue.split(":")[0];
+              hostNames.add(hostName);
+            }
+
+            if (hostNames.size() < 2) {
+              throw new ConfigurationTopologyException("NAMENODE HA for nameservice = " + nameService + " requires at least 2 hosts running NAMENODE but there are: " +
+                hostNames.size() + " Hosts: " + hostNames);
+            } else {
+              // by default, select the active and standby namenodes for this nameservice
+              // using the first two hostnames found
+              // since HA is assumed, there should only be two NameNodes deployed per NameService
+              activeNameNodeHostnames.add(hostNames.get(0));
+              standbyNameNodeHostnames.add(hostNames.get(1));
+            }
+          }
+
+          // set the properties what configure the NameNode Active/Standby status for each nameservice
+          if (!activeNameNodeHostnames.isEmpty() && !standbyNameNodeHostnames.isEmpty()) {
+            clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME, String.join(",", activeNameNodeHostnames));
+            clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_STANDBY_NAMENODE_SET_PROPERTY_NAME, String.join(",", standbyNameNodeHostnames));
+
+            // also set the clusterID property, required for Federation installs of HDFS
+            if (!isPropertySet(clusterProps, HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_HA_INITIAL_CLUSTER_ID_PROPERTY_NAME)) {
+              clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_HA_INITIAL_CLUSTER_ID_PROPERTY_NAME, getClusterName());
+            }
+
+            configTypesUpdated.add(HDFS_HA_INITIAL_CONFIG_TYPE);
+          } else {
+            LOG.warn("Error in processing the set of active/standby namenodes in this federated cluster, please check hdfs-site configuration");
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Call registered updaters on cluster configuration + call default updater ({@link HostGroupUpdater#INSTANCE}) on
+   * properties that were submitted in the blueprint or the cluster template and don't have a registered updater.
+   */
+  private void doGeneralPropertyUpdatesForClusterCreate(Configuration clusterConfig,
+                                                        Map<String, Map<String, String>> clusterProps,
+                                                        Set<String> configTypesUpdated) {
+    // Iterate through the updaters and apply them in case applicable properties exist
+    Collection<Map<String, Map<String, PropertyUpdater>>> updaters = createCollectionOfUpdaters();
+    for (Map<String, Map<String, PropertyUpdater>> updaterMap : updaters) {
       for (Map.Entry<String, Map<String, PropertyUpdater>> entry : updaterMap.entrySet()) {
-        String type = entry.getKey();
+        final String configType = entry.getKey();
         for (Map.Entry<String, PropertyUpdater> updaterEntry : entry.getValue().entrySet()) {
           String propertyName = updaterEntry.getKey();
           PropertyUpdater updater = updaterEntry.getValue();
 
           // topo cluster scoped configuration which also includes all default and BP properties
-          Map<String, String> typeMap = clusterProps.get(type);
+          Map<String, String> typeMap = clusterProps.get(configType);
           if (typeMap != null && typeMap.containsKey(propertyName) && typeMap.get(propertyName) != null) {
             final String originalValue = typeMap.get(propertyName);
             final String updatedValue =
-              updater.updateForClusterCreate(propertyName, originalValue, clusterProps, clusterTopology);
-
-            if(updatedValue == null ) {
+              updateValue(configType, propertyName, originalValue, updater, clusterProps, clusterConfig, configTypesUpdated, true);
+            if (null == updatedValue) {
               continue;
             }
-
-            if (!updatedValue.equals(originalValue)) {
-              configTypesUpdated.add(type);
-            }
-
-            clusterConfig.setProperty(type, propertyName, updatedValue);
           }
-
           // host group configs
-          for (HostGroupInfo groupInfo : groupInfoMap.values()) {
+          for (HostGroupInfo groupInfo : clusterTopology.getHostGroupInfo().values()) {
             Configuration hgConfig = groupInfo.getConfiguration();
             Map<String, Map<String, String>> hgConfigProps = hgConfig.getFullProperties(1);
-            Map<String, String> hgTypeMap = hgConfigProps.get(type);
+            Map<String, String> hgTypeMap = hgConfigProps.get(configType);
             if (hgTypeMap != null && hgTypeMap.containsKey(propertyName)) {
               final String originalValue = hgTypeMap.get(propertyName);
-              final String updatedValue =
-                updater.updateForClusterCreate(propertyName, originalValue, hgConfigProps, clusterTopology);
-
-              if (!updatedValue.equals(originalValue)) {
-                configTypesUpdated.add(type);
-              }
-
-              hgConfig.setProperty(type, propertyName, updatedValue);
+              updateValue(configType, propertyName, originalValue, updater, hgConfigProps, hgConfig, configTypesUpdated, true);
             }
           }
         }
       }
     }
 
-    //todo: lots of hard coded HA rules included here
-    if (clusterTopology.isNameNodeHAEnabled()) {
-
-      // add "dfs.internal.nameservices" if it's not specified
-      Map<String, String> hdfsSiteConfig = clusterConfig.getFullProperties().get("hdfs-site");
-      String nameservices = hdfsSiteConfig.get("dfs.nameservices");
-      String int_nameservices = hdfsSiteConfig.get("dfs.internal.nameservices");
-      if(int_nameservices == null && nameservices != null) {
-        clusterConfig.setProperty("hdfs-site", "dfs.internal.nameservices", nameservices);
-      }
-
-      // parse out the nameservices value
-      String[] parsedNameServices = parseNameServices(hdfsSiteConfig);
-
-      // if a single nameservice is configured (default HDFS HA deployment)
-      if (parsedNameServices.length == 1) {
-        LOG.info("Processing a single HDFS NameService, which indicates a default HDFS NameNode HA deployment");
-        // if the active/stanbdy namenodes are not specified, assign them automatically
-        if (! isNameNodeHAInitialActiveNodeSet(clusterProps) && ! isNameNodeHAInitialStandbyNodeSet(clusterProps)) {
-          Collection<String> nnHosts = clusterTopology.getHostAssignmentsForComponent("NAMENODE");
-          if (nnHosts.size() < 2) {
-            throw new ConfigurationTopologyException("NAMENODE HA requires at least 2 hosts running NAMENODE but there are: " +
-                nnHosts.size() + " Hosts: " + nnHosts);
-          }
-
-          // set the properties that configure which namenode is active,
-          // and which is a standby node in this HA deployment
-          Iterator<String> nnHostIterator = nnHosts.iterator();
-          clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_ACTIVE_NAMENODE_PROPERTY_NAME, nnHostIterator.next());
-          clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_STANDBY_NAMENODE_PROPERTY_NAME, nnHostIterator.next());
-
-          configTypesUpdated.add(HDFS_HA_INITIAL_CONFIG_TYPE);
-        }
-      } else {
-        if (!isPropertySet(clusterProps, HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME) && !isPropertySet(clusterProps, HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_STANDBY_NAMENODE_SET_PROPERTY_NAME)) {
-          // multiple nameservices indicates an HDFS NameNode Federation install
-          // process each nameservice to determine the active/standby nodes
-          LOG.info("Processing multiple HDFS NameService instances, which indicates a NameNode Federation deployment");
-          if (parsedNameServices.length > 1) {
-            Set<String> activeNameNodeHostnames = new HashSet<>();
-            Set<String> standbyNameNodeHostnames = new HashSet<>();
-
-            for (String nameService : parsedNameServices) {
-              List<String> hostNames = new ArrayList<>();
-              String[] nameNodes = parseNameNodes(nameService, hdfsSiteConfig);
-              for (String nameNode : nameNodes) {
-                // use the HA rpc-address property to obtain the NameNode hostnames
-                String propertyName = "dfs.namenode.rpc-address." + nameService + "." + nameNode;
-                String propertyValue = hdfsSiteConfig.get(propertyName);
-                if (propertyValue == null) {
-                  throw new ConfigurationTopologyException("NameNode HA property = " + propertyName + " is not found in the cluster config.  This indicates an error in configuration for HA/Federated clusters.  " +
-                    "Please recheck the HDFS configuration and try this deployment again");
-                }
-
-                String hostName = propertyValue.split(":")[0];
-                hostNames.add(hostName);
-              }
-
-              if (hostNames.size() < 2) {
-                throw new ConfigurationTopologyException("NAMENODE HA for nameservice = " + nameService + " requires at least 2 hosts running NAMENODE but there are: " +
-                  hostNames.size() + " Hosts: " + hostNames);
-              } else {
-                // by default, select the active and standby namenodes for this nameservice
-                // using the first two hostnames found
-                // since HA is assumed, there should only be two NameNodes deployed per NameService
-                activeNameNodeHostnames.add(hostNames.get(0));
-                standbyNameNodeHostnames.add(hostNames.get(1));
-              }
-            }
-
-            // set the properties what configure the NameNode Active/Standby status for each nameservice
-            if (!activeNameNodeHostnames.isEmpty() && !standbyNameNodeHostnames.isEmpty()) {
-              clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_ACTIVE_NAMENODE_SET_PROPERTY_NAME, String.join(",", activeNameNodeHostnames));
-              clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_STANDBY_NAMENODE_SET_PROPERTY_NAME, String.join(",", standbyNameNodeHostnames));
-
-              // also set the clusterID property, required for Federation installs of HDFS
-              if (!isPropertySet(clusterProps, HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_HA_INITIAL_CLUSTER_ID_PROPERTY_NAME)) {
-                clusterConfig.setProperty(HDFS_HA_INITIAL_CONFIG_TYPE, HDFS_HA_INITIAL_CLUSTER_ID_PROPERTY_NAME, getClusterName());
+    // Iterate through all user defined properties (blueprint + cluster template) and call the default updater for those
+    // which don't have a configured updater. This is to make sure that %HOSTGROUP::name% tokens are replaced for each property
+    Set<Pair<String, String>> propertiesWithUpdaters = getAllPropertiesWithUpdaters(updaters);
+    // apply default updater on cluster config
+    applyDefaultUpdater(clusterConfig, clusterConfig.getFullProperties(1), configTypesUpdated, propertiesWithUpdaters);
+    // apply default updater on hostgroup configs
+    clusterTopology.getHostGroupInfo().values().stream().forEach(
+      hostGroup -> {
+        Configuration hostGroupConfig = hostGroup.getConfiguration();
+        Map<String, Map<String, String>> hostGroupConfigProps = hostGroupConfig.getFullProperties(1);
+        applyDefaultUpdater(hostGroupConfig, hostGroupConfigProps, configTypesUpdated, propertiesWithUpdaters);
+      });
+  }
+
+  /**
+   * Calculates all properties that have registered updaters based on the received collection
+   * @param updaters collection of all updaters
+   * @return a set of all properties with updaters as (configType, propertyName) pairs.
+   */
+  private Set<Pair<String, String>> getAllPropertiesWithUpdaters(Collection<Map<String, Map<String, PropertyUpdater>>> updaters) {
+    return updaters.stream().
+      flatMap(map -> map.entrySet().stream()).
+      flatMap(entry -> {
+        String configType = entry.getKey();
+        return entry.getValue().keySet().stream().map(propertyName -> Pair.of(configType, propertyName));
+      }).
+      collect(toSet());
+  }
+
+  /**
+   * Applies the default updater ({@link HostGroupUpdater#INSTANCE}) for properties that don't have a registered updater.
+   * This is to make sure that %HOSTGROUP::name% token replacements happen for all properties.
+   */
+  private void applyDefaultUpdater(Configuration configuration,
+                                   Map<String, Map<String, String>> properties,
+                                   Set<String> configTypesUpdated,
+                                   Set<Pair<String, String>> propertiesWithUpdaters) {
+    properties.entrySet().forEach(
+      configTypeEntry -> {
+        String configType = configTypeEntry.getKey();
+        configTypeEntry.getValue().entrySet().forEach(
+          propertyEntry -> {
+            String propertyName = propertyEntry.getKey();
+            if (!propertiesWithUpdaters.contains(Pair.of(configType, propertyName))) {
+              String oldValue = propertyEntry.getValue();
+              String newValue = updateValue(configType, propertyName, oldValue, PropertyUpdater.defaultUpdater(), properties,
+                configuration, configTypesUpdated, false);
+              if (!Objects.equals(oldValue, newValue)) {
+                LOG.info("Property {}/{} was updated by the default updater from [{}] to [{}]",
+                  configType, propertyName, oldValue, newValue);
               }
-
-              configTypesUpdated.add(HDFS_HA_INITIAL_CONFIG_TYPE);
-            } else {
-              LOG.warn("Error in processing the set of active/standby namenodes in this federated cluster, please check hdfs-site configuration");
             }
-          }
-        }
+          });
+      });
+  }
+
+  /**
+   * Encapsulates commonly repeated tasks around updating a configuration value during cluster creation.
+   * @param configType the configuration type (e.g. hdfs-site)
+   * @param propertyName the name of the property (e.g. dfs.namenode.name.dir)
+   * @param oldValue the old value of the property
+   * @param updater the property updater to use
+   * @param allProps other properties to be considered by the updater
+   * @param configuration configuration to update (cluster global config or hostgroup config)
+   * @param configTypesUpdated set of updated config types (configType param will be added if updater changes the
+   *                           value of the property)
+   * @param alwaysUpdateConfig boolean to indicate whether the {@link Configuration} received as parameter should always
+   *                           (except when new value is {@code null}) be updated or only in case the new value differs
+   *                           from the original. (TODO: what is the reason for always updating the configuration?)
+   * @return the updated value
+   */
+  private String updateValue(String configType,
+                             String propertyName,
+                             String oldValue,
+                             PropertyUpdater updater,
+                             Map<String, Map<String, String>> allProps,
+                             Configuration configuration,
+                             Set<String> configTypesUpdated,
+                             boolean alwaysUpdateConfig) {
+    String newValue = updater.updateForClusterCreate(propertyName, oldValue, allProps, clusterTopology);
+    if (null != newValue) {
+      if (!newValue.equals(oldValue)) {
+        configTypesUpdated.add(configType);
+      }
+      if (!newValue.equals(oldValue) || alwaysUpdateConfig) {
+        configuration.setProperty(configType, propertyName, newValue);
       }
     }
-
-    // Explicitly set any properties that are required but not currently provided in the stack definition.
-    setStackToolsAndFeatures(clusterConfig, configTypesUpdated);
-    setRetryConfiguration(clusterConfig, configTypesUpdated);
-    setupHDFSProxyUsers(clusterConfig, configTypesUpdated);
-    addExcludedConfigProperties(clusterConfig, configTypesUpdated, clusterTopology.getBlueprint().getStack());
-
-    trimProperties(clusterConfig, clusterTopology);
-
-    return configTypesUpdated;
+    return newValue;
   }
 
+
   private String getClusterName() throws ConfigurationTopologyException {
     String clusterNameToReturn = null;
     try {
@@ -582,8 +730,8 @@ public class BlueprintConfigurationProcessor {
    */
   private static boolean shouldPropertyBeStoredWithDefault(String propertyName) {
     if (!StringUtils.isBlank(propertyName) &&
-        (HBASE_SITE_HBASE_COPROCESSOR_MASTER_CLASSES.equals(propertyName) ||
-         HBASE_SITE_HBASE_COPROCESSOR_REGION_CLASSES.equals(propertyName))) {
+      (HBASE_SITE_HBASE_COPROCESSOR_MASTER_CLASSES.equals(propertyName) ||
+        HBASE_SITE_HBASE_COPROCESSOR_REGION_CLASSES.equals(propertyName))) {
       return true;
     }
 
@@ -615,7 +763,7 @@ public class BlueprintConfigurationProcessor {
       if (! hgConfiguration.getFullProperties(1).isEmpty()) {
         // create new configuration which only contains properties specified in host group and BP host group
         allConfigs.add(new Configuration(hgConfiguration.getProperties(), null,
-            new Configuration(hgConfiguration.getParentConfiguration().getProperties(), null)));
+          new Configuration(hgConfiguration.getParentConfiguration().getProperties(), null)));
       }
     }
 
@@ -651,21 +799,21 @@ public class BlueprintConfigurationProcessor {
       Cluster cluster = clusterTopology.getAmbariContext().getController().getClusters().getCluster(clusterName);
       authToLocalPerClusterMap = new HashMap<>();
       authToLocalPerClusterMap.put(Long.valueOf(clusterTopology.getClusterId()), clusterTopology.getAmbariContext().getController().getKerberosHelper().getKerberosDescriptor(cluster, false).getAllAuthToLocalProperties());
-      } catch (AmbariException e) {
-        LOG.error("Error while getting authToLocal properties. ", e);
+    } catch (AmbariException e) {
+      LOG.error("Error while getting authToLocal properties. ", e);
     }
     PropertyFilter [] exportPropertyFilters = getExportPropertyFilters(authToLocalPerClusterMap);
     for (Map.Entry<String, Map<String, String>> configEntry : properties.entrySet()) {
       String type = configEntry.getKey();
       try {
-          clusterTopology.getBlueprint().getStack().getServiceForConfigType(type);
-        } catch (IllegalArgumentException illegalArgumentException) {
-            LOG.error(new StringBuilder(String.format("Error encountered while trying to obtain the service name for config type [%s]. ", type))
-            .append("Further processing on this config type will be skipped. ")
-            .append("This usually means that a service's definitions have been manually removed from the Ambari stack definitions. ")
-            .append("If the stack definitions have not been changed manually, this may indicate a stack definition error in Ambari. ").toString(), illegalArgumentException);
-            continue;
-        }
+        clusterTopology.getBlueprint().getStack().getServiceForConfigType(type);
+      } catch (IllegalArgumentException illegalArgumentException) {
+        LOG.error(new StringBuilder(String.format("Error encountered while trying to obtain the service name for config type [%s]. ", type))
+          .append("Further processing on this config type will be skipped. ")
+          .append("This usually means that a service's definitions have been manually removed from the Ambari stack definitions. ")
+          .append("If the stack definitions have not been changed manually, this may indicate a stack definition error in Ambari. ").toString(), illegalArgumentException);
+        continue;
+      }
       Map<String, String> typeProperties = configEntry.getValue();
 
       for (Map.Entry<String, String> propertyEntry : typeProperties.entrySet()) {
@@ -808,7 +956,7 @@ public class BlueprintConfigurationProcessor {
    *
    * @return Collection of PropertyUpdater maps used to handle cluster config update
    */
-  private Collection<Map<String, Map<String, PropertyUpdater>>> createCollectionOfUpdaters() {
+  Collection<Map<String, Map<String, PropertyUpdater>>> createCollectionOfUpdaters() {
     Collection<Map<String, Map<String, PropertyUpdater>>> updaters = allUpdaters;
 
     if (clusterTopology.isNameNodeHAEnabled()) {
@@ -1258,7 +1406,7 @@ public class BlueprintConfigurationProcessor {
               if (propValue.contains(host)) {
                 matchedHost = true;
                 configuration.setProperty(type, propertyName,
-                    propValue.replace(host, "%HOSTGROUP::" + groupInfo.getHostGroupName() + "%"));
+                  propValue.replace(host, "%HOSTGROUP::" + groupInfo.getHostGroupName() + "%"));
                 break;
               }
             }
@@ -1272,10 +1420,10 @@ public class BlueprintConfigurationProcessor {
           // also will not remove properties that reference the special 0.0.0.0 network
           // address or properties with undefined hosts
           if (! matchedHost &&
-              ! isNameServiceProperty(propertyName) &&
-              ! isSpecialNetworkAddress(propValue)  &&
-              ! isUndefinedAddress(propValue) &&
-              ! isPlaceholder(propValue)) {
+            ! isNameServiceProperty(propertyName) &&
+            ! isSpecialNetworkAddress(propValue)  &&
+            ! isUndefinedAddress(propValue) &&
+            ! isPlaceholder(propValue)) {
 
             configuration.removeProperty(type, propertyName);
           }
@@ -1352,7 +1500,7 @@ public class BlueprintConfigurationProcessor {
             Collection<String> hosts = groupInfo.getHostNames();
             for (String host : hosts) {
               propValue = propValue.replaceAll(host + "\\b", "%HOSTGROUP::" +
-                  groupInfo.getHostGroupName() + "%");
+                groupInfo.getHostGroupName() + "%");
             }
           }
           Collection<String> addedGroups = new HashSet<>();
@@ -1406,7 +1554,7 @@ public class BlueprintConfigurationProcessor {
       HostGroupInfo hostGroupInfo = topology.getHostGroupInfo().get(groupName);
       if (hostGroupInfo == null) {
         throw new IllegalArgumentException(
-            "Unable to match blueprint host group token to a host group: " + groupName);
+          "Unable to match blueprint host group token to a host group: " + groupName);
       }
 
       for (String host : hostGroupInfo.getHostNames()) {
@@ -1478,9 +1626,9 @@ public class BlueprintConfigurationProcessor {
      * @return new property value
      */
     String updateForClusterCreate(String propertyName,
-                                         String origValue,
-                                         Map<String, Map<String, String>> properties,
-                                         ClusterTopology topology);
+                                  String origValue,
+                                  Map<String, Map<String, String>> properties,
+                                  ClusterTopology topology);
 
     /**
      * Determine the required host groups for the provided property.
@@ -1496,50 +1644,98 @@ public class BlueprintConfigurationProcessor {
                                              String origValue,
                                              Map<String, Map<String, String>> properties,
                                              ClusterTopology topology);
+
+    /**
+     * @return the default updater to apply on user defined (blueprint + cluster template, not stack defaults) properties
+     * configuration properties that do not have a registered updater
+     */
+    static PropertyUpdater defaultUpdater() {
+      return HostGroupUpdater.INSTANCE;
+    }
   }
 
-  private static class HostGroupUpdater implements PropertyUpdater {
+  static class HostGroupUpdater implements PropertyUpdater {
 
-    public static final PropertyUpdater INSTANCE = new HostGroupUpdater();
+    static final HostGroupUpdater INSTANCE = new HostGroupUpdater();
 
     @Override
     public String updateForClusterCreate(String propertyName,
-      String origValue,
-      Map<String, Map<String, String>> properties,
-      ClusterTopology topology) {
-
-      //todo: getHostStrings
-      Matcher m = HostGroup.HOSTGROUP_REGEX.matcher(origValue);
-      if (m.find()) {
-        String hostGroupName = m.group(1);
-
-        HostGroupInfo groupInfo = topology.getHostGroupInfo().get(hostGroupName);
-        if (groupInfo == null) {
-          //todo: this should be validated in configuration validation
-          throw new RuntimeException(
-            "Encountered a host group token in configuration which couldn't be matched to a host group: "
-              + hostGroupName);
-        }
-
-        //todo: warn if > hosts
-        return origValue.replace(m.group(0), groupInfo.getHostNames().iterator().next());
-      }
+                                         String origValue,
+                                         Map<String, Map<String, String>> properties,
+                                         ClusterTopology topology) {
 
-      return origValue;
+      HostGroups hostGroups = new HostGroups(topology, propertyName);
+
+      //todo: getHostStrings (?)
+
+      // replaces all %HOSTGROUP::name% references to host names in the value string one by one. The value string can contain
+      // only one (typical) or multiple %HOSTGROUP references. If the same host group is referenced multiple times,
+      // another host will be picked each time.
+      // Assuming you have the following hostgroups and hosts:
+      // - hostgroup1: [group1_host]
+      // - hostgroup2: [group2_host]
+      // - hostgroup3: [group3_host1, group3_host2, group3_host3]
+      // the following replacements will be made:
+      // - %HOSTGROUP::group1%:8080 --> grop1_host:8080
+      // - %HOSTGROUP::group1%:8080,%HOSTGROUP::group2%:8080 --> group1_host:8080,group2_host:8080
+      // - %HOSTGROUP::group3%:8080,%HOSTGROUP::group3%:8080,%HOSTGROUP::group3%:8080 -->
+      //      group3_host1:8080,group3_host2:8080,group3_host3:8080 (maybe in different order)
+      LinkedList<Pair<Pair<Integer, Integer>, String>> replacements = new LinkedList<>();
+      for (Matcher m = HostGroup.HOSTGROUP_REGEX.matcher(origValue); m.find(); ) {
+        String replacement = hostGroups.getHost(m.group(1));
+        int from = m.start();
+        int to = m.end();
+        replacements.add(Pair.of(Pair.of(from, to), replacement));
+      }
+      StringBuilder newValue = new StringBuilder(origValue);
+      // replace in descending order so indices remain valid
+      for (Iterator<Pair<Pair<Integer, Integer>, String>> it = replacements.descendingIterator(); it.hasNext(); ) {
+        Pair<Pair<Integer, Integer>, String> replacement = it.next();
+        int from = replacement.getLeft().getLeft();
+        int to = replacement.getLeft().getRight();
+        String replacementValue = replacement.getRight();
+        newValue.replace(from, to, replacementValue);
+      }
+      return newValue.toString();
     }
 
     @Override
     public Collection<String> getRequiredHostGroups(String propertyName,
-      String origValue,
-      Map<String, Map<String, String>> properties,
-      ClusterTopology topology) {
+                                                    String origValue,
+                                                    Map<String, Map<String, String>> properties,
+                                                    ClusterTopology topology) {
       //todo: getHostStrings
       Matcher m = HostGroup.HOSTGROUP_REGEX.matcher(origValue);
-      if (m.find()) {
-        String hostGroupName = m.group(1);
-        return Collections.singleton(hostGroupName);
+      Set<String> hostGroups = new HashSet<>();
+      while (m.find()) {
+        hostGroups.add(m.group(1));
+      }
+      return hostGroups;
+    }
+
+    static class HostGroups {
+      private ClusterTopology topology;
+      private String propertyName; // for logging purpose only
+      private Set<String> hostGroupsUsed = new HashSet<>();
+
+      HostGroups(ClusterTopology topology, String propertyName) {
+        this.topology = topology;
+        this.propertyName = propertyName;
+      }
+
+      String getHost(String hostGroup) {
+        Preconditions.checkState(!hostGroupsUsed.contains(hostGroup),
+          "Multiple occurrence of host group [%s] in property value of: [%s].", hostGroup, propertyName);
+        HostGroupInfo hostGroupInfo = topology.getHostGroupInfo().get(hostGroup);
+        Preconditions.checkArgument(null != hostGroupInfo,
+          "Encountered a host group token in configuration which couldn't be matched to a host group: %s", hostGroup);
+        if (hostGroupInfo.getHostNames().size() > 1) {
+          LOG.warn("Host group {} contains multiple hosts. Using {} with such host groups may result in unintended configuration.",
+            hostGroup, HostGroupUpdater.class.getSimpleName());
+        }
+        hostGroupsUsed.add(hostGroup);
+        return hostGroupInfo.getHostNames().iterator().next();
       }
-      return Collections.emptySet();
     }
   }
 
@@ -1706,7 +1902,7 @@ public class BlueprintConfigurationProcessor {
           // is handled by this updater, return an empty set
           if (! cardinality.isValidCount(0)) {
             LOG.warn("The property '{}' is associated with the component '{}' which isn't mapped to any host group. " +
-                    "This may affect configuration topology resolution.", propertyName, component);
+              "This may affect configuration topology resolution.", propertyName, component);
           }
           return Collections.emptySet();
         }
@@ -1949,7 +2145,7 @@ public class BlueprintConfigurationProcessor {
     private boolean isDatabaseManaged(Map<String, Map<String, String>> properties) {
       // conditional property should always exist since it is required to be specified in the stack
       return properties.get(configPropertyType).
-          get(conditionalPropertyName).startsWith("New");
+        get(conditionalPropertyName).startsWith("New");
     }
   }
 
@@ -2198,7 +2394,7 @@ public class BlueprintConfigurationProcessor {
 
         if (!topology.getBlueprint().getHostGroups().containsKey(groupName)) {
           throw new IllegalArgumentException(
-              "Unable to match blueprint host group token to a host group: " + groupName);
+            "Unable to match blueprint host group token to a host group: " + groupName);
         }
         requiredHostGroups.add(groupName);
       }
@@ -2280,14 +2476,14 @@ public class BlueprintConfigurationProcessor {
      */
     public boolean isFQDNValue(String value) {
       return !value.contains("%HOSTGROUP") &&
-            !value.contains("localhost");
+        !value.contains("localhost");
     }
   }
 
   /**
    * Return properties of the form ['value']
    */
-   static class YamlMultiValuePropertyDecorator extends AbstractPropertyValueDecorator {
+  static class YamlMultiValuePropertyDecorator extends AbstractPropertyValueDecorator {
 
     // currently, only plain and single-quoted Yaml flows are supported by this updater
     enum FlowStyle {
@@ -2443,7 +2639,7 @@ public class BlueprintConfigurationProcessor {
         String key = keyValuePair.split("=")[0].trim();
         if (mapOfKeysToUpdaters.containsKey(key)) {
           String result = mapOfKeysToUpdaters.get(key).updateForClusterCreate(
-              key, keyValuePair.split("=")[1].trim(), properties, topology);
+            key, keyValuePair.split("=")[1].trim(), properties, topology);
           // append the internal property result, escape out any commas in the internal property,
           // this is required due to the specific syntax of templeton.hive.properties
           updatedResult.append(key);
@@ -2465,7 +2661,7 @@ public class BlueprintConfigurationProcessor {
 
       // short-circuit out any custom property values defined by the deployer
       if (!origValue.contains("%HOSTGROUP") &&
-          (!origValue.contains("localhost"))) {
+        (!origValue.contains("localhost"))) {
         // this property must contain FQDNs specified directly by the user
         // of the Blueprint, so the processor should not attempt to update them
         return Collections.emptySet();
@@ -2478,7 +2674,7 @@ public class BlueprintConfigurationProcessor {
         String key = keyValuePair.split("=")[0];
         if (mapOfKeysToUpdaters.containsKey(key)) {
           requiredGroups.addAll(mapOfKeysToUpdaters.get(key).getRequiredHostGroups(
-              propertyName, keyValuePair.split("=")[1], properties, topology));
+            propertyName, keyValuePair.split("=")[1], properties, topology));
         }
       }
       return requiredGroups;
@@ -2685,7 +2881,7 @@ public class BlueprintConfigurationProcessor {
     hiveSiteMap.put("hive.server2.authentication.ldap.url", new SingleHostTopologyUpdater("HIVE_SERVER2"));
     multiHiveSiteMap.put("hive.metastore.uris", new MultipleHostTopologyUpdater("HIVE_METASTORE", ',', true, true, true));
     dbHiveSiteMap.put("javax.jdo.option.ConnectionURL",
-        new DBTopologyUpdater("MYSQL_SERVER", "hive-env", "hive_database"));
+      new DBTopologyUpdater("MYSQL_SERVER", "hive-env", "hive_database"));
     multiCoreSiteMap.put("hadoop.proxyuser.hive.hosts", new MultipleHostTopologyUpdater("HIVE_SERVER"));
     multiCoreSiteMap.put("hadoop.proxyuser.HTTP.hosts", new MultipleHostTopologyUpdater("WEBHCAT_SERVER"));
     multiCoreSiteMap.put("hadoop.proxyuser.hcat.hosts", new MultipleHostTopologyUpdater("WEBHCAT_SERVER"));
@@ -2763,9 +2959,9 @@ public class BlueprintConfigurationProcessor {
 
       @Override
       public String updateForBlueprintExport(String propertyName,
-                                            String origValue,
-                                            Map<String, Map<String, String>> properties,
-                                            ClusterTopology topology) {
+                                             String origValue,
+                                             Map<String, Map<String, String>> properties,
+                                             ClusterTopology topology) {
 
         // if the value is the cluster id, then update to primary
         if (origValue.equals(String.valueOf(topology.getClusterId()))) {
@@ -2851,11 +3047,11 @@ public class BlueprintConfigurationProcessor {
     });
 
     multiStormSiteMap.put("supervisor_hosts",
-        new YamlMultiValuePropertyDecorator(new MultipleHostTopologyUpdater("SUPERVISOR")));
+      new YamlMultiValuePropertyDecorator(new MultipleHostTopologyUpdater("SUPERVISOR")));
     multiStormSiteMap.put("storm.zookeeper.servers",
-        new YamlMultiValuePropertyDecorator(new MultipleHostTopologyUpdater("ZOOKEEPER_SERVER")));
+      new YamlMultiValuePropertyDecorator(new MultipleHostTopologyUpdater("ZOOKEEPER_SERVER")));
     multiStormSiteMap.put("nimbus.seeds",
-        new YamlMultiValuePropertyDecorator(new MultipleHostTopologyUpdater("NIMBUS"), YamlMultiValuePropertyDecorator.FlowStyle.PLAIN));
+      new YamlMultiValuePropertyDecorator(new MultipleHostTopologyUpdater("NIMBUS"), YamlMultiValuePropertyDecorator.FlowStyle.PLAIN));
 
 
     // FALCON
@@ -2914,7 +3110,7 @@ public class BlueprintConfigurationProcessor {
     );
     for (Map<String, PropertyUpdater> rangerAuditPropsMap: configsWithRangerHdfsAuditDirProperty) {
       rangerAuditPropsMap.put("xasecure.audit.destination.hdfs.dir", new OptionalSingleHostTopologyUpdater("NAMENODE"));
-       // the same prop updater must be used as for fs.defaultFS in core-site
+      // the same prop updater must be used as for fs.defaultFS in core-site
     }
 
     // RANGER KMS
@@ -3050,7 +3246,7 @@ public class BlueprintConfigurationProcessor {
 
         if (!blueprintServices.contains(blueprintServiceForExcludedConfig)) {
           LOG.debug("Service [{}] for excluded config type [{}] is not present in the blueprint. " +
-              "Ignoring excluded config entries.", blueprintServiceForExcludedConfig, configType);
+            "Ignoring excluded config entries.", blueprintServiceForExcludedConfig, configType);
           continue;
         }
 
@@ -3110,7 +3306,7 @@ public class BlueprintConfigurationProcessor {
    * @throws ConfigurationTopologyException
    */
   private void setStackToolsAndFeatures(Configuration configuration, Set<String> configTypesUpdated)
-      throws ConfigurationTopologyException {
+    throws ConfigurationTopologyException {
     ConfigHelper configHelper = clusterTopology.getAmbariContext().getConfigHelper();
     Stack stack = clusterTopology.getBlueprint().getStack();
     String stackName = stack.getName();
@@ -3119,9 +3315,9 @@ public class BlueprintConfigurationProcessor {
     StackId stackId = new StackId(stackName, stackVersion);
 
     Set<String> properties = Sets.newHashSet(ConfigHelper.CLUSTER_ENV_STACK_NAME_PROPERTY,
-        ConfigHelper.CLUSTER_ENV_STACK_ROOT_PROPERTY, ConfigHelper.CLUSTER_ENV_STACK_TOOLS_PROPERTY,
-        ConfigHelper.CLUSTER_ENV_STACK_FEATURES_PROPERTY,
-        ConfigHelper.CLUSTER_ENV_STACK_PACKAGES_PROPERTY);
+      ConfigHelper.CLUSTER_ENV_STACK_ROOT_PROPERTY, ConfigHelper.CLUSTER_ENV_STACK_TOOLS_PROPERTY,
+      ConfigHelper.CLUSTER_ENV_STACK_FEATURES_PROPERTY,
+      ConfigHelper.CLUSTER_ENV_STACK_PACKAGES_PROPERTY);
 
     try {
       Map<String, Map<String, String>> defaultStackProperties = configHelper.getDefaultStackProperties(stackId);
@@ -3130,7 +3326,7 @@ public class BlueprintConfigurationProcessor {
       for( String property : properties ){
         if (clusterEnvDefaultProperties.containsKey(property)) {
           configuration.setProperty(CLUSTER_ENV_CONFIG_TYPE_NAME, property,
-              clusterEnvDefaultProperties.get(property));
+            clusterEnvDefaultProperties.get(property));
 
           // make sure to include the configuration type as being updated
           configTypesUpdated.add(CLUSTER_ENV_CONFIG_TYPE_NAME);
@@ -3138,7 +3334,7 @@ public class BlueprintConfigurationProcessor {
       }
     } catch( AmbariException ambariException ){
       throw new ConfigurationTopologyException("Unable to retrieve the stack tools and features",
-          ambariException);
+        ambariException);
     }
   }
 
@@ -3237,10 +3433,10 @@ public class BlueprintConfigurationProcessor {
      */
     @Override
     public boolean isPropertyIncluded(String propertyName, String propertyValue, String configType, ClusterTopology topology) {
-        Stack stack = topology.getBlueprint().getStack();
-        final String serviceName = stack.getServiceForConfigType(configType);
-        return !(stack.isPasswordProperty(serviceName, configType, propertyName) ||
-                stack.isKerberosPrincipalNameProperty(serviceName, configType, propertyName));
+      Stack stack = topology.getBlueprint().getStack();
+      final String serviceName = stack.getServiceForConfigType(configType);
+      return !(stack.isPasswordProperty(serviceName, configType, propertyName) ||
+        stack.isKerberosPrincipalNameProperty(serviceName, configType, propertyName));
     }
   }
 
@@ -3293,7 +3489,7 @@ public class BlueprintConfigurationProcessor {
     @Override
     public boolean isPropertyIncluded(String propertyName, String propertyValue, String configType, ClusterTopology topology) {
       return !(propertyConfigType.equals(configType) &&
-             this.propertyName.equals(propertyName));
+        this.propertyName.equals(propertyName));
     }
   }
 
@@ -3518,7 +3714,7 @@ public class BlueprintConfigurationProcessor {
      * Set of HAWQ Property names that are only valid in a HA scenario.
      */
     private final Set<String> setOfHawqPropertyNamesNonHA =
-            Collections.unmodifiableSet(new HashSet<>(Arrays.asList(HAWQ_SITE_HAWQ_STANDBY_ADDRESS_HOST)));
+      Collections.unmodifiableSet(new HashSet<>(Arrays.asList(HAWQ_SITE_HAWQ_STANDBY_ADDRESS_HOST)));
 
 
     /**
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java
index ba74853..54b9442 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java
@@ -18,6 +18,10 @@
 
 package org.apache.ambari.server.controller.internal;
 
+import static com.google.common.collect.Iterators.peekingIterator;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptyMap;
+import static java.util.stream.Collectors.toList;
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
@@ -68,6 +72,7 @@ import org.apache.ambari.server.topology.HostGroupInfo;
 import org.apache.ambari.server.topology.InvalidTopologyException;
 import org.apache.ambari.server.topology.TopologyRequest;
 import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
 import org.easymock.EasyMock;
 import org.easymock.EasyMockRule;
 import org.easymock.EasyMockSupport;
@@ -88,6 +93,7 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.PeekingIterator;
 import com.google.common.collect.Sets;
 
 /**
@@ -97,7 +103,7 @@ import com.google.common.collect.Sets;
 @PrepareForTest(AmbariServer.class)
 public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
-  private static final Configuration EMPTY_CONFIG = new Configuration(Collections.emptyMap(), Collections.emptyMap());
+  private static final Configuration EMPTY_CONFIG = new Configuration(emptyMap(), emptyMap());
   private final Map<String, Collection<String>> serviceComponents = new HashMap<>();
   private final Map<String, Map<String, String>> stackProperties = new HashMap<>();
   private final Map<String, String> defaultClusterEnvProperties = new HashMap<>();
@@ -151,10 +157,10 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getVersion()).andReturn(STACK_VERSION).atLeastOnce();
     // return false for all components since for this test we don't care about the value
     expect(stack.isMasterComponent((String) anyObject())).andReturn(false).anyTimes();
-    expect(stack.getConfigurationPropertiesWithMetadata(anyObject(String.class), anyObject(String.class))).andReturn(Collections.emptyMap()).anyTimes();
+    expect(stack.getConfigurationPropertiesWithMetadata(anyObject(String.class), anyObject(String.class))).andReturn(emptyMap()).anyTimes();
 
     expect(serviceInfo.getRequiredProperties()).andReturn(
-      Collections.emptyMap()).anyTimes();
+      emptyMap()).anyTimes();
     expect(serviceInfo.getRequiredServices()).andReturn(Collections.emptyList()).anyTimes();
 
     Collection<String> hdfsComponents = new HashSet<>();
@@ -273,7 +279,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("yarn-site", typeProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -321,7 +327,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -396,10 +402,10 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     parentProperties.put("yarn-site", parentYarnSiteProps);
 
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -432,7 +438,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("yarn-site", typeProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -450,11 +456,11 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     group2YarnSiteProps.put("yarn.resourcemanager.webapp.https.address", "{{rm_host}}");
     group2Properties.put("yarn-site", group2YarnSiteProps);
     // host group config -> BP config -> cluster scoped config
-    Configuration group2BPConfiguration = new Configuration(Collections.emptyMap(),
-      Collections.emptyMap(), clusterConfig);
+    Configuration group2BPConfiguration = new Configuration(emptyMap(),
+      emptyMap(), clusterConfig);
 
     Configuration group2Configuration = new Configuration(group2Properties,
-      Collections.emptyMap(), group2BPConfiguration);
+      emptyMap(), group2BPConfiguration);
 
     // set config on hostgroup
     TestHostGroup group2 = new TestHostGroup("group2", hgComponents2,
@@ -483,7 +489,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("core-site", typeProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -515,7 +521,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("yarn-site", typeProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -547,7 +553,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("hbase-site", typeProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -594,7 +600,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("webhcat-site", typeProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -645,7 +651,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("storm-site", typeProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -705,7 +711,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("hive-site", hiveSiteProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -739,7 +745,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("hive-site", typeProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -791,7 +797,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("secret-test-properties", secretProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -876,7 +882,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     falconStartupProperties.put("*.falcon.http.authentication.kerberos.principal", "HTTP/" + expectedHostName + "@EXAMPLE.COM");
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -913,7 +919,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     tezSiteProperties.put("tez.tez-ui.history-url.base", "http://host:port/TEZ/TEZ_VIEW");
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -963,7 +969,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     coreSiteProperties.put("hadoop.security.auth_to_local", "RULE:clustername");
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1028,7 +1034,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hdfsSiteProperties.put("dfs.namenode.rpc-address." + expectedNameService + "." + expectedNodeTwo, expectedHostName + ":" + expectedPortNum);
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1101,7 +1107,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hadoopEnvProperties.put("dfs_ha_initial_namenode_standby", expectedHostName);
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1165,7 +1171,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     accumuloSiteProperties.put("instance.volumes", "hdfs://" + expectedNameService + "/apps/accumulo/data");
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1204,7 +1210,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
       0, hdfsSiteProperties.size());
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1263,7 +1269,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hdfsSiteProperties.put("dfs.namenode.rpc-address." + expectedNameServiceTwo + "." + expectedNodeTwo, expectedHostNameTwo + ":" + expectedPortNum);
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1341,7 +1347,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     yarnSiteProperties.put("yarn.log.server.web-service.url", expectedHostName + ":" + expectedPortNum);
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1407,7 +1413,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     yarnSiteProperties.put("yarn.timeline-service.webapp.https.address", "0.0.0.0" + ":" + expectedPortNum);
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1482,7 +1488,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     accumuloSiteProperties.put("instance.volumes", "hdfs://" + expectedHostName + ":" + expectedPortNum + "/apps/accumulo/data");
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1562,7 +1568,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     coreSiteProperties.put("hadoop.proxyuser.hcat.hosts", expectedHostName + "," + expectedHostNameTwo);
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1658,7 +1664,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     coreSiteProperties.put("hadoop.proxyuser.hcat.hosts", expectedHostName + "," + expectedHostNameTwo);
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> groupComponents = new HashSet<>();
     groupComponents.add("NAMENODE");
@@ -1746,7 +1752,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     coreSiteProperties.put("hadoop.proxyuser.oozie.hosts", expectedHostName + "," + expectedHostNameTwo);
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // note: test hostgroups may not accurately reflect the required components for the config properties
     // which are mapped to them.  Only the hostgroup name is used for hostgroup resolution an the components
@@ -1820,7 +1826,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     oozieSiteProperties.put("oozie.service.JPAService.jdbc.url", "jdbc:mysql://" + expectedHostNameTwo + "/ooziedb");
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("OOZIE_SERVER");
     hgComponents.add("ZOOKEEPER_SERVER");
@@ -1859,7 +1865,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     oozieSiteProperties.put("oozie.service.JPAService.jdbc.url", "jdbc:mysql://" + "%HOSTGROUP::group1%" + "/ooziedb");
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("OOZIE_SERVER");
     hgComponents.add("ZOOKEEPER_SERVER");
@@ -1918,7 +1924,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     accumuloSiteProperties.put("instance.zookeeper.host", createHostAddress(expectedHostName, expectedPortNumberOne) + "," + createHostAddress(expectedHostNameTwo, expectedPortNumberTwo));
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     // test hostgroups may not accurately reflect the required components for the config properties which are mapped to them
     Collection<String> groupComponents = new HashSet<>();
@@ -1999,7 +2005,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 //    multiOozieSiteMap.put("hadoop.proxyuser.knox.hosts", new MultipleHostTopologyUpdater("KNOX_GATEWAY"));
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> groupComponents = new HashSet<>();
     groupComponents.add("KNOX_GATEWAY");
@@ -2051,7 +2057,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     kafkaBrokerProperties.put("kafka.ganglia.metrics.host", createHostAddress(expectedHostName, expectedPortNumberOne));
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> groupComponents = new HashSet<>();
     groupComponents.add("KAFKA_BROKER");
@@ -2095,7 +2101,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("worker.childopts", "some other info, undefined, more info");
 
     Configuration clusterConfig = new Configuration(configProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> groupComponents = new HashSet<>();
     groupComponents.add("ZOOKEEPER_SERVER");
@@ -2132,7 +2138,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("oozie-env", typeProps2);
     properties.put("yarn-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> group1Components = new HashSet<>();
     group1Components.add("NAMENODE");
@@ -2173,6 +2179,189 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
   }
 
   @Test
+  public void testDoUpdateForClusterCreate_HostgroupReplacement_DefaultUpdater() throws Exception {
+    Map<String, Map<String, String>> stackProperties = new HashMap<>(ImmutableMap.of(
+      "hdfs-site", new HashMap<>(ImmutableMap.of(
+        "dfs.http.address", "testhost2")),
+      "myservice-env", new HashMap<>(ImmutableMap.of(
+          "myservice_master_address", "%HOSTGROUP::group1%:8080",
+          "myservice_some_other_property", "some_value"))));
+
+    Map<String, Map<String, String>> hostGroupProperties = new HashMap<>(ImmutableMap.of(
+      "hdfs-site", new HashMap<>(ImmutableMap.of(
+        "dfs.https.address", "testhost3")),
+      "myservice-site", new HashMap<>(ImmutableMap.of(
+        "myservice_slave_address", "%HOSTGROUP::group1%:8080"))));
+
+    Configuration clusterConfig = new Configuration(new HashMap<>(), new HashMap<>());
+    clusterConfig.setParentConfiguration(new Configuration(stackProperties, emptyMap()));
+    Configuration hostGroupConfig = new Configuration(hostGroupProperties, emptyMap());
+
+    TestHostGroup group1 = new TestHostGroup("group1",
+      Sets.newHashSet("NAMENODE", "SECONDARY_NAMENODE", "RESOURCEMANAGER"),
+      Collections.singleton("testhost"),
+      hostGroupConfig);
+
+    Collection<TestHostGroup> hostGroups = Sets.newHashSet(group1);
+
+    ClusterTopology topology = createClusterTopology(bp, clusterConfig, hostGroups);
+    BlueprintConfigurationProcessor updater = new BlueprintConfigurationProcessor(topology);
+
+    Set<String> configTypesUpdated =
+      updater.doUpdateForClusterCreate();
+
+    assertTrue(configTypesUpdated.containsAll(ImmutableList.of("myservice-env", "myservice-site")));
+    // updater called on dfs.http.address and dfs.http.address but didn't change their values
+    assertTrue(!configTypesUpdated.contains("hdfs-site"));
+    Map<String, String> clusterHdfsSite = clusterConfig.getProperties().get("hdfs-site");
+    // the value of dfs.http.address didn't change, yet it was added to the cluster config as this property has a
+    // registered updater
+    assertTrue(clusterHdfsSite.containsKey("dfs.http.address"));
+    Map<String, String> myserviceEnv = clusterConfig.getProperties().get("myservice-env");
+    // default updater (to replace %HOSTGROUP::name%) was called on myservice_master_address and myservice_some_other_property
+    // - myservice_master_address was added to the cluster config as its value was updated by the default updater
+    // - the value of myservice_some_other_property didn't change and this property does not have a registered updater,
+    //   so it wasn't added to the cluster config
+    assertEquals(ImmutableMap.of("myservice_master_address", "testhost:8080"), myserviceEnv);
+
+    // %HOSTGROUP::name% has been replaced by the default updater in hostgroup config
+    Map<String, String> myserviceSite = hostGroupConfig.getProperties().get("myservice-site");
+    assertEquals(myserviceSite, ImmutableMap.of("myservice_slave_address", "testhost:8080"));
+  }
+
+  @Test
+  public void testHostgroupUpdater() throws Exception {
+    Set<String> components = ImmutableSet.of("NAMENODE", "SECONDARY_NAMENODE", "RESOURCEMANAGER");
+    Configuration hostGroupConfig = new Configuration(emptyMap(), emptyMap());
+    TestHostGroup group1 = new TestHostGroup("master1", components, ImmutableList.of("master1_host"), hostGroupConfig);
+    TestHostGroup group2 = new TestHostGroup("master2", components, ImmutableList.of("master2_host"), hostGroupConfig);
+    TestHostGroup group3 =
+      new TestHostGroup("master3", components, ImmutableList.of("master3_host1", "master3_host2"), hostGroupConfig);
+    Configuration clusterConfig = new Configuration(new HashMap<>(), new HashMap<>());
+    ClusterTopology topology = createClusterTopology(bp, clusterConfig, ImmutableList.of(group1, group2, group3));
+
+    BlueprintConfigurationProcessor.HostGroupUpdater updater = BlueprintConfigurationProcessor.HostGroupUpdater.INSTANCE;
+
+    assertEquals(
+      "master1_host:8080",
+      updater.updateForClusterCreate(
+        "mycomponent.url",
+        "%HOSTGROUP::master1%:8080",
+        clusterConfig.getProperties(),
+        topology));
+
+    assertEquals(
+      "master1_host:8080,master2_host:8080",
+      updater.updateForClusterCreate(
+        "mycomponent.urls",
+        "%HOSTGROUP::master1%:8080,%HOSTGROUP::master2%:8080",
+        clusterConfig.getProperties(),
+        topology));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testHostgroupUpdater_NonExistingHostgroup() throws Exception {
+    Set<String> components = ImmutableSet.of("NAMENODE", "SECONDARY_NAMENODE", "RESOURCEMANAGER");
+    Configuration hostGroupConfig = new Configuration(emptyMap(), emptyMap());
+    TestHostGroup group1 = new TestHostGroup("master1", components, ImmutableList.of("master1_host"), hostGroupConfig);
+    Configuration clusterConfig = new Configuration(new HashMap<>(), new HashMap<>());
+    ClusterTopology topology = createClusterTopology(bp, clusterConfig, ImmutableList.of(group1));
+    BlueprintConfigurationProcessor.HostGroupUpdater updater = BlueprintConfigurationProcessor.HostGroupUpdater.INSTANCE;
+
+    updater.updateForClusterCreate(
+      "mycomponent.urls",
+      "%HOSTGROUP::master2%:8080",
+      clusterConfig.getProperties(),
+      topology);
+  }
+
+  @Test(expected = IllegalStateException.class)
+  public void testHostgroupUpdater_SameGroupMultipleTimes() throws Exception {
+    Set<String> components = ImmutableSet.of("NAMENODE", "SECONDARY_NAMENODE", "RESOURCEMANAGER");
+    Configuration hostGroupConfig = new Configuration(emptyMap(), emptyMap());
+    TestHostGroup group1 = new TestHostGroup("master1", components, ImmutableList.of("master1_host1", "master1_host2"), hostGroupConfig);
+    Configuration clusterConfig = new Configuration(new HashMap<>(), new HashMap<>());
+    ClusterTopology topology = createClusterTopology(bp, clusterConfig, ImmutableList.of(group1));
+    BlueprintConfigurationProcessor.HostGroupUpdater updater = BlueprintConfigurationProcessor.HostGroupUpdater.INSTANCE;
+
+    updater.updateForClusterCreate(
+      "mycomponent.urls",
+      "%HOSTGROUP::master1%:8080,%HOSTGROUP::master1%:8090",
+      clusterConfig.getProperties(),
+      topology);
+  }
+
+  @Test
+  public void testHostgroupUpdater_getRequiredHostgroups() throws Exception {
+    Set<String> components = ImmutableSet.of("NAMENODE", "SECONDARY_NAMENODE", "RESOURCEMANAGER");
+    Configuration hostGroupConfig = new Configuration(emptyMap(), emptyMap());
+    TestHostGroup group1 = new TestHostGroup("master1", components, ImmutableList.of("master1_host"), hostGroupConfig);
+    TestHostGroup group2 = new TestHostGroup("master2", components, ImmutableList.of("master2_host"), hostGroupConfig);
+    TestHostGroup group3 =
+      new TestHostGroup("master3", components, ImmutableList.of("master3_host"), hostGroupConfig);
+    Configuration clusterConfig = new Configuration(new HashMap<>(), new HashMap<>());
+    ClusterTopology topology = createClusterTopology(bp, clusterConfig, ImmutableList.of(group1, group2, group3));
+
+    BlueprintConfigurationProcessor.HostGroupUpdater updater = BlueprintConfigurationProcessor.HostGroupUpdater.INSTANCE;
+
+    assertEquals(
+      ImmutableSet.of("master1"),
+      ImmutableSet.copyOf(
+        updater.getRequiredHostGroups(
+          "mycomponent.url",
+          "%HOSTGROUP::master1%:8080",
+          clusterConfig.getProperties(),
+          topology)));
+
+    assertEquals(
+      ImmutableSet.of("master1", "master2"),
+      ImmutableSet.copyOf(
+        updater.getRequiredHostGroups(
+          "mycomponent.urls",
+          "%HOSTGROUP::master1%:8080,%HOSTGROUP::master2%:8080",
+          clusterConfig.getProperties(),
+          topology)));
+
+    assertEquals(
+      ImmutableSet.of("master3"),
+      ImmutableSet.copyOf(
+        updater.getRequiredHostGroups(
+          "mycomponent.urls",
+          "%HOSTGROUP::master3%:8080",
+          clusterConfig.getProperties(),
+          topology)));
+  }
+
+  @Test
+  public void testDoUpdateForClusterCreate_OnlyOneUpdaterForEachProperty() throws Exception {
+    BlueprintConfigurationProcessor bpConfigProcessor = new BlueprintConfigurationProcessor(
+      createClusterTopology(bp, new Configuration(emptyMap(), emptyMap()), emptyList()));
+    Collection<Map<String, Map<String, BlueprintConfigurationProcessor.PropertyUpdater>>> updaters =
+      bpConfigProcessor.createCollectionOfUpdaters();
+
+    // Make a list of all (configType, propertyName) pairs that have updaters
+    List<Pair<String, String>> propertiesWithUpdaters = updaters.stream().
+      flatMap(map -> map.entrySet().stream()).
+      flatMap(entry -> {
+        String configType = entry.getKey();
+        return entry.getValue().keySet().stream().map(propertyName -> Pair.of(configType, propertyName));
+      }).
+      sorted().
+      collect(toList());
+
+    // Look for duplicates in the list
+    Set<Pair<String, String>> duplicates = new HashSet<>();
+    for (PeekingIterator<Pair<String, String>> it = peekingIterator(propertiesWithUpdaters.iterator()); it.hasNext(); ) {
+      Pair<String, String> property = it.next();
+      if (it.hasNext() && it.peek().equals(property)) {
+        duplicates.add(property);
+      }
+    }
+    assertTrue("There are properties with multiple updaters: " + duplicates, duplicates.isEmpty());
+  }
+
+
+  @Test
   public void testDoUpdateForClusterCreate_SingleHostProperty__defaultValue_providedInParent() throws Exception {
     Map<String, Map<String, String>> properties = new HashMap<>();
     Map<String, String> yarnSiteProps = new HashMap<>();
@@ -2185,10 +2374,10 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     parentProperties.put("yarn-site", parentYarnSiteProps);
 
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> group1Components = new HashSet<>();
     group1Components.add("NAMENODE");
@@ -2222,7 +2411,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("yarn-site", yarnSiteProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> group1Components = new HashSet<>();
     group1Components.add("NAMENODE");
@@ -2240,11 +2429,11 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     group2Properties.put("yarn-site", group2YarnSiteProperties);
     // group 2 host group configuration
     // HG config -> BP HG config -> cluster scoped config
-    Configuration group2BPConfig = new Configuration(Collections.emptyMap(),
-      Collections.emptyMap(), clusterConfig);
+    Configuration group2BPConfig = new Configuration(emptyMap(),
+      emptyMap(), clusterConfig);
 
     Configuration group2Config = new Configuration(group2Properties,
-      Collections.emptyMap(), group2BPConfig);
+      emptyMap(), group2BPConfig);
     // set config on HG
     TestHostGroup group2 = new TestHostGroup("group2", group2Components, Collections.singleton("testhost2"), group2Config);
 
@@ -2269,7 +2458,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("yarn-site", yarnSiteProps);
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> group1Components = new HashSet<>();
     group1Components.add("NAMENODE");
@@ -2288,11 +2477,11 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // group 2 host group configuration
     // HG config -> BP HG config -> cluster scoped config
     Configuration group2BPConfig = new Configuration(group2BPProperties,
-      Collections.emptyMap(), clusterConfig);
+      emptyMap(), clusterConfig);
 
     // can't set parent here because it is reset in cluster topology
     Configuration group2Config = new Configuration(new HashMap<>(),
-      Collections.emptyMap());
+      emptyMap());
     // set config on HG
     TestHostGroup group2 = new TestHostGroup("group2", group2Components, Collections.singleton("testhost2"), group2Config);
 
@@ -2320,7 +2509,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("yarn.timeline-service.address", "localhost");
     properties.put("yarn-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> group1Components = new HashSet<>();
     group1Components.add("NAMENODE");
@@ -2360,7 +2549,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("yarn.timeline-service.address", "localhost");
     properties.put("yarn-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> group1Components = new HashSet<>();
     group1Components.add("NAMENODE");
@@ -2404,7 +2593,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("yarn.timeline-service.webapp.https.address", "testhost:8190");
     properties.put("yarn-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> group1Components = new HashSet<>();
     group1Components.add("NAMENODE");
@@ -2443,7 +2632,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("yarn.timeline-service.address", expectedHostName);
     properties.put("yarn-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> group1Components = new HashSet<>();
     group1Components.add("NAMENODE");
@@ -2477,7 +2666,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("fs.defaultFS", "localhost:5050");
     properties.put("core-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -2508,7 +2697,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("hbase.zookeeper.quorum", "localhost");
     properties.put("hbase-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -2565,7 +2754,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("templeton.zookeeper.hosts", "localhost:9090");
     properties.put("webhcat-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -2629,7 +2818,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put(propertyName, originalValue);
     properties.put(typeName, typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add(component1);
@@ -2668,7 +2857,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put(propertyName, originalValue);
     properties.put(typeName, typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add(component1);
@@ -2703,7 +2892,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put(propertyName, originalValue);
     properties.put(typeName, typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add(component1);
@@ -2733,7 +2922,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     HashMap<String, String> clusterEnvProperties = new HashMap<>();
     configProperties.put("cluster-env", clusterEnvProperties);
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
 
     TestHostGroup testHostGroup = new TestHostGroup("test-host-group-one", Collections.emptySet(), Collections.emptySet());
     ClusterTopology topology = createClusterTopology(bp, clusterConfig, Collections.singleton(testHostGroup));
@@ -2773,7 +2962,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     clusterEnvProperties.put("command_retry_max_time_in_sec", "1");
 
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
 
     TestHostGroup testHostGroup = new TestHostGroup("test-host-group-one", Collections.emptySet(), Collections.emptySet());
     ClusterTopology topology = createClusterTopology(bp, clusterConfig, Collections.singleton(testHostGroup));
@@ -2847,7 +3036,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // configure the hbase rootdir to use the nameservice URL
     accumuloSiteProperties.put("instance.volumes", "hdfs://" + expectedNameService + "/accumulo/test/instance/volumes");
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -2926,7 +3115,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // setup properties that include host information
     webHCatSiteProperties.put("templeton.hive.properties", expectedPropertyValue);
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -2973,7 +3162,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     hiveSiteProperties.put("hive.metastore.uris", expectedMetaStoreURIs);
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("HIVE_SERVER");
@@ -3035,7 +3224,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     hiveSiteProperties.put("hive.metastore.uris", inputMetaStoreURIs);
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("HIVE_SERVER");
@@ -3105,7 +3294,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     String propertyKey = "templeton.hive.properties";
     webHCatSiteProperties.put(propertyKey, initialPropertyValue);
 
-    Map<String, Map<String, Map<String, String>>> attributes = Collections.emptyMap();
+    Map<String, Map<String, Map<String, String>>> attributes = emptyMap();
     Configuration clusterConfig = new Configuration(configProperties, attributes);
 
     Collection<TestHostGroup> hostGroups = new HashSet<>();
@@ -3155,7 +3344,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     hiveInteractiveSiteProperties.put(llapZkProperty, createHostAddress(expectedHostName, "2181") + "," + createHostAddress(expectedHostNameTwo, "2181"));
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("ZOOKEEPER_SERVER");
     TestHostGroup group1 = new TestHostGroup(expectedHostGroupName, hgComponents, Collections.singleton(expectedHostName));
@@ -3207,7 +3396,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     coreSiteProperties.put("hadoop.proxyuser.oozie.hosts", expectedHostName + "," + expectedHostNameTwo);
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("OOZIE_SERVER");
     TestHostGroup group1 = new TestHostGroup(expectedHostGroupName, hgComponents, Collections.singleton("host1"));
@@ -3271,7 +3460,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     coreSiteProperties.put("hadoop.proxyuser.oozie.hosts", expectedHostName + "," + expectedHostNameTwo);
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("OOZIE_SERVER");
     hgComponents.add("ZOOKEEPER_SERVER");
@@ -3325,7 +3514,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     yarnSiteProperties.put("yarn.resourcemanager.ha.enabled", "true");
     yarnSiteProperties.put("yarn.resourcemanager.ha.rm-ids", "rm1, rm2");
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("RESOURCEMANAGER");
     hgComponents.add("APP_TIMELINE_SERVER");
@@ -3412,7 +3601,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     yarnSiteProperties.put("yarn.resourcemanager.webapp.https.address", expectedHostName + ":" + "8080");
 
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("RESOURCEMANAGER");
     hgComponents.add("APP_TIMELINE_SERVER");
@@ -3499,7 +3688,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     hdfsSiteProperties.put("dfs.namenode.shared.edits.dir", expectedQuorumJournalURL);
 
-    Configuration clusterConfig = new Configuration(configProperties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(configProperties, emptyMap());
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
     TestHostGroup group1 = new TestHostGroup(expectedHostGroupName, hgComponents, Collections.singleton("host1"));
@@ -3529,7 +3718,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("storm.zookeeper.servers", "['localhost']");
     properties.put("storm-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -3593,7 +3782,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("nimbus.seeds", "localhost");
     properties.put("storm-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NIMBUS");
@@ -3643,7 +3832,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("nimbus.seeds", expectedValue);
     properties.put("storm-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NIMBUS");
@@ -3680,7 +3869,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("hbase_master_heapsize", "512m");
     properties.put("hbase-env", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -3712,7 +3901,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("hbase_master_heapsize", "512");
     properties.put("hbase-env", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -3744,7 +3933,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("yarn.resourcemanager.hostname", "%HOSTGROUP::group1%");
     properties.put("yarn-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -3776,7 +3965,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("yarn.resourcemanager.hostname", "%HOSTGROUP::os-amb-r6-secha-1427972156-hbaseha-3-6%");
     properties.put("yarn-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -3808,7 +3997,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("yarn.resourcemanager.hostname", "%HOSTGROUP::os-amb-r6-secha-1427972156-hbaseha-3-6%:2180");
     properties.put("yarn-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -3840,7 +4029,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("fs.defaultFS", "%HOSTGROUP::group1%:5050");
     properties.put("core-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -3872,7 +4061,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("hbase.zookeeper.quorum", "%HOSTGROUP::group1%,%HOSTGROUP::group2%");
     properties.put("hbase-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -3930,7 +4119,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("templeton.zookeeper.hosts", "%HOSTGROUP::group1%:9090,%HOSTGROUP::group2%:9091");
     properties.put("webhcat-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -3988,7 +4177,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("ha.zookeeper.quorum", "%HOSTGROUP::os-amb-r6-secha-1427972156-hbaseha-3-6%:2181,%HOSTGROUP::os-amb-r6-secha-1427972156-hbaseha-3-5%:2181,%HOSTGROUP::os-amb-r6-secha-1427972156-hbaseha-3-7%:2181");
     properties.put("core-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4049,7 +4238,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     yarnSiteConfig.put("hadoop.registry.zk.quorum", "%HOSTGROUP::host_group_1%:2181");
     properties.put("yarn-site", yarnSiteConfig);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4076,7 +4265,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("nimbus.seeds", "[%HOSTGROUP::group1%, %HOSTGROUP::group4%]");
     properties.put("storm-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4172,7 +4361,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("hive-site", hiveSiteProps);
     properties.put("hive-env", hiveEnvProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4208,7 +4397,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("hive-site", hiveSiteProps);
     properties.put("hive-env", hiveEnvProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4242,7 +4431,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("hive_database", "Existing MySQL Database");
     properties.put("hive-env", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4283,7 +4472,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getServiceForConfigType("oozie-site")).andReturn("OOZIE").anyTimes();
 
     Map<String, Map<String, String>> properties = new HashMap<>();
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("FALCON_SERVER");
@@ -4322,7 +4511,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getServiceForConfigType("oozie-site")).andReturn("OOZIE").anyTimes();
 
     Map<String, Map<String, String>> properties = new HashMap<>();
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("FALCON_SERVER");
@@ -4351,7 +4540,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getName()).andReturn("testStack").anyTimes();
     expect(stack.getVersion()).andReturn("1").anyTimes();
     expect(stack.isMasterComponent((String) anyObject())).andReturn(false).anyTimes();
-    expect(stack.getConfigurationPropertiesWithMetadata(anyObject(String.class), anyObject(String.class))).andReturn(Collections.emptyMap()).anyTimes();
+    expect(stack.getConfigurationPropertiesWithMetadata(anyObject(String.class), anyObject(String.class))).andReturn(emptyMap()).anyTimes();
 
     // customized stack calls for this test only
     expect(stack.getExcludedConfigurationTypes("FALCON")).andReturn(Collections.singleton("oozie-site")).anyTimes();
@@ -4362,7 +4551,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     typeProps.put("oozie.service.ELService.ext.functions.coord-job-submit-instances", "overridedValue");
     properties.put("oozie-site", typeProps);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("FALCON_SERVER");
@@ -4405,7 +4594,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getServiceForConfigType("storm-site")).andThrow(new IllegalArgumentException("TEST: Configuration not found in stack definitions!"));
 
     Map<String, Map<String, String>> properties = new HashMap<>();
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("FALCON_SERVER");
@@ -4445,7 +4634,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     falconStartupProperties.put("*.falcon.service.authentication.kerberos.principal", "falcon/" + createExportedHostName(expectedHostGroupName) + "@EXAMPLE.COM");
     falconStartupProperties.put("*.falcon.http.authentication.kerberos.principal", "HTTP/" + createExportedHostName(expectedHostGroupName) + "@EXAMPLE.COM");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("FALCON_SERVER");
@@ -4486,7 +4675,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     falconStartupProperties.put("*.falcon.service.authentication.kerberos.principal", "falcon/" + "localhost" + "@EXAMPLE.COM");
     falconStartupProperties.put("*.falcon.http.authentication.kerberos.principal", "HTTP/" + "localhost" + "@EXAMPLE.COM");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("FALCON_SERVER");
@@ -4523,7 +4712,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // setup properties that include host information
     webHCatSiteProperties.put("templeton.hive.properties", expectedPropertyValue);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4599,7 +4788,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getServiceForConfigType("hive-site")).andReturn("HIVE").atLeastOnce();
     expect(stack.getConfigurationPropertiesWithMetadata("HIVE", "hive-site")).andReturn(mapOfMetadata).atLeastOnce();
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4677,7 +4866,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getServiceForConfigType("hive-site")).andThrow(new RuntimeException("Expected Test Error")).once();
     expect(stack.getConfigurationPropertiesWithMetadata("HIVE", "hive-site")).andReturn(mapOfMetadata).atLeastOnce();
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4755,7 +4944,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getServiceForConfigType("hive-site")).andReturn("HIVE").atLeastOnce();
     expect(stack.getConfigurationPropertiesWithMetadata("HIVE", "hive-site")).andReturn(mapOfMetadata).atLeastOnce();
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4843,7 +5032,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getServiceForConfigType("hbase-site")).andReturn("HBASE").atLeastOnce();
     expect(stack.getConfigurationPropertiesWithMetadata("HBASE", "hbase-site")).andReturn(mapOfMetadata).atLeastOnce();
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4911,7 +5100,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     expect(stack.getServiceForConfigType("hbase-site")).andReturn("HBASE").atLeastOnce();
     expect(stack.getConfigurationPropertiesWithMetadata("HBASE", "hbase-site")).andReturn(mapOfMetadata).atLeastOnce();
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -4950,7 +5139,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     webHCatSiteProperties.put("templeton.hive.properties",
       expectedPropertyValue);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("HIVE_METASTORE");
@@ -4993,7 +5182,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     atlasProperties.put("atlas.audit.hbase.zookeeper.quorum", "localhost");
 
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hg1Components = new HashSet<>();
     hg1Components.add("KAFKA_BROKER");
@@ -5067,7 +5256,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     webHCatSiteProperties.put("templeton.hive.properties",
       expectedPropertyValue);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("HIVE_METASTORE");
@@ -5107,7 +5296,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     kafkaBrokerProperties.put("kafka.ganglia.metrics.host", "localhost");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("HIVE_METASTORE");
@@ -5157,7 +5346,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     kafkaBrokerProperties.put("kafka.ganglia.metrics.host", "localhost");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("GANGLIA_SERVER");
@@ -5244,7 +5433,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // configure the hbase rootdir to use the nameservice URL
     accumuloSiteProperties.put("instance.volumes", "hdfs://" + expectedNameService + "/accumulo/test/instance/volumes");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -5383,7 +5572,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // configure the hbase rootdir to use the nameservice URL
     accumuloSiteProperties.put("instance.volumes", "hdfs://" + expectedNameService + "/accumulo/test/instance/volumes");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -5539,7 +5728,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // configure the hbase rootdir to use the nameservice URL
     accumuloSiteProperties.put("instance.volumes", "hdfs://" + expectedNameService + "/accumulo/test/instance/volumes");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -5765,7 +5954,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // configure the hbase rootdir to use the nameservice URL
     accumuloSiteProperties.put("instance.volumes", "hdfs://" + expectedNameService + "/accumulo/test/instance/volumes");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -5875,7 +6064,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // configure the hbase rootdir to use the nameservice URL
     accumuloSiteProperties.put("instance.volumes", "hdfs://" + expectedNameService + "/accumulo/test/instance/volumes");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -6042,7 +6231,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hdfsSiteProperties.put("dfs.secondary.http.address", "localhost:8080");
     hdfsSiteProperties.put("dfs.namenode.secondary.http-address", "localhost:8080");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -6105,7 +6294,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hdfsSiteProperties.put("dfs.namenode.https-address", "localhost:8081");
     hdfsSiteProperties.put("dfs.namenode.rpc-address", "localhost:8082");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -6174,7 +6363,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hadoopEnvProperties.put("dfs_ha_initial_namenode_active", expectedHostName);
     hadoopEnvProperties.put("dfs_ha_initial_namenode_standby", expectedHostNameTwo);
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
@@ -6321,7 +6510,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // setup shared edit property, that includes a qjournal URL scheme
     hdfsSiteProperties.put("dfs.namenode.shared.edits.dir", "qjournal://" + createExportedAddress(expectedPortNum, expectedHostGroupName) + ";" + createExportedAddress(expectedPortNum, expectedHostGroupNameTwo) + "/mycluster");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("NAMENODE");
@@ -6363,7 +6552,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     // setup shared edit property, that includes a qjournal URL scheme
     hdfsSiteProperties.put("dfs.namenode.shared.edits.dir", "qjournal://" + createExportedAddress(expectedPortNum, expectedHostGroupName) + ";" + createExportedAddress(expectedPortNum, expectedHostGroupNameTwo) + "/mycluster");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("NAMENODE");
@@ -6419,9 +6608,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     TestHostGroup group1 = new TestHostGroup("master_1", ImmutableSet.of("DATANODE", "NAMENODE"), Collections.singleton("node_1"));
     TestHostGroup group2 = new TestHostGroup("master_2", ImmutableSet.of("DATANODE", "NAMENODE"), Collections.singleton("node_2"));
@@ -6453,7 +6642,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("HIVE_SERVER");
@@ -6485,7 +6674,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     coreSiteMap.put("fs.defaultFS", "localhost");
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     expect(stack.getCardinality("NAMENODE")).andReturn(new Cardinality("1")).anyTimes();
 
@@ -6518,7 +6707,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     coreSiteMap.put("fs.defaultFS", "localhost");
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     expect(stack.getCardinality("NAMENODE")).andReturn(new Cardinality("1")).anyTimes();
 
@@ -6546,6 +6735,68 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
   }
 
   @Test
+  public void testGetRequiredHostGroups___defaultUpdater() throws Exception {
+    // given
+    Map<String, Map<String, String>> properties = new HashMap<>();
+
+    Map<String, String> coreSiteMap = new HashMap<>();
+    coreSiteMap.put("fs.defaultFS", "localhost");
+    properties.put("core-site", coreSiteMap);
+
+    properties.put("myservice-site",
+      ImmutableMap.of(
+        "myservice.slave.urls", "%HOSTGROUP::group4%:8080,%HOSTGROUP::group4%:8080,%HOSTGROUP::group5%:8080"));
+
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
+
+    expect(stack.getCardinality("NAMENODE")).andReturn(new Cardinality("1")).anyTimes();
+
+    TestHostGroup group1 = new TestHostGroup("group1",
+      ImmutableSet.of("HIVE_SERVER", "NAMENODE"),
+      Collections.singleton("host1"));
+
+    TestHostGroup group2 = new TestHostGroup("group2",
+      ImmutableSet.of("NAMENODE", "DATANODE"),
+      Collections.singleton("host2"));
+
+    Configuration group3Configuration = new Configuration(
+      ImmutableMap.of(
+        "myservice-site",
+        ImmutableMap.of("myservice.master.url", "%HOSTGROUP::group3%:8080")),
+      emptyMap());
+    TestHostGroup group3 = new TestHostGroup("group3",
+      ImmutableSet.of(),
+      Collections.singleton("host3"),
+      group3Configuration);
+
+    TestHostGroup group4 = new TestHostGroup("group4",
+      ImmutableSet.of(),
+      ImmutableSet.of("host4a", "host4b"));
+
+    TestHostGroup group5 = new TestHostGroup("group5",
+      ImmutableSet.of(),
+      Collections.singleton("host5"));
+
+    TestHostGroup group6 = new TestHostGroup("group6",
+      ImmutableSet.of(),
+      Collections.singleton("host6"));
+
+    Collection<TestHostGroup> hostGroups = Lists.newArrayList(group1, group2, group3, group4, group5, group6);
+
+    ClusterTopology topology = createClusterTopology(bp, clusterConfig, hostGroups);
+    BlueprintConfigurationProcessor updater = new BlueprintConfigurationProcessor(topology);
+
+    // when
+    Set<String> requiredGroups = updater.getRequiredHostGroups();
+
+    // then
+    // - group1 and group2 due to the SingleHostTopologyUpdater defined for core-site/fs.defaultFS and NAMENODE
+    // - group3 due to myservice-site/myservice.master.url in group3's host group config and the default property updater
+    // - group4 and group5 due to myservice-site/myservice.slave.urls in cluster config and the default property updater
+    assertEquals(ImmutableSet.of("group1", "group2", "group3", "group4", "group5"), requiredGroups);
+  }
+
+  @Test
   public void testAllDefaultUserAndGroupProxyPropertiesSet() throws Exception {
     Map<String, Map<String, String>> properties = new HashMap<>();
     Map<String, String> oozieEnvProperties = new HashMap<>();
@@ -6568,7 +6819,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     falconEnvProperties.put("falcon_user", "test-falcon-user");
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("DATANODE");
@@ -6615,7 +6866,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     falconEnvProperties.put("falcon_user", "test-falcon-user");
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("DATANODE");
@@ -6659,7 +6910,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     falconEnvProperties.put("falcon_user", "test-falcon-user");
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap());
+      emptyMap());
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("DATANODE");
@@ -6699,10 +6950,10 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     coreSiteProperties.put("hadoop.proxyuser.test-oozie-user.hosts", "testOozieHostsVal");
 
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("DATANODE");
@@ -6745,9 +6996,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> hgComponents1 = new HashSet<>();
@@ -6836,9 +7087,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
   private void validateAtlasHivePropertiesForTestCase(Map<String, Map<String, String>> properties) throws Exception {
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("ATLAS_SERVER");
@@ -6883,9 +7134,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> hgComponents1 = new HashSet<>();
@@ -6916,9 +7167,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("METRICS_COLLECTOR");
@@ -6947,9 +7198,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("METRICS_COLLECTOR");
@@ -6978,9 +7229,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("METRICS_COLLECTOR");
@@ -7010,9 +7261,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("METRICS_COLLECTOR");
@@ -7067,10 +7318,10 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hostGroups.add(group2);
 
     Configuration parentConfig = new Configuration(parentProperties,
-      Collections.emptyMap(), createStackDefaults());
+      emptyMap(), createStackDefaults());
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentConfig);
+      emptyMap(), parentConfig);
 
     ClusterTopology topology = createClusterTopology(bp, clusterConfig, hostGroups);
     topology.getAdvisedConfigurations().putAll(createAdvisedConfigMap());
@@ -7127,10 +7378,10 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
 
     Configuration parentConfig = new Configuration(parentProperties,
-      Collections.emptyMap(), createStackDefaults());
+      emptyMap(), createStackDefaults());
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentConfig);
+      emptyMap(), parentConfig);
 
     ClusterTopology topology = createClusterTopology(bp, clusterConfig, hostGroups);
     topology.getAdvisedConfigurations().putAll(createAdvisedConfigMap());
@@ -7195,10 +7446,10 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hostGroups.add(group2);
 
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap(), createStackDefaults());
+      emptyMap(), createStackDefaults());
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     ClusterTopology topology = createClusterTopology(bp, clusterConfig, hostGroups);
     topology.getAdvisedConfigurations().putAll(createAdvisedConfigMap());
@@ -7250,10 +7501,10 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hostGroups.add(group2);
 
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap(), createStackDefaults());
+      emptyMap(), createStackDefaults());
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     ClusterTopology topology = createClusterTopology(bp, clusterConfig, hostGroups);
     topology.getAdvisedConfigurations().putAll(createAdvisedConfigMap());
@@ -7284,9 +7535,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> rangerComponents = new HashSet<>();
@@ -7320,9 +7571,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> rangerComponents = new HashSet<>();
@@ -7356,9 +7607,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> rangerComponents = new HashSet<>();
@@ -7797,9 +8048,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> kmsServerComponents = new HashSet<>();
@@ -7839,9 +8090,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> kmsServerComponents = new HashSet<>();
@@ -7877,9 +8128,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> kmsServerComponents = new HashSet<>();
@@ -7935,9 +8186,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> hdfsComponents = new HashSet<>();
@@ -7976,9 +8227,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> kmsServerComponents = new HashSet<>();
@@ -8019,9 +8270,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> kmsServerComponents = new HashSet<>();
@@ -8073,9 +8324,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> kmsServerComponents = new HashSet<>();
@@ -8132,9 +8383,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> stormComponents = new HashSet<>();
@@ -8176,9 +8427,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> kmsServerComponents = new HashSet<>();
@@ -8224,9 +8475,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> hdfsComponents = new HashSet<>();
@@ -8265,9 +8516,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
 
     Collection<String> kmsServerComponents = new HashSet<>();
@@ -8518,7 +8769,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hawqSite.put("hawq_standby_address_host", "localhost");
     hawqSite.put("hawq_dfs_url", createHostAddress("localhost", expectedPortNamenode) + "/hawq_data");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     //Host group which has NAMENODE
     Collection<String> hgComponents = new HashSet<>();
@@ -8562,7 +8813,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     hawqSite.put("hawq_master_address_host", "localhost");
     hawqSite.put("hawq_standby_address_host", "localhost");
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     //Host group which has HAWQMASTER
     Collection<String> hgComponents1 = new HashSet<>();
@@ -8586,7 +8837,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
   public void testDoUpdateForBlueprintExport_NonTopologyProperty__AtlasClusterName() throws Exception {
     Map<String, Map<String, String>> properties = new HashMap<>();
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("ATLAS_SERVER");
@@ -8613,7 +8864,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     String someString = "String.To.Represent.A.String.Value";
     Map<String, Map<String, String>> properties = new HashMap<>();
 
-    Configuration clusterConfig = new Configuration(properties, Collections.emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap());
 
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("ATLAS_SERVER");
@@ -8663,8 +8914,8 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("druid-common", druidCommon);
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
-    Configuration parentClusterConfig = new Configuration(parentProperties, Collections.<String, Map<String, Map<String, String>>>emptyMap());
-    Configuration clusterConfig = new Configuration(properties, Collections.<String, Map<String, Map<String, String>>>emptyMap(), parentClusterConfig);
+    Configuration parentClusterConfig = new Configuration(parentProperties, emptyMap());
+    Configuration clusterConfig = new Configuration(properties, emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = Sets.newHashSet("DRUID_COORDINATOR");
     TestHostGroup group1 = new TestHostGroup("group1", hgComponents1, Collections.singleton("host1"));
@@ -8694,9 +8945,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("METRICS_COLLECTOR");
@@ -8724,9 +8975,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     hgComponents1.add("METRICS_COLLECTOR");
@@ -8754,9 +9005,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     Collection<String> hgComponents2 = new HashSet<>();
@@ -8786,10 +9037,10 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
     properties.put("ranger-admin-site", rangerAdminSiteProps);
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
 
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
     Collection<String> hgComponents = new HashSet<>();
     hgComponents.add("NAMENODE");
     hgComponents.add("SECONDARY_NAMENODE");
@@ -8875,9 +9126,9 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
 
     Map<String, Map<String, String>> parentProperties = new HashMap<>();
     Configuration parentClusterConfig = new Configuration(parentProperties,
-      Collections.emptyMap());
+      emptyMap());
     Configuration clusterConfig = new Configuration(properties,
-      Collections.emptyMap(), parentClusterConfig);
+      emptyMap(), parentClusterConfig);
 
     Collection<String> hgComponents1 = new HashSet<>();
     TestHostGroup group1 = new TestHostGroup("group1", hgComponents1, Collections.singleton("host1"));
@@ -9016,8 +9267,8 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport {
       this.name = name;
       this.components = components;
       this.hosts = hosts;
-      configuration = new Configuration(Collections.emptyMap(),
-        Collections.emptyMap());
+      configuration = new Configuration(emptyMap(),
+        emptyMap());
     }
 
     public TestHostGroup(String name, Collection<String> components, Collection<String> hosts, Configuration configuration) {

-- 
To stop receiving notification emails like this one, please contact
benyoka@apache.org.