package alien4cloud.paas.function; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Map; import java.util.Set; import java.util.UUID; import javax.annotation.PostConstruct; import javax.annotation.Resource; import alien4cloud.dao.IGenericSearchDAO; import alien4cloud.tosca.parser.AbstractToscaParserSimpleProfileTest; import org.alien4cloud.tosca.catalog.ArchiveUploadService; import org.alien4cloud.tosca.model.Csar; import org.alien4cloud.tosca.model.definitions.AbstractPropertyValue; import org.alien4cloud.tosca.model.definitions.ConcatPropertyValue; import org.alien4cloud.tosca.model.definitions.FunctionPropertyValue; import org.alien4cloud.tosca.model.definitions.IValue; import org.alien4cloud.tosca.model.definitions.Operation; import org.alien4cloud.tosca.model.definitions.OperationOutput; import org.alien4cloud.tosca.model.definitions.ScalarPropertyValue; import org.alien4cloud.tosca.model.templates.Capability; import org.alien4cloud.tosca.model.templates.NodeTemplate; import org.alien4cloud.tosca.model.templates.Topology; import org.alien4cloud.tosca.model.types.AbstractInstantiableToscaType; import org.alien4cloud.tosca.model.types.AbstractToscaType; import org.elasticsearch.index.query.QueryBuilders; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Value; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.google.common.collect.Maps; import alien4cloud.common.AlienConstants; import alien4cloud.git.RepositoryManager; import alien4cloud.model.components.CSARSource; import alien4cloud.paas.IPaaSTemplate; import alien4cloud.paas.model.InstanceInformation; import alien4cloud.paas.model.PaaSNodeTemplate; import alien4cloud.paas.model.PaaSRelationshipTemplate; import alien4cloud.paas.plan.TopologyTreeBuilderService; import alien4cloud.paas.plan.ToscaNodeLifecycleConstants; import alien4cloud.paas.plan.ToscaRelationshipLifecycleConstants; import alien4cloud.security.model.Role; import alien4cloud.test.utils.SecurityTestUtils; import alien4cloud.tosca.parser.ParsingError; import alien4cloud.tosca.parser.ParsingResult; import alien4cloud.utils.FileUtil; import alien4cloud.utils.MapUtil; import alien4cloud.utils.services.ApplicationUtil; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:function-application-context-test.xml") public class FunctionEvaluatorTest { private static boolean INITIALIZED = false; @Resource(name = "alien-es-dao") private IGenericSearchDAO alienDAO; @Resource private ArchiveUploadService archiveUploadService; @Resource private TopologyTreeBuilderService treeBuilder; @Resource private ApplicationUtil applicationUtil; @Value("${directories.alien}/${directories.csar_repository}") private String alienRepoDir; private Path artifactsDirectory = Paths.get("target/git-artifacts"); private RepositoryManager repositoryManager = new RepositoryManager(); private Map<String, PaaSNodeTemplate> builtPaaSNodeTemplates; @PostConstruct public void postConstruct() throws Throwable { if (!INITIALIZED) { if (Files.exists(Paths.get(alienRepoDir))) { try { FileUtil.delete(Paths.get(alienRepoDir)); } catch (IOException e) { e.printStackTrace(); } } SecurityTestUtils.setTestAuthentication(Role.ADMIN); alienDAO.delete(Csar.class, QueryBuilders.matchAllQuery()); String normativeLocalName = "tosca-normative-types"; repositoryManager.cloneOrCheckout(artifactsDirectory, "https://github.com/alien4cloud/tosca-normative-types.git", "1.2.0", normativeLocalName); String sampleLocalName = "samples"; repositoryManager.cloneOrCheckout(artifactsDirectory, "https://github.com/alien4cloud/samples.git", "master", sampleLocalName); String extendedLocalName = "alien-extended-types"; repositoryManager.cloneOrCheckout(artifactsDirectory, "https://github.com/alien4cloud/alien4cloud-extended-types.git", "1.3.0", extendedLocalName); Path typesPath = artifactsDirectory.resolve(normativeLocalName); Path typesZipPath = artifactsDirectory.resolve(normativeLocalName + ".zip"); FileUtil.zip(typesPath, typesZipPath); ParsingResult<Csar> result = archiveUploadService.upload(typesZipPath, CSARSource.OTHER, AlienConstants.GLOBAL_WORKSPACE_ID); AbstractToscaParserSimpleProfileTest.assertNoBlocker(result); typesPath = artifactsDirectory.resolve(extendedLocalName).resolve("alien-base-types"); typesZipPath = artifactsDirectory.resolve("alien-base-types.zip"); FileUtil.zip(typesPath, typesZipPath); result = archiveUploadService.upload(typesZipPath, CSARSource.OTHER, AlienConstants.GLOBAL_WORKSPACE_ID); AbstractToscaParserSimpleProfileTest.assertNoBlocker(result); typesPath = artifactsDirectory.resolve(sampleLocalName).resolve("tomcat-war"); typesZipPath = artifactsDirectory.resolve("tomcat_war.zip"); FileUtil.zip(typesPath, typesZipPath); result = archiveUploadService.upload(typesZipPath, CSARSource.OTHER, AlienConstants.GLOBAL_WORKSPACE_ID); AbstractToscaParserSimpleProfileTest.assertNoBlocker(result); typesPath = Paths.get("src/test/resources/alien/paas/function/csars/test-types"); typesZipPath = artifactsDirectory.resolve("target/test-types.zip"); FileUtil.zip(typesPath, typesZipPath); result = archiveUploadService.upload(typesZipPath, CSARSource.OTHER, AlienConstants.GLOBAL_WORKSPACE_ID); AbstractToscaParserSimpleProfileTest.assertNoBlocker(result); INITIALIZED = true; } Topology topology = applicationUtil.parseYamlTopology("src/test/resources/alien/paas/function/topology/badFunctionsTomcatWar"); topology.setId(UUID.randomUUID().toString()); topology.setWorkspace(AlienConstants.GLOBAL_WORKSPACE_ID); builtPaaSNodeTemplates = treeBuilder.buildPaaSTopology(topology).getAllNodes(); } @Test public void testParseAttributConcatScalar() { Map<String, NodeTemplate> nodeTemplates = Maps.newHashMap(); NodeTemplate nodeTemplate1 = new NodeTemplate(); nodeTemplate1.setProperties( MapUtil.newHashMap(new String[] { "the_property_name_1" }, new AbstractPropertyValue[] { new ScalarPropertyValue("the_property_value_1") })); nodeTemplates.put("the_node_tempalte_1", nodeTemplate1); NodeTemplate nodeTemplate2 = new NodeTemplate(); nodeTemplate2.setProperties( MapUtil.newHashMap(new String[] { "the_property_name_2" }, new AbstractPropertyValue[] { new ScalarPropertyValue("the_property_value_2") })); nodeTemplates.put("the_node_tempalte_2", nodeTemplate2); Topology topology = new Topology(); topology.setNodeTemplates(nodeTemplates); Map<String, Map<String, InstanceInformation>> runtimeInformations = Maps.newHashMap(); // Create a IAttributeValue ConcatPropertyValue concatAttributeValue = new ConcatPropertyValue(); ScalarPropertyValue scalarParameter1 = new ScalarPropertyValue(); ScalarPropertyValue scalarParameter2 = new ScalarPropertyValue(); ScalarPropertyValue scalarParameter3 = new ScalarPropertyValue(); ScalarPropertyValue scalarParameter4 = new ScalarPropertyValue(); scalarParameter1.setValue("http://"); scalarParameter2.setValue("mywebsiteurl"); scalarParameter3.setValue(":"); scalarParameter4.setValue("port"); concatAttributeValue.setParameters(new ArrayList<IValue>()); concatAttributeValue.getParameters().add(scalarParameter1); concatAttributeValue.getParameters().add(scalarParameter2); concatAttributeValue.getParameters().add(scalarParameter3); concatAttributeValue.getParameters().add(scalarParameter4); String parsedConcatString = FunctionEvaluator.parseAttribute(null, concatAttributeValue, topology, runtimeInformations, "0", null, null); String fullUrl = scalarParameter1.getValue() + scalarParameter2.getValue() + scalarParameter3.getValue() + scalarParameter4.getValue(); Assert.assertEquals(fullUrl, parsedConcatString); } @Test public void nodeTemplatesGetPropertyKeywordsSucessTest() throws Throwable { String computeName = "comp_tomcat_war"; PaaSNodeTemplate computePaaS = builtPaaSNodeTemplates.get(computeName); Operation configOp = computePaaS.getIndexedToscaElement().getInterfaces().get(ToscaNodeLifecycleConstants.STANDARD).getOperations() .get(ToscaNodeLifecycleConstants.CONFIGURE); IValue param = configOp.getInputParameters().get("customHostName"); Assert.assertEquals(getPropertyValue(computePaaS, "customHostName"), FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, computePaaS, builtPaaSNodeTemplates)); // HOST keyword String tomcatName = "tomcat"; String warName = "war_1"; PaaSNodeTemplate tomcatPaaS = builtPaaSNodeTemplates.get(tomcatName); PaaSNodeTemplate warPaaS = builtPaaSNodeTemplates.get(warName); Operation op = warPaaS.getIndexedToscaElement().getInterfaces().get("custom").getOperations().get("update_war_file"); param = op.getInputParameters().get("TOMCAT_HOME"); Assert.assertEquals(getPropertyValue(tomcatPaaS, "tomcat_home"), FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, warPaaS, builtPaaSNodeTemplates)); } @Test public void relationshipGetPropertyKeywordsSucessTest() throws Throwable { String warName = "war_1"; String warName_2 = "war_2"; String tomcatName = "tomcat"; String computeName = "comp_tomcat_war"; PaaSNodeTemplate warPaaS = builtPaaSNodeTemplates.get(warName); PaaSNodeTemplate warPaaS_2 = builtPaaSNodeTemplates.get(warName_2); PaaSNodeTemplate tomcatPaaS = builtPaaSNodeTemplates.get(tomcatName); PaaSNodeTemplate computePaaS = builtPaaSNodeTemplates.get(computeName); PaaSRelationshipTemplate hostedOnRelTemp = warPaaS.getRelationshipTemplate("warHostedOnTomcatTomcat", "war_1"); PaaSRelationshipTemplate hostedOnRelTemp_2 = warPaaS_2.getRelationshipTemplate("warHostedOnTomcatTomcat", "war_2"); Operation configOp = hostedOnRelTemp.getIndexedToscaElement().getInterfaces().get(ToscaRelationshipLifecycleConstants.CONFIGURE).getOperations() .get(ToscaRelationshipLifecycleConstants.POST_CONFIGURE_SOURCE); // test SOURCE keyword IValue param = configOp.getInputParameters().get("contextPath"); Assert.assertEquals(getPropertyValue(warPaaS, "context_path"), FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp, builtPaaSNodeTemplates)); // get prop from the host of the source node param = configOp.getInputParameters().get("propFromSourceCompute"); Assert.assertEquals(getPropertyValue(computePaaS, "customHostName"), FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp, builtPaaSNodeTemplates)); // test TARGET keyword param = configOp.getInputParameters().get("tomcatVersion"); Assert.assertEquals(getPropertyValue(tomcatPaaS, "component_version"), FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp, builtPaaSNodeTemplates)); // get prop from the host of the source node param = configOp.getInputParameters().get("propFromTargetCompute"); Assert.assertEquals(getPropertyValue(computePaaS, "customHostName"), FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp, builtPaaSNodeTemplates)); // test SELF keyword on relationship param = configOp.getInputParameters().get("relName"); Assert.assertEquals(getPropertyValue(hostedOnRelTemp, "relName"), FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp, builtPaaSNodeTemplates)); Assert.assertEquals(getPropertyValue(hostedOnRelTemp_2, "relName"), FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp_2, builtPaaSNodeTemplates)); // getting capability properties param = configOp.getInputParameters().get("valid_node_types"); Assert.assertEquals(getCapabilityPropertyValue(tomcatPaaS, "war_host", "valid_node_types"), FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp, builtPaaSNodeTemplates)); // capabilities not existing in the node param = configOp.getInputParameters().get("null_capa_prop1"); Assert.assertEquals(null, FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp, builtPaaSNodeTemplates)); // property not existing in the capability param = configOp.getInputParameters().get("null_capa_prop2"); Assert.assertEquals(null, FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp, builtPaaSNodeTemplates)); // using SELF keywork to get a capability's property on a relationship should return null param = configOp.getInputParameters().get("bad_valid_node_types"); Assert.assertEquals(null, FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, hostedOnRelTemp, builtPaaSNodeTemplates)); } private String getPropertyValue(IPaaSTemplate<? extends AbstractToscaType> paaSTemplate, String propertyName) { return ((ScalarPropertyValue) paaSTemplate.getTemplate().getProperties().get(propertyName)).getValue(); } private String getCapabilityPropertyValue(PaaSNodeTemplate paaSTemplate, String capaName, String propertyName) { Map<String, Capability> capabilities = paaSTemplate.getNodeTemplate().getCapabilities(); if (capabilities != null) { if (capabilities.get(capaName) != null && capabilities.get(capaName).getProperties() != null) { AbstractPropertyValue capa = capabilities.get(capaName).getProperties().get(propertyName); if (capa != null && capa instanceof ScalarPropertyValue) { return ((ScalarPropertyValue) capa).getValue(); } } } return null; } @Test(expected = BadUsageKeywordException.class) public void getPropertyWrongDefOrUSageTest() throws Throwable { String computeName = "comp_tomcat_war"; PaaSNodeTemplate computePaaS = builtPaaSNodeTemplates.get(computeName); Operation configOp = computePaaS.getIndexedToscaElement().getInterfaces().get(ToscaNodeLifecycleConstants.STANDARD).getOperations() .get(ToscaNodeLifecycleConstants.CONFIGURE); // case keyword SOURCE used on a NodeType IValue param = configOp.getInputParameters().get("keywordSourceBadUsage"); try { FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, computePaaS, builtPaaSNodeTemplates); } catch (BadUsageKeywordException e) { // case keyword TARGET used on a NodeType param = configOp.getInputParameters().get("KeywordTargetBadUsage"); FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) param, computePaaS, builtPaaSNodeTemplates); } } @Test public void getOperationOutputTest() { String computeName = "comp_getOpOutput"; PaaSNodeTemplate computePaaS = builtPaaSNodeTemplates.get(computeName); // check if outputs referenced in get_operation_outputs on attributes are well registered on the related operation AbstractInstantiableToscaType tocaElement = computePaaS.getIndexedToscaElement(); IValue oldHostNameAttr = tocaElement.getAttributes().get("old_hostname"); IValue newHostNameAttr = tocaElement.getAttributes().get("new_hostname"); Operation createOp = computePaaS.getInterfaces().get(ToscaNodeLifecycleConstants.STANDARD).getOperations().get(ToscaNodeLifecycleConstants.CREATE); Operation configOp = computePaaS.getInterfaces().get(ToscaNodeLifecycleConstants.STANDARD).getOperations().get(ToscaNodeLifecycleConstants.CONFIGURE); Set<OperationOutput> createOutput = createOp.getOutputs(); Set<OperationOutput> configureOutput = configOp.getOutputs(); Assert.assertTrue(oldHostNameAttr instanceof FunctionPropertyValue); Assert.assertTrue(newHostNameAttr instanceof FunctionPropertyValue); String output1 = ((FunctionPropertyValue) oldHostNameAttr).getElementNameToFetch(); String output2 = ((FunctionPropertyValue) newHostNameAttr).getElementNameToFetch(); Assert.assertTrue(createOutput.contains(new OperationOutput(output1))); OperationOutput fullOutput1 = createOp.getOutput(output1); Assert.assertTrue(fullOutput1.getRelatedAttributes().contains("comp_getOpOutput:old_hostname")); Assert.assertTrue(configureOutput.contains(new OperationOutput(output2))); OperationOutput fullOutput2 = configOp.getOutput(output2); Assert.assertTrue(fullOutput2.getRelatedAttributes().contains("comp_getOpOutput:new_hostname")); // check if outputs referenced in get_operation_output on an input parameter is well registered on the related operation IValue param = configOp.getInputParameters().get("OUTPUT_FROM_CREATE"); Assert.assertTrue(param instanceof FunctionPropertyValue); String output3 = ((FunctionPropertyValue) param).getElementNameToFetch(); Assert.assertTrue(createOutput.contains(new OperationOutput(output3))); OperationOutput fullOutput3 = configOp.getOutput(output2); Assert.assertFalse(fullOutput3.getRelatedAttributes().contains("comp_getOpOutput:OUTPUT_FROM_CREATE")); } @Test public void parseComplexProperty() { String complexPropName = "complex_prop"; PaaSNodeTemplate complexPropNode = builtPaaSNodeTemplates.get(complexPropName); Operation configOp = complexPropNode.getIndexedToscaElement().getInterfaces().get(ToscaNodeLifecycleConstants.STANDARD).getOperations() .get(ToscaNodeLifecycleConstants.CREATE); Assert.assertEquals( "{\n" + " \"nested_map\" : {\n" + " \"tutu\" : \"tata\",\n" + " \"toctoc\" : \"tactac\"\n" + " },\n" + " \"nested\" : \"toto\",\n" + " \"nested_array\" : [ \"titi\", \"tuctuc\" ]\n" + "}", FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) configOp.getInputParameters().get("COMPLEX"), complexPropNode, builtPaaSNodeTemplates)); Assert.assertEquals("toto", FunctionEvaluator.evaluateGetPropertyFunction((FunctionPropertyValue) configOp.getInputParameters().get("NESTED"), complexPropNode, builtPaaSNodeTemplates)); Assert.assertEquals("titi", FunctionEvaluator.evaluateGetPropertyFunction( (FunctionPropertyValue) configOp.getInputParameters().get("NESTED_ARRAY_ELEMENT"), complexPropNode, builtPaaSNodeTemplates)); Assert.assertEquals("tata", FunctionEvaluator.evaluateGetPropertyFunction( (FunctionPropertyValue) configOp.getInputParameters().get("NESTED_MAP_ELEMENT"), complexPropNode, builtPaaSNodeTemplates)); } }