You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2017/11/30 17:04:26 UTC

[1/2] ambari git commit: AMBARI-22481. Make Ambari LDAP configuration API consistent with existing API (rlevas)

Repository: ambari
Updated Branches:
  refs/heads/trunk c3150a465 -> 4240f8496


http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfiguration.java
index 6c466ba..193a5c2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfiguration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfiguration.java
@@ -15,17 +15,15 @@
 
 package org.apache.ambari.server.ldap.domain;
 
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 
-import javax.inject.Inject;
-
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.inject.assistedinject.Assisted;
-
 /**
  * This class is an immutable representation of all the LDAP related configurationMap entries.
  */
@@ -35,142 +33,145 @@ public class AmbariLdapConfiguration {
 
   private final Map<String, String> configurationMap;
 
-  private Object configValue(AmbariLdapConfigKeys ambariLdapConfigKeys) {
+  private Object configValue(AmbariLdapConfigurationKeys ambariLdapConfigurationKeys) {
     Object value = null;
-    if (configurationMap.containsKey(ambariLdapConfigKeys.key())) {
-      value = configurationMap.get(ambariLdapConfigKeys.key());
+    if (configurationMap.containsKey(ambariLdapConfigurationKeys.key())) {
+      value = configurationMap.get(ambariLdapConfigurationKeys.key());
     } else {
-      LOGGER.warn("Ldap configuration property [{}] hasn't been set", ambariLdapConfigKeys.key());
+      LOGGER.warn("Ldap configuration property [{}] hasn't been set", ambariLdapConfigurationKeys.key());
     }
     return value;
   }
 
-  public void setValueFor(AmbariLdapConfigKeys ambariLdapConfigKeys, String value) {
-    configurationMap.put(ambariLdapConfigKeys.key(), value);
+  public void setValueFor(AmbariLdapConfigurationKeys ambariLdapConfigurationKeys, String value) {
+    configurationMap.put(ambariLdapConfigurationKeys.key(), value);
   }
 
-  // intentionally package private, instances to be created through the factory
-  @Inject
-  AmbariLdapConfiguration(@Assisted Map<String, String> configuration) {
+  public AmbariLdapConfiguration(Map<String, String> configuration) {
     this.configurationMap = configuration;
   }
 
   public boolean ldapEnabled() {
-    return Boolean.valueOf((String) configValue(AmbariLdapConfigKeys.LDAP_ENABLED));
+    return Boolean.valueOf((String) configValue(AmbariLdapConfigurationKeys.LDAP_ENABLED));
   }
 
   public String serverHost() {
-    return (String) configValue(AmbariLdapConfigKeys.SERVER_HOST);
+    return (String) configValue(AmbariLdapConfigurationKeys.SERVER_HOST);
   }
 
   public int serverPort() {
-    return Integer.valueOf((String) configValue(AmbariLdapConfigKeys.SERVER_PORT));
+    return Integer.valueOf((String) configValue(AmbariLdapConfigurationKeys.SERVER_PORT));
   }
 
   public boolean useSSL() {
-    return Boolean.valueOf((String) configValue(AmbariLdapConfigKeys.USE_SSL));
+    return Boolean.valueOf((String) configValue(AmbariLdapConfigurationKeys.USE_SSL));
   }
 
   public String trustStore() {
-    return (String) configValue(AmbariLdapConfigKeys.TRUST_STORE);
+    return (String) configValue(AmbariLdapConfigurationKeys.TRUST_STORE);
   }
 
   public String trustStoreType() {
-    return (String) configValue(AmbariLdapConfigKeys.TRUST_STORE_TYPE);
+    return (String) configValue(AmbariLdapConfigurationKeys.TRUST_STORE_TYPE);
   }
 
   public String trustStorePath() {
-    return (String) configValue(AmbariLdapConfigKeys.TRUST_STORE_PATH);
+    return (String) configValue(AmbariLdapConfigurationKeys.TRUST_STORE_PATH);
   }
 
   public String trustStorePassword() {
-    return (String) configValue(AmbariLdapConfigKeys.TRUST_STORE_PASSWORD);
+    return (String) configValue(AmbariLdapConfigurationKeys.TRUST_STORE_PASSWORD);
   }
 
   public boolean anonymousBind() {
-    return Boolean.valueOf((String) configValue(AmbariLdapConfigKeys.ANONYMOUS_BIND));
+    return Boolean.valueOf((String) configValue(AmbariLdapConfigurationKeys.ANONYMOUS_BIND));
   }
 
   public String bindDn() {
-    return (String) configValue(AmbariLdapConfigKeys.BIND_DN);
+    return (String) configValue(AmbariLdapConfigurationKeys.BIND_DN);
   }
 
   public String bindPassword() {
-    return (String) configValue(AmbariLdapConfigKeys.BIND_PASSWORD);
+    return (String) configValue(AmbariLdapConfigurationKeys.BIND_PASSWORD);
   }
 
   public String attributeDetection() {
-    return (String) configValue(AmbariLdapConfigKeys.ATTR_DETECTION);
+    return (String) configValue(AmbariLdapConfigurationKeys.ATTR_DETECTION);
   }
 
   public String dnAttribute() {
-    return (String) configValue(AmbariLdapConfigKeys.DN_ATTRIBUTE);
+    return (String) configValue(AmbariLdapConfigurationKeys.DN_ATTRIBUTE);
   }
 
   public String userObjectClass() {
-    return (String) configValue(AmbariLdapConfigKeys.USER_OBJECT_CLASS);
+    return (String) configValue(AmbariLdapConfigurationKeys.USER_OBJECT_CLASS);
   }
 
   public String userNameAttribute() {
-    return (String) configValue(AmbariLdapConfigKeys.USER_NAME_ATTRIBUTE);
+    return (String) configValue(AmbariLdapConfigurationKeys.USER_NAME_ATTRIBUTE);
   }
 
   public String userSearchBase() {
-    return (String) configValue(AmbariLdapConfigKeys.USER_SEARCH_BASE);
+    return (String) configValue(AmbariLdapConfigurationKeys.USER_SEARCH_BASE);
   }
 
   public String groupObjectClass() {
-    return (String) configValue(AmbariLdapConfigKeys.GROUP_OBJECT_CLASS);
+    return (String) configValue(AmbariLdapConfigurationKeys.GROUP_OBJECT_CLASS);
   }
 
   public String groupNameAttribute() {
-    return (String) configValue(AmbariLdapConfigKeys.GROUP_NAME_ATTRIBUTE);
+    return (String) configValue(AmbariLdapConfigurationKeys.GROUP_NAME_ATTRIBUTE);
   }
 
   public String groupMemberAttribute() {
-    return (String) configValue(AmbariLdapConfigKeys.GROUP_MEMBER_ATTRIBUTE);
+    return (String) configValue(AmbariLdapConfigurationKeys.GROUP_MEMBER_ATTRIBUTE);
   }
 
   public String groupSearchBase() {
-    return (String) configValue(AmbariLdapConfigKeys.GROUP_SEARCH_BASE);
+    return (String) configValue(AmbariLdapConfigurationKeys.GROUP_SEARCH_BASE);
   }
 
   public String userSearchFilter() {
-    return (String) configValue(AmbariLdapConfigKeys.USER_SEARCH_FILTER);
+    return (String) configValue(AmbariLdapConfigurationKeys.USER_SEARCH_FILTER);
   }
 
   public String userMemberReplacePattern() {
-    return (String) configValue(AmbariLdapConfigKeys.USER_MEMBER_REPLACE_PATTERN);
+    return (String) configValue(AmbariLdapConfigurationKeys.USER_MEMBER_REPLACE_PATTERN);
   }
 
   public String userMemberFilter() {
-    return (String) configValue(AmbariLdapConfigKeys.USER_MEMBER_FILTER);
+    return (String) configValue(AmbariLdapConfigurationKeys.USER_MEMBER_FILTER);
   }
 
   public String groupSearchFilter() {
-    return (String) configValue(AmbariLdapConfigKeys.GROUP_SEARCH_FILTER);
+    return (String) configValue(AmbariLdapConfigurationKeys.GROUP_SEARCH_FILTER);
   }
 
   public String groupMemberReplacePattern() {
-    return (String) configValue(AmbariLdapConfigKeys.GROUP_MEMBER_REPLACE_PATTERN);
+    return (String) configValue(AmbariLdapConfigurationKeys.GROUP_MEMBER_REPLACE_PATTERN);
   }
 
   public String groupMemberFilter() {
-    return (String) configValue(AmbariLdapConfigKeys.GROUP_MEMBER_FILTER);
+    return (String) configValue(AmbariLdapConfigurationKeys.GROUP_MEMBER_FILTER);
   }
 
   public boolean forceLowerCaseUserNames() {
-    return Boolean.valueOf((String) configValue(AmbariLdapConfigKeys.FORCE_LOWERCASE_USERNAMES));
+    return Boolean.valueOf((String) configValue(AmbariLdapConfigurationKeys.FORCE_LOWERCASE_USERNAMES));
   }
 
   public boolean paginationEnabled() {
-    return Boolean.valueOf((String) configValue(AmbariLdapConfigKeys.PAGINATION_ENABLED));
+    return Boolean.valueOf((String) configValue(AmbariLdapConfigurationKeys.PAGINATION_ENABLED));
   }
 
   public String referralHandling() {
-    return (String) configValue(AmbariLdapConfigKeys.REFERRAL_HANDLING);
+    return (String) configValue(AmbariLdapConfigurationKeys.REFERRAL_HANDLING);
   }
 
+  public Map<String, String> toMap() {
+    return (configurationMap == null)
+        ? Collections.emptyMap()
+        : new HashMap<>(configurationMap);
+  }
 
   @Override
   public String toString() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigurationFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigurationFactory.java
deleted file mode 100644
index aafd204..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigurationFactory.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed 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.ldap.domain;
-
-import java.util.Map;
-
-/**
- * Factory interface for AmbariLdapConfiguration instances.
- * It's registered as a factory in the GUICE context (so no implementations required)
- *
- * To be extended with other factory methods upon needs.
- */
-public interface AmbariLdapConfigurationFactory {
-
-  /**
-   * Creates an AmbariLdapConfiguration instance with the provided map of configuration settings.
-   *
-   * @param configuration a map where keys are the configuration properties and values are the configuration values
-   * @return an AmbariLdapConfiguration instance
-   */
-  AmbariLdapConfiguration createLdapConfiguration(Map<String, String> configuration);
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigurationKeys.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigurationKeys.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigurationKeys.java
new file mode 100644
index 0000000..2e1c36b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigurationKeys.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed 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.ldap.domain;
+
+/**
+ * Constants representing supported LDAP related property names
+ * // todo extend this with validation information, description, defaults maybe
+ */
+public enum AmbariLdapConfigurationKeys {
+
+  LDAP_ENABLED("ambari.ldap.authentication.enabled"),
+  SERVER_HOST("ambari.ldap.connectivity.server.host"),
+  SERVER_PORT("ambari.ldap.connectivity.server.port"),
+  USE_SSL("ambari.ldap.connectivity.use_ssl"),
+
+  TRUST_STORE("ambari.ldap.connectivity.trust_store"),
+  TRUST_STORE_TYPE("ambari.ldap.connectivity.trust_store.type"),
+  TRUST_STORE_PATH("ambari.ldap.connectivity.trust_store.path"),
+  TRUST_STORE_PASSWORD("ambari.ldap.connectivity.trust_store.password"),
+  ANONYMOUS_BIND("ambari.ldap.connectivity.anonymous_bind"),
+
+  BIND_DN("ambari.ldap.connectivity.bind_dn"),
+  BIND_PASSWORD("ambari.ldap.connectivity.bind_password"),
+
+  ATTR_DETECTION("ambari.ldap.attributes.detection"), // manual | auto
+
+  DN_ATTRIBUTE("ambari.ldap.attributes.dn_attr"),
+
+  USER_OBJECT_CLASS("ambari.ldap.attributes.user.object_class"),
+  USER_NAME_ATTRIBUTE("ambari.ldap.attributes.user.name_attr"),
+  USER_GROUP_MEMBER_ATTRIBUTE("ambari.ldap.attributes.user.group_member_attr"),
+  USER_SEARCH_BASE("ambari.ldap.attributes.user.search_base"),
+
+  GROUP_OBJECT_CLASS("ambari.ldap.attributes.group.object_class"),
+  GROUP_NAME_ATTRIBUTE("ambari.ldap.attributes.group.name_attr"),
+  GROUP_MEMBER_ATTRIBUTE("ambari.ldap.attributes.group.member_attr"),
+  GROUP_SEARCH_BASE("ambari.ldap.attributes.group.search_base"),
+
+  USER_SEARCH_FILTER("ambari.ldap.advanced.user_search_filter"),
+  USER_MEMBER_REPLACE_PATTERN("ambari.ldap.advanced.user_member_replace_pattern"),
+  USER_MEMBER_FILTER("ambari.ldap.advanced.user_member_filter"),
+
+  GROUP_SEARCH_FILTER("ambari.ldap.advanced.group_search_filter"),
+  GROUP_MEMBER_REPLACE_PATTERN("ambari.ldap.advanced.group_member_replace_pattern"),
+  GROUP_MEMBER_FILTER("ambari.ldap.advanced.group_member_filter"),
+
+  FORCE_LOWERCASE_USERNAMES("ambari.ldap.advanced.force_lowercase_usernames"),
+  REFERRAL_HANDLING("ambari.ldap.advanced.referrals"), // folow
+  PAGINATION_ENABLED("ambari.ldap.advanced.pagination_enabled"); // true | false
+
+  private String propertyName;
+
+  AmbariLdapConfigurationKeys(String propName) {
+    this.propertyName = propName;
+  }
+
+  public String key() {
+    return this.propertyName;
+  }
+
+  public static AmbariLdapConfigurationKeys fromKeyStr(String keyStr) {
+    for (AmbariLdapConfigurationKeys key : values()) {
+      if (key.key().equals(keyStr)) {
+        return key;
+      }
+    }
+
+    throw new IllegalStateException("invalid konfiguration key found!");
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
index ac9c1bc..f1e1881 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapConfigurationProvider.java
@@ -1,7 +1,11 @@
 /*
- * Licensed 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
+ * 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
  *
@@ -18,10 +22,10 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.ambari.server.controller.internal.AmbariServerConfigurationCategory;
 import org.apache.ambari.server.events.AmbariConfigurationChangedEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
 import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
 import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
 import org.apache.ambari.server.security.authorization.AmbariLdapAuthenticationProvider;
@@ -56,9 +60,6 @@ public class AmbariLdapConfigurationProvider implements Provider<AmbariLdapConfi
   private Provider<AmbariConfigurationDAO> ambariConfigurationDAOProvider;
 
   @Inject
-  private AmbariLdapConfigurationFactory ldapConfigurationFactory;
-
-  @Inject
   public AmbariLdapConfigurationProvider() {
   }
 
@@ -81,11 +82,11 @@ public class AmbariLdapConfigurationProvider implements Provider<AmbariLdapConfi
     List<AmbariConfigurationEntity> configEntities;
 
     LOGGER.info("Loading LDAP configuration ...");
-    configEntities = ambariConfigurationDAOProvider.get().findByCategory("ldap-configuration");
+    configEntities = ambariConfigurationDAOProvider.get().findByCategory(AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName());
 
     if (configEntities != null) {
       Map<String, String> properties = toProperties(configEntities);
-      instance = ldapConfigurationFactory.createLdapConfiguration(properties);
+      instance = new AmbariLdapConfiguration(properties);
     }
 
     LOGGER.info("Loaded LDAP configuration instance: [ {} ]", instance);

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
index 0118840..a9fd59b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/AmbariLdapFacade.java
@@ -114,9 +114,7 @@ public class AmbariLdapFacade implements LdapFacade {
 
     // todo handle the case where group membership is stored in the user rather than the group
     LOGGER.info("Testing LDAP group attributes with test user dn: {}", userDn);
-    Set<String> groups = ldapConfigurationService.checkGroupAttributes(userDn, ldapConfiguration);
-
-    return groups;
+    return ldapConfigurationService.checkGroupAttributes(userDn, ldapConfiguration);
   }
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
index ef84d1b..fc7ef98 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/LdapFacade.java
@@ -22,7 +22,7 @@ import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
 /**
  * The contract defining all the operations required by the application when communicating with an arbitrary LDAP server.
  * This interface is intended to decouple LDAP specific details from the application.
- *
+ * <p>
  * Any operation that requires interaction with an LDAP server from within Ambari should go through this interface.
  * (LDAP)
  */
@@ -39,11 +39,11 @@ public interface LdapFacade {
 
   /**
    * Runs the user and group attribute detection algorithms.
-   * The method is not intended to be used as a coniguration factory, the returned instance may not be suitable for use.
+   * The method is not intended to be used as a configuration factory, the returned instance may not be suitable for use.
    *
    * @param ambariLdapConfiguration partially filled configuration instance to be extended with detected properties
    * @return a configuration instance, with properties filled with potentially correct values
-   * @throws AmbariLdapException
+   * @throws AmbariLdapException if the attribute detection fails
    */
   AmbariLdapConfiguration detectAttributes(AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;
 
@@ -51,7 +51,8 @@ public interface LdapFacade {
    * Checks user and group related LDAP configuration attributes in the configuration object with the help of the provided parameters
    *
    * @param parameters              a map of property name and value pairs holding information to facilitate checking the attributes
-   * @param ambariLdapConfiguration configutration instance with available attributes
+   * @param ambariLdapConfiguration configuration instance with available attributes
+   * @return the set of groups assigned to the test user
    * @throws AmbariLdapException if the attribute checking fails
    */
   Set<String> checkLdapAttributes(Map<String, Object> parameters, AmbariLdapConfiguration ambariLdapConfiguration) throws AmbariLdapException;

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionService.java
index a9a9b53..23254c9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionService.java
@@ -20,8 +20,8 @@ import java.util.Map;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
 import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.ambari.server.ldap.service.AmbariLdapException;
 import org.apache.ambari.server.ldap.service.AttributeDetector;
 import org.apache.ambari.server.ldap.service.LdapAttributeDetectionService;
@@ -154,7 +154,7 @@ public class DefaultLdapAttributeDetectionService implements LdapAttributeDetect
 
     for (Map.Entry<String, String> detecteMapEntry : detectedAttributes.entrySet()) {
       LOG.info("Setting detected configuration value: [{}] - > [{}]", detecteMapEntry.getKey(), detecteMapEntry.getValue());
-      ambariLdapConfiguration.setValueFor(AmbariLdapConfigKeys.fromKeyStr(detecteMapEntry.getKey()), detecteMapEntry.getValue());
+      ambariLdapConfiguration.setValueFor(AmbariLdapConfigurationKeys.fromKeyStr(detecteMapEntry.getKey()), detecteMapEntry.getValue());
     }
 
   }
@@ -163,7 +163,7 @@ public class DefaultLdapAttributeDetectionService implements LdapAttributeDetect
     try {
 
       SearchRequest req = ldapConnectionTemplate.newSearchRequest(ambariLdapConfiguration.userSearchBase(),
-        FilterBuilder.present(ambariLdapConfiguration.dnAttribute()).toString(), SearchScope.SUBTREE);
+        FilterBuilder.present("objectClass").toString(), SearchScope.SUBTREE);
       req.setSizeLimit(SAMPLE_RESULT_SIZE);
 
       return req;
@@ -178,7 +178,7 @@ public class DefaultLdapAttributeDetectionService implements LdapAttributeDetect
     try {
 
       SearchRequest req = ldapConnectionTemplate.newSearchRequest(ambariLdapConfiguration.groupSearchBase(),
-        FilterBuilder.present(ambariLdapConfiguration.dnAttribute()).toString(), SearchScope.SUBTREE);
+        FilterBuilder.present("objectClass").toString(), SearchScope.SUBTREE);
       req.setSizeLimit(SAMPLE_RESULT_SIZE);
 
       return req;

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
index 3f6995c..cffb190 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationService.java
@@ -106,8 +106,8 @@ public class DefaultLdapConfigurationService implements LdapConfigurationService
       userDn = ldapConnectionTemplateFactory.create(ambariLdapConfiguration).searchFirst(new Dn(ambariLdapConfiguration.userSearchBase()), filter, SearchScope.SUBTREE, getUserDnNameEntryMapper(ambariLdapConfiguration));
 
       if (null == userDn) {
-        LOGGER.info("Could not find user based on the provided configuration. User attributes are not complete ");
-        throw new AmbariLdapException("User attribute configuration incomplete");
+        LOGGER.info("Could not find test user based on the provided configuration. User attributes may not be complete or the user may not exist.");
+        throw new AmbariLdapException("Could not find test user based on the provided configuration. User attributes may not be complete or the user may not exist.");
       }
       LOGGER.info("Attribute validation succeeded. Filter: [{}]", filter);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java
index 8c34ef8..191c8ee 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java
@@ -16,7 +16,7 @@ package org.apache.ambari.server.ldap.service.ads.detectors;
 
 import javax.inject.Inject;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.directory.api.ldap.model.entry.Entry;
 
 public class GroupMemberAttrDetector extends OccurrenceAndWeightBasedDetector {
@@ -60,6 +60,6 @@ public class GroupMemberAttrDetector extends OccurrenceAndWeightBasedDetector {
 
   @Override
   public String detectedProperty() {
-    return AmbariLdapConfigKeys.GROUP_MEMBER_ATTRIBUTE.key();
+    return AmbariLdapConfigurationKeys.GROUP_MEMBER_ATTRIBUTE.key();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupNameAttrDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupNameAttrDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupNameAttrDetector.java
index 0315ef2..4bd429a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupNameAttrDetector.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupNameAttrDetector.java
@@ -16,18 +16,17 @@ package org.apache.ambari.server.ldap.service.ads.detectors;
 
 import javax.inject.Inject;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class GroupNameAttrDetector extends OccurrenceAndWeightBasedDetector {
-  private static final Logger LOGGER = LoggerFactory.getLogger(UserNameAttrDetector.class);
+  private static final Logger LOGGER = LoggerFactory.getLogger(GroupNameAttrDetector.class);
 
   private enum GroupNameAttr {
 
     DISTINGUISHED_NAME("distinguishedName", 1),
-
     CN("cn", 1);
 
     private String attrName;
@@ -65,6 +64,6 @@ public class GroupNameAttrDetector extends OccurrenceAndWeightBasedDetector {
 
   @Override
   public String detectedProperty() {
-    return AmbariLdapConfigKeys.GROUP_NAME_ATTRIBUTE.key();
+    return AmbariLdapConfigurationKeys.GROUP_NAME_ATTRIBUTE.key();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupObjectClassDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupObjectClassDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupObjectClassDetector.java
index b681134..407c1b0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupObjectClassDetector.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupObjectClassDetector.java
@@ -16,7 +16,7 @@ package org.apache.ambari.server.ldap.service.ads.detectors;
 
 import javax.inject.Inject;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -26,13 +26,9 @@ public class GroupObjectClassDetector extends OccurrenceAndWeightBasedDetector {
   private static final Logger LOGGER = LoggerFactory.getLogger(GroupObjectClassDetector.class);
 
   private enum ObjectClassValue {
-
     GROUP("group", 1),
-
     GROUP_OF_NAMES("groupOfNames", 1),
-
     POSIX_GROUP("posixGroup", 1),
-
     GROUP_OF_UNIQUE_NAMES("groupOfUniqueNames", 1);
 
     private String ocVal;
@@ -68,6 +64,6 @@ public class GroupObjectClassDetector extends OccurrenceAndWeightBasedDetector {
 
   @Override
   public String detectedProperty() {
-    return AmbariLdapConfigKeys.GROUP_OBJECT_CLASS.key();
+    return AmbariLdapConfigurationKeys.GROUP_OBJECT_CLASS.key();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserGroupMemberAttrDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserGroupMemberAttrDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserGroupMemberAttrDetector.java
index b34a2b2..c785483 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserGroupMemberAttrDetector.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserGroupMemberAttrDetector.java
@@ -16,13 +16,12 @@ package org.apache.ambari.server.ldap.service.ads.detectors;
 
 import javax.inject.Inject;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.directory.api.ldap.model.entry.Entry;
 
 public class UserGroupMemberAttrDetector extends OccurrenceAndWeightBasedDetector {
 
   private enum UserGroupMemberAttr {
-
     MEMBER_OF("memberOf", 1),
     IS_MEMBER_OF("ismemberOf", 1);
 
@@ -59,6 +58,6 @@ public class UserGroupMemberAttrDetector extends OccurrenceAndWeightBasedDetecto
 
   @Override
   public String detectedProperty() {
-    return AmbariLdapConfigKeys.USER_GROUP_MEMBER_ATTRIBUTE.key();
+    return AmbariLdapConfigurationKeys.USER_GROUP_MEMBER_ATTRIBUTE.key();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserNameAttrDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserNameAttrDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserNameAttrDetector.java
index dec4459..aee0b3a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserNameAttrDetector.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserNameAttrDetector.java
@@ -17,7 +17,7 @@ package org.apache.ambari.server.ldap.service.ads.detectors;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -65,7 +65,7 @@ public class UserNameAttrDetector extends OccurrenceAndWeightBasedDetector {
 
   @Override
   public String detectedProperty() {
-    return AmbariLdapConfigKeys.USER_NAME_ATTRIBUTE.key();
+    return AmbariLdapConfigurationKeys.USER_NAME_ATTRIBUTE.key();
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java
index bf2f5b8..bb9fa1e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java
@@ -16,7 +16,7 @@ package org.apache.ambari.server.ldap.service.ads.detectors;
 
 import javax.inject.Inject;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -63,7 +63,7 @@ public class UserObjectClassDetector extends OccurrenceAndWeightBasedDetector {
 
   @Override
   public String detectedProperty() {
-    return AmbariLdapConfigKeys.USER_OBJECT_CLASS.key();
+    return AmbariLdapConfigurationKeys.USER_OBJECT_CLASS.key();
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
index 2afbf8a..99cd80e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
@@ -18,7 +18,6 @@
 
 package org.apache.ambari.server.api.services.stackadvisor.commands;
 
-import static org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommand.LDAP_CONFIGURATION_PROPERTY;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -56,6 +55,7 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequestExc
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommand.StackAdvisorData;
+import org.apache.ambari.server.controller.internal.AmbariServerConfigurationCategory;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.commons.io.FileUtils;
 import org.codehaus.jackson.JsonNode;
@@ -318,7 +318,7 @@ public class StackAdvisorCommandTest {
     command.populateLdapConfiguration((ObjectNode)servicesRootNode);
 
     JsonNode expectedLdapConfig = json(
-      map(LDAP_CONFIGURATION_PROPERTY, ldapConfigData)
+      map(AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName(), ldapConfigData)
     );
 
     assertEquals(expectedLdapConfig, servicesRootNode);

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProviderTest.java
----------------------------------------------------------------------
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 5016160..13c644a 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
@@ -35,6 +35,7 @@ import java.util.TreeMap;
 
 import javax.persistence.EntityManager;
 
+import org.apache.ambari.server.api.services.RootServiceComponentConfigurationService;
 import org.apache.ambari.server.controller.RootComponent;
 import org.apache.ambari.server.controller.RootService;
 import org.apache.ambari.server.controller.predicate.AndPredicate;
@@ -42,6 +43,7 @@ import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.utilities.PredicateBuilder;
 import org.apache.ambari.server.events.AmbariConfigurationChangedEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
@@ -60,6 +62,7 @@ import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 
+import edu.emory.mathcs.backport.java.util.Collections;
 import junit.framework.Assert;
 
 public class RootServiceComponentConfigurationResourceProviderTest extends EasyMockSupport {
@@ -74,30 +77,55 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
 
   @Test
   public void testCreateResources_Administrator() throws Exception {
-    testCreateResources(TestAuthenticationFactory.createAdministrator());
+    testCreateResources(TestAuthenticationFactory.createAdministrator(), null);
   }
 
   @Test(expected = AuthorizationException.class)
   public void testCreateResources_ClusterAdministrator() throws Exception {
-    testCreateResources(TestAuthenticationFactory.createClusterAdministrator());
+    testCreateResources(TestAuthenticationFactory.createClusterAdministrator(), null);
   }
 
   @Test(expected = AuthorizationException.class)
   public void testCreateResources_ClusterOperator() throws Exception {
-    testCreateResources(TestAuthenticationFactory.createClusterOperator());
+    testCreateResources(TestAuthenticationFactory.createClusterOperator(), null);
   }
 
   @Test(expected = AuthorizationException.class)
   public void testCreateResources_ServiceAdministrator() throws Exception {
-    testCreateResources(TestAuthenticationFactory.createServiceAdministrator());
+    testCreateResources(TestAuthenticationFactory.createServiceAdministrator(), null);
   }
 
   @Test(expected = AuthorizationException.class)
   public void testCreateResources_ServiceOperator() throws Exception {
-    testCreateResources(TestAuthenticationFactory.createServiceOperator());
+    testCreateResources(TestAuthenticationFactory.createServiceOperator(), null);
   }
 
-  private void testCreateResources(Authentication authentication) throws Exception {
+  @Test
+  public void testCreateResourcesWithDirective_Administrator() throws Exception {
+    testCreateResources(TestAuthenticationFactory.createAdministrator(), "test-directive");
+  }
+
+  @Test(expected = AuthorizationException.class)
+  public void testCreateResourcesWithDirective_ClusterAdministrator() throws Exception {
+    testCreateResources(TestAuthenticationFactory.createClusterAdministrator(), "test-directive");
+  }
+
+  @Test(expected = AuthorizationException.class)
+  public void testCreateResourcesWithDirective_ClusterOperator() throws Exception {
+    testCreateResources(TestAuthenticationFactory.createClusterOperator(), "test-directive");
+  }
+
+  @Test(expected = AuthorizationException.class)
+  public void testCreateResourcesWithDirective_ServiceAdministrator() throws Exception {
+    testCreateResources(TestAuthenticationFactory.createServiceAdministrator(), "test-directive");
+  }
+
+  @Test(expected = AuthorizationException.class)
+  public void testCreateResourcesWithDirective_ServiceOperator() throws Exception {
+    testCreateResources(TestAuthenticationFactory.createServiceOperator(), "test-directive");
+  }
+
+  private void testCreateResources(Authentication authentication, String opDirective) throws Exception {
     Injector injector = createInjector();
 
     ResourceProvider resourceProvider = injector.getInstance(RootServiceComponentConfigurationResourceProvider.class);
@@ -110,38 +138,79 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
     propertySets.add(toRequestProperties(CATEGORY_NAME_1, properties1));
 
     Map<String, String> properties2 = new HashMap<>();
-    properties2.put("property1b", "value1");
-    properties2.put("property2b", "value2");
-    propertySets.add(toRequestProperties(CATEGORY_NAME_2, properties2));
+    if (opDirective == null) {
+      properties2.put("property1b", "value1");
+      properties2.put("property2b", "value2");
+      propertySets.add(toRequestProperties(CATEGORY_NAME_2, properties2));
+    }
+
+    Map<String, String> requestInfoProperties;
+    if (opDirective == null) {
+      requestInfoProperties = Collections.emptyMap();
+    } else {
+      requestInfoProperties = Collections.singletonMap(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION, opDirective);
+    }
 
     Request request = createMock(Request.class);
     expect(request.getProperties()).andReturn(propertySets).once();
+    expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties).once();
 
     Capture<Map<String, String>> capturedProperties1 = newCapture();
     Capture<Map<String, String>> capturedProperties2 = newCapture();
 
-    AmbariConfigurationDAO dao = injector.getInstance(AmbariConfigurationDAO.class);
-    expect(dao.reconcileCategory(eq(CATEGORY_NAME_1), capture(capturedProperties1), eq(true)))
-        .andReturn(true)
-        .once();
-    expect(dao.reconcileCategory(eq(CATEGORY_NAME_2), capture(capturedProperties2), eq(true)))
-        .andReturn(true)
-        .once();
+    if (opDirective == null) {
+      AmbariConfigurationDAO dao = injector.getInstance(AmbariConfigurationDAO.class);
+      expect(dao.reconcileCategory(eq(CATEGORY_NAME_1), capture(capturedProperties1), eq(true)))
+          .andReturn(true)
+          .once();
+      expect(dao.reconcileCategory(eq(CATEGORY_NAME_2), capture(capturedProperties2), eq(true)))
+          .andReturn(true)
+          .once();
 
-    AmbariEventPublisher publisher = injector.getInstance(AmbariEventPublisher.class);
-    publisher.publish(anyObject(AmbariConfigurationChangedEvent.class));
-    expectLastCall().times(2);
+
+      AmbariEventPublisher publisher = injector.getInstance(AmbariEventPublisher.class);
+      publisher.publish(anyObject(AmbariConfigurationChangedEvent.class));
+      expectLastCall().times(2);
+    }
+
+    RootServiceComponentConfigurationHandlerFactory factory = injector.getInstance(RootServiceComponentConfigurationHandlerFactory.class);
+    expect(factory.getInstance(RootService.AMBARI.name(), RootComponent.AMBARI_SERVER.name(), CATEGORY_NAME_1))
+        .andReturn(new AmbariServerConfigurationHandler())
+        .once();
+    if (opDirective == null) {
+      expect(factory.getInstance(RootService.AMBARI.name(), RootComponent.AMBARI_SERVER.name(), CATEGORY_NAME_2))
+          .andReturn(new AmbariServerConfigurationHandler())
+          .once();
+    }
 
     replayAll();
 
     SecurityContextHolder.getContext().setAuthentication(authentication);
 
-    resourceProvider.createResources(request);
+    try {
+      resourceProvider.createResources(request);
+      if (opDirective != null) {
+        Assert.fail("Expected SystemException to be thrown");
+      }
+    } catch (AuthorizationException e) {
+      throw e;
+    } catch (SystemException e) {
+      if (opDirective == null) {
+        Assert.fail("Unexpected exception: " + e.getMessage());
+      } else {
+        Assert.assertEquals("The requested operation is not supported for this category: " + CATEGORY_NAME_1, e.getMessage());
+      }
+    }
 
     verifyAll();
 
-    validateCapturedProperties(properties1, capturedProperties1);
-    validateCapturedProperties(properties2, capturedProperties2);
+    if (opDirective == null) {
+      validateCapturedProperties(properties1, capturedProperties1);
+      validateCapturedProperties(properties2, capturedProperties2);
+    } else {
+      Assert.assertFalse(capturedProperties1.hasCaptured());
+      Assert.assertFalse(capturedProperties2.hasCaptured());
+    }
   }
 
   @Test
@@ -185,6 +254,11 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
     publisher.publish(anyObject(AmbariConfigurationChangedEvent.class));
     expectLastCall().once();
 
+    RootServiceComponentConfigurationHandlerFactory factory = injector.getInstance(RootServiceComponentConfigurationHandlerFactory.class);
+    expect(factory.getInstance(RootService.AMBARI.name(), RootComponent.AMBARI_SERVER.name(), CATEGORY_NAME_1))
+        .andReturn(new AmbariServerConfigurationHandler())
+        .once();
+
     replayAll();
 
     SecurityContextHolder.getContext().setAuthentication(authentication);
@@ -236,6 +310,11 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
     AmbariConfigurationDAO dao = injector.getInstance(AmbariConfigurationDAO.class);
     expect(dao.findByCategory(CATEGORY_NAME_1)).andReturn(createEntities(CATEGORY_NAME_1, properties)).once();
 
+    RootServiceComponentConfigurationHandlerFactory factory = injector.getInstance(RootServiceComponentConfigurationHandlerFactory.class);
+    expect(factory.getInstance(RootService.AMBARI.name(), RootComponent.AMBARI_SERVER.name(), CATEGORY_NAME_1))
+        .andReturn(new AmbariServerConfigurationHandler())
+        .once();
+
     replayAll();
 
     SecurityContextHolder.getContext().setAuthentication(authentication);
@@ -265,30 +344,55 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
 
   @Test
   public void testUpdateResources_Administrator() throws Exception {
-    testUpdateResources(TestAuthenticationFactory.createAdministrator());
+    testUpdateResources(TestAuthenticationFactory.createAdministrator(), null);
   }
 
   @Test(expected = AuthorizationException.class)
   public void testUpdateResources_ClusterAdministrator() throws Exception {
-    testUpdateResources(TestAuthenticationFactory.createClusterAdministrator());
+    testUpdateResources(TestAuthenticationFactory.createClusterAdministrator(), null);
   }
 
   @Test(expected = AuthorizationException.class)
   public void testUpdateResources_ClusterOperator() throws Exception {
-    testUpdateResources(TestAuthenticationFactory.createClusterOperator());
+    testUpdateResources(TestAuthenticationFactory.createClusterOperator(), null);
   }
 
   @Test(expected = AuthorizationException.class)
   public void testUpdateResources_ServiceAdministrator() throws Exception {
-    testUpdateResources(TestAuthenticationFactory.createServiceAdministrator());
+    testUpdateResources(TestAuthenticationFactory.createServiceAdministrator(), null);
   }
 
   @Test(expected = AuthorizationException.class)
   public void testUpdateResources_ServiceOperator() throws Exception {
-    testUpdateResources(TestAuthenticationFactory.createServiceOperator());
+    testUpdateResources(TestAuthenticationFactory.createServiceOperator(), null);
+  }
+
+  @Test
+  public void testUpdateResourcesWithDirective_Administrator() throws Exception {
+    testUpdateResources(TestAuthenticationFactory.createAdministrator(), "test-directive");
+  }
+
+  @Test(expected = AuthorizationException.class)
+  public void testUpdateResourcesWithDirective_ClusterAdministrator() throws Exception {
+    testUpdateResources(TestAuthenticationFactory.createClusterAdministrator(), "test-directive");
   }
 
-  private void testUpdateResources(Authentication authentication) throws Exception {
+  @Test(expected = AuthorizationException.class)
+  public void testUpdateResourcesWithDirective_ClusterOperator() throws Exception {
+    testUpdateResources(TestAuthenticationFactory.createClusterOperator(), "test-directive");
+  }
+
+  @Test(expected = AuthorizationException.class)
+  public void testUpdateResourcesWithDirective_ServiceAdministrator() throws Exception {
+    testUpdateResources(TestAuthenticationFactory.createServiceAdministrator(), "test-directive");
+  }
+
+  @Test(expected = AuthorizationException.class)
+  public void testUpdateResourcesWithDirective_ServiceOperator() throws Exception {
+    testUpdateResources(TestAuthenticationFactory.createServiceOperator(), "test-directive");
+  }
+
+  private void testUpdateResources(Authentication authentication, String opDirective) throws Exception {
     Injector injector = createInjector();
 
     ResourceProvider resourceProvider = injector.getInstance(RootServiceComponentConfigurationResourceProvider.class);
@@ -302,29 +406,62 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
     properties1.put("property2a", "value2");
     propertySets.add(toRequestProperties(CATEGORY_NAME_1, properties1));
 
+    Map<String, String> requestInfoProperties;
+    if (opDirective == null) {
+      requestInfoProperties = Collections.emptyMap();
+    } else {
+      requestInfoProperties = Collections.singletonMap(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION, opDirective);
+    }
+
     Request request = createMock(Request.class);
     expect(request.getProperties()).andReturn(propertySets).once();
+    expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties).once();
 
     Capture<Map<String, String>> capturedProperties1 = newCapture();
 
-    AmbariConfigurationDAO dao = injector.getInstance(AmbariConfigurationDAO.class);
-    expect(dao.reconcileCategory(eq(CATEGORY_NAME_1), capture(capturedProperties1), eq(false)))
-        .andReturn(true)
-        .once();
+    if (opDirective == null) {
+      AmbariConfigurationDAO dao = injector.getInstance(AmbariConfigurationDAO.class);
+      expect(dao.reconcileCategory(eq(CATEGORY_NAME_1), capture(capturedProperties1), eq(false)))
+          .andReturn(true)
+          .once();
 
-    AmbariEventPublisher publisher = injector.getInstance(AmbariEventPublisher.class);
-    publisher.publish(anyObject(AmbariConfigurationChangedEvent.class));
-    expectLastCall().times(1);
+      AmbariEventPublisher publisher = injector.getInstance(AmbariEventPublisher.class);
+      publisher.publish(anyObject(AmbariConfigurationChangedEvent.class));
+      expectLastCall().times(1);
+    }
+
+    RootServiceComponentConfigurationHandlerFactory factory = injector.getInstance(RootServiceComponentConfigurationHandlerFactory.class);
+    expect(factory.getInstance(RootService.AMBARI.name(), RootComponent.AMBARI_SERVER.name(), CATEGORY_NAME_1))
+        .andReturn(new AmbariServerConfigurationHandler())
+        .once();
 
     replayAll();
 
     SecurityContextHolder.getContext().setAuthentication(authentication);
 
-    resourceProvider.updateResources(request, predicate);
+    try {
+      resourceProvider.updateResources(request, predicate);
+
+      if (opDirective != null) {
+        Assert.fail("Expected SystemException to be thrown");
+      }
+    } catch (AuthorizationException e) {
+      throw e;
+    } catch (SystemException e) {
+      if (opDirective == null) {
+        Assert.fail("Unexpected exception: " + e.getMessage());
+      } else {
+        Assert.assertEquals("The requested operation is not supported for this category: " + CATEGORY_NAME_1, e.getMessage());
+      }
+    }
 
     verifyAll();
 
-    validateCapturedProperties(properties1, capturedProperties1);
+    if (opDirective == null) {
+      validateCapturedProperties(properties1, capturedProperties1);
+    } else {
+      Assert.assertFalse(capturedProperties1.hasCaptured());
+    }
   }
 
   private Predicate createPredicate(String serviceName, String componentName, String categoryName) {
@@ -387,6 +524,9 @@ public class RootServiceComponentConfigurationResourceProviderTest extends EasyM
         bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
         bind(AmbariConfigurationDAO.class).toInstance(createMock(AmbariConfigurationDAO.class));
         bind(AmbariEventPublisher.class).toInstance(createMock(AmbariEventPublisher.class));
+        bind(RootServiceComponentConfigurationHandlerFactory.class).toInstance(createMock(RootServiceComponentConfigurationHandlerFactory.class));
+
+        binder().requestStaticInjection(AmbariServerConfigurationHandler.class);
       }
     });
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java
index 3917cdf..75c9ea3 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java
@@ -14,14 +14,18 @@
 
 package org.apache.ambari.server.ldap;
 
+import static org.easymock.EasyMock.createNiceMock;
+
 import java.util.Map;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
+import javax.persistence.EntityManager;
+
 import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
-import org.apache.ambari.server.ldap.domain.TestAmbariLdapConfigurationFactory;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.ambari.server.ldap.service.ads.LdapConnectionTemplateFactory;
 import org.apache.ambari.server.ldap.service.ads.detectors.AttributeDetectorFactory;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.state.stack.OsFamily;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.ldap.client.api.LdapConnection;
@@ -67,7 +71,9 @@ public class LdapModuleFunctionalTest {
       @Override
       protected void configure() {
         // override the configuration instance binding not to access the database
-        bind(AmbariLdapConfiguration.class).toInstance(new TestAmbariLdapConfigurationFactory().createLdapConfiguration(getADProps()));
+        bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
+        bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
+        bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
       }
     });
 
@@ -82,8 +88,7 @@ public class LdapModuleFunctionalTest {
 
     // WHEN
     LdapConnectionTemplateFactory ldapConnectionTemplateFactory = injector.getInstance(LdapConnectionTemplateFactory.class);
-    AmbariLdapConfigurationFactory ambariLdapConfigurationFactory = injector.getInstance(AmbariLdapConfigurationFactory.class);
-    AmbariLdapConfiguration ldapConfiguration = ambariLdapConfigurationFactory.createLdapConfiguration(getADProps());
+    AmbariLdapConfiguration ldapConfiguration = new AmbariLdapConfiguration(getProps());
     LdapConnectionTemplate template = ldapConnectionTemplateFactory.create(ldapConfiguration);
 
     // THEN
@@ -103,36 +108,28 @@ public class LdapModuleFunctionalTest {
   }
 
 
-  private static Map<String, Object> getProps() {
-    Map<String, Object> ldapPropsMap = Maps.newHashMap();
+  private static Map<String, String> getProps() {
+    Map<String, String> ldapPropsMap = Maps.newHashMap();
 
-    ldapPropsMap.put(AmbariLdapConfigKeys.ANONYMOUS_BIND.key(), "true");
-    ldapPropsMap.put(AmbariLdapConfigKeys.SERVER_HOST.key(), "ldap.forumsys.com");
-    ldapPropsMap.put(AmbariLdapConfigKeys.SERVER_PORT.key(), "389");
-    ldapPropsMap.put(AmbariLdapConfigKeys.BIND_DN.key(), "cn=read-only-admin,dc=example,dc=com");
-    ldapPropsMap.put(AmbariLdapConfigKeys.BIND_PASSWORD.key(), "password");
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.ANONYMOUS_BIND.key(), "true");
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.SERVER_HOST.key(), "ldap.forumsys.com");
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.SERVER_PORT.key(), "389");
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.BIND_DN.key(), "cn=read-only-admin,dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.BIND_PASSWORD.key(), "password");
 //    ldapPropsMap.put(AmbariLdapConfigKeys.USE_SSL.key(), "true");
 
-    ldapPropsMap.put(AmbariLdapConfigKeys.USER_OBJECT_CLASS.key(), SchemaConstants.PERSON_OC);
-    ldapPropsMap.put(AmbariLdapConfigKeys.USER_NAME_ATTRIBUTE.key(), SchemaConstants.UID_AT);
-    ldapPropsMap.put(AmbariLdapConfigKeys.USER_SEARCH_BASE.key(), "dc=example,dc=com");
-    ldapPropsMap.put(AmbariLdapConfigKeys.DN_ATTRIBUTE.key(), SchemaConstants.UID_AT);
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.USER_OBJECT_CLASS.key(), SchemaConstants.PERSON_OC);
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.USER_NAME_ATTRIBUTE.key(), SchemaConstants.UID_AT);
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.USER_SEARCH_BASE.key(), "dc=example,dc=com");
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.DN_ATTRIBUTE.key(), SchemaConstants.UID_AT);
 //    ldapPropsMap.put(AmbariLdapConfigKeys.TRUST_STORE.key(), "custom");
-    ldapPropsMap.put(AmbariLdapConfigKeys.TRUST_STORE_TYPE.key(), "JKS");
+    ldapPropsMap.put(AmbariLdapConfigurationKeys.TRUST_STORE_TYPE.key(), "JKS");
 //    ldapPropsMap.put(AmbariLdapConfigKeys.TRUST_STORE_PATH.key(), "/Users/lpuskas/my_truststore/KeyStore.jks");
 
 
     return ldapPropsMap;
   }
 
-  private static Map<String, String> getADProps() {
-    Map<String, String> ldapPropsMap = Maps.newHashMap();
-
-
-
-    return ldapPropsMap;
-  }
-
   @Test
   public void testShouldDetectorsBeBound() throws Exception {
     // GIVEN

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/test/java/org/apache/ambari/server/ldap/domain/TestAmbariLdapConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/domain/TestAmbariLdapConfigurationFactory.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/domain/TestAmbariLdapConfigurationFactory.java
deleted file mode 100644
index 1082250..0000000
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/domain/TestAmbariLdapConfigurationFactory.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed 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.ldap.domain;
-
-
-import java.util.Map;
-
-/**
- * Implementation used for testing purposes only!
- */
-public class TestAmbariLdapConfigurationFactory implements AmbariLdapConfigurationFactory {
-
-  @Override
-  public AmbariLdapConfiguration createLdapConfiguration(Map<String, String> configuration) {
-    return new AmbariLdapConfiguration(configuration);
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/AmbariLdapFacadeTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/AmbariLdapFacadeTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/AmbariLdapFacadeTest.java
index 97ce30e..59622b5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/AmbariLdapFacadeTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/AmbariLdapFacadeTest.java
@@ -17,10 +17,8 @@ package org.apache.ambari.server.ldap.service;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
 import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
-import org.apache.ambari.server.ldap.domain.TestAmbariLdapConfigurationFactory;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.easymock.EasyMockRule;
@@ -50,9 +48,6 @@ public class AmbariLdapFacadeTest extends EasyMockSupport {
   @Mock(type = MockType.STRICT)
   public LdapAttributeDetectionService ldapAttributeDetectionServiceMock;
 
-  private AmbariLdapConfigurationFactory ambariLdapConfigurationFactory;
-
-
   @TestSubject
   private LdapFacade ldapFacade = new AmbariLdapFacade();
 
@@ -63,8 +58,7 @@ public class AmbariLdapFacadeTest extends EasyMockSupport {
 
   @Before
   public void before() {
-    ambariLdapConfigurationFactory = new TestAmbariLdapConfigurationFactory();
-    ambariLdapConfiguration = ambariLdapConfigurationFactory.createLdapConfiguration(Maps.newHashMap());
+    ambariLdapConfiguration = new AmbariLdapConfiguration(Maps.newHashMap());
     ambariLdapConfigurationCapture = Capture.newInstance();
 
 
@@ -90,7 +84,7 @@ public class AmbariLdapFacadeTest extends EasyMockSupport {
     // THEN
     // the captured configuration instance is the same the facade method got called with
     Assert.assertEquals("The configuration instance souldn't change before passing it to the service",
-      ambariLdapConfiguration, ambariLdapConfigurationCapture.getValue());
+        ambariLdapConfiguration, ambariLdapConfigurationCapture.getValue());
   }
 
   @Test(expected = AmbariLdapException.class)
@@ -122,10 +116,10 @@ public class AmbariLdapFacadeTest extends EasyMockSupport {
     Capture<String> userDnCapture = Capture.newInstance();
 
     EasyMock.expect(ldapConfigurationServiceMock.checkUserAttributes(EasyMock.capture(testUserCapture), EasyMock.capture(testPasswordCapture),
-      EasyMock.capture(ambariLdapConfigurationCapture))).andReturn("userDn");
+        EasyMock.capture(ambariLdapConfigurationCapture))).andReturn("userDn");
 
     EasyMock.expect(ldapConfigurationServiceMock.checkGroupAttributes(EasyMock.capture(userDnCapture),
-      EasyMock.capture(ambariLdapConfigurationCapture))).andReturn(Sets.newHashSet("userGroup"));
+        EasyMock.capture(ambariLdapConfigurationCapture))).andReturn(Sets.newHashSet("userGroup"));
 
     replayAll();
 
@@ -149,7 +143,7 @@ public class AmbariLdapFacadeTest extends EasyMockSupport {
     parameters.put(AmbariLdapFacade.Parameters.TEST_USER_PASSWORD.getParameterKey(), "testPassword");
 
     EasyMock.expect(ldapConfigurationServiceMock.checkUserAttributes(EasyMock.anyString(), EasyMock.anyString(),
-      EasyMock.anyObject(AmbariLdapConfiguration.class))).andThrow(new AmbariLdapException("Testing ..."));
+        EasyMock.anyObject(AmbariLdapConfiguration.class))).andThrow(new AmbariLdapException("Testing ..."));
 
     replayAll();
 
@@ -164,23 +158,23 @@ public class AmbariLdapFacadeTest extends EasyMockSupport {
 
     // configuration map with user attributes detected
     Map<String, String> userConfigMap = Maps.newHashMap();
-    userConfigMap.put(AmbariLdapConfigKeys.USER_NAME_ATTRIBUTE.key(), "uid");
-    AmbariLdapConfiguration userAttrDecoratedConfig = ambariLdapConfigurationFactory.createLdapConfiguration(userConfigMap);
+    userConfigMap.put(AmbariLdapConfigurationKeys.USER_NAME_ATTRIBUTE.key(), "uid");
+    AmbariLdapConfiguration userAttrDecoratedConfig = new AmbariLdapConfiguration(userConfigMap);
 
     // configuration map with user+group attributes detected
     Map<String, String> groupConfigMap = Maps.newHashMap(userConfigMap);
-    groupConfigMap.put(AmbariLdapConfigKeys.GROUP_NAME_ATTRIBUTE.key(), "dn");
-    AmbariLdapConfiguration groupAttrDecoratedConfig = ambariLdapConfigurationFactory.createLdapConfiguration(groupConfigMap);
+    groupConfigMap.put(AmbariLdapConfigurationKeys.GROUP_NAME_ATTRIBUTE.key(), "dn");
+    AmbariLdapConfiguration groupAttrDecoratedConfig = new AmbariLdapConfiguration(groupConfigMap);
 
     Capture<AmbariLdapConfiguration> userAttrDetectionConfigCapture = Capture.newInstance();
     Capture<AmbariLdapConfiguration> groupAttrDetectionConfigCapture = Capture.newInstance();
 
     // GIVEN
     EasyMock.expect(ldapAttributeDetectionServiceMock.detectLdapUserAttributes(EasyMock.capture(userAttrDetectionConfigCapture)))
-      .andReturn(userAttrDecoratedConfig);
+        .andReturn(userAttrDecoratedConfig);
 
     EasyMock.expect(ldapAttributeDetectionServiceMock.detectLdapGroupAttributes(EasyMock.capture(groupAttrDetectionConfigCapture)))
-      .andReturn(groupAttrDecoratedConfig);
+        .andReturn(groupAttrDecoratedConfig);
 
     replayAll();
 
@@ -189,10 +183,10 @@ public class AmbariLdapFacadeTest extends EasyMockSupport {
 
     // THEN
     Assert.assertEquals("User attribute detection called with the wrong configuration", ambariLdapConfiguration,
-      userAttrDetectionConfigCapture.getValue());
+        userAttrDetectionConfigCapture.getValue());
 
     Assert.assertEquals("Group attribute detection called with the wrong configuration", userAttrDecoratedConfig,
-      groupAttrDetectionConfigCapture.getValue());
+        groupAttrDetectionConfigCapture.getValue());
 
     Assert.assertEquals("Attribute detection returned an invalid configuration", groupAttrDecoratedConfig, detected);
 
@@ -202,7 +196,7 @@ public class AmbariLdapFacadeTest extends EasyMockSupport {
   public void testShouldAttributeDetectionFailuresResultInAmbariLdapException() throws Exception {
     // GIVEN
     EasyMock.expect(ldapAttributeDetectionServiceMock.detectLdapUserAttributes(EasyMock.anyObject(AmbariLdapConfiguration.class)))
-      .andThrow(new AmbariLdapException("Testing ..."));
+        .andThrow(new AmbariLdapException("Testing ..."));
 
     replayAll();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionServiceTest.java
index a44bf7c..e23421e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapAttributeDetectionServiceTest.java
@@ -17,10 +17,8 @@ package org.apache.ambari.server.ldap.service.ads;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
 import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
-import org.apache.ambari.server.ldap.domain.TestAmbariLdapConfigurationFactory;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.ambari.server.ldap.service.AmbariLdapException;
 import org.apache.ambari.server.ldap.service.ads.detectors.AttributeDetectorFactory;
 import org.apache.ambari.server.ldap.service.ads.detectors.ChainedAttributeDetector;
@@ -63,9 +61,6 @@ public class DefaultLdapAttributeDetectionServiceTest extends EasyMockSupport {
   @Mock
   private SearchRequest searchRequestMock;
 
-
-  private AmbariLdapConfigurationFactory ldapConfigurationFactory = new TestAmbariLdapConfigurationFactory();
-
   @TestSubject
   private DefaultLdapAttributeDetectionService defaultLdapAttributeDetectionService = new DefaultLdapAttributeDetectionService();
 
@@ -79,8 +74,8 @@ public class DefaultLdapAttributeDetectionServiceTest extends EasyMockSupport {
   public void shouldLdapUserAttributeDetection() throws Exception {
     // GIVEN
     Map<String, String> configMap = Maps.newHashMap();
-    configMap.put(AmbariLdapConfigKeys.USER_SEARCH_BASE.key(), "dc=example,dc=com");
-    AmbariLdapConfiguration ldapConfiguration = ldapConfigurationFactory.createLdapConfiguration(configMap);
+    configMap.put(AmbariLdapConfigurationKeys.USER_SEARCH_BASE.key(), "dc=example,dc=com");
+    AmbariLdapConfiguration ldapConfiguration = new AmbariLdapConfiguration(configMap);
 
     List<Object> entryList = Lists.newArrayList(new DefaultEntry("uid=gauss"));
 
@@ -110,8 +105,8 @@ public class DefaultLdapAttributeDetectionServiceTest extends EasyMockSupport {
   public void testShouldUserAttributeDetectionFailWhenLdapOerationFails() throws Exception {
     // GIVEN
     Map<String, String> configMap = Maps.newHashMap();
-    configMap.put(AmbariLdapConfigKeys.USER_SEARCH_BASE.key(), "dc=example,dc=com");
-    AmbariLdapConfiguration ldapConfiguration = ldapConfigurationFactory.createLdapConfiguration(configMap);
+    configMap.put(AmbariLdapConfigurationKeys.USER_SEARCH_BASE.key(), "dc=example,dc=com");
+    AmbariLdapConfiguration ldapConfiguration = new AmbariLdapConfiguration(configMap);
 
     EasyMock.expect(ldapConnectionTemplateFactoryMock.create(ldapConfiguration)).andThrow(new AmbariLdapException("Testing ..."));
 
@@ -130,8 +125,8 @@ public class DefaultLdapAttributeDetectionServiceTest extends EasyMockSupport {
   public void shouldLdapGroupAttributeDetection() throws Exception {
     // GIVEN
     Map<String, String> configMap = Maps.newHashMap();
-    configMap.put(AmbariLdapConfigKeys.GROUP_SEARCH_BASE.key(), "dc=example,dc=com");
-    AmbariLdapConfiguration ldapConfiguration = ldapConfigurationFactory.createLdapConfiguration(configMap);
+    configMap.put(AmbariLdapConfigurationKeys.GROUP_SEARCH_BASE.key(), "dc=example,dc=com");
+    AmbariLdapConfiguration ldapConfiguration = new AmbariLdapConfiguration(configMap);
 
     List<Object> entryList = Lists.newArrayList(new DefaultEntry("uid=gauss"));
 
@@ -161,8 +156,8 @@ public class DefaultLdapAttributeDetectionServiceTest extends EasyMockSupport {
   public void testShouldGroupAttributeDetectionFailWhenLdapOerationFails() throws Exception {
     // GIVEN
     Map<String, String> configMap = Maps.newHashMap();
-    configMap.put(AmbariLdapConfigKeys.GROUP_SEARCH_BASE.key(), "dc=example,dc=com");
-    AmbariLdapConfiguration ldapConfiguration = ldapConfigurationFactory.createLdapConfiguration(configMap);
+    configMap.put(AmbariLdapConfigurationKeys.GROUP_SEARCH_BASE.key(), "dc=example,dc=com");
+    AmbariLdapConfiguration ldapConfiguration = new AmbariLdapConfiguration(configMap);
 
     EasyMock.expect(ldapConnectionTemplateFactoryMock.create(ldapConfiguration)).andThrow(new AmbariLdapException("Testing ..."));
 
@@ -175,7 +170,6 @@ public class DefaultLdapAttributeDetectionServiceTest extends EasyMockSupport {
 
   }
 
-
   private EntryMapper<Entry> entryMapperMock() {
     return new EntryMapper<Entry>() {
       @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
index ec78e56..998844c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/DefaultLdapConfigurationServiceTest.java
@@ -17,9 +17,8 @@ package org.apache.ambari.server.ldap.service.ads;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys;
 import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.domain.TestAmbariLdapConfigurationFactory;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationKeys;
 import org.apache.ambari.server.ldap.service.AmbariLdapException;
 import org.apache.ambari.server.ldap.service.LdapConfigurationService;
 import org.apache.directory.api.ldap.model.message.SearchRequest;
@@ -65,7 +64,7 @@ public class DefaultLdapConfigurationServiceTest extends EasyMockSupport {
   @Test
   public void testShouldConnectionCheckSucceedWhenConnectionCallbackSucceeds() throws Exception {
     // GIVEN
-    AmbariLdapConfiguration ambariLdapConfiguration = new TestAmbariLdapConfigurationFactory().createLdapConfiguration(Maps.newHashMap());
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(Maps.newHashMap());
 
     // the cllback returns TRUE
     EasyMock.expect(ldapConnectionTemplateMock.execute(EasyMock.anyObject(ConnectionCallback.class))).andReturn(Boolean.TRUE);
@@ -84,7 +83,7 @@ public class DefaultLdapConfigurationServiceTest extends EasyMockSupport {
   public void testShouldConnectionCheckFailWhenConnectionCallbackFails() throws Exception {
 
     // GIVEN
-    AmbariLdapConfiguration ambariLdapConfiguration = new TestAmbariLdapConfigurationFactory().createLdapConfiguration(Maps.newHashMap());
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(Maps.newHashMap());
 
     // the callback returns FALSE
     EasyMock.expect(ldapConnectionTemplateMock.execute(EasyMock.anyObject(ConnectionCallback.class))).andReturn(Boolean.FALSE);
@@ -103,10 +102,10 @@ public class DefaultLdapConfigurationServiceTest extends EasyMockSupport {
   public void testShouldUserAttributeConfigurationCheckSucceedWhenUserDnIsFound() throws Exception {
     // GIVEN
     Map<String, String> configMap = Maps.newHashMap();
-    configMap.put(AmbariLdapConfigKeys.USER_OBJECT_CLASS.key(), "person");
-    configMap.put(AmbariLdapConfigKeys.USER_NAME_ATTRIBUTE.key(), "uid");
+    configMap.put(AmbariLdapConfigurationKeys.USER_OBJECT_CLASS.key(), "person");
+    configMap.put(AmbariLdapConfigurationKeys.USER_NAME_ATTRIBUTE.key(), "uid");
 
-    AmbariLdapConfiguration ambariLdapConfiguration = new TestAmbariLdapConfigurationFactory().createLdapConfiguration(configMap);
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(configMap);
 
     // the callback returns FALSE
     EasyMock.expect(ldapConnectionTemplateFactory.create(ambariLdapConfiguration)).andReturn(ldapConnectionTemplateMock);
@@ -127,10 +126,10 @@ public class DefaultLdapConfigurationServiceTest extends EasyMockSupport {
   public void testShouldUserAttributeConfigurationCheckFailWhenNoUsersFound() throws Exception {
     // GIVEN
     Map<String, String> configMap = Maps.newHashMap();
-    configMap.put(AmbariLdapConfigKeys.USER_OBJECT_CLASS.key(), "posixAccount");
-    configMap.put(AmbariLdapConfigKeys.USER_NAME_ATTRIBUTE.key(), "dn");
+    configMap.put(AmbariLdapConfigurationKeys.USER_OBJECT_CLASS.key(), "posixAccount");
+    configMap.put(AmbariLdapConfigurationKeys.USER_NAME_ATTRIBUTE.key(), "dn");
 
-    AmbariLdapConfiguration ambariLdapConfiguration = new TestAmbariLdapConfigurationFactory().createLdapConfiguration(configMap);
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(configMap);
 
     // the callback returns FALSE
     EasyMock.expect(ldapConnectionTemplateFactory.create(ambariLdapConfiguration)).andReturn(ldapConnectionTemplateMock);
@@ -159,7 +158,7 @@ public class DefaultLdapConfigurationServiceTest extends EasyMockSupport {
 
     SearchRequest sr = new SearchRequestImpl();
 
-    AmbariLdapConfiguration ambariLdapConfiguration = new TestAmbariLdapConfigurationFactory().createLdapConfiguration(configMap);
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(configMap);
 
     // the callback returns FALSE
     EasyMock.expect(ldapConnectionTemplateFactory.create(ambariLdapConfiguration)).andReturn(ldapConnectionTemplateMock);
@@ -188,7 +187,7 @@ public class DefaultLdapConfigurationServiceTest extends EasyMockSupport {
 
     SearchRequest sr = new SearchRequestImpl();
 
-    AmbariLdapConfiguration ambariLdapConfiguration = new TestAmbariLdapConfigurationFactory().createLdapConfiguration(configMap);
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(configMap);
 
     // the callback returns FALSE
     EasyMock.expect(ldapConnectionTemplateFactory.create(ambariLdapConfiguration)).andReturn(ldapConnectionTemplateMock);
@@ -210,10 +209,10 @@ public class DefaultLdapConfigurationServiceTest extends EasyMockSupport {
 
   private Map<String, String> groupConfigObjectMap() {
     Map<String, String> configMap = Maps.newHashMap();
-    configMap.put(AmbariLdapConfigKeys.GROUP_OBJECT_CLASS.key(), "groupOfNames");
-    configMap.put(AmbariLdapConfigKeys.GROUP_SEARCH_BASE.key(), "dc=example,dc=com");
-    configMap.put(AmbariLdapConfigKeys.GROUP_NAME_ATTRIBUTE.key(), "uid");
-    configMap.put(AmbariLdapConfigKeys.GROUP_MEMBER_ATTRIBUTE.key(), "member");
+    configMap.put(AmbariLdapConfigurationKeys.GROUP_OBJECT_CLASS.key(), "groupOfNames");
+    configMap.put(AmbariLdapConfigurationKeys.GROUP_SEARCH_BASE.key(), "dc=example,dc=com");
+    configMap.put(AmbariLdapConfigurationKeys.GROUP_NAME_ATTRIBUTE.key(), "uid");
+    configMap.put(AmbariLdapConfigurationKeys.GROUP_MEMBER_ATTRIBUTE.key(), "member");
     return configMap;
   }
 


[2/2] ambari git commit: AMBARI-22481. Make Ambari LDAP configuration API consistent with existing API (rlevas)

Posted by rl...@apache.org.
AMBARI-22481. Make Ambari LDAP configuration API consistent with existing API (rlevas)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4240f849
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4240f849
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4240f849

Branch: refs/heads/trunk
Commit: 4240f8496175bf9fb369b9411e71ad1127e356ad
Parents: c3150a4
Author: Robert Levas <rl...@hortonworks.com>
Authored: Thu Nov 30 12:04:12 2017 -0500
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Thu Nov 30 12:04:12 2017 -0500

----------------------------------------------------------------------
 .../server/api/handlers/CreateHandler.java      |   8 +-
 .../server/api/handlers/UpdateHandler.java      |   8 +-
 .../resources/ResourceInstanceFactoryImpl.java  |   4 +-
 ...ootServiceComponentConfigurationService.java |  15 ++
 .../api/services/ldap/AmbariConfiguration.java  |  46 ----
 .../api/services/ldap/LdapConfigOperation.java  |  43 ----
 .../services/ldap/LdapConfigurationRequest.java |  49 ----
 .../services/ldap/LdapConfigurationService.java | 185 --------------
 .../api/services/ldap/LdapRequestInfo.java      |  61 -----
 .../services/serializers/JsonSerializer.java    |  38 ++-
 .../commands/StackAdvisorCommand.java           |  14 +-
 .../AmbariServerConfigurationCategory.java      |  69 ++++++
 .../AmbariServerConfigurationHandler.java       | 110 +++++++++
 .../AmbariServerLDAPConfigurationHandler.java   | 172 +++++++++++++
 .../internal/OperationStatusMetaData.java       |  90 +++++++
 ...ootServiceComponentConfigurationHandler.java | 114 +++++++++
 ...iceComponentConfigurationHandlerFactory.java |  54 +++++
 ...eComponentConfigurationResourceProvider.java | 243 ++++++++-----------
 .../apache/ambari/server/ldap/LdapModule.java   |   4 -
 .../ldap/domain/AmbariLdapConfigKeys.java       |  83 -------
 .../ldap/domain/AmbariLdapConfiguration.java    |  85 +++----
 .../domain/AmbariLdapConfigurationFactory.java  |  34 ---
 .../domain/AmbariLdapConfigurationKeys.java     |  83 +++++++
 .../AmbariLdapConfigurationProvider.java        |  19 +-
 .../server/ldap/service/AmbariLdapFacade.java   |   4 +-
 .../ambari/server/ldap/service/LdapFacade.java  |   9 +-
 .../DefaultLdapAttributeDetectionService.java   |   8 +-
 .../ads/DefaultLdapConfigurationService.java    |   4 +-
 .../ads/detectors/GroupMemberAttrDetector.java  |   4 +-
 .../ads/detectors/GroupNameAttrDetector.java    |   7 +-
 .../ads/detectors/GroupObjectClassDetector.java |   8 +-
 .../detectors/UserGroupMemberAttrDetector.java  |   5 +-
 .../ads/detectors/UserNameAttrDetector.java     |   4 +-
 .../ads/detectors/UserObjectClassDetector.java  |   4 +-
 .../commands/StackAdvisorCommandTest.java       |   4 +-
 ...ponentConfigurationResourceProviderTest.java | 214 +++++++++++++---
 .../server/ldap/LdapModuleFunctionalTest.java   |  49 ++--
 .../TestAmbariLdapConfigurationFactory.java     |  29 ---
 .../ldap/service/AmbariLdapFacadeTest.java      |  36 ++-
 ...efaultLdapAttributeDetectionServiceTest.java |  24 +-
 .../DefaultLdapConfigurationServiceTest.java    |  31 ++-
 41 files changed, 1184 insertions(+), 891 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java
index b614c5e..484547a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java
@@ -24,6 +24,7 @@ import org.apache.ambari.server.api.services.Result;
 import org.apache.ambari.server.api.services.ResultImpl;
 import org.apache.ambari.server.api.services.ResultMetadata;
 import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.controller.internal.OperationStatusMetaData;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.RequestStatus;
 import org.apache.ambari.server.controller.spi.RequestStatusMetaData;
@@ -94,6 +95,11 @@ public class CreateHandler extends BaseManagementHandler {
       return null;
     }
 
-    throw new UnsupportedOperationException();
+    if (requestStatusMetaData.getClass() == OperationStatusMetaData.class) {
+      return (OperationStatusMetaData) requestStatusMetaData;
+    } else {
+      throw new IllegalArgumentException(String.format("RequestStatusDetails is of an expected type: %s",
+          requestStatusMetaData.getClass().getName()));
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java
index 2f1af51..c578cb9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java
@@ -24,6 +24,7 @@ import org.apache.ambari.server.api.services.Result;
 import org.apache.ambari.server.api.services.ResultImpl;
 import org.apache.ambari.server.api.services.ResultMetadata;
 import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.controller.internal.OperationStatusMetaData;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.RequestStatus;
@@ -79,6 +80,11 @@ public class UpdateHandler extends BaseManagementHandler {
       return null;
     }
 
-    throw new UnsupportedOperationException();
+    if (requestStatusMetaData.getClass() == OperationStatusMetaData.class) {
+      return (OperationStatusMetaData) requestStatusMetaData;
+    } else {
+      throw new IllegalArgumentException(String.format("RequestStatusDetails is of an expected type: %s",
+          requestStatusMetaData.getClass().getName()));
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index fecaedc..47da19b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.ambari.server.api.query.QueryImpl;
+import org.apache.ambari.server.api.services.RootServiceComponentConfigurationService;
 import org.apache.ambari.server.controller.internal.ClusterKerberosDescriptorResourceProvider;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
@@ -239,7 +240,8 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
 
       case RootServiceComponentConfiguration:
         resourceDefinition = new SimpleResourceDefinition(Resource.Type.RootServiceComponentConfiguration,
-            "configuration", "configurations");
+            "configuration", "configurations",
+            null, RootServiceComponentConfigurationService.DIRECTIVES_MAP);
         break;
 
       case RootServiceHostComponent:

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java
index c7c37a6..a6be143 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java
@@ -34,6 +34,7 @@ package org.apache.ambari.server.api.services;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
@@ -48,10 +49,14 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
+import org.apache.ambari.server.api.resources.BaseResourceDefinition;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.http.HttpStatus;
 
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -91,6 +96,16 @@ public class RootServiceComponentConfigurationService extends BaseService {
   private static final String REQUEST_TYPE =
       "org.apache.ambari.server.api.services.RootServiceComponentConfigurationRequestSwagger";
 
+  public static final String DIRECTIVE_OPERATION = "op";
+
+  private static final Set<String> DIRECTIVES = Sets.newHashSet(DIRECTIVE_OPERATION);
+
+  public static final Map<BaseResourceDefinition.DirectiveType, Set<String>> DIRECTIVES_MAP =
+      ImmutableMap.<BaseResourceDefinition.DirectiveType, Set<String>>builder()
+          .put(BaseResourceDefinition.DirectiveType.CREATE, DIRECTIVES)
+          .put(BaseResourceDefinition.DirectiveType.UPDATE, DIRECTIVES)
+          .build();
+
   private final String serviceName;
   private final String componentName;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
deleted file mode 100644
index 7bac65e..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed 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.api.services.ldap;
-
-import java.util.Map;
-
-/**
- * Domain POJO representing generic ambari configuration data.
- */
-public class AmbariConfiguration {
-
-  /**
-   * The type of the configuration,  eg.: ldap-configuration
-   */
-  private String type;
-
-  private Map<String, String> properties = null;
-
-  public String getType() {
-    return type;
-  }
-
-  public void setType(String type) {
-    this.type = type;
-  }
-
-  public Map<String, String> getProperties() {
-    return properties;
-  }
-
-  public void setProperties(Map<String, String> data) {
-    this.properties = data;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
deleted file mode 100644
index 478d4ff..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed 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.api.services.ldap;
-
-/**
- * Enumeration for supported operations related to LDAP configuration.
- */
-public enum LdapConfigOperation {
-  TEST_CONNECTION("test-connection"),
-  TEST_ATTRIBUTES("test-attributes"),
-  DETECT_ATTRIBUTES("detect-attributes");
-
-  private String actionStr;
-
-  LdapConfigOperation(String actionStr) {
-    this.actionStr = actionStr;
-  }
-
-  public static LdapConfigOperation fromAction(String action) {
-    for (LdapConfigOperation val : LdapConfigOperation.values()) {
-      if (val.action().equals(action)) {
-        return val;
-      }
-    }
-    throw new IllegalStateException("Action [ " + action + " ] is not supported");
-  }
-
-  public String action() {
-    return this.actionStr;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
deleted file mode 100644
index 0e065e5..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed 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.api.services.ldap;
-
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * Request object wrapping information for LDAP configuration related request calls.
- */
-public class LdapConfigurationRequest {
-
-  @SerializedName("Configuration")
-  private AmbariConfiguration ambariConfiguration;
-
-  @SerializedName("RequestInfo")
-  private LdapRequestInfo requestInfo;
-
-  public LdapConfigurationRequest() {
-  }
-
-  public AmbariConfiguration getAmbariConfiguration() {
-    return ambariConfiguration;
-  }
-
-  public void setAmbariConfiguration(AmbariConfiguration ambariConfiguration) {
-    this.ambariConfiguration = ambariConfiguration;
-  }
-
-  public LdapRequestInfo getRequestInfo() {
-    return requestInfo;
-  }
-
-  public void setRequestInfo(LdapRequestInfo requestInfo) {
-    this.requestInfo = requestInfo;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
deleted file mode 100644
index 22784cd..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Licensed 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.
- */
-
-/*
- * Licensed 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.api.services.ldap;
-
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.ambari.annotations.ApiIgnore;
-import org.apache.ambari.server.StaticallyInject;
-import org.apache.ambari.server.api.services.BaseService;
-import org.apache.ambari.server.api.services.Result;
-import org.apache.ambari.server.api.services.ResultImpl;
-import org.apache.ambari.server.api.services.ResultStatus;
-import org.apache.ambari.server.controller.internal.ResourceImpl;
-import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
-import org.apache.ambari.server.ldap.service.LdapFacade;
-import org.apache.ambari.server.security.authorization.AuthorizationException;
-import org.apache.ambari.server.security.authorization.AuthorizationHelper;
-import org.apache.ambari.server.security.authorization.ResourceType;
-import org.apache.ambari.server.security.authorization.RoleAuthorization;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.core.Authentication;
-
-import com.google.common.collect.Sets;
-
-/**
- * Endpoint designated to LDAP specific operations.
- */
-@StaticallyInject
-@Path("/ldapconfigs/")
-public class LdapConfigurationService extends BaseService {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationService.class);
-
-  @Inject
-  private static LdapFacade ldapFacade;
-
-  @Inject
-  private static AmbariLdapConfigurationFactory ambariLdapConfigurationFactory;
-
-
-  @POST
-  @ApiIgnore // until documented
-  @Path("/validate")
-  @Consumes(MediaType.APPLICATION_JSON)
-  @Produces(MediaType.APPLICATION_JSON)
-  public Response validateConfiguration(LdapConfigurationRequest ldapConfigurationRequest) {
-
-    // check if the user is authorized to perform the operation
-    authorize();
-
-    Set<String> groups = Sets.newHashSet();
-    Object responseEntity = null;
-
-    Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
-    try {
-
-      validateRequest(ldapConfigurationRequest);
-
-      AmbariLdapConfiguration ambariLdapConfiguration = ambariLdapConfigurationFactory.createLdapConfiguration(
-        ldapConfigurationRequest.getAmbariConfiguration().getProperties());
-
-      LdapConfigOperation action = LdapConfigOperation.fromAction(ldapConfigurationRequest.getRequestInfo().getAction());
-      switch (action) {
-
-        case TEST_CONNECTION:
-
-          LOGGER.info("Testing connection to the LDAP server ...");
-          ldapFacade.checkConnection(ambariLdapConfiguration);
-
-          break;
-        case TEST_ATTRIBUTES:
-
-          LOGGER.info("Testing LDAP attributes ....");
-          groups = ldapFacade.checkLdapAttributes(ldapConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
-          responseEntity = groups;
-
-          break;
-        case DETECT_ATTRIBUTES:
-
-          LOGGER.info("Detecting LDAP attributes ...");
-          ambariLdapConfiguration = ldapFacade.detectAttributes(ambariLdapConfiguration);
-          responseEntity = ambariLdapConfiguration;
-
-          break;
-        default:
-          LOGGER.warn("No action provided ...");
-          throw new IllegalArgumentException("No request action provided");
-      }
-
-    } catch (Exception e) {
-      result.setResultStatus(new ResultStatus(ResultStatus.STATUS.SERVER_ERROR, e));
-      responseEntity = e.getMessage();
-    }
-
-    return Response.status(result.getStatus().getStatusCode()).entity(responseEntity).build();
-  }
-
-  private void setResult(Set<String> groups, Result result) {
-    Resource resource = new ResourceImpl(Resource.Type.RootServiceComponentConfiguration);
-    resource.setProperty("groups", groups);
-    result.getResultTree().addChild(resource, "payload");
-  }
-
-  private void validateRequest(LdapConfigurationRequest ldapConfigurationRequest) {
-    String errMsg;
-
-    if (null == ldapConfigurationRequest) {
-      errMsg = "No ldap configuraiton request provided";
-      LOGGER.error(errMsg);
-      throw new IllegalArgumentException(errMsg);
-    }
-
-    if (null == ldapConfigurationRequest.getRequestInfo()) {
-      errMsg = String.format("No request information provided. Request: [%s]", ldapConfigurationRequest);
-      LOGGER.error(errMsg);
-      throw new IllegalArgumentException(errMsg);
-    }
-
-    if (null == ldapConfigurationRequest.getAmbariConfiguration()
-      || ldapConfigurationRequest.getAmbariConfiguration().getProperties() != null) {
-      errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapConfigurationRequest);
-      LOGGER.error(errMsg);
-      throw new IllegalArgumentException(errMsg);
-    }
-  }
-
-  private void authorize() {
-    try {
-      Authentication authentication = AuthorizationHelper.getAuthentication();
-
-      if (authentication == null || !authentication.isAuthenticated()) {
-        throw new AuthorizationException("Authentication data is not available, authorization to perform the requested operation is not granted");
-      }
-
-      if (!AuthorizationHelper.isAuthorized(authentication, ResourceType.AMBARI, null, requiredAuthorizations())) {
-        throw new AuthorizationException("The authenticated user does not have the appropriate authorizations to create the requested resource(s)");
-      }
-    } catch (AuthorizationException e) {
-      LOGGER.error("Unauthorized operation.", e);
-      throw new IllegalArgumentException("User is not authorized to perform the operation", e);
-    }
-
-  }
-
-  private Set<RoleAuthorization> requiredAuthorizations() {
-    return Sets.newHashSet(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION);
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
deleted file mode 100644
index eeecfee..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed 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.api.services.ldap;
-
-import java.util.Map;
-
-import org.apache.ambari.server.controller.RequestPostRequest;
-
-/**
- * Bean holding LDAP request specific request information.
- */
-public class LdapRequestInfo implements RequestPostRequest.RequestInfo {
-
-  // no-arg costructor facilitating JSON serialization
-  public LdapRequestInfo() {
-  }
-
-  private String action;
-
-  private Map<String, Object> parameters;
-
-  @Override
-  public String getAction() {
-    return action;
-  }
-
-  public void setAction(String action) {
-    this.action = action;
-  }
-
-  public void setParameters(Map<String, Object> parameters) {
-    this.parameters = parameters;
-  }
-
-  @Override
-  public String getCommand() {
-    return null;
-  }
-
-  @Override
-  public RequestPostRequest.OperationLevel getOperationLevel() {
-    return null;
-  }
-
-  @Override
-  public Map<String, Object> getParameters() {
-    return parameters;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java
index 0604d2b..a045d74 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java
@@ -31,6 +31,7 @@ import org.apache.ambari.server.api.services.ResultMetadata;
 import org.apache.ambari.server.api.services.ResultStatus;
 import org.apache.ambari.server.api.util.TreeNode;
 import org.apache.ambari.server.api.util.TreeNodeImpl;
+import org.apache.ambari.server.controller.internal.OperationStatusMetaData;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.codehaus.jackson.JsonFactory;
 import org.codehaus.jackson.JsonGenerator;
@@ -112,6 +113,8 @@ public class JsonSerializer implements ResultSerializer {
 
     if (resultMetadata.getClass() == DeleteResultMetadata.class) {
       processResultMetadata((DeleteResultMetadata) resultMetadata);
+    } else if (resultMetadata.getClass() == OperationStatusMetaData.class) {
+      processResultMetadata((OperationStatusMetaData) resultMetadata);
     } else {
       throw new IllegalArgumentException("ResultDetails is not of type DeleteResultDetails, cannot parse");
     }
@@ -144,6 +147,30 @@ public class JsonSerializer implements ResultSerializer {
     m_generator.writeEndObject();
   }
 
+  private void processResultMetadata(OperationStatusMetaData metaData) throws IOException {
+    m_generator.writeStartObject();
+    m_generator.writeObjectFieldStart("operationResults");
+
+    for (OperationStatusMetaData.Result result : metaData.getResults()) {
+      m_generator.writeObjectFieldStart(result.getId());
+      m_generator.writeStringField("status", result.isSuccess() ? "success" : "error");
+
+      if (result.getMessage() != null) {
+        m_generator.writeStringField("message", result.getMessage());
+      }
+
+      if (result.getResponse() != null) {
+        m_generator.writeFieldName("response");
+        m_mapper.writeValue(m_generator, result.getResponse());
+      }
+
+      m_generator.writeEndObject();
+    }
+
+    m_generator.writeEndObject();
+    m_generator.writeEndObject();
+  }
+
   private void processNode(TreeNode<Resource> node) throws IOException {
     if (isObject(node)) {
       m_generator.writeStartObject();
@@ -158,10 +185,11 @@ public class JsonSerializer implements ResultSerializer {
     }
 
     if (isArray(node)) {
-      if (node.getName() != null)
+      if (node.getName() != null) {
         m_generator.writeArrayFieldStart(node.getName());
-      else
+      } else {
         m_generator.writeStartArray();
+      }
     }
 
     for (TreeNode<Resource> child : node.getChildren()) {
@@ -186,11 +214,11 @@ public class JsonSerializer implements ResultSerializer {
   // Determines whether or not the given node is an array
   private boolean isArray(TreeNode<Resource> node) {
     return (node.getObject() == null && node.getName() != null) ||
-            (node.getObject() == null && node.getName() == null &&
-             node.getChildren().size() > 1);
+        (node.getObject() == null && node.getName() == null &&
+            node.getChildren().size() > 1);
   }
 
-  private TreeNode<Map<String, Object>> getTreeProperties (Map<String, Map<String, Object>> propertiesMap) {
+  private TreeNode<Map<String, Object>> getTreeProperties(Map<String, Map<String, Object>> propertiesMap) {
     TreeNode<Map<String, Object>> treeProperties = new TreeNodeImpl<>(null, new LinkedHashMap<>(), null);
 
     for (Map.Entry<String, Map<String, Object>> entry : propertiesMap.entrySet()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
index 4ec15ef..6e6b37e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
@@ -47,6 +47,7 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.controller.RootComponent;
 import org.apache.ambari.server.controller.RootService;
+import org.apache.ambari.server.controller.internal.AmbariServerConfigurationCategory;
 import org.apache.ambari.server.controller.internal.RootServiceComponentConfigurationResourceProvider;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.state.ServiceInfo;
@@ -78,7 +79,6 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
 
   private static final String GET_HOSTS_INFO_URI = "/api/v1/hosts"
       + "?fields=Hosts/*&Hosts/host_name.in(%s)";
-  static final String LDAP_CONFIGURATION_PROPERTY = "ldap-configuration";
 
   private static final String GET_SERVICES_INFO_URI = "/api/v1/stacks/%s/versions/%s/"
       + "?fields=Versions/stack_name,Versions/stack_version,Versions/parent_stack_version"
@@ -91,11 +91,11 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
       + "&services/StackServices/service_name.in(%s)";
 
   private static final String GET_AMBARI_LDAP_CONFIG_URI = String.format("/api/v1/services/%s/components/%s/configurations?%s=%s&fields=%s",
-    RootService.AMBARI.name(),
-    RootComponent.AMBARI_SERVER.name(),
-    RootServiceComponentConfigurationResourceProvider.CONFIGURATION_CATEGORY_PROPERTY_ID,
-    LDAP_CONFIGURATION_PROPERTY,
-    RootServiceComponentConfigurationResourceProvider.CONFIGURATION_PROPERTIES_PROPERTY_ID);
+      RootService.AMBARI.name(),
+      RootComponent.AMBARI_SERVER.name(),
+      RootServiceComponentConfigurationResourceProvider.CONFIGURATION_CATEGORY_PROPERTY_ID,
+      AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName(),
+      RootServiceComponentConfigurationResourceProvider.CONFIGURATION_PROPERTIES_PROPERTY_ID);
 
   private static final String SERVICES_PROPERTY = "services";
   private static final String SERVICES_COMPONENTS_PROPERTY = "components";
@@ -230,7 +230,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
         throw new StackAdvisorException("Unexpected JSON document encountered: missing the Configuration/properties object");
       }
 
-      root.put(LDAP_CONFIGURATION_PROPERTY, ldapConfigurationProperties);
+      root.put(AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName(), ldapConfigurationProperties);
     } else if (numConfigs > 1) {
       throw new StackAdvisorException(String.format("Multiple (%s) LDAP configs are found in the DB.", numConfigs));
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationCategory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationCategory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationCategory.java
new file mode 100644
index 0000000..f4fc83f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationCategory.java
@@ -0,0 +1,69 @@
+/*
+ * 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 org.apache.commons.lang.StringUtils;
+
+/**
+ * AmbariServerConfigurationCategory is an enumeration of the different Ambari server specific
+ * configuration categories.
+ */
+public enum AmbariServerConfigurationCategory {
+  LDAP_CONFIGURATION("ldap-configuration");
+
+  private final String categoryName;
+
+  AmbariServerConfigurationCategory(String categoryName) {
+    this.categoryName = categoryName;
+  }
+
+  public String getCategoryName() {
+    return categoryName;
+  }
+
+  /**
+   * Safely returns an {@link AmbariServerConfigurationCategory} given the category's descriptive name
+   *
+   * @param categoryName a descriptive name
+   * @return an {@link AmbariServerConfigurationCategory}
+   */
+  public static AmbariServerConfigurationCategory translate(String categoryName) {
+    if (!StringUtils.isEmpty(categoryName)) {
+      categoryName = categoryName.trim();
+      for (AmbariServerConfigurationCategory category : values()) {
+        if (category.getCategoryName().equals(categoryName)) {
+          return category;
+        }
+      }
+    }
+
+    throw new IllegalArgumentException(String.format("Invalid Ambari server configuration category name: %s", categoryName));
+  }
+
+  /**
+   * Safely returns the {@link AmbariServerConfigurationCategory}'s descriptive name or <code>null</code>
+   * if no {@link AmbariServerConfigurationCategory} was supplied.
+   *
+   * @param category an {@link AmbariServerConfigurationCategory}
+   * @return the descriptive name of an {@link AmbariServerConfigurationCategory}
+   */
+  public static String translate(AmbariServerConfigurationCategory category) {
+    return (category == null) ? null : category.getCategoryName();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
new file mode 100644
index 0000000..34285d6
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
@@ -0,0 +1,110 @@
+/*
+ * 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.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.events.AmbariConfigurationChangedEvent;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
+import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
+import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+
+/**
+ * AmbariServerConfigurationHandler handles Ambari server specific configuration properties.
+ */
+@StaticallyInject
+class AmbariServerConfigurationHandler extends RootServiceComponentConfigurationHandler {
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariServerConfigurationHandler.class);
+
+  @Inject
+  private static AmbariConfigurationDAO ambariConfigurationDAO;
+
+  @Inject
+  private static AmbariEventPublisher publisher;
+
+
+  @Override
+  public Map<String, Map<String, String>> getConfigurations(String categoryName)
+      throws NoSuchResourceException {
+    Map<String, Map<String, String>> configurations = null;
+
+    List<AmbariConfigurationEntity> entities = (categoryName == null)
+        ? ambariConfigurationDAO.findAll()
+        : ambariConfigurationDAO.findByCategory(categoryName);
+
+    if (entities != null) {
+      configurations = new HashMap<>();
+
+      for (AmbariConfigurationEntity entity : entities) {
+        String category = entity.getCategoryName();
+        Map<String, String> properties = configurations.get(category);
+
+        if (properties == null) {
+          properties = new TreeMap<>();
+          configurations.put(category, properties);
+        }
+
+        properties.put(entity.getPropertyName(), entity.getPropertyValue());
+      }
+    }
+
+    return configurations;
+  }
+
+  @Override
+  public void removeConfiguration(String categoryName) throws NoSuchResourceException {
+    if (null == categoryName) {
+      LOGGER.debug("No resource id provided in the request");
+    } else {
+      LOGGER.debug("Deleting Ambari configuration with id: {}", categoryName);
+      try {
+        if (ambariConfigurationDAO.removeByCategory(categoryName) > 0) {
+          publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
+        }
+      } catch (IllegalStateException e) {
+        throw new NoSuchResourceException(e.getMessage());
+      }
+    }
+  }
+
+  @Override
+  public void updateCategory(String categoryName, Map<String, String> properties, boolean removePropertiesIfNotSpecified) {
+    if (ambariConfigurationDAO.reconcileCategory(categoryName, properties, removePropertiesIfNotSpecified)) {
+      // notify subscribers about the configuration changes
+      publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
+    }
+  }
+
+  @Override
+  public OperationResult performOperation(String categoryName, Map<String, String> properties,
+                                          boolean mergeExistingProperties, String operation,
+                                          Map<String, Object> operationParameters) throws SystemException {
+    throw new SystemException(String.format("The requested operation is not supported for this category: %s", categoryName));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..6f16c49
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java
@@ -0,0 +1,172 @@
+/*
+ * 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.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.SystemException;
+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.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+
+/**
+ * AmbariServerLDAPConfigurationHandler handles Ambari server LDAP-specific configuration properties.
+ */
+@StaticallyInject
+class AmbariServerLDAPConfigurationHandler extends AmbariServerConfigurationHandler {
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariServerLDAPConfigurationHandler.class);
+
+  @Inject
+  private static LdapFacade ldapFacade;
+
+  @Override
+  public OperationResult performOperation(String categoryName, Map<String, String> properties,
+                                          boolean mergeExistingProperties, String operation, Map<String, Object> operationParameters) throws SystemException {
+
+    if (!AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName().equals(categoryName)) {
+      throw new SystemException(String.format("Unexpected category name for Ambari server LDAP properties: %s", categoryName));
+    }
+
+    OperationType operationType = OperationType.translate(operation);
+    if (operation == null) {
+      throw new SystemException("Unexpected operation for Ambari server LDAP properties");
+    }
+
+    Map<String, String> ldapConfigurationProperties = new HashMap<>();
+
+    // If we need to merge with the properties of an existing ldap-configuration property set, attempt
+    // to retrieve if. If one does not exist, that is ok.
+    if (mergeExistingProperties) {
+      try {
+        Map<String, Map<String, String>> _configurations = getConfigurations(categoryName);
+        if (_configurations != null) {
+          Map<String, String> _ldapProperties = _configurations.get(categoryName);
+
+          if (_ldapProperties != null) {
+            ldapConfigurationProperties.putAll(_ldapProperties);
+          }
+        }
+      } catch (NoSuchResourceException e) {
+        // Ignore this. There is no existing ldap-configuration category and that is ok.
+      }
+    }
+
+    if (properties != null) {
+      ldapConfigurationProperties.putAll(properties);
+    }
+
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapConfigurationProperties);
+
+    boolean success = true;
+    String message = null;
+    Object resultData = null;
+
+    try {
+      switch (operationType) {
+        case TEST_CONNECTION:
+          LOGGER.debug("Testing connection to the LDAP server ...");
+          ldapFacade.checkConnection(ambariLdapConfiguration);
+          break;
+
+        case TEST_ATTRIBUTES:
+          LOGGER.debug("Testing LDAP attributes ....");
+          Set<String> groups = ldapFacade.checkLdapAttributes(operationParameters, ambariLdapConfiguration);
+          resultData = Collections.singletonMap("groups", groups);
+          break;
+
+        case DETECT_ATTRIBUTES:
+          LOGGER.info("Detecting LDAP attributes ...");
+          ambariLdapConfiguration = ldapFacade.detectAttributes(ambariLdapConfiguration);
+          resultData = Collections.singletonMap("attributes", ambariLdapConfiguration.toMap());
+          break;
+
+        default:
+          LOGGER.warn("No action provided ...");
+          throw new IllegalArgumentException("No request action provided");
+      }
+    } catch (AmbariLdapException e) {
+      success = false;
+      message = determineCause(e);
+      if (StringUtils.isEmpty(message)) {
+        message = "An unexpected error has occurred.";
+      }
+
+      LOGGER.warn(String.format("Failed to perform %s: %s", operationType.name(), message), e);
+    }
+
+    return new OperationResult(operationType.getOperation(), success, message, resultData);
+  }
+
+  private String determineCause(Throwable throwable) {
+    if (throwable == null) {
+      return null;
+    } else {
+      Throwable cause = throwable.getCause();
+      if ((cause == null) || (cause == throwable)) {
+        return throwable.getMessage();
+      } else {
+        String message = determineCause(cause);
+        return (message == null) ? throwable.getMessage() : message;
+      }
+    }
+  }
+
+  enum OperationType {
+    TEST_CONNECTION("test-connection"),
+    TEST_ATTRIBUTES("test-attributes"),
+    DETECT_ATTRIBUTES("detect-attributes");
+
+    private final String operation;
+
+    OperationType(String operation) {
+      this.operation = operation;
+    }
+
+    public String getOperation() {
+      return operation;
+    }
+
+    public static OperationType translate(String operation) {
+      if (!StringUtils.isEmpty(operation)) {
+        operation = operation.trim();
+        for (OperationType category : values()) {
+          if (category.getOperation().equals(operation)) {
+            return category;
+          }
+        }
+      }
+
+      throw new IllegalArgumentException(String.format("Invalid Ambari server configuration category name: %s", operation));
+    }
+
+    public static String translate(OperationType operation) {
+      return (operation == null) ? null : operation.getOperation();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/OperationStatusMetaData.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/OperationStatusMetaData.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/OperationStatusMetaData.java
new file mode 100644
index 0000000..2467fc5
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/OperationStatusMetaData.java
@@ -0,0 +1,90 @@
+/*
+ * 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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.ambari.server.api.services.ResultMetadata;
+import org.apache.ambari.server.controller.spi.RequestStatusMetaData;
+
+/**
+ * OperationStatusMetaData is data to return as the status of an operation invoked on a set of resources
+ * while processing a REST API request.
+ * <p>
+ * Zero or more results may be set as part of the data.
+ */
+public class OperationStatusMetaData implements RequestStatusMetaData, ResultMetadata {
+
+  private final Map<String, Result> results = new HashMap<>();
+
+  public void addResult(String id, boolean success, String message, Object response) {
+    results.put(id, new Result(id, success, message, response));
+  }
+
+  public Set<String> getResultIds() {
+    return results.keySet();
+  }
+
+  public Result getResult(String id) {
+    if (results.containsKey(id)) {
+      return results.get(id);
+    }
+
+    throw new NoSuchElementException();
+  }
+
+  public List<Result> getResults() {
+    return new ArrayList<>(results.values());
+  }
+
+  public class Result {
+    private final String id;
+    private final boolean success;
+    private final String message;
+    private final Object response;
+
+    Result(String id, boolean success, String message, Object response) {
+      this.id = id;
+      this.success = success;
+      this.message = message;
+      this.response = response;
+    }
+
+    public String getId() {
+      return id;
+    }
+
+    public boolean isSuccess() {
+      return success;
+    }
+
+    public String getMessage() {
+      return message;
+    }
+
+    public Object getResponse() {
+      return response;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandler.java
new file mode 100644
index 0000000..3b58ce1
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandler.java
@@ -0,0 +1,114 @@
+/*
+ * 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.Map;
+
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.SystemException;
+
+/**
+ * RootServiceComponentConfigurationHandler is an interface to be implemented to handle the different
+ * types of root-level configurations.
+ */
+abstract class RootServiceComponentConfigurationHandler {
+  /**
+   * Retrieve the request configurations.
+   *
+   * @param categoryName the category name (or <code>null</code> for all)
+   * @return a map of category names to properties (name/value pairs).
+   * @throws NoSuchResourceException if the requested data is not found
+   */
+  public abstract Map<String, Map<String, String>> getConfigurations(String categoryName) throws NoSuchResourceException;
+
+  /**
+   * Delete the requested configuration.
+   *
+   * @param categoryName the category name
+   * @throws NoSuchResourceException if the requested category does not exist
+   */
+  public abstract void removeConfiguration(String categoryName) throws NoSuchResourceException;
+
+  /**
+   * Set or update a configuration category with the specified properties.
+   * <p>
+   * If <code>removePropertiesIfNotSpecified</code> is <code>true</code>, the persisted category is to include only the specified properties.
+   * <p>
+   * If <code>removePropertiesIfNotSpecified</code> is <code>false</code>, the persisted category is to include the union of the existing and specified properties.
+   * <p>
+   * In any case, existing property values will be overwritten by the one specified in the property map.
+   *
+   * @param categoryName                   the category name
+   * @param properties                     a map of properties to set
+   * @param removePropertiesIfNotSpecified <code>true</code> to ensure the set of properties are only those that have be explicitly specified;
+   *                                       <code>false</code> to update the set of existing properties with the specified set of properties, adding missing properties but not removing any properties
+   */
+  public abstract void updateCategory(String categoryName, Map<String, String> properties, boolean removePropertiesIfNotSpecified);
+
+  /**
+   * Preform some operation on the set of data for a category.
+   * <p>
+   * If <code>mergeExistingProperties</code> is <code>false</code>, the operation is to include the union of the existing and specified properties.
+   * <p>
+   * If <code>mergeExistingProperties</code> is <code>false</code>, the operation is to include only the specified properties.
+   *
+   * @param categoryName            the category name
+   * @param properties              a map of properties to set
+   * @param mergeExistingProperties <code>true</code> to use the the set of existing properties along with the specified set of properties;
+   *                                <code>false</code>  to use set of specified properties only
+   * @param operation               the operation to perform
+   * @param operationParameters     parameters to supply the name operation
+   * @return an {@link OperationResult}
+   * @throws SystemException if an error occurs while handling the request
+   */
+  public abstract OperationResult performOperation(String categoryName, Map<String, String> properties,
+                                                   boolean mergeExistingProperties, String operation,
+                                                   Map<String, Object> operationParameters) throws SystemException;
+
+  class OperationResult {
+    private final String id;
+    private final boolean success;
+    private final String message;
+    private final Object response;
+
+    OperationResult(String id, boolean success, String message, Object response) {
+      this.id = id;
+      this.success = success;
+      this.message = message;
+      this.response = response;
+    }
+
+    public String getId() {
+      return id;
+    }
+
+    public boolean isSuccess() {
+      return success;
+    }
+
+    public String getMessage() {
+      return message;
+    }
+
+    public Object getResponse() {
+      return response;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandlerFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandlerFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandlerFactory.java
new file mode 100644
index 0000000..38b5373
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandlerFactory.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.apache.ambari.server.controller.RootComponent;
+import org.apache.ambari.server.controller.RootService;
+
+import com.google.inject.Singleton;
+
+/**
+ * RootServiceComponentConfigurationHandlerFactory produces RootServiceComponentConfigurationHandler
+ * implementations for the relevant service, component, and category.
+ */
+@Singleton
+public class RootServiceComponentConfigurationHandlerFactory {
+
+  /**
+   * Returns the internal configuration handler used to support various configuration storage facilities.
+   *
+   * @param serviceName   the service name
+   * @param componentName the component name
+   * @param categoryName  the category name
+   * @return a {@link RootServiceComponentConfigurationHandler}
+   */
+  public RootServiceComponentConfigurationHandler getInstance(String serviceName, String componentName, String categoryName) {
+    if (RootService.AMBARI.name().equals(serviceName)) {
+      if (RootComponent.AMBARI_SERVER.name().equals(componentName)) {
+        if (AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName().equals(categoryName)) {
+          return new AmbariServerLDAPConfigurationHandler();
+        } else {
+          return new AmbariServerConfigurationHandler();
+        }
+      }
+    }
+
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java
index 7807865..b9e7d67 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java
@@ -22,14 +22,11 @@ import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeMap;
 
 import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.controller.RootComponent;
-import org.apache.ambari.server.controller.RootService;
+import org.apache.ambari.server.api.services.RootServiceComponentConfigurationService;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.Predicate;
@@ -41,22 +38,14 @@ import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PredicateHelper;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
-import org.apache.ambari.server.events.AmbariConfigurationChangedEvent;
-import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
-import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
-import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
 
 public class RootServiceComponentConfigurationResourceProvider extends AbstractAuthorizedResourceProvider {
 
-  private static final Logger LOGGER = LoggerFactory.getLogger(RootServiceComponentConfigurationResourceProvider.class);
-
   static final String RESOURCE_KEY = "Configuration";
 
   public static final String CONFIGURATION_CATEGORY_PROPERTY_ID = PropertyHelper.getPropertyId(RESOURCE_KEY, "category");
@@ -89,10 +78,7 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   }
 
   @Inject
-  private AmbariConfigurationDAO ambariConfigurationDAO;
-
-  @Inject
-  private AmbariEventPublisher publisher;
+  private RootServiceComponentConfigurationHandlerFactory rootServiceComponentConfigurationHandlerFactory;
 
   public RootServiceComponentConfigurationResourceProvider() {
     super(PROPERTIES, PK_PROPERTY_MAP);
@@ -113,9 +99,20 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   public RequestStatus createResourcesAuthorized(Request request)
       throws SystemException, UnsupportedPropertyException, ResourceAlreadyExistsException, NoSuchParentResourceException {
 
-    createOrAddProperties(null, null, null, request.getProperties(), true);
+    OperationStatusMetaData operationStatusMetadata = null;
 
-    return getRequestStatus(null);
+    Map<String, String> requestInfoProperties = request.getRequestInfoProperties();
+    if (requestInfoProperties.containsKey(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION)) {
+      String operationType = requestInfoProperties.get(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION);
+      Map<String, Object> operationParameters = getOperationParameters(requestInfoProperties);
+
+      operationStatusMetadata = performOperation(null, null, null, request.getProperties(),
+          false, operationType, operationParameters);
+    } else {
+      createOrAddProperties(null, null, null, request.getProperties(), true);
+    }
+
+    return getRequestStatus(null, null, operationStatusMetadata);
   }
 
   @Override
@@ -163,7 +160,6 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
     });
   }
 
-
   @Override
   protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
       UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
@@ -172,7 +168,7 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
     String componentName = (String) PredicateHelper.getProperties(predicate).get(CONFIGURATION_COMPONENT_NAME_PROPERTY_ID);
     String categoryName = (String) PredicateHelper.getProperties(predicate).get(CONFIGURATION_CATEGORY_PROPERTY_ID);
 
-    ConfigurationHandler handler = getConfigurationHandler(serviceName, componentName);
+    RootServiceComponentConfigurationHandler handler = rootServiceComponentConfigurationHandlerFactory.getInstance(serviceName, componentName, categoryName);
     if (handler != null) {
       handler.removeConfiguration(categoryName);
     } else {
@@ -190,9 +186,20 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
     String componentName = (String) PredicateHelper.getProperties(predicate).get(CONFIGURATION_COMPONENT_NAME_PROPERTY_ID);
     String categoryName = (String) PredicateHelper.getProperties(predicate).get(CONFIGURATION_CATEGORY_PROPERTY_ID);
 
-    createOrAddProperties(serviceName, componentName, categoryName, request.getProperties(), false);
+    OperationStatusMetaData operationStatusMetadata = null;
 
-    return getRequestStatus(null);
+    Map<String, String> requestInfoProperties = request.getRequestInfoProperties();
+    if (requestInfoProperties.containsKey(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION)) {
+      String operationType = requestInfoProperties.get(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION);
+      Map<String, Object> operationParameters = getOperationParameters(requestInfoProperties);
+
+      operationStatusMetadata = performOperation(serviceName, componentName, categoryName, request.getProperties(),
+          true, operationType, operationParameters);
+    } else {
+      createOrAddProperties(serviceName, componentName, categoryName, request.getProperties(), false);
+    }
+
+    return getRequestStatus(null, null, operationStatusMetadata);
   }
 
   private Resource toResource(String serviceName, String componentName, String categoryName, Map<String, String> properties, Set<String> requestedIds) {
@@ -211,7 +218,7 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
    * value and one or more property (<code>AmbariConfiguration/properties/property.name</code>) values.
    * If a category cannot be determined from the propery set, the default category value (passed in)
    * is used.  If a default category is set, it is assumed that it was parsed from the request predicate
-   * (if availabe).
+   * (if available).
    *
    * @param defaultServiceName             the default service name to use if needed
    * @param defaultComponentName           the default component name to use if needed
@@ -229,8 +236,7 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
       for (Map<String, Object> resourceProperties : requestProperties) {
         RequestDetails requestDetails = parseProperties(defaultServiceName, defaultComponentName, defaultCategoryName, resourceProperties);
 
-        ConfigurationHandler handler = getConfigurationHandler(requestDetails.serviceName, requestDetails.componentName);
-
+        RootServiceComponentConfigurationHandler handler = rootServiceComponentConfigurationHandlerFactory.getInstance(requestDetails.serviceName, requestDetails.componentName, requestDetails.categoryName);
         if (handler != null) {
           handler.updateCategory(requestDetails.categoryName, requestDetails.properties, removePropertiesIfNotSpecified);
         } else {
@@ -241,6 +247,49 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   }
 
   /**
+   * Performs the requested operation on the set of data for the specified configration data.
+   *
+   * @param defaultServiceName      the default service name to use if needed
+   * @param defaultComponentName    the default component name to use if needed
+   * @param defaultCategoryName     the default category to use if needed
+   * @param requestProperties       a collection of property maps parsed from the request
+   * @param mergeExistingProperties <code>true</code> to use the the set of existing properties along with the specified set of properties;
+   *                                <code>false</code>  to use set of specified properties only
+   * @param operationType           the operation to perform
+   * @param operationParameters     parameters to supply the name operation
+   * @return an {@link OperationStatusMetaData}
+   * @throws SystemException if an error occurs while performing the operation
+   */
+  private OperationStatusMetaData performOperation(String defaultServiceName, String defaultComponentName, String defaultCategoryName,
+                                                   Set<Map<String, Object>> requestProperties, boolean mergeExistingProperties,
+                                                   String operationType, Map<String, Object> operationParameters)
+      throws SystemException {
+
+    OperationStatusMetaData metaData = new OperationStatusMetaData();
+
+    // set of resource properties (each entry in the set belongs to a different resource)
+    if (requestProperties != null) {
+      for (Map<String, Object> resourceProperties : requestProperties) {
+        RequestDetails requestDetails = parseProperties(defaultServiceName, defaultComponentName, defaultCategoryName, resourceProperties);
+
+        RootServiceComponentConfigurationHandler handler = rootServiceComponentConfigurationHandlerFactory.getInstance(requestDetails.serviceName, requestDetails.componentName, requestDetails.categoryName);
+        if (handler != null) {
+          RootServiceComponentConfigurationHandler.OperationResult operationResult = handler.performOperation(requestDetails.categoryName, requestDetails.properties, mergeExistingProperties, operationType, operationParameters);
+          if (operationResult == null) {
+            throw new SystemException(String.format("An unexpected error has occurred while handling an operation for the %s component of the root service, %s", requestDetails.serviceName, requestDetails.componentName));
+          }
+
+          metaData.addResult(operationResult.getId(), operationResult.isSuccess(), operationResult.getMessage(), operationResult.getResponse());
+        } else {
+          throw new SystemException(String.format("Operations may not be performed on configurations for the %s component of the root service, %s", requestDetails.serviceName, requestDetails.componentName));
+        }
+      }
+    }
+
+    return metaData;
+  }
+
+  /**
    * Parse the property map from a request into a map of services to components to category names to maps of property names and values.
    *
    * @param defaultServiceName   the default service name to use if one is not found in the map of properties
@@ -300,7 +349,31 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   }
 
   /**
-   * Retrieves the requested configration resources
+   * Creates a map of the operation parameters from the data in the request info map.
+   * <p>
+   * Operation parmaters are set under the "parameters" category.
+   *
+   * @param requestInfoProperties a map of request info properties
+   * @return a map of operation request parameters
+   */
+  private Map<String, Object> getOperationParameters(Map<String, String> requestInfoProperties) {
+    Map<String, Object> operationParameters = new HashMap<>();
+
+    for (Map.Entry<String, String> entry : requestInfoProperties.entrySet()) {
+      String propertyCategory = PropertyHelper.getPropertyCategory(entry.getKey());
+      if ((propertyCategory != null) && propertyCategory.equals("parameters")) {
+        String name = PropertyHelper.getPropertyName(entry.getKey());
+        Object value = entry.getValue();
+        operationParameters.put(name, (value == null) ? null : value.toString());
+      }
+    }
+
+    return operationParameters;
+  }
+
+
+  /**
+   * Retrieves the requested configuration resources
    *
    * @param requestedIds the requested properties ids
    * @param propertyMap  the request properties
@@ -312,11 +385,11 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
 
     String serviceName = getStringProperty(propertyMap, CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
     String componentName = getStringProperty(propertyMap, CONFIGURATION_COMPONENT_NAME_PROPERTY_ID);
+    String categoryName = getStringProperty(propertyMap, CONFIGURATION_CATEGORY_PROPERTY_ID);
 
-    ConfigurationHandler handler = getConfigurationHandler(serviceName, componentName);
+    RootServiceComponentConfigurationHandler handler = rootServiceComponentConfigurationHandlerFactory.getInstance(serviceName, componentName, categoryName);
 
     if (handler != null) {
-      String categoryName = getStringProperty(propertyMap, CONFIGURATION_CATEGORY_PROPERTY_ID);
       Map<String, Map<String, String>> configurations = handler.getConfigurations(categoryName);
 
       if (configurations != null) {
@@ -329,24 +402,6 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
     return resources;
   }
 
-  /**
-   * Returns the internal configuration handler used to support various configuration storage facilites.
-   *
-   * @param serviceName   the service name
-   * @param componentName the component name
-   * @return
-   */
-  private ConfigurationHandler getConfigurationHandler(String serviceName, String componentName) {
-    if (RootService.AMBARI.name().equals(serviceName)) {
-      if (RootComponent.AMBARI_SERVER.name().equals(componentName)) {
-        return new AmbariServerConfigurationHandler();
-      }
-    }
-
-    return null;
-  }
-
-
   private String getStringProperty(Map<String, Object> propertyMap, String propertyId) {
     String value = null;
 
@@ -361,102 +416,6 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   }
 
   /**
-   * ConfigurationHandler is an interface to be implemented to support the relevant types of storage
-   * used to persist root-level component configurations.
-   */
-  private abstract class ConfigurationHandler {
-    /**
-     * Retrieve the request configurations.
-     *
-     * @param categoryName the category name (or <code>null</code> for all)
-     * @return a map of category names to properties (name/value pairs).
-     * @throws NoSuchResourceException if the requested data is not found
-     */
-    public abstract Map<String, Map<String, String>> getConfigurations(String categoryName) throws NoSuchResourceException;
-
-    /**
-     * Delete the requested configuration.
-     *
-     * @param categoryName the category name
-     * @throws NoSuchResourceException if the requested category does not exist
-     */
-    public abstract void removeConfiguration(String categoryName) throws NoSuchResourceException;
-
-    /**
-     * Set or update a configuration category with the specified properties.
-     * <p>
-     * If <code>removePropertiesIfNotSpecified</code> is <code>true</code>, the persisted category is to include only the specified properties.
-     * <p>
-     * If <code>removePropertiesIfNotSpecified</code> is <code>false</code>, the persisted category is to include the union of the existing and specified properties.
-     * <p>
-     * In any case, existing property values will be overwritten by the one specified in the property map.
-     *
-     * @param categoryName                   the category name
-     * @param properties                     a map of properties to set
-     * @param removePropertiesIfNotSpecified <code>true</code> to ensure the set of properties are only those that have be explicitly specified;
-     *                                       <code>false</code> to update the set of exising properties with the specified set of properties, adding missing properties but not removing any properties
-     */
-    public abstract void updateCategory(String categoryName, Map<String, String> properties, boolean removePropertiesIfNotSpecified);
-  }
-
-  /**
-   * AmbariServerConfigurationHandler handle Ambari server specific configuration properties.
-   */
-  private class AmbariServerConfigurationHandler extends ConfigurationHandler {
-    @Override
-    public Map<String, Map<String, String>> getConfigurations(String categoryName)
-        throws NoSuchResourceException {
-      Map<String, Map<String, String>> configurations = null;
-
-      List<AmbariConfigurationEntity> entities = (categoryName == null)
-          ? ambariConfigurationDAO.findAll()
-          : ambariConfigurationDAO.findByCategory(categoryName);
-
-      if (entities != null) {
-        configurations = new HashMap<>();
-
-        for (AmbariConfigurationEntity entity : entities) {
-          String category = entity.getCategoryName();
-          Map<String, String> properties = configurations.get(category);
-
-          if (properties == null) {
-            properties = new TreeMap<>();
-            configurations.put(category, properties);
-          }
-
-          properties.put(entity.getPropertyName(), entity.getPropertyValue());
-        }
-      }
-
-      return configurations;
-    }
-
-    @Override
-    public void removeConfiguration(String categoryName) throws NoSuchResourceException {
-      if (null == categoryName) {
-        LOGGER.debug("No resource id provided in the request");
-      } else {
-        LOGGER.debug("Deleting Ambari configuration with id: {}", categoryName);
-        try {
-          if (ambariConfigurationDAO.removeByCategory(categoryName) > 0) {
-            publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
-          }
-        } catch (IllegalStateException e) {
-          throw new NoSuchResourceException(e.getMessage());
-        }
-      }
-    }
-
-    @Override
-    public void updateCategory(String categoryName, Map<String, String> properties, boolean removePropertiesIfNotSpecified) {
-      if (ambariConfigurationDAO.reconcileCategory(categoryName, properties, removePropertiesIfNotSpecified)) {
-        // notify subscribers about the configuration changes
-        publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
-      }
-    }
-  }
-
-  /**
    * RequestDetails is a container for details parsed from the request.
    */
   private class RequestDetails {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
index 089da1d..64e94c4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
@@ -16,7 +16,6 @@
 package org.apache.ambari.server.ldap;
 
 import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
 import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider;
 import org.apache.ambari.server.ldap.service.AmbariLdapFacade;
 import org.apache.ambari.server.ldap.service.AttributeDetector;
@@ -36,7 +35,6 @@ import org.apache.ambari.server.ldap.service.ads.detectors.UserNameAttrDetector;
 import org.apache.ambari.server.ldap.service.ads.detectors.UserObjectClassDetector;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.assistedinject.FactoryModuleBuilder;
 import com.google.inject.multibindings.Multibinder;
 import com.google.inject.name.Names;
 
@@ -60,8 +58,6 @@ public class LdapModule extends AbstractModule {
 
     bind(AttributeDetectorFactory.class);
 
-    install(new FactoryModuleBuilder().build(AmbariLdapConfigurationFactory.class));
-
     // binding the set of user attributes detector
     Multibinder<AttributeDetector> userAttributeDetectorBinder = Multibinder.newSetBinder(binder(), AttributeDetector.class,
       Names.named(USER_ATTRIBUTES_DETECTORS));

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigKeys.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigKeys.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigKeys.java
deleted file mode 100644
index da655ad..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigKeys.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed 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.ldap.domain;
-
-/**
- * Constants representing supported LDAP related property names
- * // todo extend this with validation information, description, defaults maybe
- */
-public enum AmbariLdapConfigKeys {
-
-  LDAP_ENABLED("ambari.ldap.authentication.enabled"),
-  SERVER_HOST("ambari.ldap.connectivity.server.host"),
-  SERVER_PORT("ambari.ldap.connectivity.server.port"),
-  USE_SSL("ambari.ldap.connectivity.use_ssl"),
-
-  TRUST_STORE("ambari.ldap.connectivity.trust_store"),
-  TRUST_STORE_TYPE("ambari.ldap.connectivity.trust_store.type"),
-  TRUST_STORE_PATH("ambari.ldap.connectivity.trust_store.path"),
-  TRUST_STORE_PASSWORD("ambari.ldap.connectivity.trust_store.password"),
-  ANONYMOUS_BIND("ambari.ldap.connectivity.anonymous_bind"),
-
-  BIND_DN("ambari.ldap.connectivity.bind_dn"),
-  BIND_PASSWORD("ambari.ldap.connectivity.bind_password"),
-
-  ATTR_DETECTION("ambari.ldap.attributes.detection"), // manual | auto
-
-  DN_ATTRIBUTE("ambari.ldap.attributes.dn_attr"),
-
-  USER_OBJECT_CLASS("ambari.ldap.attributes.user.object_class"),
-  USER_NAME_ATTRIBUTE("ambari.ldap.attributes.user.name_attr"),
-  USER_GROUP_MEMBER_ATTRIBUTE("ambari.ldap.attributes.user.group_member_attr"),
-  USER_SEARCH_BASE("ambari.ldap.attributes.user.search_base"),
-
-  GROUP_OBJECT_CLASS("ambari.ldap.attributes.group.object_class"),
-  GROUP_NAME_ATTRIBUTE("ambari.ldap.attributes.group.name_attr"),
-  GROUP_MEMBER_ATTRIBUTE("ambari.ldap.attributes.group.member_attr"),
-  GROUP_SEARCH_BASE("ambari.ldap.attributes.group.search_base"),
-
-  USER_SEARCH_FILTER("ambari.ldap.advanced.user_search_filter"),
-  USER_MEMBER_REPLACE_PATTERN("ambari.ldap.advanced.user_member_replace_pattern"),
-  USER_MEMBER_FILTER("ambari.ldap.advanced.user_member_filter"),
-
-  GROUP_SEARCH_FILTER("ambari.ldap.advanced.group_search_filter"),
-  GROUP_MEMBER_REPLACE_PATTERN("ambari.ldap.advanced.group_member_replace_pattern"),
-  GROUP_MEMBER_FILTER("ambari.ldap.advanced.group_member_filter"),
-
-  FORCE_LOWERCASE_USERNAMES("ambari.ldap.advanced.force_lowercase_usernames"),
-  REFERRAL_HANDLING("ambari.ldap.advanced.referrals"), // folow
-  PAGINATION_ENABLED("ambari.ldap.advanced.pagination_enabled"); // true | false
-
-  private String propertyName;
-
-  AmbariLdapConfigKeys(String propName) {
-    this.propertyName = propName;
-  }
-
-  public String key() {
-    return this.propertyName;
-  }
-
-  public static AmbariLdapConfigKeys fromKeyStr(String keyStr) {
-    for (AmbariLdapConfigKeys key : values()) {
-      if (key.key().equals(keyStr)) {
-        return key;
-      }
-    }
-
-    throw new IllegalStateException("invalid konfiguration key found!");
-
-  }
-}