From ebcc45b8c8703cadc49cf3a0b888545845ccb9e6 Mon Sep 17 00:00:00 2001 From: Jozsef Csongvai Date: Tue, 21 Jan 2020 11:27:14 -0500 Subject: Eliminate Template Requirement Enables resource assignment without the use of a template. If no template is defined by the CBA, the default output is a kev-value map. If operation input: resolution-summary is set to true, output will be a list of ResolutionSummary. Issue-ID: CCSDK-2038 Change-Id: I5f6bcefcacec6e83cffac1134b13690b500a7563 Signed-off-by: Jozsef Csongvai --- .../resolution/ResourceResolutionComponent.kt | 4 + .../resolution/ResourceResolutionComponentDSL.kt | 11 +++ .../resolution/ResourceResolutionConstants.kt | 1 + .../resolution/ResourceResolutionService.kt | 30 ++++--- .../DatabaseResourceAssignmentProcessor.kt | 6 ++ .../processor/RestResourceResolutionProcessor.kt | 6 ++ .../resolution/utils/ResourceAssignmentUtils.kt | 69 ++++++++++++--- .../ResourceResolutionComponentDSLTest.kt | 1 + .../resolution/ResourceResolutionServiceTest.kt | 97 ++++++++++++++++++++++ .../utils/ResourceAssignmentUtilsTest.kt | 58 ++++++++++++- .../core/BluePrintConstants.kt | 3 - .../core/service/BluePrintTemplateService.kt | 8 +- .../core/utils/JacksonUtils.kt | 8 +- .../resource/dict/ResourceDefinition.kt | 27 ++++++ 14 files changed, 297 insertions(+), 32 deletions(-) (limited to 'ms') diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt index db0a6f0ed..3c95ea7bb 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt @@ -43,6 +43,7 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re const val INPUT_RESOURCE_TYPE = "resource-type" const val INPUT_ARTIFACT_PREFIX_NAMES = "artifact-prefix-names" const val INPUT_RESOLUTION_KEY = "resolution-key" + const val INPUT_RESOLUTION_SUMMARY = "resolution-summary" const val INPUT_STORE_RESULT = "store-result" const val INPUT_OCCURRENCE = "occurrence" @@ -64,6 +65,8 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re val resourceType = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE)?.returnNullIfMissing()?.textValue() ?: "" + val resolutionSummary = + getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY)?.asBoolean() ?: false val properties: MutableMap = mutableMapOf() properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = storeResult @@ -71,6 +74,7 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY] = resolutionSummary val jsonResponse = JsonNodeFactory.instance.objectNode() // Initialize Output Attribute to empty JSON diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSL.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSL.kt index 6573d0e9a..fd104d3ad 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSL.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSL.kt @@ -81,6 +81,11 @@ fun BluePrintTypes.nodeTypeComponentResourceResolution(): NodeType { false, "Key for service instance related correlation." ) + property( + ResourceResolutionComponent.INPUT_RESOLUTION_SUMMARY, BluePrintConstants.DATA_TYPE_BOOLEAN, + false, "Enables ResolutionSummary output" + ) + property( ResourceResolutionComponent.INPUT_OCCURRENCE, BluePrintConstants.DATA_TYPE_INTEGER, false, "Number of time to perform the resolution." @@ -176,6 +181,12 @@ class ComponentResourceResolutionNodeTemplateBuilder(id: String, description: St property(ResourceResolutionComponent.INPUT_RESOLUTION_KEY, resolutionKey) } + fun resolutionSummary(resolutionSummary: Boolean) = resolutionSummary(resolutionSummary.asJsonPrimitive()) + + fun resolutionSummary(resolutionSummary: JsonNode) { + property(ResourceResolutionComponent.INPUT_RESOLUTION_SUMMARY, resolutionSummary) + } + fun dynamicProperties(dynamicProperties: String) = dynamicProperties(dynamicProperties.asJsonType()) fun dynamicProperties(dynamicProperties: JsonNode) { diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt index c39933dc8..8f6069160 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt @@ -29,4 +29,5 @@ object ResourceResolutionConstants { const val RESOURCE_RESOLUTION_INPUT_OCCURRENCE = "occurrence" const val RESOURCE_RESOLUTION_INPUT_RESOURCE_ID = "resource-id" const val RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE = "resource-type" + const val RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY = "resolution-summary" } diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt index 7272a3d63..dff00c7eb 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt @@ -147,7 +147,7 @@ open class ResourceResolutionServiceImpl( properties: Map ): String { - // Velocity Artifact Definition Name + // Template Artifact Definition Name val artifactTemplate = "$artifactPrefix-template" // Resource Assignment Artifact Definition Name val artifactMapping = "$artifactPrefix-mapping" @@ -185,22 +185,28 @@ open class ResourceResolutionServiceImpl( properties ) + val resolutionSummary = properties.getOrDefault(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY, false) as Boolean val resolvedParamJsonContent = ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList()) - val artifactTemplateDefinition = bluePrintRuntimeService.bluePrintContext().checkNodeTemplateArtifact(nodeTemplateName, artifactTemplate) - val resolvedContent = if (artifactTemplateDefinition != null) { - blueprintTemplateService.generateContent( - bluePrintRuntimeService, nodeTemplateName, - artifactTemplate, resolvedParamJsonContent, false, - mutableMapOf( - ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE to - properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE].asJsonPrimitive() + val resolvedContent = when { + artifactTemplateDefinition != null -> { + blueprintTemplateService.generateContent( + bluePrintRuntimeService, nodeTemplateName, + artifactTemplate, resolvedParamJsonContent, false, + mutableMapOf( + ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE to + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE].asJsonPrimitive() + ) ) - ) - } else { - resolvedParamJsonContent + } + resolutionSummary -> { + ResourceAssignmentUtils.generateResolutionSummaryData(resourceAssignments, resourceDefinitions) + } + else -> { + resolvedParamJsonContent + } } if (isToStore(properties)) { diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt index e43b45e7d..0bfd7e4e2 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt @@ -28,6 +28,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDictionaryConstants import org.slf4j.LoggerFactory @@ -91,6 +92,11 @@ open class DatabaseResourceAssignmentProcessor( "failed to get input-key-mappings for $dName under $dSource properties" } + sourceProperties.inputKeyMapping + ?.mapValues { raRuntimeService.getDictionaryStore(it.value) } + ?.map { KeyIdentifier(it.key, it.value) } + ?.let { resourceAssignment.keyIdentifiers.addAll(it) } + logger.info( "DatabaseResource ($dSource) dictionary information: " + "Query:($sql), input-key-mapping:($inputKeyMapping), output-key-mapping:(${sourceProperties.outputKeyMapping})" diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt index 2ff5c441e..10233404c 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt @@ -27,6 +27,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment import org.slf4j.LoggerFactory import org.springframework.beans.factory.config.ConfigurableBeanFactory @@ -75,6 +76,11 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS checkNotNull(sourceProperties.inputKeyMapping) { "failed to get input-key-mappings for $dName under $dSource properties" } val resolvedInputKeyMapping = resolveInputKeyMappingVariables(inputKeyMapping).toMutableMap() + sourceProperties.inputKeyMapping + ?.mapValues { raRuntimeService.getDictionaryStore(it.value) } + ?.map { KeyIdentifier(it.key, it.value) } + ?.let { resourceAssignment.keyIdentifiers.addAll(it) } + // Resolving content Variables val payload = resolveFromInputKeyMapping(nullToEmpty(sourceProperties.payload), resolvedInputKeyMapping) val urlPath = diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt index 7ffc6db39..7101735ae 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt @@ -42,6 +42,8 @@ import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeServ import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResolutionSummary import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition import org.slf4j.LoggerFactory @@ -196,6 +198,22 @@ class ResourceAssignmentUtils { return data } + fun generateResolutionSummaryData( + resourceAssignments: List, + resourceDefinitions: Map + ): String { + val resolutionSummaryList = resourceAssignments.map { + val payload = resourceDefinitions[it.name] + ?.sources?.get(it.dictionarySource)?.properties?.get("payload") + ResolutionSummary( + it.name, it.property?.value, it.property?.required, + it.property?.type, it.keyIdentifiers, it.dictionaryName, + payload, it.dictionarySource, it.status, it.message + ) + } + return JacksonUtils.getJson(resolutionSummaryList, includeNull = true) + } + private fun useDefaultValueIfNull( resourceAssignment: ResourceAssignment, resourceAssignmentName: String @@ -263,7 +281,7 @@ class ResourceAssignmentUtils { return when (type) { in BluePrintTypes.validPrimitiveTypes() -> { // Primitive Types - parseResponseNodeForPrimitiveTypes(responseNode, outputKeyMapping) + parseResponseNodeForPrimitiveTypes(responseNode, resourceAssignment, outputKeyMapping) } in BluePrintTypes.validCollectionTypes() -> { // Array Types @@ -282,6 +300,7 @@ class ResourceAssignmentUtils { private fun parseResponseNodeForPrimitiveTypes( responseNode: JsonNode, + resourceAssignment: ResourceAssignment, outputKeyMapping: MutableMap ): JsonNode { // Return responseNode if is not a Complex Type @@ -306,11 +325,16 @@ class ResourceAssignmentUtils { if (returnNode.isNullOrMissing() || returnNode!!.isComplexType() && !returnNode.has(outputKeyMapping[outputKey])) { throw BluePrintProcessorException("Fail to find output key mapping ($outputKey) in the responseNode.") } - return if (returnNode.isComplexType()) { + + val returnValue = if (returnNode.isComplexType()) { returnNode[outputKeyMapping[outputKey]] } else { returnNode } + + outputKey?.let { KeyIdentifier(it, returnValue) } + ?.let { resourceAssignment.keyIdentifiers.add(it) } + return returnValue } private fun parseResponseNodeForCollection( @@ -337,7 +361,7 @@ class ResourceAssignmentUtils { val responseArrayNode = responseNode.toList() for (responseSingleJsonNode in responseArrayNode) { val arrayChildNode = parseSingleElementOfArrayResponseNode( - entrySchemaType, + entrySchemaType, resourceAssignment, outputKeyMapping, raRuntimeService, responseSingleJsonNode, metadata ) arrayNode.add(arrayChildNode) @@ -347,7 +371,10 @@ class ResourceAssignmentUtils { is ObjectNode -> { val responseArrayNode = responseNode.rootFieldsToMap() resultNode = - parseObjectResponseNode(entrySchemaType, outputKeyMapping, responseArrayNode, metadata) + parseObjectResponseNode( + resourceAssignment, entrySchemaType, outputKeyMapping, + responseArrayNode, metadata + ) } else -> { throw BluePrintProcessorException("Key-value response expected to match the responseNode.") @@ -387,6 +414,7 @@ class ResourceAssignmentUtils { private fun parseSingleElementOfArrayResponseNode( entrySchemaType: String, + resourceAssignment: ResourceAssignment, outputKeyMapping: MutableMap, raRuntimeService: ResourceAssignmentRuntimeService, responseNode: JsonNode, @@ -397,7 +425,13 @@ class ResourceAssignmentUtils { in BluePrintTypes.validPrimitiveTypes() -> { if (outputKeyMappingHasOnlyOneElement) { val outputKeyMap = outputKeyMapping.entries.first() + if (resourceAssignment.keyIdentifiers.none { it.name == outputKeyMap.key }) { + resourceAssignment.keyIdentifiers.add( + KeyIdentifier(outputKeyMap.key, JacksonUtils.objectMapper.createArrayNode()) + ) + } return parseSingleElementNodeWithOneOutputKeyMapping( + resourceAssignment, responseNode, outputKeyMap.key, outputKeyMap.value, @@ -416,6 +450,7 @@ class ResourceAssignmentUtils { raRuntimeService ) -> { parseSingleElementNodeWithAllOutputKeyMapping( + resourceAssignment, responseNode, outputKeyMapping, entrySchemaType, @@ -425,6 +460,7 @@ class ResourceAssignmentUtils { outputKeyMappingHasOnlyOneElement -> { val outputKeyMap = outputKeyMapping.entries.first() parseSingleElementNodeWithOneOutputKeyMapping( + resourceAssignment, responseNode, outputKeyMap.key, outputKeyMap.value, @@ -441,6 +477,7 @@ class ResourceAssignmentUtils { } private fun parseObjectResponseNode( + resourceAssignment: ResourceAssignment, entrySchemaType: String, outputKeyMapping: MutableMap, responseArrayNode: MutableMap, @@ -449,19 +486,21 @@ class ResourceAssignmentUtils { val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping) if (outputKeyMappingHasOnlyOneElement) { val outputKeyMap = outputKeyMapping.entries.first() - return parseObjectResponseNodeWithOneOutputKeyMapping( + val returnValue = parseObjectResponseNodeWithOneOutputKeyMapping( responseArrayNode, outputKeyMap.key, outputKeyMap.value, entrySchemaType, metadata ) + resourceAssignment.keyIdentifiers.add(KeyIdentifier(outputKeyMap.key, returnValue)) + return returnValue } else { throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType") } } private fun parseSingleElementNodeWithOneOutputKeyMapping( + resourceAssignment: ResourceAssignment, responseSingleJsonNode: JsonNode, - outputKeyMappingKey: - String, + outputKeyMappingKey: String, outputKeyMappingValue: String, type: String, metadata: MutableMap? @@ -476,11 +515,19 @@ class ResourceAssignmentUtils { logKeyValueResolvedResource(metadata, outputKeyMappingKey, responseKeyValue, type) JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, responseKeyValue, type, arrayChildNode) - + resourceAssignment.keyIdentifiers.find { it.name == outputKeyMappingKey && it.value.isArray } + .let { + if (it != null) + (it.value as ArrayNode).add(responseKeyValue) + else + resourceAssignment.keyIdentifiers.add( + KeyIdentifier(outputKeyMappingKey, responseKeyValue)) + } return arrayChildNode } private fun parseSingleElementNodeWithAllOutputKeyMapping( + resourceAssignment: ResourceAssignment, responseSingleJsonNode: JsonNode, outputKeyMapping: MutableMap, type: String, @@ -496,6 +543,7 @@ class ResourceAssignmentUtils { logKeyValueResolvedResource(metadata, it.key, responseKeyValue, type) JacksonUtils.populateJsonNodeValues(it.key, responseKeyValue, type, arrayChildNode) + resourceAssignment.keyIdentifiers.add(KeyIdentifier(it.key, responseKeyValue)) } return arrayChildNode } @@ -541,6 +589,7 @@ class ResourceAssignmentUtils { raRuntimeService ) -> { parseSingleElementNodeWithAllOutputKeyMapping( + resourceAssignment, responseNode, outputKeyMapping, entrySchemaType, @@ -550,8 +599,8 @@ class ResourceAssignmentUtils { outputKeyMappingHasOnlyOneElement -> { val outputKeyMap = outputKeyMapping.entries.first() parseSingleElementNodeWithOneOutputKeyMapping( - responseNode, outputKeyMap.key, outputKeyMap.value, - entrySchemaType, metadata + resourceAssignment, responseNode, outputKeyMap.key, + outputKeyMap.value, entrySchemaType, metadata ) } else -> { diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSLTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSLTest.kt index ae9b4208f..d1347113a 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSLTest.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSLTest.kt @@ -41,6 +41,7 @@ class ResourceResolutionComponentDSLTest { occurrence(2) resourceType("vnf") storeResult(false) + resolutionSummary(true) artifactPrefixNames(arrayListOf("template1", "template2")) dynamicProperties( """{ diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt index 2f338a3a1..0a12540d4 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt @@ -36,6 +36,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResolutionSummary import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration @@ -44,6 +45,7 @@ import org.springframework.context.annotation.ComponentScan import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit4.SpringRunner +import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertTrue @@ -79,6 +81,7 @@ class ResourceResolutionServiceTest { props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence + props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY] = false } @Test @@ -213,6 +216,100 @@ class ResourceResolutionServiceTest { } } + @Test + @Throws(Exception::class) + fun testResolveResourcesResolutionSummary() { + runBlocking { + props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY] = true + Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService) + + val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime( + "1234", + "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration" + ) + + val executionServiceInput = + JacksonUtils.readValueFromClassPathFile( + "payload/requests/sample-resourceresolution-request.json", + ExecutionServiceInput::class.java + )!! + + val resourceAssignmentRuntimeService = + ResourceAssignmentUtils.transformToRARuntimeService( + bluePrintRuntimeService, + "testResolveResourcesWithMappingAndTemplate" + ) + + val artifactPrefix = "notemplate" + + // Prepare Inputs + PayloadUtils.prepareInputsFromWorkflowPayload( + bluePrintRuntimeService, + executionServiceInput.payload, + "resource-assignment" + ) + + resourceResolutionService.resolveResources( + resourceAssignmentRuntimeService, + "resource-assignment", + artifactPrefix, + props + ) + }.let { + val list = JacksonUtils.getListFromJson(it, ResolutionSummary::class.java) + assertEquals(list.size, 3) + } + } + + @Test + @Throws(Exception::class) + fun testResolveResourcesWithoutTemplate() { + runBlocking { + Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService) + + val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime( + "1234", + "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration" + ) + + val executionServiceInput = + JacksonUtils.readValueFromClassPathFile( + "payload/requests/sample-resourceresolution-request.json", + ExecutionServiceInput::class.java + )!! + + val resourceAssignmentRuntimeService = + ResourceAssignmentUtils.transformToRARuntimeService( + bluePrintRuntimeService, + "testResolveResourcesWithMappingAndTemplate" + ) + + val artifactPrefix = "notemplate" + + // Prepare Inputs + PayloadUtils.prepareInputsFromWorkflowPayload( + bluePrintRuntimeService, + executionServiceInput.payload, + "resource-assignment" + ) + + resourceResolutionService.resolveResources( + resourceAssignmentRuntimeService, + "resource-assignment", + artifactPrefix, + props + ) + }.let { + assertEquals(""" + { + "service-instance-id" : "siid_1234", + "vnf-id" : "vnf_1234", + "vnf_name" : "temp_vnf" + } + """.trimIndent(), it) + } + } + @Test fun testResolveResourcesWithResourceIdAndResourceType() { props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = "" diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt index 3251dcacb..8ca401664 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt @@ -33,10 +33,12 @@ import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType import org.onap.ccsdk.cds.controllerblueprints.core.data.EntrySchema +import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition import kotlin.test.assertEquals data class IpAddress(val port: String, val ip: String) @@ -46,6 +48,7 @@ data class ExpectedResponseIpAddress(val ipAddress: IpAddress) class ResourceAssignmentUtilsTest { private lateinit var resourceAssignmentRuntimeService: ResourceAssignmentRuntimeService + private lateinit var resourceAssignment: ResourceAssignment private lateinit var inputMapToTestPrimitiveTypeWithValue: JsonNode private lateinit var inputMapToTestPrimitiveTypeWithKeyValue: JsonNode @@ -156,6 +159,34 @@ class ResourceAssignmentUtilsTest { assertEquals(expected, outcome.replace("\r\n", "\n"), "unexpected outcome generated") } + @Test + fun generate() { + val resourceAssignment = createResourceAssignmentForTest(null) + val resourceDefinition = ResourceDefinition() + val nodeTemplate = NodeTemplate().apply { + properties = mutableMapOf("payload" to JacksonUtils.jsonNode("{\"mock\": true}")) + } + resourceDefinition.sources = mutableMapOf("input" to nodeTemplate) + + val result = ResourceAssignmentUtils.generateResolutionSummaryData( + listOf(resourceAssignment), mapOf("pnf-id" to resourceDefinition)) + + assertEquals(""" + [{ + "name":"pnf-id", + "value":null, + "required":null, + "type":"string", + "key-identifiers":[], + "dictionary-name":"pnf-id", + "request-payload":{"mock":true}, + "dictionary-source":"input", + "status":null, + "message":null + }] + """.replace("\n|\\s".toRegex(), ""), result) + } + private fun createResourceAssignmentForTest(resourceValue: String?): ResourceAssignment { val valueForTest = if (resourceValue == null) null else TextNode(resourceValue) val resourceAssignmentForTest = ResourceAssignment().apply { @@ -181,6 +212,7 @@ class ResourceAssignmentUtilsTest { outcome, "Unexpected outcome returned for primitive type of simple String" ) + assertEquals(0, resourceAssignment.keyIdentifiers.size) outcome = prepareResponseNodeForTest( "sample-key-value", "string", "", @@ -191,6 +223,10 @@ class ResourceAssignmentUtilsTest { outcome, "Unexpected outcome returned for primitive type of key-value String" ) + assertEquals( + expectedValueToTestPrimitiveType, + resourceAssignment.keyIdentifiers[0].value + ) } @Test @@ -204,6 +240,13 @@ class ResourceAssignmentUtilsTest { outcome, "unexpected outcome returned for list of String" ) + + val expectedKeyIdentifierValue = JacksonUtils.getJsonNode(outcome.map { it["ip"] }) + assertEquals( + expectedKeyIdentifierValue, + resourceAssignment.keyIdentifiers[0].value + ) + // FIXME("Map is not collection type, It is known complex type") // outcome = prepareResponseNodeForTest( // "mapOfString", "map", "string", @@ -250,6 +293,9 @@ class ResourceAssignmentUtilsTest { outcome, "Unexpected outcome returned for complex type" ) + assertEquals( + expectedValueToTestComplexTypeWithOneOutputKeyMapping["host"], + resourceAssignment.keyIdentifiers[0].value) } @Test @@ -263,6 +309,16 @@ class ResourceAssignmentUtilsTest { outcome, "Unexpected outcome returned for complex type" ) + assertEquals(2, resourceAssignment.keyIdentifiers.size) + assertEquals( + expectedValueToTestComplexTypeWithAllOutputKeyMapping["name"], + resourceAssignment.keyIdentifiers[0].value + ) + + assertEquals( + expectedValueToTestComplexTypeWithAllOutputKeyMapping["ipAddress"], + resourceAssignment.keyIdentifiers[1].value + ) } private fun initInputMapAndExpectedValuesForPrimitiveType() { @@ -359,7 +415,7 @@ class ResourceAssignmentUtilsTest { response: Any ): JsonNode { - val resourceAssignment = when (sourceType) { + resourceAssignment = when (sourceType) { "list" -> { prepareRADataDictionaryCollection(dictionary_source, sourceType, entrySchema) } diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt index 20aef3498..5002810c2 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt @@ -218,9 +218,6 @@ object BluePrintConstants { const val DEFAULT_STEP_OPERATION = "process" const val DEFAULT_STEP_INTERFACE = "ComponentInterface" - const val ARTIFACT_VELOCITY_TYPE_NAME = "artifact-template-velocity" - const val ARTIFACT_JINJA_TYPE_NAME = "artifact-template-jinja" - const val MODEL_TYPE_ARTIFACT_TEMPLATE_VELOCITY = "artifact-template-velocity" const val MODEL_TYPE_ARTIFACT_TEMPLATE_JINJA = "artifact-template-jinja" const val MODEL_TYPE_ARTIFACT_MAPPING_RESOURCE = "artifact-mapping-resource" diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateService.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateService.kt index db733bda1..51a6e10ee 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateService.kt +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateService.kt @@ -40,7 +40,7 @@ class BluePrintTemplateService(private val bluePrintLoadConfiguration: BluePrint val template = bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) return when (templateType) { - BluePrintConstants.ARTIFACT_JINJA_TYPE_NAME -> { + BluePrintConstants.MODEL_TYPE_ARTIFACT_TEMPLATE_JINJA -> { BluePrintJinjaTemplateService.generateContent( template, jsonData, @@ -51,13 +51,13 @@ class BluePrintTemplateService(private val bluePrintLoadConfiguration: BluePrint bluePrintRuntimeService.bluePrintContext().version() ) } - BluePrintConstants.ARTIFACT_VELOCITY_TYPE_NAME -> { + BluePrintConstants.MODEL_TYPE_ARTIFACT_TEMPLATE_VELOCITY -> { BluePrintVelocityTemplateService.generateContent(template, jsonData, ignoreJsonNull, additionalContext) } else -> { throw BluePrintProcessorException( - "Unknown Artifact type, expecting ${BluePrintConstants.ARTIFACT_JINJA_TYPE_NAME}" + - "or ${BluePrintConstants.ARTIFACT_VELOCITY_TYPE_NAME}" + "Unknown Artifact type, expecting ${BluePrintConstants.MODEL_TYPE_ARTIFACT_TEMPLATE_JINJA}" + + "or ${BluePrintConstants.MODEL_TYPE_ARTIFACT_TEMPLATE_VELOCITY}" ) } } diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt index 3db1f84cd..573fc17d2 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt @@ -133,9 +133,13 @@ class JacksonUtils { return getJson(wrapperMap, pretty) } - fun getJson(any: kotlin.Any, pretty: Boolean = false): String { + fun getJson(any: kotlin.Any, pretty: Boolean = false, includeNull: Boolean = false): String { val objectMapper = jacksonObjectMapper() - objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) + if (includeNull) { + objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS) + } else { + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) + } if (pretty) { objectMapper.enable(SerializationFeature.INDENT_OUTPUT) } diff --git a/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt b/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt index 4ed98ddd0..f34099ea8 100644 --- a/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt +++ b/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt @@ -19,6 +19,7 @@ package org.onap.ccsdk.cds.controllerblueprints.resource.dict import com.fasterxml.jackson.annotation.JsonFormat import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.databind.JsonNode import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition import java.io.Serializable @@ -87,6 +88,9 @@ open class ResourceAssignment { @JsonProperty("updated-by") var updatedBy: String? = null + /** input & output key-mapping with their resolved values **/ + var keyIdentifiers: MutableList = mutableListOf() + override fun toString(): String { return """ [ @@ -101,6 +105,29 @@ open class ResourceAssignment { } } +data class KeyIdentifier(val name: String, val value: JsonNode) + +/** + * Data class for exposing summary of resource resolution + */ +data class ResolutionSummary( + val name: String, + val value: JsonNode?, + val required: Boolean?, + val type: String?, + @JsonProperty("key-identifiers") + val keyIdentifiers: MutableList, + @JsonProperty("dictionary-name") + val dictionaryName: String?, + @JsonProperty("request-payload") + val requestPayload: JsonNode?, + @JsonProperty("dictionary-source") + val dictionarySource: String?, + @JsonProperty("status") + val status: String?, + @JsonProperty("message") + val message: String? +) /** * Interface for Source Definitions (ex Input Source, * Default Source, Database Source, Rest Sources, etc) -- cgit 1.2.3-korg