ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tbeerbo...@apache.org
Subject git commit: AMBARI-3811 - API performance issue on large cluster
Date Wed, 20 Nov 2013 20:02:18 GMT
Updated Branches:
  refs/heads/trunk 47b80c59f -> 46e034e5e


AMBARI-3811 - API performance issue on large cluster


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

Branch: refs/heads/trunk
Commit: 46e034e5e07a6607ed5c430b27045eea53810803
Parents: 47b80c5
Author: tbeerbower <tbeerbower@hortonworks.com>
Authored: Tue Nov 19 11:19:47 2013 -0500
Committer: tbeerbower <tbeerbower@hortonworks.com>
Committed: Wed Nov 20 15:01:56 2013 -0500

----------------------------------------------------------------------
 .../ambari/server/api/query/QueryImpl.java      | 217 ++++++++++---------
 .../internal/ClusterControllerImpl.java         |  52 ++---
 .../controller/spi/ClusterController.java       |  19 ++
 .../ambari/server/api/query/QueryImplTest.java  |  78 +++++++
 .../internal/ClusterControllerImplTest.java     | 120 +++++++++-
 5 files changed, 338 insertions(+), 148 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/46e034e5/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java
b/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java
index 89513fa..caad1dd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/QueryImpl.java
@@ -23,7 +23,6 @@ import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl;
 import org.apache.ambari.server.api.resources.SubResourceDefinition;
 import org.apache.ambari.server.api.services.ResultImpl;
-import org.apache.ambari.server.controller.predicate.OrPredicate;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.controller.predicate.AndPredicate;
 import org.apache.ambari.server.controller.predicate.EqualsPredicate;
@@ -67,9 +66,9 @@ public class QueryImpl implements Query, ResourceInstance {
   private final Map<Resource.Type, String> keyValueMap = new HashMap<Resource.Type,
String>();
 
   /**
-   * Set of maps of primary and foreign key values.
+   * Set of query results.
    */
-  Set<Map<Resource.Type, String>> keyValueMaps = new HashSet<Map<Resource.Type,
String>>();
+  Map<Resource, QueryResult> queryResults = new LinkedHashMap<Resource, QueryResult>();
 
   /**
    * Sub-resources of the resource which is being operated on.
@@ -98,11 +97,6 @@ public class QueryImpl implements Query, ResourceInstance {
   private PageRequest pageRequest;
 
   /**
-   * Query resources.
-   */
-  private Set<Resource> providerResourceSet;
-
-  /**
    * The logger.
    */
   private final static Logger LOG =
@@ -166,7 +160,7 @@ public class QueryImpl implements Query, ResourceInstance {
              NoSuchParentResourceException {
 
     queryForResources();
-    return getResult();
+    return getResult(null);
   }
 
   @Override
@@ -303,14 +297,21 @@ public class QueryImpl implements Query, ResourceInstance {
       NoSuchResourceException,
       NoSuchParentResourceException {
 
-    providerResourceSet = new LinkedHashSet<Resource>();
+    Set<Resource> providerResourceSet = new HashSet<Resource>();
+
+    Resource.Type resourceType = getResourceDefinition().getType();
+    Request       request      = createRequest();
+    Predicate     predicate    = getPredicate();
 
-    // save the top level resources
-    for (Resource resource : doQuery(getPredicate())) {
-      providerResourceSet.add(resource);
+    Set<Resource> resourceSet = new LinkedHashSet<Resource>();
+
+    for (Resource queryResource : doQuery(resourceType, request, predicate)) {
+      providerResourceSet.add(queryResource);
+      resourceSet.add(queryResource);
     }
-    keyValueMaps.add(getKeyValueMap());
+    queryResults.put(null, new QueryResult(request, predicate, getKeyValueMap(), resourceSet));
 
+    clusterController.populateResources(resourceType, providerResourceSet, request, predicate);
     queryForSubResources();
   }
 
@@ -325,17 +326,31 @@ public class QueryImpl implements Query, ResourceInstance {
       NoSuchResourceException,
       NoSuchParentResourceException {
 
-    // get predicates for all of the sub resource types
-    Map<String, Predicate> predicateMap = getSubResourcePredicates(providerResourceSet);
-
     for (Map.Entry<String, QueryImpl> entry : querySubResourceSet.entrySet()) {
-      QueryImpl subResource  = entry.getValue();
 
-      subResource.providerResourceSet = new LinkedHashSet<Resource>();
+      QueryImpl     subResource  = entry.getValue();
+      Resource.Type resourceType = subResource.getResourceDefinition().getType();
+      Request       request      = subResource.createRequest();
 
-      for (Resource resource : subResource.doQuery(predicateMap.get(entry.getKey()))) {
-        subResource.providerResourceSet.add(resource);
+      Set<Resource> providerResourceSet = new HashSet<Resource>();
+
+      for (QueryResult queryResult : queryResults.values()) {
+        for (Resource resource : queryResult.getProviderResourceSet()) {
+
+          Map<Resource.Type, String> map = getKeyValueMap(resource, queryResult.getKeyValueMap());
+
+          Predicate predicate = subResource.createPredicate(map);
+
+          Set<Resource> resourceSet = new LinkedHashSet<Resource>();
+
+          for (Resource queryResource : subResource.doQuery(resourceType, request, predicate))
{
+            providerResourceSet.add(queryResource);
+            resourceSet.add(queryResource);
+          }
+          subResource.queryResults.put(resource, new QueryResult(request, predicate, map,
resourceSet));
+        }
       }
+      clusterController.populateResources(resourceType, providerResourceSet, request, null);
       subResource.queryForSubResources();
     }
   }
@@ -343,103 +358,69 @@ public class QueryImpl implements Query, ResourceInstance {
   /**
    * Query the cluster controller for the resources.
    */
-  private Set<Resource> doQuery(Predicate predicate)
+  private Set<Resource> doQuery(Resource.Type type, Request request, Predicate predicate)
       throws UnsupportedPropertyException,
       SystemException,
       NoSuchResourceException,
       NoSuchParentResourceException {
 
-    Resource.Type resourceType1 = getResourceDefinition().getType();
-
-    if (getKeyValueMap().get(resourceType1) == null) {
-      addCollectionProperties(resourceType1);
-    }
     if (queryPropertySet.isEmpty() && querySubResourceSet.isEmpty()) {
       //Add sub resource properties for default case where no fields are specified.
       querySubResourceSet.putAll(ensureSubResources());
     }
 
-    Resource.Type resourceType = getResourceDefinition().getType();
-    Request       request      = createRequest();
-
     if (LOG.isDebugEnabled()) {
       LOG.debug("Executing resource query: " + request + " where " + predicate);
     }
-    return clusterController.getResources(resourceType, request, predicate);
-  }
-
-  /**
-   * Get a map of predicates for the given resource's sub-resources keyed 
-   * by resource type.  Each predicate is a combined predicate of all 
-   * the sub resource predicates for a given type OR'd together.  This 
-   * allows for all of the sub-resources of a given type to be 
-   * acquired in a single query.
-   */
-  private Map<String, Predicate> getSubResourcePredicates(Set<Resource> resources)
{
-    Map<String, Predicate> predicateMap = new HashMap<String, Predicate>();
-
-    for (Resource resource : resources) {
-      for (Map.Entry<String, QueryImpl> entry : querySubResourceSet.entrySet()) {
-        QueryImpl subResourceInstance = entry.getValue();
-        String    subResCategory      = entry.getKey();
-
-        Set<Map<Resource.Type, String>> resourceKeyValueMaps = getKeyValueMaps(resource,
keyValueMaps);
-
-        for( Map<Resource.Type, String> map : resourceKeyValueMaps) {
-          Predicate predicate = predicateMap.get(subResCategory);
-
-          predicateMap.put(subResCategory, predicate == null ?
-              subResourceInstance.createPredicate(map) :
-              new OrPredicate(predicate, subResourceInstance.createPredicate(map)));
-        }
-        subResourceInstance.keyValueMaps.addAll(resourceKeyValueMaps);
-      }
-    }
-    return predicateMap;
+    return clusterController.getResources(type, request, predicate);
   }
 
   /**
    * Get a result from this query.
    */
-  private Result getResult()
+  private Result getResult(Resource parentResource)
       throws UnsupportedPropertyException, SystemException, NoSuchResourceException, NoSuchParentResourceException
{
 
     Result result = new ResultImpl(true);
     Resource.Type resourceType = getResourceDefinition().getType();
-    if (getKeyValueMap().get(resourceType) == null) {
-      result.getResultTree().setProperty("isCollection", "true");
-    }
+    TreeNode<Resource> tree = result.getResultTree();
 
-    Predicate predicate = createPredicate();
-    Request   request   = createRequest();
+    if (isCollectionResource()) {
+      tree.setProperty("isCollection", "true");
+    }
 
-    Iterable<Resource> iterResource;
+    QueryResult queryResult = queryResults.get(parentResource);
 
-    if (pageRequest == null) {
-      iterResource = clusterController.getIterable(
-          resourceType, providerResourceSet, request, predicate);
-    } else {
-      PageResponse pageResponse = clusterController.getPage(
-          resourceType, providerResourceSet, request, predicate, pageRequest);
-      iterResource = pageResponse.getIterable();
-    }
+    if (queryResult != null) {
+      Predicate predicate = queryResult.getPredicate();
+      Request   request   = queryResult.getRequest();
 
-    TreeNode<Resource> tree = result.getResultTree();
+      Iterable<Resource> iterResource;
 
-    int count = 1;
-    for (Resource resource : iterResource) {
-      // add a child node for the resource and provide a unique name.  The name is never
used.
-      TreeNode<Resource> node = tree.addChild(resource, resource.getType() + ":" +
count++);
-      for (Map.Entry<String, QueryImpl> entry : querySubResourceSet.entrySet()) {
-        String    subResCategory = entry.getKey();
-        QueryImpl subResource    = entry.getValue();
+      Set<Resource> providerResourceSet = queryResult.getProviderResourceSet();
 
-        subResource.setKeyValueMap(getKeyValueMap(resource, getKeyValueMap()));
+      if (pageRequest == null) {
+        iterResource = clusterController.getIterable(
+            resourceType, providerResourceSet, request, predicate);
+      } else {
+        PageResponse pageResponse = clusterController.getPage(
+            resourceType, providerResourceSet, request, predicate, pageRequest);
+        iterResource = pageResponse.getIterable();
+      }
 
-        TreeNode<Resource> childResult = subResource.getResult().getResultTree();
-        childResult.setName(subResCategory);
-        childResult.setProperty("isCollection", "false");
-        node.addChild(childResult);
+      int count = 1;
+      for (Resource resource : iterResource) {
+        // add a child node for the resource and provide a unique name.  The name is never
used.
+        TreeNode<Resource> node = tree.addChild(resource, resource.getType() + ":"
+ count++);
+        for (Map.Entry<String, QueryImpl> entry : querySubResourceSet.entrySet()) {
+          String    subResCategory = entry.getKey();
+          QueryImpl subResource    = entry.getValue();
+
+          TreeNode<Resource> childResult = subResource.getResult(resource).getResultTree();
+          childResult.setName(subResCategory);
+          childResult.setProperty("isCollection", "false");
+          node.addChild(childResult);
+        }
       }
     }
     return result;
@@ -552,6 +533,11 @@ public class QueryImpl implements Query, ResourceInstance {
 
     Map<String, TemporalInfo> mapTemporalInfo    = new HashMap<String, TemporalInfo>();
     TemporalInfo              globalTemporalInfo = temporalInfoMap.get(null);
+    Resource.Type             resourceType       = getResourceDefinition().getType();
+
+    if (getKeyValueMap().get(resourceType) == null) {
+      addCollectionProperties(resourceType);
+    }
 
     for (String group : queryPropertySet) {
       TemporalInfo temporalInfo = temporalInfoMap.get(group);
@@ -567,18 +553,6 @@ public class QueryImpl implements Query, ResourceInstance {
         Collections.<String>emptySet() : setProperties, mapTemporalInfo);
   }
 
-  // Get a set of key value maps based on the given resource and an existing set of key value
maps
-  private Set<Map<Resource.Type, String>> getKeyValueMaps(Resource resource,
-                                                          Set<Map<Resource.Type, String>>
keyValueMaps) {
-    Set<Map<Resource.Type, String>> resourceKeyValueMaps = new HashSet<Map<Resource.Type,
String>>();
-
-    for(Map<Resource.Type, String> keyValueMap : keyValueMaps) {
-      Map<Resource.Type, String> resourceKeyValueMap = getKeyValueMap(resource, keyValueMap);
-      resourceKeyValueMaps.add(resourceKeyValueMap);
-    }
-    return resourceKeyValueMaps;
-  }
-
   // Get a key value map based on the given resource and an existing key value map
   private Map<Resource.Type, String> getKeyValueMap(Resource resource,
                                                     Map<Resource.Type, String> keyValueMap)
{
@@ -601,4 +575,45 @@ public class QueryImpl implements Query, ResourceInstance {
     resourceKeyValueMap.put(resource.getType(), resource.getPropertyValue(resourceKeyProp).toString());
     return resourceKeyValueMap;
   }
+
+  // ----- inner class : QueryResult -----------------------------------------
+
+  /**
+   * Maintain information about an individual query and its result.
+   */
+  private static class QueryResult {
+    private final Request request;
+    private final Predicate predicate;
+    private final Map<Resource.Type, String> keyValueMap;
+    private final Set<Resource> providerResourceSet;
+
+    // ----- Constructor -----------------------------------------------------
+
+    private QueryResult(Request request, Predicate predicate,
+                        Map<Resource.Type, String> keyValueMap,
+                        Set<Resource> providerResourceSet) {
+      this.request = request;
+      this.predicate = predicate;
+      this.keyValueMap = keyValueMap;
+      this.providerResourceSet = providerResourceSet;
+    }
+
+    // ----- accessors -------------------------------------------------------
+
+    public Request getRequest() {
+      return request;
+    }
+
+    public Predicate getPredicate() {
+      return predicate;
+    }
+
+    public Map<Resource.Type, String> getKeyValueMap() {
+      return keyValueMap;
+    }
+
+    public Set<Resource> getProviderResourceSet() {
+      return providerResourceSet;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/46e034e5/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterControllerImpl.java
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterControllerImpl.java
index 1a9079f..4f1751d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterControllerImpl.java
@@ -113,18 +113,23 @@ public class ClusterControllerImpl implements ClusterController {
 
       // get the resources
       resources = provider.getResources(request, predicate);
+    }
+    return resources;
+  }
 
-      // populate the resources with metrics and properties.
-      populateResources(type, resources, request, predicate);
+  @Override
+  public Set<Resource> populateResources(Resource.Type type,
+                                         Set<Resource> resources,
+                                         Request request,
+                                         Predicate predicate) throws SystemException {
+    Set<Resource> keepers = resources;
 
-      // filter the fully populated resources with the given predicate
-      Iterable<Resource> iterable = getIterable(type, resources, request, predicate);
-      resources = new LinkedHashSet<Resource>();
-      for (Resource resource : iterable){
-        resources.add(resource);
+    for (PropertyProvider propertyProvider : propertyProviders.get(type)) {
+      if (providesRequestProperties(propertyProvider, request, predicate)) {
+        keepers = propertyProvider.populateResources(keepers, request, predicate);
       }
     }
-    return resources;
+    return keepers;
   }
 
   @Override
@@ -279,7 +284,8 @@ public class ClusterControllerImpl implements ClusterController {
       SystemException,
       NoSuchParentResourceException,
       NoSuchResourceException {
-    return getResources(type, request, predicate, null).getIterable();
+    PageResponse resources = getResources(type, request, predicate, null);
+    return resources.getIterable();
   }
 
   /**
@@ -415,34 +421,6 @@ public class ClusterControllerImpl implements ClusterController {
   }
 
   /**
-   * Populate the given resources from the associated property providers.  This
-   * method may filter the resources based on the predicate and return a subset
-   * of the given resources.
-   *
-   * @param type       the resource type
-   * @param resources  the resources to be populated
-   * @param request    the request
-   * @param predicate  the predicate
-   *
-   * @return the set of resources that were successfully populated
-   *
-   * @throws SystemException if unable to populate the resources
-   */
-  protected Set<Resource> populateResources(Resource.Type type,
-                                         Set<Resource> resources,
-                                         Request request,
-                                         Predicate predicate) throws SystemException {
-    Set<Resource> keepers = resources;
-
-    for (PropertyProvider propertyProvider : propertyProviders.get(type)) {
-      if (providesRequestProperties(propertyProvider, request, predicate)) {
-        keepers = propertyProvider.populateResources(keepers, request, predicate);
-      }
-    }
-    return keepers;
-  }
-
-  /**
    * Indicates whether or not the given property provider can service the given request.
    *
    * @param provider   the property provider

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/46e034e5/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/ClusterController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/ClusterController.java
b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/ClusterController.java
index 0ab15db..c50ff7e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/ClusterController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/ClusterController.java
@@ -52,6 +52,25 @@ public interface ClusterController {
       SystemException;
 
   /**
+   * Populate the given resources from the associated property providers.  This
+   * method may filter the resources based on the predicate and return a subset
+   * of the given resources.
+   *
+   * @param type       the resource type
+   * @param resources  the resources to be populated
+   * @param request    the request
+   * @param predicate  the predicate
+   *
+   * @return the set of resources that were successfully populated
+   *
+   * @throws SystemException if unable to populate the resources
+   */
+  public Set<Resource> populateResources(Resource.Type type,
+                                            Set<Resource> resources,
+                                            Request request,
+                                            Predicate predicate) throws SystemException;
+
+  /**
    * Get an iterable set of resources from the given set of resources filtered by the
    * given request and predicate objects.
    *

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/46e034e5/ambari-server/src/test/java/org/apache/ambari/server/api/query/QueryImplTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/query/QueryImplTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/api/query/QueryImplTest.java
index 8e02394..815779b 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/query/QueryImplTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/query/QueryImplTest.java
@@ -22,6 +22,7 @@ package org.apache.ambari.server.api.query;
 
 import org.apache.ambari.server.api.resources.ResourceDefinition;
 import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.resources.StackResourceDefinition;
 import org.apache.ambari.server.api.resources.SubResourceDefinition;
 import org.apache.ambari.server.api.services.Result;
 import org.apache.ambari.server.api.util.TreeNode;
@@ -126,6 +127,83 @@ public class QueryImplTest {
   }
 
   @Test
+  public void testExecute__Stack_instance_noSpecifiedProps() throws Exception {
+    ResourceDefinition resourceDefinition = new StackResourceDefinition();
+
+    Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.Stack, "HDP");
+
+    //test
+    QueryImpl instance = new TestQuery(mapIds, resourceDefinition);
+
+    Result result = instance.execute();
+
+
+    TreeNode<Resource> tree = result.getResultTree();
+
+    Assert.assertEquals(1, tree.getChildren().size());
+    TreeNode<Resource> stackNode = tree.getChild("Stack:1");
+    Assert.assertEquals("Stack:1", stackNode.getName());
+    Assert.assertEquals(Resource.Type.Stack, stackNode.getObject().getType());
+    Assert.assertEquals(1, stackNode.getChildren().size());
+    TreeNode<Resource> versionsNode = stackNode.getChild("versions");
+    Assert.assertEquals(3, versionsNode.getChildren().size());
+  }
+
+  @Test
+  public void testExecute__Stack_instance_specifiedSubResources() throws Exception {
+    ResourceDefinition resourceDefinition = new StackResourceDefinition();
+
+    Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.Stack, "HDP");
+
+    //test
+    QueryImpl instance = new TestQuery(mapIds, resourceDefinition);
+
+    instance.addProperty("versions", "*", null);
+    instance.addProperty("versions/operatingSystems", "*", null);
+    instance.addProperty("versions/operatingSystems/repositories", "*", null);
+
+    Result result = instance.execute();
+
+    TreeNode<Resource> tree = result.getResultTree();
+
+    Assert.assertEquals(1, tree.getChildren().size());
+    TreeNode<Resource> stackNode = tree.getChild("Stack:1");
+    Assert.assertEquals("Stack:1", stackNode.getName());
+    Assert.assertEquals(Resource.Type.Stack, stackNode.getObject().getType());
+    Assert.assertEquals(1, stackNode.getChildren().size());
+    TreeNode<Resource> versionsNode = stackNode.getChild("versions");
+    Assert.assertEquals(3, versionsNode.getChildren().size());
+
+    TreeNode<Resource> versionNode = versionsNode.getChild("StackVersion:1");
+    Assert.assertEquals("StackVersion:1", versionNode.getName());
+    Assert.assertEquals(Resource.Type.StackVersion, versionNode.getObject().getType());
+
+    Assert.assertEquals(2, versionNode.getChildren().size());
+    TreeNode<Resource> opSystemsNode = versionNode.getChild("operatingSystems");
+    Assert.assertEquals(3, opSystemsNode.getChildren().size());
+
+    TreeNode<Resource> opSystemNode = opSystemsNode.getChild("OperatingSystem:1");
+    Assert.assertEquals("OperatingSystem:1", opSystemNode.getName());
+    Assert.assertEquals(Resource.Type.OperatingSystem, opSystemNode.getObject().getType());
+
+    Assert.assertEquals(1, opSystemNode.getChildren().size());
+    TreeNode<Resource> repositoriesNode = opSystemNode.getChild("repositories");
+    Assert.assertEquals(1, repositoriesNode.getChildren().size());
+
+    TreeNode<Resource> repositoryNode = repositoriesNode.getChild("Repository:1");
+    Assert.assertEquals("Repository:1", repositoryNode.getName());
+    Resource repositoryResource = repositoryNode.getObject();
+    Assert.assertEquals(Resource.Type.Repository, repositoryResource.getType());
+
+    Assert.assertEquals("repo1", repositoryResource.getPropertyValue("Repositories/repo_id"));
+    Assert.assertEquals("centos5", repositoryResource.getPropertyValue("Repositories/os_type"));
+    Assert.assertEquals("1.2.1", repositoryResource.getPropertyValue("Repositories/stack_version"));
+    Assert.assertEquals("HDP", repositoryResource.getPropertyValue("Repositories/stack_name"));
+  }
+
+  @Test
   public void testExecute__Host_collection_noSpecifiedProps() throws Exception {
     ResourceDefinition resourceDefinition = createNiceMock(ResourceDefinition.class);
 

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/46e034e5/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterControllerImplTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterControllerImplTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterControllerImplTest.java
index c765dd7..5acaf57 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterControllerImplTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterControllerImplTest.java
@@ -30,6 +30,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -673,6 +674,15 @@ public class ClusterControllerImplTest {
       }
       providers.put(Resource.Type.Cluster, new TestClusterResourceProvider());
       providers.put(Resource.Type.Host, new TestHostResourceProvider());
+
+
+      providers.put(Resource.Type.Stack, new TestStackResourceProvider());
+      providers.put(Resource.Type.StackVersion, new TestStackVersionResourceProvider());
+      providers.put(Resource.Type.OperatingSystem, new TestOperatingSystemResourceProvider());
+      providers.put(Resource.Type.Repository, new TestRepositoryResourceProvider());
+
+
+
     }
 
     @Override
@@ -686,12 +696,10 @@ public class ClusterControllerImplTest {
     }
   }
 
-  private static class TestResourceProvider implements ResourceProvider {
-
-    private Resource.Type type;
+  private static class TestResourceProvider extends AbstractResourceProvider {
 
     private TestResourceProvider(Resource.Type type) {
-      this.type = type;
+      super(PropertyHelper.getPropertyIds(type), PropertyHelper.getKeyPropertyIds(type));
     }
 
     @Override
@@ -715,17 +723,39 @@ public class ClusterControllerImplTest {
     }
 
     @Override
-    public Map<Resource.Type, String> getKeyPropertyIds() {
-      return PropertyHelper.getKeyPropertyIds(type);
+    protected Set<String> getPKPropertyIds() {
+      return Collections.emptySet();
     }
 
-    @Override
-    public Set<String> checkPropertyIds(Set<String> propertyIds) {
-      return Collections.emptySet();
+    protected Set<Resource> getResources(Resource.Type type, Predicate predicate, String
keyPropertyId, Set<String> keyPropertyValues)
+        throws SystemException, UnsupportedPropertyException, NoSuchParentResourceException,
NoSuchResourceException {
+      Set<Resource> resources = new HashSet<Resource>();
+
+      for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+
+        Set<Resource> resources2 = new HashSet<Resource>();
+
+        if (!propertyMap.containsKey(keyPropertyId)) {
+          for (String keyPropertyValue : keyPropertyValues) {
+            ResourceImpl resource = new ResourceImpl(type);
+            resource.setProperty(keyPropertyId, keyPropertyValue);
+            resources2.add(resource);
+          }
+        } else {
+          resources2.add(new ResourceImpl(type));
+        }
+
+        for (Resource resource : resources2) {
+          for (Map.Entry<String, Object> entry : propertyMap.entrySet()) {
+            resource.setProperty(entry.getKey(), entry.getValue());
+          }
+        }
+        resources.addAll(resources2);
+      }
+      return resources;
     }
   }
 
-
   private static class TestClusterResourceProvider extends TestResourceProvider {
     private TestClusterResourceProvider() {
       super(Resource.Type.Cluster);
@@ -831,6 +861,76 @@ public class ClusterControllerImplTest {
       Delete
     }
   }
+
+
+  private static class TestStackResourceProvider extends TestResourceProvider {
+    private TestStackResourceProvider() {
+      super(Resource.Type.Stack);
+    }
+
+    @Override
+    public Set<Resource> getResources(Request request, Predicate predicate)
+        throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException
{
+
+      Set<String> keyPropertyValues = new HashSet<String>();
+
+      return getResources(Resource.Type.Stack, predicate, "Stacks/stack_name", keyPropertyValues);
+    }
+  }
+
+
+  private static class TestStackVersionResourceProvider extends TestResourceProvider {
+    private TestStackVersionResourceProvider() {
+      super(Resource.Type.StackVersion);
+    }
+
+    @Override
+    public Set<Resource> getResources(Request request, Predicate predicate)
+        throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException
{
+      Set<String> keyPropertyValues = new LinkedHashSet<String>();
+
+      keyPropertyValues.add("1.2.1");
+      keyPropertyValues.add("1.2.2");
+      keyPropertyValues.add("2.0.1");
+
+      return getResources(Resource.Type.StackVersion, predicate, "Versions/stack_version",
keyPropertyValues);
+    }
+  }
+
+  private static class TestOperatingSystemResourceProvider extends TestResourceProvider {
+    private TestOperatingSystemResourceProvider() {
+      super(Resource.Type.OperatingSystem);
+    }
+
+    @Override
+    public Set<Resource> getResources(Request request, Predicate predicate)
+        throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException
{
+      Set<String> keyPropertyValues = new LinkedHashSet<String>();
+
+      keyPropertyValues.add("centos5");
+      keyPropertyValues.add("centos6");
+      keyPropertyValues.add("oraclelinux5");
+
+      return getResources(Resource.Type.OperatingSystem, predicate, "OperatingSystems/os_type",
keyPropertyValues);
+    }
+  }
+
+  private static class TestRepositoryResourceProvider extends TestResourceProvider {
+    private TestRepositoryResourceProvider() {
+      super(Resource.Type.Repository);
+    }
+
+    @Override
+    public Set<Resource> getResources(Request request, Predicate predicate)
+        throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException
{
+      Set<String> keyPropertyValues = new LinkedHashSet<String>();
+
+      keyPropertyValues.add("repo1");
+
+      return getResources(Resource.Type.Repository, predicate, "Repositories/repo_id", keyPropertyValues);
+    }
+  }
+
 }
 
 


Mime
View raw message