Add ResourceResolutionResult to ResourceResolutionService 26/108426/5
authorJozsef Csongvai <jozsef.csongvai@bell.ca>
Thu, 28 May 2020 17:57:06 +0000 (13:57 -0400)
committerKAPIL SINGAL <ks220y@att.com>
Tue, 9 Jun 2020 14:19:14 +0000 (14:19 +0000)
In order to ensure consistent behavior for assignment-map, supporting
occurences and multiple artifact-prefixes, ResourceResolutionService
needs to return assignment-map alongside generated template content.

Issue-ID: CCSDK-2389
Signed-off-by: Jozsef Csongvai <jozsef.csongvai@bell.ca>
Change-Id: I54c1991d23d65217f3492b08a2170a6d41b6482d

12 files changed:
components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/node_types.json
ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionExtensions.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentTest.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintExpressionService.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintExpressionServiceTest.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeServiceTest.kt

index c57ebe7..efa4006 100644 (file)
       "version": "1.0.0",
       "attributes": {
         "assignment-params": {
+          "description": "Holds resolved template, resolution-summary or key-value",
           "required": true,
           "type": "string"
+        },
+        "assignment-map": {
+          "description": "Holds resolved values for each artifact prefix eg. { vdns: { vnf-id: 123 } }",
+          "required": true,
+          "type": "map"
         }
       },
       "capabilities": {
                   "required": false,
                   "type": "string"
                 },
+                "resolution-summary": {
+                  "description": "Enable resolution-summary output",
+                  "required": false,
+                  "type": "boolean"
+                },
                 "artifact-prefix-names": {
                   "required": true,
                   "description": "Template , Resource Assignment Artifact Prefix names",
                   "required": true,
                   "type": "string"
                 },
+                "resource-assignment-map": {
+                  "required": true,
+                  "type": "string"
+                },
                 "status": {
                   "required": true,
                   "type": "string"
index e15705a..3ebd2f8 100644 (file)
@@ -19,6 +19,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution
 
 import com.fasterxml.jackson.databind.JsonNode
 import com.fasterxml.jackson.databind.node.JsonNodeFactory
+import com.fasterxml.jackson.databind.node.ObjectNode
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
@@ -78,11 +79,16 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
         properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY] = resolutionSummary
 
         val jsonResponse = JsonNodeFactory.instance.objectNode()
-        // Initialize Output Attribute to empty JSON
+        val assignmentMap = JsonNodeFactory.instance.objectNode()
+        // Initialize Output Attributes to empty JSON
         bluePrintRuntimeService.setNodeTemplateAttributeValue(
             nodeTemplateName,
             ResourceResolutionConstants.OUTPUT_ASSIGNMENT_PARAMS, jsonResponse
         )
+        bluePrintRuntimeService.setNodeTemplateAttributeValue(
+            nodeTemplateName,
+            ResourceResolutionConstants.OUTPUT_ASSIGNMENT_MAP, assignmentMap
+        )
 
         // validate inputs if we need to store the resource and template resolution.
         if (storeResult) {
@@ -104,7 +110,7 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
         for (j in 1..occurrence) {
             properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = j
 
-            val response = resourceResolutionService.resolveResources(
+            val result = resourceResolutionService.resolveResources(
                 bluePrintRuntimeService,
                 nodeTemplateName,
                 artifactPrefixNames,
@@ -113,9 +119,11 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
 
             // provide indexed result in output if we have multiple resolution
             if (occurrence != 1) {
-                jsonResponse.set<JsonNode>(Integer.toString(j), response.asJsonNode())
+                jsonResponse.set<JsonNode>(j.toString(), result.templateMap.asJsonNode())
+                assignmentMap.set<JsonNode>(j.toString(), result.assignmentMap.asJsonNode())
             } else {
-                jsonResponse.setAll(response.asObjectNode())
+                jsonResponse.setAll<ObjectNode>(result.templateMap.asObjectNode())
+                assignmentMap.setAll<ObjectNode>(result.assignmentMap.asObjectNode())
             }
         }
 
@@ -124,6 +132,10 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
             nodeTemplateName,
             ResourceResolutionConstants.OUTPUT_ASSIGNMENT_PARAMS, jsonResponse
         )
+        bluePrintRuntimeService.setNodeTemplateAttributeValue(
+            nodeTemplateName,
+            ResourceResolutionConstants.OUTPUT_ASSIGNMENT_MAP, assignmentMap
+        )
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
index 4ad86b4..836db4c 100644 (file)
@@ -21,7 +21,6 @@ import com.fasterxml.jackson.databind.JsonNode
 import kotlinx.coroutines.async
 import kotlinx.coroutines.awaitAll
 import kotlinx.coroutines.coroutineScope
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.OUTPUT_ASSIGNMENT_MAP
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolution
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionService
@@ -30,6 +29,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.util
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceDefinitionUtils.createResourceAssignments
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
 import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
@@ -46,6 +46,11 @@ import org.springframework.context.ApplicationContext
 import org.springframework.stereotype.Service
 import java.util.UUID
 
+data class ResourceResolutionResult(
+    val templateMap: MutableMap<String, String>,
+    val assignmentMap: MutableMap<String, JsonNode>
+)
+
 interface ResourceResolutionService {
 
     fun registeredResourceSources(): List<String>
@@ -61,14 +66,14 @@ interface ResourceResolutionService {
         nodeTemplateName: String,
         artifactNames: List<String>,
         properties: Map<String, Any>
-    ): MutableMap<String, String>
+    ): ResourceResolutionResult
 
     suspend fun resolveResources(
         bluePrintRuntimeService: BluePrintRuntimeService<*>,
         nodeTemplateName: String,
         artifactPrefix: String,
         properties: Map<String, Any>
-    ): String
+    ): Pair<String, JsonNode>
 
     /** Resolve resources for all the sources defined in a particular resource Definition[resolveDefinition]
      * with other [resourceDefinitions] dependencies for the sources [sources]
@@ -124,21 +129,22 @@ open class ResourceResolutionServiceImpl(
         nodeTemplateName: String,
         artifactNames: List<String>,
         properties: Map<String, Any>
-    ): MutableMap<String, String> {
+    ): ResourceResolutionResult {
 
         val resourceAssignmentRuntimeService =
             ResourceAssignmentUtils.transformToRARuntimeService(bluePrintRuntimeService, artifactNames.toString())
 
-        val resolvedParams: MutableMap<String, String> = hashMapOf()
+        val templateMap: MutableMap<String, String> = hashMapOf()
+        val assignmentMap: MutableMap<String, JsonNode> = hashMapOf()
         artifactNames.forEach { artifactName ->
-            val resolvedContent = resolveResources(
+            val (resolvedStringContent, resolvedJsonContent) = resolveResources(
                 resourceAssignmentRuntimeService, nodeTemplateName,
                 artifactName, properties
             )
-
-            resolvedParams[artifactName] = resolvedContent
+            templateMap[artifactName] = resolvedStringContent
+            assignmentMap[artifactName] = resolvedJsonContent
         }
-        return resolvedParams
+        return ResourceResolutionResult(templateMap, assignmentMap)
     }
 
     override suspend fun resolveResources(
@@ -146,7 +152,7 @@ open class ResourceResolutionServiceImpl(
         nodeTemplateName: String,
         artifactPrefix: String,
         properties: Map<String, Any>
-    ): String {
+    ): Pair<String, JsonNode> {
 
         // Template Artifact Definition Name
         val artifactTemplate = "$artifactPrefix-template"
@@ -186,16 +192,13 @@ open class ResourceResolutionServiceImpl(
             properties
         )
 
-        bluePrintRuntimeService.setNodeTemplateAttributeValue(
-                nodeTemplateName,
-                OUTPUT_ASSIGNMENT_MAP,
-                ResourceAssignmentUtils.generateAssignmentMap(artifactPrefix, resourceAssignments)
-        )
-
         val resolutionSummary = properties.getOrDefault(
             ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY,
             false
         ) as Boolean
+        val assignmentMap = resourceAssignments
+                .associateBy({ it.name }, { it.property?.value })
+                .asJsonNode()
         val resolvedParamJsonContent =
             ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList())
         val artifactTemplateDefinition =
@@ -226,7 +229,7 @@ open class ResourceResolutionServiceImpl(
             log.info("Template resolution saved into database successfully : ($properties)")
         }
 
-        return resolvedContent
+        return Pair(resolvedContent, assignmentMap)
     }
 
     override suspend fun resolveResourceDefinition(
index f97c669..1be9649 100644 (file)
@@ -274,13 +274,6 @@ class ResourceAssignmentUtils {
             return JacksonUtils.getJson(data, includeNull = true)
         }
 
-        fun generateAssignmentMap(
-            artifactPrefix: String,
-            resourceAssignments: List<ResourceAssignment>
-        ): ObjectNode = resourceAssignments.associateBy({ it.name }, { it.property?.value })
-                .let { mutableMapOf(artifactPrefix to it) }
-                .let { JacksonUtils.objectNodeFromObject(it) }
-
         private fun useDefaultValueIfNull(
             resourceAssignment: ResourceAssignment,
             resourceAssignmentName: String
index 83dd0ce..ab1efcd 100644 (file)
@@ -147,7 +147,7 @@ class ResourceResolutionComponentTest {
                 any<List<String>>(),
                 any<MutableMap<String, Any>>()
             )
-        } returns mutableMapOf()
+        } returns ResourceResolutionResult(mutableMapOf(), mutableMapOf())
 
         runBlocking {
             resourceResolutionComponent.processNB(executionRequest)
index d5c4318..d6fc522 100644 (file)
@@ -33,6 +33,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintError
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
 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
@@ -135,12 +136,22 @@ class ResourceResolutionServiceTest {
                 "baseconfig",
                 props
             )
+        }.let { (templateMap, assignmentMap) ->
+            assertEquals("This is Sample Velocity Template", templateMap)
+
+            val expectedAssignmentMap = hashMapOf(
+                    "service-instance-id" to "siid_1234",
+                    "vnf-id" to "vnf_1234",
+                    "vnf_name" to "temp_vnf"
+            ).asJsonType()
+            assertEquals(expectedAssignmentMap, assignmentMap)
         }
     }
 
     @Test
     @Throws(Exception::class)
     fun testResolveResources() {
+        val artifactNames = listOf("baseconfig", "another")
         runBlocking {
             Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
 
@@ -155,8 +166,6 @@ class ResourceResolutionServiceTest {
                     ExecutionServiceInput::class.java
                 )!!
 
-            val artefactNames = listOf("baseconfig", "another")
-
             // Prepare Inputs
             PayloadUtils.prepareInputsFromWorkflowPayload(
                 bluePrintRuntimeService,
@@ -167,9 +176,15 @@ class ResourceResolutionServiceTest {
             resourceResolutionService.resolveResources(
                 bluePrintRuntimeService,
                 "resource-assignment",
-                artefactNames,
+                artifactNames,
                 props
             )
+        }.let {
+            assertEquals(artifactNames.toSet(), it.templateMap.keys)
+            assertEquals(artifactNames.toSet(), it.assignmentMap.keys)
+
+            assertEquals("This is Sample Velocity Template", it.templateMap["another"])
+            assertEquals("vnf_1234", it.assignmentMap["another"]!!["vnf-id"]!!.asText())
         }
     }
 
@@ -256,7 +271,7 @@ class ResourceResolutionServiceTest {
                     props
             )
         }.let {
-            val summaries = JacksonUtils.jsonNode(it)["resolution-summary"]
+            val summaries = JacksonUtils.jsonNode(it.first)["resolution-summary"]
             val list = JacksonUtils.getListFromJsonNode(summaries, ResolutionSummary::class.java)
             assertEquals(list.size, 3)
         }
@@ -265,6 +280,7 @@ class ResourceResolutionServiceTest {
     @Test
     @Throws(Exception::class)
     fun testResolveResourcesWithoutTemplate() {
+        val artifactPrefix = "notemplate"
         runBlocking {
             Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
 
@@ -285,8 +301,6 @@ class ResourceResolutionServiceTest {
                             "testResolveResourcesWithMappingAndTemplate"
                     )
 
-            val artifactPrefix = "notemplate"
-
             // Prepare Inputs
             PayloadUtils.prepareInputsFromWorkflowPayload(
                     bluePrintRuntimeService,
@@ -307,7 +321,8 @@ class ResourceResolutionServiceTest {
                   "vnf-id" : "vnf_1234",
                   "vnf_name" : "temp_vnf"
                 }
-            """.trimIndent(), it)
+            """.trimIndent(), it.first)
+            assertEquals("siid_1234", it.second["service-instance-id"].asText())
         }
     }
 
index 6734613..59be795 100644 (file)
@@ -22,7 +22,6 @@
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils
 
 import com.fasterxml.jackson.databind.JsonNode
-import com.fasterxml.jackson.databind.node.ObjectNode
 import com.fasterxml.jackson.databind.node.TextNode
 import io.mockk.every
 import io.mockk.spyk
@@ -207,20 +206,6 @@ class ResourceAssignmentUtilsTest {
         """.replace("\n|\\s".toRegex(), ""), result)
     }
 
-    @Test
-    fun generateAssignmentMapTest() {
-        val artifactPrefix = "vdns"
-        val resourceAssignments = mutableListOf(
-            createResourceAssignmentForTest("abc-123", "vnf-id"),
-            createResourceAssignmentForTest(null, "vf-module-name")
-        )
-
-        val result: ObjectNode = ResourceAssignmentUtils.generateAssignmentMap(artifactPrefix, resourceAssignments)
-
-        assertEquals("abc-123", result["vdns"]["vnf-id"].textValue())
-        assertEquals(JacksonUtils.getJsonNode(null), result["vdns"]["vf-module-name"])
-    }
-
     private fun createResourceAssignmentForTest(resourceValue: String?, resourceName: String = "pnf-id"): ResourceAssignment {
         val valueForTest = if (resourceValue == null) null else TextNode(resourceValue)
         val resourceAssignmentForTest = ResourceAssignment().apply {
index 6a3c646..b6c432b 100644 (file)
@@ -130,7 +130,7 @@ object BluePrintExpressionService {
                 val propertyPaths: List<String> = arrayNode.filterIndexed { index, _ ->
                     index >= 3
                 }.map { it.textValue() }
-                subProperty = propertyPaths.joinToString("/")
+                subProperty = propertyPaths.joinToString(".")
             }
         }
 
@@ -170,7 +170,7 @@ object BluePrintExpressionService {
                 val propertyPaths: List<String> = arrayNode.filterIndexed { index, _ ->
                     index >= 3
                 }.map { it.textValue() }
-                subAttributeName = propertyPaths.joinToString("/")
+                subAttributeName = propertyPaths.joinToString(".")
             }
         }
         return AttributeExpression(
index f8cad99..4f64527 100644 (file)
@@ -60,7 +60,7 @@ class BluePrintExpressionServiceTest {
         assertEquals("SELF", expressionData1.propertyExpression?.modelableEntityName, " Failed to get expected modelableEntityName")
         assertEquals("property-name", expressionData1.propertyExpression?.propertyName, " Failed to get expected propertyName")
         assertEquals(
-            "resource/name",
+            "resource.name",
             expressionData1.propertyExpression?.subPropertyName,
             " Failed to populate nested subPropertyName expression data"
         )
@@ -84,7 +84,7 @@ class BluePrintExpressionServiceTest {
         assertEquals("SELF", expressionData1.attributeExpression?.modelableEntityName, " Failed to get expected modelableEntityName")
         assertEquals("attribute-name", expressionData1.attributeExpression?.attributeName, " Failed to get expected attributeName")
         assertEquals(
-            "resource/name",
+            "resource.name",
             expressionData1.attributeExpression?.subAttributeName,
             " Failed to populate nested subAttributeName expression data"
         )
index 871f8af..79979b9 100644 (file)
@@ -23,6 +23,7 @@ import org.junit.Test
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.TestConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintRuntimeUtils
@@ -234,6 +235,46 @@ class BluePrintRuntimeServiceTest {
         assertNotNull(resolvedJsonNode, "Failed to populate workflow output property values")
     }
 
+    @Test
+    fun `test resolvePropertyDefinitions using sub attributes`() {
+        val bluePrintRuntimeService = getBluePrintRuntimeService()
+
+        bluePrintRuntimeService.setNodeTemplateAttributeValue(
+                "resource-assignment", "assignment-map",
+                JacksonUtils.jsonNode("""
+                    {
+                      "a-prefix":{
+                        "an-object":{
+                          "a-key":123
+                        }
+                      }
+                    }
+                """.trimIndent())
+        )
+
+        val propertyDefinitions = mutableMapOf<String, PropertyDefinition>(
+                "resolution" to PropertyDefinition().apply {
+                    this.type = "json"
+                    this.value = JacksonUtils.jsonNode("""
+                        {
+                          "get_attribute":[
+                            "resource-assignment",
+                            "",
+                            "assignment-map",
+                            "a-prefix",
+                            "an-object",
+                            "a-key"
+                            ]
+                        }
+                    """.trimIndent())
+                }
+        )
+
+        val result = bluePrintRuntimeService.resolvePropertyDefinitions("workflow", "WORKFLOW", propertyDefinitions)
+
+        assertEquals("123", result["resolution"]!!.asText())
+    }
+
     private fun getBluePrintRuntimeService(): BluePrintRuntimeService<MutableMap<String, JsonNode>> {
         val blueprintBasePath = normalizedPathName(TestConstants.PATH_TEST_BLUEPRINTS_BASECONFIG)
         val blueprintRuntime = BluePrintMetadataUtils.bluePrintRuntime("1234", blueprintBasePath)