This is an automated email from the ASF dual-hosted git repository. benyoka pushed a commit to branch branch-feature-AMBARI-14714 in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/branch-feature-AMBARI-14714 by this push: new f4cdbe8 [AMBARI-23130] Persist cluster creation request (#559) f4cdbe8 is described below commit f4cdbe83ac21d6433db94d292ba4c4035087ec7d Author: benyoka <beny...@users.noreply.github.com> AuthorDate: Wed Mar 7 10:19:58 2018 +0100 [AMBARI-23130] Persist cluster creation request (#559) * AMBARI-23130 persist raw cluster provision request and extract stack ids on server restart (benyoka) * AMBARI-23130 add columnt to other DDLs + fix DDLs (benyoka) * AMBARI-23130 fix review findings (benyoka) --- .../controller/internal/BaseClusterRequest.java | 21 ++++ .../internal/ClusterResourceProvider.java | 3 +- .../controller/internal/HostResourceProvider.java | 4 +- .../internal/ProvisionClusterRequest.java | 4 +- .../controller/internal/ScaleClusterRequest.java | 3 +- .../server/orm/entities/TopologyRequestEntity.java | 18 +++ .../BlueprintBasedClusterProvisionRequest.java | 16 ++- .../server/topology/ClusterTopologyImpl.java | 10 +- .../ambari/server/topology/PersistedStateImpl.java | 19 +++- .../ambari/server/topology/TopologyRequest.java | 12 ++ .../server/topology/TopologyRequestFactory.java | 2 +- .../topology/TopologyRequestFactoryImpl.java | 5 +- .../server/topology/TopologyRequestUtil.java | 76 +++++++++++++ .../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 | 7 +- .../main/resources/Ambari-DDL-Postgres-CREATE.sql | 1 + .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 1 + .../main/resources/Ambari-DDL-SQLServer-CREATE.sql | 1 + .../internal/ClusterResourceProviderTest.java | 11 +- .../internal/ProvisionClusterRequestTest.java | 34 +++--- .../internal/ScaleClusterRequestTest.java | 20 ++-- .../server/topology/PersistedStateImplTest.java | 123 +++++++++++++++++++++ .../server/topology/TopologyManagerTest.java | 2 +- .../server/topology/TopologyRequestUtilTest.java | 60 ++++++++++ 25 files changed, 394 insertions(+), 61 deletions(-) diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseClusterRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseClusterRequest.java index 77eafeb..0d243a2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseClusterRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseClusterRequest.java @@ -29,6 +29,7 @@ import org.apache.ambari.server.api.predicate.Token; import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.ResourceProvider; import org.apache.ambari.server.controller.utilities.ClusterControllerHelper; +import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.topology.Blueprint; import org.apache.ambari.server.topology.BlueprintFactory; import org.apache.ambari.server.topology.Configuration; @@ -36,6 +37,7 @@ import org.apache.ambari.server.topology.HostGroupInfo; import org.apache.ambari.server.topology.InvalidTopologyTemplateException; import org.apache.ambari.server.topology.SecurityConfiguration; import org.apache.ambari.server.topology.TopologyRequest; +import org.apache.ambari.server.topology.TopologyRequestUtil; /** * Provides common cluster request functionality. @@ -54,6 +56,11 @@ public abstract class BaseClusterRequest implements TopologyRequest { protected ProvisionAction provisionAction; /** + * The raw request body. We would like to persist it. + */ + protected String rawRequestBody; + + /** * cluster id */ protected Long clusterId; @@ -119,6 +126,19 @@ public abstract class BaseClusterRequest implements TopologyRequest { } /** + * @return the raw request body in JSON string + */ + public String getRawRequestBody() { + return rawRequestBody; + } + + @Override + public Set<StackId> getStackIds() { + return TopologyRequestUtil.getStackIdsFromRequest( + TopologyRequestUtil.getPropertyMap(rawRequestBody)); + } + + /** * Validate that all properties specified in the predicate are valid for the Host resource. * * @param predicate predicate to validate @@ -180,6 +200,7 @@ public abstract class BaseClusterRequest implements TopologyRequest { return securityConfiguration; } + /** * Get the host resource provider instance. * diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java index f03231b..baf64e0 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java @@ -533,7 +533,8 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider ProvisionClusterRequest createClusterRequest; try { - createClusterRequest = topologyRequestFactory.createProvisionClusterRequest(properties, securityConfiguration); + createClusterRequest = + topologyRequestFactory.createProvisionClusterRequest(rawRequestBody, properties, securityConfiguration); } catch (InvalidTopologyTemplateException e) { throw new IllegalArgumentException("Invalid Cluster Creation Template: " + e, e); } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java index 20146e8..18122e9 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java @@ -1087,7 +1087,9 @@ public class HostResourceProvider extends AbstractControllerResourceProvider { private RequestStatusResponse submitHostRequests(Request request) throws SystemException { ScaleClusterRequest requestRequest; try { - requestRequest = new ScaleClusterRequest(request.getProperties()); + requestRequest = new ScaleClusterRequest( + request.getRequestInfoProperties().get(Request.REQUEST_INFO_BODY_PROPERTY), + request.getProperties()); } catch (InvalidTopologyTemplateException e) { throw new IllegalArgumentException("Invalid Add Hosts Template: " + e, e); } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java index 70b8ab5..7a5086d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java @@ -174,8 +174,10 @@ public class ProvisionClusterRequest extends BaseClusterRequest implements Provi * @param properties request properties * @param securityConfiguration security config related properties */ - public ProvisionClusterRequest(Map<String, Object> properties, SecurityConfiguration securityConfiguration) throws + public ProvisionClusterRequest(String rawRequestBody, Map<String, Object> properties, SecurityConfiguration securityConfiguration) throws InvalidTopologyTemplateException { + this.rawRequestBody = rawRequestBody; + setClusterName(String.valueOf(properties.get( ClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID))); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java index 5e5eec8..958a3d5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java @@ -51,7 +51,8 @@ public class ScaleClusterRequest extends BaseClusterRequest { * * @throws InvalidTopologyTemplateException if any validation of properties fails */ - public ScaleClusterRequest(Set<Map<String, Object>> propertySet) throws InvalidTopologyTemplateException { + public ScaleClusterRequest(String rawRequestBody, Set<Map<String, Object>> propertySet) throws InvalidTopologyTemplateException { + this.rawRequestBody = rawRequestBody; for (Map<String, Object> properties : propertySet) { // can only operate on a single cluster per logical request if (getClusterName() == null) { diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyRequestEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyRequestEntity.java index d281838..d9ab181 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyRequestEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyRequestEntity.java @@ -75,6 +75,10 @@ public class TopologyRequestEntity { @Column(name = "description", length = 1024, nullable = false) private String description; + @Lob + @Column(name = "raw_request_body", length = 100000, nullable = false) + private String rawRequestBody; + @OneToMany(mappedBy = "topologyRequestEntity", cascade = CascadeType.ALL) private Collection<TopologyHostGroupEntity> topologyHostGroupEntities; @@ -141,6 +145,20 @@ public class TopologyRequestEntity { this.description = description; } + /** + * @return the raw request body in JSON + */ + public String getRawRequestBody() { + return rawRequestBody; + } + + /** + * @param rawRequestBody the raw request body in JSON + */ + public void setRawRequestBody(String rawRequestBody) { + this.rawRequestBody = rawRequestBody; + } + public Collection<TopologyHostGroupEntity> getTopologyHostGroupEntities() { return topologyHostGroupEntities; } 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 43f3724..22d4bab 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 @@ -24,7 +24,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.function.Function; -import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -37,7 +36,6 @@ import org.apache.ambari.server.state.StackId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; @@ -52,7 +50,7 @@ public class BlueprintBasedClusterProvisionRequest implements Blueprint, Provisi private final ProvisionClusterRequest request; private final Set<StackId> stackIds; private final StackDefinition stack; - private final Map<String, MpackInstance> mpacks; + private final Set<MpackInstance> mpacks; private final SecurityConfiguration securityConfiguration; public BlueprintBasedClusterProvisionRequest(AmbariContext ambariContext, SecurityConfigurationFactory securityConfigurationFactory, Blueprint blueprint, ProvisionClusterRequest request) { @@ -61,9 +59,9 @@ public class BlueprintBasedClusterProvisionRequest implements Blueprint, Provisi stackIds = ImmutableSet.copyOf(Sets.union(blueprint.getStackIds(), request.getStackIds())); stack = ambariContext.composeStacks(stackIds); - mpacks = ImmutableMap.copyOf( - Stream.concat(blueprint.getMpacks().stream(), request.getMpacks().stream()) - .collect(toMap(MpackInstance::getMpackName, Function.identity()))); + mpacks = ImmutableSet.<MpackInstance>builder(). + addAll(blueprint.getMpacks()). + addAll(request.getMpacks()).build(); securityConfiguration = processSecurityConfiguration(securityConfigurationFactory); @@ -104,7 +102,7 @@ public class BlueprintBasedClusterProvisionRequest implements Blueprint, Provisi @Override public Collection<MpackInstance> getMpacks() { - return mpacks.values(); + return mpacks; } @Override @@ -166,7 +164,7 @@ public class BlueprintBasedClusterProvisionRequest implements Blueprint, Provisi public Map<String, Map<String, ServiceInstance>> getServicesByMpack() { Map<String, Map<String, ServiceInstance>> result = new HashMap<>(); - for (MpackInstance mpack : mpacks.values()) { + for (MpackInstance mpack : mpacks) { Map<String, ServiceInstance> services = mpack.getServiceInstances().stream() .collect(toMap(ServiceInstance::getName, Function.identity())); result.put(mpack.getMpackName(), services); @@ -179,7 +177,7 @@ public class BlueprintBasedClusterProvisionRequest implements Blueprint, Provisi * whose name is unique across all mpacks. */ public Map<String, ServiceInstance> getUniqueServices() { - Map<String, ServiceInstance> map = mpacks.values().stream() + Map<String, ServiceInstance> map = mpacks.stream() .flatMap(mpack -> mpack.getServiceInstances().stream()) .collect(toMap(ServiceInstance::getName, Function.identity(), (s1, s2) -> null)); map.entrySet().removeIf(e -> e.getValue() == null); // remove non-unique names mapped to null diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java index 9581457..1ea1101 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java @@ -46,6 +46,7 @@ import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; /** * Represents a cluster topology. @@ -68,18 +69,21 @@ public class ClusterTopologyImpl implements ClusterTopology { private final BlueprintBasedClusterProvisionRequest provisionRequest; private final String defaultPassword; private final Map<String, Set<ResolvedComponent>> resolvedComponents; + private final Setting setting; public ClusterTopologyImpl(AmbariContext ambariContext, TopologyRequest topologyRequest) throws InvalidTopologyException { this.ambariContext = ambariContext; this.clusterId = topologyRequest.getClusterId(); this.blueprint = topologyRequest.getBlueprint(); + this.setting = blueprint.getSetting(); this.configuration = topologyRequest.getConfiguration(); configRecommendationStrategy = ConfigRecommendationStrategy.NEVER_APPLY; provisionAction = topologyRequest instanceof BaseClusterRequest ? ((BaseClusterRequest) topologyRequest).getProvisionAction() : INSTALL_AND_START; // FIXME provisionRequest = null; defaultPassword = null; - stackIds = topologyRequest.getBlueprint().getStackIds(); + stackIds = ImmutableSet.copyOf( + Sets.union(topologyRequest.getStackIds(), topologyRequest.getBlueprint().getStackIds())); stack = ambariContext.composeStacks(stackIds); resolvedComponents = ImmutableMap.of(); @@ -104,7 +108,7 @@ public class ClusterTopologyImpl implements ClusterTopology { defaultPassword = provisionRequest.getDefaultPassword(); stackIds = request.getStackIds(); stack = request.getStack(); - + setting = request.getSetting(); blueprint.getConfiguration().setParentConfiguration(stack.getConfiguration(getServices())); registerHostGroupInfo(request.getHostGroupInfo()); } @@ -150,7 +154,7 @@ public class ClusterTopologyImpl implements ClusterTopology { @Override public Setting getSetting() { - return provisionRequest.getSetting(); + return setting; } @Override diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/PersistedStateImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/PersistedStateImpl.java index 13c9eff..ae70db4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/PersistedStateImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/PersistedStateImpl.java @@ -23,7 +23,9 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import javax.inject.Inject; import javax.inject.Singleton; import org.apache.ambari.server.AmbariException; @@ -50,12 +52,12 @@ import org.apache.ambari.server.orm.entities.TopologyLogicalTaskEntity; import org.apache.ambari.server.orm.entities.TopologyRequestEntity; import org.apache.ambari.server.stack.NoSuchStackException; import org.apache.ambari.server.state.Host; +import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.topology.tasks.TopologyTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.Gson; -import com.google.inject.Inject; import com.google.inject.persist.Transactional; /** @@ -92,9 +94,6 @@ public class PersistedStateImpl implements PersistedState { private HostRoleCommandDAO hostRoleCommandDAO; @Inject - private HostRoleCommandDAO physicalTaskDAO; - - @Inject private BlueprintFactory blueprintFactory; @Inject @@ -255,6 +254,8 @@ public class PersistedStateImpl implements PersistedState { private TopologyRequestEntity toEntity(BaseClusterRequest request) { TopologyRequestEntity entity = new TopologyRequestEntity(); + entity.setRawRequestBody(request.getRawRequestBody()); + //todo: this isn't set for a scaling operation because we had intended to allow multiple //todo: bp's to be used to scale a cluster although this isn't currently supported by //todo: new topology infrastructure @@ -330,7 +331,7 @@ public class PersistedStateImpl implements PersistedState { logicalTaskEntity.setTopologyHostTaskEntity(topologyTaskEntity); Long physicalId = request.getPhysicalTaskId(logicalTaskId); if (physicalId != null) { - logicalTaskEntity.setHostRoleCommandEntity(physicalTaskDAO.findByPK(physicalId)); + logicalTaskEntity.setHostRoleCommandEntity(hostRoleCommandDAO.findByPK(physicalId)); } logicalTaskEntity.setTopologyHostTaskEntity(topologyTaskEntity); } @@ -391,6 +392,7 @@ public class PersistedStateImpl implements PersistedState { private final Configuration configuration; private final Map<String, HostGroupInfo> hostGroupInfoMap = new HashMap<>(); private final ProvisionAction provisionAction; + private final Set<StackId> stackIds; public ReplayedTopologyRequest(TopologyRequestEntity entity, BlueprintFactory blueprintFactory) { clusterId = entity.getClusterId(); @@ -398,6 +400,8 @@ public class PersistedStateImpl implements PersistedState { description = entity.getDescription(); provisionAction = entity.getProvisionAction(); + stackIds = TopologyRequestUtil.getStackIdsFromRequest(entity.getRawRequestBody()); + try { blueprint = blueprintFactory.getBlueprint(entity.getBlueprintName()); } catch (NoSuchStackException e) { @@ -410,6 +414,11 @@ public class PersistedStateImpl implements PersistedState { } @Override + public Set<StackId> getStackIds() { + return stackIds; + } + + @Override public Long getClusterId() { return clusterId; } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequest.java index 94fcf23..ffdf1c7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequest.java @@ -18,7 +18,12 @@ package org.apache.ambari.server.topology; +import static java.util.Collections.emptySet; + import java.util.Map; +import java.util.Set; + +import org.apache.ambari.server.state.StackId; /** * A request which is used to create or modify a cluster topology. @@ -70,4 +75,11 @@ public interface TopologyRequest { * @return string description of the request */ String getDescription(); + + /** + * @return a set of stack id's if supported by the TopologyRequest. + */ + default Set<StackId> getStackIds() { + return emptySet(); + } } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestFactory.java index 751e2d7..136be39 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestFactory.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestFactory.java @@ -28,6 +28,6 @@ import org.apache.ambari.server.controller.internal.ProvisionClusterRequest; */ public interface TopologyRequestFactory { - ProvisionClusterRequest createProvisionClusterRequest(Map<String, Object> properties, SecurityConfiguration securityConfiguration) throws InvalidTopologyTemplateException; + ProvisionClusterRequest createProvisionClusterRequest(String rawRequestBody, Map<String, Object> properties, SecurityConfiguration securityConfiguration) throws InvalidTopologyTemplateException; // todo: use to create other request types } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestFactoryImpl.java index 44f0d1f..50d3fa1 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestFactoryImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestFactoryImpl.java @@ -29,8 +29,7 @@ import org.apache.ambari.server.controller.internal.ProvisionClusterRequest; public class TopologyRequestFactoryImpl implements TopologyRequestFactory { @Override - public ProvisionClusterRequest createProvisionClusterRequest(Map<String, Object> properties, SecurityConfiguration securityConfiguration) throws InvalidTopologyTemplateException { - return new ProvisionClusterRequest(properties, securityConfiguration); - + public ProvisionClusterRequest createProvisionClusterRequest(String rawRequestBody, Map<String, Object> properties, SecurityConfiguration securityConfiguration) throws InvalidTopologyTemplateException { + return new ProvisionClusterRequest(rawRequestBody, properties, securityConfiguration); } } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestUtil.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestUtil.java new file mode 100644 index 0000000..1b160a4 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyRequestUtil.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ambari.server.topology; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.stream.Collectors.toSet; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.ambari.server.state.StackId; +import org.apache.ambari.server.utils.JsonUtils; + +import com.fasterxml.jackson.core.type.TypeReference; + +/** + * Utility functions for topology requests. + */ +public class TopologyRequestUtil { + + public static final String NAME = "name"; + public static final String VERSION = "version"; + + + /** + * @param rawRequestJson The topology request in raw JSON format. Null input is handled gracefully. + * @return a Set of stack id's contained in the request + */ + public static Set<StackId> getStackIdsFromRequest(String rawRequestJson) { + return getStackIdsFromRequest(getPropertyMap(rawRequestJson)); + } + + + /** + * @param rawRequestMap The topology request in raw JSON format. Null input is handled gracefully. + * @return a Set of stack id's contained in the request + */ + public static Set<StackId> getStackIdsFromRequest(Map<String, Object> rawRequestMap) { + List<Map<String, String>> mpackInstances = (List<Map<String, String>>) + rawRequestMap.getOrDefault("mpack_instances", emptyList()); + return mpackInstances.stream().map(m -> { + checkArgument(m.containsKey(NAME), "Missing mpack name"); + checkArgument(m.containsKey(VERSION), "Missing mpack version"); + return new StackId(m.get(NAME), m.get(VERSION)); + }).collect(toSet()); + } + + /** + * @param rawRequestJson The topology request in raw JSON format. Null input is handled gracefully. + * @return the request body parsed as map (null is parsed as empty map) + */ + public static Map<String, Object> getPropertyMap(String rawRequestJson) { + return null == rawRequestJson ? + emptyMap() : + JsonUtils.fromJson(rawRequestJson, new TypeReference<Map<String, Object>>() {}); + } +} 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 e714665..e523466 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql @@ -893,6 +893,7 @@ CREATE TABLE topology_request ( action VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, bp_name VARCHAR(100) NOT NULL, + raw_request_body CLOB NOT NULL, cluster_properties VARCHAR(3000), cluster_attributes VARCHAR(3000), description VARCHAR(1024), 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 8e87d56..827d62e 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -910,6 +910,7 @@ CREATE TABLE topology_request ( action VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, bp_name VARCHAR(100) NOT NULL, + raw_request_body LONGTEXT NOT NULL, cluster_properties LONGTEXT, cluster_attributes LONGTEXT, description VARCHAR(1024), 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 9bb13aa..116122a 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -136,7 +136,8 @@ CREATE TABLE servicegroups ( stack_id NUMBER(19) NOT NULL, CONSTRAINT PK_servicegroups PRIMARY KEY (id, cluster_id), CONSTRAINT FK_servicegroups_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id), - CONSTRAINT FK_servicegroups_stack_id FOREIGN KEY (stack_id) REFERENCES stack (stack_id)); + CONSTRAINT FK_servicegroups_stack_id FOREIGN KEY (stack_id) REFERENCES stack (stack_id), + CONSTRAINT UQ_TEMP_UNTIL_REAL_PK UNIQUE(id)); CREATE TABLE servicegroupdependencies ( id NUMBER(19) NOT NULL, @@ -208,8 +209,7 @@ CREATE TABLE serviceconfig ( CONSTRAINT PK_serviceconfig PRIMARY KEY (service_config_id), CONSTRAINT FK_serviceconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id), CONSTRAINT FK_serviceconfig_clstr_svc FOREIGN KEY (service_id, service_group_id, cluster_id) REFERENCES clusterservices (id, service_group_id, cluster_id), - CONSTRAINT UQ_scv_service_version UNIQUE (cluster_id, service_id, version), - CONSTRAINT UQ_TEMP_UNTIL_REAL_PK UNIQUE(id)); + CONSTRAINT UQ_scv_service_version UNIQUE (cluster_id, service_id, version) ); CREATE TABLE serviceconfighosts ( service_config_id NUMBER(19) NOT NULL, @@ -888,6 +888,7 @@ CREATE TABLE topology_request ( action VARCHAR(255) NOT NULL, cluster_id NUMBER(19) NOT NULL, bp_name VARCHAR(100) NOT NULL, + raw_request_body CLOB NOT NULL, cluster_properties CLOB, cluster_attributes CLOB, description VARCHAR(1024), 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 b0907a3..99dcbe8 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -894,6 +894,7 @@ CREATE TABLE topology_request ( action VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, bp_name VARCHAR(100) NOT NULL, + raw_request_body TEXT NOT NULL, cluster_properties TEXT, cluster_attributes TEXT, description VARCHAR(1024), 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 ad0b71f..bc635e0 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql @@ -888,6 +888,7 @@ CREATE TABLE topology_request ( action VARCHAR(255) NOT NULL, cluster_id NUMERIC(19) NOT NULL, bp_name VARCHAR(100) NOT NULL, + raw_request_body TEXT NOT NULL, cluster_properties TEXT, cluster_attributes TEXT, description VARCHAR(1024), 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 041011c..1de62da 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql @@ -911,6 +911,7 @@ CREATE TABLE topology_request ( action VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, bp_name VARCHAR(100) NOT NULL, + raw_request_body TEXT NOT NULL, cluster_properties TEXT, cluster_attributes TEXT, description VARCHAR(1024), diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java index 5e1ba49..06d95bd 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java @@ -20,6 +20,7 @@ package org.apache.ambari.server.controller.internal; import static org.easymock.EasyMock.anyBoolean; import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.anyString; import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createNiceMock; @@ -154,7 +155,7 @@ public class ClusterResourceProviderTest { expect(securityFactory.createSecurityConfigurationFromRequest(EasyMock.anyObject(), anyBoolean())).andReturn(null) .once(); - expect(topologyFactory.createProvisionClusterRequest(properties, null)).andReturn(topologyRequest).once(); + expect(topologyFactory.createProvisionClusterRequest("{}", properties, null)).andReturn(topologyRequest).once(); expect(topologyManager.provisionCluster(topologyRequest)).andReturn(requestStatusResponse).once(); expect(requestStatusResponse.getRequestId()).andReturn(5150L).anyTimes(); @@ -184,7 +185,7 @@ public class ClusterResourceProviderTest { expect(request.getProperties()).andReturn(requestProperties).anyTimes(); expect(request.getRequestInfoProperties()).andReturn(requestInfoProperties).anyTimes(); - expect(topologyFactory.createProvisionClusterRequest(properties, securityConfiguration)).andReturn(topologyRequest).once(); + expect(topologyFactory.createProvisionClusterRequest(anyString(), eq(properties), eq(securityConfiguration))).andReturn(topologyRequest).once(); expect(securityFactory.createSecurityConfigurationFromRequest(EasyMock.anyObject(), anyBoolean())).andReturn (securityConfiguration).once(); expect(topologyManager.provisionCluster(topologyRequest)).andReturn(requestStatusResponse).once(); @@ -208,7 +209,7 @@ public class ClusterResourceProviderTest { // set expectations expect(request.getProperties()).andReturn(requestProperties).anyTimes(); // throw exception from topology request factory an assert that the correct exception is thrown from resource provider - expect(topologyFactory.createProvisionClusterRequest(properties, null)).andThrow(new InvalidTopologyException + expect(topologyFactory.createProvisionClusterRequest(null, properties, null)).andThrow(new InvalidTopologyException ("test")); replayAll(); @@ -472,7 +473,7 @@ public class ClusterResourceProviderTest { expect(securityFactory.createSecurityConfigurationFromRequest(EasyMock.anyObject(), anyBoolean())).andReturn(null) .once(); - expect(topologyFactory.createProvisionClusterRequest(properties, null)).andReturn(topologyRequest).once(); + expect(topologyFactory.createProvisionClusterRequest(anyString(), eq(properties), anyObject())).andReturn(topologyRequest).once(); expect(topologyManager.provisionCluster(topologyRequest)).andReturn(requestStatusResponse).once(); expect(requestStatusResponse.getRequestId()).andReturn(5150L).anyTimes(); @@ -803,7 +804,7 @@ public class ClusterResourceProviderTest { expect(securityFactory.createSecurityConfigurationFromRequest(EasyMock.anyObject(), anyBoolean())).andReturn(null) .once(); - expect(topologyFactory.createProvisionClusterRequest(properties, null)).andReturn(topologyRequest).once(); + expect(topologyFactory.createProvisionClusterRequest("{}", properties, null)).andReturn(topologyRequest).once(); expect(topologyManager.provisionCluster(topologyRequest)).andReturn(requestStatusResponse).once(); expect(requestStatusResponse.getRequestId()).andReturn(5150L).anyTimes(); diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequestTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequestTest.java index 5ed582f..3cc4890 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequestTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequestTest.java @@ -109,7 +109,7 @@ public class ProvisionClusterRequestTest { replay(hostResourceProvider); Map<String, Object> properties = createBlueprintRequestPropertiesNameOnly(CLUSTER_NAME, BLUEPRINT_NAME); - ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(null, properties, null); assertEquals(CLUSTER_NAME, provisionClusterRequest.getClusterName()); assertEquals(TopologyRequest.Type.PROVISION, provisionClusterRequest.getType()); @@ -160,7 +160,7 @@ public class ProvisionClusterRequestTest { replay(hostResourceProvider); Map<String, Object> properties = createBlueprintRequestPropertiesCountOnly(CLUSTER_NAME, BLUEPRINT_NAME); - ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(null, properties, null); assertEquals(CLUSTER_NAME, provisionClusterRequest.getClusterName()); assertEquals(TopologyRequest.Type.PROVISION, provisionClusterRequest.getType()); @@ -211,7 +211,7 @@ public class ProvisionClusterRequestTest { @Test public void testMultipleGroups() throws Exception { Map<String, Object> properties = createBlueprintRequestProperties(CLUSTER_NAME, BLUEPRINT_NAME); - ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(null, properties, null); assertEquals(CLUSTER_NAME, provisionClusterRequest.getClusterName()); assertEquals(TopologyRequest.Type.PROVISION, provisionClusterRequest.getType()); @@ -286,7 +286,7 @@ public class ProvisionClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); // should result in an exception - new ProvisionClusterRequest(properties, null); + new ProvisionClusterRequest(null, properties, null); } @Test @@ -301,7 +301,7 @@ public class ProvisionClusterRequestTest { credentialsSet.add(credentialHashMap); properties.put("credentials", credentialsSet); - ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(null, properties, null); assertEquals(provisionClusterRequest.getCredentialsMap().get("testAlias").getAlias(), "testAlias"); assertEquals(provisionClusterRequest.getCredentialsMap().get("testAlias").getPrincipal(), "testPrincipal"); @@ -326,7 +326,7 @@ public class ProvisionClusterRequestTest { credentialsSet.add(credentialHashMap); properties.put("credentials", credentialsSet); - ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest provisionClusterRequest = new ProvisionClusterRequest(null, properties, null); } @Test(expected= InvalidTopologyTemplateException.class) @@ -338,7 +338,7 @@ public class ProvisionClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); // should result in an exception - new ProvisionClusterRequest(properties, null); + new ProvisionClusterRequest(null, properties, null); } @Test(expected= InvalidTopologyTemplateException.class) @@ -350,7 +350,7 @@ public class ProvisionClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); // should result in an exception - new ProvisionClusterRequest(properties, null); + new ProvisionClusterRequest(null, properties, null); } @Test(expected = InvalidTopologyTemplateException.class) @@ -370,7 +370,7 @@ public class ProvisionClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); // should result in an exception - new ProvisionClusterRequest(properties, null); + new ProvisionClusterRequest(null, properties, null); } @@ -383,7 +383,7 @@ public class ProvisionClusterRequestTest { replay(hostResourceProvider); // should result in an exception due to invalid property in host predicate - new ProvisionClusterRequest(createBlueprintRequestProperties(CLUSTER_NAME, BLUEPRINT_NAME), null); + new ProvisionClusterRequest(null, createBlueprintRequestProperties(CLUSTER_NAME, BLUEPRINT_NAME), null); } @Test(expected = InvalidTopologyTemplateException.class) @@ -395,7 +395,7 @@ public class ProvisionClusterRequestTest { Map<String, Object> properties = createBlueprintRequestPropertiesNameOnly(CLUSTER_NAME, BLUEPRINT_NAME); ((Map) ((List) properties.get("host_groups")).iterator().next()).put("host_count", "5"); // should result in an exception due to both host name and host count being specified - new ProvisionClusterRequest(properties, null); + new ProvisionClusterRequest(null, properties, null); } @Test(expected = InvalidTopologyTemplateException.class) @@ -407,13 +407,13 @@ public class ProvisionClusterRequestTest { Map<String, Object> properties = createBlueprintRequestPropertiesNameOnly(CLUSTER_NAME, BLUEPRINT_NAME); ((Map) ((List) properties.get("host_groups")).iterator().next()).put("host_predicate", "Hosts/host_name=myTestHost"); // should result in an exception due to both host name and host count being specified - new ProvisionClusterRequest(properties, null); + new ProvisionClusterRequest(null, properties, null); } @Test public void testQuickLinksProfile_NoDataInRequest() throws Exception { Map<String, Object> properties = createBlueprintRequestProperties(CLUSTER_NAME, BLUEPRINT_NAME); - ProvisionClusterRequest request = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest request = new ProvisionClusterRequest(null, properties, null); assertNull("No quick links profile is expected", request.getQuickLinksProfileJson()); } @@ -424,7 +424,7 @@ public class ProvisionClusterRequestTest { properties.put(ProvisionClusterRequest.QUICKLINKS_PROFILE_FILTERS_PROPERTY, Sets.newHashSet(QuickLinksProfileBuilderTest.filter(null, null, true))); - ProvisionClusterRequest request = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest request = new ProvisionClusterRequest(null, properties, null); assertEquals("Quick links profile doesn't match expected", "{\"filters\":[{\"visible\":true}],\"services\":[]}", request.getQuickLinksProfileJson()); @@ -439,7 +439,7 @@ public class ProvisionClusterRequestTest { Set<Map<String, Object>> services = Sets.newHashSet(hdfs); properties.put(ProvisionClusterRequest.QUICKLINKS_PROFILE_SERVICES_PROPERTY, services); - ProvisionClusterRequest request = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest request = new ProvisionClusterRequest(null, properties, null); assertEquals("Quick links profile doesn't match expected", "{\"filters\":[],\"services\":[{\"name\":\"HDFS\",\"components\":[],\"filters\":[{\"visible\":true}]}]}", request.getQuickLinksProfileJson()); @@ -457,7 +457,7 @@ public class ProvisionClusterRequestTest { Set<Map<String, Object>> services = Sets.newHashSet(hdfs); properties.put(ProvisionClusterRequest.QUICKLINKS_PROFILE_SERVICES_PROPERTY, services); - ProvisionClusterRequest request = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest request = new ProvisionClusterRequest(null, properties, null); System.out.println(request.getQuickLinksProfileJson()); assertEquals("Quick links profile doesn't match expected", "{\"filters\":[{\"visible\":true}],\"services\":[{\"name\":\"HDFS\",\"components\":[],\"filters\":[{\"visible\":true}]}]}", @@ -470,7 +470,7 @@ public class ProvisionClusterRequestTest { properties.put(ProvisionClusterRequest.QUICKLINKS_PROFILE_SERVICES_PROPERTY, "Hello World!"); - ProvisionClusterRequest request = new ProvisionClusterRequest(properties, null); + ProvisionClusterRequest request = new ProvisionClusterRequest(null, properties, null); } public static Map<String, Object> createBlueprintRequestProperties(String clusterName, String blueprintName) { diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ScaleClusterRequestTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ScaleClusterRequestTest.java index b9f32a0..cc02db4 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ScaleClusterRequestTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ScaleClusterRequestTest.java @@ -112,7 +112,7 @@ public class ScaleClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); - ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(Collections.singleton(props)); + ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest("{}", Collections.singleton(props)); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); assertEquals(String.format("Scale Cluster '%s' (+%s hosts)", CLUSTER_NAME, "1"), @@ -150,7 +150,7 @@ public class ScaleClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); - ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(propertySet); + ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest("{}", propertySet); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); assertEquals(String.format("Scale Cluster '%s' (+%s hosts)", CLUSTER_NAME, "2"), @@ -177,7 +177,7 @@ public class ScaleClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); - ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(Collections.singleton( + ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest("{}", Collections.singleton( createScaleClusterPropertiesGroup1_HostCount(CLUSTER_NAME, BLUEPRINT_NAME))); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); @@ -203,7 +203,7 @@ public class ScaleClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); - ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(Collections.singleton( + ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest("{}", Collections.singleton( createScaleClusterPropertiesGroup1_HostCount2(CLUSTER_NAME, BLUEPRINT_NAME))); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); @@ -225,7 +225,7 @@ public class ScaleClusterRequestTest { @Test public void test_basic_hostCountAndPredicate() throws Exception { - ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(Collections.singleton( + ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest("{}", Collections.singleton( createScaleClusterPropertiesGroup1_HostCountAndPredicate(CLUSTER_NAME, BLUEPRINT_NAME))); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); @@ -252,7 +252,7 @@ public class ScaleClusterRequestTest { propertySet.add(createScaleClusterPropertiesGroup1_HostCount(CLUSTER_NAME, BLUEPRINT_NAME)); propertySet.add(createScaleClusterPropertiesGroup1_HostName(CLUSTER_NAME, BLUEPRINT_NAME)); - ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest(propertySet); + ScaleClusterRequest scaleClusterRequest = new ScaleClusterRequest("{}", propertySet); assertEquals(TopologyRequest.Type.SCALE, scaleClusterRequest.getType()); assertEquals(String.format("Scale Cluster '%s' (+%s hosts)", CLUSTER_NAME, "3"), @@ -300,7 +300,7 @@ public class ScaleClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); // should result in an exception - new ScaleClusterRequest(Collections.singleton(properties)); + new ScaleClusterRequest("{}", Collections.singleton(properties)); } @Test(expected = InvalidTopologyTemplateException.class) @@ -313,7 +313,7 @@ public class ScaleClusterRequestTest { reset(hostResourceProvider); replay(hostResourceProvider); // should result in an exception because neither host name or host count are specified - new ScaleClusterRequest(Collections.singleton(properties)); + new ScaleClusterRequest("{}", Collections.singleton(properties)); } @@ -326,7 +326,7 @@ public class ScaleClusterRequestTest { replay(hostResourceProvider); // should result in an exception due to invalid property in host predicate - new ScaleClusterRequest(Collections.singleton( + new ScaleClusterRequest("{}", Collections.singleton( createScaleClusterPropertiesGroup1_HostCountAndPredicate(CLUSTER_NAME, BLUEPRINT_NAME))); } @@ -340,7 +340,7 @@ public class ScaleClusterRequestTest { propertySet.add(createScaleClusterPropertiesGroup1_HostName2(CLUSTER_NAME, "OTHER_BLUEPRINT")); // should result in an exception due to different blueprints being specified - new ScaleClusterRequest(propertySet); + new ScaleClusterRequest("{}", propertySet); } public static Map<String, Object> createScaleClusterPropertiesGroup1_HostName(String clusterName, String blueprintName) { diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/PersistedStateImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/PersistedStateImplTest.java new file mode 100644 index 0000000..7f6ee4b --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/PersistedStateImplTest.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ambari.server.topology; + + +import static org.easymock.EasyMock.capture; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.newCapture; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reset; +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.Field; + +import org.apache.ambari.server.controller.internal.BaseClusterRequest; +import org.apache.ambari.server.controller.internal.ProvisionAction; +import org.apache.ambari.server.controller.internal.ProvisionClusterRequest; +import org.apache.ambari.server.orm.dao.TopologyRequestDAO; +import org.apache.ambari.server.orm.entities.TopologyRequestEntity; +import org.easymock.Capture; +import org.easymock.EasyMockRunner; +import org.easymock.Mock; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.google.common.collect.ImmutableMap; + + +@RunWith(EasyMockRunner.class) +public class PersistedStateImplTest { + + private static final String CLUSTER_REQUEST = + "{'blueprint': 'bp', 'host_groups': [{'name': 'group','host_count': '1' }]}".replace('\'', '"'); + + private static final String BLUEPRINT_NAME = "bp"; + + @Mock + private TopologyRequestDAO topologyRequestDAO; + + @Mock + private BlueprintFactory blueprintFactory; + + @Mock + private Blueprint blueprint; + + @Mock + private ProvisionClusterRequest + request; + + private PersistedStateImpl persistedState; + + @Before + public void init() throws Exception { + expect(blueprint.getName()).andReturn(BLUEPRINT_NAME).anyTimes(); + expect(blueprint.getConfiguration()).andReturn(new Configuration()).anyTimes(); + expect(blueprintFactory.getBlueprint(BLUEPRINT_NAME)).andReturn(blueprint).anyTimes(); + + expect(request.getBlueprint()).andReturn(blueprint).anyTimes(); + expect(request.getRawRequestBody()).andReturn(CLUSTER_REQUEST).anyTimes(); + expect(request.getType()).andReturn(TopologyRequest.Type.PROVISION).anyTimes(); + expect(request.getConfiguration()).andReturn(new Configuration()).anyTimes(); + expect(request.getClusterId()).andReturn(1L).anyTimes(); + expect(request.getDescription()).andReturn("").anyTimes(); + expect(request.getProvisionAction()).andReturn(ProvisionAction.INSTALL_AND_START).anyTimes(); + HostGroupInfo hostGroupInfo = new HostGroupInfo("hostgroup1"); + hostGroupInfo.setConfiguration(new Configuration()); + expect(request.getHostGroupInfo()).andReturn(ImmutableMap.of("hostgroup1", hostGroupInfo)).anyTimes(); + + replay(blueprint, blueprintFactory, request); + + Field blueprintFactoryField = BaseClusterRequest.class.getDeclaredField("blueprintFactory"); + blueprintFactoryField.setAccessible(true); + blueprintFactoryField.set(null, blueprintFactory); + + persistedState = new PersistedStateImpl(); + Field topologyRequestDAOField = PersistedStateImpl.class.getDeclaredField("topologyRequestDAO"); + topologyRequestDAOField.setAccessible(true); + topologyRequestDAOField.set(persistedState, topologyRequestDAO); + } + + @After + public void tearDown() { + reset(topologyRequestDAO, blueprintFactory, blueprint, request); + } + + @Test + public void testPersistTopologyRequest_RawRequestIsSaved() throws Exception { + // Given + Capture<TopologyRequestEntity> entityCapture = newCapture(); + topologyRequestDAO.create(capture(entityCapture)); + expectLastCall().andAnswer(() -> { + entityCapture.getValue().setId(1L); + return null; + }); + replay(topologyRequestDAO); + + // When + persistedState.persistTopologyRequest(request); + + // Then + assertEquals(CLUSTER_REQUEST, entityCapture.getValue().getRawRequestBody()); + } + +} \ No newline at end of file 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 9f3a1f0..89f2f4f 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 @@ -584,7 +584,7 @@ public class TopologyManagerTest { expect(persistedState.getAllRequests()).andReturn(Collections.emptyMap()).anyTimes(); replayAll(); topologyManager.provisionCluster(request); - topologyManager.scaleHosts(new ScaleClusterRequest(propertySet)); + topologyManager.scaleHosts(new ScaleClusterRequest("{}", propertySet)); Assert.fail("InvalidTopologyException should have been thrown"); } diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyRequestUtilTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyRequestUtilTest.java new file mode 100644 index 0000000..db4046a --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyRequestUtilTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ambari.server.topology; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; + +import org.apache.ambari.server.state.StackId; +import org.junit.Test; + +import com.google.common.collect.ImmutableSet; + +public class TopologyRequestUtilTest { + + private static final String REQUEST_WITH_MPACK_INSTANCES = + "{ 'mpack_instances' : [ {'name': 'HDPCORE', 'version': '1.0.0-b98'}, {'name': 'EDW', 'version': '1.0.0'} ] }".replace('\'', '"'); + + private static final String REQUEST_WITH_INVALID_MPACK_INSTANCE = + "{ 'mpack_instances' : [ {'name': 'HDPCORE', 'version': '1.0.0-b98'}, {'name': 'EDW'} ] }".replace('\'', '"'); + + private static final String REQUEST_WITHOUT_MPACK_INSTANCE = "{}"; + + + @Test + public void testGetStackIdsFromRawRequest_normalCase() { + assertEquals( + ImmutableSet.of(new StackId("HDPCORE", "1.0.0-b98"), new StackId("EDW", "1.0.0")), + TopologyRequestUtil.getStackIdsFromRequest(REQUEST_WITH_MPACK_INSTANCES)); + } + + @Test + public void testGetStackIdsFromRawRequest_noMpackInstances() { + assertEquals( + Collections.emptySet(), + TopologyRequestUtil.getStackIdsFromRequest(REQUEST_WITHOUT_MPACK_INSTANCE)); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetStackIdsFromRawRequest_wrongMpackInstance() { + TopologyRequestUtil.getStackIdsFromRequest(REQUEST_WITH_INVALID_MPACK_INSTANCE); + } + +} \ No newline at end of file -- To stop receiving notification emails like this one, please contact beny...@apache.org.