AMBARI-22487 : New endpoint service_config_version for creating new config 
versions via service endpoint instead of cluster update (mradhakrishnan)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: c23a33fa4a193b68bbc4a11144367877974d66ed
Parents: e99aece
Author: Madhuvanthi Radhakrishnan <[email protected]>
Authored: Tue Dec 5 13:35:15 2017 -0800
Committer: Madhuvanthi Radhakrishnan <[email protected]>
Committed: Tue Dec 5 13:35:15 2017 -0800

----------------------------------------------------------------------
 .../api/services/ConfigurationService.java      |   5 +-
 .../services/ServiceConfigVersionService.java   |  39 +++-
 .../controller/AmbariManagementController.java  |  13 ++
 .../AmbariManagementControllerImpl.java         | 194 +++++++++++++++++++
 .../controller/ServiceConfigVersionRequest.java |  24 ++-
 .../ServiceConfigVersionResourceProvider.java   | 118 +++++++----
 6 files changed, 349 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c23a33fa/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 79128a2..c89a506 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
@@ -24,6 +24,7 @@ import java.util.Map;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 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;
@@ -77,8 +78,8 @@ public class ConfigurationService extends BaseService {
   }
 
   @Path("service_config_versions")
-  public ServiceConfigVersionService getServiceConfigVersionService() {
-    return new ServiceConfigVersionService(m_clusterName);
+  public ServiceConfigVersionService getServiceConfigVersionService(@Context 
javax.ws.rs.core.Request request, @PathParam("serviceName") String serviceName) 
{
+    return new ServiceConfigVersionService(m_clusterName, m_serviceGroupName, 
serviceName);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/c23a33fa/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceConfigVersionService.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceConfigVersionService.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceConfigVersionService.java
index c6e3201..3150d9a 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceConfigVersionService.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceConfigVersionService.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import javax.ws.rs.GET;
+import javax.ws.rs.POST;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.HttpHeaders;
@@ -38,20 +39,54 @@ public class ServiceConfigVersionService extends 
BaseService {
    */
   private String m_clusterName;
 
+  /**
+   * Parent service group name.
+   */
+  private String m_serviceGroupName = null;
+
+  /**
+   * Parent service name.
+   */
+  private String m_serviceName = null;
+
   public ServiceConfigVersionService(String m_clusterName) {
     this.m_clusterName = m_clusterName;
   }
 
+  /**
+   * Constructor.
+   *
+   * @param clusterName cluster name
+   * @param serviceGroupName service group name
+   * @param serviceName service name
+   */
+  public ServiceConfigVersionService(String clusterName, String 
serviceGroupName, String serviceName) {
+    m_clusterName = clusterName;
+    m_serviceGroupName = serviceGroupName;
+    m_serviceName = serviceName;
+  }
+
+  @POST @ApiIgnore // until documented
+  @Produces("text/plain")
+  public Response createConfigurations(String body,@Context HttpHeaders 
headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST, 
createServiceConfigResource(m_clusterName, m_serviceGroupName, m_serviceName));
+  }
+
   @GET @ApiIgnore // until documented
   @Produces("text/plain")
   public Response getServiceConfigVersions(String body, @Context HttpHeaders 
headers, @Context UriInfo ui) {
-    return handleRequest(headers, body, ui, Request.Type.GET, 
createServiceConfigResource(m_clusterName));
+    return handleRequest(headers, body, ui, Request.Type.GET, 
createServiceConfigResource(m_clusterName, m_serviceGroupName, m_serviceName));
   }
 
-  ResourceInstance createServiceConfigResource(String clusterName) {
+  ResourceInstance createServiceConfigResource(String clusterName, String 
serviceGroupName, String serviceName) {
     Map<Resource.Type,String> mapIds = new HashMap<>();
     mapIds.put(Resource.Type.Cluster, clusterName);
     mapIds.put(Resource.Type.ServiceConfigVersion, null);
+    if (serviceName != null && serviceGroupName != null) {
+      mapIds.put(Resource.Type.ServiceGroup, serviceGroupName);
+      mapIds.put(Resource.Type.Service, serviceName);
+    }
 
     return createResource(Resource.Type.ServiceConfigVersion, mapIds);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c23a33fa/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 b5bc813..6385118 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
@@ -1016,5 +1016,18 @@ public interface AmbariManagementController {
    */
   void removeMpack(MpackEntity mpackEntity, StackEntity stackEntity) throws 
IOException;
 
+  /**
+   * Creates serviceconfigversions and corresponding new configurations if it 
is an initial request
+   * OR
+   * Rollbacks to an existing serviceconfigversion if request specifies.
+   * @param requests
+   *
+   * @return
+   *
+   * @throws AmbariException
+   *
+   * @throws AuthorizationException
+   */
+  Set<ServiceConfigVersionResponse> 
createServiceConfigVersion(Set<ServiceConfigVersionRequest> requests) throws 
AmbariException, AuthorizationException;
 }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c23a33fa/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 1eaed17..59e6622 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
@@ -116,6 +116,7 @@ import org.apache.ambari.server.metadata.ActionMetadata;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
 import org.apache.ambari.server.metadata.RoleCommandOrderProvider;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
 import org.apache.ambari.server.orm.dao.ExtensionDAO;
 import org.apache.ambari.server.orm.dao.ExtensionLinkDAO;
 import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
@@ -124,6 +125,7 @@ import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.dao.WidgetDAO;
 import org.apache.ambari.server.orm.dao.WidgetLayoutDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.ExtensionLinkEntity;
 import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.orm.entities.MpackEntity;
@@ -333,6 +335,8 @@ public class AmbariManagementControllerImpl implements 
AmbariManagementControlle
   private AmbariManagementHelper helper;
 
   @Inject
+  private ClusterServiceDAO clusterServiceDAO;
+  @Inject
   private ExtensionDAO extensionDAO;
   @Inject
   private ExtensionLinkDAO linkDAO;
@@ -5902,4 +5906,194 @@ public class AmbariManagementControllerImpl implements 
AmbariManagementControlle
     return QuickLinkVisibilityControllerFactory.get(quickLinkProfileJson);
   }
 
+  @Override
+  public Set<ServiceConfigVersionResponse> 
createServiceConfigVersion(Set<ServiceConfigVersionRequest> requests) throws 
AmbariException, AuthorizationException {
+
+    Set<ServiceConfigVersionResponse> serviceConfigVersionResponses = new 
HashSet<>();
+    for (ServiceConfigVersionRequest request : requests) {
+      request.setIsCurrent(true);
+      Cluster cluster = getClusters().getCluster(request.getClusterName());
+      //save data to return configurations created
+      List<ConfigurationResponse> configurationResponses =
+              new LinkedList<>();
+      ServiceConfigVersionResponse serviceConfigVersionResponse = null;
+      List<ConfigurationRequest> desiredConfigs = request.getConfigs();
+
+      if (desiredConfigs != null && request.getVersion() != null) {
+        String msg = "Unable to set desired configs and rollback at same time, 
request = " + request;
+        LOG.error(msg);
+        throw new IllegalArgumentException(msg);
+      }
+
+      //check if desired configs are available in request and they were changed
+      boolean isConfigurationCreationNeeded = false;
+      if (desiredConfigs != null) {
+        for (ConfigurationRequest configurationRequest : desiredConfigs) {
+          Map<String, String> requestConfigProperties = 
configurationRequest.getProperties();
+          Map<String, Map<String, String>> requestConfigAttributes = 
configurationRequest.getPropertiesAttributes();
+
+          // processing password properties
+          if (requestConfigProperties != null && 
!requestConfigProperties.isEmpty()) {
+            Map<PropertyInfo.PropertyType, Set<String>> propertiesTypes = 
cluster.getConfigPropertiesTypes(
+                    configurationRequest.getType()
+            );
+            for (Entry<String, String> property : 
requestConfigProperties.entrySet()) {
+              String propertyName = property.getKey();
+              String propertyValue = property.getValue();
+              if ((propertiesTypes.containsKey(PropertyType.PASSWORD) &&
+                      
propertiesTypes.get(PropertyType.PASSWORD).contains(propertyName)) ||
+                      (requestConfigAttributes != null && 
requestConfigAttributes.containsKey(PASSWORD) &&
+                              
requestConfigAttributes.get(PASSWORD).containsKey(propertyName) &&
+                              
requestConfigAttributes.get(PASSWORD).get(propertyName).equals("true"))) {
+                if (SecretReference.isSecret(propertyValue)) {
+                  SecretReference ref = new SecretReference(propertyValue, 
cluster);
+                  requestConfigProperties.put(propertyName, ref.getValue());
+                }
+              }
+            }
+          }
+
+          Config clusterConfig = 
cluster.getDesiredConfigByType(configurationRequest.getType());
+          Map<String, String> clusterConfigProperties = null;
+          Map<String, Map<String, String>> clusterConfigAttributes = null;
+          if (clusterConfig != null) {
+            clusterConfigProperties = clusterConfig.getProperties();
+            clusterConfigAttributes = clusterConfig.getPropertiesAttributes();
+            if (!isAttributeMapsEqual(requestConfigAttributes, 
clusterConfigAttributes)) {
+              isConfigurationCreationNeeded = true;
+              break;
+            }
+          } else {
+            isConfigurationCreationNeeded = true;
+            break;
+          }
+
+          if (requestConfigProperties == null || 
requestConfigProperties.isEmpty()) {
+            Config existingConfig = 
cluster.getConfig(configurationRequest.getType(), 
configurationRequest.getVersionTag());
+            if (existingConfig != null) {
+              if (!StringUtils.equals(existingConfig.getTag(), 
clusterConfig.getTag())) {
+                isConfigurationCreationNeeded = true;
+                break;
+              }
+            }
+          }
+          if (requestConfigProperties != null && clusterConfigProperties != 
null) {
+            if (requestConfigProperties.size() != 
clusterConfigProperties.size()) {
+              isConfigurationCreationNeeded = true;
+              break;
+            } else {
+              if (cluster.getServiceByConfigType(clusterConfig.getType()) != 
null && clusterConfig.getServiceConfigVersions().isEmpty()) {
+                //If there's no service config versions containing this config 
(except cluster configs), recreate it even if exactly equal
+                LOG.warn("Existing desired config doesn't belong to any 
service config version, " +
+                                "forcing config recreation, " +
+                                "clusterName={}, type = {}, tag={}", 
cluster.getClusterName(), clusterConfig.getType(),
+                        clusterConfig.getTag());
+                isConfigurationCreationNeeded = true;
+                break;
+              }
+              for (Entry<String, String> property : 
requestConfigProperties.entrySet()) {
+                if (!StringUtils.equals(property.getValue(), 
clusterConfigProperties.get(property.getKey()))) {
+                  isConfigurationCreationNeeded = true;
+                  break;
+                }
+              }
+            }
+          }
+        }
+      }
+
+      // set or create configuration mapping (and optionally create the map of 
properties)
+      if (isConfigurationCreationNeeded) {
+
+        if (!desiredConfigs.isEmpty()) {
+          Set<Config> configs = new HashSet<>();
+          String note = null;
+
+          for (ConfigurationRequest cr : desiredConfigs) {
+            String configType = cr.getType();
+
+            if (null != cr.getProperties()) {
+              // !!! empty property sets are supported, and need to be able to 
use
+              // previously-defined configs (revert)
+              Map<String, Config> all = cluster.getConfigsByType(configType);
+              if (null == all ||                              // none set
+                      !all.containsKey(cr.getVersionTag()) ||     // tag not 
set
+                      cr.getProperties().size() > 0) {            // 
properties to set
+
+                cr.setClusterName(cluster.getClusterName());
+
+                ClusterServiceEntity clusterServiceEntity = 
clusterServiceDAO.findByName(cluster.getClusterName(), 
request.getServiceGroupName(), request.getServiceName());
+                cr.setServiceId(clusterServiceEntity.getServiceId());
+                cr.setServiceGroupId(clusterServiceEntity.getServiceGroupId());
+                configurationResponses.add(createConfiguration(cr));
+
+                LOG.info(MessageFormat.format("Applying configuration with tag 
''{0}'' to cluster ''{1}''  for configuration type {2}",
+                        cr.getVersionTag(),
+                        request.getClusterName(),
+                        configType));
+              }
+            }
+            note = request.getNote();
+            Config config = cluster.getConfig(configType, cr.getVersionTag());
+            if (null != config) {
+              configs.add(config);
+            }
+          }
+          if (!configs.isEmpty()) {
+            Map<String, Config> existingConfigTypeToConfig = new 
HashMap<String, Config>();
+            for (Config config : configs) {
+              Config existingConfig = 
cluster.getDesiredConfigByType(config.getType());
+              existingConfigTypeToConfig.put(config.getType(), existingConfig);
+            }
+
+            String authName = getAuthName();
+            serviceConfigVersionResponse = cluster.addDesiredConfig(authName, 
configs, note);
+            if (serviceConfigVersionResponse != null) {
+              List<String> hosts = serviceConfigVersionResponse.getHosts();
+              int numAffectedHosts = null != hosts ? hosts.size() : 0;
+              configChangeLog.info("(configchange) Changing default config. 
cluster: '{}', changed by: '{}', service_name: '{}', config_group: '{}', num 
affected hosts during creation: '{}', note: '{}'",
+                      request.getClusterName(), authName, 
serviceConfigVersionResponse.getServiceName(),
+                      serviceConfigVersionResponse.getGroupName(), 
numAffectedHosts, serviceConfigVersionResponse.getNote());
+
+              for (Config config : configs) {
+                configChangeLog.info("(configchange)    type: '{}', tag: '{}', 
version: '{}'", config.getType(), config.getTag(), config.getVersion());
+
+                Map<String, String> configKeyToAction = 
getConfigKeyDeltaToAction(existingConfigTypeToConfig.get(config.getType()), 
config.getProperties());
+                Map<String, List<String>> actionToListConfigKeys = 
inverseMapByValue(configKeyToAction);
+
+                if (!actionToListConfigKeys.isEmpty()) {
+                  String configOutput = 
getActionToConfigListAsString(actionToListConfigKeys);
+                  configChangeLog.info("(configchange)    Config type '{}' was 
modified with the following keys, {}", config.getType(), configOutput);
+                }
+              }
+            }
+          }
+        }
+      }
+
+      if (request.getVersion() != null) {
+        if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, 
cluster.getResourceId(), EnumSet.of(RoleAuthorization.SERVICE_MODIFY_CONFIGS))) 
{
+          throw new AuthorizationException("The authenticated user does not 
have authorization to modify service configurations");
+        }
+
+        if (StringUtils.isEmpty(request.getServiceName())) {
+          String msg = "Service name and version should be specified in 
service config version";
+          LOG.error(msg);
+          throw new IllegalArgumentException(msg);
+        }
+        serviceConfigVersionResponse = cluster.setServiceConfigVersion(
+                cluster.getService(request.getServiceGroupName(), 
request.getServiceName()).getServiceId(),
+                request.getVersion(), getAuthName(),
+                request.getNote());
+      }
+
+      if (serviceConfigVersionResponse != null) {
+        if (!configurationResponses.isEmpty()) {
+          
serviceConfigVersionResponse.setConfigurations(configurationResponses);
+        }
+      }
+      serviceConfigVersionResponses.add(serviceConfigVersionResponse);
+    }
+    return serviceConfigVersionResponses;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c23a33fa/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
index 29a7a42..518503f 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
@@ -18,6 +18,9 @@
 
 package org.apache.ambari.server.controller;
 
+
+import java.util.List;
+
 public class ServiceConfigVersionRequest {
   private String clusterName;
   private String serviceName;
@@ -28,11 +31,13 @@ public class ServiceConfigVersionRequest {
   private String userName;
   private String note;
   private Boolean isCurrent;
+  private List<ConfigurationRequest> configs;
+  private String stackId;
 
   public ServiceConfigVersionRequest() {
   }
 
-  public ServiceConfigVersionRequest(String clusterName, String 
serviceGroupName, String serviceName, Long version, Long createTime, Long 
applyTime, String userName, Boolean isCurrent) {
+  public ServiceConfigVersionRequest(String clusterName, String 
serviceGroupName, String serviceName, Long version, Long createTime, Long 
applyTime, String userName, Boolean isCurrent, String note, String stackId) {
     this.clusterName = clusterName;
     this.serviceGroupName = serviceGroupName;
     this.serviceName = serviceName;
@@ -41,6 +46,8 @@ public class ServiceConfigVersionRequest {
     this.applyTime = applyTime;
     this.userName = userName;
     this.isCurrent = isCurrent;
+    this.note = note;
+    this.stackId = stackId;
   }
 
   public String getServiceName() {
@@ -115,6 +122,21 @@ public class ServiceConfigVersionRequest {
     this.serviceGroupName = serviceGroupName;
   }
 
+  public String getStackId() {
+    return stackId;
+  }
+
+  public void setStackId(String stackId) {
+    this.stackId = stackId;
+  }
+
+  public void setConfigs(List<ConfigurationRequest> configRequests) {
+    configs = configRequests;
+  }
+
+  public List<ConfigurationRequest> getConfigs() {
+    return configs;
+  }
 
   @Override
   public String toString() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/c23a33fa/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
index cbc08eb..927f4ba 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
@@ -25,6 +25,7 @@ import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -32,6 +33,7 @@ import java.util.TreeMap;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.ConfigurationRequest;
 import org.apache.ambari.server.controller.ConfigurationResponse;
 import org.apache.ambari.server.controller.ServiceConfigVersionRequest;
 import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
@@ -45,6 +47,7 @@ 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.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 
 public class ServiceConfigVersionResourceProvider extends
@@ -58,10 +61,10 @@ public class ServiceConfigVersionResourceProvider extends
   public static final String SERVICE_CONFIG_VERSION_SERVICE_ID_PROPERTY_ID = 
PropertyHelper.getPropertyId(null, "service_id");
   public static final String SERVICE_CONFIG_VERSION_CREATE_TIME_PROPERTY_ID = 
PropertyHelper.getPropertyId(null, "createtime");
   public static final String SERVICE_CONFIG_VERSION_USER_PROPERTY_ID = 
PropertyHelper.getPropertyId(null, "user");
-  public static final String SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID = 
PropertyHelper.getPropertyId(null, "service_config_version_note");
+  public static final String SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID = 
PropertyHelper.getPropertyId("ServiceConfigVersion", 
"service_config_version_note");
   public static final String SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID = 
PropertyHelper.getPropertyId(null, "group_id");
   public static final String SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID = 
PropertyHelper.getPropertyId(null, "group_name");
-  public static final String SERVICE_CONFIG_VERSION_STACK_ID_PROPERTY_ID = 
PropertyHelper.getPropertyId(null, "stack_id");
+  public static final String SERVICE_CONFIG_VERSION_STACK_ID_PROPERTY_ID = 
PropertyHelper.getPropertyId("ServiceConfigVersion", "stack_id");
   public static final String SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID = 
PropertyHelper.getPropertyId(null, "is_current");
   public static final String SERVICE_CONFIG_VERSION_IS_COMPATIBLE_PROPERTY_ID 
= PropertyHelper.getPropertyId(null, "is_cluster_compatible");
   public static final String SERVICE_CONFIG_VERSION_HOSTS_PROPERTY_ID = 
PropertyHelper.getPropertyId(null, "hosts");
@@ -92,11 +95,13 @@ public class ServiceConfigVersionResourceProvider extends
     PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_HOSTS_PROPERTY_ID);
     PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID);
     PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_IS_COMPATIBLE_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_CONFIG_VERSION_SERVICE_GROUP_NAME_PROPERTY_ID);
 
     // keys
-    
KEY_PROPERTY_IDS.put(Resource.Type.Service,SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID);
-    
KEY_PROPERTY_IDS.put(Resource.Type.Cluster,SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID);
-    
KEY_PROPERTY_IDS.put(Resource.Type.ServiceConfigVersion,SERVICE_CONFIG_VERSION_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.Service, 
SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.Cluster, 
SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.ServiceConfigVersion, 
SERVICE_CONFIG_VERSION_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroup, 
SERVICE_CONFIG_VERSION_SERVICE_GROUP_NAME_PROPERTY_ID);
   }
 
 
@@ -106,7 +111,7 @@ public class ServiceConfigVersionResourceProvider extends
   private static Set<String> pkPropertyIds =
     new HashSet<>(Arrays.asList(new String[]{
       SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID,
-      SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID}));
+      SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID, 
SERVICE_CONFIG_VERSION_SERVICE_GROUP_NAME_PROPERTY_ID}));
 
 
   // ----- Constructors ------------------------------------------------------
@@ -133,7 +138,63 @@ public class ServiceConfigVersionResourceProvider extends
 
   @Override
   public RequestStatus createResources(Request request) throws 
SystemException, UnsupportedPropertyException, ResourceAlreadyExistsException, 
NoSuchParentResourceException {
-    throw new UnsupportedOperationException("Cannot explicitly create service 
config version");
+    final Set<ServiceConfigVersionRequest> requests = new HashSet<>();
+    Set<ServiceConfigVersionResponse> responses = new HashSet<>();
+
+    for (Map<String, Object> propertyMap : request.getProperties()) {
+      requests.add(createRequest(propertyMap));
+    }
+    responses = createResources(new 
Command<Set<ServiceConfigVersionResponse>>() {
+      @Override
+      public Set<ServiceConfigVersionResponse> invoke() throws 
AmbariException, AuthorizationException {
+        return getManagementController().createServiceConfigVersion(requests);
+      }
+    });
+
+    Set<Resource> associatedResources = new HashSet<>();
+    for (ServiceConfigVersionResponse serviceConfigVersionResponse : 
responses) {
+      Resource resource = new ResourceImpl(Resource.Type.ServiceConfigVersion);
+      
resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_GROUP_NAME_PROPERTY_ID,
+              serviceConfigVersionResponse.getServiceGroupName());
+      
resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_GROUP_ID_PROPERTY_ID,
+              serviceConfigVersionResponse.getServiceGroupId());
+      
resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID,
+              serviceConfigVersionResponse.getServiceName());
+      
resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_ID_PROPERTY_ID,
+              serviceConfigVersionResponse.getServiceId());
+      
resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_PROPERTY_ID,
+              serviceConfigVersionResponse.getVersion());
+      
resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID,
+              serviceConfigVersionResponse.getNote());
+      
resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID,
+              serviceConfigVersionResponse.getGroupId());
+      
resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID,
+              serviceConfigVersionResponse.getGroupName());
+      if (serviceConfigVersionResponse.getConfigurations() != null) {
+        resource.setProperty(
+                
ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID,
+                serviceConfigVersionResponse.getConfigurations());
+      }
+      associatedResources.add(resource);
+    }
+
+    return getRequestStatus(null, associatedResources);
+  }
+
+  private List<ConfigurationRequest> getConfigurationRequests(Set<Map<String, 
Object>>  configurations) {
+    List<ConfigurationRequest> configs = new LinkedList<>();
+    for (Map<String, Object> value: configurations) {
+      ConfigurationRequest newConfig = new ConfigurationRequest();
+      for (Map.Entry<String, Object> e : value.entrySet()) {
+        String propName =
+                PropertyHelper.getPropertyName("Config" + '/' + e.getKey());
+        String absCatategory =
+                PropertyHelper.getPropertyCategory("Config" + '/' + 
e.getKey());
+        parseProperties(newConfig, absCatategory, propName, e.getValue() == 
null ? null : e.getValue().toString());
+      }
+      configs.add(newConfig);
+    }
+    return configs;
   }
 
   @Override
@@ -159,6 +220,7 @@ public class ServiceConfigVersionResourceProvider extends
       Resource resource = new ResourceImpl(Resource.Type.ServiceConfigVersion);
       resource.setProperty(SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID, 
clusterName);
       resource.setProperty(SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID, 
response.getServiceName());
+      
resource.setProperty(SERVICE_CONFIG_VERSION_SERVICE_GROUP_NAME_PROPERTY_ID, 
response.getServiceGroupName());
       resource.setProperty(SERVICE_CONFIG_VERSION_USER_PROPERTY_ID, 
response.getUserName());
       resource.setProperty(SERVICE_CONFIG_VERSION_PROPERTY_ID, 
response.getVersion());
       resource.setProperty(SERVICE_CONFIG_VERSION_CREATE_TIME_PROPERTY_ID, 
response.getCreateTime());
@@ -186,36 +248,6 @@ public class ServiceConfigVersionResourceProvider extends
     throw new UnsupportedOperationException("Cannot delete service config 
version");
   }
 
-  @Override
-  public Set<String> checkPropertyIds(Set<String> propertyIds) {
-    propertyIds = super.checkPropertyIds(propertyIds);
-
-    if (propertyIds.isEmpty()) {
-      return propertyIds;
-    }
-    Set<String> unsupportedProperties = new HashSet<>();
-
-    for (String propertyId : propertyIds) {
-      if (!propertyId.equals("cluster_name") && 
!propertyId.equals("service_config_version") &&
-          !propertyId.equals("service_group_name")&&
-          !propertyId.equals("service_name") && 
!propertyId.equals("createtime") &&
-          !propertyId.equals("appliedtime") && !propertyId.equals("user") &&
-          !propertyId.equals("service_config_version_note") &&
-          !propertyId.equals("group_id") &&
-          !propertyId.equals("group_name") &&
-          !propertyId.equals("stack_id") &&
-          !propertyId.equals("is_current") &&
-          !propertyId.equals("is_cluster_compatible") &&
-          !propertyId.equals("hosts")) {
-
-        unsupportedProperties.add(propertyId);
-
-      }
-    }
-    return unsupportedProperties;
-  }
-
-
   private ServiceConfigVersionRequest createRequest(Map<String, Object> 
properties) {
     String clusterName = (String) 
properties.get(SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID);
     String serviceGroupName = (String) 
properties.get(SERVICE_CONFIG_VERSION_SERVICE_GROUP_NAME_PROPERTY_ID);
@@ -224,8 +256,16 @@ public class ServiceConfigVersionResourceProvider extends
     Boolean isCurrent = Boolean.valueOf((String) 
properties.get(SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID));
     Object versionObject = properties.get(SERVICE_CONFIG_VERSION_PROPERTY_ID);
     Long version = versionObject == null ? null : 
Long.valueOf(versionObject.toString());
-
-    return new ServiceConfigVersionRequest(clusterName, serviceGroupName, 
serviceName, version, null, null, user, isCurrent);
+    String note = (String) 
properties.get(SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID);
+    String stackId = (String) 
properties.get(SERVICE_CONFIG_VERSION_STACK_ID_PROPERTY_ID);
+    ServiceConfigVersionRequest scvr = new 
ServiceConfigVersionRequest(clusterName, serviceGroupName, serviceName, 
version, null, null, user, isCurrent, note, stackId);
+    if(version == null && properties.containsKey("configurations")) {
+      List<ConfigurationRequest> configRequests = 
getConfigurationRequests((Set<Map<String, Object>>) 
properties.get("configurations"));
+      if (!configRequests.isEmpty()) {
+        scvr.setConfigs(configRequests);
+      }
+    }
+    return scvr;
   }
 
   private List<Map<String, Object>> convertToSubResources(final String 
clusterName, List<ConfigurationResponse> configs) {

Reply via email to