import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.ResourceAssignmentProcessor
import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceDefinitionUtils.createResourceAssignments
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
-import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
-import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService
+import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BlueprintRuntimeService
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BlueprintTemplateService
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.utils.BulkResourceSequencingUtils
import org.springframework.stereotype.Service
import java.util.UUID
+data class ResourceResolutionResult(
+ val templateMap: MutableMap<String, String>,
+ val assignmentMap: MutableMap<String, JsonNode>
+)
+
interface ResourceResolutionService {
fun registeredResourceSources(): List<String>
suspend fun resolveFromDatabase(
- bluePrintRuntimeService: BluePrintRuntimeService<*>,
+ bluePrintRuntimeService: BlueprintRuntimeService<*>,
artifactTemplate: String,
resolutionKey: String
): String
suspend fun resolveResources(
- bluePrintRuntimeService: BluePrintRuntimeService<*>,
+ bluePrintRuntimeService: BlueprintRuntimeService<*>,
nodeTemplateName: String,
artifactNames: List<String>,
properties: Map<String, Any>
- ): MutableMap<String, String>
+ ): ResourceResolutionResult
suspend fun resolveResources(
- bluePrintRuntimeService: BluePrintRuntimeService<*>,
+ bluePrintRuntimeService: BlueprintRuntimeService<*>,
nodeTemplateName: String,
artifactPrefix: String,
properties: Map<String, Any>
- ): String
+ ): Pair<String, MutableList<ResourceAssignment>>
/** Resolve resources for all the sources defined in a particular resource Definition[resolveDefinition]
* with other [resourceDefinitions] dependencies for the sources [sources]
* Used to get the same resource values from multiple sources. **/
suspend fun resolveResourceDefinition(
- blueprintRuntimeService: BluePrintRuntimeService<*>,
+ blueprintRuntimeService: BlueprintRuntimeService<*>,
resourceDefinitions: MutableMap<String, ResourceDefinition>,
resolveDefinition: String,
sources: List<String>
):
- MutableMap<String, JsonNode>
+ MutableMap<String, JsonNode>
suspend fun resolveResourceAssignments(
- blueprintRuntimeService: BluePrintRuntimeService<*>,
+ blueprintRuntimeService: BlueprintRuntimeService<*>,
resourceDefinitions: MutableMap<String, ResourceDefinition>,
resourceAssignments: MutableList<ResourceAssignment>,
artifactPrefix: String,
open class ResourceResolutionServiceImpl(
private var applicationContext: ApplicationContext,
private var templateResolutionDBService: TemplateResolutionService,
- private var blueprintTemplateService: BluePrintTemplateService,
+ private var blueprintTemplateService: BlueprintTemplateService,
private var resourceResolutionDBService: ResourceResolutionDBService
) :
ResourceResolutionService {
}
override suspend fun resolveFromDatabase(
- bluePrintRuntimeService: BluePrintRuntimeService<*>,
+ bluePrintRuntimeService: BlueprintRuntimeService<*>,
artifactTemplate: String,
resolutionKey: String
): String {
}
override suspend fun resolveResources(
- bluePrintRuntimeService: BluePrintRuntimeService<*>,
+ bluePrintRuntimeService: BlueprintRuntimeService<*>,
nodeTemplateName: String,
artifactNames: List<String>,
properties: Map<String, Any>
- ): MutableMap<String, String> {
+ ): ResourceResolutionResult {
val resourceAssignmentRuntimeService =
ResourceAssignmentUtils.transformToRARuntimeService(bluePrintRuntimeService, artifactNames.toString())
- val resolvedParams: MutableMap<String, String> = hashMapOf()
+ val templateMap: MutableMap<String, String> = hashMapOf()
+ val assignmentMap: MutableMap<String, JsonNode> = hashMapOf()
artifactNames.forEach { artifactName ->
- val resolvedContent = resolveResources(
+ val (resolvedStringContent, resourceAssignmentList) = resolveResources(
resourceAssignmentRuntimeService, nodeTemplateName,
artifactName, properties
)
-
- resolvedParams[artifactName] = resolvedContent
+ val resolvedJsonContent = resourceAssignmentList
+ .associateBy({ it.name }, { it.property?.value })
+ .asJsonNode()
+
+ templateMap[artifactName] = resolvedStringContent
+ assignmentMap[artifactName] = resolvedJsonContent
+
+ val failedResolution = resourceAssignmentList.filter { it.status != "success" && it.property?.required == true }.map { it.name }
+ if (failedResolution.isNotEmpty()) {
+ // The following error message is returned by default to handle a scenario when
+ // error message comes empty even when resolution has actually failed.
+ // Example: input-source type resolution seems to fail with no error code.
+ bluePrintRuntimeService.getBlueprintError().errors.add("Failed to resolve required resources($failedResolution)")
+ bluePrintRuntimeService.getBlueprintError().errors.addAll(resourceAssignmentRuntimeService.getBlueprintError().errors)
+ }
}
- return resolvedParams
+ return ResourceResolutionResult(templateMap, assignmentMap)
}
override suspend fun resolveResources(
- bluePrintRuntimeService: BluePrintRuntimeService<*>,
+ bluePrintRuntimeService: BlueprintRuntimeService<*>,
nodeTemplateName: String,
artifactPrefix: String,
properties: Map<String, Any>
- ): String {
+ ): Pair<String, MutableList<ResourceAssignment>> {
- // Velocity Artifact Definition Name
+ // Template Artifact Definition Name
val artifactTemplate = "$artifactPrefix-template"
// Resource Assignment Artifact Definition Name
val artifactMapping = "$artifactPrefix-mapping"
- val resolvedContent: String
- log.info("Resolving resource for template artifact($artifactTemplate) with resource assignment artifact($artifactMapping)")
+ log.info("Resolving resource with resource assignment artifact($artifactMapping)")
val resourceAssignmentContent =
bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactMapping)
val resourceAssignments: MutableList<ResourceAssignment> =
JacksonUtils.getListFromJson(resourceAssignmentContent, ResourceAssignment::class.java)
- as? MutableList<ResourceAssignment>
- ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions")
+ as? MutableList<ResourceAssignment>
+ ?: throw BlueprintProcessorException("couldn't get Dictionary Definitions")
if (isToStore(properties)) {
val existingResourceResolution = isNewResolution(bluePrintRuntimeService, properties, artifactPrefix)
properties
)
+ val resolutionSummary = properties.getOrDefault(
+ ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY,
+ false
+ ) as Boolean
+
val resolvedParamJsonContent =
ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList())
-
- resolvedContent = blueprintTemplateService.generateContent(
- bluePrintRuntimeService, nodeTemplateName,
- artifactTemplate, resolvedParamJsonContent, false,
- mutableMapOf(
- ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE to
- properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE].asJsonPrimitive()
- )
- )
+ val artifactTemplateDefinition =
+ bluePrintRuntimeService.bluePrintContext().checkNodeTemplateArtifact(nodeTemplateName, artifactTemplate)
+
+ val resolvedContent = when {
+ artifactTemplateDefinition != null -> {
+ blueprintTemplateService.generateContent(
+ bluePrintRuntimeService, nodeTemplateName,
+ artifactTemplate, resolvedParamJsonContent, false,
+ mutableMapOf(
+ ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE to
+ properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE]
+ .asJsonPrimitive()
+ )
+ )
+ }
+ resolutionSummary -> {
+ ResourceAssignmentUtils.generateResolutionSummaryData(resourceAssignments, resourceDefinitions)
+ }
+ else -> {
+ resolvedParamJsonContent
+ }
+ }
if (isToStore(properties)) {
templateResolutionDBService.write(properties, resolvedContent, bluePrintRuntimeService, artifactPrefix)
log.info("Template resolution saved into database successfully : ($properties)")
}
- return resolvedContent
+ return Pair(resolvedContent, resourceAssignments)
}
override suspend fun resolveResourceDefinition(
- blueprintRuntimeService: BluePrintRuntimeService<*>,
+ blueprintRuntimeService: BlueprintRuntimeService<*>,
resourceDefinitions: MutableMap<String, ResourceDefinition>,
resolveDefinition: String,
sources: List<String>
- ):
- MutableMap<String, JsonNode> {
+ ): MutableMap<String, JsonNode> {
// Populate Dummy Resource Assignments
val resourceAssignments = createResourceAssignments(resourceDefinitions, resolveDefinition, sources)
* request.
*/
override suspend fun resolveResourceAssignments(
- blueprintRuntimeService: BluePrintRuntimeService<*>,
+ blueprintRuntimeService: BlueprintRuntimeService<*>,
resourceDefinitions: MutableMap<String, ResourceDefinition>,
resourceAssignments: MutableList<ResourceAssignment>,
artifactPrefix: String,
// Execute Non Dependent Assignments in parallel ( ie asynchronously )
val deferred = batchResourceAssignments
.filter { it.name != "*" && it.name != "start" }
- .filter { it.status != BluePrintConstants.STATUS_SUCCESS }
+ .filter { it.status != BlueprintConstants.STATUS_SUCCESS }
.map { resourceAssignment ->
async {
val dictionaryName = resourceAssignment.dictionaryName
val resourceAssignmentProcessor =
applicationContext.getBean(processorName) as? ResourceAssignmentProcessor
- ?: throw BluePrintProcessorException(
+ ?: throw BlueprintProcessorException(
"failed to get resource processor ($processorName) " +
- "for resource assignment(${resourceAssignment.name})"
+ "for resource assignment(${resourceAssignment.name})"
)
try {
- // Set BluePrint Runtime Service
+ // Set Blueprint Runtime Service
resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService
// Set Resource Dictionaries
resourceAssignmentProcessor.resourceDictionaries = resourceDefinitions
+
+ resourceAssignmentProcessor.resourceAssignments = resourceAssignments
+
// Invoke Apply Method
resourceAssignmentProcessor.applyNB(resourceAssignment)
}
// Set errors from RA
- blueprintRuntimeService.setBluePrintError(resourceAssignmentRuntimeService.getBluePrintError())
+ blueprintRuntimeService.setBlueprintError(resourceAssignmentRuntimeService.getBlueprintError())
} catch (e: RuntimeException) {
log.error("Fail in processing ${resourceAssignment.name}", e)
- throw BluePrintProcessorException(e)
+ throw BlueprintProcessorException(e)
}
}
}
}
else -> {
val resourceDefinition = resourceDefinitions[dictionaryName]
- ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dictionaryName")
+ ?: throw BlueprintProcessorException("couldn't get resource dictionary definition for $dictionaryName")
val resourceSource = resourceDefinition.sources[dictionarySource]
- ?: throw BluePrintProcessorException("couldn't get resource definition $dictionaryName source($dictionarySource)")
+ ?: throw BlueprintProcessorException("couldn't get resource definition $dictionaryName source($dictionarySource)")
ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR.plus(resourceSource.type)
}
// Check whether to store or not the resolution of resource and template
private fun isToStore(properties: Map<String, Any>): Boolean {
return properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) &&
- properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean
+ properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean
}
// Check whether resolution already exist in the database for the specified resolution-key or resourceId/resourceType
private suspend fun isNewResolution(
- bluePrintRuntimeService: BluePrintRuntimeService<*>,
+ bluePrintRuntimeService: BlueprintRuntimeService<*>,
properties: Map<String, Any>,
artifactPrefix: String
): List<ResourceResolution> {
)
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 - will resolve all resources not already resolved."
)
}
return existingResourceAssignments
resourceAssignmentList: MutableList<ResourceAssignment>
) {
resourceResolutionList.forEach { resourceResolution ->
- if (resourceResolution.status == BluePrintConstants.STATUS_SUCCESS) {
+ if (resourceResolution.status == BlueprintConstants.STATUS_SUCCESS) {
resourceAssignmentList.forEach {
if (compareOne(resourceResolution, it)) {
- log.info("Resource ({}) already resolve: value=({})", it.name, resourceResolution.value)
+ log.info(
+ "Resource ({}) already resolved: value=({})", it.name,
+ if (hasLogProtect(it.property)) LOG_REDACTED else resourceResolution.value
+ )
// Make sure to recreate value as per the defined type.
val value = resourceResolution.value!!.asJsonType(it.property!!.type)
// Comparision 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 &&
+ return (
+ resourceResolution.name == resourceAssignment.name &&
resourceResolution.dictionaryName == resourceAssignment.dictionaryName &&
resourceResolution.dictionarySource == resourceAssignment.dictionarySource &&
- resourceResolution.dictionaryVersion == resourceAssignment.version)
+ resourceResolution.dictionaryVersion == resourceAssignment.version
+ )
}
private fun exposeOccurrencePropertyInResourceAssignments(