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/16 19:45:56 UTC

[40/50] [abbrv] ambari git commit: AMBARI-22418. Make Ambari configuration API consistent with existing API. (rlevas)

AMBARI-22418.  Make Ambari 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/3f2743b5
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3f2743b5
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3f2743b5

Branch: refs/heads/branch-feature-AMBARI-20859
Commit: 3f2743b58ba65c4bdc7d37df5348d17124bf305a
Parents: 2d81d49
Author: Robert Levas <rl...@hortonworks.com>
Authored: Wed Nov 15 12:11:34 2017 -0500
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Wed Nov 15 12:11:34 2017 -0500

----------------------------------------------------------------------
 .../resources/ResourceInstanceFactoryImpl.java  |   9 +-
 .../RootServiceComponentResourceDefinition.java |   9 +-
 .../AmbariConfigurationRequestSwagger.java      |  37 --
 .../AmbariConfigurationResponseSwagger.java     |  40 --
 .../services/AmbariConfigurationService.java    | 193 --------
 .../server/api/services/AmbariMetaInfo.java     |   4 +-
 ...iceComponentConfigurationRequestSwagger.java |  43 ++
 ...ceComponentConfigurationResponseSwagger.java |  43 ++
 ...ootServiceComponentConfigurationService.java | 226 +++++++++
 .../server/api/services/RootServiceService.java |   7 +
 .../api/services/ldap/AmbariConfiguration.java  |   6 +-
 .../services/ldap/LdapConfigurationRequest.java |   2 +-
 .../services/ldap/LdapConfigurationService.java |   6 +-
 .../commands/StackAdvisorCommand.java           |  62 ++-
 .../server/controller/ControllerModule.java     |   4 +-
 .../controller/MaintenanceStateHelper.java      |   3 +-
 .../controller/ResourceProviderFactory.java     |   4 +-
 .../ambari/server/controller/RootComponent.java |  27 ++
 .../ambari/server/controller/RootService.java   |  36 ++
 .../controller/RootServiceResponseFactory.java  |  44 +-
 .../AbstractControllerResourceProvider.java     |   4 +-
 .../AmbariConfigurationResourceProvider.java    | 302 ------------
 ...eComponentConfigurationResourceProvider.java | 476 +++++++++++++++++++
 .../RootServiceComponentPropertyProvider.java   |   4 +-
 .../RootServiceComponentResourceProvider.java   |   4 +-
 .../ambari/server/controller/spi/Resource.java  |   6 +-
 .../listeners/alerts/AlertReceivedListener.java |  10 +-
 .../alerts/AlertStateChangedListener.java       |   6 +-
 .../ldap/domain/AmbariLdapConfiguration.java    |   6 +-
 .../domain/AmbariLdapConfigurationFactory.java  |   2 +-
 .../AmbariLdapConfigurationProvider.java        |   6 +-
 .../metadata/AmbariServiceAlertDefinitions.java |  20 +-
 .../server/orm/dao/AlertDefinitionDAO.java      |   7 +-
 .../ambari/server/orm/dao/AlertDispatchDAO.java |   4 +-
 .../server/state/alert/AlertDefinitionHash.java |   8 +-
 .../server/state/cluster/ClusterImpl.java       |   4 +-
 .../services/AmbariServerAlertService.java      |   4 +-
 .../commands/StackAdvisorCommandTest.java       |   8 +-
 .../AmbariManagementControllerTest.java         |  16 +-
 .../RootServiceResponseFactoryTest.java         |  27 +-
 ...AmbariConfigurationResourceProviderTest.java | 377 ---------------
 ...ponentConfigurationResourceProviderTest.java | 393 +++++++++++++++
 ...ootServiceComponentPropertyProviderTest.java |  15 +-
 ...ootServiceComponentResourceProviderTest.java |   9 +-
 .../server/ldap/LdapModuleFunctionalTest.java   |   4 +-
 .../TestAmbariLdapConfigurationFactory.java     |   2 +-
 .../ldap/service/AmbariLdapFacadeTest.java      |   4 +-
 ...efaultLdapAttributeDetectionServiceTest.java |   8 +-
 .../DefaultLdapConfigurationServiceTest.java    |  12 +-
 .../metadata/AgentAlertDefinitionsTest.java     |   6 +-
 .../server/orm/dao/AlertDefinitionDAOTest.java  |   7 +-
 .../state/alerts/AlertReceivedListenerTest.java |  16 +-
 .../alerts/AlertStateChangedEventTest.java      |   4 +-
 53 files changed, 1444 insertions(+), 1142 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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 f5fb6e9..fecaedc 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
@@ -237,6 +237,11 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new RootServiceComponentResourceDefinition();
         break;
 
+      case RootServiceComponentConfiguration:
+        resourceDefinition = new SimpleResourceDefinition(Resource.Type.RootServiceComponentConfiguration,
+            "configuration", "configurations");
+        break;
+
       case RootServiceHostComponent:
         resourceDefinition = new RootServiceHostComponentResourceDefinition();
         break;
@@ -471,10 +476,6 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
       case RemoteCluster:
         resourceDefinition = new RemoteClusterResourceDefinition();
         break;
-      case AmbariConfiguration:
-        resourceDefinition = new SimpleResourceDefinition(Resource.Type.AmbariConfiguration, "ambariconfiguration", "ambariconfigurations");
-
-        break;
 
       default:
         throw new IllegalArgumentException("Unsupported resource type: " + type);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java
index e8cb570..1c036e4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.server.api.resources;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 import org.apache.ambari.server.controller.spi.Resource;
@@ -44,10 +45,12 @@ public class RootServiceComponentResourceDefinition extends
   public String getSingularName() {
     return "component";
   }
-  
+
   @Override
   public Set<SubResourceDefinition> getSubResourceDefinitions() {
-    return Collections.singleton(new SubResourceDefinition(
-        Resource.Type.RootServiceHostComponent, Collections.singleton(Resource.Type.Host), true));
+    Set<SubResourceDefinition> definitions = new HashSet<>();
+    definitions.add(new SubResourceDefinition(Resource.Type.RootServiceHostComponent, Collections.singleton(Resource.Type.Host), true));
+    definitions.add(new SubResourceDefinition(Resource.Type.RootServiceComponentConfiguration));
+    return definitions;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
deleted file mode 100644
index 2dca9f5..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationRequestSwagger.java
+++ /dev/null
@@ -1,37 +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;
-
-import java.util.Map;
-
-import org.apache.ambari.server.controller.ApiModel;
-
-import io.swagger.annotations.ApiModelProperty;
-
-/**
- * Request data model for {@link org.apache.ambari.server.api.services.AmbariConfigurationService}
- */
-public interface AmbariConfigurationRequestSwagger extends ApiModel {
-
-  @ApiModelProperty(name = "AmbariConfiguration")
-  AmbariConfigurationRequestInfo getAmbariConfiguration();
-
-  interface AmbariConfigurationRequestInfo {
-    @ApiModelProperty
-    String getCategoryName();
-
-    @ApiModelProperty
-    Map<String, Object> getProperties();
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
deleted file mode 100644
index c55ac1d..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationResponseSwagger.java
+++ /dev/null
@@ -1,40 +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;
-
-import java.util.Map;
-
-import org.apache.ambari.server.controller.ApiModel;
-
-import io.swagger.annotations.ApiModelProperty;
-
-/**
- * Response data model for {@link org.apache.ambari.server.api.services.AmbariConfigurationService}
- */
-public interface AmbariConfigurationResponseSwagger extends ApiModel {
-
-  @ApiModelProperty(name = "AmbariConfiguration")
-  AmbariConfigurationResponseInfo getAmbariConfigurationResponse();
-
-  interface AmbariConfigurationResponseInfo {
-    @ApiModelProperty
-    Long getId();
-
-    @ApiModelProperty
-    Map<String, Object> getData();
-
-    @ApiModelProperty
-    String getType();
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java
deleted file mode 100644
index 86ed666..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariConfigurationService.java
+++ /dev/null
@@ -1,193 +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;
-
-import java.util.Collections;
-
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.http.HttpStatus;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-
-/**
- * Rest endpoint for managing ambari configurations. Supports CRUD operations.
- * Ambari configurations are resources that relate to the ambari server instance even before a cluster is provisioned.
- *
- * Ambari configuration resources may be shared with components and services in the cluster
- * (by recommending them as default values)
- *
- * Eg. LDAP configuration is stored as AmbariConfiguration.
- * The request payload has the form:
- *
- * <pre>
- *      {
- *        "AmbariConfiguration": {
- *          "category": "ldap-configuration",
- *          "properties": {
- *             "authentication.ldap.primaryUrl": "localhost:33389"
- *             "authentication.ldap.secondaryUrl": "localhost:333"
- *             "authentication.ldap.baseDn": "dc=ambari,dc=apache,dc=org"
- *             // ......
- *          }
- *        }
- *      }
- * </pre>
- */
-@Path("/ambariconfigs/")
-@Api(value = "Ambari Configurations", description = "Endpoint for Ambari configuration related operations")
-public class AmbariConfigurationService extends BaseService {
-
-  private static final String AMBARI_CONFIGURATION_REQUEST_TYPE =
-    "org.apache.ambari.server.api.services.AmbariConfigurationRequestSwagger";
-
-  /**
-   * Creates an ambari configuration resource.
-   *
-   * @param body    the payload in json format
-   * @param headers http headers
-   * @param uri     request uri information
-   * @return
-   */
-  @POST
-  @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Creates an ambari configuration resource",
-    nickname = "AmbariConfigurationService#createAmbariConfiguration")
-  @ApiImplicitParams({
-    @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
-  })
-  @ApiResponses({
-    @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION),
-    @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
-    @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
-    @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS),
-    @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
-    @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
-    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
-  })
-  public Response createAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri) {
-    return handleRequest(headers, body, uri, Request.Type.POST, createResource(Resource.Type.AmbariConfiguration,
-      Collections.emptyMap()));
-  }
-
-  @GET
-  @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Retrieve all ambari configuration resources",
-    nickname = "AmbariConfigurationService#getAmbariConfigurations",
-    notes = "Returns all Ambari configurations.",
-    response = AmbariConfigurationResponseSwagger.class,
-    responseContainer = RESPONSE_CONTAINER_LIST)
-  @ApiImplicitParams({
-    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
-      defaultValue = "AmbariConfiguration/properties, AmbariConfiguration/category",
-      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
-    @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
-      defaultValue = "AmbariConfiguration/category",
-      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
-    @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
-    @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
-    @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
-  })
-  @ApiResponses(value = {
-    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
-    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
-  })
-  public Response getAmbariConfigurations(String body, @Context HttpHeaders headers, @Context UriInfo uri) {
-    return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration,
-      Collections.emptyMap()));
-  }
-
-  @GET
-  @Path("{category}")
-  @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Retrieve the details of an ambari configuration resource",
-    nickname = "AmbariConfigurationService#getAmbariConfiguration",
-    response = AmbariConfigurationResponseSwagger.class)
-  @ApiImplicitParams({
-    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*",
-      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
-  })
-  @ApiResponses(value = {
-    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
-    @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
-    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
-  })
-  public Response getAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
-                                         @PathParam("category") String category) {
-    return handleRequest(headers, body, uri, Request.Type.GET, createResource(Resource.Type.AmbariConfiguration,
-      Collections.singletonMap(Resource.Type.AmbariConfiguration, category)));
-  }
-
-  @PUT
-  @Path("{category}")
-  @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Updates ambari configuration resources ",
-    nickname = "AmbariConfigurationService#updateAmbariConfiguration")
-  @ApiImplicitParams({
-    @ApiImplicitParam(dataType = AMBARI_CONFIGURATION_REQUEST_TYPE, paramType = PARAM_TYPE_BODY),
-    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "AmbariConfiguration/*",
-      dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
-  })
-  @ApiResponses({
-    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
-    @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
-    @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
-    @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
-    @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
-    @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
-    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
-  })
-  public Response updateAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
-                                            @PathParam("category") String category) {
-    return handleRequest(headers, body, uri, Request.Type.PUT, createResource(Resource.Type.AmbariConfiguration,
-      Collections.singletonMap(Resource.Type.AmbariConfiguration, category)));
-  }
-
-  @DELETE
-  @Path("{category}")
-  @Produces(MediaType.TEXT_PLAIN)
-  @ApiOperation(value = "Deletes an ambari configuration resource",
-    nickname = "AmbariConfigurationService#deleteAmbariConfiguration")
-  @ApiResponses({
-    @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
-    @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
-    @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
-    @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
-    @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
-  })
-  public Response deleteAmbariConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
-                                            @PathParam("category") String category) {
-    return handleRequest(headers, body, uri, Request.Type.DELETE, createResource(Resource.Type.AmbariConfiguration,
-      Collections.singletonMap(Resource.Type.AmbariConfiguration, category)));
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
index 46ee65a..b1eba8f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
@@ -43,7 +43,7 @@ import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ParentObjectNotFoundException;
 import org.apache.ambari.server.StackAccessException;
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
+import org.apache.ambari.server.controller.RootService;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.customactions.ActionDefinition;
 import org.apache.ambari.server.customactions.ActionDefinitionManager;
@@ -1179,7 +1179,7 @@ public class AmbariMetaInfo {
         String componentName = definition.getComponentName();
 
         // the AMBARI service is special, skip it here
-        if (Services.AMBARI.name().equals(serviceName)) {
+        if (RootService.AMBARI.name().equals(serviceName)) {
           continue;
         }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationRequestSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationRequestSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationRequestSwagger.java
new file mode 100644
index 0000000..dffa125
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationRequestSwagger.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+import java.util.Map;
+
+import org.apache.ambari.server.controller.ApiModel;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Request data model for {@link org.apache.ambari.server.api.services.RootServiceComponentConfigurationService}
+ */
+public interface RootServiceComponentConfigurationRequestSwagger extends ApiModel {
+
+  @ApiModelProperty(name = "Configuration")
+  RootServiceComponentConfigurationRequestInfo getRootServiceComponentConfigurationRequestInfo();
+
+  interface RootServiceComponentConfigurationRequestInfo {
+    @ApiModelProperty
+    String getServiceName();
+
+    @ApiModelProperty
+    String getComponentName();
+
+    @ApiModelProperty
+    String getCategoryName();
+
+    @ApiModelProperty
+    Map<String, String> getProperties();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationResponseSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationResponseSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationResponseSwagger.java
new file mode 100644
index 0000000..fb3c09d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationResponseSwagger.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+import java.util.Map;
+
+import org.apache.ambari.server.controller.ApiModel;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Response data model for {@link org.apache.ambari.server.api.services.RootServiceComponentConfigurationService}
+ */
+public interface RootServiceComponentConfigurationResponseSwagger extends ApiModel {
+
+  @ApiModelProperty(name = "Configuration")
+  RootServiceComponentConfigurationResponseInfo getRootServiceComponentConfigurationResponseInfo();
+
+  interface RootServiceComponentConfigurationResponseInfo {
+    @ApiModelProperty
+    String getServiceName();
+
+    @ApiModelProperty
+    String getComponentName();
+
+    @ApiModelProperty
+    String getCategoryName();
+
+    @ApiModelProperty
+    Map<String, Object> getProperties();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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
new file mode 100644
index 0000000..c7c37a6
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+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.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.http.HttpStatus;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * Rest endpoint for managing ambari root service component configurations. Supports CRUD operations.
+ * Ambari configurations are resources that relate to the ambari server instance even before a cluster is provisioned.
+ * <p>
+ * Ambari configuration resources may be shared with components and services in the cluster
+ * (by recommending them as default values)
+ * <p>
+ * Eg. LDAP configuration is stored as Configuration.
+ * The request payload has the form:
+ * <p>
+ * <pre>
+ *      {
+ *        "Configuration": {
+ *          "service_name": "AMBARI",
+ *          "component_name": "AMBARI_SERVER",
+ *          "category": "ldap-configuration",
+ *          "properties": {
+ *             "authentication.ldap.primaryUrl": "localhost:33389"
+ *             "authentication.ldap.secondaryUrl": "localhost:333"
+ *             "authentication.ldap.baseDn": "dc=ambari,dc=apache,dc=org"
+ *             // ......
+ *          }
+ *        }
+ *      }
+ * </pre>
+ */
+@Api(value = "Root Service Configurations", description = "Endpoint for Ambari root service component configuration related operations")
+public class RootServiceComponentConfigurationService extends BaseService {
+
+  private static final String REQUEST_TYPE =
+      "org.apache.ambari.server.api.services.RootServiceComponentConfigurationRequestSwagger";
+
+  private final String serviceName;
+  private final String componentName;
+
+  public RootServiceComponentConfigurationService(String serviceName, String componentName) {
+    this.serviceName = serviceName;
+    this.componentName = componentName;
+  }
+
+  /**
+   * Creates a root service component configuration resource.
+   *
+   * @param body    the payload in json format
+   * @param headers http headers
+   * @param uri     request uri information
+   * @return
+   */
+  @POST
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Creates a root service component configuration resource",
+      nickname = "RootServiceComponentConfigurationService#createConfiguration")
+  @ApiImplicitParams({
+      @ApiImplicitParam(dataType = REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+      @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+      @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response createConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri) {
+    return handleRequest(headers, body, uri, Request.Type.POST, createResource(null));
+  }
+
+  @GET
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Retrieve all root service component configuration resources",
+      nickname = "RootServiceComponentConfigurationService#getConfigurations",
+      notes = "Returns all root service component configurations.",
+      response = RootServiceComponentConfigurationResponseSwagger.class,
+      responseContainer = RESPONSE_CONTAINER_LIST)
+  @ApiImplicitParams({
+      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
+          defaultValue = "Configuration/properties, Configuration/category, Configuration/component_name, Configuration/service_name",
+          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
+          defaultValue = "Configuration/category",
+          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses(value = {
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+  })
+  public Response getConfigurations(String body, @Context HttpHeaders headers, @Context UriInfo uri) {
+    return handleRequest(headers, body, uri, Request.Type.GET, createResource(null));
+  }
+
+  @GET
+  @Path("{category}")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Retrieve the details of a root service component configuration resource",
+      nickname = "RootServiceComponentConfigurationService#getConfiguration",
+      response = RootServiceComponentConfigurationResponseSwagger.class)
+  @ApiImplicitParams({
+      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "Configuration/*",
+          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses(value = {
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+  })
+  public Response getConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
+                                   @PathParam("category") String category) {
+    return handleRequest(headers, body, uri, Request.Type.GET, createResource(category));
+  }
+
+  @PUT
+  @Path("{category}")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Updates root service component configuration resources ",
+      nickname = "RootServiceComponentConfigurationService#updateConfiguration")
+  @ApiImplicitParams({
+      @ApiImplicitParam(dataType = REQUEST_TYPE, paramType = PARAM_TYPE_BODY),
+      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "Configuration/*",
+          dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+      @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response updateConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
+                                      @PathParam("category") String category) {
+    return handleRequest(headers, body, uri, Request.Type.PUT, createResource(category));
+  }
+
+  @DELETE
+  @Path("{category}")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Deletes a root service component configuration resource",
+      nickname = "RootServiceComponentConfigurationService#deleteConfiguration")
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response deleteConfiguration(String body, @Context HttpHeaders headers, @Context UriInfo uri,
+                                      @PathParam("category") String category) {
+    return handleRequest(headers, body, uri, Request.Type.DELETE, createResource(category));
+  }
+
+  ResourceInstance createResource(String categoryName) {
+    Map<Resource.Type, String> mapIds = new HashMap<>();
+    mapIds.put(Resource.Type.RootService, serviceName);
+    mapIds.put(Resource.Type.RootServiceComponent, componentName);
+    mapIds.put(Resource.Type.RootServiceComponentConfiguration, categoryName);
+
+    return createResource(Resource.Type.RootServiceComponentConfiguration, mapIds);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java
index 5afb7dc..1ab2797 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java
@@ -297,6 +297,13 @@ public class RootServiceService extends BaseService {
     return handleRequest(headers, body, ui, Request.Type.GET, resource);
   }
 
+  @Path("{serviceName}/components/{componentName}/configurations")
+  public RootServiceComponentConfigurationService getAmbariServerConfigurationHandler(@Context javax.ws.rs.core.Request request,
+                                                                                      @PathParam("serviceName") String serviceName,
+                                                                                      @PathParam("componentName") String componentName) {
+    return new RootServiceComponentConfigurationService(serviceName, componentName);
+  }
+
   protected ResourceInstance createServiceResource(String serviceName) {
     Map<Resource.Type, String> mapIds = Collections.singletonMap(Resource.Type.RootService, serviceName);
     return createResource(Resource.Type.RootService, mapIds);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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
index e9f0b1e..7bac65e 100644
--- 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
@@ -26,7 +26,7 @@ public class AmbariConfiguration {
    */
   private String type;
 
-  private Map<String, Object> properties = null;
+  private Map<String, String> properties = null;
 
   public String getType() {
     return type;
@@ -36,11 +36,11 @@ public class AmbariConfiguration {
     this.type = type;
   }
 
-  public Map<String, Object> getProperties() {
+  public Map<String, String> getProperties() {
     return properties;
   }
 
-  public void setProperties(Map<String, Object> data) {
+  public void setProperties(Map<String, String> data) {
     this.properties = data;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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
index 2e478c4..0e065e5 100644
--- 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
@@ -22,7 +22,7 @@ import com.google.gson.annotations.SerializedName;
  */
 public class LdapConfigurationRequest {
 
-  @SerializedName("AmbariConfiguration")
+  @SerializedName("Configuration")
   private AmbariConfiguration ambariConfiguration;
 
   @SerializedName("RequestInfo")

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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
index 00c13f6..22784cd 100644
--- 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
@@ -40,7 +40,7 @@ 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.AmbariConfigurationService;
+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;
@@ -64,7 +64,7 @@ import com.google.common.collect.Sets;
  */
 @StaticallyInject
 @Path("/ldapconfigs/")
-public class LdapConfigurationService extends AmbariConfigurationService {
+public class LdapConfigurationService extends BaseService {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationService.class);
 
@@ -133,7 +133,7 @@ public class LdapConfigurationService extends AmbariConfigurationService {
   }
 
   private void setResult(Set<String> groups, Result result) {
-    Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
+    Resource resource = new ResourceImpl(Resource.Type.RootServiceComponentConfiguration);
     resource.setProperty("groups", groups);
     result.getResultTree().addChild(resource, "payload");
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/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 91edf86..17591ec 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
@@ -45,6 +45,8 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 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.spi.Resource;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.utils.DateUtils;
@@ -84,7 +86,9 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
       + ",services/configurations/dependencies/StackConfigurationDependency/dependency_name"
       + ",services/configurations/dependencies/StackConfigurationDependency/dependency_type,services/configurations/StackConfigurations/type"
       + "&services/StackServices/service_name.in(%s)";
-  private static final String GET_LDAP_CONFIG_URI = "/api/v1/configurations?AmbariConfiguration/type=ldap&fields=AmbariConfiguration/*";
+  private static final String GET_AMBARI_LDAP_CONFIG_URI = "/api/v1/services/AMBARI/components/AMBARI_SERVER/configurations" +
+      "?Configuration/category=ldap-configuration" +
+      "&fields=Configuration/properties";
   private static final String SERVICES_PROPERTY = "services";
   private static final String SERVICES_COMPONENTS_PROPERTY = "components";
   private static final String CONFIG_GROUPS_PROPERTY = "config-groups";
@@ -96,7 +100,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
   private static final String CHANGED_CONFIGURATIONS_PROPERTY = "changed-configurations";
   private static final String USER_CONTEXT_PROPERTY = "user-context";
   private static final String AMBARI_SERVER_CONFIGURATIONS_PROPERTY = "ambari-server-properties";
-  protected static final String LDAP_CONFIGURATION_PROPERTY = "ldap-configuration";
+  static final String LDAP_CONFIGURATION_PROPERTY = "ldap-configuration";
 
   private File recommendationsDir;
   private String recommendationsArtifactsLifetime;
@@ -176,17 +180,18 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
 
   /**
    * Retrieves the LDAP configuration if exists and adds it to services.json
+   *
    * @param root The JSON document that will become service.json when passed to the stack advisor engine
    * @throws StackAdvisorException
    * @throws IOException
    */
-  protected void populateLdapConfiguration(ObjectNode root) throws StackAdvisorException, IOException {
-    Response response = handleRequest(null, null, new LocalUriInfo(GET_LDAP_CONFIG_URI), Request.Type.GET,
+   void populateLdapConfiguration(ObjectNode root) throws StackAdvisorException, IOException {
+    Response response = handleRequest(null, null, new LocalUriInfo(GET_AMBARI_LDAP_CONFIG_URI), Request.Type.GET,
         createConfigResource());
 
     if (response.getStatus() != Status.OK.getStatusCode()) {
       String message = String.format(
-          "Error occured during retrieving ldap configuration, status=%s, response=%s",
+          "Error occurred during retrieving ldap configuration, status=%s, response=%s",
           response.getStatus(), (String) response.getEntity());
       LOG.warn(message);
       throw new StackAdvisorException(message);
@@ -198,25 +203,28 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
     }
 
     JsonNode ldapConfigRoot = mapper.readTree(ldapConfigJSON);
-    ArrayNode ldapConfigs = ((ArrayNode)ldapConfigRoot.get("items"));
+    ArrayNode ldapConfigs = ((ArrayNode) ldapConfigRoot.get("items"));
     int numConfigs = ldapConfigs.size();
-    // Zero or one config may exist
-    switch (numConfigs) {
-      case 0:
-        LOG.debug("No LDAP config is stored in the DB");
-        break;
-      case 1:
-        ArrayNode ldapConfigData = (ArrayNode)ldapConfigs.get(0).get("AmbariConfiguration").get("data");
-        if (ldapConfigData.size() == 0) {
-          throw new StackAdvisorException("No configuration data for LDAP configuration.");
-        }
-        if (ldapConfigData.size() > 1) {
-          throw new StackAdvisorException("Ambigous configuration data for LDAP configuration.");
-        }
-        root.put(LDAP_CONFIGURATION_PROPERTY, ldapConfigData.get(0));
-        break;
-      default:
-        throw new StackAdvisorException(String.format("Multiple (%s) LDAP configs are found in the DB.", numConfigs));
+
+    if (numConfigs == 1) {
+      JsonNode ldapConfigItem = ldapConfigs.get(0);
+      if (ldapConfigItem == null) {
+        throw new StackAdvisorException("Unexpected JSON document encountered: missing data");
+      }
+
+      JsonNode ldapConfiguration = ldapConfigItem.get("Configuration");
+      if (ldapConfiguration == null) {
+        throw new StackAdvisorException("Unexpected JSON document encountered: missing the Configuration object");
+      }
+
+      JsonNode ldapConfigurationProperties = ldapConfiguration.get("properties");
+      if (ldapConfigurationProperties == null) {
+        throw new StackAdvisorException("Unexpected JSON document encountered: missing the Configuration/properties object");
+      }
+
+      root.put(LDAP_CONFIGURATION_PROPERTY, ldapConfigurationProperties);
+    } else if (numConfigs > 1) {
+      throw new StackAdvisorException(String.format("Multiple (%s) LDAP configs are found in the DB.", numConfigs));
     }
   }
 
@@ -486,8 +494,12 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
     return createResource(Resource.Type.Host, mapIds);
   }
 
-  protected ResourceInstance createConfigResource() {
-    return createResource(Resource.Type.AmbariConfiguration, new HashMap<>());
+  private ResourceInstance createConfigResource() {
+    Map<Resource.Type, String> mapIds = new HashMap<>();
+    mapIds.put(Resource.Type.RootService, RootService.AMBARI.name());
+    mapIds.put(Resource.Type.RootServiceComponent, RootComponent.AMBARI_SERVER.name());
+
+    return createResource(Resource.Type.RootServiceComponentConfiguration, mapIds);
   }
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 1425e1b..ed7513f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -63,7 +63,6 @@ import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.configuration.Configuration.ConnectionPoolType;
 import org.apache.ambari.server.configuration.Configuration.DatabaseType;
 import org.apache.ambari.server.controller.internal.AlertTargetResourceProvider;
-import org.apache.ambari.server.controller.internal.AmbariConfigurationResourceProvider;
 import org.apache.ambari.server.controller.internal.ClusterStackVersionResourceProvider;
 import org.apache.ambari.server.controller.internal.ComponentResourceProvider;
 import org.apache.ambari.server.controller.internal.CredentialResourceProvider;
@@ -73,6 +72,7 @@ import org.apache.ambari.server.controller.internal.HostResourceProvider;
 import org.apache.ambari.server.controller.internal.KerberosDescriptorResourceProvider;
 import org.apache.ambari.server.controller.internal.MemberResourceProvider;
 import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider;
+import org.apache.ambari.server.controller.internal.RootServiceComponentConfigurationResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
 import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
 import org.apache.ambari.server.controller.internal.ViewInstanceResourceProvider;
@@ -471,10 +471,10 @@ public class ControllerModule extends AbstractModule {
         .implement(ResourceProvider.class, Names.named("credential"), CredentialResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("kerberosDescriptor"), KerberosDescriptorResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("upgrade"), UpgradeResourceProvider.class)
-        .implement(ResourceProvider.class, Names.named("ambariConfiguration"), AmbariConfigurationResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("clusterStackVersion"), ClusterStackVersionResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("alertTarget"), AlertTargetResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("viewInstance"), ViewInstanceResourceProvider.class)
+        .implement(ResourceProvider.class, Names.named("rootServiceHostComponentConfiguration"), RootServiceComponentConfigurationResourceProvider.class)
         .build(ResourceProviderFactory.class));
 
     install(new FactoryModuleBuilder().implement(

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java
index d9a585f..1ffe841 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java
@@ -24,7 +24,6 @@ import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.HostNotFoundException;
-import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
 import org.apache.ambari.server.controller.internal.RequestOperationLevel;
 import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.controller.spi.Resource;
@@ -265,7 +264,7 @@ public class MaintenanceStateHelper {
     }
 
     // the AMBARI service is not a real service; it's never in MM
-    if( StringUtils.equals(Services.AMBARI.name(), serviceName)){
+    if( StringUtils.equals(RootService.AMBARI.name(), serviceName)){
       return MaintenanceState.OFF;
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
index 711ae10..f6ca16b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
@@ -68,8 +68,8 @@ public interface ResourceProviderFactory {
   @Named("upgrade")
   UpgradeResourceProvider getUpgradeResourceProvider(AmbariManagementController managementController);
 
-  @Named("ambariConfiguration")
-  ResourceProvider getAmbariConfigurationResourceProvider();
+  @Named("rootServiceHostComponentConfiguration")
+  ResourceProvider getRootServiceHostComponentConfigurationResourceProvider();
 
   @Named("clusterStackVersion")
   ClusterStackVersionResourceProvider getClusterStackVersionResourceProvider(AmbariManagementController managementController);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/RootComponent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/RootComponent.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootComponent.java
new file mode 100644
index 0000000..74cdfcf
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootComponent.java
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * RootComponent is an enumeration of root-level components.
+ */
+public enum RootComponent {
+  AMBARI_SERVER,
+  AMBARI_AGENT
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/RootService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/RootService.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootService.java
new file mode 100644
index 0000000..22f571d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootService.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * RootService is an enumeration of root-level services.
+ */
+public enum RootService {
+  AMBARI(RootComponent.values());
+
+  private final RootComponent[] components;
+
+  RootService(RootComponent[] components) {
+    this.components = components;
+  }
+
+  public RootComponent[] getComponents() {
+    return components;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java
index ad9ed20..63d41fd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java
@@ -62,9 +62,9 @@ public class RootServiceResponseFactory extends
       serviceName = request.getServiceName();
 
     if (serviceName != null) {
-      Services service;
+      RootService service;
       try {
-        service = Services.valueOf(serviceName);
+        service = RootService.valueOf(serviceName);
       }
       catch (IllegalArgumentException ex) {
         throw new ObjectNotFoundException("Root service name: " + serviceName);
@@ -74,7 +74,7 @@ public class RootServiceResponseFactory extends
     } else {
       response = new HashSet<>();
       
-      for (Services service: Services.values())    
+      for (RootService service: RootService.values())
         response.add(new RootServiceResponse(service.toString()));
     }    
     return response;
@@ -87,10 +87,10 @@ public class RootServiceResponseFactory extends
 
     String serviceName = request.getServiceName();
     String componentName = request.getComponentName();
-    Services service;
+    RootService service;
 
     try {
-      service = Services.valueOf(serviceName);
+      service = RootService.valueOf(serviceName);
     }
     catch (IllegalArgumentException ex) {
       throw new ObjectNotFoundException("Root service name: " + serviceName);
@@ -100,9 +100,9 @@ public class RootServiceResponseFactory extends
     }
     
     if (componentName != null) {
-      Components component;
+      RootComponent component;
       try {
-        component = Components.valueOf(componentName);
+        component = RootComponent.valueOf(componentName);
         if (!ArrayUtils.contains(service.getComponents(), component))
           throw new ObjectNotFoundException("No component name: " + componentName + "in service: " + serviceName);
       }
@@ -114,7 +114,7 @@ public class RootServiceResponseFactory extends
                                        getComponentProperties(componentName)));
     } else {
     
-      for (Components component: service.getComponents())    
+      for (RootComponent component: service.getComponents())
         response.add(new RootServiceComponentResponse(serviceName, component.toString(),
                      getComponentVersion(component.name(), null),
                      getComponentProperties(component.name())));
@@ -123,7 +123,7 @@ public class RootServiceResponseFactory extends
   }
 
   private String getComponentVersion(String componentName, HostResponse host) {
-    Components component = Components.valueOf(componentName);
+    RootComponent component = RootComponent.valueOf(componentName);
     String componentVersion;
       
     switch (component) {
@@ -150,10 +150,10 @@ public class RootServiceResponseFactory extends
     
     Map<String, String> response;
     Set<String> propertiesToHideInResponse;
-    Components component = null;
+    RootComponent component = null;
 
     if (componentName != null) {
-      component = Components.valueOf(componentName);
+      component = RootComponent.valueOf(componentName);
       
       switch (component) {
       case AMBARI_SERVER:
@@ -176,24 +176,6 @@ public class RootServiceResponseFactory extends
     return response;
   }
 
-  
-  public enum Services {
-    AMBARI(Components.values());
-    private Components[] components;
-
-    Services(Components[] components) {
-      this.components = components;
-    }
-
-    public Components[] getComponents() {
-      return components;
-    }
-  }
-  
-  public enum Components {
-    AMBARI_SERVER, AMBARI_AGENT
-  }
-
   @Override
   public Set<RootServiceHostComponentResponse> getRootServiceHostComponent(RootServiceHostComponentRequest request, Set<HostResponse> hosts) throws AmbariException {
     Set<RootServiceHostComponentResponse> response = new HashSet<>();
@@ -208,7 +190,7 @@ public class RootServiceResponseFactory extends
       Set<HostResponse> filteredHosts = new HashSet<>(hosts);
       
       //Make some filtering of hosts if need
-      if (component.getComponentName().equals(Components.AMBARI_SERVER.name())) {
+      if (component.getComponentName().equals(RootComponent.AMBARI_SERVER.name())) {
         CollectionUtils.filter(filteredHosts, new Predicate() {
           @Override
           public boolean evaluate(Object arg0) {
@@ -220,7 +202,7 @@ public class RootServiceResponseFactory extends
       
       for (HostResponse host : filteredHosts) {
         String state;
-        if (component.getComponentName().equals(Components.AMBARI_SERVER.name())) {
+        if (component.getComponentName().equals(RootComponent.AMBARI_SERVER.name())) {
           state = RUNNING_STATE;
         } else {
           state = host.getHostState().toString();

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index 1dc0841..cc2548c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -206,6 +206,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
         return new RootServiceResourceProvider(propertyIds, keyPropertyIds, managementController);
       case RootServiceComponent:
         return new RootServiceComponentResourceProvider(propertyIds, keyPropertyIds, managementController);
+      case RootServiceComponentConfiguration:
+        return resourceProviderFactory.getRootServiceHostComponentConfigurationResourceProvider();
       case RootServiceHostComponent:
         return new RootServiceHostComponentResourceProvider(propertyIds, keyPropertyIds, managementController);
       case ConfigGroup:
@@ -254,8 +256,6 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
         return new ClusterKerberosDescriptorResourceProvider(managementController);
       case LoggingQuery:
         return new LoggingResourceProvider(propertyIds, keyPropertyIds, managementController);
-      case AmbariConfiguration:
-        return resourceProviderFactory.getAmbariConfigurationResourceProvider();
       case AlertTarget:
         return resourceProviderFactory.getAlertTargetResourceProvider();
       case ViewInstance:

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f2743b5/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java
deleted file mode 100644
index a24400d..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariConfigurationResourceProvider.java
+++ /dev/null
@@ -1,302 +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.controller.internal;
-
-import java.util.Arrays;
-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.spi.NoSuchParentResourceException;
-import org.apache.ambari.server.controller.spi.NoSuchResourceException;
-import org.apache.ambari.server.controller.spi.Predicate;
-import org.apache.ambari.server.controller.spi.Request;
-import org.apache.ambari.server.controller.spi.RequestStatus;
-import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
-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;
-
-/**
- * Resource provider for AmbariConfiguration resources.
- */
-public class AmbariConfigurationResourceProvider extends AbstractAuthorizedResourceProvider {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariConfigurationResourceProvider.class);
-
-  static final String AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID = PropertyHelper.getPropertyId("AmbariConfiguration", "category");
-  static final String AMBARI_CONFIGURATION_PROPERTIES_PROPERTY_ID = PropertyHelper.getPropertyId("AmbariConfiguration", "properties");
-
-  private static final Set<String> PROPERTIES = Collections.unmodifiableSet(
-      new HashSet<>(Arrays.asList(
-          AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID,
-          AMBARI_CONFIGURATION_PROPERTIES_PROPERTY_ID)
-      )
-  );
-
-  private static final Map<Resource.Type, String> PK_PROPERTY_MAP = Collections.unmodifiableMap(
-      Collections.singletonMap(Resource.Type.AmbariConfiguration, AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID)
-  );
-
-  private static final Set<String> PK_PROPERTY_IDS = Collections.unmodifiableSet(
-      new HashSet<>(PK_PROPERTY_MAP.values())
-  );
-
-  @Inject
-  private AmbariConfigurationDAO ambariConfigurationDAO;
-
-  @Inject
-  private AmbariEventPublisher publisher;
-
-  public AmbariConfigurationResourceProvider() {
-    super(PROPERTIES, PK_PROPERTY_MAP);
-
-    Set<RoleAuthorization> authorizations = EnumSet.of(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION);
-    setRequiredCreateAuthorizations(authorizations);
-    setRequiredDeleteAuthorizations(authorizations);
-    setRequiredUpdateAuthorizations(authorizations);
-    setRequiredGetAuthorizations(authorizations);
-  }
-
-  @Override
-  protected Set<String> getPKPropertyIds() {
-    return PK_PROPERTY_IDS;
-  }
-
-  @Override
-  public RequestStatus createResourcesAuthorized(Request request)
-      throws SystemException, UnsupportedPropertyException, ResourceAlreadyExistsException, NoSuchParentResourceException {
-
-    createOrAddProperties(null, request.getProperties(), true);
-
-    return getRequestStatus(null);
-  }
-
-  @Override
-  protected Set<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
-      UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
-
-    return getResources(new Command<Set<Resource>>() {
-      @Override
-      public Set<Resource> invoke() throws AmbariException {
-        Set<Resource> resources = new HashSet<>();
-        Set<String> requestedIds = getRequestPropertyIds(request, predicate);
-
-        if (CollectionUtils.isEmpty(requestedIds)) {
-          requestedIds = PROPERTIES;
-        }
-
-        if (predicate == null) {
-          Set<Resource> _resources = getAmbariConfigurationResources(requestedIds, null);
-          if (!CollectionUtils.isEmpty(_resources)) {
-            resources.addAll(_resources);
-          }
-        } else {
-          for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
-            Set<Resource> _resources = getAmbariConfigurationResources(requestedIds, propertyMap);
-            if (!CollectionUtils.isEmpty(_resources)) {
-              resources.addAll(_resources);
-            }
-          }
-        }
-
-        return resources;
-      }
-    });
-  }
-
-
-  @Override
-  protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
-      UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
-
-    String categoryName = (String) PredicateHelper.getProperties(predicate).get(AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID);
-
-    if (null == categoryName) {
-      LOGGER.debug("No resource id provided in the request");
-    } else {
-      LOGGER.debug("Deleting Ambari configuration with id: {}", categoryName);
-      try {
-        ambariConfigurationDAO.removeByCategory(categoryName);
-      } catch (IllegalStateException e) {
-        throw new NoSuchResourceException(e.getMessage());
-      }
-    }
-
-    // notify subscribers about the configuration changes
-    publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
-    return getRequestStatus(null);
-  }
-
-  @Override
-  protected RequestStatus updateResourcesAuthorized(Request request, Predicate predicate)
-      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
-
-    String categoryName = (String) PredicateHelper.getProperties(predicate).get(AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID);
-    createOrAddProperties(categoryName, request.getProperties(), false);
-
-    return getRequestStatus(null);
-  }
-
-  /**
-   * Retrieves groups of properties from the request data and create or updates them as needed.
-   * <p>
-   * Each group of properties is expected to have a category (<code>AmbariConfiguration/category</code>)
-   * 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).
-   *
-   * @param defaultCategoryName            the default category to use if needed
-   * @param requestProperties              a collection of property maps parsed from the request
-   * @param removePropertiesIfNotSpecified <code>true</code> to remove existing properties that have not been specifed in the request; <code>false</code> append or update the existing set of properties with values from the request
-   * @throws SystemException if an error occurs saving the configuration data
-   */
-  private void createOrAddProperties(String defaultCategoryName, Set<Map<String, Object>> requestProperties, boolean removePropertiesIfNotSpecified)
-      throws SystemException {
-    // set of resource properties (each entry in the set belongs to a different resource)
-    if (requestProperties != null) {
-      for (Map<String, Object> resourceProperties : requestProperties) {
-        Map<String, Map<String, String>> entityMap = parseProperties(defaultCategoryName, resourceProperties);
-
-        if (entityMap != null) {
-          for (Map.Entry<String, Map<String, String>> entry : entityMap.entrySet()) {
-            String categoryName = entry.getKey();
-
-            if (ambariConfigurationDAO.reconcileCategory(categoryName, entry.getValue(), removePropertiesIfNotSpecified)) {
-              // notify subscribers about the configuration changes
-              publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
-            }
-          }
-        }
-      }
-    }
-  }
-
-  private Resource toResource(String categoryName, Map<String, String> properties, Set<String> requestedIds) {
-    Resource resource = new ResourceImpl(Resource.Type.AmbariConfiguration);
-    setResourceProperty(resource, AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID, categoryName, requestedIds);
-    setResourceProperty(resource, AMBARI_CONFIGURATION_PROPERTIES_PROPERTY_ID, properties, requestedIds);
-    return resource;
-  }
-
-  /**
-   * Parse the property map from a request into a map of category names to maps of property names and values.
-   *
-   * @param defaultCategoryName the default category name to use if one is not found in the map of properties
-   * @param resourceProperties  a map of properties from a request item
-   * @return a map of category names to maps of name/value pairs
-   * @throws SystemException if an issue with the data is determined
-   */
-  private Map<String, Map<String, String>> parseProperties(String defaultCategoryName, Map<String, Object> resourceProperties) throws SystemException {
-    String categoryName = null;
-    Map<String, String> properties = new HashMap<>();
-
-    for (Map.Entry<String, Object> entry : resourceProperties.entrySet()) {
-      String propertyName = entry.getKey();
-
-      if (AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID.equals(propertyName)) {
-        if (entry.getValue() instanceof String) {
-          categoryName = (String) entry.getValue();
-        }
-      } else {
-        String propertyCategory = PropertyHelper.getPropertyCategory(entry.getKey());
-        if ((propertyCategory != null) && propertyCategory.equals(AMBARI_CONFIGURATION_PROPERTIES_PROPERTY_ID)) {
-          String name = PropertyHelper.getPropertyName(entry.getKey());
-          Object value = entry.getValue();
-          properties.put(name, (value == null) ? null : value.toString());
-        }
-      }
-    }
-
-    if (categoryName == null) {
-      categoryName = defaultCategoryName;
-    }
-
-    if (StringUtils.isEmpty(categoryName)) {
-      throw new SystemException("The configuration type must be set");
-    }
-
-    if (properties.isEmpty()) {
-      throw new SystemException("The configuration properties must be set");
-    }
-
-    return Collections.singletonMap(categoryName, properties);
-  }
-
-  private Set<Resource> getAmbariConfigurationResources(Set<String> requestedIds, Map<String, Object> propertyMap) {
-    Set<Resource> resources = new HashSet<>();
-
-    String categoryName = getStringProperty(propertyMap, AMBARI_CONFIGURATION_CATEGORY_PROPERTY_ID);
-
-    List<AmbariConfigurationEntity> entities = (categoryName == null)
-        ? ambariConfigurationDAO.findAll()
-        : ambariConfigurationDAO.findByCategory(categoryName);
-
-    if (entities != null) {
-      Map<String, Map<String, String>> 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());
-      }
-
-      for (Map.Entry<String, Map<String, String>> entry : configurations.entrySet()) {
-        resources.add(toResource(entry.getKey(), entry.getValue(), requestedIds));
-      }
-    }
-
-    return resources;
-  }
-
-  private String getStringProperty(Map<String, Object> propertyMap, String propertyId) {
-    String value = null;
-
-    if (propertyMap != null) {
-      Object o = propertyMap.get(propertyId);
-      if (o instanceof String) {
-        value = (String) o;
-      }
-    }
-
-    return value;
-  }
-}