diff options
18 files changed, 328 insertions, 83 deletions
diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_cli/Definitions/capability-cli-blueprint.json b/components/model-catalog/blueprint-model/test-blueprint/capability_cli/Definitions/capability-cli-blueprint.json new file mode 100644 index 000000000..c66bb6ef2 --- /dev/null +++ b/components/model-catalog/blueprint-model/test-blueprint/capability_cli/Definitions/capability-cli-blueprint.json @@ -0,0 +1,83 @@ +{ + "tosca_definitions_version": "controller_blueprint_1_0_0", + "metadata": { + "template_author": "Brinda Santh Muthuramalingam", + "author-email": "brindasanth@in.ibm.com", + "user-groups": "ADMIN, OPERATION", + "template_name": "capability-cli", + "template_version": "1.0.0", + "template_tags": "brinda, tosca" + }, + "imports": [ + { + "file": "Definitions/data_types.json" + }, + { + "file": "Definitions/relationship_types.json" + }, + { + "file": "Definitions/artifact_types.json" + }, + { + "file": "Definitions/node_types.json" + }, + { + "file": "Definitions/policy_types.json" + } + ], + "dsl_definitions": { + "config-deploy-properties": { + "resolution-key": { + "get_input": "resolution-key" + } + } + }, + "topology_template": { + "workflows": { + "check": { + "steps": { + "activate-process": { + "description": "Check CLI", + "target": "check", + "activities": [ + { + "call_operation": "ComponentCliExecutor.process" + } + ] + } + } + } + }, + "node_templates": { + "check": { + "type": "component-cli-executor", + "interfaces": { + "ComponentCliExecutor": { + "operations": { + "process": { + "implementation": { + "primary": "component-script" + }, + "inputs": { + "script-type": "kotlin", + "script-class-reference": "InternalSimpleCli_cba$TestCliScriptFunction", + "instance-dependencies": [] + }, + "outputs": { + "response-data": "", + "status": "success" + } + } + } + } + }, + "artifacts": { + "command-template": { + "type": "artifact-template-velocity", + "file": "Templates/check-command-template.vtl" + } + } + } + } + } +}
\ No newline at end of file diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_cli/Scripts/kotlin/CapabilityCli.cba.kts b/components/model-catalog/blueprint-model/test-blueprint/capability_cli/Scripts/kotlin/CapabilityCli.cba.kts new file mode 100644 index 000000000..e22fd7ef0 --- /dev/null +++ b/components/model-catalog/blueprint-model/test-blueprint/capability_cli/Scripts/kotlin/CapabilityCli.cba.kts @@ -0,0 +1,34 @@ +/* + * Copyright © 2019 IBM. + * + * 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. + */ + + + +open class Check : CliComponentFunction() { + + private val log = LoggerFactory.getLogger(CliComponentFunction::class.java)!! + + override fun getName(): String { + return "SimpleCliConfigure" + } + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + log.info("Executing process") + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + log.info("Executing Recovery") + } +}
\ No newline at end of file diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_cli/TOSCA-Metadata/TOSCA.meta b/components/model-catalog/blueprint-model/test-blueprint/capability_cli/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 000000000..001889672 --- /dev/null +++ b/components/model-catalog/blueprint-model/test-blueprint/capability_cli/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,5 @@ +TOSCA-Meta-File-Version: 1.0.0 +CSAR-Version: 1.0 +Created-By: Brinda Santh +Entry-Definitions: Definitions/capability-cli-blueprint.json +Template-Tags: capability-cli-blueprint 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 6dcffca09..c7f35f7c8 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 @@ -22,6 +22,9 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.Reso import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction import org.onap.ccsdk.cds.blueprintsprocessor.ssh.SshLibConstants import org.onap.ccsdk.cds.blueprintsprocessor.ssh.service.BluePrintSshLibPropertyService +import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile +import org.onap.ccsdk.cds.controllerblueprints.core.readNBLines +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService abstract class CliComponentFunction : AbstractScriptComponentFunction() { @@ -32,6 +35,18 @@ abstract class CliComponentFunction : AbstractScriptComponentFunction() { functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) + open suspend fun readCommandLinesFromArtifact(artifactName: String): List<String> { + val artifactDefinition = bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName) + val file = normalizedFile(bluePrintRuntimeService.bluePrintContext().rootPath, artifactDefinition.file) + return file.readNBLines() + } + + suspend fun generateMessage(artifactName: String, json: String): String { + val templateService = BluePrintTemplateService() + return templateService.generateContent(bluePrintRuntimeService, nodeTemplateName, artifactName, json, true) + } + + fun generateMessage(artifactName: String): String { return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) } diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutor.kt b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutor.kt index 8c58272f1..0c1c52320 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutor.kt +++ b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutor.kt @@ -35,6 +35,7 @@ open class ComponentCliExecutor(private var componentFunctionScriptingService: C const val SCRIPT_TYPE = "script-type" const val SCRIPT_CLASS_REFERENCE = "script-class-reference" const val INSTANCE_DEPENDENCIES = "instance-dependencies" + const val RESPONSE_DATA = "response-data" } private lateinit var scriptComponent: CliComponentFunction diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/scripts/InternalSimpleCli.cba.kts b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/scripts/InternalSimpleCli.cba.kts index 136d01143..18d4a4797 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/scripts/InternalSimpleCli.cba.kts +++ b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/scripts/InternalSimpleCli.cba.kts @@ -18,6 +18,8 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput import org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor.CliComponentFunction +import org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor.ComponentCliExecutor +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.slf4j.LoggerFactory open class TestCliScriptFunction : CliComponentFunction() { @@ -36,3 +38,41 @@ open class TestCliScriptFunction : CliComponentFunction() { log.info("Executing Recovery") } } + + +open class Check : CliComponentFunction() { + + private val log = LoggerFactory.getLogger(CliComponentFunction::class.java)!! + + override fun getName(): String { + return "Check" + } + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + // Get the Device Information from the DSL Model + val deviceInformation = bluePrintRuntimeService.resolveDSLExpression("device-properties") + + // Get the Client Service + val sshClientService = bluePrintSshLibPropertyService().blueprintSshClientService(deviceInformation) + + sshClientService.startSessionNB() + + // Read Commands + val commands = readCommandLinesFromArtifact("command-template") + + // Execute multiple Commands + val responseLog = sshClientService.executeCommandsNB(commands, 5000) + + // Close Session + sshClientService.closeSessionNB() + + // Set the Response Data + setAttribute(ComponentCliExecutor.RESPONSE_DATA, responseLog.asJsonPrimitive()) + + log.info("Executing process") + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + log.info("Executing Recovery") + } +} 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 51062256d..ebff47899 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 @@ -46,10 +46,10 @@ interface ResourceResolutionService { artifactNames: List<String>, properties: Map<String, Any>): MutableMap<String, String> suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactPrefix: String, properties: Map<String, Any>): String + artifactPrefix: String, properties: Map<String, Any>): String suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactMapping: String, artifactTemplate: String?): String + artifactMapping: String, artifactTemplate: String?): String suspend fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>, resourceDefinitions: MutableMap<String, ResourceDefinition>, @@ -89,7 +89,7 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica } override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactPrefix: String, properties: Map<String, Any>): String { + artifactPrefix: String, properties: Map<String, Any>): String { // Velocity Artifact Definition Name val artifactTemplate = "$artifactPrefix-template" @@ -110,7 +110,7 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactMapping: String, artifactTemplate: String?): String { + artifactMapping: String, artifactTemplate: String?): String { val resolvedContent: String log.info("Resolving resource for template artifact($artifactTemplate) with resource assignment artifact($artifactMapping)") @@ -137,11 +137,9 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica // Check Template is there if (artifactTemplate != null) { - val blueprintTemplateService = BluePrintTemplateService(bluePrintRuntimeService, nodeTemplateName, artifactTemplate) - val templateContent = - bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactTemplate) - - resolvedContent = blueprintTemplateService.generateContent(templateContent, resolvedParamJsonContent) + val blueprintTemplateService = BluePrintTemplateService() + resolvedContent = blueprintTemplateService.generateContent(bluePrintRuntimeService, nodeTemplateName, + artifactTemplate, resolvedParamJsonContent) } else { resolvedContent = resolvedParamJsonContent diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/ResourceAssignmentProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/ResourceAssignmentProcessor.kt index 8dbd47cc2..3482d4534 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/ResourceAssignmentProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/ResourceAssignmentProcessor.kt @@ -25,6 +25,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.util import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintFunctionNode import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintVelocityTemplateService import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils @@ -67,6 +68,7 @@ abstract class ResourceAssignmentProcessor : BlueprintFunctionNode<ResourceAssig ?: throw BluePrintProcessorException("couldn't get resource definition for ($name)") } + //TODO("Convert return Map<String, JsonNode>") open fun resolveInputKeyMappingVariables(inputKeyMapping: Map<String, String>): Map<String, Any> { val resolvedInputKeyMapping = HashMap<String, Any>() if (MapUtils.isNotEmpty(inputKeyMapping)) { @@ -80,12 +82,14 @@ abstract class ResourceAssignmentProcessor : BlueprintFunctionNode<ResourceAssig return resolvedInputKeyMapping } + //TODO("Convert keyMapping = MutableMap<String, JsonNode>") open suspend fun resolveFromInputKeyMapping(valueToResolve: String, keyMapping: MutableMap<String, Any>): String { if (valueToResolve.isEmpty() || !valueToResolve.contains("$")) { return valueToResolve } - return BluePrintVelocityTemplateService.generateContent(valueToResolve, additionalContext = keyMapping) + //TODO("Optimize to JSON Node directly") + return BluePrintVelocityTemplateService.generateContent(valueToResolve, keyMapping.asJsonNode().toString()) } final override suspend fun applyNB(resourceAssignment: ResourceAssignment): Boolean { diff --git a/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/service/BasicAuthSshClientService.kt b/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/service/BasicAuthSshClientService.kt index 67d5d5153..adbde0f87 100644 --- a/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/service/BasicAuthSshClientService.kt +++ b/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/service/BasicAuthSshClientService.kt @@ -36,6 +36,7 @@ open class BasicAuthSshClientService(private val basicAuthSshClientProperties: B private lateinit var sshClient: SshClient private lateinit var clientSession: ClientSession + var channel: ChannelExec? = null override suspend fun startSessionNB(): ClientSession { sshClient = SshClient.setUpDefaultClient() @@ -69,31 +70,29 @@ open class BasicAuthSshClientService(private val basicAuthSshClientProperties: B override suspend fun executeCommandNB(command: String, timeOut: Long): String { log.debug("Executing host($clientSession) command($command)") - var channel: ChannelExec? = null - try { - channel = clientSession.createExecChannel(command) - //TODO("Convert to streaming ") - val outputStream = ByteArrayOutputStream() - channel.out = outputStream - channel.err = outputStream - channel.open().await() - val waitMask = channel.waitFor(Collections.unmodifiableSet(EnumSet.of(ClientChannelEvent.CLOSED)), timeOut) - if (waitMask.contains(ClientChannelEvent.TIMEOUT)) { - throw BluePrintProcessorException("Failed to retrieve command result in time: $command") - } - val exitStatus = channel.exitStatus - ClientChannel.validateCommandExitStatusCode(command, exitStatus!!) - return outputStream.toString() - } finally { - if (channel != null) - channel.close() + channel = clientSession.createExecChannel(command) + checkNotNull(channel) { "failed to create Channel for the command : $command" } + + //TODO("Convert to streaming ") + val outputStream = ByteArrayOutputStream() + channel!!.out = outputStream + channel!!.err = outputStream + channel!!.open().await() + val waitMask = channel!!.waitFor(Collections.unmodifiableSet(EnumSet.of(ClientChannelEvent.CLOSED)), timeOut) + if (waitMask.contains(ClientChannelEvent.TIMEOUT)) { + throw BluePrintProcessorException("Failed to retrieve command result in time: $command") } + val exitStatus = channel!!.exitStatus + ClientChannel.validateCommandExitStatusCode(command, exitStatus!!) + return outputStream.toString() } override suspend fun closeSessionNB() { + if (channel != null) + channel!!.close() if (sshClient.isStarted) { sshClient.stop() - log.debug("SSH Client Service stopped successfully") } + log.debug("SSH Client Service stopped successfully") } } diff --git a/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/service/BluePrintSshLibPropertyService.kt b/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/service/BluePrintSshLibPropertyService.kt index 9971c500f..1950b71aa 100644 --- a/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/service/BluePrintSshLibPropertyService.kt +++ b/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/service/BluePrintSshLibPropertyService.kt @@ -16,16 +16,23 @@ package org.onap.ccsdk.cds.blueprintsprocessor.ssh.service +import com.fasterxml.jackson.databind.JsonNode import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintProperties import org.onap.ccsdk.cds.blueprintsprocessor.ssh.BasicAuthSshClientProperties import org.onap.ccsdk.cds.blueprintsprocessor.ssh.SshClientProperties import org.onap.ccsdk.cds.blueprintsprocessor.ssh.SshLibConstants import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.stereotype.Service @Service(SshLibConstants.SERVICE_BLUEPRINT_SSH_LIB_PROPERTY) open class BluePrintSshLibPropertyService(private var bluePrintProperties: BluePrintProperties) { + fun blueprintSshClientService(jsonNode: JsonNode): BlueprintSshClientService { + val restClientProperties = sshClientProperties(jsonNode) + return blueprintSshClientService(restClientProperties) + } + fun blueprintSshClientService(selector: String): BlueprintSshClientService { val prefix = "${SshLibConstants.PROPERTY_SSH_CLIENT_PREFIX}$selector" val sshClientProperties = sshClientProperties(prefix) @@ -44,6 +51,19 @@ open class BluePrintSshLibPropertyService(private var bluePrintProperties: BlueP } } + fun sshClientProperties(jsonNode: JsonNode): SshClientProperties { + val type = jsonNode.get("type").textValue() + return when (type) { + SshLibConstants.TYPE_BASIC_AUTH -> { + JacksonUtils.readValue(jsonNode, + BasicAuthSshClientProperties::class.java)!! + } + else -> { + throw BluePrintProcessorException("SSH adaptor($type) is not supported") + } + } + } + private fun blueprintSshClientService(sshClientProperties: SshClientProperties): BlueprintSshClientService { when (sshClientProperties) { diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/CustomFunctions.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/CustomFunctions.kt index 0e45232f2..583fc9d4d 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/CustomFunctions.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/CustomFunctions.kt @@ -122,6 +122,18 @@ fun JsonNode.rootFieldsToMap(): MutableMap<String, JsonNode> { } } +fun JsonNode.removeNullNode() { + val it = this.iterator() + while (it.hasNext()) { + val child = it.next() + if (child.isNull) { + it.remove() + } else { + child.removeNullNode() + } + } +} + fun MutableMap<String, JsonNode>.putJsonElement(key: String, value: Any) { val convertedValue = value.asJsonType() diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BlueprintTemplateService.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BlueprintTemplateService.kt index ec1542cd3..86bf3ff56 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BlueprintTemplateService.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BlueprintTemplateService.kt @@ -18,21 +18,43 @@ package org.onap.ccsdk.cds.controllerblueprints.core.interfaces import com.fasterxml.jackson.core.io.CharTypes import com.fasterxml.jackson.databind.node.JsonNodeFactory import com.fasterxml.jackson.databind.node.TextNode +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService interface BlueprintTemplateService { /** * Generate dynamique content using Velocity Template or Jinja template * + * @param bluePrintRuntimeService blueprint runtime + * @param nodeTemplateName node template + * @param artifactName Artifact Name + * @param jsonData json string data content to mash + * @param ignoreJsonNull Ignore Null value in the JSON content + * @param additionalContext (Key, value) mutable map for additional variables + * @return Content result + * + **/ + suspend fun generateContent(bluePrintRuntimeService: BluePrintRuntimeService<*>, + nodeTemplateName: String, + artifactName: String, + jsonData: String = "", + ignoreJsonNull: Boolean = false, + additionalContext: MutableMap<String, Any> = mutableMapOf()): String + + + /** + * Generate dynamique content using Velocity Template or Jinja template + * * @param template template string content - * @param json json string content + * @param templateType template type + * @param jsonData json string data content to mash * @param ignoreJsonNull Ignore Null value in the JSON content * @param additionalContext (Key, value) mutable map for additional variables * @return Content result * **/ - suspend fun generateContent(template: String, json: String = "", ignoreJsonNull: Boolean = false, - additionalContext: MutableMap<String, Any> = mutableMapOf()): String + suspend fun generateContent(template: String, templateType: String, jsonData: String = "", ignoreJsonNull: Boolean = false, + additionalContext: MutableMap<String, Any> = mutableMapOf()): String } /** diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintJinjaTemplateService.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintJinjaTemplateService.kt index f835cbe52..912667e0a 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintJinjaTemplateService.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintJinjaTemplateService.kt @@ -21,14 +21,13 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.hubspot.jinjava.Jinjava import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintJsonNodeFactory -import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintTemplateService -import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.core.removeNullNode -object BluePrintJinjaTemplateService: BlueprintTemplateService { +object BluePrintJinjaTemplateService { - override suspend fun generateContent(template: String, json: String, ignoreJsonNull: Boolean, - additionalContext: MutableMap<String, Any>): String { + fun generateContent(template: String, json: String, ignoreJsonNull: Boolean, + additionalContext: MutableMap<String, Any>): String { // Load template val jinJava = Jinjava() val mapper = ObjectMapper() @@ -40,7 +39,7 @@ object BluePrintJinjaTemplateService: BlueprintTemplateService { val jsonNode = mapper.readValue<JsonNode>(json, JsonNode::class.java) ?: throw BluePrintProcessorException("couldn't get json node from json") if (ignoreJsonNull) - JacksonUtils.removeJsonNullNode(jsonNode) + jsonNode.removeNullNode() jsonNode.fields().forEach { entry -> additionalContext[entry.key] = entry.value } diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintVelocityTemplateService.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintVelocityTemplateService.kt index 4b6905bff..496182ee7 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintVelocityTemplateService.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintVelocityTemplateService.kt @@ -26,35 +26,50 @@ import org.apache.velocity.VelocityContext import org.apache.velocity.app.Velocity import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintJsonNodeFactory -import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintTemplateService -import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.core.removeNullNode import java.io.StringWriter -object BluePrintVelocityTemplateService: BlueprintTemplateService { +object BluePrintVelocityTemplateService { /** - * Generate Content from Velocity Template and JSON Content or property map. + * Generate Content from Velocity Template and JSON Content with injected API */ - override suspend fun generateContent(template: String, json: String, ignoreJsonNull: Boolean, additionalContext: - MutableMap<String, Any>): String { - Velocity.init() + fun generateContent(template: String, json: String, ignoreJsonNull: Boolean = false, + additionalContext: MutableMap<String, Any> = mutableMapOf()): String { + + // Customized Object Mapper to remove String double quotes val mapper = ObjectMapper() val nodeFactory = BluePrintJsonNodeFactory() mapper.nodeFactory = nodeFactory + val jsonNode: JsonNode? = if (json.isNotEmpty()) { + mapper.readValue(json, JsonNode::class.java) + ?: throw BluePrintProcessorException("couldn't get json node from json") + } else { + null + } + return generateContent(template, jsonNode, ignoreJsonNull, additionalContext) + } + + /** + * Generate Content from Velocity Template and JSON Node with injected API + */ + fun generateContent(template: String, jsonNode: JsonNode?, ignoreJsonNull: Boolean = false, + additionalContext: MutableMap<String, Any> = mutableMapOf()): String { + + Velocity.init() + val velocityContext = VelocityContext() velocityContext.put("StringUtils", StringUtils::class.java) velocityContext.put("BooleanUtils", BooleanUtils::class.java) // Add the Custom Velocity Context API - additionalContext.forEach { name, value -> velocityContext.put(name, value) } + additionalContext.forEach { (name, value) -> velocityContext.put(name, value) } // Add the JSON Data to the context - if (json.isNotEmpty()) { - val jsonNode = mapper.readValue<JsonNode>(json, JsonNode::class.java) - ?: throw BluePrintProcessorException("couldn't get json node from json") + if (jsonNode != null) { if (ignoreJsonNull) - JacksonUtils.removeJsonNullNode(jsonNode) + jsonNode.removeNullNode() jsonNode.fields().forEach { entry -> velocityContext.put(entry.key, entry.value) } @@ -64,6 +79,7 @@ object BluePrintVelocityTemplateService: BlueprintTemplateService { Velocity.evaluate(velocityContext, stringWriter, "TemplateData", template) stringWriter.flush() return stringWriter.toString() + } } diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BlueprintTemplateService.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BlueprintTemplateService.kt index 73457b986..45e2678ed 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BlueprintTemplateService.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BlueprintTemplateService.kt @@ -20,19 +20,26 @@ import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintTemplateService import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils -class BluePrintTemplateService(val bluePrintRuntimeService: BluePrintRuntimeService<*>, - val nodeTemplateName: String, val artifactName: String): - BlueprintTemplateService { +class BluePrintTemplateService : BlueprintTemplateService { + + override suspend fun generateContent(bluePrintRuntimeService: BluePrintRuntimeService<*>, + nodeTemplateName: String, artifactName: String, jsonData: String, + ignoreJsonNull: Boolean, additionalContext: MutableMap<String, Any>): String { - override suspend fun generateContent(template: String, json: String, ignoreJsonNull: Boolean, additionalContext: MutableMap<String, Any>): String { val artifactDefinition = bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName) val templateType = artifactDefinition.type + val template = bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) + return generateContent(template, templateType, jsonData, ignoreJsonNull, additionalContext) + } + + override suspend fun generateContent(template: String, templateType: String, jsonData: String, ignoreJsonNull: Boolean, + additionalContext: MutableMap<String, Any>): String { return when (templateType) { BluePrintConstants.ARTIFACT_JINJA_TYPE_NAME -> { - BluePrintJinjaTemplateService.generateContent(template, json, ignoreJsonNull, additionalContext) + BluePrintJinjaTemplateService.generateContent(template, jsonData, ignoreJsonNull, additionalContext) } BluePrintConstants.ARTIFACT_VELOCITY_TYPE_NAME -> { - BluePrintVelocityTemplateService.generateContent(template, json, ignoreJsonNull, additionalContext) + BluePrintVelocityTemplateService.generateContent(template, jsonData, ignoreJsonNull, additionalContext) } else -> { throw BluePrintProcessorException("Unknown Artifact type, expecting ${BluePrintConstants.ARTIFACT_JINJA_TYPE_NAME}" + @@ -41,9 +48,11 @@ class BluePrintTemplateService(val bluePrintRuntimeService: BluePrintRuntimeServ } } - suspend fun generateContentFromFiles(templatePath: String, jsonPath: String, ignoreJsonNull: Boolean, additionalContext: MutableMap<String, Any>): String { + suspend fun generateContentFromFiles(templatePath: String, templateType: String, jsonPath: String, + ignoreJsonNull: Boolean, + additionalContext: MutableMap<String, Any>): String { val json = JacksonUtils.getClassPathFileContent(jsonPath) val template = JacksonUtils.getClassPathFileContent(templatePath) - return generateContent(template, json, ignoreJsonNull, additionalContext) + return generateContent(template, templateType, json, ignoreJsonNull, additionalContext) } }
\ No newline at end of file diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt index 7b5f181da..5e9fd6207 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt @@ -58,19 +58,6 @@ class JacksonUtils { return objectMapper.treeToValue(node, valueType) } - fun removeJsonNullNode(node: JsonNode) { - val it = node.iterator() - while (it.hasNext()) { - val child = it.next() - if (child.isNull) { - it.remove() - } else { - removeJsonNullNode(child) - } - } - } - - fun getContent(fileName: String): String = runBlocking { try { normalizedFile(fileName).readNBText() diff --git a/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateServiceTest.kt b/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateServiceTest.kt index e4227180b..02505acad 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateServiceTest.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateServiceTest.kt @@ -21,6 +21,7 @@ package org.onap.ccsdk.cds.controllerblueprints.core.service import kotlinx.coroutines.runBlocking import org.junit.Test import org.junit.runner.RunWith +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.test.context.junit4.SpringRunner @@ -40,13 +41,13 @@ class BluePrintTemplateServiceTest { @Test fun testVelocityGeneratedContent() { - runBlocking { - val template = JacksonUtils.getClassPathFileContent("templates/base-config-velocity-template.vtl") - val json = JacksonUtils.getClassPathFileContent("templates/base-config-data-velocity.json") + runBlocking { + val template = JacksonUtils.getClassPathFileContent("templates/base-config-velocity-template.vtl") + val json = JacksonUtils.getClassPathFileContent("templates/base-config-data-velocity.json") - val content = BluePrintVelocityTemplateService.generateContent(template, json) - assertNotNull(content, "failed to generate content for velocity template") - } + val content = BluePrintVelocityTemplateService.generateContent(template, json) + assertNotNull(content, "failed to generate content for velocity template") + } } @@ -68,13 +69,12 @@ class BluePrintTemplateServiceTest { @Test fun testVelocityGeneratedContentFromFiles() { runBlocking { - val bluePrintTemplateService = BluePrintTemplateService(blueprintRuntime, - "resource-assignment", "baseconfig-template") + val bluePrintTemplateService = BluePrintTemplateService() val templateFile = "templates/base-config-velocity-template.vtl" val jsonFile = "templates/base-config-data-velocity.json" val content = bluePrintTemplateService.generateContentFromFiles( - templateFile, jsonFile, false, mutableMapOf()) + templateFile, BluePrintConstants.ARTIFACT_VELOCITY_TYPE_NAME, jsonFile, false, mutableMapOf()) assertNotNull(content, "failed to generate content for velocity template") } @@ -86,14 +86,13 @@ class BluePrintTemplateServiceTest { var element: MutableMap<String, Any> = mutableMapOf() element["additional_array"] = arrayListOf(hashMapOf("name" to "Element1", "location" to "Region0"), hashMapOf("name" to "Element2", "location" to "Region1")) - val bluePrintTemplateService = BluePrintTemplateService(blueprintRuntime, - "resource-assignment", "another-template") + val bluePrintTemplateService = BluePrintTemplateService() val templateFile = "templates/base-config-jinja-template.jinja" val jsonFile = "templates/base-config-data-jinja.json" val content = bluePrintTemplateService.generateContentFromFiles( - templateFile, + templateFile, BluePrintConstants.ARTIFACT_JINJA_TYPE_NAME, jsonFile, false, element) assertNotNull(content, "failed to generate content for velocity template") } diff --git a/ms/controllerblueprints/modules/service/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/enhancer/BluePrintEnhancerServiceImplTest.kt b/ms/controllerblueprints/modules/service/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/enhancer/BluePrintEnhancerServiceImplTest.kt index e1c5c402e..b4c29dec3 100644 --- a/ms/controllerblueprints/modules/service/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/enhancer/BluePrintEnhancerServiceImplTest.kt +++ b/ms/controllerblueprints/modules/service/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/enhancer/BluePrintEnhancerServiceImplTest.kt @@ -23,9 +23,11 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.onap.ccsdk.cds.controllerblueprints.TestApplication +import org.onap.ccsdk.cds.controllerblueprints.core.compress import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintEnhancerService import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintValidatorService +import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName import org.onap.ccsdk.cds.controllerblueprints.service.load.ModelTypeLoadService import org.onap.ccsdk.cds.controllerblueprints.service.load.ResourceDictionaryLoadService |