package alien4cloud.it.application.deployment; import static org.junit.Assert.*; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.alien4cloud.tosca.model.definitions.AbstractPropertyValue; import org.alien4cloud.tosca.model.definitions.PropertyValue; import org.alien4cloud.tosca.model.definitions.ScalarPropertyValue; import org.alien4cloud.tosca.model.templates.Capability; import org.alien4cloud.tosca.model.templates.NodeTemplate; import org.apache.commons.collections4.MapUtils; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import org.junit.Assert; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import alien4cloud.common.AlienConstants; import alien4cloud.it.Context; import alien4cloud.model.application.Application; import alien4cloud.model.orchestrators.locations.LocationResourceTemplate; import alien4cloud.paas.function.FunctionEvaluator; import alien4cloud.rest.application.model.SetLocationPoliciesRequest; import alien4cloud.rest.application.model.UpdateDeploymentTopologyRequest; import alien4cloud.rest.deployment.DeploymentTopologyDTO; import alien4cloud.rest.model.RestResponse; import alien4cloud.rest.topology.UpdatePropertyRequest; import alien4cloud.rest.utils.JsonUtil; import alien4cloud.topology.TopologyValidationResult; import alien4cloud.topology.task.InputArtifactTask; import alien4cloud.utils.AlienUtils; import alien4cloud.utils.MapUtil; import cucumber.api.DataTable; import cucumber.api.java.en.And; import cucumber.api.java.en.Then; import cucumber.api.java.en.When; import lombok.AllArgsConstructor; import lombok.Getter; public class DeploymentTopologyStepDefinitions { @When("^I Set the following location policies with orchestrator \"([^\"]*)\" for groups$") public void I_Set_the_following_location_policies_for_groups(String orchestratorName, Map<String, String> locationPolicies) throws Throwable { SetLocationPoliciesRequest request = new SetLocationPoliciesRequest(); String orchestratorId = Context.getInstance().getOrchestratorId(orchestratorName); request.setOrchestratorId(orchestratorId); Map<String, String> formatedPolicies = Maps.newHashMap(); for (Entry<String, String> entry : locationPolicies.entrySet()) { formatedPolicies.put(entry.getKey(), Context.getInstance().getLocationId(orchestratorId, entry.getValue())); } request.setGroupsToLocations(formatedPolicies); Application application = Context.getInstance().getApplication(); String environmentId = Context.getInstance().getDefaultApplicationEnvironmentId(application.getName()); String restUrl = String.format("/rest/v1/applications/%s/environments/%s/deployment-topology/location-policies", application.getId(), environmentId); String response = Context.getRestClientInstance().postJSon(restUrl, JsonUtil.toString(request)); Context.getInstance().registerRestResponse(response); } @Then("^the deployment topology shoud have the following location policies$") public void The_deployment_topology_shoud_have_the_following_location_policies(List<LocationPolicySetting> expectedLocationPoliciesSettings) throws Throwable { String response = Context.getInstance().getRestResponse(); RestResponse<DeploymentTopologyDTO> deploymentTopologyDTO = JsonUtil.read(response, DeploymentTopologyDTO.class, Context.getJsonMapper()); assertNotNull(deploymentTopologyDTO.getData()); Map<String, String> policies = deploymentTopologyDTO.getData().getLocationPolicies(); assertNotNull(policies); Context context = Context.getInstance(); for (LocationPolicySetting expected : expectedLocationPoliciesSettings) { String expectLocationId = context.getLocationId(context.getOrchestratorId(expected.getOrchestratorName()), expected.getLocationName()); assertEquals(expectLocationId, policies.get(expected.getGroupName())); } } @When("^I Set a unique location policy to \"([^\"]*)\"/\"([^\"]*)\" for all nodes$") public void I_Set_a_unique_location_policy_to_for_all_nodes(String orchestratorName, String locationName) throws Throwable { I_Set_the_following_location_policies_for_groups(orchestratorName, MapUtil.newHashMap(new String[] { AlienConstants.GROUP_ALL }, new String[] { locationName })); } @When("^I get the deployment toology for the current application$") public void I_get_the_deployment_toology_for_the_current_application() throws Throwable { Application application = Context.getInstance().getApplication(); String environmentId = Context.getInstance().getDefaultApplicationEnvironmentId(application.getName()); String restUrl = String.format("/rest/v1/applications/%s/environments/%s/deployment-topology/", application.getId(), environmentId); String response = Context.getRestClientInstance().get(restUrl); Context.getInstance().registerRestResponse(response); } @When("^I substitute on the current application the node \"(.*?)\" with the location resource \"(.*?)\"/\"(.*?)\"/\"(.*?)\"$") public void I_substitute_on_the_current_application_the_node_with_the_location_resource(String nodeName, String orchestratorName, String locationName, String resourceName) throws Throwable { Context context = Context.getInstance(); Application application = context.getApplication(); String envId = context.getDefaultApplicationEnvironmentId(application.getName()); String orchestratorId = context.getOrchestratorId(orchestratorName); String locationId = context.getLocationId(orchestratorId, locationName); String resourceId = context.getLocationResourceId(orchestratorId, locationId, resourceName); String restUrl = String.format("/rest/v1/applications/%s/environments/%s/deployment-topology/substitutions/%s", application.getId(), envId, nodeName); NameValuePair resourceParam = new BasicNameValuePair("locationResourceTemplateId", resourceId); String response = Context.getRestClientInstance().postUrlEncoded(restUrl, Lists.newArrayList(resourceParam)); context.registerRestResponse(response); } private DeploymentTopologyDTO getDTOAndassertNotNull() throws IOException { String response = Context.getInstance().getRestResponse(); DeploymentTopologyDTO dto = JsonUtil.read(response, DeploymentTopologyDTO.class, Context.getJsonMapper()).getData(); assertNotNull(dto); return dto; } @Then("^The deployment topology sould have the substituted nodes$") public void The_deployment_topology_sould_have_the_substituted_nodes(List<NodeSubstitutionSetting> expectedSubstitutionSettings) throws Throwable { DeploymentTopologyDTO dto = getDTOAndassertNotNull(); Map<String, String> substitutions = dto.getTopology().getSubstitutedNodes(); Map<String, LocationResourceTemplate> resources = dto.getLocationResourceTemplates(); assertTrue(MapUtils.isNotEmpty(substitutions)); assertTrue(MapUtils.isNotEmpty(resources)); for (NodeSubstitutionSetting nodeSubstitutionSetting : expectedSubstitutionSettings) { String substituteName = substitutions.get(nodeSubstitutionSetting.getNodeName()); assertEquals(nodeSubstitutionSetting.getResourceName(), substituteName); LocationResourceTemplate substitute = resources.get(substituteName); assertNotNull(substitute); assertEquals(nodeSubstitutionSetting.getResourceType(), substitute.getTypes()); } } @When("^I update the property \"(.*?)\" to \"(.*?)\" for the subtituted node \"(.*?)\"$") public void I_update_the_property_to_for_the_subtituted_node(String propertyName, String propertyValue, String nodeName) throws Throwable { Context context = Context.getInstance(); Application application = context.getApplication(); String envId = context.getDefaultApplicationEnvironmentId(application.getName()); UpdatePropertyRequest request = new UpdatePropertyRequest(propertyName, propertyValue); String restUrl = String.format("/rest/v1/applications/%s/environments/%s/deployment-topology/substitutions/%s/properties", application.getId(), envId, nodeName); String response = Context.getRestClientInstance().postJSon(restUrl, JsonUtil.toString(request)); context.registerRestResponse(response); } @Then("^The node \"(.*?)\" in the deployment topology should have the property \"(.*?)\" with value \"(.*?)\"$") public void the_node_in_the_deployment_topology_should_have_the_property_with_value(String nodeName, String propertyName, String expectPropertyValue) throws Throwable { DeploymentTopologyDTO dto = JsonUtil.read(Context.getInstance().getRestResponse(), DeploymentTopologyDTO.class, Context.getJsonMapper()).getData(); assertNotNull(dto); NodeTemplate node = dto.getTopology().getNodeTemplates().get(nodeName); assertNodePropertyValueEquals(node, propertyName, expectPropertyValue); } @When("^I update the capability \"(.*?)\" property \"(.*?)\" to \"(.*?)\" for the subtituted node \"(.*?)\"$") public void i_update_the_capability_property_to_for_the_subtituted_node(String capabilityName, String propertyName, String propertyValue, String nodeName) throws Throwable { Context context = Context.getInstance(); Application application = context.getApplication(); String envId = context.getDefaultApplicationEnvironmentId(application.getName()); UpdatePropertyRequest request = new UpdatePropertyRequest(propertyName, propertyValue); String restUrl = String.format("/rest/v1/applications/%s/environments/%s/deployment-topology/substitutions/%s/capabilities/%s/properties", application.getId(), envId, nodeName, capabilityName); String response = Context.getRestClientInstance().postJSon(restUrl, JsonUtil.toString(request)); context.registerRestResponse(response); } @Then("^The the node \"(.*?)\" in the deployment topology should have the capability \"(.*?)\"'s property \"(.*?)\" with value \"(.*?)\"$") public void the_the_node_in_the_deployment_topology_should_have_the_capability_s_property_with_value(String nodeName, String capabilityName, String propertyName, String expectedPropertyValue) throws Throwable { DeploymentTopologyDTO dto = JsonUtil.read(Context.getInstance().getRestResponse(), DeploymentTopologyDTO.class, Context.getJsonMapper()).getData(); assertNotNull(dto); NodeTemplate node = dto.getTopology().getNodeTemplates().get(nodeName); assertCapabilityPropertyValueEquals(node, capabilityName, propertyName, expectedPropertyValue); } @When("^I set the following inputs properties$") public void I_set_the_following_inputs_properties(Map<String, Object> inputProperties) throws Throwable { UpdateDeploymentTopologyRequest request = new UpdateDeploymentTopologyRequest(); request.setInputProperties(inputProperties); executeUpdateDeploymentTopologyCall(request); } @When("^I set the following orchestrator properties$") public void I_set_the_following_orchestrator_properties(Map<String, String> orchestratorProperties) throws Throwable { UpdateDeploymentTopologyRequest request = new UpdateDeploymentTopologyRequest(); request.setProviderDeploymentProperties(orchestratorProperties); executeUpdateDeploymentTopologyCall(request); } @Then("^the deployment topology should have the following inputs properties$") public void The_deployment_topology_sould_have_the_following_input_properties(Map<String, String> expectedStringInputProperties) throws Throwable { DeploymentTopologyDTO dto = getDTOAndassertNotNull(); Map<String, AbstractPropertyValue> expectedInputProperties = Maps.newHashMap(); for (Entry<String, String> inputEntry : expectedStringInputProperties.entrySet()) { expectedInputProperties.put(inputEntry.getKey(), new ScalarPropertyValue(inputEntry.getValue())); } assertPropMapContains(dto.getTopology().getInputProperties(), expectedInputProperties); } @Then("^the deployment topology should have the following orchestrator properties$") public void The_deployment_topology_sould_have_the_following_orchestrator_properties(Map<String, String> expectedInputProperties) throws Throwable { DeploymentTopologyDTO dto = getDTOAndassertNotNull(); assertMapContains(dto.getTopology().getProviderDeploymentProperties(), expectedInputProperties); } @Then("^the following nodes properties values sould be \"(.*?)\"$") public void The_following_nodes_properties_values_should_be(String expectedValue, Map<String, String> nodesProperties) throws Throwable { DeploymentTopologyDTO dto = getDTOAndassertNotNull(); for (Entry<String, String> entry : nodesProperties.entrySet()) { NodeTemplate template = MapUtils.getObject(dto.getTopology().getNodeTemplates(), entry.getKey()); assertNodePropertyValueEquals(template, entry.getValue(), expectedValue); } } private void executeUpdateDeploymentTopologyCall(UpdateDeploymentTopologyRequest request) throws IOException, JsonProcessingException { Application application = Context.getInstance().getApplication(); String envId = Context.getInstance().getDefaultApplicationEnvironmentId(application.getName()); String restUrl = String.format("/rest/v1/applications/%s/environments/%s/deployment-topology", application.getId(), envId); String response = Context.getRestClientInstance().putJSon(restUrl, JsonUtil.toString(request)); Context.getInstance().registerRestResponse(response); } private void assertNodePropertyValueEquals(NodeTemplate node, String propertyName, String expectedPropertyValue) { assertNotNull(node); AbstractPropertyValue abstractProperty = MapUtils.getObject(node.getProperties(), propertyName); assertEquals(expectedPropertyValue, FunctionEvaluator.getScalarValue(abstractProperty)); } private void assertCapabilityPropertyValueEquals(NodeTemplate node, String capabilityName, String propertyName, String expectedPropertyValue) { assertNotNull(node); Capability capability = MapUtils.getObject(node.getCapabilities(), capabilityName); assertNotNull(capability); AbstractPropertyValue abstractProperty = MapUtils.getObject(capability.getProperties(), propertyName); assertEquals(expectedPropertyValue, FunctionEvaluator.getScalarValue(abstractProperty)); } private void assertMapContains(Map<String, String> map, Map<String, String> expectedMap) { for (Entry<String, String> entry : expectedMap.entrySet()) { assertEquals(entry.getValue(), MapUtils.getObject(map, entry.getKey())); } } private void assertPropMapContains(Map<String, PropertyValue> map, Map<String, AbstractPropertyValue> expectedMap) { map = AlienUtils.safe(map); for (Entry<String, AbstractPropertyValue> entry : expectedMap.entrySet()) { assertEquals(entry.getValue(), map.get(entry.getKey())); } } @When("^I check for the valid status of the deployment topology$") public void iCheckForTheValidStatusOfTheDeploymentTopology() throws Throwable { I_get_the_deployment_toology_for_the_current_application(); } @Then("^the deployment topology should not be valid$") public void theDeploymentTopologyShouldNotBeValid() throws Throwable { Assert.assertFalse("the deployment topology is valid", JsonUtil .read(Context.getInstance().getRestResponse(), DeploymentTopologyDTO.class, Context.getJsonMapper()).getData().getValidation().isValid()); } @Then("^the deployment topology should be valid$") public void theDeploymentTopologyShouldBeValid() throws Throwable { Assert.assertTrue("the deployment topology is not valid", JsonUtil .read(Context.getInstance().getRestResponse(), DeploymentTopologyDTO.class, Context.getJsonMapper()).getData().getValidation().isValid()); } @And("^the missing inputs artifacts should be$") public void theMissingInputsArtifactsShouldBe(DataTable expectedInputArtifactsTable) throws Throwable { TopologyValidationResult topologyValidationResult = JsonUtil .read(Context.getInstance().getRestResponse(), DeploymentTopologyDTO.class, Context.getJsonMapper()).getData().getValidation(); for (List<String> expectedRow : expectedInputArtifactsTable.raw()) { boolean missingFound = topologyValidationResult.getTaskList().stream() .filter(task -> task instanceof InputArtifactTask && ((InputArtifactTask) task).getInputArtifactName().equals(expectedRow.get(0))) .findFirst().isPresent(); Assert.assertTrue(expectedRow.get(0) + " does not appear in the task list for the deployment topology", missingFound); } } @When("^I upload a file located at \"([^\"]*)\" for the input artifact \"([^\"]*)\"$") public void iUploadAFileLocatedAtForTheInputArtifact(String localFile, String inputArtifactName) throws Throwable { Application application = Context.getInstance().getApplication(); String envId = Context.getInstance().getDefaultApplicationEnvironmentId(application.getName()); String url = String.format("/rest/applications/%s/environments/%s/deployment-topology/inputArtifacts/%s/upload", application.getId(), envId, inputArtifactName); Context.getInstance().registerRestResponse( Context.getRestClientInstance().postMultipart(url, Paths.get(localFile).getFileName().toString(), Files.newInputStream(Paths.get(localFile)))); } @Getter @AllArgsConstructor(suppressConstructorProperties = true) private static class LocationPolicySetting { String groupName; String orchestratorName; String locationName; } @Getter @AllArgsConstructor(suppressConstructorProperties = true) private static class NodeSubstitutionSetting { String nodeName; String resourceName; String resourceType; } }