You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2018/11/10 11:34:09 UTC

[ambari] branch trunk updated: AMBARI-24866. Make sure we use stack advisor to apply relevant service recommendation upon LDAP configuration addition/change (#2592)

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

smolnar 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 4eee0f5  AMBARI-24866. Make sure we use stack advisor to apply relevant service recommendation upon LDAP configuration addition/change (#2592)
4eee0f5 is described below

commit 4eee0f56d2fbfdfb0caace955339bc0c46a85a3c
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Sat Nov 10 12:34:02 2018 +0100

    AMBARI-24866. Make sure we use stack advisor to apply relevant service recommendation upon LDAP configuration addition/change (#2592)
---
 .../services/stackadvisor/StackAdvisorHelper.java  |   6 +-
 .../services/stackadvisor/StackAdvisorRequest.java |   1 +
 .../services/stackadvisor/StackAdvisorRunner.java  |   7 +-
 .../commands/StackAdvisorCommandType.java          |   2 +
 .../AmbariServerLDAPConfigurationHandler.java      |  30 ++-
 .../AmbariServerSSOConfigurationHandler.java       | 174 ++---------------
 ...erverStackAdvisorAwareConfigurationHandler.java | 211 +++++++++++++++++++++
 .../src/main/resources/scripts/stack_advisor.py    |   6 +
 .../src/main/resources/stacks/service_advisor.py   |   6 +
 .../src/main/resources/stacks/stack_advisor.py     | 107 +++++++++++
 .../stackadvisor/StackAdvisorHelperTest.java       |   5 +
 .../stackadvisor/StackAdvisorRequestTypeTest.java  |   5 +
 .../stackadvisor/StackAdvisorRunnerTest.java       |   4 -
 .../AmbariServerConfigurationHandlerTest.java      |  20 +-
 ...ComponentConfigurationResourceProviderTest.java |   9 +-
 15 files changed, 401 insertions(+), 192 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java
index abdc375..d3f2072 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java
@@ -47,7 +47,6 @@ public class StackAdvisorHelper {
   private File recommendationsDir;
   private String recommendationsArtifactsLifetime;
   private int recommendationsArtifactsRolloverMax;
-  public static String pythonStackAdvisorScript;
   private final AmbariMetaInfo metaInfo;
   private final AmbariServerConfigurationHandler ambariServerConfigurationHandler;
 
@@ -61,8 +60,6 @@ public class StackAdvisorHelper {
     this.recommendationsDir = conf.getRecommendationsDir();
     this.recommendationsArtifactsLifetime = conf.getRecommendationsArtifactsLifetime();
     this.recommendationsArtifactsRolloverMax = conf.getRecommendationsArtifactsRolloverMax();
-
-    this.pythonStackAdvisorScript = conf.getStackAdvisorScript();
     this.saRunner = saRunner;
     this.metaInfo = metaInfo;
     this.ambariServerConfigurationHandler = ambariServerConfigurationHandler;
@@ -145,6 +142,9 @@ public class StackAdvisorHelper {
     } else if (requestType == StackAdvisorRequestType.SSO_CONFIGURATIONS) {
       command = new ConfigurationRecommendationCommand(StackAdvisorCommandType.RECOMMEND_CONFIGURATIONS_FOR_SSO, recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType,
           requestId, saRunner, metaInfo, ambariServerConfigurationHandler);
+    } else if (requestType == StackAdvisorRequestType.LDAP_CONFIGURATIONS) {
+      command = new ConfigurationRecommendationCommand(StackAdvisorCommandType.RECOMMEND_CONFIGURATIONS_FOR_LDAP, recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType,
+          requestId, saRunner, metaInfo, ambariServerConfigurationHandler);
     } else if (requestType == StackAdvisorRequestType.KERBEROS_CONFIGURATIONS) {
       command = new ConfigurationRecommendationCommand(StackAdvisorCommandType.RECOMMEND_CONFIGURATIONS_FOR_KERBEROS, recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType,
           requestId, saRunner, metaInfo, ambariServerConfigurationHandler);
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
index 83a9367..ea4a4e0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
@@ -228,6 +228,7 @@ public class StackAdvisorRequest {
   public enum StackAdvisorRequestType {
     HOST_GROUPS("host_groups"),
     CONFIGURATIONS("configurations"),
+    LDAP_CONFIGURATIONS("ldap-configurations"),
     SSO_CONFIGURATIONS("sso-configurations"),
     KERBEROS_CONFIGURATIONS("kerberos-configurations"),
     CONFIGURATION_DEPENDENCIES("configuration-dependencies");
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunner.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunner.java
index 395200b..424feed 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunner.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunner.java
@@ -27,6 +27,7 @@ import java.util.List;
 import org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommandType;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.serviceadvisor.ServiceAdvisor;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
@@ -67,15 +68,13 @@ public class StackAdvisorRunner {
 
     switch (serviceAdvisorType) {
       case JAVA:
-        org.apache.ambari.serviceadvisor.ServiceAdvisor serviceAdvisor = new org.apache.ambari.serviceadvisor.ServiceAdvisor();
-
         LOG.info("StackAdvisorRunner.runScript(): Calling Java ServiceAdvisor's run method.");
-        stackAdvisorReturnCode = serviceAdvisor.run(saCommandType.toString(), hostsFile, servicesFile, outputFile, errorFile);
+        stackAdvisorReturnCode = ServiceAdvisor.run(saCommandType.toString(), hostsFile, servicesFile, outputFile, errorFile);
         LOG.info(String.format("StackAdvisorRunner.runScript(): Java ServiceAdvisor's return code: %d", stackAdvisorReturnCode));
         break;
       case PYTHON:
         LOG.info("StackAdvisorRunner.runScript(): Calling Python Stack Advisor.");
-        ProcessBuilder builder = prepareShellCommand(ServiceInfo.ServiceAdvisorType.PYTHON, StackAdvisorHelper.pythonStackAdvisorScript, saCommandType,
+        ProcessBuilder builder = prepareShellCommand(ServiceInfo.ServiceAdvisorType.PYTHON, configs.getStackAdvisorScript(), saCommandType,
             actionDirectory, outputFile,
             errorFile);
         builder.environment().put("METADATA_DIR_PATH", configs.getProperty(Configuration.METADATA_DIR_PATH));
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandType.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandType.java
index 57924ee..553d0f2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandType.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandType.java
@@ -31,6 +31,8 @@ public enum StackAdvisorCommandType {
 
   RECOMMEND_CONFIGURATIONS_FOR_SSO("recommend-configurations-for-sso"),
 
+  RECOMMEND_CONFIGURATIONS_FOR_LDAP("recommend-configurations-for-ldap"),
+
   RECOMMEND_CONFIGURATIONS_FOR_KERBEROS("recommend-configurations-for-kerberos"),
 
   RECOMMEND_CONFIGURATION_DEPENDENCIES("recommend-configuration-dependencies"),
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java
index bfb2e75..f08c1de 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java
@@ -18,19 +18,26 @@
 
 package org.apache.ambari.server.controller.internal;
 
+import static org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest.StackAdvisorRequestType.LDAP_CONFIGURATIONS;
+
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorHelper;
 import org.apache.ambari.server.configuration.AmbariServerConfigurationCategory;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
 import org.apache.ambari.server.ldap.service.AmbariLdapException;
 import org.apache.ambari.server.ldap.service.LdapFacade;
 import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -42,17 +49,27 @@ import com.google.inject.Singleton;
  * AmbariServerLDAPConfigurationHandler handles Ambari server LDAP-specific configuration properties.
  */
 @Singleton
-public class AmbariServerLDAPConfigurationHandler extends AmbariServerConfigurationHandler {
+public class AmbariServerLDAPConfigurationHandler extends AmbariServerStackAdvisorAwareConfigurationHandler {
   private static final Logger LOGGER = LoggerFactory.getLogger(AmbariServerLDAPConfigurationHandler.class);
 
   private final LdapFacade ldapFacade;
 
   @Inject
-  AmbariServerLDAPConfigurationHandler(LdapFacade ldapFacade, AmbariConfigurationDAO ambariConfigurationDAO,
-                                       AmbariEventPublisher publisher, Configuration ambariConfiguration) {
-    super(ambariConfigurationDAO, publisher, ambariConfiguration);
+  AmbariServerLDAPConfigurationHandler(Clusters clusters, ConfigHelper configHelper, AmbariManagementController managementController,
+      StackAdvisorHelper stackAdvisorHelper, AmbariConfigurationDAO ambariConfigurationDAO, AmbariEventPublisher publisher, Configuration ambariConfiguration,
+      LdapFacade ldapFacade) {
+    super(ambariConfigurationDAO, publisher, ambariConfiguration, clusters, configHelper, managementController, stackAdvisorHelper);
     this.ldapFacade = ldapFacade;
   }
+  
+  @Override
+  public void updateComponentCategory(String categoryName, Map<String, String> properties, boolean removePropertiesIfNotSpecified) throws AmbariException {
+    super.updateComponentCategory(categoryName, properties, removePropertiesIfNotSpecified);
+    final AmbariLdapConfiguration ldapConfiguration = new AmbariLdapConfiguration(getConfigurationProperties(AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName()));
+    if (ldapConfiguration.ldapEnabled()) {
+      processClusters(LDAP_CONFIGURATIONS);
+    }
+  }
 
   @Override
   public OperationResult performOperation(String categoryName, Map<String, String> properties,
@@ -143,6 +160,11 @@ public class AmbariServerLDAPConfigurationHandler extends AmbariServerConfigurat
     }
   }
 
+  @Override
+  protected String getServiceVersionNote() {
+    return "Ambari managed LDAP configurations";
+  }
+
   enum OperationType {
     TEST_CONNECTION("test-connection"),
     TEST_ATTRIBUTES("test-attributes"),
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerSSOConfigurationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerSSOConfigurationHandler.java
index dece520..39f0d5f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerSSOConfigurationHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerSSOConfigurationHandler.java
@@ -20,34 +20,20 @@ import static org.apache.ambari.server.configuration.AmbariServerConfigurationKe
 import static org.apache.ambari.server.configuration.AmbariServerConfigurationKey.SSO_MANAGE_SERVICES;
 
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorHelper;
-import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
-import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
-import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ConfigHelper;
-import org.apache.ambari.server.state.Host;
-import org.apache.ambari.server.state.Service;
-import org.apache.ambari.server.state.StackId;
-import org.apache.ambari.server.state.ValueAttributesInfo;
 import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -57,29 +43,12 @@ import com.google.inject.Singleton;
  * handing changes to the SSO configuration
  */
 @Singleton
-public class AmbariServerSSOConfigurationHandler extends AmbariServerConfigurationHandler {
-  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariServerSSOConfigurationHandler.class);
-
-  private final Clusters clusters;
-
-  private final ConfigHelper configHelper;
-
-  private final AmbariManagementController managementController;
-
-  private final StackAdvisorHelper stackAdvisorHelper;
+public class AmbariServerSSOConfigurationHandler extends AmbariServerStackAdvisorAwareConfigurationHandler {
 
   @Inject
-  public AmbariServerSSOConfigurationHandler(Clusters clusters, ConfigHelper configHelper,
-                                             AmbariManagementController managementController,
-                                             StackAdvisorHelper stackAdvisorHelper,
-                                             AmbariConfigurationDAO ambariConfigurationDAO,
-                                             AmbariEventPublisher publisher,
-                                             Configuration ambariConfiguration) {
-    super(ambariConfigurationDAO, publisher, ambariConfiguration);
-    this.clusters = clusters;
-    this.configHelper = configHelper;
-    this.managementController = managementController;
-    this.stackAdvisorHelper = stackAdvisorHelper;
+  public AmbariServerSSOConfigurationHandler(Clusters clusters, ConfigHelper configHelper, AmbariManagementController managementController,
+      StackAdvisorHelper stackAdvisorHelper, AmbariConfigurationDAO ambariConfigurationDAO, AmbariEventPublisher publisher, Configuration ambariConfiguration) {
+    super(ambariConfigurationDAO, publisher, ambariConfiguration, clusters, configHelper, managementController, stackAdvisorHelper);
   }
 
   @Override
@@ -91,24 +60,11 @@ public class AmbariServerSSOConfigurationHandler extends AmbariServerConfigurati
     super.updateComponentCategory(categoryName, properties, removePropertiesIfNotSpecified);
 
     // Determine if Ambari is managing SSO configurations...
-    boolean manageSSOConfigurations;
-
-    Map<String, String> ssoProperties = getConfigurationProperties(SSO_CONFIGURATION.getCategoryName());
-    manageSSOConfigurations = (ssoProperties != null) && "true".equalsIgnoreCase(ssoProperties.get(SSO_MANAGE_SERVICES.key()));
+    final Map<String, String> ssoProperties = getConfigurationProperties(SSO_CONFIGURATION.getCategoryName());
+    final boolean manageSSOConfigurations = (ssoProperties != null) && "true".equalsIgnoreCase(ssoProperties.get(SSO_MANAGE_SERVICES.key()));
 
     if (manageSSOConfigurations) {
-      Map<String, Cluster> clusterMap = clusters.getClusters();
-
-      if (clusterMap != null) {
-        for (Cluster cluster : clusterMap.values()) {
-          try {
-            LOGGER.info(String.format("Managing the SSO configuration for the cluster named '%s'", cluster.getClusterName()));
-            processCluster(cluster);
-          } catch (AmbariException | StackAdvisorException e) {
-            LOGGER.warn(String.format("Failed to update the the SSO configuration for the cluster named '%s': ", cluster.getClusterName()), e);
-          }
-        }
-      }
+      processClusters(SSO_CONFIGURATIONS);
     }
   }
 
@@ -133,117 +89,9 @@ public class AmbariServerSSOConfigurationHandler extends AmbariServerConfigurati
           .collect(Collectors.toSet());
     }
   }
-
-  /**
-   * Build the stack advisor request, call the stack advisor, then automatically handle the recommendations.
-   * <p>
-   * Any recommendation coming back from the Stack/service advisor is expected to be only SSO-related
-   * configurations.
-   * <p>
-   * If there are no changes to the current configurations, no new configuration versions will be created.
-   *
-   * @param cluster the cluster to process
-   * @throws AmbariException
-   * @throws StackAdvisorException
-   */
-  private void processCluster(Cluster cluster) throws AmbariException, StackAdvisorException {
-    StackId stackVersion = cluster.getCurrentStackVersion();
-    List<String> hosts = cluster.getHosts().stream().map(Host::getHostName).collect(Collectors.toList());
-    Set<String> serviceNames = cluster.getServices().values().stream().map(Service::getName).collect(Collectors.toSet());
-
-    // Build the StackAdvisor request for SSO-related configurations.  it is expected that the stack
-    // advisor will abide by the configurations set in the Ambari sso-configurations to enable and
-    // disable SSO integration for the relevant services.
-    StackAdvisorRequest request = StackAdvisorRequest.StackAdvisorRequestBuilder.
-        forStack(stackVersion.getStackName(), stackVersion.getStackVersion())
-        .ofType(SSO_CONFIGURATIONS)
-        .forHosts(hosts)
-        .forServices(serviceNames)
-        .withComponentHostsMap(cluster.getServiceComponentHostMap(null, null))
-        .withConfigurations(calculateExistingConfigurations(cluster))
-        .build();
-
-    // Execute the stack advisor
-    RecommendationResponse response = stackAdvisorHelper.recommend(request);
-
-    // Process the recommendations and automatically apply them.  Ideally this is what the user wanted
-    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()) {
-        processConfigurationType(cluster, configuration.getKey(), configuration.getValue());
-      }
-    }
-  }
-
-  /**
-   * Process the configuration to add, update, and remove properties as needed.
-   *
-   * @param cluster        the cluster
-   * @param configType     the configuration type
-   * @param configurations the recommended configuration values
-   * @throws AmbariException
-   */
-  private void processConfigurationType(Cluster cluster, String configType,
-                                        RecommendationResponse.BlueprintConfigurations configurations)
-      throws AmbariException {
-
-    Map<String, String> updates = new HashMap<>();
-    Collection<String> removals = new HashSet<>();
-
-    // Gather the updates
-    Map<String, String> recommendedConfigProperties = configurations.getProperties();
-    if (recommendedConfigProperties != null) {
-      updates.putAll(recommendedConfigProperties);
-    }
-
-    // Determine if any properties need to be removed
-    Map<String, ValueAttributesInfo> recommendedConfigPropertyAttributes = configurations.getPropertyAttributes();
-    if (recommendedConfigPropertyAttributes != null) {
-      for (Map.Entry<String, ValueAttributesInfo> entry : recommendedConfigPropertyAttributes.entrySet()) {
-        ValueAttributesInfo info = entry.getValue();
-
-        if ((info != null) && "true".equalsIgnoreCase(info.getDelete())) {
-          updates.remove(entry.getKey());
-          removals.add(entry.getKey());
-        }
-      }
-    }
-
-    configHelper.updateConfigType(cluster, cluster.getCurrentStackVersion(), managementController,
-        configType, updates, removals,
-        "internal", "Ambari-managed single sign-on configurations");
-  }
-
-  /**
-   * Calculate the current configurations for all services
-   *
-   * @param cluster the cluster
-   * @return a map of services and their configurations
-   * @throws AmbariException
-   */
-  private Map<String, Map<String, Map<String, String>>> calculateExistingConfigurations(Cluster cluster) throws AmbariException {
-    Map<String, Map<String, String>> configurationTags = configHelper.getEffectiveDesiredTags(cluster, null);
-    Map<String, Map<String, String>> effectiveConfigs = configHelper.getEffectiveConfigProperties(cluster, configurationTags);
-
-    Map<String, Map<String, Map<String, String>>> requestConfigurations = new HashMap<>();
-    if (effectiveConfigs != null) {
-      for (Map.Entry<String, Map<String, String>> configuration : effectiveConfigs.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();
-        }
-
-        properties.put("properties", configurationProperties);
-        requestConfigurations.put(configType, properties);
-      }
-    }
-
-    return requestConfigurations;
+  
+  @Override
+  protected String getServiceVersionNote() {
+    return "Ambari-managed single sign-on configurations";
   }
 }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerStackAdvisorAwareConfigurationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerStackAdvisorAwareConfigurationHandler.java
new file mode 100644
index 0000000..e872de9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerStackAdvisorAwareConfigurationHandler.java
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
+import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorHelper;
+import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
+import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
+import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.ConfigHelper;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.ValueAttributesInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * AmbariServerStackAdvisorAwareConfigurationHandler handles Ambari server specific configuration properties using the stack advisor.
+ */
+class AmbariServerStackAdvisorAwareConfigurationHandler extends AmbariServerConfigurationHandler {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariServerStackAdvisorAwareConfigurationHandler.class);
+
+  private final Clusters clusters;
+  private final ConfigHelper configHelper;
+  private final AmbariManagementController managementController;
+  private final StackAdvisorHelper stackAdvisorHelper;
+
+  AmbariServerStackAdvisorAwareConfigurationHandler(AmbariConfigurationDAO ambariConfigurationDAO, AmbariEventPublisher publisher, Configuration ambariConfiguration,
+      Clusters clusters, ConfigHelper configHelper, AmbariManagementController managementController, StackAdvisorHelper stackAdvisorHelper) {
+    super(ambariConfigurationDAO, publisher, ambariConfiguration);
+    this.clusters = clusters;
+    this.configHelper = configHelper;
+    this.managementController = managementController;
+    this.stackAdvisorHelper = stackAdvisorHelper;
+  }
+  
+  /**
+   * Build the stack advisor request, call the stack advisor, then automatically
+   * handle the recommendations on all clusters that managed by Ambari.
+   * 
+   * @param stackAdvisorRequestType
+   *          the stack advisor request type
+   */
+  protected void processClusters(StackAdvisorRequest.StackAdvisorRequestType stackAdvisorRequestType) {
+    final Map<String, Cluster> clusterMap = clusters.getClusters();
+
+    if (clusterMap != null) {
+      for (Cluster cluster : clusterMap.values()) {
+        try {
+          LOGGER.info("Managing the {} configuration for the cluster named '{}'", stackAdvisorRequestType.toString(), cluster.getClusterName());
+          processCluster(cluster, stackAdvisorRequestType);
+        } catch (AmbariException | StackAdvisorException e) {
+          LOGGER.warn("Failed to update the {} for the cluster named '{}': ", stackAdvisorRequestType.toString(), cluster.getClusterName(), e);
+        }
+      }
+    }
+  }
+
+  /**
+   * Build the stack advisor request, call the stack advisor, then automatically
+   * handle the recommendations.
+   * <p>
+   * Any recommendation coming back from the Stack/service advisor is expected to
+   * be only related configurations of the given request type (LDAP/SSO)
+   * <p>
+   * If there are no changes to the current configurations, no new configuration
+   * versions will be created.
+   *
+   * @param cluster
+   *          the cluster to process
+   * @param stackAdvisorRequestType
+   *          the stack advisor request type
+   * @throws AmbariException
+   * @throws StackAdvisorException
+   */
+  protected void processCluster(Cluster cluster, StackAdvisorRequest.StackAdvisorRequestType stackAdvisorRequestType) throws AmbariException, StackAdvisorException {
+    final StackId stackVersion = cluster.getCurrentStackVersion();
+    final List<String> hosts = cluster.getHosts().stream().map(Host::getHostName).collect(Collectors.toList());
+    final Set<String> serviceNames = cluster.getServices().values().stream().map(Service::getName).collect(Collectors.toSet());
+
+    final StackAdvisorRequest request = StackAdvisorRequest.StackAdvisorRequestBuilder
+        .forStack(stackVersion.getStackName(), stackVersion.getStackVersion())
+        .ofType(stackAdvisorRequestType)
+        .forHosts(hosts)
+        .forServices(serviceNames)
+        .withComponentHostsMap(cluster.getServiceComponentHostMap(null, null))
+        .withConfigurations(calculateExistingConfigurations(cluster))
+        .build();
+
+    // Execute the stack advisor
+    final RecommendationResponse response = stackAdvisorHelper.recommend(request);
+
+    // Process the recommendations and automatically apply them. Ideally this is what the user wanted
+    final RecommendationResponse.Recommendation recommendation = (response == null) ? null : response.getRecommendations();
+    final RecommendationResponse.Blueprint blueprint = (recommendation == null) ? null : recommendation.getBlueprint();
+    final Map<String, RecommendationResponse.BlueprintConfigurations> configurations = (blueprint == null) ? null : blueprint.getConfigurations();
+
+    if (configurations != null) {
+      for (Map.Entry<String, RecommendationResponse.BlueprintConfigurations> configuration : configurations.entrySet()) {
+        processConfigurationType(cluster, configuration.getKey(), configuration.getValue());
+      }
+    }
+  }
+
+  /**
+   * Process the configuration to add, update, and remove properties as needed.
+   *
+   * @param cluster
+   *          the cluster
+   * @param configType
+   *          the configuration type
+   * @param configurations
+   *          the recommended configuration values
+   * @throws AmbariException
+   */
+  private void processConfigurationType(Cluster cluster, String configType, RecommendationResponse.BlueprintConfigurations configurations) throws AmbariException {
+    Map<String, String> updates = new HashMap<>();
+    Collection<String> removals = new HashSet<>();
+
+    // Gather the updates
+    Map<String, String> recommendedConfigProperties = configurations.getProperties();
+    if (recommendedConfigProperties != null) {
+      updates.putAll(recommendedConfigProperties);
+    }
+
+    // Determine if any properties need to be removed
+    Map<String, ValueAttributesInfo> recommendedConfigPropertyAttributes = configurations.getPropertyAttributes();
+    if (recommendedConfigPropertyAttributes != null) {
+      for (Map.Entry<String, ValueAttributesInfo> entry : recommendedConfigPropertyAttributes.entrySet()) {
+        ValueAttributesInfo info = entry.getValue();
+
+        if ((info != null) && "true".equalsIgnoreCase(info.getDelete())) {
+          updates.remove(entry.getKey());
+          removals.add(entry.getKey());
+        }
+      }
+    }
+
+    configHelper.updateConfigType(cluster, cluster.getCurrentStackVersion(), managementController, configType, updates, removals, "internal",
+        getServiceVersionNote());
+  }
+  
+  protected String getServiceVersionNote() {
+    return "Ambari-managed configuration change";
+  }
+
+  /**
+   * Calculate the current configurations for all services
+   *
+   * @param cluster
+   *          the cluster
+   * @return a map of services and their configurations
+   * @throws AmbariException
+   */
+  private Map<String, Map<String, Map<String, String>>> calculateExistingConfigurations(Cluster cluster) throws AmbariException {
+    Map<String, Map<String, String>> configurationTags = configHelper.getEffectiveDesiredTags(cluster, null);
+    Map<String, Map<String, String>> effectiveConfigs = configHelper.getEffectiveConfigProperties(cluster, configurationTags);
+
+    Map<String, Map<String, Map<String, String>>> requestConfigurations = new HashMap<>();
+    if (effectiveConfigs != null) {
+      for (Map.Entry<String, Map<String, String>> configuration : effectiveConfigs.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();
+        }
+
+        properties.put("properties", configurationProperties);
+        requestConfigurations.put(configType, properties);
+      }
+    }
+
+    return requestConfigurations;
+  }
+
+}
diff --git a/ambari-server/src/main/resources/scripts/stack_advisor.py b/ambari-server/src/main/resources/scripts/stack_advisor.py
index b39a6e8..5ae2128 100755
--- a/ambari-server/src/main/resources/scripts/stack_advisor.py
+++ b/ambari-server/src/main/resources/scripts/stack_advisor.py
@@ -27,6 +27,7 @@ RECOMMEND_COMPONENT_LAYOUT_ACTION = 'recommend-component-layout'
 VALIDATE_COMPONENT_LAYOUT_ACTION = 'validate-component-layout'
 RECOMMEND_CONFIGURATIONS = 'recommend-configurations'
 RECOMMEND_CONFIGURATIONS_FOR_SSO = 'recommend-configurations-for-sso'
+RECOMMEND_CONFIGURATIONS_FOR_LDAP = 'recommend-configurations-for-ldap'
 RECOMMEND_CONFIGURATIONS_FOR_KERBEROS = 'recommend-configurations-for-kerberos'
 RECOMMEND_CONFIGURATION_DEPENDENCIES = 'recommend-configuration-dependencies'
 VALIDATE_CONFIGURATIONS = 'validate-configurations'
@@ -35,6 +36,7 @@ ALL_ACTIONS = [RECOMMEND_COMPONENT_LAYOUT_ACTION,
                VALIDATE_COMPONENT_LAYOUT_ACTION,
                RECOMMEND_CONFIGURATIONS,
                RECOMMEND_CONFIGURATIONS_FOR_SSO,
+               RECOMMEND_CONFIGURATIONS_FOR_LDAP,
                RECOMMEND_CONFIGURATIONS_FOR_KERBEROS,
                RECOMMEND_CONFIGURATION_DEPENDENCIES,
                VALIDATE_CONFIGURATIONS]
@@ -125,6 +127,10 @@ def main(argv=None):
     services[ADVISOR_CONTEXT] = {CALL_TYPE : 'recommendConfigurationsForSSO'}
     result = stackAdvisor.recommendConfigurationsForSSO(services, hosts)
     result_file = os.path.join(actionDir, "configurations.json")
+  elif action == RECOMMEND_CONFIGURATIONS_FOR_LDAP:
+    services[ADVISOR_CONTEXT] = {CALL_TYPE : 'recommendConfigurationsForLDAP'}
+    result = stackAdvisor.recommendConfigurationsForLDAP(services, hosts)
+    result_file = os.path.join(actionDir, "configurations.json")
   elif action == RECOMMEND_CONFIGURATIONS_FOR_KERBEROS:
     services[ADVISOR_CONTEXT] = {CALL_TYPE : 'recommendConfigurationsForKerberos'}
     result = stackAdvisor.recommendConfigurationsForKerberos(services, hosts)
diff --git a/ambari-server/src/main/resources/stacks/service_advisor.py b/ambari-server/src/main/resources/stacks/service_advisor.py
index 43bbbab..e79e0dc 100644
--- a/ambari-server/src/main/resources/stacks/service_advisor.py
+++ b/ambari-server/src/main/resources/stacks/service_advisor.py
@@ -99,6 +99,12 @@ class ServiceAdvisor(DefaultStackAdvisor):
     """
     pass
 
+  def getServiceConfigurationRecommendationsForLDAP(self, configurations, clusterSummary, services, hosts):
+    """
+    Any LDAP related configuration recommendations for the service should be defined in this function.
+    """
+    pass
+
   def getServiceConfigurationRecommendationsForKerberos(self, configurations, clusterSummary, services, hosts):
     """
     Any Kerberos-related configuration recommendations for the service should be defined in this function.
diff --git a/ambari-server/src/main/resources/stacks/stack_advisor.py b/ambari-server/src/main/resources/stacks/stack_advisor.py
index 7b53648..336ae75 100644
--- a/ambari-server/src/main/resources/stacks/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/stack_advisor.py
@@ -341,6 +341,64 @@ class StackAdvisor(object):
     """
     pass
 
+  def recommendConfigurationsForLDAP(self, services, hosts):
+    """
+    Returns recommendation of LDAP related service configurations based on host-specific layout of components.
+
+    This function takes as input all details about services being installed, and hosts
+    they are being installed into, to recommend host-specific configurations.
+
+    @type services: dictionary
+    @param services: Dictionary containing all information about services and component layout selected by the user.
+    @type hosts: dictionary
+    @param hosts: Dictionary containing all information about hosts in this cluster
+    @rtype: dictionary
+    @return: Layout recommendation of service components on cluster hosts in Ambari Blueprints friendly format.
+        Example: {
+         "services": [
+          "HIVE",
+          "TEZ",
+          "YARN"
+         ],
+         "recommendations": {
+          "blueprint": {
+           "host_groups": [],
+           "configurations": {
+            "yarn-site": {
+             "properties": {
+              "yarn.scheduler.minimum-allocation-mb": "682",
+              "yarn.scheduler.maximum-allocation-mb": "2048",
+              "yarn.nodemanager.resource.memory-mb": "2048"
+             }
+            },
+            "tez-site": {
+             "properties": {
+              "tez.am.java.opts": "-server -Xmx546m -Djava.net.preferIPv4Stack=true -XX:+UseNUMA -XX:+UseParallelGC",
+              "tez.am.resource.memory.mb": "682"
+             }
+            },
+            "hive-site": {
+             "properties": {
+              "hive.tez.container.size": "682",
+              "hive.tez.java.opts": "-server -Xmx546m -Djava.net.preferIPv4Stack=true -XX:NewRatio=8 -XX:+UseNUMA -XX:+UseParallelGC",
+              "hive.auto.convert.join.noconditionaltask.size": "238026752"
+             }
+            }
+           }
+          },
+          "blueprint_cluster_binding": {
+           "host_groups": []
+          }
+         },
+         "hosts": [
+          "c6401.ambari.apache.org",
+          "c6402.ambari.apache.org",
+          "c6403.ambari.apache.org"
+         ]
+        }
+    """
+    pass
+
   def recommendConfigurationsForKerberos(self, services, hosts):
     """
     Returns recommendation of Kerberos-related service configurations based on host-specific layout
@@ -1691,6 +1749,55 @@ class DefaultStackAdvisor(StackAdvisor):
 
     return recommendations
 
+  def recommendConfigurationsForLDAP(self, services, hosts):
+    self.services = services
+
+    stackName = services["Versions"]["stack_name"]
+    stackVersion = services["Versions"]["stack_version"]
+    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
+    servicesList, componentsList = self.get_service_and_component_lists(services["services"])
+
+    clusterSummary = self.getConfigurationClusterSummary(servicesList, hosts, componentsList, services)
+
+    recommendations = {
+      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
+      "hosts": hostsList,
+      "services": servicesList,
+      "recommendations": {
+        "blueprint": {
+          "configurations": {},
+          "host_groups": []
+        },
+        "blueprint_cluster_binding": {
+          "host_groups": []
+        }
+      }
+    }
+
+    # If recommendation for config groups
+    if "config-groups" in services:
+      self.recommendConfigGroupsConfigurations(recommendations, services, componentsList, hosts, servicesList)
+    else:
+      configurations = recommendations["recommendations"]["blueprint"]["configurations"]
+
+      # there can be dependencies between service recommendations which require special ordering
+      # for now, make sure custom services (that have service advisors) run after standard ones
+      serviceAdvisors = []
+      recommenderDict = self.getServiceConfigurationRecommenderForSSODict()
+      for service in services["services"]:
+        serviceName = service["StackServices"]["service_name"]
+        calculation = recommenderDict.get(serviceName, None)
+        if calculation is not None:
+          calculation(configurations, clusterSummary, services, hosts)
+        else:
+          serviceAdvisor = self.getServiceAdvisor(serviceName)
+          if serviceAdvisor is not None:
+            serviceAdvisors.append(serviceAdvisor)
+      for serviceAdvisor in serviceAdvisors:
+        serviceAdvisor.getServiceConfigurationRecommendationsForLDAP(configurations, clusterSummary, services, hosts)
+
+    return recommendations
+
   def recommendConfigurationsForKerberos(self, services, hosts):
     self.services = services
 
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java
index 2b3e6bb..8f85216 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java
@@ -182,6 +182,11 @@ public class StackAdvisorHelperTest {
   }
 
   @Test
+  public void testCreateRecommendationCommand_returnsLDAPConfigurationRecommendationCommand() throws IOException, StackAdvisorException {
+    testCreateConfigurationRecommendationCommand(StackAdvisorRequestType.LDAP_CONFIGURATIONS, StackAdvisorCommandType.RECOMMEND_CONFIGURATIONS_FOR_LDAP);
+  }
+
+  @Test
   public void testCreateRecommendationCommand_returnsKerberosConfigurationRecommendationCommand() throws IOException, StackAdvisorException {
     testCreateConfigurationRecommendationCommand(StackAdvisorRequestType.KERBEROS_CONFIGURATIONS, StackAdvisorCommandType.RECOMMEND_CONFIGURATIONS_FOR_KERBEROS);
   }
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequestTypeTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequestTypeTest.java
index cc0dac2..300ae00 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequestTypeTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequestTypeTest.java
@@ -45,6 +45,11 @@ public class StackAdvisorRequestTypeTest {
   }
 
   @Test
+  public void testFromString_returnsLDAPConfigurationsType() throws StackAdvisorException {
+    testFromString("ldap-configurations", StackAdvisorRequestType.LDAP_CONFIGURATIONS);
+  }
+
+  @Test
   public void testFromString_returnsKerberosConfigurationsType() throws StackAdvisorException {
     testFromString("kerberos-configurations", StackAdvisorRequestType.KERBEROS_CONFIGURATIONS);
   }
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunnerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunnerTest.java
index a4fea7c..c77c603 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunnerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunnerTest.java
@@ -61,7 +61,6 @@ public class StackAdvisorRunnerTest {
 
   @Test(expected = StackAdvisorException.class)
   public void testRunScript_processStartThrowsException_returnFalse() throws Exception {
-    String script = "echo";
     StackAdvisorCommandType saCommandType = StackAdvisorCommandType.RECOMMEND_COMPONENT_LAYOUT;
     File actionDirectory = temp.newFolder("actionDir");
     ProcessBuilder processBuilder = createNiceMock(ProcessBuilder.class);
@@ -78,7 +77,6 @@ public class StackAdvisorRunnerTest {
 
   @Test(expected = StackAdvisorRequestException.class)
   public void testRunScript_processExitCode1_returnFalse() throws Exception {
-    String script = "echo";
     StackAdvisorCommandType saCommandType = StackAdvisorCommandType.RECOMMEND_COMPONENT_LAYOUT;
     File actionDirectory = temp.newFolder("actionDir");
     ProcessBuilder processBuilder = createNiceMock(ProcessBuilder.class);
@@ -97,7 +95,6 @@ public class StackAdvisorRunnerTest {
 
   @Test(expected = StackAdvisorException.class)
   public void testRunScript_processExitCode2_returnFalse() throws Exception {
-    String script = "echo";
     StackAdvisorCommandType saCommandType = StackAdvisorCommandType.RECOMMEND_COMPONENT_LAYOUT;
     File actionDirectory = temp.newFolder("actionDir");
     ProcessBuilder processBuilder = createNiceMock(ProcessBuilder.class);
@@ -117,7 +114,6 @@ public class StackAdvisorRunnerTest {
 
   @Test
   public void testRunScript_processExitCodeZero_returnTrue() throws Exception {
-    String script = "echo";
     StackAdvisorCommandType saCommandType = StackAdvisorCommandType.RECOMMEND_COMPONENT_LAYOUT;
     File actionDirectory = temp.newFolder("actionDir");
     ProcessBuilder processBuilder = createNiceMock(ProcessBuilder.class);
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandlerTest.java
index 0a0d1a4..4c0082e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandlerTest.java
@@ -70,10 +70,10 @@ public class AmbariServerConfigurationHandlerTest extends EasyMockSupport {
     AmbariEventPublisher publisher = createMock(AmbariEventPublisher.class);
     Configuration configuration = createMock(Configuration.class);
 
-    replayAll();
-
     AmbariServerConfigurationHandler handler = new AmbariServerConfigurationHandler(ambariConfigurationDAO, publisher, configuration);
 
+    replayAll();
+
     Map<String, RootServiceComponentConfiguration> allConfigurations = handler.getComponentConfigurations(null);
     Assert.assertEquals(2, allConfigurations.size());
     Assert.assertTrue(allConfigurations.containsKey(SSO_CONFIGURATION.getCategoryName()));
@@ -101,10 +101,10 @@ public class AmbariServerConfigurationHandlerTest extends EasyMockSupport {
 
     Configuration configuration = createMock(Configuration.class);
 
-    replayAll();
-
     AmbariServerConfigurationHandler handler = new AmbariServerConfigurationHandler(ambariConfigurationDAO, publisher, configuration);
 
+    replayAll();
+
     handler.removeComponentConfiguration(SSO_CONFIGURATION.getCategoryName());
     handler.removeComponentConfiguration("invalid category");
 
@@ -129,10 +129,10 @@ public class AmbariServerConfigurationHandlerTest extends EasyMockSupport {
 
     Configuration configuration = createMock(Configuration.class);
 
-    replayAll();
-
     AmbariServerConfigurationHandler handler = new AmbariServerConfigurationHandler(ambariConfigurationDAO, publisher, configuration);
 
+    replayAll();
+
     handler.updateComponentCategory(SSO_CONFIGURATION.getCategoryName(), properties, false);
 
     handler.updateComponentCategory(SSO_CONFIGURATION.getCategoryName(), properties, true);
@@ -163,10 +163,10 @@ public class AmbariServerConfigurationHandlerTest extends EasyMockSupport {
     AmbariEventPublisher publisher = createMock(AmbariEventPublisher.class);
     Configuration configuration = createMock(Configuration.class);
 
-    replayAll();
-
     AmbariServerConfigurationHandler handler = new AmbariServerConfigurationHandler(ambariConfigurationDAO, publisher, configuration);
 
+    replayAll();
+
     Map<String, Map<String, String>> allConfigurations = handler.getConfigurations();
     Assert.assertEquals(2, allConfigurations.size());
     Assert.assertTrue(allConfigurations.containsKey(SSO_CONFIGURATION.getCategoryName()));
@@ -192,10 +192,10 @@ public class AmbariServerConfigurationHandlerTest extends EasyMockSupport {
     AmbariEventPublisher publisher = createMock(AmbariEventPublisher.class);
     Configuration configuration = createMock(Configuration.class);
 
-    replayAll();
-
     AmbariServerConfigurationHandler handler = new AmbariServerConfigurationHandler(ambariConfigurationDAO, publisher, configuration);
 
+    replayAll();
+
     Map<String, String> ssoConfigurations = handler.getConfigurationProperties(SSO_CONFIGURATION.getCategoryName());
     Assert.assertEquals(2, ssoConfigurations.size());
     Assert.assertTrue(ssoConfigurations.containsKey(SSO_ENABLED_SERVICES.key()));
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProviderTest.java
index 17ef6ca..0576528 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProviderTest.java
@@ -204,6 +204,7 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
       expect(dao.reconcileCategory(eq(SSO_CONFIG_CATEGORY), capture(capturedProperties2), eq(true)))
           .andReturn(true)
           .once();
+      expect(dao.findByCategory(LDAP_CONFIG_CATEGORY)).andReturn(Collections.emptyList());
       expect(dao.findByCategory(eq(SSO_CONFIG_CATEGORY)))
           .andReturn(Collections.emptyList())
           .once();
@@ -437,7 +438,7 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
       expect(dao.reconcileCategory(eq(LDAP_CONFIG_CATEGORY), capture(capturedProperties1), eq(false)))
           .andReturn(true)
           .once();
-
+      expect(dao.findByCategory(LDAP_CONFIG_CATEGORY)).andReturn(Collections.emptyList());
       publisher.publish(anyObject(AmbariConfigurationChangedEvent.class));
       expectLastCall().times(1);
     }
@@ -484,7 +485,6 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
     propertySets.add(toRequestProperties(LDAP_CONFIG_CATEGORY, properties));
     setupBasicExpectations(properties, propertySets);
     expect(configuration.isSecurityPasswordEncryptionEnabled()).andThrow(new AssertionFailedError()).anyTimes(); //this call should never have never been hit
-
     replayAll();
     resourceProvider.updateResources(request, predicate);
     verifyAll();
@@ -548,7 +548,7 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
   private void setupBasicExpectations(Map<String, String> expectedProperties, Set<Map<String, Object>> propertySets) {
     expect(request.getProperties()).andReturn(propertySets).once();
     expect(request.getRequestInfoProperties()).andReturn(new HashMap<>());
-    expect(dao.findByCategory(LDAP_CONFIG_CATEGORY)).andReturn(createEntities(AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName(), expectedProperties)).times(2);
+    expect(dao.findByCategory(LDAP_CONFIG_CATEGORY)).andReturn(createEntities(AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName(), expectedProperties)).times(3);
     expect(factory.getInstance(RootService.AMBARI.name(), RootComponent.AMBARI_SERVER.name(), LDAP_CONFIG_CATEGORY)).andReturn(ambariServerLDAPConfigurationHandler).once();
   }
 
@@ -626,7 +626,8 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
 
         bind(AmbariServerConfigurationHandler.class).toInstance(new AmbariServerConfigurationHandler(ambariConfigurationDAO, publisher, configuration));
         bind(AmbariServerSSOConfigurationHandler.class).toInstance(new AmbariServerSSOConfigurationHandler(clusters, configHelper, managementController, stackAdvisorHelper, ambariConfigurationDAO, publisher, configuration));
-        bind(AmbariServerLDAPConfigurationHandler.class).toInstance(new AmbariServerLDAPConfigurationHandler(ldapFacade, ambariConfigurationDAO, publisher, configuration));
+        bind(AmbariServerLDAPConfigurationHandler.class).toInstance(new AmbariServerLDAPConfigurationHandler(clusters, configHelper, managementController,
+            stackAdvisorHelper, ambariConfigurationDAO, publisher, configuration, ldapFacade));
         bind(RootServiceComponentConfigurationHandlerFactory.class).toInstance(createMock(RootServiceComponentConfigurationHandlerFactory.class));
       }
     });