summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json7
-rw-r--r--components/model-catalog/proto-definition/proto/BluePrintManagement.proto8
-rw-r--r--ms/blueprintsprocessor/application/src/main/resources/sql/schema.sql1
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt14
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt1
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt86
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt139
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt104
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt189
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt78
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request2.json31
-rwxr-xr-xms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/domain/BlueprintModel.kt23
-rw-r--r--ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/repository/BlueprintModelRepository.kt10
-rw-r--r--ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintCatalogServiceImpl.kt6
-rwxr-xr-xms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintProcessorCatalogServiceImpl.kt8
-rw-r--r--ms/blueprintsprocessor/modules/commons/db-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BlueprintProcessorCatalogServiceImplTest.kt11
-rw-r--r--ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt17
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt30
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt9
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt112
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt67
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt3
22 files changed, 866 insertions, 88 deletions
diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json b/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json
index cc2013076..853fe563e 100644
--- a/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json
+++ b/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json
@@ -39,6 +39,11 @@
"required": false,
"type": "boolean"
},
+ "force-resolution": {
+ "description": "Delete existing values to force new resolution. Ineffective when occurrence < 1",
+ "required": false,
+ "type": "boolean"
+ },
"resource-type": {
"description": "Request type.",
"required": false,
@@ -97,4 +102,4 @@
}
},
"derived_from": "tosca.nodes.Component"
-} \ No newline at end of file
+}
diff --git a/components/model-catalog/proto-definition/proto/BluePrintManagement.proto b/components/model-catalog/proto-definition/proto/BluePrintManagement.proto
index a363e8ade..ee8bd2540 100644
--- a/components/model-catalog/proto-definition/proto/BluePrintManagement.proto
+++ b/components/model-catalog/proto-definition/proto/BluePrintManagement.proto
@@ -42,6 +42,13 @@ message BluePrintManagementOutput {
google.protobuf.Struct properties = 4;
}
+// Get the list of workflows available for a given blueprintName/Version
+message BluePrintGetWorkflowsInput {
+ org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader commonHeader = 1;
+ string blueprintName = 2;
+ string blueprintVersion = 3;
+}
+
message FileChunk {
bytes chunk = 1;
}
@@ -73,4 +80,5 @@ service BluePrintManagementService {
rpc uploadBlueprint (BluePrintUploadInput) returns (BluePrintManagementOutput);
rpc removeBlueprint (BluePrintRemoveInput) returns (BluePrintManagementOutput);
rpc bootstrapBlueprint (BluePrintBootstrapInput) returns (BluePrintManagementOutput);
+ rpc getWorkflows(BluePrintGetWorkflowsInput) returns (BluePrintManagementOutput);
}
diff --git a/ms/blueprintsprocessor/application/src/main/resources/sql/schema.sql b/ms/blueprintsprocessor/application/src/main/resources/sql/schema.sql
index 851adcf6c..84cce281e 100644
--- a/ms/blueprintsprocessor/application/src/main/resources/sql/schema.sql
+++ b/ms/blueprintsprocessor/application/src/main/resources/sql/schema.sql
@@ -22,6 +22,7 @@ CREATE TABLE IF NOT EXISTS configurator.BLUEPRINT_MODEL (
published varchar(1) not null,
updated_by varchar(100) not null,
tags longtext null default null,
+ workflows longtext null default null,
primary key PK_BLUEPRINT_MODEL (blueprint_model_id),
UNIQUE KEY UK_BLUEPRINT_MODEL (artifact_name , artifact_version)
) ENGINE=InnoDB;
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 0435d1d2c..d46f75e41 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
@@ -63,6 +63,7 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
val resolutionKey =
getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY)?.returnNullIfMissing()?.textValue() ?: ""
val storeResult = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT)?.asBoolean() ?: false
+ val forceResolution = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_FORCE_RESOLUTION)?.asBoolean() ?: false
val resourceId =
getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID)?.returnNullIfMissing()?.textValue() ?: ""
@@ -73,6 +74,7 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
val properties: MutableMap<String, Any> = mutableMapOf()
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = storeResult
+ properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_FORCE_RESOLUTION] = forceResolution
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType
@@ -107,9 +109,13 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
val artifactPrefixNamesNode = getOperationInput(ResourceResolutionConstants.INPUT_ARTIFACT_PREFIX_NAMES)
val artifactPrefixNames = JacksonUtils.getListFromJsonNode(artifactPrefixNamesNode, String::class.java)
+ val alwaysPerformNewResolution = occurrence <= 0
+ val resolutionsToPerform: Int = if (alwaysPerformNewResolution) 1 else occurrence
+ for (j in 1..resolutionsToPerform) {
- for (j in 1..occurrence) {
- properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = j
+ if (!alwaysPerformNewResolution) {
+ properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = j
+ }
val result = resourceResolutionService.resolveResources(
bluePrintRuntimeService,
@@ -119,8 +125,8 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
stepName
)
- // provide indexed result in output if we have multiple resolution
- if (occurrence != 1) {
+ // provide indexed result in output if we have multiple resolution.
+ if (resolutionsToPerform != 1) {
jsonResponse.set<JsonNode>(j.toString(), result.templateMap.asJsonNode())
assignmentMap.set<JsonNode>(j.toString(), result.assignmentMap.asJsonNode())
} else {
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 e2a8920f5..9f22b8134 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
@@ -27,6 +27,7 @@ object ResourceResolutionConstants {
const val FILE_NAME_RESOURCE_DEFINITION_TYPES = "resources_definition_types.json"
const val RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY = "resolution-key"
const val RESOURCE_RESOLUTION_INPUT_STORE_RESULT = "store-result"
+ const val RESOURCE_RESOLUTION_INPUT_FORCE_RESOLUTION = "force-resolution"
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"
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 df07b8e03..a3c137807 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
@@ -199,7 +199,9 @@ open class ResourceResolutionServiceImpl(
val artifactTemplate = "$artifactPrefix-template"
// Resource Assignment Artifact Definition Name
val artifactMapping = "$artifactPrefix-mapping"
+ val forceResolution = isForceResolution(properties)
+ val propertiesMutableMap = properties.toMutableMap()
log.info("Resolving resource with resource assignment artifact($artifactMapping)")
val resourceAssignmentContent =
@@ -211,12 +213,27 @@ open class ResourceResolutionServiceImpl(
?: throw BluePrintProcessorException("couldn't get Dictionary Definitions")
if (isToStore(properties)) {
- val existingResourceResolution = isNewResolution(bluePrintRuntimeService, properties, artifactPrefix)
+ val alwaysPerformNewResolution = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] as Int <= 0
+ val existingResourceResolution = if (alwaysPerformNewResolution) {
+ 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.
+ emptyList()
+ } else {
+ isNewResolution(bluePrintRuntimeService, properties, artifactPrefix)
+ }
if (existingResourceResolution.isNotEmpty()) {
- updateResourceAssignmentWithExisting(
- bluePrintRuntimeService as ResourceAssignmentRuntimeService,
- existingResourceResolution, resourceAssignments
- )
+ if (forceResolution) {
+ resourceResolutionDBService.deleteResourceResolutionList(existingResourceResolution)
+ log.info("Force resolution is enabled - will resolve all resources.")
+ } else {
+ updateResourceAssignmentWithExisting(
+ bluePrintRuntimeService as ResourceAssignmentRuntimeService,
+ existingResourceResolution, resourceAssignments
+ )
+ log.info("Force resolution is disabled - will resolve all resources not already resolved.")
+ }
}
}
@@ -230,7 +247,7 @@ open class ResourceResolutionServiceImpl(
resourceDefinitions,
resourceAssignments,
artifactPrefix,
- properties
+ propertiesMutableMap
)
val resolutionSummary = properties.getOrDefault(
@@ -264,7 +281,7 @@ open class ResourceResolutionServiceImpl(
}
if (isToStore(properties)) {
- templateResolutionDBService.write(properties, resolvedContent, bluePrintRuntimeService, artifactPrefix)
+ templateResolutionDBService.write(propertiesMutableMap, resolvedContent, bluePrintRuntimeService, artifactPrefix)
log.info("Template resolution saved into database successfully : ($properties)")
}
@@ -407,6 +424,10 @@ open class ResourceResolutionServiceImpl(
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean
}
+ private fun isForceResolution(properties: Map<String, Any>): Boolean =
+ properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_FORCE_RESOLUTION) &&
+ properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_FORCE_RESOLUTION] as Boolean
+
// Check whether resolution already exist in the database for the specified resolution-key or resourceId/resourceType
private suspend fun isNewResolution(
bluePrintRuntimeService: BluePrintRuntimeService<*>,
@@ -428,7 +449,7 @@ open class ResourceResolutionServiceImpl(
)
if (existingResourceAssignments.isNotEmpty()) {
log.info(
- "Resolution with resolutionKey=($resolutionKey) already exist - will resolve all resources not already resolved.",
+ "Resolution with resolutionKey=($resolutionKey) already exist",
resolutionKey
)
}
@@ -445,8 +466,7 @@ open class ResourceResolutionServiceImpl(
)
if (existingResourceAssignments.isNotEmpty()) {
log.info(
- "Resolution with resourceId=($resourceId) and resourceType=($resourceType) already " +
- "exist - will resolve all resources not already resolved."
+ "Resolution with resourceId=($resourceId) and resourceType=($resourceType) already exist"
)
}
return existingResourceAssignments
@@ -480,7 +500,7 @@ open class ResourceResolutionServiceImpl(
}
}
- // Comparision between what we have in the database vs what we have to assign.
+ // Comparison between what we have in the database vs what we have to assign.
private fun compareOne(resourceResolution: ResourceResolution, resourceAssignment: ResourceAssignment): Boolean {
return (
resourceResolution.name == resourceAssignment.name &&
@@ -499,4 +519,48 @@ open class ResourceResolutionServiceImpl(
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE].asJsonPrimitive()
)
}
+
+ /**
+ * This method returns 'occurrence' required to persist new resource resolution.
+ *
+ * @param bluePrintRuntimeService
+ * @param properties
+ * @param artifactPrefix
+ */
+ private suspend fun findNextOccurrence(
+ bluePrintRuntimeService: BluePrintRuntimeService<*>,
+ properties: Map<String, Any>,
+ artifactPrefix: String
+ ): Int {
+ val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+ val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
+ val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
+ 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 next occurrence: " +
+ "Either provide a resolution-key OR combination of resource-id and resource-type"
+ )
+ }
+
+ if (resolutionKey.isNotEmpty()) {
+ return resourceResolutionDBService.findNextOccurrenceByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+ resolutionKey,
+ blueprintName,
+ blueprintVersion,
+ artifactPrefix
+ )
+ } else {
+ return resourceResolutionDBService.findNextOccurrenceByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
+ blueprintName,
+ blueprintVersion,
+ resourceId,
+ resourceType
+ )
+ }
+ }
}
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 5958c7899..ed9e6d1d6 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
@@ -90,7 +90,7 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
artifactPrefix: String,
resolutionKey: String,
name: String
- ): ResourceResolution = withContext(Dispatchers.IO) {
+ ): ResourceResolution? = withContext(Dispatchers.IO) {
resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndName(
resolutionKey,
@@ -116,6 +116,87 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
)
}
+ /**
+ * This returns the resolutions of first N 'occurrences'.
+ *
+ * @param blueprintName
+ * @param blueprintVersion
+ * @param artifactPrefix
+ * @param resolutionKey
+ * @param firstN
+ */
+ suspend fun findFirstNOccurrences(
+ blueprintName: String,
+ blueprintVersion: String,
+ artifactPrefix: String,
+ resolutionKey: String,
+ firstN: Int
+ ): Map<Int, List<ResourceResolution>> = withContext(Dispatchers.IO) {
+
+ resourceResolutionRepository.findFirstNOccurrences(
+ resolutionKey,
+ blueprintName,
+ blueprintVersion,
+ artifactPrefix,
+ firstN
+ ).groupBy(ResourceResolution::occurrence).toSortedMap(reverseOrder())
+ }
+
+ /**
+ * This returns the resolutions of last N 'occurrences'.
+ *
+ * @param blueprintName
+ * @param blueprintVersion
+ * @param artifactPrefix
+ * @param resolutionKey
+ * @param lastN
+ */
+ suspend fun findLastNOccurrences(
+ blueprintName: String,
+ blueprintVersion: String,
+ artifactPrefix: String,
+ resolutionKey: String,
+ lastN: Int
+ ): Map<Int, List<ResourceResolution>> = withContext(Dispatchers.IO) {
+
+ resourceResolutionRepository.findLastNOccurrences(
+ resolutionKey,
+ blueprintName,
+ blueprintVersion,
+ artifactPrefix,
+ lastN
+ ).groupBy(ResourceResolution::occurrence).toSortedMap(reverseOrder())
+ }
+
+ /**
+ * This returns the resolutions with 'occurrence' value between begin and end.
+ *
+ * @param blueprintName
+ * @param blueprintVersion
+ * @param artifactPrefix
+ * @param resolutionKey
+ * @param begin
+ * @param end
+ */
+ suspend fun findOccurrencesWithinRange(
+ blueprintName: String,
+ blueprintVersion: String,
+ artifactPrefix: String,
+ resolutionKey: String,
+ begin: Int,
+ end: Int
+ ): Map<Int, List<ResourceResolution>> = withContext(Dispatchers.IO) {
+
+ resourceResolutionRepository.findOccurrencesWithinRange(
+ resolutionKey,
+ blueprintName,
+ blueprintVersion,
+ artifactPrefix,
+ begin,
+ end
+ ).groupBy(ResourceResolution::occurrence).toSortedMap(reverseOrder())
+ }
+
suspend fun readWithResourceIdAndResourceType(
blueprintName: String,
blueprintVersion: String,
@@ -221,4 +302,60 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
resolutionKey
)
}
+
+ suspend fun deleteResourceResolutionList(listResourceResolution: List<ResourceResolution>) = withContext(Dispatchers.IO) {
+ try {
+ resourceResolutionRepository.deleteInBatch(listResourceResolution)
+ } catch (ex: Exception) {
+ throw BluePrintException("Failed to batch delete resource resolution", ex)
+ }
+ }
+
+ /**
+ * This method returns the (highest occurrence + 1) of resource resolutions if present in DB, returns 1 otherwise.
+ * The 'occurrence' is used to persist new resource resolution in the DB.
+ *
+ * @param resolutionKey
+ * @param blueprintName
+ * @param blueprintVersion
+ * @param artifactPrefix
+ */
+ suspend fun findNextOccurrenceByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+ resolutionKey: String,
+ blueprintName: String,
+ blueprintVersion: String,
+ artifactPrefix: String
+ ) = withContext(Dispatchers.IO) {
+ val maxOccurrence = resourceResolutionRepository.findMaxOccurrenceByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+ resolutionKey,
+ blueprintName,
+ blueprintVersion,
+ artifactPrefix
+ )
+ maxOccurrence?.inc() ?: 1
+ }
+
+ /**
+ * This method returns the (highest occurrence + 1) of resource resolutions if present in DB, returns 1 otherwise.
+ * The 'occurrence' is used to persist new resource resolution in the DB.
+ *
+ * @param blueprintName
+ * @param blueprintVersion
+ * @param resourceId
+ * @param resourceType
+ */
+ suspend fun findNextOccurrenceByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
+ blueprintName: String,
+ blueprintVersion: String,
+ resourceId: String,
+ resourceType: String
+ ) = withContext(Dispatchers.IO) {
+ val maxOccurrence = resourceResolutionRepository.findMaxOccurrenceByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
+ blueprintName,
+ blueprintVersion,
+ resourceId,
+ resourceType
+ )
+ maxOccurrence?.inc() ?: 1
+ }
}
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 c2d630e5e..4b707b04e 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
@@ -16,19 +16,111 @@
package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db
import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.data.jpa.repository.Query
+import org.springframework.data.repository.query.Param
import org.springframework.stereotype.Repository
import javax.transaction.Transactional
@Repository
interface ResourceResolutionRepository : JpaRepository<ResourceResolution, String> {
+ @Query(
+ value = "SELECT * FROM RESOURCE_RESOLUTION WHERE resolution_key = :key AND blueprint_name = :blueprintName AND blueprint_version = :blueprintVersion AND artifact_name = :artifactName AND name = :name ORDER BY occurrence DESC, creation_date DESC LIMIT 1",
+ nativeQuery = true
+ )
fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndName(
- key: String,
- blueprintName: String?,
- blueprintVersion: String?,
- artifactName: String,
- name: String
- ): ResourceResolution
+ @Param("key")key: String,
+ @Param("blueprintName")blueprintName: String,
+ @Param("blueprintVersion")blueprintVersion: String,
+ @Param("artifactName")artifactName: String,
+ @Param("name")name: String
+ ): 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 <= :firstN
+ """,
+ nativeQuery = true
+ )
+ fun findFirstNOccurrences(
+ @Param("key")key: String,
+ @Param("blueprintName")blueprintName: String,
+ @Param("blueprintVersion")blueprintVersion: String,
+ @Param("artifactName")artifactName: String,
+ @Param("firstN")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 > (
+ select max(occurrence) - :lastN from RESOURCE_RESOLUTION
+ WHERE resolution_key = :key AND blueprint_name = :blueprintName
+ AND blueprint_version = :blueprintVersion AND artifact_name = :artifactName
+ )
+ ORDER BY occurrence DESC, creation_date DESC
+ """,
+ nativeQuery = true
+ )
+ fun findLastNOccurrences(
+ @Param("key")key: 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
+ ORDER BY occurrence DESC, creation_date DESC
+ """,
+ nativeQuery = true
+ )
+ fun findOccurrencesWithinRange(
+ @Param("key")key: String,
+ @Param("blueprintName")blueprintName: String,
+ @Param("blueprintVersion")blueprintVersion: String,
+ @Param("artifactName")artifactName: String,
+ @Param("begin")begin: Int,
+ @Param("end")end: Int
+ ): List<ResourceResolution>
+
+ @Query(
+ value = """
+ SELECT max(occurrence) FROM RESOURCE_RESOLUTION WHERE resolution_key = :key
+ AND blueprint_name = :blueprintName AND blueprint_version = :blueprintVersion
+ AND artifact_name = :artifactName
+ """,
+ nativeQuery = true
+ )
+ fun findMaxOccurrenceByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+ @Param("key")key: String,
+ @Param("blueprintName")blueprintName: String,
+ @Param("blueprintVersion")blueprintVersion: String,
+ @Param("artifactName")artifactName: String
+ ): Int?
+
+ @Query(
+ value = """
+ SELECT max(occurrence) FROM RESOURCE_RESOLUTION WHERE blueprint_name = :blueprintName
+ AND blueprint_version = :blueprintVersion AND resource_id = :resourceId
+ AND resource_type = :resourceType
+ """,
+ nativeQuery = true
+ )
+ fun findMaxOccurrenceByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
+ @Param("blueprintName")blueprintName: String,
+ @Param("blueprintVersion")blueprintVersion: String,
+ @Param("resourceId")resourceId: String,
+ @Param("resourceType")resourceType: String
+ ): Int?
fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
resolutionKey: String,
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 3d2a9755c..a801a7eb9 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
@@ -153,6 +153,195 @@ class ResourceResolutionServiceTest {
}
}
+ /**
+ * Always perform new resolution even if resolution exists in the database.
+ */
+ @Test
+ @Throws(Exception::class)
+ fun testResolveResourceAlwaysPerformNewResolution() {
+ 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)
+
+ 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
+ )!!
+
+ val resourceAssignmentRuntimeService =
+ ResourceAssignmentUtils.transformToRARuntimeService(
+ bluePrintRuntimeService,
+ "testResolveResource"
+ )
+
+ // Prepare inputs from Request#1
+ PayloadUtils.prepareInputsFromWorkflowPayload(
+ bluePrintRuntimeService,
+ executionServiceInput.payload,
+ "resource-assignment"
+ )
+
+ // Resolve resources as per Request#1
+ resourceResolutionService.resolveResources(
+ resourceAssignmentRuntimeService,
+ "resource-assignment",
+ "baseconfig",
+ props
+ )
+
+ // Request#2
+ val executionServiceInput2 =
+ JacksonUtils.readValueFromClassPathFile(
+ "payload/requests/sample-resourceresolution-request2.json",
+ ExecutionServiceInput::class.java
+ )!!
+
+ // Prepare inputs from Request#2
+ PayloadUtils.prepareInputsFromWorkflowPayload(
+ bluePrintRuntimeService,
+ executionServiceInput2.payload,
+ "resource-assignment"
+ )
+
+ // Resolve resources as per Request#2
+ resourceResolutionService.resolveResources(
+ resourceAssignmentRuntimeService,
+ "resource-assignment",
+ "baseconfig",
+ props
+ )
+ }.let { (templateMap, assignmentList) ->
+ assertEquals("This is Sample Velocity Template", templateMap)
+
+ val assignmentListForRequest1 = mutableListOf(
+ "service-instance-id" to "siid_1234",
+ "vnf-id" to "vnf_1234",
+ "vnf_name" to "temp_vnf"
+ )
+ val assignmentListForRequest2 = mutableListOf(
+ "service-instance-id" to "siid_new_resolution",
+ "vnf-id" to "vnf_new_resolution",
+ "vnf_name" to "temp_vnf_new_resolution"
+ )
+ assertEquals(assignmentListForRequest1.size, assignmentList.size)
+ assertEquals(assignmentListForRequest2.size, assignmentList.size)
+
+ // AlwaysPerformNewResolution use case - resolution request #2 should returns the resolution as per
+ // assignmentListForRequest2 since new resolution is performed.
+ 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
+ @Throws(Exception::class)
+ fun testResolveResourceNoNewResolution() {
+ runBlocking {
+ // Occurrence > 0 indicates to not perform new resolution if resolution exists in the database.
+ props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = 1
+ Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
+
+ 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
+ )!!
+
+ val resourceAssignmentRuntimeService =
+ ResourceAssignmentUtils.transformToRARuntimeService(
+ bluePrintRuntimeService,
+ "testResolveResource"
+ )
+
+ // Prepare inputs from Request#1
+ PayloadUtils.prepareInputsFromWorkflowPayload(
+ bluePrintRuntimeService,
+ executionServiceInput.payload,
+ "resource-assignment"
+ )
+ // Resolve resources as per Request#1
+ resourceResolutionService.resolveResources(
+ resourceAssignmentRuntimeService,
+ "resource-assignment",
+ "baseconfig",
+ props
+ )
+
+ // Request#2
+ val executionServiceInput2 =
+ JacksonUtils.readValueFromClassPathFile(
+ "payload/requests/sample-resourceresolution-request2.json",
+ ExecutionServiceInput::class.java
+ )!!
+
+ // Prepare inputs from Request#2
+ PayloadUtils.prepareInputsFromWorkflowPayload(
+ bluePrintRuntimeService,
+ executionServiceInput2.payload,
+ "resource-assignment"
+ )
+
+ // Resolve resources as per Request#2
+ resourceResolutionService.resolveResources(
+ resourceAssignmentRuntimeService,
+ "resource-assignment",
+ "baseconfig",
+ props
+ )
+ }.let { (templateMap, assignmentList) ->
+ assertEquals("This is Sample Velocity Template", templateMap)
+
+ val assignmentListForRequest1 = mutableListOf(
+ "service-instance-id" to "siid_1234",
+ "vnf-id" to "vnf_1234",
+ "vnf_name" to "temp_vnf"
+ )
+ val assignmentListForRequest2 = mutableListOf(
+ "service-instance-id" to "siid_new_resolution",
+ "vnf-id" to "vnf_new_resolution",
+ "vnf_name" to "temp_vnf_new_resolution"
+ )
+ assertEquals(assignmentListForRequest1.size, assignmentList.size)
+ assertEquals(assignmentListForRequest2.size, assignmentList.size)
+
+ // NoNewResolution use case - resolution for request #2 returns the same resolution as
+ // assignmentListForRequest1 since no new resolution is/was actually performed.
+ var areEqual = assignmentListForRequest1.zip(assignmentList).all { (it1, it2) ->
+ it1.first == it2.name && it1.second == it2.property?.value?.asText() ?: null
+ }
+ assertEquals(true, areEqual)
+
+ areEqual = assignmentListForRequest2.zip(assignmentList).all { (it1, it2) ->
+ it1.first == it2.name && it1.second == it2.property?.value?.asText() ?: null
+ }
+ assertEquals(false, areEqual)
+ }
+ }
+
@Test
@Throws(Exception::class)
fun testResolveResources() {
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt
index fa59876a9..8d4109fcf 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt
@@ -30,6 +30,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRunt
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
import org.springframework.dao.EmptyResultDataAccessException
import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
open class ResourceResolutionDBServiceTest {
@@ -158,9 +159,11 @@ open class ResourceResolutionDBServiceTest {
resourceResolutionDBService.readValue(
blueprintName, blueprintVersion, artifactPrefix, resolutionKey, "bob"
)
-
- assertEquals(rr.name, res.name)
- assertEquals(rr.value, res.value)
+ assertNotEquals(res, null, "resource resolution failed")
+ if (res != null) {
+ assertEquals(rr.name, res.name)
+ assertEquals(rr.value, res.value)
+ }
}
}
@@ -184,6 +187,75 @@ open class ResourceResolutionDBServiceTest {
}
@Test
+ fun findFirstNOccurrencesTest() {
+ props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
+ val rr1 = ResourceResolution()
+ val rr2 = ResourceResolution()
+ val list = listOf(rr1, rr2)
+ every {
+ resourceResolutionRepository.findFirstNOccurrences(
+ any(), any(), any(), any(), 1
+ )
+ } returns list
+ runBlocking {
+ val res =
+ resourceResolutionDBService.findFirstNOccurrences(
+ blueprintName, blueprintVersion, artifactPrefix, resolutionKey, 1
+ )
+ assertEquals(false, res.isEmpty(), "find first N occurrences test failed")
+ assertEquals(1, res.size)
+ assertNotEquals(null, res[0])
+ res[0]?.let { assertEquals(2, it.size) }
+ }
+ }
+
+ @Test
+ fun findLastNOccurrencesTest() {
+ props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
+ val rr1 = ResourceResolution()
+ val rr2 = ResourceResolution()
+ val list = listOf(rr1, rr2)
+ every {
+ resourceResolutionRepository.findLastNOccurrences(
+ any(), any(), any(), any(), 1
+ )
+ } returns list
+ runBlocking {
+ val res =
+ resourceResolutionDBService.findLastNOccurrences(
+ blueprintName, blueprintVersion, artifactPrefix, resolutionKey, 1
+ )
+ assertEquals(false, res.isEmpty(), "find last N occurrences test failed")
+ assertEquals(1, res.size)
+ assertNotEquals(null, res[0])
+ res[0]?.let { assertEquals(2, it.size) }
+ }
+ }
+
+ @Test
+ fun findOccurrencesWithinRangeTest() {
+ props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
+ val rr1 = ResourceResolution()
+ val rr2 = ResourceResolution()
+ val list = listOf(rr1, rr2)
+ every {
+ resourceResolutionRepository.findOccurrencesWithinRange(
+ any(), any(), any(), any(), 0, 1
+ )
+ } returns list
+ runBlocking {
+ val res =
+ resourceResolutionDBService.findOccurrencesWithinRange(
+ blueprintName, blueprintVersion, artifactPrefix, resolutionKey, 0, 1
+ )
+ assertEquals(false, res.isEmpty(), "find occurrences within a range test failed")
+ assertEquals(1, res.size)
+ assertNotEquals(null, res[0])
+ res[0]?.let { assertEquals(2, it.size) }
+ }
+ }
+
+ @Test
fun readWithResourceIdAndResourceTypeTest() {
val rr1 = ResourceResolution()
val rr2 = ResourceResolution()
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
new file mode 100644
index 000000000..726477515
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/payload/requests/sample-resourceresolution-request2.json
@@ -0,0 +1,31 @@
+{
+ "actionIdentifiers": {
+ "actionName": "sample-action",
+ "blueprintName": "sample-blueprint",
+ "blueprintVersion": "1.0.0",
+ "mode": "sync"
+ },
+ "commonHeader": {
+ "flags": {
+ "isForce": true,
+ "ttl": 3600
+ },
+ "originatorId": "unit_tests",
+ "requestId": "123456-1001",
+ "subRequestId": "sub-123456-1001"
+ },
+ "payload": {
+ "resource-assignment-request": {
+ "resource-assignment-properties": {
+ "request-id": "1234",
+ "profile_name": "1.0.0",
+ "service-instance-id": "siid_new_resolution",
+ "vnf-id": "vnf_new_resolution",
+ "action-name": "assign-activate",
+ "scope-type": "vnf-type",
+ "hostname": "localhost",
+ "vnf_name": "temp_vnf_new_resolution"
+ }
+ }
+ }
+}
diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/domain/BlueprintModel.kt b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/domain/BlueprintModel.kt
index 9f4d32e7a..1feac8cd2 100755
--- a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/domain/BlueprintModel.kt
+++ b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/domain/BlueprintModel.kt
@@ -19,12 +19,17 @@ package org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain
import com.fasterxml.jackson.annotation.JsonFormat
import io.swagger.annotations.ApiModelProperty
import org.hibernate.annotations.Proxy
+import org.onap.ccsdk.cds.controllerblueprints.core.data.Workflow
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.io.Serializable
import java.util.Date
+import javax.persistence.AttributeConverter
import javax.persistence.CascadeType
import javax.persistence.Column
+import javax.persistence.Convert
+import javax.persistence.Converter
import javax.persistence.Entity
import javax.persistence.EntityListeners
import javax.persistence.FetchType
@@ -123,8 +128,26 @@ class BlueprintModel : Serializable {
@OneToOne(mappedBy = "blueprintModel", fetch = FetchType.EAGER, orphanRemoval = true, cascade = [CascadeType.ALL])
var blueprintModelContent: BlueprintModelContent? = null
+ // will be populated with workflow specs for each workflow (JSON object)
+ @Lob
+ @Convert(converter = WorkflowsConverter::class)
+ @Column(name = "workflows", nullable = false)
+ lateinit var workflows: Map<String, Workflow>
+
companion object {
private const val serialVersionUID = 1L
}
+
+ @Converter
+ class WorkflowsConverter : AttributeConverter<Map<String, Workflow>, String> {
+ override fun convertToDatabaseColumn(node: Map<String, Workflow>): String {
+ return JacksonUtils.getJson(node, true)
+ }
+
+ override fun convertToEntityAttribute(dbData: String): Map<String, Workflow> {
+ if (dbData == null || "".equals(dbData)) return emptyMap()
+ return JacksonUtils.getMapFromJson(dbData, Workflow::class.java)
+ }
+ }
}
diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/repository/BlueprintModelRepository.kt b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/repository/BlueprintModelRepository.kt
index a6f0da1cc..67869d11f 100644
--- a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/repository/BlueprintModelRepository.kt
+++ b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/repository/BlueprintModelRepository.kt
@@ -17,6 +17,7 @@
package org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository
+import com.fasterxml.jackson.databind.JsonNode
import org.jetbrains.annotations.NotNull
import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain.BlueprintModel
import org.springframework.data.jpa.repository.JpaRepository
@@ -60,6 +61,15 @@ interface BlueprintModelRepository : JpaRepository<BlueprintModel, String> {
fun findIdByArtifactNameAndArtifactVersion(@Param("artifactName") artifactName: String, @Param("artifactVersion") artifactVersion: String): String?
/**
+ * Find the workflows for a given blueprint name/version
+ * @param artifactName artifactName
+ * @param artifactVersion artifactVersion
+ * @return String?
+ */
+ @Query("SELECT m.workflows from BlueprintModel m WHERE m.artifactName = :artifactName AND m.artifactVersion = :artifactVersion")
+ fun findWorkflowsByArtifactNameAndArtifactVersion(@Param("artifactName") artifactName: String, @Param("artifactVersion") artifactVersion: String): JsonNode?
+
+ /**
* This is a findTopByArtifactNameOrderByArtifactIdDesc method
*
* @param artifactName artifactName
diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintCatalogServiceImpl.kt b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintCatalogServiceImpl.kt
index 9d1826395..06376346c 100644
--- a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintCatalogServiceImpl.kt
+++ b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintCatalogServiceImpl.kt
@@ -21,6 +21,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.db.primary.service
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
+import org.onap.ccsdk.cds.controllerblueprints.core.data.Workflow
import org.onap.ccsdk.cds.controllerblueprints.core.deCompress
import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintValidatorService
@@ -71,10 +72,11 @@ abstract class BlueprintCatalogServiceImpl(
val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(processingId, workingDir!!)
val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+ val workflows = bluePrintRuntimeService.bluePrintContext().workflows()!!
metadata[BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID] = processingId
metadata[BluePrintConstants.PROPERTY_BLUEPRINT_VALID] = valid
- save(metadata, archiveFile)
+ save(metadata, archiveFile, workflows)
return processingId
}
@@ -87,7 +89,7 @@ abstract class BlueprintCatalogServiceImpl(
override suspend fun deleteFromDatabase(name: String, version: String) = delete(name, version)
- abstract suspend fun save(metadata: MutableMap<String, String>, archiveFile: File)
+ abstract suspend fun save(metadata: MutableMap<String, String>, archiveFile: File, workflows: Map<String, Workflow>)
abstract suspend fun get(name: String, version: String, extract: Boolean): Path?
abstract suspend fun delete(name: String, version: String)
}
diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintProcessorCatalogServiceImpl.kt b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintProcessorCatalogServiceImpl.kt
index 9c007da31..c45a28a07 100755
--- a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintProcessorCatalogServiceImpl.kt
+++ b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/service/BlueprintProcessorCatalogServiceImpl.kt
@@ -29,6 +29,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants
import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
+import org.onap.ccsdk.cds.controllerblueprints.core.data.Workflow
import org.onap.ccsdk.cds.controllerblueprints.core.deCompress
import org.onap.ccsdk.cds.controllerblueprints.core.deleteNBDir
import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintValidatorService
@@ -120,7 +121,7 @@ class BlueprintProcessorCatalogServiceImpl(
}
}
- override suspend fun save(metadata: MutableMap<String, String>, archiveFile: File) {
+ override suspend fun save(metadata: MutableMap<String, String>, archiveFile: File, workflows: Map<String, Workflow>) {
val artifactName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]
val artifactVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]
@@ -152,9 +153,8 @@ class BlueprintProcessorCatalogServiceImpl(
blueprintModel.artifactVersion = artifactVersion
blueprintModel.updatedBy = metadata[BluePrintConstants.METADATA_TEMPLATE_AUTHOR]!!
blueprintModel.tags = metadata[BluePrintConstants.METADATA_TEMPLATE_TAGS]!!
- val description =
- if (null != metadata[BluePrintConstants.METADATA_TEMPLATE_DESCRIPTION]) metadata[BluePrintConstants.METADATA_TEMPLATE_DESCRIPTION] else ""
- blueprintModel.artifactDescription = description
+ blueprintModel.artifactDescription = "Controller Blueprint for $artifactName:$artifactVersion"
+ blueprintModel.workflows = workflows
val blueprintModelContent = BlueprintModelContent()
blueprintModelContent.id = metadata[BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID]
diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BlueprintProcessorCatalogServiceImplTest.kt b/ms/blueprintsprocessor/modules/commons/db-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BlueprintProcessorCatalogServiceImplTest.kt
index b7b1f78cf..5f1d09578 100644
--- a/ms/blueprintsprocessor/modules/commons/db-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BlueprintProcessorCatalogServiceImplTest.kt
+++ b/ms/blueprintsprocessor/modules/commons/db-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BlueprintProcessorCatalogServiceImplTest.kt
@@ -102,10 +102,11 @@ class BlueprintProcessorCatalogServiceImplTest {
runBlocking {
val file = normalizedFile("./target/blueprints/generated-cba.zip")
assertTrue(file.exists(), "couldnt get file ${file.absolutePath}")
- val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+ val ctx = bluePrintRuntimeService.bluePrintContext()
+ val metadata = ctx.metadata!!
metadata[BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID] = blueprintId
- blueprintsProcessorCatalogService.save(metadata, file)
+ blueprintsProcessorCatalogService.save(metadata, file, ctx.workflows()!!)
}
}
@@ -114,10 +115,12 @@ class BlueprintProcessorCatalogServiceImplTest {
runBlocking {
val file = normalizedFile("./target/blueprints/generated-cba.zip")
assertTrue(file.exists(), "couldnt get file ${file.absolutePath}")
- val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+
+ val ctx = bluePrintRuntimeService.bluePrintContext()
+ val metadata = ctx.metadata!!
metadata[BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID] = blueprintId
- blueprintsProcessorCatalogService.save(metadata, file)
+ blueprintsProcessorCatalogService.save(metadata, file, ctx.workflows()!!)
blueprintsProcessorCatalogService.get("baseconfiguration", "1.0.0", true)
}
diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt
index 611c0855d..b1d8abd16 100644
--- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt
+++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt
@@ -29,6 +29,7 @@ import kotlinx.coroutines.reactor.ReactorContext
import kotlinx.coroutines.reactor.asCoroutineContext
import kotlinx.coroutines.withContext
import org.apache.http.message.BasicHeader
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_INVOCATION_ID
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_ORIGINATOR_ID
@@ -107,8 +108,12 @@ class RestLoggerService {
}
}
-/** Used in Rest controller API methods to populate MDC context to nested coroutines from reactor web filter context. */
+/**
+ * Used in Rest controller API methods to populate MDC context to nested coroutines from reactor web filter context.
+ * @param executionServiceInput (Optional) Used to override values populated in the MDC Context
+ */
suspend fun <T> mdcWebCoroutineScope(
+ executionServiceInput: ExecutionServiceInput? = null,
block: suspend CoroutineScope.() -> T
) = coroutineScope {
val reactorContext = this.coroutineContext[ReactorContext]
@@ -118,12 +123,20 @@ suspend fun <T> mdcWebCoroutineScope(
!reactorContext.context.isEmpty &&
reactorContext.context.hasKey(MDCContext)
) {
- val mdcContext = reactorContext.context.get<MDCContext>(MDCContext)
+ val mdcContext = if (executionServiceInput != null) {
+ // MDC Context with overridden request ID
+ MDC.put("RequestID", executionServiceInput.commonHeader.requestId)
+ MDCContext(MDC.getCopyOfContextMap())
+ } else {
+ // Default MDC Context
+ reactorContext.context.get(MDCContext)
+ }
if (mdcContext != null)
newCoroutineContext(this.coroutineContext + reactorContext + mdcContext)
else
newCoroutineContext(this.coroutineContext + reactorContext)
} else this.coroutineContext
+
// Execute the block with new and old context
withContext(newContext) {
block()
diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt
index 54f8dbc9d..0dc0941c2 100644
--- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt
@@ -29,10 +29,12 @@ import org.onap.ccsdk.cds.controllerblueprints.common.api.Status
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
import org.onap.ccsdk.cds.controllerblueprints.core.emptyTONull
import org.onap.ccsdk.cds.controllerblueprints.core.utils.currentTimestamp
import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintBootstrapInput
import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintDownloadInput
+import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintGetWorkflowsInput
import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementOutput
import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementServiceGrpc
import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintRemoveInput
@@ -241,6 +243,33 @@ open class BluePrintManagementGRPCHandler(
}
}
+ @PreAuthorize("hasRole('USER')")
+ override fun getWorkflows(
+ request: BluePrintGetWorkflowsInput,
+ responseObserver: StreamObserver<BluePrintManagementOutput>
+ ) {
+ runBlocking {
+ val blueprintName = request.blueprintName
+ val blueprintVersion = request.blueprintVersion
+ val blueprint = "blueprint $blueprintName:$blueprintVersion"
+
+ log.info("request(${request.commonHeader.requestId}): Received getWorkflows $blueprint")
+ try {
+ val workflowsSetJson = bluePrintModelHandler.getWorkflowNamesFromRepository(blueprintName, blueprintVersion)
+ responseObserver.onNext(successStatus(request.commonHeader, mapOf("workflows" to workflowsSetJson).asJsonType().toString()))
+ } catch (e: Exception) {
+ responseObserver.onNext(
+ failStatus(
+ request.commonHeader,
+ "request(${request.commonHeader.requestId}): Failed to get workflows for ($blueprint)", e
+ )
+ )
+ } finally {
+ responseObserver.onCompleted()
+ }
+ }
+ }
+
private fun outputWithFileBytes(header: CommonHeader, byteArray: ByteArray): BluePrintManagementOutput =
BluePrintManagementOutput.newBuilder()
.setCommonHeader(header)
@@ -258,6 +287,7 @@ open class BluePrintManagementGRPCHandler(
private fun successStatus(header: CommonHeader, propertyContent: String? = null): BluePrintManagementOutput {
// Populate Response Payload
val propertiesBuilder = BluePrintManagementOutput.newBuilder().propertiesBuilder
+ // propertyContent is expected to have a string which contains a JSON map
propertyContent?.let {
JsonFormat.parser().merge(propertyContent, propertiesBuilder)
}
diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt
index 66d4b0e16..777a21457 100644
--- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt
@@ -393,10 +393,7 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
@PostMapping(
path = arrayOf("/workflow-spec"),
- produces = arrayOf(
- MediaType
- .APPLICATION_JSON_VALUE
- ),
+ produces = arrayOf(MediaType.APPLICATION_JSON_VALUE),
consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE)
)
@ApiOperation(
@@ -418,9 +415,7 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
}
@GetMapping(
- path = arrayOf(
- "/workflows/blueprint-name/{name}/version/{version}"
- ),
+ path = arrayOf("/workflows/blueprint-name/{name}/version/{version}"),
produces = arrayOf(MediaType.APPLICATION_JSON_VALUE)
)
@ApiOperation(
diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt
index 7bbaa8c59..a5fcd322c 100644
--- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt
@@ -39,6 +39,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType
import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
import org.onap.ccsdk.cds.controllerblueprints.core.deleteNBDir
import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.data.Workflow
import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintEnhancerService
import org.onap.ccsdk.cds.controllerblueprints.core.logger
@@ -107,42 +108,78 @@ open class BluePrintModelHandler(
}
@Throws(BluePrintException::class)
- open suspend fun prepareWorkFlowSpec(req: WorkFlowSpecRequest):
- WorkFlowSpecResponse {
- val basePath = blueprintsProcessorCatalogService.getFromDatabase(
- req
- .blueprintName,
- req.version
- )
- log.info("blueprint base path $basePath")
+ private suspend fun getBlueprintCtxByNameAndVersion(blueprintName: String, version: String): BluePrintContext {
+ val basePath = blueprintsProcessorCatalogService.getFromDatabase(blueprintName, version)
+ log.info("blueprint base path $basePath for blueprint: $blueprintName version:$version")
+ return BluePrintMetadataUtils.getBluePrintContext(basePath.toString())
+ }
+
+ @Throws(BluePrintException::class)
+ /**
+ * Try to get workflows cached from the BLUEPRINT_MODEL table first,
+ * failing that, load the CBA from the filesystem and extract workflows.
+ * The second case is possible during update scenario - current CDS DB already contains desired CBAs and reupload
+ * is not feasible.
+ */
+ open suspend fun getWorkflowsFromRepository(name: String, version: String): Map<String, Workflow> {
+ var workflowsFromCache: Map<String, Workflow>
+ try {
+ workflowsFromCache = blueprintModelRepository.findByArtifactNameAndArtifactVersion(name, version)?.workflows!!
+ if (workflowsFromCache.isEmpty()) {
+ log.info("findByArtifactNameAndArtifactVersion did not return list of workflows for blueprintName:($name) version:($version), falling back to loading CBA from filesystem.")
+ workflowsFromCache = getBlueprintCtxByNameAndVersion(name, version).workflows()!!
+ // TODO: does it make sense to update the BLUEPRINT_MODEL workflows in this case or just wait for CBA reupload?
+ }
+ } catch (e: Exception) {
+ throw BluePrintException("Failed to get workflows from DB cache or by reading CBA", e)
+ }
+ return workflowsFromCache
+ }
+
+ // lookup workflows list from field.
+ open suspend fun getWorkflowNamesFromRepository(name: String, version: String): Set<String> {
+ return getWorkflowsFromRepository(name, version).keys
+ }
- val blueprintContext = BluePrintMetadataUtils.getBluePrintContext(basePath.toString())
- val workFlow = blueprintContext.workflowByName(req.workflowName)
+ @Throws(BluePrintException::class)
+ open suspend fun prepareWorkFlowSpec(req: WorkFlowSpecRequest): WorkFlowSpecResponse {
+ val basePath = blueprintsProcessorCatalogService.getFromDatabase(req.blueprintName, req.version)
+ log.info("blueprint base path $basePath")
- val wfRes = WorkFlowSpecResponse()
- wfRes.blueprintName = req.blueprintName
- wfRes.version = req.version
+ val blueprintContext = BluePrintMetadataUtils.getBluePrintContext(basePath.toString())
+ val workFlow = blueprintContext.workflowByName(req.workflowName)
- val workFlowData = WorkFlowData()
- workFlowData.workFlowName = req.workflowName
- workFlowData.inputs = workFlow.inputs
- workFlowData.outputs = workFlow.outputs
- wfRes.workFlowData = workFlowData
+ val wfRes = WorkFlowSpecResponse()
+ wfRes.blueprintName = req.blueprintName
+ wfRes.version = req.version
- if (workFlow.inputs != null) {
- for ((k, v) in workFlow.inputs!!) {
- addPropertyInfo(k, v, blueprintContext, wfRes)
- }
+ val workFlowData = WorkFlowData()
+ workFlowData.workFlowName = req.workflowName
+ workFlowData.inputs = workFlow.inputs
+ workFlowData.outputs = workFlow.outputs
+
+ if (workFlow.inputs != null) {
+ for ((k, v) in workFlow.inputs!!) {
+ addPropertyInfo(v, blueprintContext, wfRes)
}
+ }
- if (workFlow.outputs != null) {
- for ((k, v) in workFlow.outputs!!) {
- addPropertyInfo(k, v, blueprintContext, wfRes)
- }
+ if (workFlow.outputs != null) {
+ for ((k, v) in workFlow.outputs!!) {
+ addPropertyInfo(k, v, blueprintContext, wfRes)
}
+ }
- return wfRes
+ wfRes.workFlowData = workFlowData
+ return wfRes
+ }
+
+ private fun addPropertyInfo(prop: PropertyDefinition, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
+ addDataType(prop.type, ctx, res)
+ if (prop.entrySchema != null && prop.entrySchema!!.type != null) {
+ addDataType(prop.entrySchema!!.type, ctx, res)
}
+ }
private fun addPropertyInfo(propName: String, prop: PropertyDefinition, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
updatePropertyInfo(propName, prop, ctx, res)
@@ -192,23 +229,19 @@ open class BluePrintModelHandler(
}
}
+ // wrap CBA workflows list in WorkflowsResponse object
@Throws(BluePrintException::class)
open suspend fun getWorkflowNames(name: String, version: String): WorkFlowsResponse {
- val basePath = blueprintsProcessorCatalogService.getFromDatabase(
- name, version
+ var workflows = getWorkflowsFromRepository(name, version)
+ if (workflows == null) throw httpProcessorException(
+ ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API,
+ "Failed to find workflows list for blueprint: ($name) version: ($version) from filesystem."
)
- log.info("blueprint base path $basePath")
var res = WorkFlowsResponse()
res.blueprintName = name
res.version = version
-
- val blueprintContext = BluePrintMetadataUtils.getBluePrintContext(
- basePath.toString()
- )
- if (blueprintContext.workflows() != null) {
- res.workflows = blueprintContext.workflows()!!.keys
- }
+ res.workflows = workflows.keys.toMutableSet()
return res
}
@@ -242,6 +275,7 @@ open class BluePrintModelHandler(
try {
return upload(filePart, false)
} catch (e: IOException) {
+ log.error("saveBlueprintModel fails ${e.message}", e)
throw httpProcessorException(
ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
"Error in Save CBA: ${e.message}", e.errorCauseOrDefault()
@@ -527,13 +561,15 @@ open class BluePrintModelHandler(
val enhancedByteArray = enrichBlueprintFileSource(filePart)
return upload(enhancedByteArray, true)
} catch (e: BluePrintProcessorException) {
- e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
val errorMsg = "Error while enhancing and uploading the CBA package."
+ log.error(errorMsg, e)
+ e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT)
throw e.updateErrorMessage(
DesignerApiDomains.DESIGNER_API, errorMsg,
"Wrong CBA file provided, please verify the source CBA."
)
} catch (e: Exception) {
+ log.error("Error enriching/uploading CBA", e)
throw httpProcessorException(
ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API,
"EnrichBlueprint: ${e.message}", e.errorCauseOrDefault()
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt
index 15c27a43b..d2b7ac368 100644
--- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt
@@ -26,6 +26,8 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.R
import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes
+import org.onap.ccsdk.cds.error.catalog.core.ErrorPayload
+import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
@@ -110,6 +112,60 @@ open class ResourceController(private var resourceResolutionDBService: ResourceR
}
@RequestMapping(
+ path = ["/occurrences"],
+ method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE]
+ )
+ @ApiOperation(
+ value = "Get the map of resolved resources with 'occurrence' as the keys to the resolved resources ",
+ notes = "With optional 'occurrence' options, subset of stored resolved resources can be retrieved " +
+ "using the blueprint name, blueprint version, artifact name and the resolution-key.",
+ response = ResourceResolution::class,
+ responseContainer = "List",
+ produces = MediaType.APPLICATION_JSON_VALUE
+ )
+ @ResponseBody
+ @PreAuthorize("hasRole('USER')")
+ fun getOccurrences(
+ @ApiParam(value = "Name of the CBA.", required = true)
+ @RequestParam(value = "bpName", required = true) bpName: String,
+ @ApiParam(value = "Version of the CBA.", required = true)
+ @RequestParam(value = "bpVersion", required = true) bpVersion: String,
+ @ApiParam(value = "Artifact name for which to retrieve a resolved resource.", required = true)
+ @RequestParam(value = "artifactName", required = true, defaultValue = "") artifactName: String,
+ @ApiParam(value = "Resolution Key associated with the resolution.", required = true)
+ @RequestParam(value = "resolutionKey", required = true, defaultValue = "") resolutionKey: String,
+ @ApiParam(value = "Number of earlier N occurrences of the resolutions.", required = false)
+ @RequestParam(value = "firstN", required = false) firstN: Int?,
+ @ApiParam(value = "Number of latest N occurrences of the resolutions.", required = false)
+ @RequestParam(value = "lastN", required = false) lastN: Int?,
+ @ApiParam(value = "For Range option - 'begin' is the start occurrence of range of the resolutions.", required = false)
+ @RequestParam(value = "begin", required = false) begin: Int?,
+ @ApiParam(value = "For Range option - 'end' is the end occurrence of the range of the resolutions.", required = false)
+ @RequestParam(value = "end", required = false) end: Int?
+ ): ResponseEntity<Map<Int, List<ResourceResolution>>> = runBlocking {
+ when {
+ artifactName.isEmpty() -> "'artifactName' must not be empty"
+ resolutionKey.isEmpty() -> "'resolutionKey' must not be empty"
+ // Optional options - validate if provided
+ (firstN != null && lastN != null) -> "Retrieve occurrences using either 'firstN' OR 'lastN' option"
+ ((firstN != null || lastN != null) && (begin != null || end != null)) -> "Retrieve occurrences using either 'firstN' OR 'lastN' OR 'begin' and 'end' option."
+ ((begin != null && end == null) || (begin == null && end != null)) -> " Retrieving occurrences within range - please provide both 'begin' and 'end' option"
+ else -> null
+ }?.let { throw httpProcessorException(ErrorCatalogCodes.REQUEST_NOT_FOUND, ResourceApiDomains.RESOURCE_API, it) }
+
+ when {
+ firstN != null ->
+ resourceResolutionDBService.findFirstNOccurrences(bpName, bpVersion, artifactName, resolutionKey, firstN)
+ lastN != null ->
+ resourceResolutionDBService.findLastNOccurrences(bpName, bpVersion, artifactName, resolutionKey, lastN)
+ begin != null && end != null ->
+ resourceResolutionDBService.findOccurrencesWithinRange(bpName, bpVersion, artifactName, resolutionKey, begin, end)
+ else ->
+ resourceResolutionDBService.readWithResolutionKey(bpName, bpVersion, artifactName, resolutionKey).groupBy(ResourceResolution::occurrence).toSortedMap(reverseOrder())
+ }.let { result -> ResponseEntity.ok().body(result) }
+ }
+
+ @RequestMapping(
method = [RequestMethod.DELETE], produces = [MediaType.APPLICATION_JSON_VALUE]
)
@ApiOperation(
@@ -161,9 +217,14 @@ open class ResourceController(private var resourceResolutionDBService: ResourceR
@ApiParam(value = "Name of the resource to retrieve", required = true)
@RequestParam(value = "name", required = true) name: String
):
- ResponseEntity<ResourceResolution> = runBlocking {
+ ResponseEntity<out Any>? = runBlocking {
- ResponseEntity.ok()
- .body(resourceResolutionDBService.readValue(bpName, bpVersion, artifactName, resolutionKey, name))
+ var result: ResourceResolution? = resourceResolutionDBService.readValue(bpName, bpVersion, artifactName, resolutionKey, name)
+ if (result != null) {
+ ResponseEntity.ok().body(result)
+ } else {
+ var errorPayload = ErrorPayload(HttpStatus.NOT_FOUND.value(), ErrorCatalogCodes.GENERIC_FAILURE, "No records found")
+ ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorPayload)
+ }
}
}
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt
index bb7ecc6ad..9e0a7ee71 100644
--- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt
@@ -91,8 +91,7 @@ open class ExecutionServiceController {
suspend fun process(
@ApiParam(value = "ExecutionServiceInput payload.", required = true)
@RequestBody executionServiceInput: ExecutionServiceInput
- ): ResponseEntity<ExecutionServiceOutput> = mdcWebCoroutineScope {
-
+ ): ResponseEntity<ExecutionServiceOutput> = mdcWebCoroutineScope(executionServiceInput) {
if (executionServiceInput.actionIdentifiers.mode == ACTION_MODE_ASYNC) {
throw httpProcessorException(
ErrorCatalogCodes.GENERIC_FAILURE,