diff options
author | andre.schmid <andre.schmid@est.tech> | 2022-07-18 17:25:41 +0100 |
---|---|---|
committer | Michael Morris <michael.morris@est.tech> | 2022-07-29 20:08:14 +0000 |
commit | 3f9669fdae5f7c6cb1bfe34742df35dfe3a14aa7 (patch) | |
tree | 307686e72403ee837fd342efb9865b0b6a83da7c /common-be/src | |
parent | 22d13840722a4020b1aaf75eeff3622e83c4b6d4 (diff) |
Support a custom yaml value in tosca function
Allows to add a custom YAML value to properties in the TOSCA function
feature.
Change-Id: I15e65088a18537d9832428717be826ac0ef6049a
Issue-ID: SDC-4099
Signed-off-by: André Schmid <andre.schmid@est.tech>
Diffstat (limited to 'common-be/src')
9 files changed, 218 insertions, 86 deletions
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CustomYamlFunction.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CustomYamlFunction.java index 84543e29f7..e9d584486d 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CustomYamlFunction.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CustomYamlFunction.java @@ -36,7 +36,10 @@ public class CustomYamlFunction implements ToscaFunction, ToscaFunctionParameter @Override public String getValue() { - return new Yaml().dump(yamlValue); + if (yamlValue == null) { + return null; + } + return yamlValue instanceof String ? (String) yamlValue : new Yaml().dump(yamlValue); } @Override diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializer.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializer.java index 74aed12471..fda832b98e 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializer.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializer.java @@ -32,10 +32,14 @@ import java.util.List; import org.apache.commons.lang3.StringUtils; import org.openecomp.sdc.be.datatypes.enums.PropertySource; import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; public class ToscaFunctionJsonDeserializer extends StdDeserializer<ToscaFunction> { + private static final Logger LOGGER = LoggerFactory.getLogger(ToscaFunctionJsonDeserializer.class); + public ToscaFunctionJsonDeserializer() { this(null); } @@ -74,16 +78,26 @@ public class ToscaFunctionJsonDeserializer extends StdDeserializer<ToscaFunction } if (toscaFunctionType == ToscaFunctionType.YAML) { - return this.deserializeYamlFunction(node); + return this.deserializeYamlFunction(node, context); } return null; } - private ToscaFunction deserializeYamlFunction(JsonNode node) { + private ToscaFunction deserializeYamlFunction(final JsonNode node, final DeserializationContext context) throws JsonMappingException { var yamlFunction = new CustomYamlFunction(); - final Object value = new Yaml().load(node.get("value").asText()); - yamlFunction.setYamlValue(value); + final JsonNode valueJsonNode = node.get("value"); + if (valueJsonNode == null) { + return yamlFunction; + } + final String valueAsText = valueJsonNode.asText(); + try { + yamlFunction.setYamlValue(new Yaml().load(valueAsText)); + } catch (final Exception e) { + final String errorMsg = String.format("Could not parse YAML expression: '%s'", valueAsText); + LOGGER.debug(errorMsg, e); + throw context.instantiationException(ToscaFunction.class, errorMsg); + } return yamlFunction; } diff --git a/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/CustomYamlFunctionTest.java b/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/CustomYamlFunctionTest.java new file mode 100644 index 0000000000..033fd10e2a --- /dev/null +++ b/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/CustomYamlFunctionTest.java @@ -0,0 +1,50 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.datatypes.elements; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.yaml.snakeyaml.Yaml; + +class CustomYamlFunctionTest { + + @Test + void getTypeTest() { + final var yamlFunction = new CustomYamlFunction(); + assertEquals(ToscaFunctionType.YAML, yamlFunction.getType()); + } + + @Test + void getValue() { + final var yamlFunction = new CustomYamlFunction(); + assertNull(yamlFunction.getValue()); + final String yamlValue1 = "my value"; + yamlFunction.setYamlValue(yamlValue1); + assertEquals(yamlValue1, yamlFunction.getValue()); + final Map<String, Map<String, String>> yamlValue2 = Map.of("entry", Map.of("property1", "value1")); + yamlFunction.setYamlValue(yamlValue2); + assertEquals(new Yaml().dump(yamlValue2), yamlFunction.getValue()); + } +}
\ No newline at end of file diff --git a/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializerTest.java b/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializerTest.java index e11b661098..b17a3dc3a3 100644 --- a/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializerTest.java +++ b/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializerTest.java @@ -21,35 +21,36 @@ package org.openecomp.sdc.be.datatypes.elements; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.ValueInstantiationException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.Test; import org.openecomp.sdc.be.datatypes.enums.PropertySource; import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType; +import org.yaml.snakeyaml.Yaml; class ToscaFunctionJsonDeserializerTest { + private static final Path TEST_RESOURCES_PATH = Path.of("src/test/resources/toscaFunctionJsonDeserializer"); + @Test - void testGetInputToscaFunction() throws JsonProcessingException { - final String toscaGetInputFunction = "{\n" - + " \"propertyUniqueId\": \"e57525d7-2115-4934-9ba4-9cebfa22bad2.nf_naming\",\n" - + " \"type\": \"GET_INPUT\",\n" - + " \"propertySource\": \"SELF\",\n" - + " \"propertyName\": \"instance_name\",\n" - + " \"sourceName\": \"ciResVFc26a0b30ec20\",\n" - + " \"sourceUniqueId\": \"aee643c9-6c8e-4a24-af7a-a9aff5c072c0\",\n" - + " \"propertyPathFromSource\": [\n" - + " \"nf_naming\",\n" - + " \"instance_name\"\n" - + " ]\n" - + " }"; - ToscaFunction toscaFunction = parseToscaFunction(toscaGetInputFunction); + void testGetInputToscaFunction() throws IOException { + //given + final String toscaGetInputFunction = Files.readString(TEST_RESOURCES_PATH.resolve("getInput.json")); + //when + final ToscaFunction toscaFunction = parseToscaFunction(toscaGetInputFunction); + //then assertTrue(toscaFunction instanceof ToscaGetFunctionDataDefinition); final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) toscaFunction; assertEquals(ToscaFunctionType.GET_INPUT, toscaGetFunction.getType()); @@ -63,20 +64,12 @@ class ToscaFunctionJsonDeserializerTest { } @Test - void testGetInputToscaFunctionLegacyConversion() throws JsonProcessingException { - final String toscaGetInputFunction = "{\n" - + " \"propertyUniqueId\": \"e57525d7-2115-4934-9ba4-9cebfa22bad2.nf_naming\",\n" - + " \"functionType\": \"GET_INPUT\",\n" - + " \"propertySource\": \"SELF\",\n" - + " \"propertyName\": \"instance_name\",\n" - + " \"sourceName\": \"ciResVFc26a0b30ec20\",\n" - + " \"sourceUniqueId\": \"aee643c9-6c8e-4a24-af7a-a9aff5c072c0\",\n" - + " \"propertyPathFromSource\": [\n" - + " \"nf_naming\",\n" - + " \"instance_name\"\n" - + " ]\n" - + " }"; - ToscaFunction toscaFunction = parseToscaFunction(toscaGetInputFunction); + void testGetInputToscaFunctionLegacyConversion() throws IOException { + //given + final String toscaGetInputFunction = Files.readString(TEST_RESOURCES_PATH.resolve("getInputLegacy.json")); + //when + final ToscaFunction toscaFunction = parseToscaFunction(toscaGetInputFunction); + //then assertTrue(toscaFunction instanceof ToscaGetFunctionDataDefinition); final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) toscaFunction; assertEquals(ToscaFunctionType.GET_INPUT, toscaGetFunction.getType()); @@ -84,70 +77,66 @@ class ToscaFunctionJsonDeserializerTest { } @Test - void testNoFunctionTypeProvided() { - final String toscaGetInputFunction = "{\n" - + " \"propertyUniqueId\": \"e57525d7-2115-4934-9ba4-9cebfa22bad2.nf_naming\",\n" - + " \"propertySource\": \"SELF\",\n" - + " \"propertyName\": \"instance_name\",\n" - + " \"sourceName\": \"ciResVFc26a0b30ec20\",\n" - + " \"sourceUniqueId\": \"aee643c9-6c8e-4a24-af7a-a9aff5c072c0\",\n" - + " \"propertyPathFromSource\": [\n" - + " \"nf_naming\",\n" - + " \"instance_name\"\n" - + " ]\n" - + " }"; + void testNoFunctionTypeProvided() throws IOException { + //given + final String toscaGetInputFunction = Files.readString(TEST_RESOURCES_PATH.resolve("getFunctionMissingType.json")); + //when/then final ValueInstantiationException actualException = assertThrows(ValueInstantiationException.class, () -> parseToscaFunction(toscaGetInputFunction)); assertTrue(actualException.getMessage().contains("Attribute type not provided")); } @Test - void testConcatToscaFunction() throws JsonProcessingException { - final String toscaGetInputFunction = "{\n" - + " \"type\": \"CONCAT\",\n" - + " \"parameters\": [\n" - + " {\n" - + " \"propertyUniqueId\": \"e57525d7-2115-4934-9ba4-9cebfa22bad2.nf_naming\",\n" - + " \"type\": \"GET_INPUT\",\n" - + " \"propertySource\": \"SELF\",\n" - + " \"propertyName\": \"instance_name\",\n" - + " \"sourceName\": \"ciResVFc26a0b30ec20\",\n" - + " \"sourceUniqueId\": \"aee643c9-6c8e-4a24-af7a-a9aff5c072c0\",\n" - + " \"propertyPathFromSource\": [\n" - + " \"nf_naming\",\n" - + " \"instance_name\"\n" - + " ]\n" - + " }, {\n" - + " \"type\": \"STRING\",\n" - + " \"value\": \"my string\"\n" - + " },\n" - + " {\n" - + " \"type\": \"CONCAT\",\n" - + " \"parameters\": [\n" - + " {\n" - + " \"type\": \"STRING\",\n" - + " \"value\": \"string1\"\n" - + " },\n" - + " {\n" - + " \"type\": \"STRING\",\n" - + " \"value\": \"string2\"\n" - + " }\n" - + " ]\n" - + " }\n" - + " ]\n" - + "}"; - ToscaFunction toscaFunction = parseToscaFunction(toscaGetInputFunction); + void testConcatToscaFunction() throws IOException { + //given + final String toscaConcatFunction = Files.readString(TEST_RESOURCES_PATH.resolve("concatFunction.json")); + //when + final ToscaFunction toscaFunction = parseToscaFunction(toscaConcatFunction); + //then assertTrue(toscaFunction instanceof ToscaConcatFunction); + final Object yamlObject = new Yaml().load(toscaFunction.getValue()); + assertTrue(yamlObject instanceof Map); + final Map<String, Object> yamlMap = (Map<String, Object>) yamlObject; + final Object concatFunctionObj = yamlMap.get(ToscaFunctionType.CONCAT.getName()); + assertNotNull(concatFunctionObj); + assertTrue(concatFunctionObj instanceof List); + final List<Object> concatFunctionParameters = (List<Object>) concatFunctionObj; + assertEquals(3, concatFunctionParameters.size(), "Expecting three parameters"); + assertTrue(concatFunctionParameters.get(0) instanceof Map); + final Map<String, Object> parameter1Map = (Map<String, Object>) concatFunctionParameters.get(0); + assertNotNull(parameter1Map.get(ToscaFunctionType.GET_INPUT.getName())); + assertTrue(parameter1Map.get(ToscaFunctionType.GET_INPUT.getName()) instanceof List); + List<String> getInputParameters = (List<String>) parameter1Map.get(ToscaFunctionType.GET_INPUT.getName()); + assertEquals(2, getInputParameters.size(), "Expecting two parameters in the get_input function"); + assertEquals("nf_naming", getInputParameters.get(0)); + assertEquals("instance_name", getInputParameters.get(1)); + + assertEquals("my string", concatFunctionParameters.get(1)); + + assertTrue(concatFunctionParameters.get(2) instanceof Map); + final Map<String, Object> parameter2Map = (Map<String, Object>) concatFunctionParameters.get(2); + assertNotNull(parameter2Map.get(ToscaFunctionType.CONCAT.getName())); + assertTrue(parameter2Map.get(ToscaFunctionType.CONCAT.getName()) instanceof List); + List<Object> concatParameters = (List<Object>) parameter2Map.get(ToscaFunctionType.CONCAT.getName()); + assertEquals(3, concatParameters.size(), "Expecting two parameters in the sub concat function"); + assertEquals("string1", concatParameters.get(0)); + assertEquals("string2", concatParameters.get(1)); + assertTrue(concatParameters.get(2) instanceof Map); + Map<String, Object> yamlFunctionValueMap = (Map<String, Object>) concatParameters.get(2); + assertTrue(yamlFunctionValueMap.get("myList") instanceof List); + assertTrue(yamlFunctionValueMap.get("get_something") instanceof List); + assertTrue(yamlFunctionValueMap.get("string") instanceof String); } @Test - void testYamlFunction() throws JsonProcessingException { - String yamlFunction = "{\n" - + " \"type\": \"YAML\",\n" - + " \"value\": \"tosca_definitions_version: tosca_simple_yaml_1_0_0\\nnode_types: \\n tosca.nodes.Compute:\\n derived_from: tosca.nodes.Root\\n attributes:\\n private_address:\\n type: string\\n public_address:\\n type: string\\n networks:\\n type: map\\n entry_schema:\\n type: tosca.datatypes.network.NetworkInfo\\n ports:\\n type: map\\n entry_schema:\\n type: tosca.datatypes.network.PortInfo\\n requirements:\\n - local_storage: \\n capability: tosca.capabilities.Attachment\\n node: tosca.nodes.BlockStorage\\n relationship: tosca.relationships.AttachesTo\\n occurrences: [0, UNBOUNDED] \\n capabilities:\\n host: \\n type: tosca.capabilities.Container\\n valid_source_types: [tosca.nodes.SoftwareComponent] \\n endpoint :\\n type: tosca.capabilities.Endpoint.Admin \\n os: \\n type: tosca.capabilities.OperatingSystem\\n scalable:\\n type: tosca.capabilities.Scalable\\n binding:\\n type: tosca.capabilities.network.Bindable\\n\"\n" - + "}"; - ToscaFunction toscaFunction = parseToscaFunction(yamlFunction); + void testYamlFunction() throws IOException { + //given + final String yamlFunction = Files.readString(TEST_RESOURCES_PATH.resolve("yamlFunction.json")); + //when + final ToscaFunction toscaFunction = parseToscaFunction(yamlFunction); + //then assertTrue(toscaFunction instanceof CustomYamlFunction); + assertDoesNotThrow(() -> new Yaml().load(toscaFunction.getValue())); } private ToscaFunction parseToscaFunction(final String toscaFunctionJson) throws JsonProcessingException { diff --git a/common-be/src/test/resources/toscaFunctionJsonDeserializer/concatFunction.json b/common-be/src/test/resources/toscaFunctionJsonDeserializer/concatFunction.json new file mode 100644 index 0000000000..808d96f3e6 --- /dev/null +++ b/common-be/src/test/resources/toscaFunctionJsonDeserializer/concatFunction.json @@ -0,0 +1,37 @@ +{ + "type": "CONCAT", + "parameters": [ + { + "propertyUniqueId": "e57525d7-2115-4934-9ba4-9cebfa22bad2.nf_naming", + "type": "GET_INPUT", + "propertySource": "SELF", + "propertyName": "instance_name", + "sourceName": "ciResVFc26a0b30ec20", + "sourceUniqueId": "aee643c9-6c8e-4a24-af7a-a9aff5c072c0", + "propertyPathFromSource": [ + "nf_naming", + "instance_name" + ] + }, { + "type": "STRING", + "value": "my string" + }, + { + "type": "CONCAT", + "parameters": [ + { + "type": "STRING", + "value": "string1" + }, + { + "type": "STRING", + "value": "string2" + }, + { + "type": "YAML", + "value": "myList: [1, two, three three]\nget_something: [SELF, something]\nstring: this is my string\n" + } + ] + } + ] +}
\ No newline at end of file diff --git a/common-be/src/test/resources/toscaFunctionJsonDeserializer/getFunctionMissingType.json b/common-be/src/test/resources/toscaFunctionJsonDeserializer/getFunctionMissingType.json new file mode 100644 index 0000000000..23a2678587 --- /dev/null +++ b/common-be/src/test/resources/toscaFunctionJsonDeserializer/getFunctionMissingType.json @@ -0,0 +1,11 @@ +{ + "propertyUniqueId": "e57525d7-2115-4934-9ba4-9cebfa22bad2.nf_naming", + "propertySource": "SELF", + "propertyName": "instance_name", + "sourceName": "ciResVFc26a0b30ec20", + "sourceUniqueId": "aee643c9-6c8e-4a24-af7a-a9aff5c072c0", + "propertyPathFromSource": [ + "nf_naming", + "instance_name" + ] +}
\ No newline at end of file diff --git a/common-be/src/test/resources/toscaFunctionJsonDeserializer/getInput.json b/common-be/src/test/resources/toscaFunctionJsonDeserializer/getInput.json new file mode 100644 index 0000000000..a992f22a75 --- /dev/null +++ b/common-be/src/test/resources/toscaFunctionJsonDeserializer/getInput.json @@ -0,0 +1,12 @@ +{ + "propertyUniqueId": "e57525d7-2115-4934-9ba4-9cebfa22bad2.nf_naming", + "type": "GET_INPUT", + "propertySource": "SELF", + "propertyName": "instance_name", + "sourceName": "ciResVFc26a0b30ec20", + "sourceUniqueId": "aee643c9-6c8e-4a24-af7a-a9aff5c072c0", + "propertyPathFromSource": [ + "nf_naming", + "instance_name" + ] +}
\ No newline at end of file diff --git a/common-be/src/test/resources/toscaFunctionJsonDeserializer/getInputLegacy.json b/common-be/src/test/resources/toscaFunctionJsonDeserializer/getInputLegacy.json new file mode 100644 index 0000000000..c09571bb3e --- /dev/null +++ b/common-be/src/test/resources/toscaFunctionJsonDeserializer/getInputLegacy.json @@ -0,0 +1,12 @@ +{ + "propertyUniqueId": "e57525d7-2115-4934-9ba4-9cebfa22bad2.nf_naming", + "functionType": "GET_INPUT", + "propertySource": "SELF", + "propertyName": "instance_name", + "sourceName": "ciResVFc26a0b30ec20", + "sourceUniqueId": "aee643c9-6c8e-4a24-af7a-a9aff5c072c0", + "propertyPathFromSource": [ + "nf_naming", + "instance_name" + ] +}
\ No newline at end of file diff --git a/common-be/src/test/resources/toscaFunctionJsonDeserializer/yamlFunction.json b/common-be/src/test/resources/toscaFunctionJsonDeserializer/yamlFunction.json new file mode 100644 index 0000000000..dfe63f00f4 --- /dev/null +++ b/common-be/src/test/resources/toscaFunctionJsonDeserializer/yamlFunction.json @@ -0,0 +1,4 @@ +{ + "type": "YAML", + "value": "tosca_definitions_version: tosca_simple_yaml_1_0_0\nnode_types: \n tosca.nodes.Compute:\n derived_from: tosca.nodes.Root\n attributes:\n private_address:\n type: string\n public_address:\n type: string\n networks:\n type: map\n entry_schema:\n type: tosca.datatypes.network.NetworkInfo\n ports:\n type: map\n entry_schema:\n type: tosca.datatypes.network.PortInfo\n requirements:\n - local_storage: \n capability: tosca.capabilities.Attachment\n node: tosca.nodes.BlockStorage\n relationship: tosca.relationships.AttachesTo\n occurrences: [0, UNBOUNDED] \n capabilities:\n host: \n type: tosca.capabilities.Container\n valid_source_types: [tosca.nodes.SoftwareComponent] \n endpoint :\n type: tosca.capabilities.Endpoint.Admin \n os: \n type: tosca.capabilities.OperatingSystem\n scalable:\n type: tosca.capabilities.Scalable\n binding:\n type: tosca.capabilities.network.Bindable\n" +}
\ No newline at end of file |