From 396b49a03e418ce7f68587c3e4444ed262325e0a Mon Sep 17 00:00:00 2001 From: Alexis de Talhouët Date: Thu, 20 Jun 2019 22:12:08 -0400 Subject: Store resolution and expose with REST API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ie1fe9c02542ccd5fbfa18f1e2d6ddb633f55c214 Issue-ID: CCSDK-1423 Signed-off-by: Alexis de Talhouët --- .../functions/cli/executor/CliComponentFunction.kt | 5 - .../netconf/executor/NetconfComponentFunction.kt | 5 - .../resolution/ResourceResolutionComponent.kt | 9 +- .../resolution/ResourceResolutionConstants.kt | 2 + .../resolution/ResourceResolutionService.kt | 138 ++++++----- .../resource/resolution/db/ResourceResolution.kt | 91 ++++++++ .../resolution/db/ResourceResolutionDBService.kt | 128 +++++++++++ .../resolution/db/ResourceResolutionRepository.kt | 22 +- .../db/ResourceResolutionResultRepository.kt | 25 ++ .../db/ResourceResolutionResultService.kt | 2 +- .../resolution/ResourceResolutionServiceTest.kt | 7 +- .../restconf/executor/RestconfComponentFunction.kt | 5 - .../resource/api/ResourceResolutionController.java | 48 ---- .../ResolutionResultsServiceExceptionHandler.kt | 14 +- .../resolutionresults/api/ResourceController.kt | 84 +++++++ .../resolutionresults/api/ResourceException.kt | 21 ++ .../api/ResourceControllerTest.kt | 251 +++++++++++++++++++++ 17 files changed, 706 insertions(+), 151 deletions(-) create mode 100644 ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolution.kt create mode 100644 ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt create mode 100644 ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultRepository.kt delete mode 100644 ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionController.java create mode 100644 ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt create mode 100644 ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceException.kt create mode 100644 ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceControllerTest.kt (limited to 'ms/blueprintsprocessor') diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt index 1b84964e8..65d1c3eee 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt +++ b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt @@ -49,11 +49,6 @@ abstract class CliComponentFunction : AbstractScriptComponentFunction() { resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) } - fun resolveAndGenerateMessage(artifactMapping: String, artifactTemplate: String): String = runBlocking { - resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactMapping, artifactTemplate) - } - fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf()) diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt index be7451aa9..4cec6a2bf 100644 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt @@ -44,11 +44,6 @@ abstract class NetconfComponentFunction : AbstractScriptComponentFunction() { resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) } - fun resolveAndGenerateMessage(artifactMapping: String, artifactTemplate: String): String = runBlocking { - resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactMapping, artifactTemplate) - } - fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf()) 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 0bc83763a..7c2c11c06 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 @@ -37,10 +37,15 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re val occurrence = getOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE) val key = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY) val storeResult = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) + val resourceId = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID) + val resourceType = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE) + val properties: MutableMap = mutableMapOf() - properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = - storeResult?.asBoolean() ?: false + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = storeResult?.asBoolean() ?: false + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY] = key?.asText() ?: "" + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId?.asText() ?: "" + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType?.asText() ?: "" val artifactPrefixNamesNode = getOperationInput(ResourceResolutionConstants.INPUT_ARTIFACT_PREFIX_NAMES) val artifactPrefixNames = JacksonUtils.getListFromJsonNode(artifactPrefixNamesNode, String::class.java) 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 9d422f1c6..929e9e8df 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,8 @@ object ResourceResolutionConstants { const val RESOURCE_RESOLUTION_INPUT_KEY = "resolution-key" const val RESOURCE_RESOLUTION_INPUT_STORE_RESULT = "store-result" 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" } \ 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 fe5906220..b1482934f 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 @@ -20,6 +20,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionResultService import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.ResourceAssignmentProcessor import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils @@ -48,27 +49,26 @@ interface ResourceResolutionService { suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, artifactPrefix: String, properties: Map): String - suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactMapping: String, artifactTemplate: String?): String - suspend fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>, resourceDefinitions: MutableMap, resourceAssignments: MutableList, - identifierName: String) + artifactPrefix: String, + properties: Map) } @Service(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) open class ResourceResolutionServiceImpl(private var applicationContext: ApplicationContext, private var resolutionResultService: ResourceResolutionResultService, - private var blueprintTemplateService: BluePrintTemplateService) : - ResourceResolutionService { + private var blueprintTemplateService: BluePrintTemplateService, + private var resourceResolutionDBService: ResourceResolutionDBService) : + ResourceResolutionService { private val log = LoggerFactory.getLogger(ResourceResolutionService::class.java) override fun registeredResourceSources(): List { return applicationContext.getBeanNamesForType(ResourceAssignmentProcessor::class.java) - .filter { it.startsWith(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) } - .map { it.substringAfter(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) } + .filter { it.startsWith(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) } + .map { it.substringAfter(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) } } override suspend fun resolveFromDatabase(bluePrintRuntimeService: BluePrintRuntimeService<*>, @@ -78,12 +78,13 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica } override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactNames: List, properties: Map): MutableMap { + artifactNames: List, + properties: Map): MutableMap { val resolvedParams: MutableMap = hashMapOf() artifactNames.forEach { artifactName -> val resolvedContent = resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactName, properties) + artifactName, properties) resolvedParams[artifactName] = resolvedContent } return resolvedParams @@ -97,52 +98,38 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica // Resource Assignment Artifact Definition Name val artifactMapping = "$artifactPrefix-mapping" - val result = resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactMapping, artifactTemplate) - - if (properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) - && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean) { - resolutionResultService.write(properties, result, bluePrintRuntimeService, artifactPrefix) - log.info("resolution saved into database successfully : ($properties)") - } - - return result - } - - - override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactMapping: String, artifactTemplate: String?): String { - val resolvedContent: String log.info("Resolving resource for template artifact($artifactTemplate) with resource assignment artifact($artifactMapping)") - val identifierName = artifactTemplate ?: "no-template" - val resourceAssignmentContent = - bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactMapping) + bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactMapping) val resourceAssignments: MutableList = - JacksonUtils.getListFromJson(resourceAssignmentContent, ResourceAssignment::class.java) - as? MutableList - ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions") + JacksonUtils.getListFromJson(resourceAssignmentContent, ResourceAssignment::class.java) + as? MutableList + ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions") // Get the Resource Dictionary Name val resourceDefinitions: MutableMap = ResourceAssignmentUtils - .resourceDefinitions(bluePrintRuntimeService.bluePrintContext().rootPath) + .resourceDefinitions(bluePrintRuntimeService.bluePrintContext().rootPath) // Resolve resources - resolveResourceAssignments(bluePrintRuntimeService, resourceDefinitions, resourceAssignments, identifierName) + resolveResourceAssignments(bluePrintRuntimeService, + resourceDefinitions, + resourceAssignments, + artifactPrefix, + properties) val resolvedParamJsonContent = - ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList()) + ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList()) - // Check Template is there - if (artifactTemplate != null) { - resolvedContent = blueprintTemplateService.generateContent(bluePrintRuntimeService, nodeTemplateName, - artifactTemplate, resolvedParamJsonContent) + resolvedContent = blueprintTemplateService.generateContent(bluePrintRuntimeService, nodeTemplateName, + artifactTemplate, resolvedParamJsonContent) - } else { - resolvedContent = resolvedParamJsonContent + if (properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) + && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean) { + resolutionResultService.write(properties, resolvedContent, bluePrintRuntimeService, artifactPrefix) + log.info("template resolution saved into database successfully : ($properties)") } return resolvedContent @@ -156,44 +143,55 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica override suspend fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>, resourceDefinitions: MutableMap, resourceAssignments: MutableList, - identifierName: String) { + artifactPrefix: String, + properties: Map) { val bulkSequenced = BulkResourceSequencingUtils.process(resourceAssignments) val resourceAssignmentRuntimeService = - ResourceAssignmentUtils.transformToRARuntimeService(blueprintRuntimeService, identifierName) + ResourceAssignmentUtils.transformToRARuntimeService(blueprintRuntimeService, artifactPrefix) coroutineScope { bulkSequenced.forEach { batchResourceAssignments -> // Execute Non Dependent Assignments in parallel ( ie asynchronously ) val deferred = batchResourceAssignments.filter { it.name != "*" && it.name != "start" } - .map { resourceAssignment -> - async { - val dictionaryName = resourceAssignment.dictionaryName - val dictionarySource = resourceAssignment.dictionarySource - /** - * Get the Processor name - */ - val processorName = processorName(dictionaryName!!, dictionarySource!!, resourceDefinitions) - - val resourceAssignmentProcessor = - applicationContext.getBean(processorName) as? ResourceAssignmentProcessor - ?: throw BluePrintProcessorException("failed to get resource processor ($processorName) " + - "for resource assignment(${resourceAssignment.name})") - try { - // Set BluePrint Runtime Service - resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService - // Set Resource Dictionaries - resourceAssignmentProcessor.resourceDictionaries = resourceDefinitions - // Invoke Apply Method - resourceAssignmentProcessor.applyNB(resourceAssignment) - // Set errors from RA - blueprintRuntimeService.setBluePrintError(resourceAssignmentRuntimeService.getBluePrintError()) - } catch (e: RuntimeException) { - log.error("Fail in processing ${resourceAssignment.name}", e) - throw BluePrintProcessorException(e) + .map { resourceAssignment -> + async { + val dictionaryName = resourceAssignment.dictionaryName + val dictionarySource = resourceAssignment.dictionarySource + /** + * Get the Processor name + */ + val processorName = processorName(dictionaryName!!, dictionarySource!!, resourceDefinitions) + + val resourceAssignmentProcessor = + applicationContext.getBean(processorName) as? ResourceAssignmentProcessor + ?: throw BluePrintProcessorException("failed to get resource processor ($processorName) " + + "for resource assignment(${resourceAssignment.name})") + try { + // Set BluePrint Runtime Service + resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService + // Set Resource Dictionaries + resourceAssignmentProcessor.resourceDictionaries = resourceDefinitions + // Invoke Apply Method + resourceAssignmentProcessor.applyNB(resourceAssignment) + + if (properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) + && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean) { + resourceResolutionDBService.write(properties, + blueprintRuntimeService, + artifactPrefix, + resourceAssignment) + log.info("resolution saved into database successfully : ($resourceAssignment)") } + + // Set errors from RA + blueprintRuntimeService.setBluePrintError(resourceAssignmentRuntimeService.getBluePrintError()) + } catch (e: RuntimeException) { + log.error("Fail in processing ${resourceAssignment.name}", e) + throw BluePrintProcessorException(e) } } + } log.debug("Resolving (${deferred.size})resources parallel.") deferred.awaitAll() } @@ -217,10 +215,10 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica } 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) } diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolution.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolution.kt new file mode 100644 index 000000000..767a1feaf --- /dev/null +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolution.kt @@ -0,0 +1,91 @@ +/* + * Copyright © 2019 Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db + +import com.fasterxml.jackson.annotation.JsonFormat +import com.fasterxml.jackson.annotation.JsonProperty +import org.hibernate.annotations.Proxy +import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import java.io.Serializable +import java.util.* +import javax.persistence.Column +import javax.persistence.Entity +import javax.persistence.EntityListeners +import javax.persistence.Id +import javax.persistence.Lob +import javax.persistence.Table +import javax.persistence.Temporal +import javax.persistence.TemporalType + +@EntityListeners(AuditingEntityListener::class) +@Entity +@Table(name = "RESOURCE_RESOLUTION") +@Proxy(lazy = false) +class ResourceResolution : Serializable { + + @Id + @Column(name = "resource_resolution_id") + var id: String? = null + + @Column(name = "resolution_key", nullable = false) + var resolutionKey: String? = null + + @Column(name = "resource_type", nullable = false) + var resourceType: String? = null + + @Column(name = "resource_id", nullable = false) + var resourceId: String? = null + + @Column(name = "blueprint_name", nullable = false) + var blueprintName: String? = null + + @Column(name = "blueprint_version", nullable = false) + var blueprintVersion: String? = null + + @Column(name = "artifact_name", nullable = false) + var artifactName: String? = null + + @Column(name = "status", nullable = false) + var status: String? = null + + @Column(name = "name", nullable = false) + var name: String? = null + + @Column(name = "dictionary_vname", nullable = false) + var dictionaryName: String? = null + + @Column(name = "dictionary_status", nullable = false) + var dictionarySource: String? = null + + @Column(name = "dictionary_version", nullable = false) + var dictionaryVersion: Int = 0 + + @Lob + @Column(name = "value", nullable = false) + var value: String? = null + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + @LastModifiedDate + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "creation_date") + var createdDate = Date() + + companion object { + private const val serialVersionUID = 1L + } +} \ 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/db/ResourceResolutionDBService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt new file mode 100644 index 000000000..81239be30 --- /dev/null +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment +import org.slf4j.LoggerFactory +import org.springframework.dao.DataIntegrityViolationException +import org.springframework.stereotype.Service +import java.util.* + +@Service +class ResourceResolutionDBService(private val resourceResolutionRepository: ResourceResolutionRepository) { + + private val log = LoggerFactory.getLogger(ResourceResolutionDBService::class.toString()) + + suspend fun readValue(blueprintName: String, + blueprintVersion: String, + artifactPrefix: String, + resolutionKey: String, + name: String): ResourceResolution = withContext(Dispatchers.IO) { + + resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndName( + resolutionKey, + blueprintName, + blueprintVersion, + artifactPrefix, + name) + } + + suspend fun readWithResolutionKey(blueprintName: String, + blueprintVersion: String, + artifactPrefix: String, + resolutionKey: String): List = withContext(Dispatchers.IO) { + + resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName( + resolutionKey, + blueprintName, + blueprintVersion, + artifactPrefix) + } + + suspend fun readWithResourceIdAndResourceType(blueprintName: String, + blueprintVersion: String, + resourceId: String, + resourceType: String): List = withContext(Dispatchers.IO) { + + resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType( + blueprintName, + blueprintVersion, + resourceId, + resourceType) + } + + suspend fun write(properties: Map, + bluePrintRuntimeService: BluePrintRuntimeService<*>, + artifactPrefix: String, + resourceAssignment: ResourceAssignment): ResourceResolution = withContext(Dispatchers.IO) { + + 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_KEY].toString() + val resourceType = + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE].toString() + val resourceId = + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID].toString() + + write(blueprintName, + blueprintVersion, + resolutionKey, + resourceId, + resourceType, + artifactPrefix, + resourceAssignment) + } + + suspend fun write(blueprintName: String, + blueprintVersion: String, + resolutionKey: String, + resourceId: String, + resourceType: String, + artifactPrefix: String, + resourceAssignment: ResourceAssignment): ResourceResolution = withContext(Dispatchers.IO) { + + val resourceResolution = ResourceResolution() + resourceResolution.id = UUID.randomUUID().toString() + resourceResolution.artifactName = artifactPrefix + resourceResolution.blueprintVersion = blueprintVersion + resourceResolution.blueprintName = blueprintName + resourceResolution.resolutionKey = resolutionKey + resourceResolution.resourceType = resourceType + resourceResolution.resourceId = resourceId + resourceResolution.value = JacksonUtils.getValue(resourceAssignment.property?.value!!).toString() + resourceResolution.name = resourceAssignment.name + resourceResolution.dictionaryName = resourceAssignment.dictionaryName + resourceResolution.dictionaryVersion = resourceAssignment.version + resourceResolution.dictionarySource = resourceAssignment.dictionarySource + resourceResolution.status = resourceAssignment.status + + try { + resourceResolutionRepository.saveAndFlush(resourceResolution) + } catch (ex: Exception) { + throw BluePrintException("Failed to store resource resolution result.", ex) + } + } +} \ 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/db/ResourceResolutionRepository.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt index 72bb4a384..d2cbf8411 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 @@ -17,9 +17,21 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db import org.springframework.data.jpa.repository.JpaRepository -interface ResourceResolutionRepository : JpaRepository { +interface ResourceResolutionRepository : JpaRepository { - fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(key: String, blueprintName: String?, - blueprintVersion: String?, - artifactName: String): ResourceResolutionResult -} + fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndName(key: String, + blueprintName: String?, + blueprintVersion: String?, + artifactName: String, + name: String): ResourceResolution + + fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(resolutionKey: String, + blueprintName: String, + blueprintVersion: String, + artifactPrefix: String): List + + fun findByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(blueprintName: String, + blueprintVersion: String, + resourceId: String, + resourceType: String): List +} \ 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/db/ResourceResolutionResultRepository.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultRepository.kt new file mode 100644 index 000000000..efc130a84 --- /dev/null +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultRepository.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db + +import org.springframework.data.jpa.repository.JpaRepository + +interface ResourceResolutionResultRepository : JpaRepository { + + fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(key: String, blueprintName: String?, + blueprintVersion: String?, + artifactName: String): ResourceResolutionResult +} diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt index 3cb9dec63..ebb34ba4a 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt @@ -27,7 +27,7 @@ import org.springframework.stereotype.Service import java.util.* @Service -class ResourceResolutionResultService(private val resourceResolutionRepository: ResourceResolutionRepository) { +class ResourceResolutionResultService(private val resourceResolutionRepository: ResourceResolutionResultRepository) { suspend fun read(bluePrintRuntimeService: BluePrintRuntimeService<*>, artifactPrefix: String, resolutionKey: String): String = withContext(Dispatchers.IO) { 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 9c2a100bc..4a3e75cde 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 @@ -128,15 +128,10 @@ class ResourceResolutionServiceTest { val artifactPrefix = "another" - // Templating Artifact Definition Name - val artifactTemplate = "$artifactPrefix-template" - // Resource Assignment Artifact Definition Name - val artifactMapping = "$artifactPrefix-mapping" - // Prepare Inputs PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService, executionServiceInput.payload, "resource-assignment") - resourceResolutionService.resolveResources(bluePrintRuntimeService, "resource-assignment", artifactMapping, artifactTemplate) + resourceResolutionService.resolveResources(bluePrintRuntimeService, "resource-assignment", artifactPrefix, mapOf()) } } } diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt index 3895c39c8..b2064cb54 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt +++ b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt @@ -47,11 +47,6 @@ abstract class RestconfComponentFunction : AbstractScriptComponentFunction() { return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) } - fun resolveAndGenerateMessage(artifactMapping: String, artifactTemplate: String): String = runBlocking { - resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactMapping, artifactTemplate) - } - fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf()) diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionController.java b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionController.java deleted file mode 100644 index 3e94d79ee..000000000 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionController.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.cds.blueprintsprocessor.resource.api; - -import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Mono; - -/** - * ResourceResolutionController - * - * @author Brinda Santh Date : 8/13/2018 - */ - -@RestController -@RequestMapping("/api/v1/resource") -public class ResourceResolutionController { - - private ResourceResolutionService resourceResolutionService; - - public ResourceResolutionController(ResourceResolutionService resourceResolutionService) { - this.resourceResolutionService = resourceResolutionService; - } - - @RequestMapping(path = "/ping", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public @ResponseBody - Mono ping() { - return Mono.just("Success"); - } -} diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt index 69641c628..7f8f7da79 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt @@ -48,7 +48,7 @@ open class ResolutionResultsServiceExceptionHandler { @ExceptionHandler fun ResolutionResultsServiceExceptionHandler(e: BluePrintProcessorException): ResponseEntity { - log.error(e.message) + log.error(e.message, e) val errorCode = ErrorCode.BLUEPRINT_PATH_MISSING val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) @@ -56,7 +56,7 @@ open class ResolutionResultsServiceExceptionHandler { @ExceptionHandler fun ResolutionResultsServiceExceptionHandler(e: ServerWebInputException): ResponseEntity { - log.error(e.message) + log.error(e.message, e) val errorCode = ErrorCode.INVALID_REQUEST_FORMAT val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) @@ -64,7 +64,7 @@ open class ResolutionResultsServiceExceptionHandler { @ExceptionHandler fun ResolutionResultsServiceExceptionHandler(e: EmptyResultDataAccessException): ResponseEntity { - log.error(e.message) + log.error(e.message, e) var errorCode = ErrorCode.RESOURCE_NOT_FOUND val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) @@ -72,7 +72,7 @@ open class ResolutionResultsServiceExceptionHandler { @ExceptionHandler fun ResolutionResultsServiceExceptionHandler(e: JpaObjectRetrievalFailureException): ResponseEntity { - log.error(e.message) + log.error(e.message, e) var errorCode = ErrorCode.RESOURCE_NOT_FOUND val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) @@ -86,6 +86,12 @@ open class ResolutionResultsServiceExceptionHandler { val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) } + + @ExceptionHandler + fun ResolutionResultsServiceExceptionHandler(e: ResourceException): ResponseEntity { + log.error(e.message, e) + return ResponseEntity(ErrorMessage(e.message, e.code, debugMsg), HttpStatus.resolve(e.code)) + } } @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt new file mode 100644 index 000000000..40aa1a3e6 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt @@ -0,0 +1,84 @@ +/* + * Copyright © 2019 Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api + +import io.swagger.annotations.ApiOperation +import kotlinx.coroutines.runBlocking +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolution +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/api/v1/resources") +open class ResourceController(private var resourceResolutionDBService: ResourceResolutionDBService) { + + @RequestMapping(path = ["/ping"], method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE]) + @ResponseBody + fun ping(): String = runBlocking { + "Success" + } + + @RequestMapping(path = [""], + method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE]) + @ApiOperation(value = "Fetch all resource values associated to a resolution key. ", + notes = "Retrieve a stored resource value using the blueprint metadata, artifact name and the resolution-key.", + produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + @PreAuthorize("hasRole('USER')") + fun getAllFromResolutionKeyOrFromResourceTypeAndId(@RequestParam(value = "bpName", required = true) bpName: String, + @RequestParam(value = "bpVersion", required = true) bpVersion: String, + @RequestParam(value = "artifactName", required = false, defaultValue = "") artifactName: String, + @RequestParam(value = "resolutionKey", required = false, defaultValue = "") resolutionKey: String, + @RequestParam(value = "resourceType", required = false, defaultValue = "") resourceType: String, + @RequestParam(value = "resourceId", required = false, defaultValue = "") resourceId: String) + : ResponseEntity> = runBlocking { + + if ((resolutionKey.isNotEmpty() || artifactName.isNotEmpty()) && (resourceId.isNotEmpty() || resourceType.isNotEmpty())) { + throw ResourceException("Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.") + } else if (resolutionKey.isNotEmpty() && artifactName.isNotEmpty()) { + ResponseEntity.ok() + .body(resourceResolutionDBService.readWithResolutionKey(bpName, bpVersion, artifactName, resolutionKey)) + } else if (resourceType.isNotEmpty() && resourceId.isNotEmpty()){ + ResponseEntity.ok() + .body(resourceResolutionDBService.readWithResourceIdAndResourceType(bpName, bpVersion, resourceId, resourceType)) + } else { + throw ResourceException("Missing param. Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.") + } + } + + @RequestMapping(path = ["/resource"], + method = [RequestMethod.GET], + produces = [MediaType.APPLICATION_JSON_VALUE]) + @ApiOperation(value = "Fetch a resource value using resolution key.", + notes = "Retrieve a stored resource value using the blueprint metadata, artifact name, resolution-key along with the name of the resource value to retrieve.", + produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + @PreAuthorize("hasRole('USER')") + fun getOneFromResolutionKey(@RequestParam(value = "bpName", required = true) bpName: String, + @RequestParam(value = "bpVersion", required = true) bpVersion: String, + @RequestParam(value = "artifactName", required = true) artifactName: String, + @RequestParam(value = "resolutionKey", required = true) resolutionKey: String, + @RequestParam(value = "name", required = true) name: String) + : ResponseEntity = runBlocking { + + ResponseEntity.ok() + .body(resourceResolutionDBService.readValue(bpName, bpVersion, artifactName, resolutionKey, name)) + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceException.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceException.kt new file mode 100644 index 000000000..6815c05ef --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceException.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api + +class ResourceException(message: String) : RuntimeException(message) { + var code: Int = 404 +} + diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceControllerTest.kt new file mode 100644 index 000000000..fa8bf4459 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceControllerTest.kt @@ -0,0 +1,251 @@ +/* + * Copyright © 2019 Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api + +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.module.kotlin.readValue +import kotlinx.coroutines.runBlocking +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolution +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition +import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment +import org.python.jline.console.internal.ConsoleRunner.property +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.security.SecurityProperties +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest +import org.springframework.context.annotation.ComponentScan +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.TestPropertySource +import org.springframework.test.context.junit4.SpringRunner +import org.springframework.test.web.reactive.server.WebTestClient +import org.springframework.web.reactive.function.BodyInserters +import java.util.function.Consumer +import kotlin.test.BeforeTest +import org.h2.value.DataType.readValue +import java.util.* +import org.h2.value.DataType.readValue +import org.python.bouncycastle.asn1.x500.style.RFC4519Style.l +import org.h2.value.DataType.readValue +import java.lang.reflect.Array + + +@RunWith(SpringRunner::class) +@WebFluxTest +@ContextConfiguration(classes = [ResourceController::class, ResourceResolutionDBService::class, SecurityProperties::class]) +@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) +@TestPropertySource(locations = ["classpath:application-test.properties"]) +class ResourceControllerTest { + + private val log = LoggerFactory.getLogger(ResourceControllerTest::class.toString()) + + @Autowired + lateinit var resourceResolutionDBService: ResourceResolutionDBService + @Autowired + lateinit var webTestClient: WebTestClient + + val blueprintName = "baseconfiguration" + val blueprintVersion = "1.0.0" + val templatePrefix = "activate" + + @Test + fun `ping return Success`() { + runBlocking { + webTestClient.get().uri("/api/v1/resources/ping") + .exchange() + .expectStatus().isOk + .expectBody() + .equals("Success") + } + } + + @Test + fun getAllFromResolutionKeyTest() { + + val resolutionKey = "1" + val ra1 = createRA("bob") + val ra2 = createRA("dylan") + + runBlocking { + + store(ra1, resKey = resolutionKey) + store(ra2, resKey = resolutionKey) + + webTestClient + .get() + .uri("/api/v1/resources?bpName=$blueprintName&bpVersion=$blueprintVersion&artifactName=$templatePrefix&resolutionKey=$resolutionKey") + .exchange() + .expectStatus().isOk + .expectBody() + .consumeWith { + val json = String(it.responseBody!!) + val typeFactory = JacksonUtils.objectMapper.typeFactory + val list: List = JacksonUtils.objectMapper.readValue(json, + typeFactory.constructCollectionType(List::class.java, ResourceResolution::class.java)) + Assert.assertEquals(2, list.size) + assertEqual(ra1, list[0]) + assertEqual(ra1, list[0]) + } + } + } + + @Test + fun getAllFromFromResourceTypeAndIdTest() { + + val resourceId = "1" + val resourceType = "ServiceInstance" + val ra1 = createRA("bob") + val ra2 = createRA("dylan") + + runBlocking { + + store(ra1, resId = resourceId, resType = resourceType) + store(ra2, resId = resourceId, resType = resourceType) + + webTestClient + .get() + .uri("/api/v1/resources?bpName=$blueprintName&bpVersion=$blueprintVersion&resourceType=$resourceType&resourceId=$resourceId") + .exchange() + .expectStatus().isOk + .expectBody() + .consumeWith { + val json = String(it.responseBody!!) + val typeFactory = JacksonUtils.objectMapper.typeFactory + val list: List = JacksonUtils.objectMapper.readValue(json, + typeFactory.constructCollectionType(List::class.java, ResourceResolution::class.java)) + Assert.assertEquals(2, list.size) + assertEqual(ra1, list[0]) + assertEqual(ra1, list[0]) + } + } + } + + + @Test + fun getAllFromMissingParamTest() { + runBlocking { + webTestClient + .get() + .uri("/api/v1/resources?bpName=$blueprintName&bpVersion=$blueprintVersion") + .exchange() + .expectStatus().is4xxClientError + .expectBody() + .consumeWith { + val r = JacksonUtils.objectMapper.readValue(it.responseBody, ErrorMessage::class.java) + Assert.assertEquals("Missing param. Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.", + r.message) + } + } + } + + @Test + fun getAllFromWrongInputTest() { + runBlocking { + webTestClient + .get() + .uri("/api/v1/resources?bpName=$blueprintName&bpVersion=$blueprintVersion&artifactName=$templatePrefix&resolutionKey=test&resourceId=1") + .exchange() + .expectStatus().is4xxClientError + .expectBody() + .consumeWith { + val r = JacksonUtils.objectMapper.readValue(it.responseBody, ErrorMessage::class.java) + Assert.assertEquals("Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.", + r.message) + } + } + } + + @Test + fun getOneFromResolutionKeyTest() { + val resolutionKey = "3" + val ra = createRA("joe") + runBlocking { + store(ra, resKey = resolutionKey) + } + runBlocking { + webTestClient.get() + .uri("/api/v1/resources/resource?bpName=$blueprintName&bpVersion=$blueprintVersion&artifactName=$templatePrefix&resolutionKey=$resolutionKey&name=joe") + .exchange() + .expectStatus().isOk + .expectBody() + .consumeWith { + val r = JacksonUtils.objectMapper.readValue(it.responseBody, ResourceResolution::class.java) + assertEqual(ra, r) + } + } + } + + @Test + fun getOneFromResolutionKey404Test() { + val resolutionKey = "3" + runBlocking { + webTestClient.get() + .uri("/api/v1/resources/resource?bpName=$blueprintName&bpVersion=$blueprintVersion&artifactName=$templatePrefix&resolutionKey=$resolutionKey&name=doesntexist") + .exchange() + .expectStatus().is4xxClientError + .expectBody() + } + } + + private suspend fun store(resourceAssignment: ResourceAssignment, resKey: String = "", resId: String = "", + resType: String = "") { + resourceResolutionDBService.write(blueprintName, + blueprintVersion, + resKey, + resId, + resType, + templatePrefix, + resourceAssignment) + } + + private fun createRA(prefix: String): ResourceAssignment { + val property = PropertyDefinition() + property.value = "value$prefix".asJsonPrimitive() + + val resourceAssignment = ResourceAssignment() + resourceAssignment.name = prefix + resourceAssignment.dictionaryName = "dd$prefix" + resourceAssignment.dictionarySource = "source$prefix" + resourceAssignment.version = 2 + resourceAssignment.status = "SUCCESS" + resourceAssignment.property = property + return resourceAssignment + } + + private fun assertEqual(resourceAssignment: ResourceAssignment, resourceResolution: ResourceResolution) { + Assert.assertEquals(JacksonUtils.getValue(resourceAssignment.property?.value!!).toString(), + resourceResolution.value) + Assert.assertEquals(resourceAssignment.status, resourceResolution.status) + Assert.assertEquals(resourceAssignment.dictionarySource, resourceResolution.dictionarySource) + Assert.assertEquals(resourceAssignment.dictionaryName, resourceResolution.dictionaryName) + Assert.assertEquals(resourceAssignment.version, resourceResolution.dictionaryVersion) + Assert.assertEquals(resourceAssignment.name, resourceResolution.name) + Assert.assertEquals(blueprintVersion, resourceResolution.blueprintVersion) + Assert.assertEquals(blueprintName, resourceResolution.blueprintName) + + } +} \ No newline at end of file -- cgit 1.2.3-korg