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 <tbeerbo...@hortonworks.com> Authored: Tue Nov 19 11:19:47 2013 -0500 Committer: tbeerbower <tbeerbo...@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); + } + } + }