@Override
  public Map<String, Map<String, String>> applyStackAdvisorUpdates(Cluster cluster, Set<String> services,
                                                                   Map<String, Map<String, String>> existingConfigurations,
                                                                   Map<String, Map<String, String>> kerberosConfigurations,
                                                                   Map<String, Set<String>> propertiesToIgnore,
                                                                   Map<String, Set<String>> propertiesToRemove,
                                                                   boolean kerberosEnabled) throws AmbariException {

    List<String> hostNames = new ArrayList<>();
    Collection<Host> hosts = cluster.getHosts();

    if (hosts != null) {
      for (Host host : hosts) {
        hostNames.add(host.getHostName());
      }
    }

    // Don't actually call the stack advisor if no hosts are in the cluster, else the stack advisor
    // will throw a StackAdvisorException stating "Hosts and services must not be empty".
    // This could happen when enabling Kerberos while installing a cluster via Blueprints due to the
    // way hosts are discovered during the install process.
    if (!hostNames.isEmpty()) {
      Map<String, Map<String, Map<String, String>>> requestConfigurations = new HashMap<>();
      if (existingConfigurations != null) {
        for (Map.Entry<String, Map<String, String>> configuration : existingConfigurations.entrySet()) {
          Map<String, Map<String, String>> properties = new HashMap<>();
          String configType = configuration.getKey();
          Map<String, String> configurationProperties = configuration.getValue();

          if (configurationProperties == null) {
            configurationProperties = Collections.emptyMap();
          }

          if ("cluster-env".equals(configType)) {
            configurationProperties = new HashMap<>(configurationProperties);
            configurationProperties.put("security_enabled", (kerberosEnabled) ? "true" : "false");
          }

          properties.put("properties", configurationProperties);
          requestConfigurations.put(configType, properties);
        }
      }

      // Apply the current Kerberos properties...
      for (Map.Entry<String, Map<String, String>> configuration : kerberosConfigurations.entrySet()) {
        String configType = configuration.getKey();
        Map<String, String> configurationProperties = configuration.getValue();

        if ((configurationProperties != null) && !configurationProperties.isEmpty()) {
          Map<String, Map<String, String>> requestConfiguration = requestConfigurations.get(configType);

          if (requestConfiguration == null) {
            requestConfiguration = new HashMap<>();
            requestConfigurations.put(configType, requestConfiguration);
          }

          Map<String, String> requestConfigurationProperties = requestConfiguration.get("properties");
          if (requestConfigurationProperties == null) {
            requestConfigurationProperties = new HashMap<>();
          } else {
            requestConfigurationProperties = new HashMap<>(requestConfigurationProperties);
          }

          requestConfigurationProperties.putAll(configurationProperties);
          requestConfiguration.put("properties", requestConfigurationProperties);
        }
      }

      Set<StackId> visitedStacks = new HashSet<>();
      Map<String, Service> installedServices = cluster.getServices();

      for (String serviceName : services) {
        Service service = installedServices.get(serviceName);

        // Skip services that are not really installed
        if (service == null) {
          continue;
        }

        StackId stackId = service.getDesiredStackId();

        if (visitedStacks.contains(stackId)) {
          continue;
        }

        StackAdvisorRequest request = StackAdvisorRequest.StackAdvisorRequestBuilder
          .forStack(stackId.getStackName(), stackId.getStackVersion())
          .forServices(services)
          .forHosts(hostNames)
          .withComponentHostsMap(cluster.getServiceComponentHostMap(null, services))
          .withConfigurations(requestConfigurations)
          .ofType(StackAdvisorRequest.StackAdvisorRequestType.KERBEROS_CONFIGURATIONS)
          .build();

        try {
          RecommendationResponse response = stackAdvisorHelper.recommend(request);

          RecommendationResponse.Recommendation recommendation = (response == null) ? null : response.getRecommendations();
          RecommendationResponse.Blueprint blueprint = (recommendation == null) ? null : recommendation.getBlueprint();
          Map<String, RecommendationResponse.BlueprintConfigurations> configurations = (blueprint == null) ? null : blueprint.getConfigurations();

          if (configurations != null) {
            for (Map.Entry<String, RecommendationResponse.BlueprintConfigurations> configuration : configurations.entrySet()) {
              String configType = configuration.getKey();
              Map<String, String> recommendedConfigProperties = configuration.getValue().getProperties();
              Map<String, ValueAttributesInfo> recommendedConfigPropertyAttributes = configuration.getValue().getPropertyAttributes();
              Map<String, String> existingConfigProperties = (existingConfigurations == null) ? null : existingConfigurations.get(configType);
              Map<String, String> kerberosConfigProperties = kerberosConfigurations.get(configType);
              Set<String> ignoreProperties = (propertiesToIgnore == null) ? null : propertiesToIgnore.get(configType);

              addRecommendedPropertiesForConfigType(kerberosConfigurations, configType, recommendedConfigProperties,
                existingConfigProperties, kerberosConfigProperties, ignoreProperties);

              if (recommendedConfigPropertyAttributes != null) {
                removeRecommendedPropertiesForConfigType(configType, recommendedConfigPropertyAttributes,
                  existingConfigProperties, kerberosConfigurations, ignoreProperties, propertiesToRemove);
              }
            }
          }

        } catch (Exception e) {
          throw new AmbariException(e.getMessage(), e);
        }

        visitedStacks.add(stackId);
      }

    }

    return kerberosConfigurations;
  }
Adds host assignments, recommended by the Stack Advisor, to the configuration map (clusterHostInfo)
for the components specified in the component filter <code>componentFilter</code> (or all if the
component filter is <code>null</code>).

@param cluster         the cluster
@param services        the relevant services to consider
@param componentFilter the set of components to add to the clusterHostInfo structure
@param configurations  the configurations map to update
@throws AmbariException if an error occurs
ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java