Repository: ambari
Updated Branches:
  refs/heads/trunk 6fdc34f12 -> cb2b75c67


AMBARI-6135.  Blueprint validation fails when dependency is deployed to 
multiple host groups.


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

Branch: refs/heads/trunk
Commit: cb2b75c67de7819be25075ef46edd27e91f51c4c
Parents: 6fdc34f
Author: John Speidel <jspei...@hortonworks.com>
Authored: Mon Jun 16 11:48:18 2014 -0400
Committer: John Speidel <jspei...@hortonworks.com>
Committed: Mon Jun 16 14:04:49 2014 -0400

----------------------------------------------------------------------
 .../internal/BaseBlueprintProcessor.java        |  19 +-
 .../internal/BlueprintResourceProviderTest.java | 225 ++++++++++++++++++-
 2 files changed, 241 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/cb2b75c6/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 c6995f4..800ff3b 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
@@ -340,7 +340,7 @@ public abstract class BaseBlueprintProcessor extends 
AbstractControllerResourceP
     int actualCount = getHostGroupsForComponent(component, hostGroups).size();
     if (! cardinality.isValidCount(actualCount)) {
       boolean validated = ! isDependencyManaged(stack, component, 
clusterConfig);
-      if (! validated && autoDeploy != null && autoDeploy.isEnabled() && 
cardinality.cardinality.equals("1")) {
+      if (! validated && autoDeploy != null && autoDeploy.isEnabled() && 
cardinality.supportsAutoDeploy()) {
         String coLocateName = autoDeploy.getCoLocate();
         if (coLocateName != null && ! coLocateName.isEmpty()) {
           Collection<HostGroup> coLocateHostGroups = getHostGroupsForComponent(
@@ -912,7 +912,7 @@ public abstract class BaseBlueprintProcessor extends 
AbstractControllerResourceP
 
           if (dependencyScope.equals("cluster")) {
             Collection<String> missingDependencyInfo = 
verifyComponentCardinalityCount(entity, hostGroups,
-                componentName, new Cardinality("1"), autoDeployInfo, stack, 
clusterConfig);
+                componentName, new Cardinality("1+"), autoDeployInfo, stack, 
clusterConfig);
             resolved = missingDependencyInfo.isEmpty();
           } else if (dependencyScope.equals("host")) {
             if (components.contains(component) || (autoDeployInfo != null && 
autoDeployInfo.isEnabled())) {
@@ -1013,5 +1013,20 @@ public abstract class BaseBlueprintProcessor extends 
AbstractControllerResourceP
         return count == exact;
       } else return count >= min && count <= max;
     }
+
+    /**
+     * Determine if the cardinality count supports auto-deployment.
+     * This determination is independent of whether the component is configured
+     * to be auto-deployed.  This only indicates whether auto-deployment is
+     * supported for the current cardinality.
+     *
+     * At this time, only cardinalities of ALL or where a count of 1 is valid 
are
+     * supported.
+     *
+     * @return true if cardinality supports auto-deployment
+     */
+    public boolean supportsAutoDeploy() {
+      return isValidCount(1) || isAll;
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/cb2b75c6/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 d04f24f..85dbf97 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
@@ -45,6 +45,7 @@ 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.AutoDeployInfo;
 import org.apache.ambari.server.state.ComponentInfo;
 import org.apache.ambari.server.state.DependencyInfo;
 import org.apache.ambari.server.state.ServiceInfo;
@@ -620,7 +621,229 @@ public class BlueprintResourceProviderTest {
   }
 
   @Test
-  public void testCreateResource_Validate__Cardinality__Negative() throws 
AmbariException, ResourceAlreadyExistsException,
+   public void 
testCreateResource_Validate__Cardinality__MultipleDependencyInstances() throws 
AmbariException, ResourceAlreadyExistsException,
+      SystemException, UnsupportedPropertyException, 
NoSuchParentResourceException {
+
+    Set<Map<String, Object>> setProperties = getTestProperties();
+    setConfigurationProperties(setProperties);
+
+    AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
+    Capture<Set<StackServiceRequest>> stackServiceRequestCapture = new 
Capture<Set<StackServiceRequest>>();
+    Capture<Set<StackServiceComponentRequest>> serviceComponentRequestCapture 
= new Capture<Set<StackServiceComponentRequest>>();
+    Capture<StackConfigurationRequest> stackConfigurationRequestCapture = new 
Capture<StackConfigurationRequest>();
+    Request request = createMock(Request.class);
+    StackServiceResponse stackServiceResponse = 
createMock(StackServiceResponse.class);
+    StackServiceComponentResponse stackServiceComponentResponse = 
createNiceMock(StackServiceComponentResponse.class);
+    StackServiceComponentResponse stackServiceComponentResponse2 = 
createNiceMock(StackServiceComponentResponse.class);
+    Set<StackServiceComponentResponse> setServiceComponents = new 
HashSet<StackServiceComponentResponse>();
+    setServiceComponents.add(stackServiceComponentResponse);
+    setServiceComponents.add(stackServiceComponentResponse2);
+
+    DependencyInfo dependencyInfo = new DependencyInfo();
+    AutoDeployInfo autoDeployInfo = new AutoDeployInfo();
+    autoDeployInfo.setEnabled(false);
+    dependencyInfo.setAutoDeploy(autoDeployInfo);
+    dependencyInfo.setScope("cluster");
+    dependencyInfo.setName("test-service/component1");
+
+    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(managementController.getStackServices(capture(stackServiceRequestCapture))).andReturn(
+        Collections.<StackServiceResponse>singleton(stackServiceResponse));
+    
expect(stackServiceResponse.getServiceName()).andReturn("test-service").anyTimes();
+    
expect(stackServiceResponse.getStackName()).andReturn("test-stack-name").anyTimes();
+    
expect(stackServiceResponse.getStackVersion()).andReturn("test-stack-version").anyTimes();
+
+    
expect(managementController.getStackComponents(capture(serviceComponentRequestCapture))).andReturn(setServiceComponents).anyTimes();
+    
expect(stackServiceComponentResponse.getCardinality()).andReturn("2").anyTimes();
+    
expect(stackServiceComponentResponse.getComponentName()).andReturn("component1").anyTimes();
+    
expect(stackServiceComponentResponse.getServiceName()).andReturn("test-service").anyTimes();
+    
expect(stackServiceComponentResponse.getStackName()).andReturn("test-stack-name").anyTimes();
+    
expect(stackServiceComponentResponse.getStackVersion()).andReturn("test-stack-version").anyTimes();
+    
expect(stackServiceComponentResponse2.getCardinality()).andReturn("1").anyTimes();
+    
expect(stackServiceComponentResponse2.getComponentName()).andReturn("component2").anyTimes();
+    
expect(stackServiceComponentResponse2.getServiceName()).andReturn("test-service").anyTimes();
+    
expect(stackServiceComponentResponse2.getStackName()).andReturn("test-stack-name").anyTimes();
+    
expect(stackServiceComponentResponse2.getStackVersion()).andReturn("test-stack-version").anyTimes();
+
+    
expect(managementController.getStackConfigurations(Collections.singleton(capture(stackConfigurationRequestCapture)))).
+        andReturn(Collections.<StackConfigurationResponse>emptySet());
+
+    expect(metaInfo.getComponentDependencies("test-stack-name", 
"test-stack-version", "test-service", "component2")).
+        
andReturn(Collections.<DependencyInfo>singletonList(dependencyInfo)).anyTimes();
+    expect(metaInfo.getComponentDependencies("test-stack-name", 
"test-stack-version", "test-service", "component1")).
+        andReturn(Collections.<DependencyInfo>emptyList()).anyTimes();
+
+    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();
+    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.getRequiredProperties("test-stack-name", 
"test-stack-version", "test-service")).andReturn(
+        Collections.<String, 
org.apache.ambari.server.state.PropertyInfo>emptyMap()).anyTimes();
+    dao.create(capture(entityCapture));
+
+    replay(dao, metaInfo, request, managementController, stackServiceResponse,
+        stackServiceComponentResponse, stackServiceComponentResponse2);
+    // 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, metaInfo, request, managementController, stackServiceResponse,
+        stackServiceComponentResponse, stackServiceComponentResponse2);
+  }
+
+  @Test
+  public void testCreateResource_Validate__Cardinality__AutoCommit() throws 
AmbariException, ResourceAlreadyExistsException,
+      SystemException, UnsupportedPropertyException, 
NoSuchParentResourceException {
+
+    Set<Map<String, Object>> setProperties = getTestProperties();
+    setConfigurationProperties(setProperties);
+
+    // remove component2 from BP
+    Iterator iter = ((HashSet<Map<String, HashSet<Map<String, String>>>>) 
setProperties.iterator().next().
+        get(BlueprintResourceProvider.HOST_GROUP_PROPERTY_ID)).
+        iterator().next().get("components").iterator();
+    iter.next();
+    iter.remove();
+
+    AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
+    Capture<Set<StackServiceRequest>> stackServiceRequestCapture = new 
Capture<Set<StackServiceRequest>>();
+    Capture<Set<StackServiceComponentRequest>> serviceComponentRequestCapture 
= new Capture<Set<StackServiceComponentRequest>>();
+    Capture<StackConfigurationRequest> stackConfigurationRequestCapture = new 
Capture<StackConfigurationRequest>();
+    Request request = createMock(Request.class);
+    StackServiceResponse stackServiceResponse = 
createMock(StackServiceResponse.class);
+    StackServiceComponentResponse stackServiceComponentResponse = 
createNiceMock(StackServiceComponentResponse.class);
+    StackServiceComponentResponse stackServiceComponentResponse2 = 
createNiceMock(StackServiceComponentResponse.class);
+    Set<StackServiceComponentResponse> setServiceComponents = new 
HashSet<StackServiceComponentResponse>();
+    setServiceComponents.add(stackServiceComponentResponse);
+    setServiceComponents.add(stackServiceComponentResponse2);
+
+    DependencyInfo dependencyInfo = new DependencyInfo();
+    AutoDeployInfo autoDeployInfo = new AutoDeployInfo();
+    autoDeployInfo.setEnabled(true);
+    autoDeployInfo.setCoLocate("test-service/component1");
+    dependencyInfo.setAutoDeploy(autoDeployInfo);
+    dependencyInfo.setScope("cluster");
+    dependencyInfo.setName("test-service/component2");
+
+    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(managementController.getStackServices(capture(stackServiceRequestCapture))).andReturn(
+        Collections.<StackServiceResponse>singleton(stackServiceResponse));
+    
expect(stackServiceResponse.getServiceName()).andReturn("test-service").anyTimes();
+    
expect(stackServiceResponse.getStackName()).andReturn("test-stack-name").anyTimes();
+    
expect(stackServiceResponse.getStackVersion()).andReturn("test-stack-version").anyTimes();
+
+    
expect(managementController.getStackComponents(capture(serviceComponentRequestCapture))).andReturn(setServiceComponents).anyTimes();
+    
expect(stackServiceComponentResponse.getCardinality()).andReturn("2").anyTimes();
+    
expect(stackServiceComponentResponse.getComponentName()).andReturn("component1").anyTimes();
+    
expect(stackServiceComponentResponse.getServiceName()).andReturn("test-service").anyTimes();
+    
expect(stackServiceComponentResponse.getStackName()).andReturn("test-stack-name").anyTimes();
+    
expect(stackServiceComponentResponse.getStackVersion()).andReturn("test-stack-version").anyTimes();
+    
expect(stackServiceComponentResponse2.getCardinality()).andReturn("1").anyTimes();
+    
expect(stackServiceComponentResponse2.getComponentName()).andReturn("component2").anyTimes();
+    
expect(stackServiceComponentResponse2.getServiceName()).andReturn("test-service").anyTimes();
+    
expect(stackServiceComponentResponse2.getStackName()).andReturn("test-stack-name").anyTimes();
+    
expect(stackServiceComponentResponse2.getStackVersion()).andReturn("test-stack-version").anyTimes();
+
+    
expect(managementController.getStackConfigurations(Collections.singleton(capture(stackConfigurationRequestCapture)))).
+        andReturn(Collections.<StackConfigurationResponse>emptySet());
+
+    expect(metaInfo.getComponentDependencies("test-stack-name", 
"test-stack-version", "test-service", "component2")).
+        andReturn(Collections.<DependencyInfo>emptyList()).anyTimes();
+    expect(metaInfo.getComponentDependencies("test-stack-name", 
"test-stack-version", "test-service", "component1")).
+        
andReturn(Collections.<DependencyInfo>singletonList(dependencyInfo)).anyTimes();
+
+    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();
+    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.getRequiredProperties("test-stack-name", 
"test-stack-version", "test-service")).andReturn(
+        Collections.<String, 
org.apache.ambari.server.state.PropertyInfo>emptyMap()).anyTimes();
+    dao.create(capture(entityCapture));
+
+    replay(dao, metaInfo, request, managementController, stackServiceResponse,
+        stackServiceComponentResponse, stackServiceComponentResponse2);
+    // 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, metaInfo, request, managementController, stackServiceResponse,
+        stackServiceComponentResponse, stackServiceComponentResponse2);
+  }
+
+  @Test
+  public void testCreateResource_Validate__Cardinality__Fail() throws 
AmbariException, ResourceAlreadyExistsException,
       SystemException, UnsupportedPropertyException, 
NoSuchParentResourceException {
 
     Set<Map<String, Object>> setProperties = getTestProperties();

Reply via email to