Repository: ambari
Updated Branches:
  refs/heads/trunk cc51c2a60 -> 2885f1912


AMBARI-6669. Provide properties_attributes support in cluster creation from 
blueprint


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

Branch: refs/heads/trunk
Commit: 2885f1912559a2cab1dd0e69495844411425cbdd
Parents: cc51c2a
Author: Srimanth Gunturi <sgunt...@hortonworks.com>
Authored: Tue Jul 29 23:29:13 2014 -0700
Committer: Srimanth Gunturi <sgunt...@hortonworks.com>
Committed: Wed Jul 30 12:45:26 2014 -0700

----------------------------------------------------------------------
 .../controller/StackConfigurationResponse.java  |  35 +-
 .../internal/BaseBlueprintProcessor.java        | 116 ++++-
 .../internal/ClusterResourceProvider.java       |  70 ++-
 .../StackConfigurationResourceProvider.java     |  17 +-
 .../ambari/server/state/PropertyInfo.java       |  25 +-
 .../api/util/StackExtensionHelperTest.java      |   8 +-
 .../internal/ClusterResourceProviderTest.java   | 473 +++++++++++++++++++
 .../StackConfigurationResourceProviderTest.java |  79 +++-
 .../ambari/server/state/PropertyInfoTest.java   |  62 +++
 .../services/HDFS/configuration/hdfs-site.xml   |  45 ++
 10 files changed, 886 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/main/java/org/apache/ambari/server/controller/StackConfigurationResponse.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackConfigurationResponse.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackConfigurationResponse.java
index 44454ec..96ca232 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackConfigurationResponse.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackConfigurationResponse.java
@@ -19,6 +19,8 @@
 package org.apache.ambari.server.controller;
 
 
+import java.util.Map;
+
 public class StackConfigurationResponse {
 
   /**
@@ -27,14 +29,15 @@ public class StackConfigurationResponse {
    * @param propertyValue Property Value
    * @param propertyDescription Property Description
    * @param type Configuration type
-   * @param isFinal Is property final
+   * @param propertyAttributes Attributes map
    */
-  public StackConfigurationResponse(String propertyName, String propertyValue, 
String propertyDescription, String type, Boolean isFinal) {
+  public StackConfigurationResponse(String propertyName, String propertyValue, 
String propertyDescription,
+                                    String type, Map<String, String> 
propertyAttributes) {
     setPropertyName(propertyName);
     setPropertyValue(propertyValue);
     setPropertyDescription(propertyDescription);
     setType(type);
-    setFinal(isFinal);
+    setPropertyAttributes(propertyAttributes);
   }
 
   /**
@@ -45,18 +48,18 @@ public class StackConfigurationResponse {
    * @param type Configuration type
    * @param isRequired Is required to be set
    * @param propertyType Property Type
-   * @param isFinal Is property final
+   * @param propertyAttributes Attributes map
    */
   public StackConfigurationResponse(String propertyName, String propertyValue,
                                     String propertyDescription, String type,
-                                    Boolean isRequired, String propertyType, 
Boolean isFinal) {
+                                    Boolean isRequired, String propertyType, 
Map<String, String> propertyAttributes) {
     setPropertyName(propertyName);
     setPropertyValue(propertyValue);
     setPropertyDescription(propertyDescription);
     setType(type);
     setRequired(isRequired);
     setPropertyType(propertyType);
-    setFinal(isFinal);
+    setPropertyAttributes(propertyAttributes);
   }
 
   private String stackName;
@@ -66,7 +69,7 @@ public class StackConfigurationResponse {
   private String propertyValue;
   private String propertyDescription;
   private String type;
-  private Boolean isFinal;
+  private Map<String, String> propertyAttributes;
   private Boolean isRequired;
   private String propertyType;
 
@@ -130,12 +133,22 @@ public class StackConfigurationResponse {
     this.type = type;
   }
 
-  public Boolean isFinal() {
-    return isFinal;
+  /**
+   * Provides attributes of this configuration.
+   *
+   * @return Map of attribute name to attribute value
+   */
+  public Map<String, String> getPropertyAttributes() {
+    return propertyAttributes;
   }
 
-  public void setFinal(Boolean isFinal) {
-    this.isFinal = isFinal;
+  /**
+   * Sets attributes for this configuration.
+   *
+   * @param propertyAttributes Map of attribute name to attribute value
+   */
+  public void setPropertyAttributes(Map<String, String> propertyAttributes) {
+    this.propertyAttributes = propertyAttributes;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseBlueprintProcessor.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseBlueprintProcessor.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseBlueprintProcessor.java
index 800ff3b..b3a8019 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseBlueprintProcessor.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseBlueprintProcessor.java
@@ -206,6 +206,33 @@ public abstract class BaseBlueprintProcessor extends 
AbstractControllerResourceP
   }
 
   /**
+   * Process cluster scoped configuration attributes contained in blueprint.
+   *
+   * @param blueprint  blueprint entity
+   *
+   * @return cluster scoped property attributes contained within in blueprint
+   */
+  protected Map<String, Map<String, Map<String, String>>> 
processBlueprintAttributes(BlueprintEntity blueprint) {
+
+    Map<String, Map<String, Map<String, String>>> mapAttributes =
+        new HashMap<String, Map<String, Map<String, String>>>();
+    Collection<BlueprintConfigEntity> configs = blueprint.getConfigurations();
+
+    if (configs != null) {
+      Gson gson = new Gson();
+      for (BlueprintConfigEntity config : configs) {
+        Map<String, Map<String, String>> typeAttrs =
+            gson.<Map<String, Map<String, 
String>>>fromJson(config.getConfigAttributes(), Map.class);
+        if (typeAttrs != null && !typeAttrs.isEmpty()) {
+          mapAttributes.put(config.getType(), typeAttrs);
+        }
+      }
+    }
+
+    return mapAttributes;
+  }
+
+  /**
    * Override existing properties or add new.
    *
    * @param existingProperties  current property values
@@ -480,8 +507,38 @@ public abstract class BaseBlueprintProcessor extends 
AbstractControllerResourceP
     /**
      * Map of service to config type properties
      */
-    private Map<String, Map<String, Map<String, String>>> 
serviceConfigurations =
-        new HashMap<String, Map<String, Map<String, String>>>();
+    private Map<String, Map<String, Map<String, ConfigProperty>>> 
serviceConfigurations =
+        new HashMap<String, Map<String, Map<String, ConfigProperty>>>();
+
+    /**
+     * Contains a configuration property's value and attributes.
+     */
+    private class ConfigProperty {
+
+      private ConfigProperty(String value, Map<String, String> attributes) {
+        this.value = value;
+        this.attributes = attributes;
+      }
+
+      private String value;
+      private Map<String, String> attributes;
+
+      public String getValue() {
+        return value;
+      }
+
+      public void setValue(String value) {
+        this.value = value;
+      }
+
+      public Map<String, String> getAttributes() {
+        return attributes;
+      }
+
+      public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+      }
+    }
 
     /**
      * Constructor.
@@ -565,7 +622,47 @@ public abstract class BaseBlueprintProcessor extends 
AbstractControllerResourceP
      * @return map of property names to values for the specified service and 
configuration type
      */
     public Map<String, String> getConfigurationProperties(String service, 
String type) {
-      return serviceConfigurations.get(service).get(type);
+      Map<String, String> configMap = new HashMap<String, String>();
+      Map<String, ConfigProperty> configProperties = 
serviceConfigurations.get(service).get(type);
+      if (configProperties != null) {
+        for (Map.Entry<String, ConfigProperty> configProperty : 
configProperties.entrySet()) {
+          configMap.put(configProperty.getKey(), 
configProperty.getValue().getValue());
+        }
+      }
+      return configMap;
+    }
+
+    /**
+     * Get config attributes for the specified service and configuration type.
+     *
+     * @param service  service name
+     * @param type     configuration type
+     *
+     * @return  map of attribute names to map of property names to attribute 
values
+     *          for the specified service and configuration type
+     */
+    public Map<String, Map<String, String>> getConfigurationAttributes(String 
service, String type) {
+      Map<String, Map<String, String>> attributesMap = new HashMap<String, 
Map<String, String>>();
+      Map<String, ConfigProperty> configProperties = 
serviceConfigurations.get(service).get(type);
+      if (configProperties != null) {
+        for (Map.Entry<String, ConfigProperty> configProperty : 
configProperties.entrySet()) {
+          String propertyName = configProperty.getKey();
+          Map<String, String> propertyAttributes = 
configProperty.getValue().getAttributes();
+          if (propertyAttributes != null) {
+            for (Map.Entry<String, String> propertyAttribute : 
propertyAttributes.entrySet()) {
+              String attributeName = propertyAttribute.getKey();
+              String attributeValue = propertyAttribute.getValue();
+              Map<String, String> attributes = 
attributesMap.get(attributeName);
+              if (attributes == null) {
+                  attributes = new HashMap<String, String>();
+                  attributesMap.put(attributeName, attributes);
+              }
+              attributes.put(propertyName, attributeValue);
+            }
+          }
+        }
+      }
+      return attributesMap;
     }
 
     /**
@@ -603,8 +700,8 @@ public abstract class BaseBlueprintProcessor extends 
AbstractControllerResourceP
      * @return name of service which corresponds to the specified 
configuration type
      */
     public String getServiceForConfigType(String config) {
-      for (Map.Entry<String, Map<String, Map<String, String>>> entry : 
serviceConfigurations.entrySet()) {
-        Map<String, Map<String, String>> typeMap = entry.getValue();
+      for (Map.Entry<String, Map<String, Map<String, ConfigProperty>>> entry : 
serviceConfigurations.entrySet()) {
+        Map<String, Map<String, ConfigProperty>> typeMap = entry.getValue();
         if (typeMap.containsKey(config)) {
           return entry.getKey();
         }
@@ -702,7 +799,7 @@ public abstract class BaseBlueprintProcessor extends 
AbstractControllerResourceP
      * @throws AmbariException an exception occurred getting configurations 
from the stack definition
      */
     private void parseConfigurations(String service) throws AmbariException {
-      Map<String, Map<String, String>> mapServiceConfig = new HashMap<String, 
Map<String, String>>();
+      Map<String, Map<String, ConfigProperty>> mapServiceConfig = new 
HashMap<String, Map<String, ConfigProperty>>();
 
       serviceConfigurations.put(service, mapServiceConfig);
 
@@ -715,12 +812,13 @@ public abstract class BaseBlueprintProcessor extends 
AbstractControllerResourceP
         if (type.endsWith(".xml")) {
           type = type.substring(0, type.length() - 4);
         }
-        Map<String, String> mapTypeConfig = mapServiceConfig.get(type);
+        Map<String, ConfigProperty> mapTypeConfig = mapServiceConfig.get(type);
         if (mapTypeConfig == null) {
-          mapTypeConfig = new HashMap<String, String>();
+          mapTypeConfig = new HashMap<String, ConfigProperty>();
           mapServiceConfig.put(type, mapTypeConfig);
         }
-        mapTypeConfig.put(config.getPropertyName(), config.getPropertyValue());
+        mapTypeConfig.put(config.getPropertyName(),
+            new ConfigProperty(config.getPropertyValue(), 
config.getPropertyAttributes()));
       }
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
index 464f116..a39e5ad 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
@@ -84,6 +84,11 @@ public class ClusterResourceProvider extends 
BaseBlueprintProcessor {
    */
   private Map<String, Map<String, String>> mapClusterConfigurations =
       new HashMap<String, Map<String, String>>();
+  /**
+   * Maps configuration type (string) to property attributes, and their values
+   */
+  private Map<String, Map<String, Map<String, String>>> mapClusterAttributes =
+      new HashMap<String, Map<String, Map<String, String>>>();
 
 
   // ----- Constructors ----------------------------------------------------
@@ -314,8 +319,9 @@ public class ClusterResourceProvider extends 
BaseBlueprintProcessor {
 
     Map<String, HostGroup> blueprintHostGroups = 
parseBlueprintHostGroups(blueprint, stack);
     applyRequestInfoToHostGroups(properties, blueprintHostGroups);
-    processConfigurations(processBlueprintConfigurations(blueprint, 
(Collection<Map<String, String>>)
-        properties.get("configurations")), stack, blueprintHostGroups);
+    Collection<Map<String, String>> configOverrides = (Collection<Map<String, 
String>>)properties.get("configurations");
+    processConfigurations(processBlueprintConfigurations(blueprint, 
configOverrides),
+        processBlueprintAttributes(blueprint), stack, blueprintHostGroups);
     validatePasswordProperties(blueprint, blueprintHostGroups, (String) 
properties.get("default_password"));
 
     String clusterName = (String) properties.get(CLUSTER_NAME_PROPERTY_ID);
@@ -573,9 +579,10 @@ public class ClusterResourceProvider extends 
BaseBlueprintProcessor {
     for (Map.Entry<String, Map<String, String>> entry : 
mapClusterConfigurations.entrySet()) {
       String type = entry.getKey();
 
+      Map<String, Map<String, String>> confAttributes = 
mapClusterAttributes.get(type);
       try {
         //todo: properly handle non system exceptions
-        setConfigurationsOnCluster(clusterName, type, entry.getValue());
+        setConfigurationsOnCluster(clusterName, type, entry.getValue(), 
confAttributes);
       } catch (AmbariException e) {
         throw new SystemException("Unable to set configurations on cluster.", 
e);
       }
@@ -592,7 +599,8 @@ public class ClusterResourceProvider extends 
BaseBlueprintProcessor {
    * @throws AmbariException if an exception occurs setting the properties
    */
   private void setConfigurationsOnCluster(String clusterName, String type,
-                                          Map<String, String> properties) 
throws AmbariException {
+                                          Map<String, String> properties,
+                                          Map<String, Map<String, String>> 
propertiesAttributes) throws AmbariException {
 
     Map<String, Object> clusterProperties = new HashMap<String, Object>();
     clusterProperties.put(CLUSTER_NAME_PROPERTY_ID, clusterName);
@@ -602,6 +610,15 @@ public class ClusterResourceProvider extends 
BaseBlueprintProcessor {
       clusterProperties.put(CLUSTER_DESIRED_CONFIGS_PROPERTY_ID +
           "/properties/" + entry.getKey(), entry.getValue());
     }
+    if (propertiesAttributes != null) {
+      for (Map.Entry<String, Map<String, String>> attribute : 
propertiesAttributes.entrySet()) {
+        String attributeName = attribute.getKey();
+        for (Map.Entry<String, String> attributeOccurrence : 
attribute.getValue().entrySet()) {
+          clusterProperties.put(CLUSTER_DESIRED_CONFIGS_PROPERTY_ID + 
"/properties_attributes/"
+              + attributeName + "/" + attributeOccurrence.getKey(), 
attributeOccurrence.getValue());
+        }
+      }
+    }
     getManagementController().updateClusters(
         Collections.singleton(getRequest(clusterProperties)), null);
   }
@@ -708,7 +725,8 @@ public class ClusterResourceProvider extends 
BaseBlueprintProcessor {
    * @param blueprintHostGroups  host groups contained in the blueprint
    */
   private void processConfigurations(Map<String, Map<String, String>> 
blueprintConfigurations,
-                                    Stack stack, Map<String, HostGroup> 
blueprintHostGroups)  {
+                                     Map<String, Map<String, Map<String, 
String>>> blueprintAttributes,
+                                     Stack stack, Map<String, HostGroup> 
blueprintHostGroups)  {
 
     for (String service : getServicesToDeploy(stack, blueprintHostGroups)) {
       for (String type : stack.getConfigurationTypes(service)) {
@@ -718,9 +736,26 @@ public class ClusterResourceProvider extends 
BaseBlueprintProcessor {
           mapClusterConfigurations.put(type, typeProps);
         }
         typeProps.putAll(stack.getConfigurationProperties(service, type));
+        Map<String, Map<String, String>> stackTypeAttributes = 
stack.getConfigurationAttributes(service, type);
+        if (!stackTypeAttributes.isEmpty()) {
+          if (!mapClusterAttributes.containsKey(type)) {
+            mapClusterAttributes.put(type, new HashMap<String, Map<String, 
String>>());
+          }
+          Map<String, Map<String, String>> typeAttrs = 
mapClusterAttributes.get(type);
+          for (Map.Entry<String, Map<String, String>> attribute : 
stackTypeAttributes.entrySet()) {
+            String attributeName = attribute.getKey();
+            Map<String, String> attributes = typeAttrs.get(attributeName);
+            if (attributes == null) {
+                attributes = new HashMap<String, String>();
+                typeAttrs.put(attributeName, attributes);
+            }
+            attributes.putAll(attribute.getValue());
+          }
+        }
       }
     }
     processBlueprintClusterConfigurations(blueprintConfigurations);
+    processBlueprintClusterConfigAttributes(blueprintAttributes);
 
     for (Map.Entry<String, Map<String, String>> entry : 
mapClusterConfigurations.entrySet()) {
       for (Map.Entry<String, String> propertyEntry : 
entry.getValue().entrySet()) {
@@ -757,6 +792,31 @@ public class ClusterResourceProvider extends 
BaseBlueprintProcessor {
   }
 
   /**
+   * Process cluster scoped configuration attributes provided in blueprint.
+   *
+   * @param blueprintAttributes  map of configuration type to configuration 
attributes and their values
+   */
+  private void processBlueprintClusterConfigAttributes(Map<String, Map<String, 
Map<String, String>>> blueprintAttributes) {
+    for (Map.Entry<String, Map<String, Map<String, String>>> entry : 
blueprintAttributes.entrySet()) {
+      Map<String, Map<String, String>> attributes = entry.getValue();
+      if (attributes != null && !attributes.isEmpty()) {
+        String type = entry.getKey();
+        if (!mapClusterAttributes.containsKey(type)) {
+          mapClusterAttributes.put(type, new HashMap<String, Map<String, 
String>>());
+        }
+        Map<String, Map<String, String>> typeAttrs = 
mapClusterAttributes.get(type);
+        for (Map.Entry<String, Map<String, String>> attribute : 
attributes.entrySet()) {
+          String attributeName = attribute.getKey();
+          if (!typeAttrs.containsKey(attributeName)) {
+            typeAttrs.put(attributeName, new HashMap<String, String>());
+          }
+          typeAttrs.get(attributeName).putAll(attribute.getValue());
+        }
+      }
+    }
+  }
+
+  /**
    * Explicitly set any properties that are required but not currently 
provided in the stack definition.
    */
   private void setMissingConfigurations() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProvider.java
index 4aa56f0..2e2bfe1 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProvider.java
@@ -128,8 +128,12 @@ public class StackConfigurationResourceProvider extends
       setResourceProperty(resource, PROPERTY_TYPE_PROPERTY_ID,
           response.getType(), requestedIds);
 
-      setResourceProperty(resource, PROPERTY_FINAL_PROPERTY_ID,
-          response.isFinal(), requestedIds);
+      setDefaultPropertiesAttributes(resource, requestedIds);
+
+      for (Map.Entry<String, String> attribute : 
response.getPropertyAttributes().entrySet()) {
+        setResourceProperty(resource, 
PropertyHelper.getPropertyId("StackConfigurations", attribute.getKey()),
+            attribute.getValue(), requestedIds);
+      }
 
       resources.add(resource);
     }
@@ -137,6 +141,15 @@ public class StackConfigurationResourceProvider extends
     return resources;
   }
 
+  /**
+   * Set default values for properties attributes before applying original ones
+   * to prevent absence in case of empty attributes map
+   */
+  private void setDefaultPropertiesAttributes(Resource resource, Set<String> 
requestedIds) {
+    setResourceProperty(resource, PROPERTY_FINAL_PROPERTY_ID,
+        "false", requestedIds);
+  }
+
   private StackConfigurationRequest getRequest(Map<String, Object> properties) 
{
     return new StackConfigurationRequest(
         (String) properties.get(STACK_NAME_PROPERTY_ID),

http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java 
b/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java
index 8789383..6a17e9d 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java
@@ -20,9 +20,14 @@ package org.apache.ambari.server.state;
 
 
 import org.apache.ambari.server.controller.StackConfigurationResponse;
+import org.w3c.dom.Element;
 
+import javax.xml.bind.annotation.XmlAnyElement;
 import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 public class PropertyInfo {
   private String name;
@@ -32,7 +37,8 @@ public class PropertyInfo {
   private boolean deleted;
   private boolean requireInput;
   private PropertyType type = PropertyType.DEFAULT;
-  private boolean isFinal;
+  @XmlAnyElement
+  private List<Element> propertyAttributes = new ArrayList<Element>();
 
   public String getName() {
     return name;
@@ -68,7 +74,7 @@ public class PropertyInfo {
   
   public StackConfigurationResponse convertToResponse() {
     return new StackConfigurationResponse(getName(), getValue(),
-      getDescription() , getFilename(), isRequireInput(), getType().name(), 
isFinal());
+      getDescription() , getFilename(), isRequireInput(), getType().name(), 
getAttributesMap());
   }
 
   public boolean isDeleted() {
@@ -79,13 +85,12 @@ public class PropertyInfo {
     this.deleted = deleted;
   }
 
-  @XmlElement(name="final")
-  public boolean isFinal() {
-    return isFinal;
-  }
-
-  public void setFinal(boolean isFinal) {
-    this.isFinal = isFinal;
+  public Map<String, String> getAttributesMap() {
+    Map<String, String> attributes = new HashMap<String, String>();
+    for (Element propertyAttribute : propertyAttributes) {
+      attributes.put(propertyAttribute.getTagName(), 
propertyAttribute.getFirstChild().getNodeValue());
+    }
+    return attributes;
   }
 
   @XmlAttribute(name = "require-input")

http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java
index 7d07fe1..517f3b7 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/api/util/StackExtensionHelperTest.java
@@ -599,7 +599,8 @@ public class StackExtensionHelperTest {
     assertEquals("yarn.scheduler.capacity.maximum-applications", 
propertyInfo.getName());
     assertEquals("Maximum number of applications that can be pending and 
running.", propertyInfo.getDescription());
     assertEquals("10000", propertyInfo.getValue());
-    assertEquals(true, propertyInfo.isFinal());
+    assertEquals(1, propertyInfo.getAttributesMap().size());
+    assertEquals("true", propertyInfo.getAttributesMap().get("final"));
     assertEquals(null, propertyInfo.getFilename());
     assertEquals(false, propertyInfo.isDeleted());
     assertEquals(false, propertyInfo.isRequireInput());
@@ -609,7 +610,8 @@ public class StackExtensionHelperTest {
     assertEquals("yarn.scheduler.capacity.maximum-am-resource-percent", 
propertyInfo.getName());
     assertEquals("Maximum percent of resources in the cluster.", 
propertyInfo.getDescription());
     assertEquals("0.2", propertyInfo.getValue());
-    assertEquals(false, propertyInfo.isFinal());
+    assertEquals(1, propertyInfo.getAttributesMap().size());
+    assertEquals("false", propertyInfo.getAttributesMap().get("final"));
     assertEquals(null, propertyInfo.getFilename());
     assertEquals(true, propertyInfo.isDeleted());
     assertEquals(false, propertyInfo.isRequireInput());
@@ -619,7 +621,7 @@ public class StackExtensionHelperTest {
     assertEquals("yarn.scheduler.capacity.root.queues", 
propertyInfo.getName());
     assertEquals("The queues at the this level (root is the root queue).", 
propertyInfo.getDescription());
     assertEquals("default", propertyInfo.getValue());
-    assertEquals(false, propertyInfo.isFinal());
+    assertEquals(0, propertyInfo.getAttributesMap().size());
     assertEquals(null, propertyInfo.getFilename());
     assertEquals(false, propertyInfo.isDeleted());
     assertEquals(true, propertyInfo.isRequireInput());

http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
index 11e5993..a1cb64e 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
@@ -28,6 +28,7 @@ import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -187,6 +188,11 @@ public class ClusterResourceProviderTest {
     Capture<Set<StackConfigurationRequest>> 
serviceConfigurationRequestCapture1 = new 
Capture<Set<StackConfigurationRequest>>();
     Capture<Set<StackConfigurationRequest>> 
serviceConfigurationRequestCapture2 = new 
Capture<Set<StackConfigurationRequest>>();
 
+    Map<String, String> coreSiteAttributes = new HashMap<String, String>();
+    coreSiteAttributes.put("final", "true");
+    Map<String, String> hdfsSiteAttributes = new HashMap<String, String>();
+    hdfsSiteAttributes.put("final", "true");
+
     BlueprintConfigEntity blueprintConfig = 
createNiceMock(BlueprintConfigEntity.class);
     BlueprintConfigEntity blueprintConfig2 = 
createNiceMock(BlueprintConfigEntity.class);
 
@@ -322,6 +328,7 @@ public class ClusterResourceProviderTest {
     expect(stackConfigurationResponse1.getType()).andReturn("core-site.xml");
     
expect(stackConfigurationResponse1.getPropertyName()).andReturn("property1");
     expect(stackConfigurationResponse1.getPropertyValue()).andReturn("value1");
+    
expect(stackConfigurationResponse1.getPropertyAttributes()).andReturn(coreSiteAttributes);
 
     
expect(managementController.getStackComponents(capture(serviceComponentRequestCapture2))).
         andReturn(stackServiceComponentResponses2);
@@ -332,6 +339,7 @@ public class ClusterResourceProviderTest {
     expect(stackConfigurationResponse2.getType()).andReturn("hdfs-site.xml");
     
expect(stackConfigurationResponse2.getPropertyName()).andReturn("property2");
     expect(stackConfigurationResponse2.getPropertyValue()).andReturn("value2");
+    
expect(stackConfigurationResponse2.getPropertyAttributes()).andReturn(hdfsSiteAttributes);
 
     expect(stackConfigurationResponse3.getType()).andReturn("global.xml");
     
expect(stackConfigurationResponse3.getPropertyName()).andReturn("oozie_user");
@@ -500,6 +508,10 @@ public class ClusterResourceProviderTest {
     ConfigurationRequest hdfsConfigRequest = 
mapConfigRequests.get("hdfs-site");
     assertEquals(1, hdfsConfigRequest.getProperties().size());
     assertEquals("value2", hdfsConfigRequest.getProperties().get("property2"));
+    Map<String, Map<String, String>> hdfsAttributes = 
hdfsConfigRequest.getPropertiesAttributes();
+    assertTrue(hdfsAttributes.containsKey("final"));
+    assertEquals(1, hdfsAttributes.get("final").size());
+    assertEquals("true", hdfsAttributes.get("final").get("property2"));
     ConfigurationRequest coreConfigRequest = 
mapConfigRequests.get("core-site");
     assertEquals(5, coreConfigRequest.getProperties().size());
     assertEquals("value2", coreConfigRequest.getProperties().get("property1"));
@@ -507,6 +519,10 @@ public class ClusterResourceProviderTest {
     assertEquals("*", 
coreConfigRequest.getProperties().get("hadoop.proxyuser.oozie.hosts"));
     assertEquals("users", 
coreConfigRequest.getProperties().get("hadoop.proxyuser.oozie.groups"));
     assertEquals("new.property.value", 
coreConfigRequest.getProperties().get("new.property"));
+    Map<String, Map<String, String>> coreAttributes = 
coreConfigRequest.getPropertiesAttributes();
+    assertTrue(coreAttributes.containsKey("final"));
+    assertEquals(1, coreAttributes.get("final").size());
+    assertEquals("true", coreAttributes.get("final").get("property1"));
     ConfigurationRequest hiveConfigRequest = 
mapConfigRequests.get("hive-site");
     assertEquals(1, hiveConfigRequest.getProperties().size());
     assertEquals("host.domain:12345", 
hiveConfigRequest.getProperties().get("javax.jdo.option.ConnectionURL"));
@@ -1904,6 +1920,463 @@ public class ClusterResourceProviderTest {
     }
   }
 
+  @Test
+  public void testCreateResource_blueprint_attrbiutesProvided() throws 
Exception {
+    String blueprintName = "test-blueprint";
+    String stackName = "test";
+    String stackVersion = "1.23";
+    String clusterName = "c1";
+
+    BlueprintDAO blueprintDAO = createStrictMock(BlueprintDAO.class);
+    AmbariMetaInfo metaInfo = createMock(AmbariMetaInfo.class);
+    AmbariManagementController managementController = 
createStrictMock(AmbariManagementController.class);
+    Request request = createNiceMock(Request.class);
+    RequestStatusResponse response = 
createNiceMock(RequestStatusResponse.class);
+    BlueprintEntity blueprint = createNiceMock(BlueprintEntity.class);
+    StackServiceResponse stackServiceResponse1 = 
createNiceMock(StackServiceResponse.class);
+    StackServiceResponse stackServiceResponse2 = 
createNiceMock(StackServiceResponse.class);
+    Capture<Set<StackServiceRequest>> stackServiceRequestCapture = new 
Capture<Set<StackServiceRequest>>();
+
+    StackServiceComponentResponse stackServiceComponentResponse1 = 
createNiceMock(StackServiceComponentResponse.class);
+    StackServiceComponentResponse stackServiceComponentResponse2 = 
createNiceMock(StackServiceComponentResponse.class);
+    StackServiceComponentResponse stackServiceComponentResponse3 = 
createNiceMock(StackServiceComponentResponse.class);
+    StackServiceComponentResponse stackServiceComponentResponse4 = 
createNiceMock(StackServiceComponentResponse.class);
+    Capture<Set<StackServiceComponentRequest>> serviceComponentRequestCapture1 
= new Capture<Set<StackServiceComponentRequest>>();
+    Capture<Set<StackServiceComponentRequest>> serviceComponentRequestCapture2 
= new Capture<Set<StackServiceComponentRequest>>();
+
+    StackConfigurationResponse stackConfigurationResponse1 = 
createNiceMock(StackConfigurationResponse.class);
+    StackConfigurationResponse stackConfigurationResponse2 = 
createNiceMock(StackConfigurationResponse.class);
+    StackConfigurationResponse stackConfigurationResponse3 = 
createNiceMock(StackConfigurationResponse.class);
+    StackConfigurationResponse stackConfigurationResponse4 = 
createNiceMock(StackConfigurationResponse.class);
+    StackConfigurationResponse stackConfigurationResponse5 = 
createNiceMock(StackConfigurationResponse.class);
+    Capture<Set<StackConfigurationRequest>> 
serviceConfigurationRequestCapture1 = new 
Capture<Set<StackConfigurationRequest>>();
+    Capture<Set<StackConfigurationRequest>> 
serviceConfigurationRequestCapture2 = new 
Capture<Set<StackConfigurationRequest>>();
+
+    Map<String, String> coreSiteAttributes = new HashMap<String, String>();
+    coreSiteAttributes.put("final", "true");
+    Map<String, String> hdfsSiteAttributes = new HashMap<String, String>();
+    hdfsSiteAttributes.put("final", "true");
+
+    BlueprintConfigEntity blueprintConfig = 
createNiceMock(BlueprintConfigEntity.class);
+    BlueprintConfigEntity blueprintConfig2 = 
createNiceMock(BlueprintConfigEntity.class);
+
+    HostGroupEntity hostGroup = createNiceMock(HostGroupEntity.class);
+    HostGroupComponentEntity hostGroupComponent1 = 
createNiceMock(HostGroupComponentEntity.class);
+    HostGroupComponentEntity hostGroupComponent2 = 
createNiceMock(HostGroupComponentEntity.class);
+    HostGroupComponentEntity hostGroupComponent3 = 
createNiceMock(HostGroupComponentEntity.class);
+    HostGroupComponentEntity hostGroupComponent4 = 
createNiceMock(HostGroupComponentEntity.class);
+
+    HostGroupConfigEntity hostGroupConfig = 
createNiceMock(HostGroupConfigEntity.class);
+
+    ServiceResourceProvider serviceResourceProvider = 
createStrictMock(ServiceResourceProvider.class);
+    ResourceProvider componentResourceProvider = 
createStrictMock(ResourceProvider.class);
+    ResourceProvider hostResourceProvider = 
createStrictMock(ResourceProvider.class);
+    ResourceProvider hostComponentResourceProvider = 
createStrictMock(ResourceProvider.class);
+    ConfigGroupResourceProvider configGroupResourceProvider = 
createStrictMock(ConfigGroupResourceProvider.class);
+    PersistKeyValueImpl persistKeyValue = 
createNiceMock(PersistKeyValueImpl.class);
+
+    Capture<ClusterRequest> createClusterRequestCapture = new 
Capture<ClusterRequest>();
+    Capture<Set<ClusterRequest>> updateClusterRequestCapture = new 
Capture<Set<ClusterRequest>>();
+    Capture<Map<String, String>> updateClusterPropertyMapCapture = new 
Capture<Map<String, String>>();
+    Capture<Set<ClusterRequest>> updateClusterRequestCapture2 = new 
Capture<Set<ClusterRequest>>();
+    Capture<Map<String, String>> updateClusterPropertyMapCapture2 = new 
Capture<Map<String, String>>();
+    Capture<Set<ClusterRequest>> updateClusterRequestCapture3 = new 
Capture<Set<ClusterRequest>>();
+    Capture<Map<String, String>> updateClusterPropertyMapCapture3 = new 
Capture<Map<String, String>>();
+    Capture<Set<ClusterRequest>> updateClusterRequestCapture4 = new 
Capture<Set<ClusterRequest>>();
+    Capture<Map<String, String>> updateClusterPropertyMapCapture4 = new 
Capture<Map<String, String>>();
+    Capture<Set<ClusterRequest>> updateClusterRequestCapture5 = new 
Capture<Set<ClusterRequest>>();
+    Capture<Map<String, String>> updateClusterPropertyMapCapture5 = new 
Capture<Map<String, String>>();
+
+    Capture<Request> serviceRequestCapture = new Capture<Request>();
+    Capture<Request> componentRequestCapture = new Capture<Request>();
+    Capture<Request> componentRequestCapture2 = new Capture<Request>();
+    Capture<Request> hostRequestCapture = new Capture<Request>();
+    Capture<Request> hostComponentRequestCapture = new Capture<Request>();
+    Capture<Set<ConfigGroupRequest>> configGroupRequestCapture = new 
Capture<Set<ConfigGroupRequest>>();
+
+    Set<StackServiceResponse> stackServiceResponses = new 
LinkedHashSet<StackServiceResponse>();
+    stackServiceResponses.add(stackServiceResponse1);
+    stackServiceResponses.add(stackServiceResponse2);
+
+    // service1 has 3 components
+    Set<StackServiceComponentResponse> stackServiceComponentResponses1 = new 
LinkedHashSet<StackServiceComponentResponse>();
+    stackServiceComponentResponses1.add(stackServiceComponentResponse1);
+    stackServiceComponentResponses1.add(stackServiceComponentResponse2);
+    stackServiceComponentResponses1.add(stackServiceComponentResponse4);
+
+    // service2 has 1 components
+    Set<StackServiceComponentResponse> stackServiceComponentResponses2 = new 
LinkedHashSet<StackServiceComponentResponse>();
+    stackServiceComponentResponses2.add(stackServiceComponentResponse3);
+
+    // service1 has 2 config
+    Set<StackConfigurationResponse> stackConfigurationResponses1 = new 
LinkedHashSet<StackConfigurationResponse>();
+    stackConfigurationResponses1.add(stackConfigurationResponse1);
+    stackConfigurationResponses1.add(stackConfigurationResponse5);
+
+    // service2 has 3 config
+    Set<StackConfigurationResponse> stackConfigurationResponses2 = new 
LinkedHashSet<StackConfigurationResponse>();
+    stackConfigurationResponses2.add(stackConfigurationResponse2);
+    stackConfigurationResponses2.add(stackConfigurationResponse3);
+    stackConfigurationResponses2.add(stackConfigurationResponse4);
+
+    Collection<HostGroupComponentEntity> hostGroupComponents = new 
LinkedHashSet<HostGroupComponentEntity>();
+    hostGroupComponents.add(hostGroupComponent1);
+    hostGroupComponents.add(hostGroupComponent2);
+    hostGroupComponents.add(hostGroupComponent3);
+    hostGroupComponents.add(hostGroupComponent4);
+
+    // request properties
+    Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, 
Object>>();
+    Map<String, Object> properties = new LinkedHashMap<String, Object>();
+
+    properties.put(ClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID, 
clusterName);
+    properties.put(ClusterResourceProvider.BLUEPRINT_PROPERTY_ID, 
blueprintName);
+    propertySet.add(properties);
+
+    Collection<Map<String, Object>> hostGroups = new ArrayList<Map<String, 
Object>>();
+    Map<String, Object> hostGroupProperties = new HashMap<String, Object>();
+    hostGroups.add(hostGroupProperties);
+    hostGroupProperties.put("name", "group1");
+    Collection<Map<String, String>> hostGroupHosts = new ArrayList<Map<String, 
String>>();
+    hostGroupProperties.put("hosts", hostGroupHosts);
+    Map<String, String> hostGroupHostProperties = new HashMap<String, 
String>();
+    hostGroupHostProperties.put("fqdn", "host.domain");
+    hostGroupHosts.add(hostGroupHostProperties);
+    properties.put("host_groups", hostGroups);
+
+    Map<String, String> mapGroupConfigProperties = new HashMap<String, 
String>();
+    mapGroupConfigProperties.put("myGroupProp", "awesomeValue");
+
+    // blueprint core-site cluster configuration properties
+    Map<String, String> blueprintCoreConfigProperties = new HashMap<String, 
String>();
+    blueprintCoreConfigProperties.put("property1", "value2");
+    blueprintCoreConfigProperties.put("new.property", "new.property.value");
+
+    Map<String, String> blueprintGlobalConfigProperties = new HashMap<String, 
String>();
+    blueprintGlobalConfigProperties.put("hive_database", "New MySQL Database");
+
+    // blueprint core-site cluster configuration properties
+    Map<String, Map<String, String>> blueprintCoreConfigAttributes = new 
HashMap<String, Map<String, String>>();
+    Map<String, String> coreFinalAttributes = new HashMap<String, String>();
+    coreFinalAttributes.put("property1", "false");
+    coreFinalAttributes.put("new.property", "true");
+    blueprintCoreConfigAttributes.put("final", coreFinalAttributes);
+
+    Map<String, Map<String, String>> blueprintHiveEnvConfigAttributes = new 
HashMap<String, Map<String, String>>();
+    Map<String, String> globalFinalAttributes = new HashMap<String, String>();
+    globalFinalAttributes.put("hive_database", "true");
+    blueprintHiveEnvConfigAttributes.put("final", globalFinalAttributes);
+
+    Collection<BlueprintConfigEntity> configurations = new 
HashSet<BlueprintConfigEntity>();
+    configurations.add(blueprintConfig);
+    configurations.add(blueprintConfig2);
+
+    // expectations
+    expect(request.getProperties()).andReturn(propertySet).anyTimes();
+    expect(blueprintDAO.findByName(blueprintName)).andReturn(blueprint);
+    expect(blueprint.getStackName()).andReturn(stackName);
+    expect(blueprint.getStackVersion()).andReturn(stackVersion);
+    expect(blueprint.getConfigurations()).andReturn(configurations).times(2);
+    expect(blueprint.validateConfigurations(metaInfo, 
PropertyInfo.PropertyType.PASSWORD)).andReturn(
+        Collections.<String, Map<String, Collection<String>>>emptyMap());
+
+    expect(metaInfo.getComponentDependencies("test", "1.23", "service1", 
"component1")).
+        andReturn(Collections.<DependencyInfo>emptyList());
+    expect(metaInfo.getComponentDependencies("test", "1.23", "service1", 
"component2")).
+        andReturn(Collections.<DependencyInfo>emptyList());
+    expect(metaInfo.getComponentDependencies("test", "1.23", "service1", 
"MYSQL_SERVER")).
+        andReturn(Collections.<DependencyInfo>emptyList());
+    expect(metaInfo.getComponentDependencies("test", "1.23", "service2", 
"component3")).
+        andReturn(Collections.<DependencyInfo>emptyList());
+
+    
expect(managementController.getStackServices(capture(stackServiceRequestCapture))).andReturn(stackServiceResponses);
+    expect(stackServiceResponse1.getServiceName()).andReturn("service1");
+    expect(stackServiceResponse2.getServiceName()).andReturn("service2");
+
+    
expect(managementController.getStackComponents(capture(serviceComponentRequestCapture1))).
+        andReturn(stackServiceComponentResponses1);
+    
expect(stackServiceComponentResponse1.getComponentName()).andReturn("component1");
+    
expect(stackServiceComponentResponse2.getComponentName()).andReturn("component2");
+    
expect(stackServiceComponentResponse4.getComponentName()).andReturn("MYSQL_SERVER");
+
+    
expect(managementController.getStackConfigurations(capture(serviceConfigurationRequestCapture1))).
+        andReturn(stackConfigurationResponses1);
+    expect(stackConfigurationResponse1.getType()).andReturn("core-site.xml");
+    
expect(stackConfigurationResponse1.getPropertyName()).andReturn("property1");
+    expect(stackConfigurationResponse1.getPropertyValue()).andReturn("value1");
+    
expect(stackConfigurationResponse1.getPropertyAttributes()).andReturn(coreSiteAttributes);
+
+    
expect(managementController.getStackComponents(capture(serviceComponentRequestCapture2))).
+        andReturn(stackServiceComponentResponses2);
+    
expect(stackServiceComponentResponse3.getComponentName()).andReturn("component3");
+
+    
expect(managementController.getStackConfigurations(capture(serviceConfigurationRequestCapture2))).
+        andReturn(stackConfigurationResponses2);
+    expect(stackConfigurationResponse2.getType()).andReturn("hdfs-site.xml");
+    
expect(stackConfigurationResponse2.getPropertyName()).andReturn("property2");
+    expect(stackConfigurationResponse2.getPropertyValue()).andReturn("value2");
+    
expect(stackConfigurationResponse2.getPropertyAttributes()).andReturn(hdfsSiteAttributes);
+
+    expect(stackConfigurationResponse3.getType()).andReturn("global.xml");
+    
expect(stackConfigurationResponse3.getPropertyName()).andReturn("oozie_user");
+    expect(stackConfigurationResponse3.getPropertyValue()).andReturn("oozie");
+
+    expect(stackConfigurationResponse4.getType()).andReturn("core-site.xml");
+    
expect(stackConfigurationResponse4.getPropertyName()).andReturn("property3");
+    expect(stackConfigurationResponse4.getPropertyValue()).andReturn("value3");
+
+    expect(stackConfigurationResponse5.getType()).andReturn("hive-site.xml");
+    
expect(stackConfigurationResponse5.getPropertyName()).andReturn("javax.jdo.option.ConnectionURL");
+    
expect(stackConfigurationResponse5.getPropertyValue()).andReturn("localhost:12345");
+
+    
expect(blueprintConfig.getBlueprintName()).andReturn("test-blueprint").anyTimes();
+    expect(blueprintConfig.getType()).andReturn("core-site").anyTimes();
+    expect(blueprintConfig.getConfigData()).andReturn(new 
Gson().toJson(blueprintCoreConfigProperties)).anyTimes();
+    expect(blueprintConfig.getConfigAttributes()).andReturn(new 
Gson().toJson(blueprintCoreConfigAttributes)).anyTimes();
+    
expect(blueprintConfig2.getBlueprintName()).andReturn("test-blueprint").anyTimes();
+    expect(blueprintConfig2.getType()).andReturn("hive-env").anyTimes();
+    expect(blueprintConfig2.getConfigData()).andReturn(new 
Gson().toJson(blueprintGlobalConfigProperties)).anyTimes();
+    expect(blueprintConfig2.getConfigAttributes()).andReturn(new 
Gson().toJson(blueprintHiveEnvConfigAttributes)).anyTimes();
+
+    
expect(blueprint.getHostGroups()).andReturn(Collections.singleton(hostGroup)).anyTimes();
+    expect(hostGroup.getName()).andReturn("group1").anyTimes();
+    
expect(hostGroup.getComponents()).andReturn(hostGroupComponents).anyTimes();
+    expect(hostGroupComponent1.getName()).andReturn("component1").anyTimes();
+    expect(hostGroupComponent2.getName()).andReturn("component2").anyTimes();
+    expect(hostGroupComponent3.getName()).andReturn("component3").anyTimes();
+    expect(hostGroupComponent4.getName()).andReturn("MYSQL_SERVER").anyTimes();
+    expect(hostGroup.getConfigurations()).andReturn(
+        
Collections.<HostGroupConfigEntity>singleton(hostGroupConfig)).anyTimes();
+
+    expect(hostGroupConfig.getType()).andReturn("core-site").anyTimes();
+    expect(hostGroupConfig.getConfigData()).andReturn(new 
Gson().toJson(mapGroupConfigProperties)).anyTimes();
+
+    managementController.createCluster(capture(createClusterRequestCapture));
+    
expect(managementController.updateClusters(capture(updateClusterRequestCapture),
+        capture(updateClusterPropertyMapCapture))).andReturn(null);
+    
expect(managementController.updateClusters(capture(updateClusterRequestCapture2),
+        capture(updateClusterPropertyMapCapture2))).andReturn(null);
+    
expect(managementController.updateClusters(capture(updateClusterRequestCapture3),
+        capture(updateClusterPropertyMapCapture3))).andReturn(null);
+    
expect(managementController.updateClusters(capture(updateClusterRequestCapture4),
+        capture(updateClusterPropertyMapCapture4))).andReturn(null);
+    
expect(managementController.updateClusters(capture(updateClusterRequestCapture5),
+        capture(updateClusterPropertyMapCapture5))).andReturn(null);
+
+    
expect(serviceResourceProvider.createResources(capture(serviceRequestCapture))).andReturn(null);
+    
expect(componentResourceProvider.createResources(capture(componentRequestCapture))).andReturn(null);
+    
expect(componentResourceProvider.createResources(capture(componentRequestCapture2))).andReturn(null);
+    
expect(hostResourceProvider.createResources(capture(hostRequestCapture))).andReturn(null);
+    
expect(hostComponentResourceProvider.createResources(capture(hostComponentRequestCapture))).andReturn(null);
+
+    
expect(serviceResourceProvider.installAndStart(clusterName)).andReturn(response);
+
+    expect(configGroupResourceProvider.createResources(
+        capture(configGroupRequestCapture))).andReturn(null);
+
+    persistKeyValue.put("CLUSTER_CURRENT_STATUS", 
"{\"clusterState\":\"CLUSTER_STARTED_5\"}");
+
+    replay(blueprintDAO, managementController, request, response, blueprint, 
stackServiceResponse1, stackServiceResponse2,
+        stackServiceComponentResponse1, stackServiceComponentResponse2, 
stackServiceComponentResponse3,
+        stackServiceComponentResponse4, stackConfigurationResponse1, 
stackConfigurationResponse2,
+        stackConfigurationResponse3, stackConfigurationResponse4, 
stackConfigurationResponse5, blueprintConfig,
+        blueprintConfig2, hostGroup, hostGroupComponent1, hostGroupComponent2, 
hostGroupComponent3, hostGroupComponent4,
+        hostGroupConfig, serviceResourceProvider, componentResourceProvider, 
hostResourceProvider,
+        hostComponentResourceProvider, configGroupResourceProvider, 
persistKeyValue, metaInfo);
+
+    // test
+    ClusterResourceProvider.init(blueprintDAO, metaInfo);
+    PersistKeyValueService.init(persistKeyValue);
+    ResourceProvider provider = new TestClusterResourceProvider(
+        managementController, serviceResourceProvider, 
componentResourceProvider,
+        hostResourceProvider, hostComponentResourceProvider, 
configGroupResourceProvider);
+
+    RequestStatus requestStatus = provider.createResources(request);
+
+    assertEquals(RequestStatus.Status.InProgress, requestStatus.getStatus());
+
+    Set<StackServiceRequest> stackServiceRequests = 
stackServiceRequestCapture.getValue();
+    assertEquals(1, stackServiceRequests.size());
+    StackServiceRequest ssr = stackServiceRequests.iterator().next();
+    assertNull(ssr.getServiceName());
+    assertEquals("test", ssr.getStackName());
+    assertEquals("1.23", ssr.getStackVersion());
+
+    Set<StackServiceComponentRequest> stackServiceComponentRequests1 = 
serviceComponentRequestCapture1.getValue();
+    Set<StackServiceComponentRequest> stackServiceComponentRequests2 = 
serviceComponentRequestCapture2.getValue();
+    assertEquals(1, stackServiceComponentRequests1.size());
+    assertEquals(1, stackServiceComponentRequests2.size());
+    StackServiceComponentRequest scr1 = 
stackServiceComponentRequests1.iterator().next();
+    StackServiceComponentRequest scr2 = 
stackServiceComponentRequests2.iterator().next();
+    assertNull(scr1.getComponentName());
+    assertNull(scr2.getComponentName());
+    assertEquals("1.23", scr1.getStackVersion());
+    assertEquals("1.23", scr2.getStackVersion());
+    assertEquals("test", scr1.getStackName());
+    assertEquals("test", scr2.getStackName());
+    assertTrue(scr1.getServiceName().equals("service1") || 
scr1.getServiceName().equals("service2"));
+    assertTrue(scr2.getServiceName().equals("service1") || 
scr2.getServiceName().equals("service2") &&
+        ! scr2.getServiceName().equals(scr1.getServiceName()));
+
+    Set<StackConfigurationRequest> serviceConfigurationRequest1 = 
serviceConfigurationRequestCapture1.getValue();
+    Set<StackConfigurationRequest> serviceConfigurationRequest2 = 
serviceConfigurationRequestCapture2.getValue();
+    assertEquals(1, serviceConfigurationRequest1.size());
+    assertEquals(1, serviceConfigurationRequest2.size());
+    StackConfigurationRequest configReq1 = 
serviceConfigurationRequest1.iterator().next();
+    StackConfigurationRequest configReq2 = 
serviceConfigurationRequest2.iterator().next();
+    assertNull(configReq1.getPropertyName());
+    assertNull(configReq2.getPropertyName());
+    assertEquals("1.23", configReq1.getStackVersion());
+    assertEquals("1.23", configReq2.getStackVersion());
+    assertEquals("test", configReq1.getStackName());
+    assertEquals("test", configReq2.getStackName());
+    assertTrue(configReq1.getServiceName().equals("service1") || 
configReq1.getServiceName().equals("service2"));
+    assertTrue(configReq2.getServiceName().equals("service1") || 
configReq2.getServiceName().equals("service2") &&
+        ! configReq2.getServiceName().equals(configReq1.getServiceName()));
+
+    ClusterRequest clusterRequest = createClusterRequestCapture.getValue();
+    assertEquals(clusterName, clusterRequest.getClusterName());
+    assertEquals("test-1.23", clusterRequest.getStackVersion());
+
+    Set<ClusterRequest> updateClusterRequest1 = 
updateClusterRequestCapture.getValue();
+    Set<ClusterRequest> updateClusterRequest2 = 
updateClusterRequestCapture2.getValue();
+    Set<ClusterRequest> updateClusterRequest3 = 
updateClusterRequestCapture3.getValue();
+    Set<ClusterRequest> updateClusterRequest4 = 
updateClusterRequestCapture4.getValue();
+    Set<ClusterRequest> updateClusterRequest5 = 
updateClusterRequestCapture5.getValue();
+    assertEquals(1, updateClusterRequest1.size());
+    assertEquals(1, updateClusterRequest2.size());
+    assertEquals(1, updateClusterRequest3.size());
+    assertEquals(1, updateClusterRequest4.size());
+    assertEquals(1, updateClusterRequest5.size());
+    ClusterRequest ucr1 = updateClusterRequest1.iterator().next();
+    ClusterRequest ucr2 = updateClusterRequest2.iterator().next();
+    ClusterRequest ucr3 = updateClusterRequest3.iterator().next();
+    ClusterRequest ucr4 = updateClusterRequest4.iterator().next();
+    ClusterRequest ucr5 = updateClusterRequest5.iterator().next();
+    assertEquals(clusterName, ucr1.getClusterName());
+    assertEquals(clusterName, ucr2.getClusterName());
+    assertEquals(clusterName, ucr3.getClusterName());
+    assertEquals(clusterName, ucr4.getClusterName());
+    assertEquals(clusterName, ucr5.getClusterName());
+    ConfigurationRequest cr1 = ucr1.getDesiredConfig();
+    ConfigurationRequest cr2 = ucr2.getDesiredConfig();
+    ConfigurationRequest cr3 = ucr3.getDesiredConfig();
+    ConfigurationRequest cr4 = ucr4.getDesiredConfig();
+    ConfigurationRequest cr5 = ucr5.getDesiredConfig();
+    assertEquals("1", cr1.getVersionTag());
+    assertEquals("1", cr2.getVersionTag());
+    assertEquals("1", cr3.getVersionTag());
+    assertEquals("1", cr4.getVersionTag());
+    assertEquals("1", cr5.getVersionTag());
+    Map<String, ConfigurationRequest> mapConfigRequests = new HashMap<String, 
ConfigurationRequest>();
+    mapConfigRequests.put(cr1.getType(), cr1);
+    mapConfigRequests.put(cr2.getType(), cr2);
+    mapConfigRequests.put(cr3.getType(), cr3);
+    mapConfigRequests.put(cr4.getType(), cr4);
+    mapConfigRequests.put(cr5.getType(), cr5);
+    assertEquals(5, mapConfigRequests.size());
+    ConfigurationRequest globalConfigRequest = mapConfigRequests.get("global");
+    assertEquals(4, globalConfigRequest.getProperties().size());
+    assertEquals("hadoop", 
globalConfigRequest.getProperties().get("user_group"));
+    assertEquals("ambari-qa", 
globalConfigRequest.getProperties().get("smokeuser"));
+    assertEquals("default@REPLACEME.NOWHERE", 
globalConfigRequest.getProperties().get("nagios_contact"));
+    assertEquals("oozie", 
globalConfigRequest.getProperties().get("oozie_user"));
+    assertNotNull(globalConfigRequest.getPropertiesAttributes());
+    assertEquals(0, globalConfigRequest.getPropertiesAttributes().size());
+    ConfigurationRequest hiveEnvConfigRequest = 
mapConfigRequests.get("hive-env");
+    assertEquals("New MySQL Database", 
hiveEnvConfigRequest.getProperties().get("hive_database"));
+    assertNotNull(hiveEnvConfigRequest.getPropertiesAttributes());
+    assertEquals(1, hiveEnvConfigRequest.getPropertiesAttributes().size());
+    Map<String, String> hiveEnvFinalAttrs = 
hiveEnvConfigRequest.getPropertiesAttributes().get("final");
+    assertEquals(1, hiveEnvFinalAttrs.size());
+    assertEquals("true", hiveEnvFinalAttrs.get("hive_database"));
+    ConfigurationRequest hdfsConfigRequest = 
mapConfigRequests.get("hdfs-site");
+    assertEquals(1, hdfsConfigRequest.getProperties().size());
+    assertEquals("value2", hdfsConfigRequest.getProperties().get("property2"));
+    Map<String, Map<String, String>> hdfsAttributes = 
hdfsConfigRequest.getPropertiesAttributes();
+    assertTrue(hdfsAttributes.containsKey("final"));
+    assertEquals(1, hdfsAttributes.get("final").size());
+    assertEquals("true", hdfsAttributes.get("final").get("property2"));
+    ConfigurationRequest coreConfigRequest = 
mapConfigRequests.get("core-site");
+    assertEquals(5, coreConfigRequest.getProperties().size());
+    assertEquals("value2", coreConfigRequest.getProperties().get("property1"));
+    assertEquals("value3", coreConfigRequest.getProperties().get("property3"));
+    assertEquals("*", 
coreConfigRequest.getProperties().get("hadoop.proxyuser.oozie.hosts"));
+    assertEquals("users", 
coreConfigRequest.getProperties().get("hadoop.proxyuser.oozie.groups"));
+    assertEquals("new.property.value", 
coreConfigRequest.getProperties().get("new.property"));
+    assertNotNull(coreConfigRequest.getPropertiesAttributes());
+    assertEquals(1, coreConfigRequest.getPropertiesAttributes().size());
+    Map<String, String> coreFinalAttrs = 
coreConfigRequest.getPropertiesAttributes().get("final");
+    assertEquals(2, coreFinalAttrs.size());
+    assertEquals("false", coreFinalAttrs.get("property1"));
+    assertEquals("true", coreFinalAttrs.get("new.property"));
+    ConfigurationRequest hiveConfigRequest = 
mapConfigRequests.get("hive-site");
+    assertEquals(1, hiveConfigRequest.getProperties().size());
+    assertEquals("host.domain:12345", 
hiveConfigRequest.getProperties().get("javax.jdo.option.ConnectionURL"));
+    assertNotNull(hiveConfigRequest.getPropertiesAttributes());
+    assertEquals(0, hiveConfigRequest.getPropertiesAttributes().size());
+
+    assertNull(updateClusterPropertyMapCapture.getValue());
+    assertNull(updateClusterPropertyMapCapture2.getValue());
+    assertNull(updateClusterPropertyMapCapture3.getValue());
+    assertNull(updateClusterPropertyMapCapture4.getValue());
+
+    Request serviceRequest = serviceRequestCapture.getValue();
+    assertEquals(2, serviceRequest.getProperties().size());
+    Request componentRequest = componentRequestCapture.getValue();
+    Request componentRequest2 = componentRequestCapture2.getValue();
+    assertEquals(3, componentRequest.getProperties().size());
+    Set<String> componentRequest1Names = new HashSet<String>();
+    for (Map<String, Object> componentRequest1Properties : 
componentRequest.getProperties()) {
+      assertEquals(3, componentRequest1Properties.size());
+      assertEquals(clusterName, 
componentRequest1Properties.get("ServiceComponentInfo/cluster_name"));
+      assertEquals("service1", 
componentRequest1Properties.get("ServiceComponentInfo/service_name"));
+      componentRequest1Names.add((String) 
componentRequest1Properties.get("ServiceComponentInfo/component_name"));
+    }
+    assertTrue(componentRequest1Names.contains("component1") && 
componentRequest1Names.contains("component2")
+        && componentRequest1Names.contains("MYSQL_SERVER"));
+    assertEquals(1, componentRequest2.getProperties().size());
+    Map<String, Object> componentRequest2Properties = 
componentRequest2.getProperties().iterator().next();
+    assertEquals(clusterName, 
componentRequest2Properties.get("ServiceComponentInfo/cluster_name"));
+    assertEquals("service2", 
componentRequest2Properties.get("ServiceComponentInfo/service_name"));
+    assertEquals("component3", 
componentRequest2Properties.get("ServiceComponentInfo/component_name"));
+    Request hostRequest = hostRequestCapture.getValue();
+    assertEquals(1, hostRequest.getProperties().size());
+    assertEquals(clusterName, 
hostRequest.getProperties().iterator().next().get("Hosts/cluster_name"));
+    assertEquals("host.domain", 
hostRequest.getProperties().iterator().next().get("Hosts/host_name"));
+    Request hostComponentRequest = hostComponentRequestCapture.getValue();
+    assertEquals(4, hostComponentRequest.getProperties().size());
+    Set<String> componentNames = new HashSet<String>();
+    for (Map<String, Object> hostComponentProperties : 
hostComponentRequest.getProperties()) {
+      assertEquals(3, hostComponentProperties.size());
+      assertEquals(clusterName, 
hostComponentProperties.get("HostRoles/cluster_name"));
+      assertEquals("host.domain", 
hostComponentProperties.get("HostRoles/host_name"));
+      componentNames.add((String) 
hostComponentProperties.get("HostRoles/component_name"));
+    }
+    assertTrue(componentNames.contains("component1") && 
componentNames.contains("component2") &&
+        componentNames.contains("component3") && 
componentNames.contains("MYSQL_SERVER"));
+
+    Set<ConfigGroupRequest> configGroupRequests = 
configGroupRequestCapture.getValue();
+    assertEquals(1, configGroupRequests.size());
+    ConfigGroupRequest configGroupRequest = 
configGroupRequests.iterator().next();
+    assertEquals(clusterName, configGroupRequest.getClusterName());
+    assertEquals("group1", configGroupRequest.getGroupName());
+    assertEquals("service1", configGroupRequest.getTag());
+    assertEquals("Host Group Configuration", 
configGroupRequest.getDescription());
+    Set<String> hosts = configGroupRequest.getHosts();
+    assertEquals(1, hosts.size());
+    assertEquals("host.domain", hosts.iterator().next());
+    assertEquals(1, configGroupRequest.getConfigs().size());
+
+    verify(blueprintDAO, managementController, request, response, blueprint, 
stackServiceResponse1, stackServiceResponse2,
+        stackServiceComponentResponse1, stackServiceComponentResponse2, 
stackServiceComponentResponse3,
+        stackServiceComponentResponse4, stackConfigurationResponse1, 
stackConfigurationResponse2,
+        stackConfigurationResponse3, stackConfigurationResponse4, 
stackConfigurationResponse5, blueprintConfig,
+        blueprintConfig2, hostGroup, hostGroupComponent1, hostGroupComponent2, 
hostGroupComponent3, hostGroupComponent4,
+        hostGroupConfig, serviceResourceProvider, componentResourceProvider, 
hostResourceProvider,
+        hostComponentResourceProvider, configGroupResourceProvider, 
persistKeyValue, metaInfo);
+  }
+
   @SuppressWarnings("unchecked")
   @Test
   public void testBlueprintPropertyUpdaters() throws Exception {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProviderTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProviderTest.java
index 7a7b07f..d673671 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackConfigurationResourceProviderTest.java
@@ -23,7 +23,9 @@ import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.ambari.server.controller.AmbariManagementController;
@@ -41,18 +43,20 @@ public class StackConfigurationResourceProviderTest {
   private static final String PROPERTY_VALUE = "value";
   private static final String PROPERTY_DESC = "Desc";
   private static final String TYPE = "type.xml";
-  private static final Boolean FINAL = false;
 
   @Test
   public void testGetResources() throws Exception{
        
+    Map<String, String> attributes = new HashMap<String, String>();
+    attributes.put("final", "true");
+
     Resource.Type type = Resource.Type.StackConfiguration;
 
     AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
 
     Set<StackConfigurationResponse> allResponse = new 
HashSet<StackConfigurationResponse>();
     
-    allResponse.add(new StackConfigurationResponse(PROPERTY_NAME, 
PROPERTY_VALUE, PROPERTY_DESC, TYPE, FINAL));
+    allResponse.add(new StackConfigurationResponse(PROPERTY_NAME, 
PROPERTY_VALUE, PROPERTY_DESC, TYPE, attributes));
    
     // set expectations
     expect(managementController.getStackConfigurations(
@@ -93,14 +97,81 @@ public class StackConfigurationResourceProviderTest {
           
resource.getPropertyValue(StackConfigurationResourceProvider.PROPERTY_DESCRIPTION_PROPERTY_ID);
       String propertyType = (String) 
           
resource.getPropertyValue(StackConfigurationResourceProvider.PROPERTY_TYPE_PROPERTY_ID);
-      Boolean propertyIsFinal = (Boolean)
+      String propertyIsFinal = (String)
           
resource.getPropertyValue(StackConfigurationResourceProvider.PROPERTY_FINAL_PROPERTY_ID);
       
       Assert.assertEquals(PROPERTY_NAME, propertyName);
       Assert.assertEquals(PROPERTY_VALUE, propertyValue);
       Assert.assertEquals(PROPERTY_DESC, propertyDesc);
       Assert.assertEquals(TYPE, propertyType);
-      Assert.assertEquals(FINAL, propertyIsFinal);
+      Assert.assertEquals("true", propertyIsFinal);
+
+    }
+
+    // verify
+    verify(managementController);
+  }
+
+  @Test
+  public void testGetResources_noFinal() throws Exception{
+
+    Map<String, String> attributes = new HashMap<String, String>();
+
+    Resource.Type type = Resource.Type.StackConfiguration;
+
+    AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
+
+    Set<StackConfigurationResponse> allResponse = new 
HashSet<StackConfigurationResponse>();
+
+    allResponse.add(new StackConfigurationResponse(PROPERTY_NAME, 
PROPERTY_VALUE, PROPERTY_DESC, TYPE, attributes));
+
+    // set expectations
+    expect(managementController.getStackConfigurations(
+        
AbstractResourceProviderTest.Matcher.getStackConfigurationRequestSet(null, 
null, null, null))).
+        andReturn(allResponse).times(1);
+    // replay
+    replay(managementController);
+
+    ResourceProvider provider = 
AbstractControllerResourceProvider.getResourceProvider(
+        type,
+        PropertyHelper.getPropertyIds(type),
+        PropertyHelper.getKeyPropertyIds(type),
+        managementController);
+
+    Set<String> propertyIds = new HashSet<String>();
+
+    propertyIds.add(StackConfigurationResourceProvider.STACK_NAME_PROPERTY_ID);
+    
propertyIds.add(StackConfigurationResourceProvider.STACK_VERSION_PROPERTY_ID);
+    
propertyIds.add(StackConfigurationResourceProvider.SERVICE_NAME_PROPERTY_ID);
+    
propertyIds.add(StackConfigurationResourceProvider.PROPERTY_NAME_PROPERTY_ID);
+    
propertyIds.add(StackConfigurationResourceProvider.PROPERTY_VALUE_PROPERTY_ID);
+    
propertyIds.add(StackConfigurationResourceProvider.PROPERTY_DESCRIPTION_PROPERTY_ID);
+    
propertyIds.add(StackConfigurationResourceProvider.PROPERTY_TYPE_PROPERTY_ID);
+    
propertyIds.add(StackConfigurationResourceProvider.PROPERTY_FINAL_PROPERTY_ID);
+
+    // create the request
+    Request request = PropertyHelper.getReadRequest(propertyIds);
+
+    // get all ... no predicate
+    Set<Resource> resources = provider.getResources(request, null);
+
+    Assert.assertEquals(allResponse.size(), resources.size());
+
+    for (Resource resource : resources) {
+      String propertyName = (String) 
resource.getPropertyValue(StackConfigurationResourceProvider.PROPERTY_NAME_PROPERTY_ID);
+      String propertyValue = (String) 
resource.getPropertyValue(StackConfigurationResourceProvider.PROPERTY_VALUE_PROPERTY_ID);
+      String propertyDesc = (String)
+          
resource.getPropertyValue(StackConfigurationResourceProvider.PROPERTY_DESCRIPTION_PROPERTY_ID);
+      String propertyType = (String)
+          
resource.getPropertyValue(StackConfigurationResourceProvider.PROPERTY_TYPE_PROPERTY_ID);
+      String propertyIsFinal = (String)
+          
resource.getPropertyValue(StackConfigurationResourceProvider.PROPERTY_FINAL_PROPERTY_ID);
+
+      Assert.assertEquals(PROPERTY_NAME, propertyName);
+      Assert.assertEquals(PROPERTY_VALUE, propertyValue);
+      Assert.assertEquals(PROPERTY_DESC, propertyDesc);
+      Assert.assertEquals(TYPE, propertyType);
+      Assert.assertEquals("false", propertyIsFinal);
 
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/test/java/org/apache/ambari/server/state/PropertyInfoTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/state/PropertyInfoTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/state/PropertyInfoTest.java
new file mode 100644
index 0000000..c4eff8c
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/state/PropertyInfoTest.java
@@ -0,0 +1,62 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.state;
+
+import org.apache.ambari.server.api.util.StackExtensionHelper;
+import org.apache.ambari.server.state.stack.ConfigurationXml;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+public class PropertyInfoTest {
+
+  @Test
+  public void testGetAttributesMap() throws Exception {
+    Map<String, String> attributes;
+    File configFile = new 
File("./src/test/resources/stacks/HDP/2.0.8/services/HDFS/configuration/hdfs-site.xml");
+    ConfigurationXml configuration = 
StackExtensionHelper.unmarshal(ConfigurationXml.class, configFile);
+    List<PropertyInfo> properties = configuration.getProperties();
+    PropertyInfo dfsNameDir = properties.get(0);
+    assertNotNull(dfsNameDir);
+    assertEquals("dfs.name.dir", dfsNameDir.getName());
+    attributes = dfsNameDir.getAttributesMap();
+    assertEquals(1, attributes.size());
+    assertTrue(attributes.containsKey("final"));
+    assertEquals("true", attributes.get("final"));
+
+    PropertyInfo dfsSupportAppend = properties.get(1);
+    assertNotNull(dfsSupportAppend);
+    assertEquals("dfs.support.append", dfsSupportAppend.getName());
+    attributes = dfsSupportAppend.getAttributesMap();
+    assertEquals(2, attributes.size());
+    assertTrue(attributes.containsKey("final"));
+    assertEquals("true", attributes.get("final"));
+    assertTrue(attributes.containsKey("deletable"));
+    assertEquals("false", attributes.get("deletable"));
+
+    PropertyInfo dfsWebhdfsEnabled = properties.get(2);
+    assertNotNull(dfsWebhdfsEnabled);
+    assertEquals("dfs.webhdfs.enabled", dfsWebhdfsEnabled.getName());
+    attributes = dfsWebhdfsEnabled.getAttributesMap();
+    assertEquals(0, attributes.size());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/2885f191/ambari-server/src/test/resources/stacks/HDP/2.0.8/services/HDFS/configuration/hdfs-site.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/resources/stacks/HDP/2.0.8/services/HDFS/configuration/hdfs-site.xml
 
b/ambari-server/src/test/resources/stacks/HDP/2.0.8/services/HDFS/configuration/hdfs-site.xml
new file mode 100644
index 0000000..c40fbd0
--- /dev/null
+++ 
b/ambari-server/src/test/resources/stacks/HDP/2.0.8/services/HDFS/configuration/hdfs-site.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<configuration>
+
+  <property>
+    <name>dfs.name.dir</name>
+    <value></value>
+    <description>Determines where on the local filesystem the DFS name node
+      should store the name table.</description>
+    <final>true</final>
+  </property>
+
+  <property>
+    <name>dfs.support.append</name>
+    <value>true</value>
+    <description>to enable dfs append</description>
+    <final>true</final>
+    <deletable>false</deletable>
+  </property>
+
+  <property>
+    <name>dfs.webhdfs.enabled</name>
+    <value>true</value>
+    <description>to enable webhdfs</description>
+  </property>
+
+</configuration>

Reply via email to