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

ambari git commit: AMBARI-22355 : New endpoint at ServiceLevel for configurations - POST, GET (mradhakrishnan)

Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-14714 527c4a2d7 -> 5301b3f5c


AMBARI-22355 : New endpoint at ServiceLevel for configurations - POST, GET (mradhakrishnan)


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

Branch: refs/heads/branch-feature-AMBARI-14714
Commit: 5301b3f5c8d5ab826a89d83968cb64642d8347e9
Parents: 527c4a2
Author: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Authored: Wed Nov 8 09:48:20 2017 -0800
Committer: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Committed: Wed Nov 8 09:48:20 2017 -0800

----------------------------------------------------------------------
 .../resources/ServiceResourceDefinition.java    |   2 +-
 .../api/services/ConfigurationService.java      |  36 ++++-
 .../server/api/services/ServiceService.java     |  13 ++
 .../controller/AmbariManagementController.java  |   2 +-
 .../AmbariManagementControllerImpl.java         | 130 +++++++++++++------
 .../server/controller/ConfigurationRequest.java |  40 +++++-
 .../controller/ConfigurationResponse.java       |  66 ++++++++++
 .../internal/ConfigurationResourceProvider.java | 100 ++++++++++++--
 .../server/orm/dao/ClusterServiceDAO.java       |  16 +++
 .../orm/entities/ClusterConfigEntity.java       |  11 ++
 .../orm/entities/ClusterServiceEntity.java      |  10 +-
 .../org/apache/ambari/server/state/Cluster.java |  38 ++++++
 .../ambari/server/state/ConfigFactory.java      |   2 +-
 .../ambari/server/state/ConfigHelper.java       |   4 +-
 .../apache/ambari/server/state/ConfigImpl.java  |  15 ++-
 .../server/state/cluster/ClusterImpl.java       | 112 +++++++++++++++-
 .../state/configgroup/ConfigGroupImpl.java      |   3 +-
 .../server/upgrade/AbstractUpgradeCatalog.java  |   3 +-
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |   2 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   2 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   2 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   2 +
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |   2 +
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   2 +
 24 files changed, 546 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java
index 0009c70..5f6b6ba 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java
@@ -54,7 +54,7 @@ public class ServiceResourceDefinition extends BaseResourceDefinition {
     subs.add(new SubResourceDefinition(Resource.Type.Alert));
     //todo: dynamic sub-resource definition
     subs.add(new SubResourceDefinition(Resource.Type.Artifact));
-
+    subs.add(new SubResourceDefinition(Resource.Type.Configuration));
     return subs;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java
index 0eb8bd6..79128a2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java
@@ -44,14 +44,38 @@ public class ConfigurationService extends BaseService {
   private String m_clusterName;
 
   /**
+   * Parent service group name.
+   */
+  private String m_serviceGroupName = null;
+
+  /**
+   * Parent service name.
+   */
+  private String m_serviceName = null;
+
+
+  /**
    * Constructor.
    *
-   * @param clusterName cluster id
+   * @param clusterName cluster name
    */
   public ConfigurationService(String clusterName) {
     m_clusterName = clusterName;
   }
 
+  /**
+   * Constructor.
+   *
+   * @param clusterName cluster name
+   * @param serviceGroupName service group name
+   * @param serviceName service name
+   */
+  public ConfigurationService(String clusterName, String serviceGroupName, String serviceName) {
+    m_clusterName = clusterName;
+    m_serviceGroupName = serviceGroupName;
+    m_serviceName = serviceName;
+  }
+
   @Path("service_config_versions")
   public ServiceConfigVersionService getServiceConfigVersionService() {
     return new ServiceConfigVersionService(m_clusterName);
@@ -68,7 +92,7 @@ public class ConfigurationService extends BaseService {
   @GET @ApiIgnore // until documented
   @Produces("text/plain")
   public Response getConfigurations(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(headers, body, ui, Request.Type.GET, createConfigurationResource(m_clusterName));
+    return handleRequest(headers, body, ui, Request.Type.GET, createConfigurationResource(m_clusterName, m_serviceGroupName, m_serviceName));
   }
 
   /**
@@ -97,7 +121,7 @@ public class ConfigurationService extends BaseService {
   @Produces("text/plain")
   public Response createConfigurations(String body,@Context HttpHeaders headers, @Context UriInfo ui) {
 
-    return handleRequest(headers, body, ui, Request.Type.POST, createConfigurationResource(m_clusterName));
+    return handleRequest(headers, body, ui, Request.Type.POST, createConfigurationResource(m_clusterName, m_serviceGroupName, m_serviceName));
   }
 
   /**
@@ -107,10 +131,14 @@ public class ConfigurationService extends BaseService {
    *
    * @return a service resource instance
    */
-  ResourceInstance createConfigurationResource(String clusterName) {
+  ResourceInstance createConfigurationResource(String clusterName, String serviceGroupName, String serviceName) {
     Map<Resource.Type,String> mapIds = new HashMap<>();
     mapIds.put(Resource.Type.Cluster, clusterName);
     mapIds.put(Resource.Type.Configuration, null);
+    if (serviceName != null && serviceGroupName != null) {
+      mapIds.put(Resource.Type.ServiceGroup, serviceGroupName);
+      mapIds.put(Resource.Type.Service, serviceName);
+    }
 
     return createResource(Resource.Type.Configuration, mapIds);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java
index afdfcc4..1f3332f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java
@@ -718,6 +718,19 @@ public class ServiceService extends BaseService {
   }
 
   /**
+   * Gets the configurations sub-resource.
+   *
+   * @param request      the request
+   * @param serviceName  the serviceName
+   *
+   * @return the configuration service
+   */
+  @Path("{serviceName}/configurations")
+  public ConfigurationService getConfigurationHandler (@Context javax.ws.rs.core.Request request, @PathParam("serviceName") String serviceName) {
+    return new ConfigurationService(m_clusterName, m_serviceGroupName, serviceName);
+  }
+
+  /**
    * Create a service resource instance.
    *
    * @param clusterName         cluster name

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index 358b1bf..86ac3c4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -125,7 +125,7 @@ public interface AmbariManagementController {
    * @return config created
    */
   Config createConfig(Cluster cluster, StackId stackId, String type, Map<String, String> properties,
-                      String versionTag, Map<String, Map<String, String>> propertiesAttributes);
+                      String versionTag, Map<String, Map<String, String>> propertiesAttributes, Long serviceId);
 
   /**
    * Creates users.

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 7f5c051..dc16f22 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -1011,22 +1011,27 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     }
 
     Config config = createConfig(cluster, stackId, request.getType(), requestProperties,
-      request.getVersionTag(), propertiesAttributes);
+      request.getVersionTag(), propertiesAttributes, request.getServiceId() == null? null : request.getServiceId());
 
     LOG.info(MessageFormat.format("Creating configuration with tag ''{0}'' to cluster ''{1}''  for configuration type {2}",
         request.getVersionTag(),
         request.getClusterName(),
         configType));
 
-    return new ConfigurationResponse(cluster.getClusterName(), config);
+    if(request.getServiceId() == null) {
+      return new ConfigurationResponse(cluster.getClusterName(), config);
+    }
+    else {
+      return new ConfigurationResponse(cluster.getClusterName(), config, request.getServiceId(), request.getServiceGroupId());
+    }
   }
 
   @Override
   public Config createConfig(Cluster cluster, StackId stackId, String type, Map<String, String> properties,
-                             String versionTag, Map<String, Map<String, String>> propertiesAttributes) {
+                             String versionTag, Map<String, Map<String, String>> propertiesAttributes, Long serviceId) {
 
     Config config = configFactory.createNew(stackId, cluster, type, versionTag, properties,
-        propertiesAttributes);
+        propertiesAttributes, serviceId);
 
     cluster.addConfig(config);
     return config;
@@ -1470,52 +1475,101 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
     // !!! if only one, then we need full properties
     if (null != request.getType() && null != request.getVersionTag()) {
-      Config config = cluster.getConfig(request.getType(),
-          request.getVersionTag());
-      if (null != config) {
-        ConfigurationResponse response = new ConfigurationResponse(
-            cluster.getClusterName(), config);
-        responses.add(response);
+      ConfigurationResponse response = null;
+      Config config = null;
+      //TODO : Remove after getting rid of cluster configurations
+      if (request.getServiceId() == null) {
+        config = cluster.getConfig(request.getType(),
+                request.getVersionTag());
+        if (null != config) {
+          response = new ConfigurationResponse(
+                  cluster.getClusterName(), config);
+        }
       }
+      else {
+        config = cluster.getConfigByServiceId(request.getType(), request.getVersionTag(), request.getServiceId());
+        if (null != config) {
+          response = new ConfigurationResponse(
+                  cluster.getClusterName(), config, request.getServiceId(), request.getServiceGroupId());
+        }
+      }
+      responses.add(response);
     }
     else {
+      ConfigurationResponse response = null;
       boolean includeProps = request.includeProperties();
+      Map<String, Config> configs = null;
+      //Get by type
       if (null != request.getType()) {
-        Map<String, Config> configs = cluster.getConfigsByType(
-            request.getType());
-
-        if (null != configs) {
-          for (Entry<String, Config> entry : configs.entrySet()) {
-            Config config = entry.getValue();
-            ConfigurationResponse response = new ConfigurationResponse(
-                cluster.getClusterName(), config.getStackId(),
-                request.getType(),
-                config.getTag(), entry.getValue().getVersion(),
-                includeProps ? config.getProperties() : new HashMap<>(),
-                includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
-                config.getPropertiesTypes());
-            responses.add(response);
+        //TODO : Remove after getting rid of cluster configurations
+        if (request.getServiceId() == null) {
+          configs = cluster.getConfigsByType(
+                  request.getType());
+          if (null != configs) {
+            for (Entry<String, Config> entry : configs.entrySet()) {
+              Config config = entry.getValue();
+              response = new ConfigurationResponse(
+                      cluster.getClusterName(), config.getStackId(),
+                      request.getType(),
+                      config.getTag(), entry.getValue().getVersion(),
+                      includeProps ? config.getProperties() : new HashMap<>(),
+                      includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
+                      config.getPropertiesTypes());
+              responses.add(response);
+            }
+          }
+        }
+        else {
+          configs = cluster.getConfigsByServiceIdType(
+                  request.getType(), request.getServiceId());
+          if (null != configs) {
+            for (Entry<String, Config> entry : configs.entrySet()) {
+              Config config = entry.getValue();
+              response = new ConfigurationResponse(
+                      cluster.getClusterName(), config.getStackId(),
+                      request.getType(),
+                      config.getTag(), entry.getValue().getVersion(),
+                      includeProps ? config.getProperties() : new HashMap<>(),
+                      includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
+                      config.getPropertiesTypes(), request.getServiceId(), request.getServiceGroupId());
+              responses.add(response);
+            }
           }
         }
-      } else {
-        // !!! all configuration
-        Collection<Config> all = cluster.getAllConfigs();
-
-        for (Config config : all) {
-          ConfigurationResponse response = new ConfigurationResponse(
-              cluster.getClusterName(), config.getStackId(), config.getType(),
-              config.getTag(), config.getVersion(),
-              includeProps ? config.getProperties() : new HashMap<>(),
-              includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
-              config.getPropertiesTypes());
 
-          responses.add(response);
+      }
+      else {
+        // !!! all configuration
+        Collection<Config> all = null;
+        //TODO : Remove after getting rid of cluster configurations
+        if (request.getServiceId() == null) {
+          all = cluster.getAllConfigs();
+          for (Config config : all) {
+            response = new ConfigurationResponse(
+                    cluster.getClusterName(), config.getStackId(), config.getType(),
+                    config.getTag(), config.getVersion(),
+                    includeProps ? config.getProperties() : new HashMap<>(),
+                    includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
+                    config.getPropertiesTypes());
+            responses.add(response);
+          }
+        }
+        else {
+          all = cluster.getConfigsByServiceId(request.getServiceId());
+          for (Config config : all) {
+            response = new ConfigurationResponse(
+                    cluster.getClusterName(), config.getStackId(), config.getType(),
+                    config.getTag(), config.getVersion(),
+                    includeProps ? config.getProperties() : new HashMap<>(),
+                    includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
+                    config.getPropertiesTypes(), request.getServiceId(), request.getServiceGroupId());
+            responses.add(response);
+          }
         }
+
       }
     }
-
     return responses;
-
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java
index cf035b0..d26cf16 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java
@@ -36,6 +36,8 @@ public class ConfigurationRequest {
   private boolean selected = true;
   private Map<String, Map<String, String>> configsAttributes;
   private boolean includeProperties;
+  private Long serviceId;
+  private Long serviceGroupId;
 
   public ConfigurationRequest() {
     configs = new HashMap<>();
@@ -46,7 +48,7 @@ public class ConfigurationRequest {
                               String type,
                               String tag,
                               Map<String, String> configs,
-                              Map<String, Map<String, String>> configsAttributes) {
+                              Map<String, Map<String, String>> configsAttributes, Long serviceId, Long serviceGroupId) {
 
     this.clusterName = clusterName;
     this.configs = configs;
@@ -55,6 +57,23 @@ public class ConfigurationRequest {
     this.configs = configs;
     this.configsAttributes = configsAttributes;
     this.includeProperties = (type != null && tag != null);
+    this.serviceId = serviceId == null ? null : serviceId;
+    this.serviceGroupId = serviceGroupId == null ? null : serviceGroupId;
+
+  }
+
+  /**
+   * @return service id
+   */
+  public Long getServiceId() {
+    return serviceId;
+  }
+
+  /**
+   * @param serviceId
+   */
+  public void setServiceId(Long serviceId) {
+    this.serviceId = serviceId;
   }
 
   /**
@@ -121,7 +140,24 @@ public class ConfigurationRequest {
   public void setSelected(boolean selected) {
     this.selected = selected;
   }
-  
+
+
+  /**
+   *
+   * @return serviceGroupId
+   */
+  public Long getServiceGroupId() {
+    return serviceGroupId;
+  }
+
+  /**
+   *
+   * @param serviceGroupId
+   */
+  public void setServiceGroupId(Long serviceGroupId) {
+    this.serviceGroupId = serviceGroupId;
+  }
+
   /**
    * Gets if the configuration is to be selected.
    * @return <code>true</code> if the configuration is selected.

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
index abf2096..cbf6685 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
@@ -43,6 +43,10 @@ public class ConfigurationResponse {
 
   private Long version;
 
+  private Long serviceId;
+
+  private Long serviceGroupId;
+
   private List<Long> serviceConfigVersions;
 
   private Map<String, String> configs;
@@ -94,6 +98,41 @@ public class ConfigurationResponse {
     this(clusterName, config.getStackId(), config.getType(), config.getTag(),
         config.getVersion(), config.getProperties(),
         config.getPropertiesAttributes(), config.getPropertiesTypes());
+
+  }
+
+
+  /**
+   * Constructor.
+   *
+   * @param clusterName
+   * @param config
+   */
+  public ConfigurationResponse(String clusterName, Config config, Long serviceId, Long serviceGroupId) {
+    this(clusterName, config.getStackId(), config.getType(), config.getTag(),
+            config.getVersion(), config.getProperties(),
+            config.getPropertiesAttributes(), config.getPropertiesTypes(), serviceId, serviceGroupId);
+
+  }
+
+  public ConfigurationResponse(String clusterName, StackId stackId,
+                               String type, String versionTag, Long version,
+                               Map<String, String> configs,
+                               Map<String, Map<String, String>> configAttributes,
+                               Map<PropertyInfo.PropertyType, Set<String>> propertiesTypes, Long serviceId, Long serviceGroupId) {
+    this.clusterName = clusterName;
+    this.stackId = stackId;
+    this.configs = configs;
+    this.type = type;
+    this.versionTag = versionTag;
+    this.version = version;
+    this.configs = configs;
+    this.configAttributes = configAttributes;
+    this.propertiesTypes = propertiesTypes;
+    this.serviceId = serviceId;
+    this.serviceGroupId = serviceGroupId;
+    SecretReference.replacePasswordsWithReferences(propertiesTypes, configs, type, version);
+    SecretReference.replacePasswordsWithReferencesForCustomProperties(configAttributes, configs, type, version);
   }
 
   /**
@@ -154,6 +193,22 @@ public class ConfigurationResponse {
     this.version = version;
   }
 
+  public Long getServiceId() {
+    return serviceId;
+  }
+
+  public void setServiceId(Long serviceId) {
+    this.serviceId = serviceId;
+  }
+
+  public Long getServiceGroupId() {
+    return serviceGroupId;
+  }
+
+  public void setServiceGroupId(Long serviceGroupId) {
+    this.serviceGroupId = serviceGroupId;
+  }
+
   /**
    * Gets the Stack ID that this configuration is scoped for.
    *
@@ -190,6 +245,15 @@ public class ConfigurationResponse {
       return false;
     }
 
+    if (serviceId != null ? !serviceId.equals(that.serviceId) : that.serviceId != null) {
+      return false;
+    }
+
+    if (serviceGroupId != null ? !serviceGroupId.equals(that.serviceGroupId) : that.serviceGroupId != null) {
+      return false;
+    }
+
+
     return true;
   }
 
@@ -199,6 +263,8 @@ public class ConfigurationResponse {
     result = 31 * result + (stackId != null ? stackId.hashCode() : 0);
     result = 31 * result + (type != null ? type.hashCode() : 0);
     result = 31 * result + (version != null ? version.hashCode() : 0);
+    result = 31 * result + (serviceId != null ? serviceId.hashCode() : 0);
+    result = 31 * result + (serviceGroupId != null ? serviceGroupId.hashCode() : 0);
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java
index 0f26085..4e70a8e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java
@@ -28,6 +28,7 @@ import java.util.Set;
 import java.util.regex.Pattern;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.StaticallyInject;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.ConfigurationRequest;
 import org.apache.ambari.server.controller.ConfigurationResponse;
@@ -41,12 +42,17 @@ 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.PropertyHelper;
+import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
+import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 
+import com.google.inject.Inject;
+
 /**
  * Resource provider for configuration resources.
  */
+@StaticallyInject
 public class ConfigurationResourceProvider extends
     AbstractControllerResourceProvider {
 
@@ -62,12 +68,21 @@ public class ConfigurationResourceProvider extends
   public static final String CONFIGURATION_CONFIG_TYPE_PROPERTY_ID = PropertyHelper.getPropertyId(null, "type");
   public static final String CONFIGURATION_CONFIG_TAG_PROPERTY_ID = PropertyHelper.getPropertyId(null, "tag");
   public static final String CONFIGURATION_CONFIG_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId(null, "version");
+  public static final String CONFIGURATION_SERVICE_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_name");
+  public static final String CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_group_name");
+  public static final String CONFIGURATION_SERVICE_ID_PROPERTY_ID = PropertyHelper.getPropertyId("Config", "service_id");
+  public static final String CONFIGURATION_SERVICE_GROUP_ID_PROPERTY_ID = PropertyHelper.getPropertyId("Config", "service_group_id");
+
 
   /**
    * The property ids for a configuration resource.
    */
   private static final Set<String> PROPERTY_IDS = new HashSet<>();
 
+  @Inject
+  protected static ClusterServiceDAO clusterServiceDAO;
+
+
   /**
    * The key property ids for a configuration resource.
    */
@@ -80,10 +95,16 @@ public class ConfigurationResourceProvider extends
     PROPERTY_IDS.add(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID);
     PROPERTY_IDS.add(CONFIGURATION_CONFIG_TAG_PROPERTY_ID);
     PROPERTY_IDS.add(CONFIGURATION_CONFIG_VERSION_PROPERTY_ID);
+    PROPERTY_IDS.add(CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(CONFIGURATION_SERVICE_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(CONFIGURATION_SERVICE_GROUP_ID_PROPERTY_ID);
 
     // keys
     KEY_PROPERTY_IDS.put(Resource.Type.Configuration,CONFIGURATION_CONFIG_TYPE_PROPERTY_ID);
     KEY_PROPERTY_IDS.put(Resource.Type.Cluster,CONFIGURATION_CLUSTER_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.Service,CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroup,CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
   }
 
   /**
@@ -92,7 +113,7 @@ public class ConfigurationResourceProvider extends
   private static Set<String> pkPropertyIds =
     new HashSet<>(Arrays.asList(new String[]{
       CONFIGURATION_CLUSTER_NAME_PROPERTY_ID,
-      CONFIGURATION_CONFIG_TYPE_PROPERTY_ID}));
+      CONFIGURATION_CONFIG_TYPE_PROPERTY_ID, CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID, CONFIGURATION_SERVICE_NAME_PROPERTY_ID}));
 
 
   // ----- Constructors ------------------------------------------------------
@@ -122,10 +143,23 @@ public class ConfigurationResourceProvider extends
              ResourceAlreadyExistsException,
              NoSuchParentResourceException {
 
+    Set<Resource> associatedResources = new HashSet<>();
+
     for (Map<String, Object> map : request.getProperties()) {
       String cluster = (String) map.get(CONFIGURATION_CLUSTER_NAME_PROPERTY_ID);
       String type = (String) map.get(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID);
-      String tag  = (String) map.get(CONFIGURATION_CONFIG_TAG_PROPERTY_ID);
+      String tag = (String) map.get(CONFIGURATION_CONFIG_TAG_PROPERTY_ID);
+      String serviceName = null;
+      String serviceGroupName = null;
+      Long serviceId = null;
+      Long serviceGroupId = null;
+      if (map.containsKey(CONFIGURATION_SERVICE_NAME_PROPERTY_ID) && map.containsKey(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID)) {
+        serviceName = (String) map.get(CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+        serviceGroupName = (String) map.get(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
+        ClusterServiceEntity clusterServiceEntity = clusterServiceDAO.findByName(cluster, serviceGroupName, serviceName);
+        serviceId = clusterServiceEntity.getServiceId();
+        serviceGroupId = clusterServiceEntity.getServiceGroupId();
+      }
 
       Map<String, String> configMap = new HashMap<>();
       Map<String, Map<String, String>> configAttributesMap = null;
@@ -136,8 +170,8 @@ public class ConfigurationResourceProvider extends
           configMap.put(PropertyHelper.getPropertyName(entry.getKey()), entry.getValue().toString());
         }
         if (propertyCategory != null
-            && PROPERTIES_ATTRIBUTES_PATTERN.matcher(propertyCategory).matches()
-            && null != entry.getValue()) {
+                && PROPERTIES_ATTRIBUTES_PATTERN.matcher(propertyCategory).matches()
+                && null != entry.getValue()) {
           if (null == configAttributesMap) {
             configAttributesMap = new HashMap<>();
           }
@@ -151,18 +185,35 @@ public class ConfigurationResourceProvider extends
         }
       }
 
-      final ConfigurationRequest configRequest = new ConfigurationRequest(cluster, type, tag, configMap, configAttributesMap);
+      final ConfigurationRequest configRequest = new ConfigurationRequest(cluster, type, tag, configMap, configAttributesMap, serviceId, serviceGroupId);
 
-      createResources(new Command<Void>() {
+      ConfigurationResponse configurationResponse = createResources(new Command<ConfigurationResponse>() {
         @Override
-        public Void invoke() throws AmbariException, AuthorizationException {
-          getManagementController().createConfiguration(configRequest);
-          return null;
+        public ConfigurationResponse invoke() throws AmbariException, AuthorizationException {
+          return getManagementController().createConfiguration(configRequest);
+
         }
       });
 
+      if (configurationResponse != null) {
+        Resource resource = new ResourceImpl(Resource.Type.Configuration);
+        resource.setProperty(CONFIGURATION_CLUSTER_NAME_PROPERTY_ID, configurationResponse.getClusterName());
+        resource.setProperty(CONFIGURATION_STACK_ID_PROPERTY_ID, configurationResponse.getStackId().getStackId());
+        resource.setProperty(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID, configurationResponse.getType());
+        resource.setProperty(CONFIGURATION_CONFIG_TAG_PROPERTY_ID, configurationResponse.getVersionTag());
+        resource.setProperty(CONFIGURATION_CONFIG_VERSION_PROPERTY_ID, configurationResponse.getVersion());
+        if (configurationResponse.getServiceId() != null) {
+          resource.setProperty(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID, serviceGroupName);
+          resource.setProperty(CONFIGURATION_SERVICE_NAME_PROPERTY_ID, serviceName);
+          resource.setProperty(CONFIGURATION_SERVICE_ID_PROPERTY_ID, serviceId);
+          resource.setProperty(CONFIGURATION_SERVICE_GROUP_ID_PROPERTY_ID, serviceGroupId);
+        }
+        associatedResources.add(resource);
+      }
     }
-    return getRequestStatus(null);
+        return getRequestStatus(null, associatedResources);
+
+
   }
 
   @Override
@@ -170,9 +221,16 @@ public class ConfigurationResourceProvider extends
     throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
 
     final Set<ConfigurationRequest> requests = new HashSet<>();
+    String serviceName = null;
+    String serviceGroupName = null;
 
     for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
-      requests.add(getRequest(request, propertyMap));
+      ConfigurationRequest configurationRequest = getRequest(request, propertyMap);
+      if (configurationRequest.getServiceId() != null) {
+        serviceGroupName = (String) propertyMap.get(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
+        serviceName = (String) propertyMap.get(CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+      }
+      requests.add(configurationRequest);
     }
 
     Set<ConfigurationResponse> responses = getResources(new Command<Set<ConfigurationResponse>>() {
@@ -193,6 +251,12 @@ public class ConfigurationResourceProvider extends
       resource.setProperty(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID, response.getType());
       resource.setProperty(CONFIGURATION_CONFIG_TAG_PROPERTY_ID, response.getVersionTag());
       resource.setProperty(CONFIGURATION_CONFIG_VERSION_PROPERTY_ID, response.getVersion());
+      if (response.getServiceId() != null) {
+        resource.setProperty(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID, serviceGroupName );
+        resource.setProperty(CONFIGURATION_SERVICE_NAME_PROPERTY_ID, serviceName );
+        resource.setProperty(CONFIGURATION_SERVICE_ID_PROPERTY_ID, response.getServiceId());
+        resource.setProperty(CONFIGURATION_SERVICE_GROUP_ID_PROPERTY_ID, response.getServiceGroupId());
+      }
 
       if (null != response.getConfigs() && response.getConfigs().size() > 0) {
         Map<String, String> configs = response.getConfigs();
@@ -281,10 +345,22 @@ public class ConfigurationResourceProvider extends
   private ConfigurationRequest getRequest(Request request, Map<String, Object> properties) {
     String type = (String) properties.get(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID);
     String tag  = (String) properties.get(CONFIGURATION_CONFIG_TAG_PROPERTY_ID);
+    String cluster  = (String) properties.get(CONFIGURATION_CLUSTER_NAME_PROPERTY_ID);
+    String serviceName = null;
+    String serviceGroupName = null;
+    Long serviceId = null;
+    Long serviceGroupId = null;
+    if (properties.containsKey(CONFIGURATION_SERVICE_NAME_PROPERTY_ID) && properties.containsKey(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID)) {
+      serviceName = (String) properties.get(CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+      serviceGroupName = (String) properties.get(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
+      ClusterServiceEntity clusterServiceEntity = clusterServiceDAO.findByName(cluster, serviceGroupName, serviceName);
+      serviceId = clusterServiceEntity.getServiceId();
+      serviceGroupId = clusterServiceEntity.getServiceGroupId();
+    }
 
     ConfigurationRequest configRequest = new ConfigurationRequest(
         (String) properties.get(CONFIGURATION_CLUSTER_NAME_PROPERTY_ID),
-        type, tag, new HashMap<>(), new HashMap<>());
+        type, tag, new HashMap<>(), new HashMap<>(), serviceId, serviceGroupId);
 
     Set<String> requestedIds = request.getPropertyIds();
     if (requestedIds.contains("properties") || requestedIds.contains("*")) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
index 0eeb19b..c7032aa 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
@@ -61,6 +61,22 @@ public class ClusterServiceDAO {
   }
 
   @RequiresSession
+  public ClusterServiceEntity findByName(String clusterName, String serviceGroupName, String serviceName) {
+    TypedQuery<ClusterServiceEntity> query = entityManagerProvider.get()
+            .createNamedQuery("clusterServiceByName" , ClusterServiceEntity.class);
+    query.setParameter("clusterName", clusterName);
+    query.setParameter("serviceGroupName", serviceGroupName);
+    query.setParameter("serviceName", serviceName);
+
+    try {
+      return query.getSingleResult();
+    }
+    catch (NoResultException ignored) {
+      return null;
+    }
+  }
+
+  @RequiresSession
   public List<ClusterServiceEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), ClusterServiceEntity.class);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java
index beecf4e..4a0e84c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java
@@ -90,6 +90,17 @@ public class ClusterConfigEntity {
   @Column(name = "cluster_id", nullable = false, insertable = false, updatable = false, length = 10)
   private Long clusterId;
 
+  @Column(name = "service_id", nullable = true)
+  private Long serviceId;
+
+  public Long getServiceId() {
+    return serviceId;
+  }
+
+  public void setServiceId(Long serviceId) {
+    this.serviceId = serviceId;
+  }
+
   @Column(name = "type_name")
   private String type;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
index 976bb67..e5a1618 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
@@ -48,7 +48,15 @@ import javax.persistence.TableGenerator;
       "JOIN clusterService.serviceGroupEntity serviceGroup " +
       "WHERE clusterService.serviceId=:serviceId " +
       "AND  serviceGroup.serviceGroupId=:serviceGroupId " +
-      "AND serviceGroup.clusterId=:clusterId")
+      "AND serviceGroup.clusterId=:clusterId"),
+   @NamedQuery(name = "clusterServiceByName", query =
+     "SELECT clusterService " +
+      "FROM ClusterServiceEntity clusterService " +
+       "JOIN clusterService.serviceGroupEntity serviceGroup " +
+        "JOIN clusterService.clusterEntity clusterEntity " +
+       "WHERE clusterService.serviceName=:serviceName " +
+       "AND  serviceGroup.serviceGroupName=:serviceGroupName " +
+        "AND clusterEntity.clusterName=:clusterName")
 })
 @Entity
 @TableGenerator(name = "service_id_generator",

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
index 27d37e3..f12759e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
@@ -325,6 +325,16 @@ public interface Cluster {
   Map<String, Config> getConfigsByType(String configType);
 
   /**
+   * Gets all configs that match the specified type.  Result is not the
+   * DESIRED configuration for a cluster.
+   *
+   * @param configType the config type to return
+   *        serviceId the serviceid for the config
+   * @return a map of configuration objects that have been set for the given type
+   */
+  Map<String, Config> getConfigsByServiceIdType(String configType, Long serviceId);
+
+  /**
    * Gets all properties types that mach the specified type.
    *
    * @param configType the config type to return
@@ -344,6 +354,18 @@ public interface Cluster {
   Config getConfig(String configType, String versionTag);
 
   /**
+   * Gets the specific config that matches the specified type and tag.  This not
+   * necessarily a DESIRED configuration that applies to a cluster.
+   *
+   * @param configType the config type to find
+   * @param versionTag the config version tag to find
+   * @param serviceId the service for the config
+   * @return a {@link Config} object, or <code>null</code> if the specific type
+   * and version have not been set.
+   */
+  Config getConfigByServiceId(String configType, String versionTag, Long serviceId);
+
+  /**
    * Get latest (including inactive ones) configurations with any of the given types.
    * This method does not take into account the configuration being enabled.
    *
@@ -371,6 +393,15 @@ public interface Cluster {
   void addConfig(Config config);
 
   /**
+   * Sets a specific config.  NOTE:  This is not a DESIRED configuration that
+   * applies to a cluster.
+   *
+   * @param config the config instance to add
+   *        serviceId service id for the config
+   */
+  void addConfig(Config config, Long serviceId);
+
+  /**
    * Gets all configurations defined for a cluster.
    *
    * @return the collection of all configs that have been defined.
@@ -378,6 +409,13 @@ public interface Cluster {
   Collection<Config> getAllConfigs();
 
   /**
+   * Gets all configurations defined for a cluster service.
+   *
+   * @return the collection of all configs that have been defined.
+   */
+  List<Config> getConfigsByServiceId(Long serviceId);
+
+  /**
    * Adds and sets a DESIRED configuration to be applied to a cluster.  There
    * can be only one selected config per type.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java
index 2879345..4c21820 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java
@@ -50,7 +50,7 @@ public interface ConfigFactory {
    * @return
    */
   Config createNew(StackId stackId, Cluster cluster, @Assisted("type") String type, @Assisted("tag") String tag,
-      Map<String, String> map, Map<String, Map<String, String>> mapAttributes);
+      Map<String, String> map, Map<String, Map<String, String>> mapAttributes, Long serviceId);
 
   /**
    * Creates a new {@link Config} object using provided entity

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
index 8c0e656..e999e24 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
@@ -1197,8 +1197,8 @@ public class ConfigHelper {
         }
       }
     }
-
-    return controller.createConfig(cluster, stackId, type, properties, tag, propertyAttributes);
+    //TODO check at the right use case
+    return controller.createConfig(cluster, stackId, type, properties, tag, propertyAttributes, null);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
index 44d76af..2d2e7b8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
@@ -105,16 +105,15 @@ public class ConfigImpl implements Config {
       @Assisted @Nullable Map<String, Map<String, String>> propertiesAttributes,
       ClusterDAO clusterDAO, StackDAO stackDAO,
       Gson gson, AmbariEventPublisher eventPublisher, LockFactory lockFactory) {
-    this(cluster.getDesiredStackVersion(), cluster, type, tag, properties, propertiesAttributes,
+    this(cluster.getDesiredStackVersion(), cluster, type, tag, properties, propertiesAttributes,null,
         clusterDAO, stackDAO, gson, eventPublisher, lockFactory);
   }
 
-
   @AssistedInject
   ConfigImpl(@Assisted @Nullable StackId stackId, @Assisted Cluster cluster, @Assisted("type") String type,
       @Assisted("tag") @Nullable String tag,
       @Assisted Map<String, String> properties,
-      @Assisted @Nullable Map<String, Map<String, String>> propertiesAttributes,
+      @Assisted @Nullable Map<String, Map<String, String>> propertiesAttributes,@Assisted @Nullable Long serviceId,
       ClusterDAO clusterDAO, StackDAO stackDAO,
       Gson gson, AmbariEventPublisher eventPublisher, LockFactory lockFactory) {
 
@@ -150,6 +149,10 @@ public class ConfigImpl implements Config {
     entity.setStack(stackEntity);
     entity.setData(gson.toJson(properties));
 
+    if (null != serviceId) {
+      entity.setServiceId(serviceId);
+    }
+
     if (null != propertiesAttributes) {
       entity.setAttributes(gson.toJson(propertiesAttributes));
     }
@@ -347,7 +350,11 @@ public class ConfigImpl implements Config {
     persistEntitiesInTransaction(entity);
 
     // ensure that the in-memory state of the cluster is kept consistent
-    cluster.addConfig(this);
+    if(entity.getServiceId() == null) {
+      cluster.addConfig(this);
+    }else{
+      cluster.addConfig(this,entity.getServiceId());
+    }
 
     // re-load the entity associations for the cluster
     cluster.refresh();

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index 755a80f..78201f0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -189,6 +189,11 @@ public class ClusterImpl implements Cluster {
   private final ConcurrentMap<String, ConcurrentMap<String, Config>> allConfigs = new ConcurrentHashMap<>();
 
   /**
+   * [ Service -> [ allConfigs ] ]
+   */
+  private final ConcurrentMap<Long, ConcurrentMap<String, ConcurrentMap<String, Config>>>  serviceConfigs = new ConcurrentHashMap<>();
+
+  /**
    * [ ServiceName -> [ ServiceComponentName -> [ HostName -> [ ... ] ] ] ]
    */
   private final ConcurrentMap<String, ConcurrentMap<String, ConcurrentMap<String, ServiceComponentHost>>> serviceComponentHosts = new ConcurrentHashMap<>();
@@ -1402,6 +1407,71 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
+  public Config getConfigByServiceId(String configType, String versionTag, Long serviceId) {
+    clusterGlobalLock.readLock().lock();
+    try {
+      if (!serviceConfigs.containsKey(serviceId)) {
+        return null;
+      }
+      else {
+        ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(serviceId);
+        if (!allServiceConfigs.containsKey(configType)
+                || !allServiceConfigs.get(configType).containsKey(versionTag)) {
+          return null;
+        }
+        return allServiceConfigs.get(configType).get(versionTag);
+      }
+    }
+    finally {
+        clusterGlobalLock.readLock().unlock();
+    }
+  }
+
+  @Override
+  public List<Config> getConfigsByServiceId(Long serviceId) {
+    clusterGlobalLock.readLock().lock();
+    try {
+      if (!serviceConfigs.containsKey(serviceId)) {
+        return null;
+      }
+      else {
+        List<Config> list = new ArrayList<>();
+        ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(serviceId);
+        for (Entry<String, ConcurrentMap<String, Config>> entry : allServiceConfigs.entrySet()) {
+          for (Config config : entry.getValue().values()) {
+            list.add(config);
+          }
+        }
+        return Collections.unmodifiableList(list);
+      }
+    }
+    finally {
+        clusterGlobalLock.readLock().unlock();
+    }
+  }
+
+  @Override
+  public Map<String, Config> getConfigsByServiceIdType(String configType, Long serviceId) {
+    clusterGlobalLock.readLock().lock();
+    try {
+      if (!serviceConfigs.containsKey(serviceId)) {
+        return null;
+      }
+      else {
+        List<Config> list = new ArrayList<>();
+        ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(serviceId);
+        if (!allServiceConfigs.containsKey(configType)) {
+          return null;
+        }
+        return Collections.unmodifiableMap(allServiceConfigs.get(configType));
+      }
+    }
+    finally {
+      clusterGlobalLock.readLock().unlock();
+    }
+  }
+
+  @Override
   public List<Config> getLatestConfigsWithTypes(Collection<String> types) {
     return clusterDAO.getLatestConfigurationsWithTypes(clusterId, getDesiredStackVersion(), types)
       .stream()
@@ -1448,6 +1518,26 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
+  public void addConfig(Config config, Long serviceId) {
+    if (config.getType() == null || config.getType().isEmpty()) {
+      throw new IllegalArgumentException("Config type cannot be empty");
+    }
+    clusterGlobalLock.writeLock().lock();
+    try {
+      if (!serviceConfigs.containsKey(serviceId)) {
+        ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = new ConcurrentHashMap<>();
+        serviceConfigs.put(serviceId, allServiceConfigs);
+      }
+      ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(serviceId);
+      allServiceConfigs.put(config.getType(), new ConcurrentHashMap<>());
+      allServiceConfigs.get(config.getType()).put(config.getTag(), config);
+      serviceConfigs.put(serviceId,allServiceConfigs);
+    } finally {
+        clusterGlobalLock.writeLock().unlock();
+    }
+  }
+
+  @Override
   public Collection<Config> getAllConfigs() {
     clusterGlobalLock.readLock().lock();
     try {
@@ -2855,10 +2945,30 @@ public class ClusterImpl implements Cluster {
     try {
       ClusterEntity clusterEntity = getClusterEntity();
       allConfigs.clear();
+      serviceConfigs.clear();
 
       if (!clusterEntity.getClusterConfigEntities().isEmpty()) {
         for (ClusterConfigEntity entity : clusterEntity.getClusterConfigEntities()) {
-
+          if (entity.getServiceId() != null) {
+            if(!serviceConfigs.containsKey(entity.getServiceId())) {
+              ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = new ConcurrentHashMap<>();
+              if (!allServiceConfigs.containsKey(entity.getType())) {
+                allServiceConfigs.put(entity.getType(), new ConcurrentHashMap<>());
+              }
+              Config config = configFactory.createExisting(this, entity);
+              allServiceConfigs.get(entity.getType()).put(entity.getTag(), config);
+              serviceConfigs.put(entity.getServiceId(), allServiceConfigs);
+            }
+            else {
+              ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(entity.getServiceId());
+              if (!allServiceConfigs.containsKey(entity.getType())) {
+                allServiceConfigs.put(entity.getType(), new ConcurrentHashMap<>());
+              }
+              Config config = configFactory.createExisting(this, entity);
+              allServiceConfigs.get(entity.getType()).put(entity.getTag(), config);
+              serviceConfigs.put(entity.getServiceId(), allServiceConfigs);
+            }
+          }
           if (!allConfigs.containsKey(entity.getType())) {
             allConfigs.put(entity.getType(), new ConcurrentHashMap<>());
           }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java
index 33902af..2536d8b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java
@@ -435,8 +435,9 @@ public class ConfigGroupImpl implements ConfigGroup {
         if (clusterConfigEntity == null) {
           Service service = cluster.getService(serviceId);
 
+          //TODO check the serviceid = null for the right use case
           config = configFactory.createNew(service.getDesiredStackId(), cluster, config.getType(),
-              config.getTag(), config.getProperties(), config.getPropertiesAttributes());
+              config.getTag(), config.getProperties(), config.getPropertiesAttributes(), null);
 
           entry.setValue(config);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
index 5a2b92a..ebb0362 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
@@ -587,8 +587,9 @@ public abstract class AbstractUpgradeCatalog implements UpgradeCatalog {
             propertiesAttributes = Collections.emptyMap();
           }
 
+          //TODO check the serviceid = null for the right use case
           controller.createConfig(cluster, cluster.getDesiredStackVersion(), configType,
-              mergedProperties, newTag, propertiesAttributes);
+              mergedProperties, newTag, propertiesAttributes, null);
 
           Config baseConfig = cluster.getConfig(configType, newTag);
           if (baseConfig != null) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
index e1e7c9e..5bc419e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -99,9 +99,11 @@ CREATE TABLE clusterconfig (
   create_timestamp BIGINT NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (version_tag, type_name, cluster_id),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index b438e69..b3bd221 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -118,9 +118,11 @@ CREATE TABLE clusterconfig (
   create_timestamp BIGINT NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index aab7f95..f6294c7 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -99,9 +99,11 @@ CREATE TABLE clusterconfig (
   create_timestamp NUMBER(19) NOT NULL,
   unmapped SMALLINT DEFAULT 0 NOT NULL,
   selected_timestamp NUMBER(19) DEFAULT 0 NOT NULL,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 8832818..e2bf5f3 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -117,9 +117,11 @@ CREATE TABLE clusterconfig (
   create_timestamp BIGINT NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index 135707b..1379112 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -98,9 +98,11 @@ CREATE TABLE clusterconfig (
   create_timestamp NUMERIC(19) NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp NUMERIC(19) NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index 7d93aad..5f03331 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -112,9 +112,11 @@ CREATE TABLE clusterconfig (
   create_timestamp BIGINT NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY CLUSTERED (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));