summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json8
-rw-r--r--components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/data_types.json6
-rw-r--r--components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/maxoccurrence-mapping.json23
-rw-r--r--components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Templates/maxoccurrence-template.vtl1
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt99
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt29
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt23
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt110
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request.json5
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request2.json4
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt3
11 files changed, 308 insertions, 3 deletions
diff --git a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json
index 85a056c5e..c506ad05e 100644
--- a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json
+++ b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json
@@ -180,6 +180,14 @@
"type": "artifact-mapping-resource",
"file": "Definitions/another-mapping.json"
},
+ "maxoccurrence-template": {
+ "type": "artifact-template-velocity",
+ "file": "Templates/maxoccurrence-template.vtl"
+ },
+ "maxoccurrence-mapping": {
+ "type": "artifact-mapping-resource",
+ "file": "Definitions/maxoccurrence-mapping.json"
+ },
"notemplate-mapping": {
"type": "artifact-mapping-resource",
"file": "Definitions/notemplate-mapping.json"
diff --git a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/data_types.json b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/data_types.json
index 6d771cd68..94c587af7 100644
--- a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/data_types.json
+++ b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/data_types.json
@@ -51,6 +51,12 @@
"vnf_name": {
"required": true,
"type": "string"
+ },
+ "firmware-version": {
+ "type" : "string"
+ },
+ "ip-address": {
+ "type" : "string"
}
},
"derived_from": "tosca.datatypes.Dynamic"
diff --git a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/maxoccurrence-mapping.json b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/maxoccurrence-mapping.json
new file mode 100644
index 000000000..729488520
--- /dev/null
+++ b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/maxoccurrence-mapping.json
@@ -0,0 +1,23 @@
+[
+ {
+ "name": "firmware-version",
+ "input-param": true,
+ "property": {
+ "type": "string"
+ },
+ "dictionary-name": "input-source",
+ "dictionary-source": "input",
+ "dependencies": []
+ },
+ {
+ "name": "ip-address",
+ "input-param": true,
+ "property": {
+ "type": "string"
+ },
+ "max-occurrence": 1,
+ "dictionary-name": "input-source",
+ "dictionary-source": "input",
+ "dependencies": []
+ }
+] \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Templates/maxoccurrence-template.vtl b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Templates/maxoccurrence-template.vtl
new file mode 100644
index 000000000..9a9fc27eb
--- /dev/null
+++ b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Templates/maxoccurrence-template.vtl
@@ -0,0 +1 @@
+This is maxoccurrence Velocity Template \ No newline at end of file
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 a3c137807..427d48f3c 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
@@ -218,7 +218,18 @@ open class ResourceResolutionServiceImpl(
val occurrence = findNextOccurrence(bluePrintRuntimeService, properties, artifactPrefix)
log.info("Always perform new resolutions - next occurrence: $occurrence")
propertiesMutableMap[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
- // Since we are performing new resolution, simply pass empty list.
+ // If resolution has already been performed previously then may need to update some assignments
+ val resourceAssignmentFilteredMap: Map<String, ResourceAssignment> =
+ resourceAssignments.filter { it.maxOccurrence != null && it.maxOccurrence!! in 1 until occurrence }
+ .associateBy { it.name }
+ if (occurrence > 1 && resourceAssignmentFilteredMap.isNotEmpty())
+ updateResourceAssignmentByOccurrence(
+ bluePrintRuntimeService as ResourceAssignmentRuntimeService,
+ propertiesMutableMap,
+ artifactPrefix,
+ resourceAssignmentFilteredMap as MutableMap<String, ResourceAssignment>
+ )
+ // we may be performing new resolution for some resources, simply pass an empty list.
emptyList()
} else {
isNewResolution(bluePrintRuntimeService, properties, artifactPrefix)
@@ -500,6 +511,92 @@ open class ResourceResolutionServiceImpl(
}
}
+ /**
+ * Utility to update the resourceAssignments with existing resolutions if maxOccurrence is defined on it.
+ */
+ private suspend fun updateResourceAssignmentByOccurrence(
+ raRuntimeService: ResourceAssignmentRuntimeService,
+ properties: Map<String, Any>,
+ artifactPrefix: String,
+ resourceAssignmentFilteredMap: MutableMap<String, ResourceAssignment>
+ ) {
+ val resourceResolutionMap =
+ getResourceResolutionByLastOccurrence(raRuntimeService, properties, artifactPrefix).associateBy { it.name }
+
+ resourceAssignmentFilteredMap
+ .filter {
+ resourceResolutionMap.containsKey(it.key) && compareOne(
+ resourceResolutionMap[it.key]!!,
+ it.value
+ )
+ }
+ .forEach { raMapEntry ->
+ val resourceResolution = resourceResolutionMap[raMapEntry.key]
+ val resourceAssignment = raMapEntry.value
+
+ resourceResolution?.value?.let {
+ val value = it.asJsonType(resourceAssignment.property!!.type)
+ resourceAssignment.property!!.value = value
+ ResourceAssignmentUtils.setResourceDataValue(
+ resourceAssignment,
+ raRuntimeService,
+ value
+ )
+ }
+ resourceAssignment.status = resourceResolution?.status
+ resourceResolutionDBService.write(
+ properties,
+ raRuntimeService,
+ artifactPrefix,
+ resourceAssignment
+ )
+ }
+ }
+
+ /**
+ * Utility to find resource resolution based on occurrence.
+ */
+ private suspend fun getResourceResolutionByLastOccurrence(
+ bluePrintRuntimeService: BluePrintRuntimeService<*>,
+ properties: Map<String, Any>,
+ artifactPrefix: String
+ ): List<ResourceResolution> {
+
+ val resolutionKey = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] as String
+ val resourceId = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] as String
+ val resourceType = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] as String
+
+ // This should not happen since the request has already been validated but worth to check it here as well.
+ if (resourceType.isEmpty() && resourceId.isEmpty() && resolutionKey.isEmpty()) {
+ throw BluePrintProcessorException(
+ "Can't proceed to get last occurrence: " +
+ "Either provide a resolution-key OR combination of resource-id and resource-type"
+ )
+ }
+ val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+ val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
+ val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
+
+ return if (resolutionKey.isNotEmpty()) {
+ resourceResolutionDBService.findLastNOccurrences(
+ blueprintName,
+ blueprintVersion,
+ artifactPrefix,
+ resolutionKey,
+ 1
+ ).takeIf { it.isNotEmpty() }?.values?.first() ?: emptyList()
+ } else {
+ resourceResolutionDBService.findLastNOccurrences(
+ blueprintName,
+ blueprintVersion,
+ artifactPrefix,
+ resourceId,
+ resourceType,
+ 1
+ ).takeIf { it.isNotEmpty() }?.values?.first() ?: emptyList()
+ }
+ }
+
// Comparison between what we have in the database vs what we have to assign.
private fun compareOne(resourceResolution: ResourceResolution, resourceAssignment: ResourceAssignment): Boolean {
return (
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt
index aa7b61f6a..bd8f9d27d 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt
@@ -170,6 +170,35 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
}
/**
+ * This returns the resolutions of last N 'occurrences'.
+ *
+ * @param blueprintName
+ * @param blueprintVersion
+ * @param artifactPrefix
+ * @param resourceId
+ * @param resourceType
+ * @param lastN
+ */
+ suspend fun findLastNOccurrences(
+ blueprintName: String,
+ blueprintVersion: String,
+ artifactPrefix: String,
+ resourceId: String,
+ resourceType: String,
+ lastN: Int
+ ): Map<Int, List<ResourceResolution>> = withContext(Dispatchers.IO) {
+
+ resourceResolutionRepository.findLastNOccurrences(
+ resourceId,
+ resourceType,
+ blueprintName,
+ blueprintVersion,
+ artifactPrefix,
+ lastN
+ ).groupBy(ResourceResolution::occurrence).toSortedMap(reverseOrder())
+ }
+
+ /**
* This returns the resolutions with 'occurrence' value between begin and end.
*
* @param blueprintName
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt
index 9317a71cd..5861cf8cb 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt
@@ -77,6 +77,29 @@ interface ResourceResolutionRepository : JpaRepository<ResourceResolution, Strin
@Query(
value = """
+ SELECT * FROM RESOURCE_RESOLUTION WHERE resource_id = :resourceId
+ AND resource_type =:resourceType AND blueprint_name = :blueprintName
+ AND blueprint_version = :blueprintVersion AND artifact_name = :artifactName
+ AND occurrence > (
+ select max(occurrence) - :lastN from RESOURCE_RESOLUTION
+ WHERE resource_id = :resourceId
+ AND resource_type =:resourceType AND blueprint_name = :blueprintName
+ AND blueprint_version = :blueprintVersion AND artifact_name = :artifactName)
+ ORDER BY occurrence DESC, creation_date DESC
+ """,
+ nativeQuery = true
+ )
+ fun findLastNOccurrences(
+ @Param("resourceId")resourceId: String,
+ @Param("resourceType")resourceType: String,
+ @Param("blueprintName")blueprintName: String,
+ @Param("blueprintVersion")blueprintVersion: String,
+ @Param("artifactName")artifactName: String,
+ @Param("lastN")begin: Int
+ ): List<ResourceResolution>
+
+ @Query(
+ value = """
SELECT * FROM RESOURCE_RESOLUTION WHERE resolution_key = :key
AND blueprint_name = :blueprintName AND blueprint_version = :blueprintVersion
AND artifact_name = :artifactName AND occurrence BETWEEN :begin AND :end
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 a801a7eb9..b39e709d0 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
@@ -249,6 +249,116 @@ class ResourceResolutionServiceTest {
}
/**
+ * Always perform new resolution even if resolution exists in the database.
+ */
+ @Test
+ @Throws(Exception::class)
+ fun testResolveResourcesForMaxOccurrence() {
+ runBlocking {
+ // Occurrence <= 0 indicates to perform new resolution even if resolution exists in the database.
+ props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = -1
+ Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
+
+ // Run time for Request#1
+ val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(
+ "1234",
+ "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration"
+ )
+
+ // Request#1
+ val executionServiceInput =
+ JacksonUtils.readValueFromClassPathFile(
+ "payload/requests/sample-resourceresolution-request.json",
+ ExecutionServiceInput::class.java
+ )!!
+
+ // Prepare inputs from Request#1
+ PayloadUtils.prepareInputsFromWorkflowPayload(
+ bluePrintRuntimeService,
+ executionServiceInput.payload,
+ "resource-assignment"
+ )
+
+ val resourceAssignmentRuntimeService =
+ ResourceAssignmentUtils.transformToRARuntimeService(
+ bluePrintRuntimeService,
+ "testResolveResource"
+ )
+
+ // Resolve resources as per Request#1
+ resourceResolutionService.resolveResources(
+ resourceAssignmentRuntimeService,
+ "resource-assignment",
+ "maxoccurrence",
+ props
+ )
+
+ // Run time for Request#2
+ val bluePrintRuntimeService2 = BluePrintMetadataUtils.getBluePrintRuntime(
+ "1234",
+ "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration"
+ )
+
+ // Request#2
+ val executionServiceInput2 =
+ JacksonUtils.readValueFromClassPathFile(
+ "payload/requests/sample-resourceresolution-request2.json",
+ ExecutionServiceInput::class.java
+ )!!
+
+ val resourceAssignmentRuntimeService2 =
+ ResourceAssignmentUtils.transformToRARuntimeService(
+ bluePrintRuntimeService2,
+ "testResolveResource"
+ )
+
+ // Prepare inputs from Request#2
+ PayloadUtils.prepareInputsFromWorkflowPayload(
+ bluePrintRuntimeService2,
+ executionServiceInput2.payload,
+ "resource-assignment"
+ )
+
+ // Resolve resources as per Request#2
+ resourceResolutionService.resolveResources(
+ resourceAssignmentRuntimeService2,
+ "resource-assignment",
+ "maxoccurrence",
+ props
+ )
+ }.let { (template, assignmentList) ->
+ assertEquals("This is maxoccurrence Velocity Template", template)
+
+ val assignmentListForRequest1 = mutableListOf(
+ "firmware-version" to "firmware-version-0",
+ "ip-address" to "192.0.0.1"
+ )
+ val assignmentListForRequest2 = mutableListOf(
+ "firmware-version" to "firmware-version-1",
+ "ip-address" to "192.0.0.1"
+ )
+ assertEquals(assignmentListForRequest1.size, assignmentList.size)
+ assertEquals(assignmentListForRequest2.size, assignmentList.size)
+
+ // firmware-version has max-occurrence = 0 means perform new resolution all the time.
+ // ip-address has max-occurrence = 1 so its resolution should only be done once.
+ //
+ // AlwaysPerformNewResolution + max-occurrence feature use case - resolution request #2 should returns
+ // the resolution as per assignmentListForRequest2 since new resolution is only performed for
+ // firmware-version and not for ip-address.
+ var areEqual = assignmentListForRequest1.zip(assignmentList).all { (it1, it2) ->
+ it1.first == it2.name && it1.second == it2.property?.value?.asText() ?: null
+ }
+ assertEquals(false, areEqual)
+
+ areEqual = assignmentListForRequest2.zip(assignmentList).all { (it1, it2) ->
+ it1.first == it2.name && it1.second == it2.property?.value?.asText() ?: null
+ }
+ assertEquals(true, areEqual)
+ }
+ }
+
+ /**
* Don't perform new resolution in case resolution already exists in the database.
*/
@Test
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request.json b/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request.json
index 3ca754f87..e247ea248 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request.json
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request.json
@@ -25,7 +25,10 @@
"action-name": "assign-activate",
"scope-type": "vnf-type",
"hostname": "localhost",
- "vnf_name": "temp_vnf"
+ "vnf_name": "temp_vnf",
+ "firmware-version": "firmware-version-0",
+ "ip-address": "192.0.0.1"
+
}
}
}
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request2.json b/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request2.json
index 726477515..17f5aad52 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request2.json
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request2.json
@@ -24,7 +24,9 @@
"action-name": "assign-activate",
"scope-type": "vnf-type",
"hostname": "localhost",
- "vnf_name": "temp_vnf_new_resolution"
+ "vnf_name": "temp_vnf_new_resolution",
+ "firmware-version": "firmware-version-1",
+ "ip-address": "192.0.0.2"
}
}
}
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 2e7e18258..f92548612 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
@@ -62,6 +62,9 @@ open class ResourceAssignment {
@JsonProperty(value = "property")
var property: PropertyDefinition? = null
+ @JsonProperty(value = "max-occurrence")
+ var maxOccurrence: Int? = null
+
@JsonProperty("input-param")
var inputParameter: Boolean = false