This is an automated email from the ASF dual-hosted git repository. jgolieb pushed a commit to branch branch-feature-AMBARI-14714-mpack-advisor in repository https://gitbox.apache.org/repos/asf/ambari.git
commit febf6a54dae6114d779b1c067e84506270a73c6f Author: Doroszlai, Attila <[email protected]> AuthorDate: Wed May 30 00:28:58 2018 +0200 AMBARI-22875. Service group name mismatch --- .../internal/ExportBlueprintRequest.java | 3 +- .../orm/entities/HostGroupComponentEntity.java | 2 +- .../server/orm/entities/MpackInstanceEntity.java | 21 +- .../BlueprintBasedClusterProvisionRequest.java | 11 - .../ambari/server/topology/BlueprintFactory.java | 36 +-- .../ambari/server/topology/BlueprintImpl.java | 16 +- .../apache/ambari/server/topology/Component.java | 47 +--- .../ambari/server/topology/HostGroupImpl.java | 2 +- .../ambari/server/topology/MpackInstance.java | 48 +--- .../ambari/server/topology/ResolvedComponent.java | 9 +- .../server/topology/ResolvedComponent_Builder.java | 2 +- .../server/topology/StackComponentResolver.java | 56 ++--- .../src/main/resources/Ambari-DDL-Derby-CREATE.sql | 1 + .../src/main/resources/Ambari-DDL-MySQL-CREATE.sql | 1 + .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 1 + .../main/resources/Ambari-DDL-Postgres-CREATE.sql | 1 + .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 1 + .../main/resources/Ambari-DDL-SQLServer-CREATE.sql | 1 + .../ambari/server/topology/AmbariContextTest.java | 6 +- .../server/topology/BlueprintFactoryTest.java | 42 ---- .../server/topology/DownloadMpacksTaskTest.java | 6 +- .../topology/StackComponentResolverTest.java | 275 ++++++++++++++++++--- .../server/topology/TopologyManagerTest.java | 4 +- .../RejectUnknownComponentsTest.java} | 10 +- 24 files changed, 345 insertions(+), 257 deletions(-) diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java index dc3f2d5..6e6fd69 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java @@ -272,8 +272,7 @@ public class ExportBlueprintRequest implements TopologyRequest { String.valueOf(resource.getPropertyValue(HostComponentResourceProvider.HOST_COMPONENT_SERVICE_NAME_PROPERTY_ID)); String serviceGroupName = String.valueOf(resource.getPropertyValue(HostComponentResourceProvider.HOST_COMPONENT_SERVICE_GROUP_NAME_PROPERTY_ID)); - StackId stackId = serviceGroupToMpack.get(serviceGroupName); - getComponents().add(new Component(componentName, stackId, serviceName, null)); + getComponents().add(new Component(componentName, serviceGroupName, serviceName, null)); } addAmbariComponentIfLocalhost((String) host.getObject().getPropertyValue( PropertyHelper.getPropertyId("Hosts", "host_name"))); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java index f16ef40..708fb3f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostGroupComponentEntity.java @@ -211,7 +211,7 @@ public class HostGroupComponentEntity { /** * @return the name of the service instance defining this component - * (only needs to be set if component resolution would be ambigous otherwise) + * (only needs to be set if component resolution would be ambiguous otherwise) */ public String getServiceName() { return serviceName; diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MpackInstanceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MpackInstanceEntity.java index 1956108..9063ed0 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MpackInstanceEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MpackInstanceEntity.java @@ -59,6 +59,9 @@ public abstract class MpackInstanceEntity { @Column(name = "mpack_name", nullable = false) private String mpackName; + @Column(name = "mpack_type", nullable = false) + private String mpackType; + @Column(name = "mpack_version", nullable = false) private String mpackVersion; @@ -90,20 +93,34 @@ public abstract class MpackInstanceEntity { } /** - * @return the name of the mpack + * @return the name of the mpack instance */ public String getMpackName() { return mpackName; } /** - * @param mpackName the name of the mpack + * @param mpackName the name of the mpack instance */ public void setMpackName(String mpackName) { this.mpackName = mpackName; } /** + * @return the name (type) of the mpack + */ + public String getMpackType() { + return mpackType; + } + + /** + * @param mpackType the name (type) of the mpack + */ + public void setMpackType(String mpackType) { + this.mpackType = mpackType; + } + + /** * @return the version of the mpack */ public String getMpackVersion() { diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintBasedClusterProvisionRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintBasedClusterProvisionRequest.java index 22d4bab..58ce5d7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintBasedClusterProvisionRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintBasedClusterProvisionRequest.java @@ -20,7 +20,6 @@ package org.apache.ambari.server.topology; import static java.util.stream.Collectors.toMap; import java.util.Collection; -import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.function.Function; @@ -162,16 +161,6 @@ public class BlueprintBasedClusterProvisionRequest implements Blueprint, Provisi return stack; } - public Map<String, Map<String, ServiceInstance>> getServicesByMpack() { - Map<String, Map<String, ServiceInstance>> result = new HashMap<>(); - for (MpackInstance mpack : mpacks) { - Map<String, ServiceInstance> services = mpack.getServiceInstances().stream() - .collect(toMap(ServiceInstance::getName, Function.identity())); - result.put(mpack.getMpackName(), services); - } - return result; - } - /** * @return service instances defined in the topology, mapped by service name, * whose name is unique across all mpacks. diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java index cc29551..0f13539 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java @@ -18,8 +18,6 @@ package org.apache.ambari.server.topology; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toSet; import static org.apache.ambari.server.controller.internal.BlueprintResourceProvider.BLUEPRINT_NAME_PROPERTY_ID; import static org.apache.ambari.server.controller.internal.BlueprintResourceProvider.COMPONENT_MPACK_INSTANCE_PROPERTY; @@ -44,9 +42,6 @@ import java.util.Collections; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.TreeSet; -import java.util.function.Function; -import java.util.stream.Stream; import javax.inject.Inject; import javax.inject.Provider; @@ -56,14 +51,12 @@ import org.apache.ambari.server.orm.dao.BlueprintDAO; import org.apache.ambari.server.orm.entities.BlueprintEntity; import org.apache.ambari.server.stack.NoSuchStackException; import org.apache.ambari.server.state.StackId; -import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Joiner; /** * Create a Blueprint instance. @@ -84,7 +77,7 @@ public class BlueprintFactory { BlueprintEntity entity = blueprintDAO.get().findByName(blueprintName); if (entity != null) { Set<StackId> stackIds = entity.getMpackInstances().stream() - .map(m -> new StackId(m.getMpackName(), m.getMpackVersion())) + .map(m -> new StackId(m.getMpackType(), m.getMpackVersion())) .collect(toSet()); return new BlueprintImpl(entity, stackIds); } @@ -113,7 +106,7 @@ public class BlueprintFactory { if (stackId.isPresent()) { String stackName = stackId.get().getStackName(); String stackVersion = stackId.get().getStackVersion(); - mpackInstances = Collections.singleton(new MpackInstance(stackName, stackVersion, null, null, Configuration.createEmpty())); + mpackInstances = Collections.singleton(new MpackInstance(stackName, stackName, stackVersion, null, Configuration.createEmpty())); } } Set<StackId> stackIds = mpackInstances.stream() @@ -151,29 +144,6 @@ public class BlueprintFactory { : Optional.empty(); } - /** - * Verify that each item in <code>items</code> is defined by only one stack. - * - * @param items the items to check - * @param type string description of the type of items (eg. "Service", or "Component") - * @param lookup a function to find the set of stacks that an item belongs to - * @throws IllegalArgumentException if some items are defined in multiple stacks - */ - static void verifyStackDefinitionsAreDisjoint(Stream<String> items, String type, Function<String, Set<StackId>> lookup) { - Set<Pair<String, Set<StackId>>> definedInMultipleStacks = items - .map(s -> Pair.of(s, lookup.apply(s))) - .filter(p -> p.getRight().size() > 1) - .collect(toCollection(TreeSet::new)); - - if (!definedInMultipleStacks.isEmpty()) { - String msg = definedInMultipleStacks.stream() - .map(p -> String.format("%s %s is defined in multiple stacks: %s", type, p.getLeft(), Joiner.on(", ").join(p.getRight()))) - .collect(joining("\n")); - LOG.error(msg); - throw new IllegalArgumentException(msg); - } - } - //todo: Move logic to HostGroupImpl @SuppressWarnings("unchecked") private Collection<HostGroup> processHostGroups(Map<String, Object> properties) { @@ -227,7 +197,7 @@ public class BlueprintFactory { //TODO, might want to add some validation here, to only accept value enum types, rwn ProvisionAction provisionAction = componentProperties.containsKey(COMPONENT_PROVISION_ACTION_PROPERTY_ID) ? ProvisionAction.valueOf(componentProperties.get(COMPONENT_PROVISION_ACTION_PROPERTY_ID)) : null; - components.add(new Component(componentName, new StackId(mpackInstance), serviceInstance, provisionAction)); + components.add(new Component(componentName, mpackInstance, serviceInstance, provisionAction)); } return components; diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java index 633bcb0..7e60cb9 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java @@ -29,6 +29,8 @@ import java.util.Map; import java.util.Set; import java.util.function.Supplier; +import javax.annotation.Nonnull; + import org.apache.ambari.server.orm.entities.BlueprintConfigEntity; import org.apache.ambari.server.orm.entities.BlueprintConfiguration; import org.apache.ambari.server.orm.entities.BlueprintEntity; @@ -103,6 +105,7 @@ public class BlueprintImpl implements Blueprint { return stackIds; } + @Nonnull @Override public SecurityConfiguration getSecurity() { return security; @@ -185,12 +188,8 @@ public class BlueprintImpl implements Blueprint { private Collection<MpackInstance> parseMpacks(BlueprintEntity blueprintEntity) throws NoSuchStackException { Collection<MpackInstance> mpackInstances = new ArrayList<>(); - for (BlueprintMpackInstanceEntity mpack: blueprintEntity.getMpackInstances()) { - MpackInstance mpackInstance = new MpackInstance(); - mpackInstance.setMpackName(mpack.getMpackName()); - mpackInstance.setMpackVersion(mpack.getMpackVersion()); - mpackInstance.setUrl(mpack.getMpackUri()); - mpackInstance.setConfiguration(processConfiguration(mpack.getConfigurations())); + for (BlueprintMpackInstanceEntity mpack : blueprintEntity.getMpackInstances()) { + MpackInstance mpackInstance = new MpackInstance(mpack.getMpackName(), mpack.getMpackType(), mpack.getMpackVersion(), mpack.getMpackUri(), BlueprintImpl.fromConfigEntities(mpack.getConfigurations())); // TODO: come up with proper mpack -> stack resolution for(MpackInstanceServiceEntity serviceEntity: mpack.getServiceInstances()) { ServiceInstance serviceInstance = new ServiceInstance( @@ -329,10 +328,7 @@ public class BlueprintImpl implements Blueprint { componentEntity.setHostGroupEntity(group); componentEntity.setHostGroupName(group.getName()); componentEntity.setServiceName(component.getServiceInstance()); - if (null != component.getStackId()) { - componentEntity.setMpackName(component.getStackId().getStackName()); - componentEntity.setMpackVersion(component.getStackId().getStackVersion()); - } + componentEntity.setMpackName(component.getMpackInstance()); // add provision action (if specified) to entity type // otherwise, just leave this column null (provision_action) diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Component.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Component.java index eac584f..99ab038 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/Component.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Component.java @@ -24,41 +24,25 @@ import java.util.Objects; import javax.annotation.Nullable; import org.apache.ambari.server.controller.internal.ProvisionAction; -import org.apache.ambari.server.state.StackId; + +import com.google.common.base.MoreObjects; public class Component { private final String name; - - @Nullable private final String mpackInstance; - - @Nullable - private final StackId stackId; - - @Nullable private final String serviceInstance; private final ProvisionAction provisionAction; - @Deprecated public Component(String name) { this(name, null, null, null); } - public Component(String name, @Nullable String mpackInstance, @Nullable String serviceInstance) { + public Component(String name, @Nullable String mpackInstance, @Nullable String serviceInstance, ProvisionAction provisionAction) { this.name = name; - this.stackId = null; this.mpackInstance = mpackInstance; this.serviceInstance = serviceInstance; - this.provisionAction = null; - } - - public Component(String name, @Nullable StackId stackId, @Nullable String serviceInstance, ProvisionAction provisionAction) { - this.name = name; - this.stackId = stackId; - this.mpackInstance = null; - this.serviceInstance = serviceInstance; - this.provisionAction = provisionAction; + this.provisionAction = provisionAction != null ? provisionAction : ProvisionAction.INSTALL_AND_START; } /** @@ -70,21 +54,7 @@ public class Component { return this.name; } - /** - * @return the mpack associated with this component as {@link String} (can be {@code null} if component -> mpack mapping is unambiguous) - */ - public String getStackIdAsString() { - return stackId != null ? stackId.toString() : null; - } - - /** - * @return the mpack associated with this component as {@link StackId} (can be {@code null} if component -> mpack mapping is unambiguous) - */ - public StackId getStackId() { - return stackId; - } - - + @Nullable public String getMpackInstance() { return this.mpackInstance; } @@ -93,6 +63,7 @@ public class Component { * @return the service instance this component belongs to. Can be {@code null} if component does not belong to a service * instance (there is a single service of the component's service type) */ + @Nullable public String getServiceInstance() { return serviceInstance; } @@ -109,9 +80,8 @@ public class Component { @Override public String toString() { - return com.google.common.base.Objects.toStringHelper(this) + return MoreObjects.toStringHelper(this) .add("name", name) - .add("stackId", stackId) .add("mpackInstance", mpackInstance) .add("serviceInstance", serviceInstance) .add("provisionAction", provisionAction) @@ -125,7 +95,6 @@ public class Component { if (o == null || getClass() != o.getClass()) return false; Component component = (Component) o; return Objects.equals(name, component.name) && - Objects.equals(stackId, component.stackId) && Objects.equals(mpackInstance, component.mpackInstance) && Objects.equals(serviceInstance, component.serviceInstance) && provisionAction == component.provisionAction; @@ -133,6 +102,6 @@ public class Component { @Override public int hashCode() { - return Objects.hash(name, stackId, mpackInstance, serviceInstance, provisionAction); + return Objects.hash(name, mpackInstance, serviceInstance, provisionAction); } } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupImpl.java index 83375d5..29e75a0 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupImpl.java @@ -140,7 +140,7 @@ public class HostGroupImpl implements HostGroup { Component component = new Component( componentEntity.getName(), - stackId, + componentEntity.getMpackName(), componentEntity.getServiceName(), null == componentEntity.getProvisionAction() ? null : ProvisionAction.valueOf(componentEntity.getProvisionAction())); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/MpackInstance.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/MpackInstance.java index 882621b..5756941 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/MpackInstance.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/MpackInstance.java @@ -21,7 +21,6 @@ package org.apache.ambari.server.topology; import java.util.ArrayList; import java.util.Collection; -import org.apache.ambari.server.controller.internal.Stack; import org.apache.ambari.server.orm.entities.BlueprintEntity; import org.apache.ambari.server.orm.entities.BlueprintMpackInstanceEntity; import org.apache.ambari.server.orm.entities.MpackInstanceConfigEntity; @@ -43,19 +42,23 @@ public class MpackInstance implements Configurable { @JsonProperty("url") private String url; + @JsonProperty("type") private String mpackType; - private Stack stack; private Configuration configuration = new Configuration(); @JsonProperty("service_instances") private Collection<ServiceInstance> serviceInstances = new ArrayList<>(); - public MpackInstance(String mpackName, String mpackVersion, String url, Stack stack, Configuration configuration) { + public MpackInstance(StackId stackId) { + this(null, stackId.getStackName(), stackId.getStackVersion(), null, Configuration.createEmpty()); + } + + public MpackInstance(String mpackName, String mpackType, String mpackVersion, String url, Configuration configuration) { this.mpackName = mpackName; + this.mpackType = mpackType; this.mpackVersion = mpackVersion; this.url = url; - this.stack = stack; this.configuration = configuration; } @@ -69,42 +72,20 @@ public class MpackInstance implements Configurable { public MpackInstance() { } public String getMpackName() { - return mpackName; - } - - public void setMpackName(String mpackName) { - this.mpackName = mpackName; + return mpackName != null ? mpackName : mpackType; } public String getMpackType() { - return mpackType; - } - - public void setMpackType(String mpackType) { - this.mpackType = mpackType; + return mpackType != null ? mpackType : mpackName; } - public String getMpackVersion() { return mpackVersion; } - public void setMpackVersion(String mpackVersion) { - this.mpackVersion = mpackVersion; - } - @JsonIgnore public StackId getStackId() { - return new StackId(getMpackName(), getMpackVersion()); - } - - @JsonIgnore - public Stack getStack() { - return stack; - } - - public void setStack(Stack stack) { - this.stack = stack; + return new StackId(getMpackType(), getMpackVersion()); } @JsonIgnore @@ -171,7 +152,8 @@ public class MpackInstance implements Configurable { */ private void setCommonProperties(MpackInstanceEntity mpackInstanceEntity) { mpackInstanceEntity.setMpackUri(url); - mpackInstanceEntity.setMpackName(mpackName); + mpackInstanceEntity.setMpackName(getMpackName()); + mpackInstanceEntity.setMpackType(getMpackType()); mpackInstanceEntity.setMpackVersion(mpackVersion); Collection<MpackInstanceConfigEntity> mpackConfigEntities = BlueprintImpl.toConfigEntities(configuration, MpackInstanceConfigEntity::new); @@ -192,11 +174,7 @@ public class MpackInstance implements Configurable { } public static MpackInstance fromEntity(MpackInstanceEntity entity) { - MpackInstance mpack = new MpackInstance(); - mpack.setUrl(entity.getMpackUri()); - mpack.setMpackName(entity.getMpackName()); - mpack.setMpackVersion(entity.getMpackVersion()); - mpack.setConfiguration(BlueprintImpl.fromConfigEntities(entity.getConfigurations())); + MpackInstance mpack = new MpackInstance(entity.getMpackName(), entity.getMpackType(), entity.getMpackVersion(), entity.getMpackUri(), BlueprintImpl.fromConfigEntities(entity.getConfigurations())); for (MpackInstanceServiceEntity serviceEntity: entity.getServiceInstances()) { ServiceInstance serviceInstance = new ServiceInstance(); serviceInstance.setName(serviceEntity.getName()); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ResolvedComponent.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ResolvedComponent.java index 2b9d478..b3849b4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ResolvedComponent.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ResolvedComponent.java @@ -61,7 +61,14 @@ public interface ResolvedComponent { .component(component) .componentName(component.getName()) .serviceName(Optional.ofNullable(component.getServiceInstance())) - .serviceGroupName(Optional.ofNullable(component.getStackIdAsString())); + .serviceGroupName(Optional.ofNullable(component.getMpackInstance())); + } + + /** + * Starts building a {@code ResolvedComponent}. + */ + static Builder builder(String name) { + return new Builder().componentName(name); } class Builder extends ResolvedComponent_Builder { diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ResolvedComponent_Builder.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ResolvedComponent_Builder.java index 7f3e805..082ed4b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ResolvedComponent_Builder.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ResolvedComponent_Builder.java @@ -34,7 +34,7 @@ import com.google.common.base.Preconditions; * Auto-generated superclass of {@link ResolvedComponent.Builder}, derived from the API of {@link * ResolvedComponent}. */ -abstract class ResolvedComponent_Builder { +abstract class ResolvedComponent_Builder implements ResolvedComponent { /** Creates a new builder using {@code value} as a template. */ public static ResolvedComponent.Builder from(ResolvedComponent value) { diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/StackComponentResolver.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/StackComponentResolver.java index 783be40..4448feb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/StackComponentResolver.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/StackComponentResolver.java @@ -17,13 +17,16 @@ */ package org.apache.ambari.server.topology; +import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.Stream; @@ -34,7 +37,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Joiner; import com.google.common.base.Strings; public class StackComponentResolver implements ComponentResolver { @@ -43,20 +45,21 @@ public class StackComponentResolver implements ComponentResolver { @Override public Map<String, Set<ResolvedComponent>> resolveComponents(BlueprintBasedClusterProvisionRequest request) { - Map<String, ServiceInstance> uniqueServices = request.getUniqueServices(); - Map<String, Map<String, ServiceInstance>> mpackServices = request.getServicesByMpack(); + Collection<MpackInstance> mpacks = request.getMpacks(); + Map<String, StackId> stackIdByMpackName = getMpackStackIds(mpacks); Map<String, Set<ResolvedComponent>> result = new HashMap<>(); List<String> problems = new LinkedList<>(); StackDefinition stack = request.getStack(); for (HostGroup hg : request.getHostGroups().values()) { - result.put(hg.getName(), new HashSet<>()); + Set<ResolvedComponent> hostGroupComponents = new HashSet<>(); + result.put(hg.getName(), hostGroupComponents); for (Component comp : hg.getComponents()) { + String mpackInstanceName = comp.getMpackInstance(); Stream<Pair<StackId, ServiceInfo>> servicesForComponent = stack.getServicesForComponent(comp.getName()); - servicesForComponent = filterByMpackName(comp, servicesForComponent); - servicesForComponent = filterByServiceName(comp, servicesForComponent, mpackServices, uniqueServices); + servicesForComponent = filterByMpackName(mpackInstanceName, servicesForComponent, stackIdByMpackName); Set<Pair<StackId, ServiceInfo>> serviceMatches = servicesForComponent.collect(toSet()); @@ -75,13 +78,13 @@ public class StackComponentResolver implements ComponentResolver { .build(); LOG.debug("Component resolved: " + resolved); - result.get(hg.getName()).add(resolved); + hostGroupComponents.add(resolved); } } } if (!problems.isEmpty()) { - throw new IllegalArgumentException("Component resolution failure:\n" + Joiner.on("\n").join(problems)); + throw new IllegalArgumentException("Component resolution failure:\n" + String.join("\n", problems)); } return result; @@ -95,8 +98,8 @@ public class StackComponentResolver implements ComponentResolver { .append(" found for component ").append(comp.getName()) .append(" in host group " ).append(hg.getName()); - if (!Strings.isNullOrEmpty(comp.getStackIdAsString())) { - sb.append(" mpack: ").append(comp.getStackIdAsString()); + if (!Strings.isNullOrEmpty(comp.getMpackInstance())) { + sb.append(" mpack: ").append(comp.getMpackInstance()); } if (!Strings.isNullOrEmpty(comp.getServiceInstance())) { sb.append(" service: ").append(comp.getServiceInstance()); @@ -108,33 +111,22 @@ public class StackComponentResolver implements ComponentResolver { return sb.toString(); } - // if component references a specific service instance, filter the stream by the type of that service - private static Stream<Pair<StackId, ServiceInfo>> filterByServiceName(Component comp, Stream<Pair<StackId, ServiceInfo>> stream, - Map<String, Map<String, ServiceInstance>> mpackServices, Map<String, ServiceInstance> uniqueServices + // if component references a specific mpack instance, filter the stream by the name of that mpack + private static Stream<Pair<StackId, ServiceInfo>> filterByMpackName( + String mpackInstanceName, + Stream<Pair<StackId, ServiceInfo>> stream, + Map<String, StackId> stackIdByMpackInstanceName ) { - if (!Strings.isNullOrEmpty(comp.getServiceInstance())) { - String mpackName = comp.getStackIdAsString(); - Map<String, ServiceInstance> services = !Strings.isNullOrEmpty(mpackName) - ? mpackServices.get(mpackName) - : uniqueServices; - - ServiceInstance service = services.get(comp.getServiceInstance()); - if (service != null) { - String serviceType = service.getType(); - - return stream.filter(pair -> pair.getRight().getName().equals(serviceType)); - } + if (mpackInstanceName != null) { + StackId mpackStackId = stackIdByMpackInstanceName.get(mpackInstanceName); + return stream.filter(pair -> Objects.equals(pair.getLeft(), mpackStackId)); } - return stream; } - // if component references a specific mpack instance, filter the stream by the name of that mpack - private static Stream<Pair<StackId, ServiceInfo>> filterByMpackName(Component comp, Stream<Pair<StackId, ServiceInfo>> stream) { - if (comp.getStackId() != null) { - return stream.filter(pair -> pair.getLeft().equals(comp.getStackId())); - } - return stream; + private static Map<String, StackId> getMpackStackIds(Collection<MpackInstance> mpacks) { + return mpacks.stream() + .collect(toMap(MpackInstance::getMpackName, MpackInstance::getStackId)); } } diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql index 5c0e8a1..a4cfeb6 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql @@ -621,6 +621,7 @@ CREATE TABLE mpack_instance( blueprint_name VARCHAR(255), topology_request_id BIGINT, mpack_name VARCHAR(255) NOT NULL, + mpack_type VARCHAR(255) NOT NULL, mpack_version VARCHAR(255) NOT NULL, mpack_uri VARCHAR(255), mpack_id BIGINT, diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql index d9f1472..4dce027 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -639,6 +639,7 @@ CREATE TABLE mpack_instance( blueprint_name VARCHAR(255), topology_request_id BIGINT, mpack_name VARCHAR(255) NOT NULL, + mpack_type VARCHAR(255) NOT NULL, mpack_version VARCHAR(255) NOT NULL, mpack_uri VARCHAR(255), mpack_id BIGINT, diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql index a2b9dee..88bb0c3 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -619,6 +619,7 @@ CREATE TABLE mpack_instance( blueprint_name VARCHAR2(255), topology_request_id NUMBER(19), mpack_name VARCHAR2(255) NOT NULL, + mpack_type VARCHAR(255) NOT NULL, mpack_version VARCHAR2(255) NOT NULL, mpack_uri VARCHAR2(255), mpack_id NUMBER(19), diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql index 505e8db..dc33e43 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -622,6 +622,7 @@ CREATE TABLE mpack_instance( blueprint_name VARCHAR(255), topology_request_id BIGINT, mpack_name VARCHAR(255) NOT NULL, + mpack_type VARCHAR(255) NOT NULL, mpack_version VARCHAR(255) NOT NULL, mpack_uri VARCHAR(255), mpack_id BIGINT, diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql index 0033a69..3e847c6 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql @@ -617,6 +617,7 @@ CREATE TABLE mpack_instance( blueprint_name VARCHAR(255), topology_request_id NUMERIC(19), mpack_name VARCHAR(255) NOT NULL, + mpack_type VARCHAR(255) NOT NULL, mpack_version VARCHAR(255) NOT NULL, mpack_uri VARCHAR(255), mpack_id NUMERIC(19), diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql index c6cca3c..1f1a24d 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql @@ -636,6 +636,7 @@ CREATE TABLE mpack_instance( blueprint_name VARCHAR(255), topology_request_id BIGINT, mpack_name VARCHAR(255) NOT NULL, + mpack_type VARCHAR(255) NOT NULL, mpack_version VARCHAR(255) NOT NULL, mpack_uri VARCHAR(255), mpack_id BIGINT, diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/AmbariContextTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/AmbariContextTest.java index b53bc5e..5354088 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/topology/AmbariContextTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/AmbariContextTest.java @@ -407,9 +407,9 @@ public class AmbariContextTest { // test Stream<ResolvedComponent> components = Stream.of( - ResolvedComponent.builder(new Component("component1", new StackId("mpack", "1.0"), "service1", null)).buildPartial(), - ResolvedComponent.builder(new Component("component2", new StackId("mpack", "1.0"), "service1", null)).buildPartial(), - ResolvedComponent.builder(new Component("component3", new StackId("mpack", "1.0"), "service2", null)).buildPartial() + ResolvedComponent.builder(new Component("component1", "mpack", "service1", null)).buildPartial(), + ResolvedComponent.builder(new Component("component2", "mpack", "service1", null)).buildPartial(), + ResolvedComponent.builder(new Component("component3", "mpack", "service2", null)).buildPartial() ); context.createAmbariHostResources(CLUSTER_ID, "host1", components); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintFactoryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintFactoryTest.java index ff163d3..2b64390 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintFactoryTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintFactoryTest.java @@ -35,7 +35,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.apache.ambari.server.controller.internal.BlueprintResourceProvider; import org.apache.ambari.server.controller.internal.BlueprintResourceProviderTest; @@ -250,45 +249,4 @@ public class BlueprintFactoryTest { testFactory.createBlueprint(props, null); } - @Test(expected = IllegalArgumentException.class) // THEN - public void verifyDefinitionsDisjointShouldRejectDuplication() { - // GIVEN - final String service1 = "unique service"; - final String service2 = "duplicated service"; - StackId stack1 = new StackId("a_stack", "1.0"); - StackId stack2 = new StackId("another_stack", "0.9"); - Stream<String> stream = ImmutableSet.of(service1, service2).stream(); - - // WHEN - BlueprintFactory.verifyStackDefinitionsAreDisjoint(stream, "Services", service -> { - switch (service) { - case service1: return ImmutableSet.of(stack1); - case service2: return ImmutableSet.of(stack1, stack2); - default: return null; - } - }); - } - - @Test - public void verifyStackDefinitionsAreDisjointShouldAllowDisjointStacks() { - // GIVEN - final String service1 = "unique service"; - final String service2 = "another service"; - StackId stack1 = new StackId("a_stack", "1.0"); - StackId stack2 = new StackId("another_stack", "0.9"); - Stream<String> stream = ImmutableSet.of(service1, service2).stream(); - - // WHEN - BlueprintFactory.verifyStackDefinitionsAreDisjoint(stream, "Services", service -> { - switch (service) { - case service1: return ImmutableSet.of(stack1); - case service2: return ImmutableSet.of(stack2); - default: return null; - } - }); - - // THEN - // no exception expected - } - } diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/DownloadMpacksTaskTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/DownloadMpacksTaskTest.java index 8a27be5..bce2a1e 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/topology/DownloadMpacksTaskTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/DownloadMpacksTaskTest.java @@ -124,11 +124,7 @@ public class DownloadMpacksTaskTest { } private static MpackInstance mpack(String stackName, String stackVersion) { - MpackInstance mpack = new MpackInstance(); - mpack.setMpackName(stackName); - mpack.setMpackVersion(stackVersion); - mpack.setUrl(createUri(stackName, stackVersion)); - return mpack; + return new MpackInstance(stackName, stackName, stackVersion, createUri(stackName, stackVersion), Configuration.createEmpty()); } private static String createUri(String stackName, String stackVersion) { diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/StackComponentResolverTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/StackComponentResolverTest.java index 6235aae..98179a6 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/topology/StackComponentResolverTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/StackComponentResolverTest.java @@ -17,71 +17,280 @@ */ package org.apache.ambari.server.topology; -import static org.easymock.EasyMock.createNiceMock; +import static java.util.Comparator.comparing; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; +import static org.easymock.EasyMock.anyString; import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.reset; +import static org.junit.Assert.assertEquals; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Stream; import org.apache.ambari.server.controller.internal.StackDefinition; -import org.apache.ambari.server.topology.validators.RejectUnknownComponents; -import org.apache.ambari.server.topology.validators.TopologyValidator; -import org.junit.After; +import org.apache.ambari.server.state.ServiceInfo; +import org.apache.ambari.server.state.StackId; +import org.apache.commons.lang3.tuple.Pair; +import org.easymock.EasyMockRule; +import org.easymock.EasyMockSupport; +import org.easymock.Mock; +import org.easymock.MockType; +import org.easymock.TestSubject; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Sets; -public class StackComponentResolverTest { +public class StackComponentResolverTest extends EasyMockSupport { - private final TopologyValidator validator = new RejectUnknownComponents(); - private final ClusterTopology topology = createNiceMock(ClusterTopology.class); - private final StackDefinition stack = createNiceMock(StackDefinition.class); + private static final StackId STACK_ID1 = new StackId("HDPCORE", "1.0.0-b123"); + private static final StackId STACK_ID2 = new StackId("ODS", "1.0.0-b1111"); + private static final MpackInstance MPACK_INSTANCE1 = new MpackInstance(STACK_ID1); + private static final MpackInstance MPACK_INSTANCE2 = new MpackInstance(STACK_ID2); + + private static final Comparator<ResolvedComponent> RESOLVED_COMPONENT_COMPARATOR = comparing((ResolvedComponent comp) -> comp.stackId().toString()) + .thenComparing(ResolvedComponent::effectiveServiceGroupName) + .thenComparing(ResolvedComponent::effectiveServiceName) + .thenComparing(ResolvedComponent::componentName); + + private static final Set<String> CLIENT_COMPONENTS = Sets.union(hdpCoreComponents(), odsComponents()).stream() + .map(ResolvedComponent::componentName) + .filter(each -> each.contains("_CLIENT")) + .collect(toSet()); + + @Rule + public EasyMockRule rule = new EasyMockRule(this); + + @TestSubject + private final ComponentResolver subject = new StackComponentResolver(); + + @Mock(type = MockType.NICE) + private BlueprintBasedClusterProvisionRequest request; + + @Mock(type = MockType.NICE) + private StackDefinition stack; @Before - public void setUp() { - expect(topology.getStack()).andReturn(stack).anyTimes(); + public void setup() { + expect(request.getStack()).andReturn(stack).anyTimes(); } - @After - public void tearDown() { - reset(topology, stack); + @Test(expected = IllegalArgumentException.class) // THEN + public void ambiguousComponentName() { + // GIVEN + Set<ResolvedComponent> components = build(Sets.union(hdpCoreComponents(), odsComponents())); + aStackWith(components); + defineMpacksAs(MPACK_INSTANCE1, MPACK_INSTANCE2); + aHostGroupWith(components); + replayAll(); + + // WHEN + Map<String, Set<ResolvedComponent>> resolved = subject.resolveComponents(request); + } + + @Test(expected = IllegalArgumentException.class) // THEN + public void unknownComponent() { + // GIVEN + Set<ResolvedComponent> components = build(Sets.union(hdpCoreComponents(), odsComponents())); + aStackWith(components); + defineMpacksAs(MPACK_INSTANCE1, MPACK_INSTANCE2); + aHostGroupWith(new Component("UNKNOWN_COMPONENT")); + replayAll(); + + // WHEN + Map<String, Set<ResolvedComponent>> resolved = subject.resolveComponents(request); } @Test - public void acceptsKnownComponents() throws Exception { + public void withExplicitNamesOnlyForClients() { // GIVEN - componentsInTopologyAre("VALID_COMPONENT", "ANOTHER_COMPONENT"); - validComponentsAre("VALID_COMPONENT", "ANOTHER_COMPONENT", "ONE_MORE_COMPONENT"); + Set<ResolvedComponent.Builder> builders = Sets.union(hdpCoreComponents(), odsComponents()); + builders.stream().filter(each -> CLIENT_COMPONENTS.contains(each.componentName())).forEach(each -> each.serviceGroupName(each.stackId().getStackName())); + Set<ResolvedComponent> components = build(builders); + aStackWith(components); + defineMpacksAs(MPACK_INSTANCE1, MPACK_INSTANCE2); + aHostGroupWith(components); + replayAll(); // WHEN - validator.validate(topology); + Map<String, Set<ResolvedComponent>> resolved = subject.resolveComponents(request); // THEN - // no exception expected + assertHostGroupEquals(ImmutableMap.of("node", components), resolved); } - @Test(expected = InvalidTopologyException.class) - public void rejectsUnknownComponents() throws Exception { + @Test + public void withExplicitDefaultNames() { // GIVEN - componentsInTopologyAre("VALID_COMPONENT", "UNKNOWN_COMPONENT"); - validComponentsAre("VALID_COMPONENT", "ANOTHER_COMPONENT"); + String mpackInstanceName1 = STACK_ID1.getStackName(), mpackInstanceName2 = STACK_ID2.getStackName(); + Set<ResolvedComponent> components = build(Sets.union( + inServiceGroup(mpackInstanceName1, hdpCoreComponents()), + inServiceGroup(mpackInstanceName2, odsComponents()) + )); + + aStackWith(components); + + defineMpacksAs( + withCustomName(MPACK_INSTANCE1, mpackInstanceName1), + withCustomName(MPACK_INSTANCE2, mpackInstanceName2) + ); + + aHostGroupWith(components); + replayAll(); + + // WHEN + Map<String, Set<ResolvedComponent>> resolved = subject.resolveComponents(request); + + // THEN + assertHostGroupEquals(ImmutableMap.of("node", components), resolved); + } + + @Test + public void withCustomNames() { + // GIVEN + String mpackInstanceName1 = "hdp-core", mpackInstanceName2 = "ods!"; + Set<ResolvedComponent> components = build(Sets.union( + inServiceGroup(mpackInstanceName1, hdpCoreComponents()), + inServiceGroup(mpackInstanceName2, odsComponents()) + )); + + aStackWith(components); + + defineMpacksAs( + withCustomName(MPACK_INSTANCE1, mpackInstanceName1), + withCustomName(MPACK_INSTANCE2, mpackInstanceName2) + ); + + aHostGroupWith(components); + replayAll(); // WHEN - validator.validate(topology); + Map<String, Set<ResolvedComponent>> resolved = subject.resolveComponents(request); + + // THEN + assertHostGroupEquals(ImmutableMap.of("node", components), resolved); + } + + private void defineMpacksAs(MpackInstance... mpacks) { + expect(request.getMpacks()).andReturn(ImmutableSet.copyOf(mpacks)).anyTimes(); + } + + private void aStackWith(Set<ResolvedComponent> components) { + Map<Pair<String, String>, List<ResolvedComponent>> byServiceName = components.stream() + .collect(groupingBy(each -> Pair.of(each.effectiveServiceGroupName(), each.effectiveServiceName()))); + + Map<ResolvedComponent, ServiceInfo> services = new HashMap<>(); + for (Map.Entry<Pair<String, String>, List<ResolvedComponent>> entry : byServiceName.entrySet()) { + ServiceInfo service = createNiceMock(ServiceInfo.class); + expect(service.getName()).andReturn(entry.getValue().iterator().next().serviceType()).anyTimes(); + for (ResolvedComponent component : entry.getValue()) { + services.put(component, service); + } + } + + Map<String, List<Pair<ResolvedComponent, ServiceInfo>>> byComponentName = components.stream() + .map(each -> Pair.of(each, services.get(each))) + .collect(groupingBy(each -> each.getLeft().componentName())); + + for (Map.Entry<String, List<Pair<ResolvedComponent, ServiceInfo>>> entry : byComponentName.entrySet()) { + expect(stack.getServicesForComponent(entry.getKey())) + .andAnswer(() -> entry.getValue().stream().map(each -> Pair.of(each.getLeft().stackId(), each.getRight()))).anyTimes(); + } + expect(stack.getServicesForComponent(anyString())).andAnswer(Stream::empty).anyTimes(); + } + + private void mpacksWith(String serviceName, String componentName, MpackInstance... mpacks) { + defineMpacksAs(mpacks); + + Collection<Pair<StackId, ServiceInfo>> services = Arrays.stream(mpacks) + .map(mpack -> { + ServiceInfo service = createNiceMock(ServiceInfo.class); + expect(service.getName()).andReturn(serviceName).anyTimes(); + return Pair.of(mpack.getStackId(), service); + }) + .collect(toList()); + expect(stack.getServicesForComponent(componentName)).andAnswer(services::stream).anyTimes(); + } + + private void aHostGroupWith(Component component) { + hostGroupWith(ImmutableSet.of(component)); + } + + private void aHostGroupWith(Collection<ResolvedComponent> components) { + hostGroupWith(components.stream() + .map(each -> new Component(each.componentName(), each.serviceGroupName().orElse(null), each.effectiveServiceName(), null)) + .collect(toSet())); + } + + private void hostGroupWith(Set<Component> components) { + HostGroup hostGroup = new HostGroupImpl("node", components, Configuration.createEmpty(), "1+"); + Map<String, HostGroup> hostGroups = ImmutableMap.of(hostGroup.getName(), hostGroup); + expect(request.getHostGroups()).andReturn(hostGroups).anyTimes(); + } + + private static Set<ResolvedComponent> build(ResolvedComponent.Builder builder) { + return build(ImmutableSet.of(builder)); + } + + private static Set<ResolvedComponent> build(Set<ResolvedComponent.Builder> builders) { + builders.forEach(each -> + each.component(new Component(each.componentName(), each.effectiveServiceGroupName(), each.effectiveServiceName(), null))); + + return builders.stream() + .map(ResolvedComponent.Builder::build) + .collect(toSet()); + } + + private static MpackInstance withCustomName(MpackInstance mpack, String name) { + return new MpackInstance(name, mpack.getMpackType(), mpack.getMpackVersion(), mpack.getUrl(), mpack.getConfiguration()); + } + + private static Set<ResolvedComponent.Builder> inServiceGroup(String name, Collection<ResolvedComponent.Builder> components) { + return components.stream().map(each -> each.serviceGroupName(name)).collect(toSet()); + } + + private static void assertHostGroupEquals(Map<String, Set<ResolvedComponent>> expected, Map<String, Set<ResolvedComponent>> actual) { + assertEquals(expected.keySet(), actual.keySet()); + for (String hostGroupName : expected.keySet()) { + Set<ResolvedComponent> expectedComponents = ImmutableSortedSet.copyOf(RESOLVED_COMPONENT_COMPARATOR, expected.get(hostGroupName)); + Set<ResolvedComponent> actualComponents = ImmutableSortedSet.copyOf(RESOLVED_COMPONENT_COMPARATOR, actual.get(hostGroupName)); + assertEquals(expectedComponents, actualComponents); + } } - private void componentsInTopologyAre(String... components) { - expect(topology.getComponents()).andReturn(Stream.of(components) - .map(name -> ResolvedComponent.builder(new Component(name)).buildPartial()) - ).anyTimes(); - replay(topology); + private static Set<ResolvedComponent.Builder> hdpCoreComponents() { + Set<ResolvedComponent.Builder> builders = ImmutableSet.of( + ResolvedComponent.builder("HADOOP_CLIENT").serviceType("HADOOP_CLIENTS"), + ResolvedComponent.builder("DATANODE").serviceType("HDFS"), + ResolvedComponent.builder("NAMENODE").serviceType("HDFS"), + ResolvedComponent.builder("ZOOKEEPER_CLIENT").serviceType("ZOOKEEPER_CLIENTS"), + ResolvedComponent.builder("ZOOKEEPER_SERVER").serviceType("ZOOKEEPER") + ); + builders.forEach(each -> each.stackId(STACK_ID1)); + return builders; } - private void validComponentsAre(String... components) { - expect(stack.getComponents()).andReturn(ImmutableSet.<String>builder().add(components).build()).anyTimes(); - replay(stack); + private static Set<ResolvedComponent.Builder> odsComponents() { + Set<ResolvedComponent.Builder> builders = ImmutableSet.of( + ResolvedComponent.builder("HADOOP_CLIENT").serviceType("HADOOP_CLIENTS"), + ResolvedComponent.builder("HBASE_MASTER").serviceType("HBASE"), + ResolvedComponent.builder("HBASE_REGIONSERVER").serviceType("HBASE"), + ResolvedComponent.builder("HBASE_CLIENT").serviceType("HBASE_CLIENTS"), + ResolvedComponent.builder("ZOOKEEPER_CLIENT").serviceType("ZOOKEEPER_CLIENTS") + ); + builders.forEach(each -> each.stackId(STACK_ID2)); + return builders; } } diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java index 39799de..5f7c854 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java @@ -220,8 +220,8 @@ public class TopologyManagerTest { private final Collection<Component> group2Components = Arrays.asList(new Component("component3"), new Component("component4")); private final Collection<String> group2ComponentNames = group2Components.stream().map(Component::getName).collect(toSet()); - private final MpackInstance mpack1 = new MpackInstance("HDPCORE", "1.0.0.0", "http://mpacks.org/hdpcore", null, new Configuration()); - private final MpackInstance mpack2 = new MpackInstance("HDF", "3.3.0", "http://mpacks.org/hdf", null, new Configuration()); + private final MpackInstance mpack1 = new MpackInstance("HDPCORE", "HDPCORE", "1.0.0.0", "http://mpacks.org/hdpcore", new Configuration()); + private final MpackInstance mpack2 = new MpackInstance("HDF", "HDF", "3.3.0", "http://mpacks.org/hdf", new Configuration()); private Map<String, Collection<String>> group1ServiceComponents = new HashMap<>(); private Map<String, Collection<String>> group2ServiceComponents = new HashMap<>(); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/StackComponentResolverTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/RejectUnknownComponentsTest.java similarity index 89% copy from ambari-server/src/test/java/org/apache/ambari/server/topology/StackComponentResolverTest.java copy to ambari-server/src/test/java/org/apache/ambari/server/topology/validators/RejectUnknownComponentsTest.java index 6235aae..d71051b 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/topology/StackComponentResolverTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/RejectUnknownComponentsTest.java @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.ambari.server.topology; +package org.apache.ambari.server.topology.validators; import static org.easymock.EasyMock.createNiceMock; import static org.easymock.EasyMock.expect; @@ -25,15 +25,17 @@ import static org.easymock.EasyMock.reset; import java.util.stream.Stream; import org.apache.ambari.server.controller.internal.StackDefinition; -import org.apache.ambari.server.topology.validators.RejectUnknownComponents; -import org.apache.ambari.server.topology.validators.TopologyValidator; +import org.apache.ambari.server.topology.ClusterTopology; +import org.apache.ambari.server.topology.Component; +import org.apache.ambari.server.topology.InvalidTopologyException; +import org.apache.ambari.server.topology.ResolvedComponent; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.google.common.collect.ImmutableSet; -public class StackComponentResolverTest { +public class RejectUnknownComponentsTest { private final TopologyValidator validator = new RejectUnknownComponents(); private final ClusterTopology topology = createNiceMock(ClusterTopology.class); -- To stop receiving notification emails like this one, please contact [email protected].
