private void applyStackAdvisorHostRecommendations(Cluster cluster,
                                                    Set<String> services,
                                                    Set<String> componentFilter,
                                                    Map<String, Map<String, String>> configurations)
    throws AmbariException {
    StackId stackVersion = cluster.getCurrentStackVersion();
    List<String> hostNames = new ArrayList<>();

    Collection<Host> hosts = cluster.getHosts();
    if (hosts != null) {
      for (Host host : hosts) {
        hostNames.add(host.getHostName());
      }
    }

    StackAdvisorRequest request = StackAdvisorRequest.StackAdvisorRequestBuilder
      .forStack(stackVersion.getStackName(), stackVersion.getStackVersion())
      .forServices(services)
      .forHosts(hostNames)
      .withComponentHostsMap(cluster.getServiceComponentHostMap(null, services))
      .ofType(StackAdvisorRequest.StackAdvisorRequestType.HOST_GROUPS)
      .build();

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

      RecommendationResponse.Recommendation recommendation = (response == null) ? null : response.getRecommendations();
      RecommendationResponse.Blueprint blueprint = (recommendation == null) ? null : recommendation.getBlueprint();
      Set<RecommendationResponse.HostGroup> hostGroups = (blueprint == null) ? null : blueprint.getHostGroups();


      if (hostGroups != null) {
        RecommendationResponse.BlueprintClusterBinding blueprintBinding = recommendation.getBlueprintClusterBinding();
        Map<String, RecommendationResponse.BindingHostGroup> bindingMap = new HashMap<>();
        if (blueprintBinding != null) {
          Set<RecommendationResponse.BindingHostGroup> bindingHostGroups = blueprintBinding.getHostGroups();
          if (bindingHostGroups != null) {
            for (RecommendationResponse.BindingHostGroup bindingHostGroup : bindingHostGroups) {
              bindingMap.put(bindingHostGroup.getName(), bindingHostGroup);
            }
          }
        }

        // Get (and create if needed) the clusterHostInfo map
        Map<String, String> clusterHostInfoMap = configurations.computeIfAbsent(CLUSTER_HOST_INFO, __ -> new HashMap<>());

        // Iterate through the recommendations to find the recommended host assignments
        for (RecommendationResponse.HostGroup hostGroup : hostGroups) {
          Set<Map<String, String>> components = hostGroup.getComponents();

          if (components != null) {
            RecommendationResponse.BindingHostGroup binding = bindingMap.get(hostGroup.getName());

            if (binding != null) {
              Set<Map<String, String>> hostGroupHosts = binding.getHosts();

              if (hostGroupHosts != null) {
                for (Map<String, String> component : components) {
                  String componentName = component.get("name");

                  // If the component filter is null or the current component is found in the filter,
                  // include it in the map
                  if ((componentFilter == null) || componentFilter.contains(componentName)) {
                    String key = StageUtils.getClusterHostInfoKey(componentName);

                    Set<String> fqdns = new TreeSet<>();

                    // Values are a comma-delimited list of hosts.
                    // If a value exists, split it and add the tokens to the set
                    if (!StringUtils.isEmpty(clusterHostInfoMap.get(key))) {
                      fqdns.addAll(Arrays.asList(clusterHostInfoMap.get(key).split(",")));
                    }

                    // Add the set of hosts for the current host group
                    for (Map<String, String> hostGroupHost : hostGroupHosts) {
                      String fqdn = hostGroupHost.get("fqdn");

                      if (!StringUtils.isEmpty(fqdn)) {
                        fqdns.add(fqdn);
                      }
                    }

                    // create the comma-delimited list of hosts
                    clusterHostInfoMap.put(key, StringUtils.join(fqdns, ','));
                  }
                }
              }
            }
          }
        }
      }
    } catch (StackAdvisorException e) {
      LOG.error("Failed to obtain the recommended host groups for the preconfigured components.", e);
      throw new AmbariException(e.getMessage(), e);
    }
  }
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