You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by js...@apache.org on 2014/05/01 21:32:09 UTC

git commit: AMBARI-5648. Provide basic validation of fields for blueprint create api.

Repository: ambari
Updated Branches:
  refs/heads/trunk b0d850eb9 -> 327f9c3a8


AMBARI-5648.  Provide basic validation of fields for blueprint create api.


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

Branch: refs/heads/trunk
Commit: 327f9c3a87e9faad3a6acddbea5863851c3cd799
Parents: b0d850e
Author: John Speidel <js...@hortonworks.com>
Authored: Wed Apr 30 22:01:44 2014 -0400
Committer: John Speidel <js...@hortonworks.com>
Committed: Thu May 1 15:31:26 2014 -0400

----------------------------------------------------------------------
 .../ambari/server/controller/AmbariServer.java  |   3 +-
 .../internal/BlueprintResourceProvider.java     | 173 +++++++--
 .../server/orm/entities/HostGroupEntity.java    |   6 +-
 .../internal/BlueprintResourceProviderTest.java | 380 ++++++++++++++++++-
 4 files changed, 512 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/327f9c3a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index cdb7fea..5ee07e0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -511,7 +511,8 @@ public class AmbariServer {
     StackDefinedPropertyProvider.init(injector);
     NagiosPropertyProvider.init(injector);
     AbstractControllerResourceProvider.init(injector.getInstance(ResourceProviderFactory.class));
-    BlueprintResourceProvider.init(injector.getInstance(BlueprintDAO.class), injector.getInstance(Gson.class));
+    BlueprintResourceProvider.init(injector.getInstance(BlueprintDAO.class),
+        injector.getInstance(Gson.class), ambariMetaInfo);
     StackDependencyResourceProvider.init(ambariMetaInfo);
     ClusterResourceProvider.injectBlueprintDAO(injector.getInstance(BlueprintDAO.class));
     ViewRegistry.init(injector.getInstance(ViewDAO.class), injector.getInstance(ViewInstanceDAO.class));

http://git-wip-us.apache.org/repos/asf/ambari/blob/327f9c3a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
index ea2fdec..353b58f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
@@ -22,6 +22,7 @@ import com.google.gson.Gson;
 import com.google.inject.Inject;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.DuplicateResourceException;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.Predicate;
@@ -39,6 +40,8 @@ import org.apache.ambari.server.orm.entities.BlueprintEntity;
 import org.apache.ambari.server.orm.entities.HostGroupComponentEntity;
 import org.apache.ambari.server.orm.entities.HostGroupConfigEntity;
 import org.apache.ambari.server.orm.entities.HostGroupEntity;
+import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.ServiceInfo;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -92,6 +95,11 @@ public class BlueprintResourceProvider extends AbstractResourceProvider {
    */
   private static Gson jsonSerializer;
 
+  /**
+   * Stack information.
+   */
+  private static AmbariMetaInfo stackInfo;
+
 
   // ----- Constructors ----------------------------------------------------
 
@@ -110,11 +118,13 @@ public class BlueprintResourceProvider extends AbstractResourceProvider {
    *
    * @param blueprintDAO  blueprint data access object
    * @param gson          gson json serializer
+   * @param metaInfo      stack related information
    */
   @Inject
-  public static void init(BlueprintDAO blueprintDAO, Gson gson) {
+  public static void init(BlueprintDAO blueprintDAO, Gson gson, AmbariMetaInfo metaInfo) {
     dao            = blueprintDAO;
     jsonSerializer = gson;
+    stackInfo      = metaInfo;
   }
 
 
@@ -186,8 +196,7 @@ public class BlueprintResourceProvider extends AbstractResourceProvider {
       throws SystemException, UnsupportedPropertyException,
              NoSuchResourceException, NoSuchParentResourceException {
 
-    // no-op, blueprints are immutable
-    //todo: meaningful error message
+    // no-op, blueprints are immutable.  Service doesn't support PUT so should never get here.
     return null;
   }
 
@@ -319,7 +328,7 @@ public class BlueprintResourceProvider extends AbstractResourceProvider {
    * @return new blueprint entity
    */
   @SuppressWarnings("unchecked")
-  protected BlueprintEntity toEntity(Map<String, Object> properties) {
+  protected BlueprintEntity toBlueprintEntity(Map<String, Object> properties) {
     String name = (String) properties.get(BLUEPRINT_NAME_PROPERTY_ID);
     if (name == null || name.isEmpty()) {
       throw new IllegalArgumentException("Blueprint name must be provided");
@@ -330,42 +339,146 @@ public class BlueprintResourceProvider extends AbstractResourceProvider {
     blueprint.setStackName((String) properties.get(STACK_NAME_PROPERTY_ID));
     blueprint.setStackVersion((String) properties.get(STACK_VERSION_PROPERTY_ID));
 
-    Collection<HostGroupEntity> blueprintHostGroups = new ArrayList<HostGroupEntity>();
-    blueprint.setHostGroups(blueprintHostGroups);
+    createHostGroupEntities(blueprint,
+        (HashSet<HashMap<String, Object>>) properties.get(HOST_GROUP_PROPERTY_ID));
 
-    HashSet<HashMap<String, Object>> setHostGroups =
-        (HashSet<HashMap<String, Object>>) properties.get(HOST_GROUP_PROPERTY_ID);
+    createBlueprintConfigEntities((Collection<Map<String,
+        String>>) properties.get(CONFIGURATION_PROPERTY_ID), blueprint);
+
+    return blueprint;
+  }
+
+  /**
+   * Create host group entities and add to the parent blueprint entity.
+   *
+   * @param blueprint      parent blueprint entity
+   * @param setHostGroups  set of host group property maps
+   */
+  @SuppressWarnings("unchecked")
+  private void createHostGroupEntities(BlueprintEntity blueprint,
+                                       HashSet<HashMap<String, Object>> setHostGroups) {
+
+    if (setHostGroups == null || setHostGroups.isEmpty()) {
+      throw new IllegalArgumentException("At least one host group must be specified in a blueprint");
+    }
+
+    Collection<HostGroupEntity> entities = new ArrayList<HostGroupEntity>();
+    Collection<String> stackComponentNames = getAllStackComponents(
+        blueprint.getStackName(), blueprint.getStackVersion());
 
     for (HashMap<String, Object> hostGroupProperties : setHostGroups) {
-      HostGroupEntity group = new HostGroupEntity();
-      group.setName((String) hostGroupProperties.get(HOST_GROUP_NAME_PROPERTY_ID));
-      group.setBlueprintEntity(blueprint);
-      group.setBlueprintName(name);
-      group.setCardinality((String) hostGroupProperties.get(HOST_GROUP_CARDINALITY_PROPERTY_ID));
+      HostGroupEntity hostGroup = new HostGroupEntity();
+      entities.add(hostGroup);
+
+      String hostGroupName = (String) hostGroupProperties.get(HOST_GROUP_NAME_PROPERTY_ID);
+      if (hostGroupName == null || hostGroupName.isEmpty()) {
+        throw new IllegalArgumentException("Every host group must include a non-null 'name' property");
+      }
+
+      hostGroup.setName(hostGroupName);
+      hostGroup.setBlueprintEntity(blueprint);
+      hostGroup.setBlueprintName(blueprint.getBlueprintName());
+      hostGroup.setCardinality((String) hostGroupProperties.get(HOST_GROUP_CARDINALITY_PROPERTY_ID));
+
       createHostGroupConfigEntities((Collection<Map<String,
-          String>>) hostGroupProperties.get(CONFIGURATION_PROPERTY_ID), group);
+          String>>) hostGroupProperties.get(CONFIGURATION_PROPERTY_ID), hostGroup);
 
-      Collection<HostGroupComponentEntity> components = new ArrayList<HostGroupComponentEntity>();
-      group.setComponents(components);
+      createComponentEntities(hostGroup, (HashSet<HashMap<String, String>>)
+          hostGroupProperties.get(COMPONENT_PROPERTY_ID), stackComponentNames);
+    }
+    blueprint.setHostGroups(entities);
+  }
 
-      HashSet<HashMap<String, String>> setComponents =
-          (HashSet<HashMap<String, String>>) hostGroupProperties.get(COMPONENT_PROPERTY_ID);
-      for (HashMap<String, String> componentProperties : setComponents) {
-        HostGroupComponentEntity component = new HostGroupComponentEntity();
-        component.setName(componentProperties.get(COMPONENT_NAME_PROPERTY_ID));
-        component.setBlueprintName(name);
-        component.setHostGroupEntity(group);
-        component.setHostGroupName((String) hostGroupProperties.get(HOST_GROUP_NAME_PROPERTY_ID));
+  /**
+   * Create component entities and add to parent host group.
+   *
+   * @param group           parent host group
+   * @param setComponents   set of component property maps
+   * @param componentNames  set of all component names for the associated stack
+   */
+  @SuppressWarnings("unchecked")
+  private void createComponentEntities(HostGroupEntity group, HashSet<HashMap<String, String>> setComponents,
+                                       Collection<String> componentNames) {
+    
+    Collection<HostGroupComponentEntity> components = new ArrayList<HostGroupComponentEntity>();
+    String groupName = group.getName();
+    group.setComponents(components);
+
+    if (setComponents == null || setComponents.isEmpty()) {
+      throw new IllegalArgumentException("Host group '" + groupName + "' must contain at least one component");
+    }
 
-        components.add(component);
+    for (HashMap<String, String> componentProperties : setComponents) {
+      HostGroupComponentEntity component = new HostGroupComponentEntity();
+      components.add(component);
+
+      String componentName = componentProperties.get(COMPONENT_NAME_PROPERTY_ID);
+      if (componentName == null || componentName.isEmpty()) {
+        throw new IllegalArgumentException("Host group '" + groupName +
+            "' contains a component with no 'name' property");
       }
-      blueprintHostGroups.add(group);
+
+      if (! componentNames.contains(componentName)) {
+        throw new IllegalArgumentException("The component '" + componentName + "' in host group '" +
+            groupName + "' is not valid for the specified stack");
+      }
+
+      component.setName(componentName);
+      component.setBlueprintName(group.getBlueprintName());
+      component.setHostGroupEntity(group);
+      component.setHostGroupName(group.getName());
     }
+    group.setComponents(components);
+  }
 
-    createBlueprintConfigEntities((Collection<Map<String,
-        String>>) properties.get(CONFIGURATION_PROPERTY_ID), blueprint);
+  /**
+   * Obtain all component names for the specified stack.
+   *
+   * @param stackName     stack name
+   * @param stackVersion  stack version
+   *
+   * @return collection of component names for the specified stack
+   * @throws IllegalArgumentException if the specified stack doesn't exist
+   */
+  private Collection<String> getAllStackComponents(String stackName, String stackVersion) {
+    Collection<String> componentNames = new HashSet<String>();
+    componentNames.add("AMBARI_SERVER");
+    Collection<ComponentInfo> components;
+    try {
+      components = getComponents(stackName, stackVersion);
+    } catch (AmbariException e) {
+      throw new IllegalArgumentException("The specified stack doesn't exist.  Name='" +
+          stackName + "', Version='" + stackVersion + "'");
+    }
+    if (components != null) {
+      for (ComponentInfo component : components) {
+        componentNames.add(component.getName());
+      }
+    }
+    return componentNames;
+  }
 
-    return blueprint;
+  /**
+   * Get all the components for the specified stack.
+   *
+   * @param stackName  stack name
+   * @param version    stack version
+   *
+   * @return all components for the specified stack
+   * @throws AmbariException if the stack doesn't exist
+   */
+  private Collection<ComponentInfo> getComponents(String stackName, String version) throws AmbariException {
+    Collection<ComponentInfo> components = new HashSet<ComponentInfo>();
+    Map<String, ServiceInfo> services = stackInfo.getServices(stackName, version);
+
+    for (ServiceInfo service : services.values()) {
+      List<ComponentInfo> serviceComponents = stackInfo.getComponentsByService(
+          stackName, version, service.getName());
+      for (ComponentInfo component : serviceComponents) {
+        components.add(component);
+      }
+    }
+    return components;
   }
 
   /**
@@ -470,7 +583,7 @@ public class BlueprintResourceProvider extends AbstractResourceProvider {
     return new Command<Void>() {
       @Override
       public Void invoke() throws AmbariException {
-        BlueprintEntity blueprint = toEntity(properties);
+        BlueprintEntity blueprint = toBlueprintEntity(properties);
 
         if (LOG.isDebugEnabled()) {
           LOG.debug("Creating Blueprint, name=" + blueprint.getBlueprintName());

http://git-wip-us.apache.org/repos/asf/ambari/blob/327f9c3a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntity.java
index 863632a..f0422e3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupEntity.java
@@ -47,7 +47,7 @@ public class HostGroupEntity {
 
   @Column
   @Basic
-  private String cardinality;
+  private String cardinality = "NOT SPECIFIED";
 
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "hostGroup")
   private Collection<HostGroupComponentEntity> components;
@@ -165,6 +165,8 @@ public class HostGroupEntity {
    * @param cardinality cardinality value
    */
   public void setCardinality(String cardinality) {
-    this.cardinality = cardinality;
+    if (cardinality != null) {
+      this.cardinality = cardinality;
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/327f9c3a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java
index 9e12c63..f046b00 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintResourceProviderTest.java
@@ -19,6 +19,9 @@
 package org.apache.ambari.server.controller.internal;
 
 import com.google.gson.Gson;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ParentObjectNotFoundException;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.predicate.EqualsPredicate;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
@@ -36,6 +39,8 @@ import org.apache.ambari.server.orm.entities.BlueprintEntity;
 import org.apache.ambari.server.orm.entities.HostGroupComponentEntity;
 import org.apache.ambari.server.orm.entities.HostGroupConfigEntity;
 import org.apache.ambari.server.orm.entities.HostGroupEntity;
+import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.easymock.Capture;
 
 import static org.junit.Assert.assertFalse;
@@ -71,37 +76,58 @@ import static org.junit.Assert.fail;
 /**
  * BlueprintResourceProvider unit tests.
  */
+@SuppressWarnings("unchecked")
 public class BlueprintResourceProviderTest {
 
   private static String BLUEPRINT_NAME = "test-blueprint";
 
   private final static BlueprintDAO dao = createStrictMock(BlueprintDAO.class);
   private final static Gson gson = new Gson();
+  private final static AmbariMetaInfo metaInfo = createStrictMock(AmbariMetaInfo.class);
 
   @BeforeClass
   public static void initClass() {
-    BlueprintResourceProvider.init(dao, gson);
+    BlueprintResourceProvider.init(dao, gson, metaInfo);
   }
 
   @Before
   public void resetGlobalMocks() {
-    reset(dao);
+    reset(dao, metaInfo);
   }
 
   @Test
-  public void testCreateResources() throws ResourceAlreadyExistsException, SystemException,
-                                           UnsupportedPropertyException, NoSuchParentResourceException {
+  public void testCreateResources() throws AmbariException, ResourceAlreadyExistsException, SystemException,
+      UnsupportedPropertyException, NoSuchParentResourceException {
 
-    Set<Map<String, Object>> setProperties = getTestProperties();
     Request request = createMock(Request.class);
+
+    Map<String, ServiceInfo> services = new HashMap<String, ServiceInfo>();
+    ServiceInfo service = new ServiceInfo();
+    service.setName("test-service");
+    services.put("test-service", service);
+
+    List<ComponentInfo> serviceComponents = new ArrayList<ComponentInfo>();
+    ComponentInfo component1 = new ComponentInfo();
+    component1.setName("component1");
+    ComponentInfo component2 = new ComponentInfo();
+    component2.setName("component2");
+    serviceComponents.add(component1);
+    serviceComponents.add(component2);
+
+    Set<Map<String, Object>> setProperties = getTestProperties();
+
+
     Capture<BlueprintEntity> entityCapture = new Capture<BlueprintEntity>();
 
     // set expectations
     expect(request.getProperties()).andReturn(setProperties);
     expect(dao.findByName(BLUEPRINT_NAME)).andReturn(null);
+    expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
+    expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
+        andReturn(serviceComponents).anyTimes();
     dao.create(capture(entityCapture));
 
-    replay(dao, request);
+    replay(dao, metaInfo, request);
     // end expectations
 
     ResourceProvider provider = createProvider();
@@ -119,24 +145,41 @@ public class BlueprintResourceProviderTest {
 
     validateEntity(entityCapture.getValue(), false);
 
-    verify(dao, request);
+    verify(dao, metaInfo, request);
   }
 
   @Test
-  public void testCreateResources_withConfiguration() throws ResourceAlreadyExistsException, SystemException,
+  public void testCreateResources_withConfiguration() throws AmbariException, ResourceAlreadyExistsException, SystemException,
       UnsupportedPropertyException, NoSuchParentResourceException {
 
     Set<Map<String, Object>> setProperties = getTestProperties();
     setConfigurationProperties(setProperties);
     Request request = createMock(Request.class);
+
+    Map<String, ServiceInfo> services = new HashMap<String, ServiceInfo>();
+    ServiceInfo service = new ServiceInfo();
+    service.setName("test-service");
+    services.put("test-service", service);
+
+    List<ComponentInfo> serviceComponents = new ArrayList<ComponentInfo>();
+    ComponentInfo component1 = new ComponentInfo();
+    component1.setName("component1");
+    ComponentInfo component2 = new ComponentInfo();
+    component2.setName("component2");
+    serviceComponents.add(component1);
+    serviceComponents.add(component2);
+
     Capture<BlueprintEntity> entityCapture = new Capture<BlueprintEntity>();
 
     // set expectations
     expect(request.getProperties()).andReturn(setProperties);
     expect(dao.findByName(BLUEPRINT_NAME)).andReturn(null);
+    expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
+    expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
+        andReturn(serviceComponents).anyTimes();
     dao.create(capture(entityCapture));
 
-    replay(dao, request);
+    replay(dao, metaInfo, request);
     // end expectations
 
     ResourceProvider provider = createProvider();
@@ -154,7 +197,7 @@ public class BlueprintResourceProviderTest {
 
     validateEntity(entityCapture.getValue(), true);
 
-    verify(dao, request);
+    verify(dao, metaInfo, request);
   }
 
   @Test
@@ -163,8 +206,7 @@ public class BlueprintResourceProviderTest {
     Request request = createNiceMock(Request.class);
 
     ResourceProvider provider = createProvider();
-    BlueprintEntity entity = ((BlueprintResourceProvider) provider).toEntity(
-        getTestProperties().iterator().next());
+    BlueprintEntity entity = createEntity(getTestProperties().iterator().next());
 
     List<BlueprintEntity> results = new ArrayList<BlueprintEntity>();
     results.add(entity);
@@ -188,8 +230,7 @@ public class BlueprintResourceProviderTest {
     ResourceProvider provider = createProvider();
     Set<Map<String, Object>> testProperties = getTestProperties();
     setConfigurationProperties(testProperties);
-    BlueprintEntity entity = ((BlueprintResourceProvider) provider).toEntity(
-        testProperties.iterator().next());
+    BlueprintEntity entity = createEntity(testProperties.iterator().next());
 
     List<BlueprintEntity> results = new ArrayList<BlueprintEntity>();
     results.add(entity);
@@ -213,8 +254,7 @@ public class BlueprintResourceProviderTest {
     Capture<BlueprintEntity> entityCapture = new Capture<BlueprintEntity>();
 
     ResourceProvider provider = createProvider();
-    BlueprintEntity blueprintEntity = ((BlueprintResourceProvider) provider).toEntity(
-        getTestProperties().iterator().next());
+    BlueprintEntity blueprintEntity = createEntity(getTestProperties().iterator().next());
 
     // set expectations
     expect(dao.findByName(BLUEPRINT_NAME)).andReturn(blueprintEntity);
@@ -240,6 +280,256 @@ public class BlueprintResourceProviderTest {
     validateEntity(entityCapture.getValue(), false);
   }
 
+  @Test
+  public void testCreateResource_validate__NoHostGroups() throws AmbariException, ResourceAlreadyExistsException, SystemException,
+      UnsupportedPropertyException, NoSuchParentResourceException
+  {
+    Request request = createMock(Request.class);
+
+    Set<Map<String, Object>> setProperties = getTestProperties();
+    setProperties.iterator().next().remove(BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID);
+
+    // set expectations
+    expect(request.getProperties()).andReturn(setProperties);
+
+    replay(dao, metaInfo, request);
+    // end expectations
+
+    ResourceProvider provider = createProvider();
+    try {
+      provider.createResources(request);
+      fail("Exception expected");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+    verify(dao, metaInfo, request);
+  }
+
+  @Test
+  public void testCreateResource_Validate__NoHostGroupName() throws AmbariException, ResourceAlreadyExistsException,
+      SystemException, UnsupportedPropertyException, NoSuchParentResourceException
+  {
+    Request request = createMock(Request.class);
+
+    Map<String, ServiceInfo> services = new HashMap<String, ServiceInfo>();
+    ServiceInfo service = new ServiceInfo();
+    service.setName("test-service");
+    services.put("test-service", service);
+
+    List<ComponentInfo> serviceComponents = new ArrayList<ComponentInfo>();
+    ComponentInfo component1 = new ComponentInfo();
+    component1.setName("component1");
+    ComponentInfo component2 = new ComponentInfo();
+    component2.setName("component2");
+    serviceComponents.add(component1);
+    serviceComponents.add(component2);
+
+
+    Set<Map<String, Object>> setProperties = getTestProperties();
+    ((HashSet<Map<String, String>>) setProperties.iterator().next().get(BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID)).
+        iterator().next().put("name", "");
+
+    // set expectations
+    expect(request.getProperties()).andReturn(setProperties);
+    expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
+    expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
+        andReturn(serviceComponents).anyTimes();
+
+    replay(dao, metaInfo, request);
+    // end expectations
+
+    ResourceProvider provider = createProvider();
+    try {
+      provider.createResources(request);
+      fail("Exception expected");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+    verify(dao, metaInfo, request);
+  }
+
+  @Test
+  public void testCreateResource_Validate__NoHostGroupComponents() throws AmbariException, ResourceAlreadyExistsException,
+      SystemException, UnsupportedPropertyException, NoSuchParentResourceException
+  {
+    Request request = createMock(Request.class);
+
+    Map<String, ServiceInfo> services = new HashMap<String, ServiceInfo>();
+    ServiceInfo service = new ServiceInfo();
+    service.setName("test-service");
+    services.put("test-service", service);
+
+    List<ComponentInfo> serviceComponents = new ArrayList<ComponentInfo>();
+    ComponentInfo component1 = new ComponentInfo();
+    component1.setName("component1");
+    ComponentInfo component2 = new ComponentInfo();
+    component2.setName("component2");
+    serviceComponents.add(component1);
+    serviceComponents.add(component2);
+
+
+    Set<Map<String, Object>> setProperties = getTestProperties();
+    ((HashSet<Map<String, String>>) setProperties.iterator().next().get(BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID)).
+        iterator().next().remove("components");
+
+    // set expectations
+    expect(request.getProperties()).andReturn(setProperties);
+    expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
+    expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
+        andReturn(serviceComponents).anyTimes();
+
+    replay(dao, metaInfo, request);
+    // end expectations
+
+    ResourceProvider provider = createProvider();
+    try {
+      provider.createResources(request);
+      fail("Exception expected");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+    verify(dao, metaInfo, request);
+  }
+
+  @Test
+  public void testCreateResource_Validate__NoHostGroupComponentName() throws AmbariException, ResourceAlreadyExistsException,
+      SystemException, UnsupportedPropertyException, NoSuchParentResourceException
+  {
+    Request request = createMock(Request.class);
+
+    Map<String, ServiceInfo> services = new HashMap<String, ServiceInfo>();
+    ServiceInfo service = new ServiceInfo();
+    service.setName("test-service");
+    services.put("test-service", service);
+
+    List<ComponentInfo> serviceComponents = new ArrayList<ComponentInfo>();
+    ComponentInfo component1 = new ComponentInfo();
+    component1.setName("component1");
+    ComponentInfo component2 = new ComponentInfo();
+    component2.setName("component2");
+    serviceComponents.add(component1);
+    serviceComponents.add(component2);
+
+    Set<Map<String, Object>> setProperties = getTestProperties();
+    ((HashSet<Map<String, String>>) ((HashSet<Map<String, Object>>) setProperties.iterator().next().get(
+        BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID)).iterator().next().get("components")).
+        iterator().next().put("name", "");
+
+    // set expectations
+    expect(request.getProperties()).andReturn(setProperties);
+    expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
+    expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
+        andReturn(serviceComponents).anyTimes();
+
+    replay(dao, metaInfo, request);
+    // end expectations
+
+    ResourceProvider provider = createProvider();
+    try {
+      provider.createResources(request);
+      fail("Exception expected");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+    verify(dao, metaInfo, request);
+  }
+
+  @Test
+  public void testCreateResource_Validate__InvalidComponent() throws AmbariException, ResourceAlreadyExistsException,
+      SystemException, UnsupportedPropertyException, NoSuchParentResourceException
+  {
+    Request request = createMock(Request.class);
+
+    Map<String, ServiceInfo> services = new HashMap<String, ServiceInfo>();
+    ServiceInfo service = new ServiceInfo();
+    service.setName("test-service");
+    services.put("test-service", service);
+
+    List<ComponentInfo> serviceComponents = new ArrayList<ComponentInfo>();
+    ComponentInfo component1 = new ComponentInfo();
+    // change component1->foo which results in a validation failure for bad component name
+    component1.setName("foo");
+    ComponentInfo component2 = new ComponentInfo();
+    component2.setName("component2");
+    serviceComponents.add(component1);
+    serviceComponents.add(component2);
+
+
+    Set<Map<String, Object>> setProperties = getTestProperties();
+
+    // set expectations
+    expect(request.getProperties()).andReturn(setProperties);
+    expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
+    expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
+        andReturn(serviceComponents).anyTimes();
+
+    replay(dao, metaInfo, request);
+    // end expectations
+
+    ResourceProvider provider = createProvider();
+    try {
+      provider.createResources(request);
+      fail("Exception expected");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+    verify(dao, metaInfo, request);
+  }
+
+  @Test
+  public void testCreateResource_Validate__AmbariServerComponent() throws AmbariException, ResourceAlreadyExistsException,
+      SystemException, UnsupportedPropertyException, NoSuchParentResourceException
+  {
+    Request request = createMock(Request.class);
+
+    Map<String, ServiceInfo> services = new HashMap<String, ServiceInfo>();
+    ServiceInfo service = new ServiceInfo();
+    service.setName("test-service");
+    services.put("test-service", service);
+
+    List<ComponentInfo> serviceComponents = new ArrayList<ComponentInfo>();
+    ComponentInfo component1 = new ComponentInfo();
+    component1.setName("component1");
+    ComponentInfo component2 = new ComponentInfo();
+    component2.setName("component2");
+    serviceComponents.add(component1);
+    serviceComponents.add(component2);
+
+    Set<Map<String, Object>> setProperties = getTestProperties();
+    ((HashSet<Map<String, String>>) ((HashSet<Map<String, Object>>) setProperties.iterator().next().get(
+        BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID)).iterator().next().get("components")).
+        iterator().next().put("name", "AMBARI_SERVER");
+
+
+    Capture<BlueprintEntity> entityCapture = new Capture<BlueprintEntity>();
+
+    // set expectations
+    expect(request.getProperties()).andReturn(setProperties);
+    expect(dao.findByName(BLUEPRINT_NAME)).andReturn(null);
+    expect(metaInfo.getServices("test-stack-name", "test-stack-version")).andReturn(services).anyTimes();
+    expect(metaInfo.getComponentsByService("test-stack-name", "test-stack-version", "test-service")).
+        andReturn(serviceComponents).anyTimes();
+    dao.create(capture(entityCapture));
+
+    replay(dao, metaInfo, request);
+    // end expectations
+
+    ResourceProvider provider = createProvider();
+    AbstractResourceProviderTest.TestObserver observer = new AbstractResourceProviderTest.TestObserver();
+    ((ObservableResourceProvider)provider).addObserver(observer);
+
+    provider.createResources(request);
+
+    ResourceProviderEvent lastEvent = observer.getLastEvent();
+    assertNotNull(lastEvent);
+    assertEquals(Resource.Type.Blueprint, lastEvent.getResourceType());
+    assertEquals(ResourceProviderEvent.Type.Create, lastEvent.getType());
+    assertEquals(request, lastEvent.getRequest());
+    assertNull(lastEvent.getPredicate());
+
+    verify(dao, metaInfo, request);
+  }
+
   private Set<Map<String, Object>> getTestProperties() {
     Map<String, String> mapHostGroupComponentProperties = new HashMap<String, String>();
     mapHostGroupComponentProperties.put(BlueprintResourceProvider.COMPONENT_NAME_PROPERTY_ID, "component1");
@@ -272,7 +562,6 @@ public class BlueprintResourceProviderTest {
     mapProperties.put(BlueprintResourceProvider.BLUEPRINT_NAME_PROPERTY_ID, BLUEPRINT_NAME);
     mapProperties.put(BlueprintResourceProvider.STACK_NAME_PROPERTY_ID, "test-stack-name");
     mapProperties.put(BlueprintResourceProvider.STACK_VERSION_PROPERTY_ID, "test-stack-version");
-    mapProperties.put(BlueprintResourceProvider.STACK_VERSION_PROPERTY_ID, "test-stack-version");
     mapProperties.put(BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID, setHostGroupProperties);
 
     return Collections.singleton(mapProperties);
@@ -415,5 +704,62 @@ public class BlueprintResourceProviderTest {
         PropertyHelper.getPropertyIds(Resource.Type.Blueprint),
         PropertyHelper.getKeyPropertyIds(Resource.Type.Blueprint));
   }
+
+  private BlueprintEntity createEntity(Map<String, Object> properties) {
+    BlueprintEntity entity = new BlueprintEntity();
+    entity.setBlueprintName((String) properties.get(BlueprintResourceProvider.BLUEPRINT_NAME_PROPERTY_ID));
+    entity.setStackName((String) properties.get(BlueprintResourceProvider.STACK_NAME_PROPERTY_ID));
+    entity.setStackVersion((String) properties.get(BlueprintResourceProvider.STACK_VERSION_PROPERTY_ID));
+
+    Set<Map<String, Object>> hostGroupProperties = (Set<Map<String, Object>>) properties.get(
+        BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID);
+
+    Collection<HostGroupEntity> hostGroups = new ArrayList<HostGroupEntity>();
+    for (Map<String, Object> groupProperties : hostGroupProperties) {
+      HostGroupEntity hostGroup = new HostGroupEntity();
+      hostGroups.add(hostGroup);
+      hostGroup.setName((String) groupProperties.get(BlueprintResourceProvider.HOST_GROUP_NAME_PROPERTY_ID));
+      hostGroup.setCardinality((String) groupProperties.get(BlueprintResourceProvider.HOST_GROUP_CARDINALITY_PROPERTY_ID));
+      hostGroup.setConfigurations(new ArrayList<HostGroupConfigEntity>());
+
+      Set<Map<String, String>> setComponentProperties = (Set<Map<String, String>>) groupProperties.get(
+          BlueprintResourceProvider.COMPONENT_PROPERTY_ID);
+
+      Collection<HostGroupComponentEntity> components = new ArrayList<HostGroupComponentEntity>();
+      for (Map<String, String> compProperties : setComponentProperties) {
+        HostGroupComponentEntity component = new HostGroupComponentEntity();
+        components.add(component);
+        component.setName(compProperties.get(BlueprintResourceProvider.COMPONENT_NAME_PROPERTY_ID));
+      }
+      hostGroup.setComponents(components);
+
+    }
+    entity.setHostGroups(hostGroups);
+
+
+    Collection<Map<String, String>> configProperties = (Collection<Map<String, String>>) properties.get(
+        BlueprintResourceProvider.CONFIGURATION_PROPERTY_ID);
+    Map<String, String> configData = new HashMap<String, String>();
+    Collection<BlueprintConfigEntity> configs = new ArrayList<BlueprintConfigEntity>();
+    if (configProperties != null) {
+      for (Map<String, String> config : configProperties) {
+        BlueprintConfigEntity configEntity = new BlueprintConfigEntity();
+        for (Map.Entry<String, String> entry : config.entrySet()) {
+          String absolutePropName = entry.getKey();
+
+          int idx = absolutePropName.indexOf('/');
+          if (configEntity.getType() == null) {
+            configEntity.setType(absolutePropName.substring(0, idx));
+          }
+          configData.put(absolutePropName.substring(idx + 1), entry.getValue());
+        }
+        configEntity.setConfigData(gson.toJson(configData));
+        configs.add(configEntity);
+      }
+    }
+    entity.setConfigurations(configs);
+
+    return entity;
+  }
 }