Repository: ambari
Updated Branches:
  refs/heads/trunk 211c78bbb -> 27a228977


AMBARI-10931. Blueprints processor needs stronger validation of Blueprint JSON 
structure (Emil Anca via rlevas)


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

Branch: refs/heads/trunk
Commit: 27a228977c02860926ae71d90395b6dde5b16517
Parents: 211c78b
Author: Emil Anca <[email protected]>
Authored: Tue May 19 09:35:23 2015 -0400
Committer: Robert Levas <[email protected]>
Committed: Tue May 19 09:35:23 2015 -0400

----------------------------------------------------------------------
 .../internal/BlueprintResourceProvider.java     |  20 ++
 .../internal/BlueprintResourceProviderTest.java | 187 ++++++++++++++-----
 2 files changed, 163 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/27a22897/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 aab5395..f85ec32 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
@@ -375,8 +375,28 @@ public class BlueprintResourceProvider extends 
AbstractControllerResourceProvide
    */
   private Command<Void> getCreateCommand(final Map<String, Object> properties, 
final Map<String, String> requestInfoProps) {
     return new Command<Void>() {
+      @SuppressWarnings("rawtypes")
       @Override
       public Void invoke() throws AmbariException {
+        String rawRequestBody = 
requestInfoProps.get(Request.REQUEST_INFO_BODY_PROPERTY);
+        Map<String, Object> rawBodyMap = jsonSerializer.<Map<String, 
Object>>fromJson(rawRequestBody, Map.class);
+        Object configurationData = rawBodyMap.get(CONFIGURATION_PROPERTY_ID);
+
+        if (configurationData != null) {
+          if (configurationData instanceof List) {
+            for (Object map : (List) configurationData) {
+              if (map instanceof Map) {
+                if (((Map) map).size() > 1) {
+                  throw new IllegalArgumentException("Configuration Maps must 
hold a single configuration type each");
+                }
+              } else {
+                throw new IllegalArgumentException("Configuration elements 
must be Maps");
+              }
+            }
+          } else {
+            throw new IllegalArgumentException("Configurations property must 
be a List of Maps");
+          }
+        }
         Blueprint blueprint;
         try {
           blueprint = blueprintFactory.createBlueprint(properties);

http://git-wip-us.apache.org/repos/asf/ambari/blob/27a22897/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 118a7be..4a5ff46 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
@@ -58,6 +58,7 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.dao.BlueprintDAO;
 import org.apache.ambari.server.orm.dao.StackDAO;
@@ -127,22 +128,9 @@ public class BlueprintResourceProviderTest {
 
     AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
     Request request = createMock(Request.class);
-    //Capture<Set<StackServiceRequest>> stackServiceRequestCapture = new 
Capture<Set<StackServiceRequest>>();
-
-//    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 = getBlueprintTestProperties();
+    Map<String, String> requestInfoProperties = getTestRequestInfoProperties();
 
     // set expectations
     
expect(blueprintFactory.createBlueprint(setProperties.iterator().next())).andReturn(blueprint).once();
@@ -151,16 +139,8 @@ public class BlueprintResourceProviderTest {
     expect(blueprint.toEntity()).andReturn(entity);
     expect(blueprint.getName()).andReturn(BLUEPRINT_NAME).atLeastOnce();
     expect(request.getProperties()).andReturn(setProperties);
-    expect(request.getRequestInfoProperties()).andReturn(Collections.<String, 
String>emptyMap());
+    
expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties);
     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();
-//    expect(metaInfo.getComponentToService("test-stack-name", 
"test-stack-version", "component1")).
-//        andReturn("test-service").anyTimes();
-//    expect(metaInfo.getComponentToService("test-stack-name", 
"test-stack-version", "component2")).
-//        andReturn("test-service").anyTimes();
-//    expect(metaInfo.getService("test-stack-name", "test-stack-version", 
"test-service")).andReturn(service).anyTimes();
     dao.create(entity);
 
     replay(dao, entity, metaInfo, blueprintFactory, blueprint, request, 
managementController);
@@ -184,8 +164,6 @@ public class BlueprintResourceProviderTest {
     assertEquals(request, lastEvent.getRequest());
     assertNull(lastEvent.getPredicate());
 
-    //validateEntity(entityCapture.getValue(), false);
-
     verify(dao, entity, blueprintFactory, metaInfo, request, 
managementController);
   }
 
@@ -197,6 +175,8 @@ public class BlueprintResourceProviderTest {
 
 
     Set<Map<String, Object>> setProperties = getBlueprintTestProperties();
+    Map<String, String> requestInfoProperties = getTestRequestInfoProperties();
+    requestInfoProperties.put("validate_topology", "false");
 
     // set expectations
     
expect(blueprintFactory.createBlueprint(setProperties.iterator().next())).andReturn(blueprint).once();
@@ -204,7 +184,7 @@ public class BlueprintResourceProviderTest {
     expect(blueprint.toEntity()).andReturn(entity);
     expect(blueprint.getName()).andReturn(BLUEPRINT_NAME).atLeastOnce();
     expect(request.getProperties()).andReturn(setProperties);
-    expect(request.getRequestInfoProperties()).andReturn(Collections.<String, 
String>singletonMap("validate_topology", "false"));
+    
expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties);
     expect(dao.findByName(BLUEPRINT_NAME)).andReturn(null);
     dao.create(entity);
 
@@ -237,6 +217,7 @@ public class BlueprintResourceProviderTest {
 
     Request request = createMock(Request.class);
     Set<Map<String, Object>> setProperties = getBlueprintTestProperties();
+    Map<String, String> requestInfoProperties = getTestRequestInfoProperties();
 
     // set expectations
     
expect(blueprintFactory.createBlueprint(setProperties.iterator().next())).andReturn(blueprint).once();
@@ -246,7 +227,7 @@ public class BlueprintResourceProviderTest {
     expectLastCall().andThrow(new InvalidTopologyException("test"));
 
     expect(request.getProperties()).andReturn(setProperties);
-    expect(request.getRequestInfoProperties()).andReturn(Collections.<String, 
String>emptyMap());
+    
expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties);
     expect(dao.findByName(BLUEPRINT_NAME)).andReturn(null);
 
     replay(dao, entity, metaInfo, blueprintFactory, blueprint, request);
@@ -278,23 +259,9 @@ public class BlueprintResourceProviderTest {
     Set<Map<String, Object>> setProperties = getBlueprintTestProperties();
     setConfigurationProperties(setProperties);
     AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
-//    Capture<Set<StackServiceRequest>> stackServiceRequestCapture = new 
Capture<Set<StackServiceRequest>>();
+    Map<String, String> requestInfoProperties = getTestRequestInfoProperties();
     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 expectations
     
expect(blueprintFactory.createBlueprint(setProperties.iterator().next())).andReturn(blueprint).once();
     blueprint.validateRequiredProperties();
@@ -302,7 +269,7 @@ public class BlueprintResourceProviderTest {
     expect(blueprint.toEntity()).andReturn(entity);
     expect(blueprint.getName()).andReturn(BLUEPRINT_NAME).atLeastOnce();
     expect(request.getProperties()).andReturn(setProperties);
-    expect(request.getRequestInfoProperties()).andReturn(Collections.<String, 
String>emptyMap());
+    
expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties);
     expect(dao.findByName(BLUEPRINT_NAME)).andReturn(null);
     dao.create(entity);
 
@@ -338,11 +305,13 @@ public class BlueprintResourceProviderTest {
     Set<Map<String, Object>> setProperties = getBlueprintTestProperties();
     
setProperties.iterator().next().remove(BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID);
 
+    Map<String, String> requestInfoProperties = getTestRequestInfoProperties();
+
     // set expectations
     
expect(blueprintFactory.createBlueprint(setProperties.iterator().next())).andThrow(
         new IllegalArgumentException("Blueprint name must be provided"));
     expect(request.getProperties()).andReturn(setProperties);
-    expect(request.getRequestInfoProperties()).andReturn(Collections.<String, 
String>emptyMap());
+    
expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties);
 
     replay(dao, entity, metaInfo, blueprintFactory, blueprint, request);
     // end expectations
@@ -431,6 +400,126 @@ public class BlueprintResourceProviderTest {
     verify(dao);
   }
 
+  @Test
+  public void testCreateResources_withEmptyConfiguration() throws Exception {
+
+    Set<Map<String, Object>> setProperties = getBlueprintTestProperties();
+    setConfigurationProperties(setProperties);
+    AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
+    Map<String, String> requestInfoProperties = new HashMap<String, String>();
+    requestInfoProperties.put(Request.REQUEST_INFO_BODY_PROPERTY, 
"{\"configurations\":[]}");
+    Request request = createMock(Request.class);
+
+    // set expectations
+    
expect(blueprintFactory.createBlueprint(setProperties.iterator().next())).andReturn(blueprint).once();
+    blueprint.validateRequiredProperties();
+    blueprint.validateTopology();
+    expect(blueprint.toEntity()).andReturn(entity);
+    expect(blueprint.getName()).andReturn(BLUEPRINT_NAME).atLeastOnce();
+    expect(request.getProperties()).andReturn(setProperties);
+    
expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties);
+    expect(dao.findByName(BLUEPRINT_NAME)).andReturn(null);
+    dao.create(entity);
+
+    replay(dao, entity, metaInfo, blueprintFactory, blueprint, request, 
managementController);
+    // end expectations
+
+    ResourceProvider provider = 
AbstractControllerResourceProvider.getResourceProvider(
+        Resource.Type.Blueprint,
+        PropertyHelper.getPropertyIds(Resource.Type.Blueprint),
+        PropertyHelper.getKeyPropertyIds(Resource.Type.Blueprint),
+        managementController);
+
+    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, entity, blueprintFactory, metaInfo, request, 
managementController);
+  }
+
+  @Test
+  public void testCreateResources_withSingleConfigurationType() throws 
Exception {
+
+    Set<Map<String, Object>> setProperties = getBlueprintTestProperties();
+    setConfigurationProperties(setProperties);
+    AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
+    Map<String, String> requestInfoProperties = new HashMap<String, String>();
+    requestInfoProperties.put(Request.REQUEST_INFO_BODY_PROPERTY, 
"{\"configurations\":[{\"configuration-type\":{\"properties\":{\"property\":\"value\"}}}]}");
+    Request request = createMock(Request.class);
+
+    // set expectations
+    
expect(blueprintFactory.createBlueprint(setProperties.iterator().next())).andReturn(blueprint).once();
+    blueprint.validateRequiredProperties();
+    blueprint.validateTopology();
+    expect(blueprint.toEntity()).andReturn(entity);
+    expect(blueprint.getName()).andReturn(BLUEPRINT_NAME).atLeastOnce();
+    expect(request.getProperties()).andReturn(setProperties);
+    
expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties);
+    expect(dao.findByName(BLUEPRINT_NAME)).andReturn(null);
+    dao.create(entity);
+
+    replay(dao, entity, metaInfo, blueprintFactory, blueprint, request, 
managementController);
+    // end expectations
+
+    ResourceProvider provider = 
AbstractControllerResourceProvider.getResourceProvider(
+        Resource.Type.Blueprint,
+        PropertyHelper.getPropertyIds(Resource.Type.Blueprint),
+        PropertyHelper.getKeyPropertyIds(Resource.Type.Blueprint),
+        managementController);
+
+    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, entity, blueprintFactory, metaInfo, request, 
managementController);
+  }
+
+  @Test
+  public void testCreateResources_withWrongConfigurationsStructure() throws 
ResourceAlreadyExistsException, SystemException,
+      UnsupportedPropertyException, NoSuchParentResourceException
+  {
+    Request request = createMock(Request.class);
+
+    Set<Map<String, Object>> setProperties = getBlueprintTestProperties();
+
+    Map<String, String> requestInfoProperties = new HashMap<String, String>();
+    String configurationData = 
"{\"configurations\":[{\"config-type1\":{\"properties\" 
:{\"property\":\"property-value\"}},"
+        + "\"config-type2\" : {\"properties_attributes\" : {\"property\" : 
\"property-value\"}, \"properties\" : {\"property\" : \"property-value\"}}}"
+        + "]}";
+    requestInfoProperties.put(Request.REQUEST_INFO_BODY_PROPERTY, 
configurationData);
+
+    // set expectations
+    expect(request.getProperties()).andReturn(setProperties);
+    
expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties);
+
+    replay(dao, metaInfo, request);
+    // end expectations
+
+    try {
+      provider.createResources(request);
+      fail("Exception expected");
+    } catch (IllegalArgumentException e) {
+      //expected exception
+    }
+    verify(dao, metaInfo, request);
+  }
+
   public static Set<Map<String, Object>> getBlueprintTestProperties() {
     Map<String, String> mapHostGroupComponentProperties = new HashMap<String, 
String>();
     
mapHostGroupComponentProperties.put(BlueprintResourceProvider.COMPONENT_NAME_PROPERTY_ID,
 "component1");
@@ -605,6 +694,16 @@ public class BlueprintResourceProviderTest {
     return entity;
   }
 
+  private Map<String, String> getTestRequestInfoProperties() {
+    Map<String, String> setPropertiesInfo = new HashMap<String, String>();
+    String configurationData = 
"{\"configurations\":[{\"config-type1\":{\"properties\" 
:{\"property\":\"property-value\"}}},"
+        + "{\"config-type2\" : {\"properties_attributes\" : {\"property\" : 
\"property-value\"}, \"properties\" : {\"property\" : \"property-value\"}}}"
+        + "]}";
+    setPropertiesInfo.put(Request.REQUEST_INFO_BODY_PROPERTY, 
configurationData);
+    return setPropertiesInfo;
+  }
+
+
   @Test
   public void testPopulateConfigurationEntity_oldSchema() throws Exception {
     Map<String, String> configuration = new HashMap<String, String>();

Reply via email to