Repository: ambari Updated Branches: refs/heads/trunk 064f1d195 -> 3e57dc24c
AMBARI-15717. Compatible Stacks not returning correctly (ncole) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3e57dc24 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3e57dc24 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3e57dc24 Branch: refs/heads/trunk Commit: 3e57dc24c7ba3eaafe4a9d0e179c6e813726bcaa Parents: 064f1d1 Author: Nate Cole <[email protected]> Authored: Wed Apr 6 09:53:15 2016 -0400 Committer: Nate Cole <[email protected]> Committed: Wed Apr 6 12:20:26 2016 -0400 ---------------------------------------------------------------------- .../ambari/server/api/query/QueryImpl.java | 23 +- .../internal/ClusterControllerImpl.java | 21 ++ .../internal/CompatibleRepositoryVersion.java | 20 +- ...atibleRepositoryVersionResourceProvider.java | 242 +++++++++++++------ .../internal/ReadOnlyResourceProvider.java | 12 + .../controller/spi/ClusterController.java | 11 + .../ambari/server/api/query/QueryImplTest.java | 9 +- ...leRepositoryVersionResourceProviderTest.java | 62 ++++- 8 files changed, 298 insertions(+), 102 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/3e57dc24/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 36ed189..ba3a774 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 @@ -367,6 +367,11 @@ public class QueryImpl implements Query, ResourceInstance { Resource.Type resourceType = getResourceDefinition().getType(); Predicate queryPredicate = createPredicate(getKeyValueMap(), processUserPredicate(userPredicate)); + Predicate updated = clusterController.getAmendedPredicate(resourceType, queryPredicate); + if (null != updated) { + queryPredicate = updated; + } + // must occur after processing user predicate and prior to creating request finalizeProperties(); @@ -408,16 +413,16 @@ public class QueryImpl implements Query, ResourceInstance { } // Optimization: - // Currently the steps executed when sub-resources are requested are: + // Currently the steps executed when sub-resources are requested are: // (1) Get *all* top-level resources // (2) Populate all top-level resources - // (3) Query for and populate sub-resources of *all* top-level resources + // (3) Query for and populate sub-resources of *all* top-level resources // (4) Apply pagination and predicate on resources from above // // Though this works, it is very inefficient when either: // (a) Predicate does not apply to sub-resources // (b) Page request is present - // It is inefficient because we needlessly populate sub-resources that might not get + // It is inefficient because we needlessly populate sub-resources that might not get // used due to their top-level resources being filtered out by the predicate and paging // // The optimization is to apply the predicate and paging request on the top-level resources @@ -551,22 +556,22 @@ public class QueryImpl implements Query, ResourceInstance { * â * âââ CResource2 * p3:2 - * + * * Given the following query ... - * + * * api/v1/a_resources?b_resources/p1>3&b_resources/p2=5&c_resources/p3=1 - * + * * The caller should pass the following property ids ... - * + * * b_resources/p1 * b_resources/p2 * c_resources/p3 - * + * * getJoinedResourceProperties should produce the following map of property sets * by making recursive calls on the sub-resources of each of this query's resources, * joining the resulting property sets, and adding them to the map keyed by the * resource ... - * + * * { * AResource1=[{b_resources/p1=1, b_resources/p2=5, c_resources/p3=1}, * {b_resources/p1=2, b_resources/p2=0, c_resources/p3=1}, http://git-wip-us.apache.org/repos/asf/ambari/blob/3e57dc24/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 9f864f8..e776b5a 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 @@ -108,9 +108,18 @@ public class ClusterControllerImpl implements ClusterController { } + // ----- ClusterController ------------------------------------------------- @Override + public Predicate getAmendedPredicate(Type type, Predicate predicate) { + ExtendedResourceProviderWrapper provider = ensureResourceProviderWrapper(type); + ensurePropertyProviders(type); + + return provider.getAmendedPredicate(predicate); + } + + @Override public QueryResponse getResources(Type type, Request request, Predicate predicate) throws UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException, SystemException { @@ -937,6 +946,18 @@ public class ClusterControllerImpl implements ClusterController { } + /** + * @return the amended predicate, or {@code null} to use the provided one + */ + public Predicate getAmendedPredicate(Predicate predicate) { + if (ReadOnlyResourceProvider.class.isInstance(resourceProvider)) { + return ((ReadOnlyResourceProvider) resourceProvider).amendPredicate(predicate); + } else { + return null; + } + } + + // ----- ExtendedResourceProvider ---------------------------------------- @Override http://git-wip-us.apache.org/repos/asf/ambari/blob/3e57dc24/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersion.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersion.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersion.java index 1c5fe89..bf388a7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersion.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersion.java @@ -17,10 +17,11 @@ */ package org.apache.ambari.server.controller.internal; -import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; +import java.util.HashSet; +import java.util.Set; -import java.util.ArrayList; -import java.util.List; +import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; +import org.apache.ambari.server.state.stack.upgrade.UpgradeType; /** * Helper class for maintaining RepositoryVersionEntity along with @@ -28,11 +29,11 @@ import java.util.List; */ public class CompatibleRepositoryVersion { private RepositoryVersionEntity repositoryVersionEntity; - private List<String> supportedTypes; + private Set<UpgradeType> supportedTypes; public CompatibleRepositoryVersion(RepositoryVersionEntity repositoryVersionEntity) { this.repositoryVersionEntity = repositoryVersionEntity; - this.supportedTypes = new ArrayList<String>(); + this.supportedTypes = new HashSet<>(); } /** @@ -40,16 +41,14 @@ public class CompatibleRepositoryVersion { * * @param type Supported Upgrade Type. */ - public void addUpgradePackType(String type) { - if (!supportedTypes.contains(type)) { - supportedTypes.add(type); - } + public void addUpgradePackType(UpgradeType type) { + supportedTypes.add(type); } /** * @return List of supported Upgrade Type(s). */ - public List<String> getSupportedTypes() { + public Set<UpgradeType> getSupportedTypes() { return supportedTypes; } @@ -59,4 +58,5 @@ public class CompatibleRepositoryVersion { public RepositoryVersionEntity getRepositoryVersionEntity() { return repositoryVersionEntity; } + } http://git-wip-us.apache.org/repos/asf/ambari/blob/3e57dc24/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProvider.java index 26b9645..87e73c5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProvider.java @@ -17,13 +17,22 @@ */ package org.apache.ambari.server.controller.internal; -import com.google.common.collect.Sets; -import com.google.inject.Inject; -import com.google.inject.Provider; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + import org.apache.ambari.server.StaticallyInject; import org.apache.ambari.server.api.resources.OperatingSystemResourceDefinition; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.AmbariManagementController; +import org.apache.ambari.server.controller.predicate.AndPredicate; +import org.apache.ambari.server.controller.predicate.EqualsPredicate; +import org.apache.ambari.server.controller.predicate.OrPredicate; import org.apache.ambari.server.controller.spi.NoSuchParentResourceException; import org.apache.ambari.server.controller.spi.NoSuchResourceException; import org.apache.ambari.server.controller.spi.Predicate; @@ -32,19 +41,15 @@ import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.Resource.Type; import org.apache.ambari.server.controller.spi.SystemException; import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; +import org.apache.ambari.server.controller.utilities.PredicateBuilder; import org.apache.ambari.server.orm.dao.RepositoryVersionDAO; import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.state.stack.UpgradePack; -import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import com.google.inject.Provider; /** @@ -55,17 +60,19 @@ public class CompatibleRepositoryVersionResourceProvider extends ReadOnlyResourc // ----- Property ID constants --------------------------------------------- - public static final String REPOSITORY_VERSION_ID_PROPERTY_ID = "CompatibleRepositoryVersions/id"; - public static final String REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID = "CompatibleRepositoryVersions/stack_name"; - public static final String REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID = "CompatibleRepositoryVersions/stack_version"; + public static final String REPOSITORY_VERSION_ID_PROPERTY_ID = "CompatibleRepositoryVersions/id"; + public static final String REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID = "CompatibleRepositoryVersions/stack_name"; + public static final String REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID = "CompatibleRepositoryVersions/stack_version"; public static final String REPOSITORY_VERSION_REPOSITORY_VERSION_PROPERTY_ID = "CompatibleRepositoryVersions/repository_version"; - public static final String REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID = "CompatibleRepositoryVersions/display_name"; - public static final String REPOSITORY_UPGRADES_SUPPORTED_TYPES_ID = "CompatibleRepositoryVersions/upgrade_types"; - public static final String SUBRESOURCE_OPERATING_SYSTEMS_PROPERTY_ID = new OperatingSystemResourceDefinition().getPluralName(); + public static final String REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID = "CompatibleRepositoryVersions/display_name"; + public static final String REPOSITORY_UPGRADES_SUPPORTED_TYPES_ID = "CompatibleRepositoryVersions/upgrade_types"; + public static final String SUBRESOURCE_OPERATING_SYSTEMS_PROPERTY_ID = new OperatingSystemResourceDefinition().getPluralName(); + private static final String REPOSITORY_STACK_VALUE = "stack_value"; private static Set<String> pkPropertyIds = Collections.singleton(REPOSITORY_VERSION_ID_PROPERTY_ID); static Set<String> propertyIds = Sets.newHashSet( + REPOSITORY_STACK_VALUE, REPOSITORY_VERSION_ID_PROPERTY_ID, REPOSITORY_VERSION_REPOSITORY_VERSION_PROPERTY_ID, REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID, @@ -89,9 +96,6 @@ public class CompatibleRepositoryVersionResourceProvider extends ReadOnlyResourc @Inject private static Provider<AmbariMetaInfo> s_ambariMetaInfo; - @Inject - private static Provider<RepositoryVersionHelper> s_repositoryVersionHelper; - /** * Create a new resource provider. */ @@ -106,76 +110,85 @@ public class CompatibleRepositoryVersionResourceProvider extends ReadOnlyResourc final Set<String> requestedIds = getRequestPropertyIds(request, predicate); final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate); - List<CompatibleRepositoryVersion> requestedEntities = new ArrayList<CompatibleRepositoryVersion>(); - String currentStackUniqueId = null; - Map<String, CompatibleRepositoryVersion> compatibleRepositoryVersionsMap = new HashMap<String, CompatibleRepositoryVersion>(); + Long currentStackUniqueId = null; + Map<Long, CompatibleRepositoryVersion> compatibleRepositoryVersionsMap = new HashMap<>(); + StackId stackId = null; + // !!! this is the case where the predicate was altered to include all stacks for (Map<String, Object> propertyMap : propertyMaps) { + if (propertyMap.containsKey(REPOSITORY_STACK_VALUE)) { + stackId = new StackId(propertyMap.get(REPOSITORY_STACK_VALUE).toString()); + break; + } + } - final StackId stackId = getStackInformationFromUrl(propertyMap); + if (null == stackId) { + if (propertyMaps.size() == 1) { + Map<String, Object> propertyMap = propertyMaps.iterator().next(); + stackId = getStackInformationFromUrl(propertyMap); + } else { + LOG.error("Property Maps size is NOT equal to 1. Current 'propertyMaps' size = {}", propertyMaps.size()); + } + } - if (stackId != null) { - if (propertyMaps.size() == 1) { - if (LOG.isDebugEnabled()) { - LOG.debug("Stack Name : " + stackId.getStackName() + ", Stack Version : " + stackId.getStackVersion()); - } - for (RepositoryVersionEntity repositoryVersionEntity : s_repositoryVersionDAO.findByStack(stackId)) { - currentStackUniqueId = Long.toString(repositoryVersionEntity.getId()); - compatibleRepositoryVersionsMap.put(currentStackUniqueId, new CompatibleRepositoryVersion(repositoryVersionEntity)); + if (null == stackId) { + LOG.error("Could not determine stack to process. Returning empty set."); + return resources; + } + + for (RepositoryVersionEntity repositoryVersionEntity : s_repositoryVersionDAO.findByStack(stackId)) { + currentStackUniqueId = repositoryVersionEntity.getId(); + compatibleRepositoryVersionsMap.put(repositoryVersionEntity.getId(), + new CompatibleRepositoryVersion(repositoryVersionEntity)); + if (LOG.isDebugEnabled()) { + LOG.debug("Added current stack id: {} to map", repositoryVersionEntity.getId()); + } + } + + Map<String, UpgradePack> packs = s_ambariMetaInfo.get().getUpgradePacks( + stackId.getStackName(), stackId.getStackVersion()); + + for (UpgradePack up : packs.values()) { + if (null != up.getTargetStack()) { + StackId targetStackId = new StackId(up.getTargetStack()); + List<RepositoryVersionEntity> repositoryVersionEntities = s_repositoryVersionDAO.findByStack(targetStackId); + + for (RepositoryVersionEntity repositoryVersionEntity : repositoryVersionEntities) { + if (compatibleRepositoryVersionsMap.containsKey(repositoryVersionEntity.getId())) { + compatibleRepositoryVersionsMap.get(repositoryVersionEntity.getId()).addUpgradePackType(up.getType()); if (LOG.isDebugEnabled()) { - LOG.debug("Added current stack id : " + currentStackUniqueId + " to Map."); + LOG.debug("Stack id: {} exists in map. Appended new upgrade type {}" + repositoryVersionEntity.getId(), up.getType()); } - } - - Map<String, UpgradePack> packs = s_ambariMetaInfo.get().getUpgradePacks( - stackId.getStackName(), stackId.getStackVersion()); - - for (UpgradePack up : packs.values()) { - if (null != up.getTargetStack()) { - StackId targetStackId = new StackId(up.getTargetStack()); - List<RepositoryVersionEntity> repositoryVersionEntities = s_repositoryVersionDAO.findByStack(targetStackId); - for (RepositoryVersionEntity repositoryVersionEntity : repositoryVersionEntities) { - if (compatibleRepositoryVersionsMap.containsKey(Long.toString(repositoryVersionEntity.getId()))) { - compatibleRepositoryVersionsMap.get(Long.toString(repositoryVersionEntity.getId())).addUpgradePackType(up.getType().toString()); - if (LOG.isDebugEnabled()) { - LOG.debug("Stack id : " + repositoryVersionEntity.getId() + " exists in Map. " + "Appended new Upgrade type : " + up.getType()); - } - } else { - CompatibleRepositoryVersion compatibleRepositoryVersionEntity = new CompatibleRepositoryVersion(repositoryVersionEntity); - compatibleRepositoryVersionEntity.addUpgradePackType(up.getType().toString()); - compatibleRepositoryVersionsMap.put(Long.toString(repositoryVersionEntity.getId()), compatibleRepositoryVersionEntity); - if (LOG.isDebugEnabled()) { - LOG.debug("Added Stack id : " + repositoryVersionEntity.getId() + " to Map with Upgrade type : " + up.getType()); - } - } - } - } else { - if (currentStackUniqueId != null) { - compatibleRepositoryVersionsMap.get(currentStackUniqueId).addUpgradePackType(up.getType().toString()); - if (LOG.isDebugEnabled()) { - LOG.debug("Current Stack id : " + currentStackUniqueId + " retrieved from Map. Added Upgrade type : " + up.getType()); - } - } else { - LOG.error("Couldn't retrieve Current stack entry from Map."); - } + } else { + CompatibleRepositoryVersion compatibleRepositoryVersionEntity = new CompatibleRepositoryVersion(repositoryVersionEntity); + compatibleRepositoryVersionEntity.addUpgradePackType(up.getType()); + compatibleRepositoryVersionsMap.put(repositoryVersionEntity.getId(), compatibleRepositoryVersionEntity); + if (LOG.isDebugEnabled()) { + LOG.debug("Added Stack id: {} to map with upgrade type {}", repositoryVersionEntity.getId(), up.getType()); } } - - } else { - LOG.error("Property Maps size NOT equal to 1. Current 'propertyMaps' size = " + propertyMaps.size()); } } else { - LOG.error("StackId is NULL."); + if (currentStackUniqueId != null) { + compatibleRepositoryVersionsMap.get(currentStackUniqueId).addUpgradePackType(up.getType()); + if (LOG.isDebugEnabled()) { + LOG.debug("Current Stack id: {} retrieved from map. Added upgrade type {}", currentStackUniqueId, up.getType()); + } + } else { + LOG.error("Couldn't retrieve Current stack entry from Map."); + } } } - for (String stackId : compatibleRepositoryVersionsMap.keySet()) { - CompatibleRepositoryVersion entity = compatibleRepositoryVersionsMap.get(stackId); + for (CompatibleRepositoryVersion entity : compatibleRepositoryVersionsMap.values()) { + RepositoryVersionEntity repositoryVersionEntity = entity.getRepositoryVersionEntity(); final Resource resource = new ResourceImpl(Resource.Type.CompatibleRepositoryVersion); setResourceProperty(resource, REPOSITORY_VERSION_ID_PROPERTY_ID, repositoryVersionEntity.getId(), requestedIds); + setResourceProperty(resource, REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID, repositoryVersionEntity.getStackName(), requestedIds); setResourceProperty(resource, REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID, repositoryVersionEntity.getStackVersion(), requestedIds); + setResourceProperty(resource, REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID, repositoryVersionEntity.getDisplayName(), requestedIds); setResourceProperty(resource, REPOSITORY_VERSION_REPOSITORY_VERSION_PROPERTY_ID, repositoryVersionEntity.getVersion(), requestedIds); setResourceProperty(resource, REPOSITORY_UPGRADES_SUPPORTED_TYPES_ID, entity.getSupportedTypes(), requestedIds); @@ -202,4 +215,89 @@ public class CompatibleRepositoryVersionResourceProvider extends ReadOnlyResourc return null; } + /** + * Identify the case where this is a top-level request, containing ONLY the stack name + * and stack version. Determine all other compatible stacks and make a new Predicate + * out of them. + * + * Consider a stack STACK-2.2 that is compatible with 2.3 and 2.4. The result of this + * call will be a predicate like so (abbreviated): + * <pre> + * in -> AndPredicate([stack_name=STACK],[stack_version=2.2]) + * out-> OrPredicate( + * AndPredicate([stack_name=STACK],[stack_version=2.2]), + * AndPredicate([stack_name=STACK],[stack_version=2.3]), + * AndPredicate([stack_name=STACK],[stack_version=2.4]) ) + * </pre> + * + * Any input predicate that does not conform to ONLY stack_name/stack_version will + * revert to the that predicate (return {@code null}). + */ + @SuppressWarnings("rawtypes") + @Override + public Predicate amendPredicate(Predicate predicate) { + if (!AndPredicate.class.isInstance(predicate)) { + return null; + } + + AndPredicate ap = (AndPredicate) predicate; + if (2 != ap.getPropertyIds().size()) { + return null; + } + + if (!ap.getPropertyIds().contains(REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID) && + !ap.getPropertyIds().contains(REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID)) { + return null; + } + + Predicate[] predicates = ap.getPredicates(); + if (!EqualsPredicate.class.isInstance(predicates[0]) || !EqualsPredicate.class.isInstance(predicates[1])) { + return null; + } + + EqualsPredicate pred1 = (EqualsPredicate) predicates[0]; + EqualsPredicate pred2 = (EqualsPredicate) predicates[1]; + + StackId stackId = null; + if (pred1.getPropertyId().equals(REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID)) { + stackId = new StackId(pred1.getValue().toString(), pred2.getValue().toString()); + } else { + stackId = new StackId(pred2.getValue().toString(), pred1.getValue().toString()); + } + + Map<String, UpgradePack> packs = s_ambariMetaInfo.get().getUpgradePacks( + stackId.getStackName(), stackId.getStackVersion()); + + Set<String> stackIds = new HashSet<>(); + + for (Entry<String, UpgradePack> entry : packs.entrySet()) { + UpgradePack pack = entry.getValue(); + String packStack = pack.getTargetStack(); + if (null == packStack || !packStack.equals(stackId.toString())) { + stackIds.add(packStack); + } + } + + + // !!! use the one passed in, it already includes the one of interest + List<Predicate> usable = new ArrayList<>(); + usable.add(predicate); + + // !!! add predicate for each of the compatible stacks as found by the upgrade packs + for (String requiredStack : stackIds) { + StackId targetStack = new StackId(requiredStack); + Predicate p = new PredicateBuilder().property(REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID).equals(targetStack.getStackName()) + .and().property(REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID).equals(targetStack.getStackVersion()).toPredicate(); + usable.add(p); + } + + // !!! add the stack that is used to find compatible versions for + Predicate p = new PredicateBuilder().property(REPOSITORY_STACK_VALUE).equals(stackId.toString()).toPredicate(); + usable.add(p); + + p = new OrPredicate(usable.toArray(new Predicate[usable.size()])); + + return p; + } + } http://git-wip-us.apache.org/repos/asf/ambari/blob/3e57dc24/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ReadOnlyResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ReadOnlyResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ReadOnlyResourceProvider.java index a72527d..562aa34 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ReadOnlyResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ReadOnlyResourceProvider.java @@ -70,4 +70,16 @@ public abstract class ReadOnlyResourceProvider extends AbstractControllerResourc NoSuchResourceException, NoSuchParentResourceException { throw new SystemException(READ_ONLY_MSG, null); } + + /** + * Get an amended predicate used when use {@link #getResources(Request, Predicate)}. This + * is needed in cases where the resource might incorrectly be filtered during predicate processing. + * Changing the predicate allows them to be included. + * @param predicate the predicate passed in the request + * @return the new predicate, or {@code null} to leave the predicate unchanged. + */ + public Predicate amendPredicate(Predicate predicate) { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/3e57dc24/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 aa1f09f..ec7425e 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 @@ -19,6 +19,8 @@ package org.apache.ambari.server.controller.spi; import java.util.Set; +import org.apache.ambari.server.controller.spi.Resource.Type; + /** * The cluster controller is the main access point for accessing resources * from the backend sources. A cluster controller maintains a mapping of @@ -132,6 +134,7 @@ public interface ClusterController extends SchemaFactory { * @param type the resource type * @return the schema object for the given resource */ + @Override public Schema getSchema(Resource.Type type); /** @@ -207,4 +210,12 @@ public interface ClusterController extends SchemaFactory { SystemException, NoSuchResourceException, NoSuchParentResourceException ; + + /** + * Gets the amended predicate for a resource. + * @param type the type of the resource + * @param predicate the predicate object to use for filtering + * @return the new predicate used for filtering + */ + Predicate getAmendedPredicate(Type type, Predicate predicate); } http://git-wip-us.apache.org/repos/asf/ambari/blob/3e57dc24/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 f869ba3..6bbb4bd 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 @@ -650,8 +650,9 @@ public class QueryImplTest { public void testExecute__Host_collection_AlertsSummary() throws Exception { ResourceDefinition resourceDefinition = new HostResourceDefinition(); Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>(); - final AtomicInteger pageCallCount = new AtomicInteger(0); + final AtomicInteger pageCallCount = new AtomicInteger(0); ClusterControllerImpl clusterControllerImpl = new ClusterControllerImpl(new ClusterControllerImplTest.TestProviderModule()) { + @Override public PageResponse getPage(Resource.Type type, QueryResponse queryResponse, Request request, Predicate predicate, PageRequest pageRequest, SortRequest sortRequest) throws UnsupportedPropertyException, SystemException, NoSuchResourceException, NoSuchParentResourceException { pageCallCount.incrementAndGet(); @@ -666,7 +667,7 @@ public class QueryImplTest { TreeNode<Resource> tree = result.getResultTree(); Assert.assertEquals(4, tree.getChildren().size()); Assert.assertEquals(1, pageCallCount.get()); - + //test 2: Predicate = (alerts_summary/CRITICAL > 0) pageCallCount.set(0); PredicateBuilder pb = new PredicateBuilder(); @@ -686,7 +687,7 @@ public class QueryImplTest { Assert.assertEquals("host:2", hostNode.getObject().getPropertyValue(PropertyHelper.getPropertyId("Hosts", "host_name"))); Assert.assertEquals(Resource.Type.Host, hostNode.getObject().getType()); Assert.assertEquals("1", hostNode.getObject().getPropertyValue(PropertyHelper.getPropertyId("alerts_summary", "CRITICAL"))); - + // test 3: Predicate = (alerts_summary/WARNING > 0) AND Page = (size=1) pageCallCount.set(0); pb = new PredicateBuilder(); @@ -976,6 +977,7 @@ public class QueryImplTest { expect(mockClusterController.getResources(eq(Resource.Type.Configuration), isA(Request.class), (Predicate)eq(null))).andReturn(mockSubQueryResponse).atLeastOnce(); expect(mockClusterController.getIterable(eq(Resource.Type.Host), isA(QueryResponse.class), isA(Request.class),(Predicate)eq(null), (PageRequest)eq(null), (SortRequest)eq(null))).andReturn(Collections.singleton(mockResource)).atLeastOnce(); expect(mockClusterController.getIterable(eq(Resource.Type.Configuration), isA(QueryResponse.class), isA(Request.class),(Predicate)eq(null), (PageRequest)eq(null), (SortRequest)eq(null))).andReturn(Collections.singleton(mockResource)).atLeastOnce(); + expect(mockClusterController.getAmendedPredicate(eq(Resource.Type.Host), (Predicate)eq(null))).andReturn((Predicate)null).atLeastOnce(); expect(mockQueryResponse.getResources()).andReturn(Collections.singleton(mockResource)).atLeastOnce(); expect(mockSubQueryResponse.getResources()).andReturn(Collections.singleton(mockResource)).atLeastOnce(); @@ -1056,6 +1058,7 @@ public class QueryImplTest { expect(mockClusterController.populateResources(eq(Resource.Type.Host), eq(Collections.singleton(mockResource)), isA(Request.class), (Predicate)eq(null))).andReturn(Collections.<Resource>emptySet()).times(1); // expect call to activate property providers for Configuration sub-resource expect(mockClusterController.populateResources(eq(Resource.Type.Configuration), eq(Collections.singleton(mockResource)), isA(Request.class), (Predicate)eq(null))).andReturn(Collections.<Resource>emptySet()).times(1); + expect(mockClusterController.getAmendedPredicate(eq(Resource.Type.Host), (Predicate)eq(null))).andReturn((Predicate)null).atLeastOnce(); expect(mockQueryResponse.getResources()).andReturn(Collections.singleton(mockResource)).atLeastOnce(); expect(mockSubQueryResponse.getResources()).andReturn(Collections.singleton(mockResource)).atLeastOnce(); http://git-wip-us.apache.org/repos/asf/ambari/blob/3e57dc24/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProviderTest.java index faef1c9..40d9b0b 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/CompatibleRepositoryVersionResourceProviderTest.java @@ -34,6 +34,7 @@ import java.util.Set; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.ResourceProviderFactory; import org.apache.ambari.server.controller.predicate.AndPredicate; +import org.apache.ambari.server.controller.predicate.OrPredicate; import org.apache.ambari.server.controller.spi.Predicate; import org.apache.ambari.server.controller.spi.Request; import org.apache.ambari.server.controller.spi.Resource; @@ -224,8 +225,8 @@ public class CompatibleRepositoryVersionResourceProviderTest { expect(ambariMetaInfo.getStack("HDP", "1.1")).andReturn(stack1).atLeastOnce(); expect(ambariMetaInfo.getStack("HDP", "2.2")).andReturn(stack2).atLeastOnce(); - expect(ambariMetaInfo.getUpgradePacks("HDP", "1.1")).andReturn(stack1.getUpgradePacks()); - expect(ambariMetaInfo.getUpgradePacks("HDP", "2.2")).andReturn(stack2.getUpgradePacks()); + expect(ambariMetaInfo.getUpgradePacks("HDP", "1.1")).andReturn(stack1.getUpgradePacks()).atLeastOnce(); + expect(ambariMetaInfo.getUpgradePacks("HDP", "2.2")).andReturn(stack2.getUpgradePacks()).atLeastOnce(); replay(ambariMetaInfo); @@ -272,9 +273,51 @@ public class CompatibleRepositoryVersionResourceProviderTest { assertEquals(2, resources.size()); // Test For Upgrade Types - Map<String, List<String>> versionToUpgradeTypesMap = new HashMap<String, List<String>>(); - versionToUpgradeTypesMap.put("1.1", Arrays.asList("ROLLING")); - versionToUpgradeTypesMap.put("2.2", Arrays.asList("NON_ROLLING", "ROLLING")); + Map<String, List<UpgradeType>> versionToUpgradeTypesMap = new HashMap<>(); + versionToUpgradeTypesMap.put("1.1", Arrays.asList(UpgradeType.ROLLING)); + versionToUpgradeTypesMap.put("2.2", Arrays.asList(UpgradeType.NON_ROLLING, UpgradeType.ROLLING)); + assertEquals(versionToUpgradeTypesMap.size(), checkUpgradeTypes(resources, versionToUpgradeTypesMap)); + } + + @Test + public void testGetResourcesWithAmendedPredicate() throws Exception { + SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createClusterAdministrator("admin", 2L)); + + final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionResourceProvider(); + + Request getRequest = PropertyHelper.getReadRequest( + RepositoryVersionResourceProvider.REPOSITORY_VERSION_ID_PROPERTY_ID, + RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID, + RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID, + CompatibleRepositoryVersionResourceProvider.REPOSITORY_UPGRADES_SUPPORTED_TYPES_ID); + Predicate predicateStackName = new PredicateBuilder().property(RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID).equals("HDP").toPredicate(); + Predicate predicateStackVersion = new PredicateBuilder().property(RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID).equals("1.1").toPredicate(); + + // !!! non-compatible, within stack + assertEquals(1, provider.getResources(getRequest, new AndPredicate(predicateStackName, predicateStackVersion)).size()); + + CompatibleRepositoryVersionResourceProvider compatibleProvider = new CompatibleRepositoryVersionResourceProvider(null); + + getRequest = PropertyHelper.getReadRequest( + CompatibleRepositoryVersionResourceProvider.REPOSITORY_VERSION_ID_PROPERTY_ID, + CompatibleRepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID, + CompatibleRepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID, + CompatibleRepositoryVersionResourceProvider.REPOSITORY_UPGRADES_SUPPORTED_TYPES_ID); + predicateStackName = new PredicateBuilder().property(CompatibleRepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID).equals("HDP").toPredicate(); + predicateStackVersion = new PredicateBuilder().property(CompatibleRepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID).equals("1.1").toPredicate(); + + // !!! compatible, across stack + Predicate newPredicate = compatibleProvider.amendPredicate(new AndPredicate(predicateStackName, predicateStackVersion)); + + assertEquals(OrPredicate.class, newPredicate.getClass()); + + Set<Resource> resources = compatibleProvider.getResources(getRequest, newPredicate); + assertEquals(2, resources.size()); + + // Test For Upgrade Types + Map<String, List<UpgradeType>> versionToUpgradeTypesMap = new HashMap<>(); + versionToUpgradeTypesMap.put("1.1", Arrays.asList(UpgradeType.ROLLING)); + versionToUpgradeTypesMap.put("2.2", Arrays.asList(UpgradeType.NON_ROLLING, UpgradeType.ROLLING)); assertEquals(versionToUpgradeTypesMap.size(), checkUpgradeTypes(resources, versionToUpgradeTypesMap)); } @@ -285,7 +328,7 @@ public class CompatibleRepositoryVersionResourceProviderTest { * @param versionToUpgradeTypesMap Contains 'Stack version' to 'Upgrade Type' Map. * @return count, 0 or number of Stack version's Upgrade Type(s) correctly compared. */ - public int checkUpgradeTypes(Set<Resource> resources, Map<String, List<String>> versionToUpgradeTypesMap) { + public int checkUpgradeTypes(Set<Resource> resources, Map<String, List<UpgradeType>> versionToUpgradeTypesMap) { int count = 0; Iterator<Resource> itr = resources.iterator(); while (itr.hasNext()) { @@ -295,9 +338,12 @@ public class CompatibleRepositoryVersionResourceProviderTest { Map<String, Object> propMap = resPropMap.get(resource); String stackVersion = propMap.get("stack_version").toString(); if (versionToUpgradeTypesMap.containsKey(stackVersion)) { - List<String> upgradeTypes = new ArrayList<>((List<String>)propMap.get("upgrade_types")); + List<UpgradeType> upgradeTypes = new ArrayList<>((Set<UpgradeType>)propMap.get("upgrade_types")); + List<UpgradeType> expectedTypes = versionToUpgradeTypesMap.get(stackVersion); Collections.sort(upgradeTypes); - assertEquals(versionToUpgradeTypesMap.get(stackVersion), upgradeTypes); + Collections.sort(expectedTypes); + + assertEquals(expectedTypes, upgradeTypes); count++; } }
