From 7466e4277c9fe098a61ae126d1892b3cd30d6f89 Mon Sep 17 00:00:00 2001 From: Brinda Santh Date: Mon, 2 Dec 2019 19:04:13 -0500 Subject: [PATCH] Remote Script Executor Component Define and Implement component-remote-script-executor component and DSL. Get the timeout from model definitions fix the dat pattern issues Define API data extension functions. Issue-ID: CCSDK-1975 Signed-off-by: Brinda Santh Change-Id: I41a429eb21a050e5ab512a7a73a394b975543f31 --- .../component-remote-script-executor.json | 66 +++++++ .../cli/executor/ComponentCliExecutorTest.kt | 7 + .../executor/ComponentRestconfExecutorTest.kt | 16 +- .../grpc/service/GrpcLoggerService.kt | 4 +- .../message/service/MessageLoggerService.kt | 3 +- .../blueprintsprocessor/core/ApiDataExtensions.kt | 28 +++ .../{BluePrintMappings.kt => ApiDataUtils.kt} | 94 ++++++++-- .../blueprintsprocessor/core/utils/PayloadUtils.kt | 61 +++++-- .../core/utils/BluePrintMappingsTest.kt | 3 +- .../rest/service/RestLoggerService.kt | 7 +- .../execution/AbstractComponentFunction.kt | 22 ++- .../execution/ComponentRemoteScriptExecutor.kt | 106 +++++++++++ .../execution/ComponentRemoteScriptExecutorDSL.kt | 148 ++++++++++++++++ .../execution/ComponentRemoteScriptExecutorTest.kt | 196 +++++++++++++++++++++ .../scripts/AbstractComponentFunctionTest.kt | 8 +- .../workflow/NodeTemplateExecutionService.kt | 8 +- .../core/BluePrintConstants.kt | 7 + .../controllerblueprints/core/utils/DateUtils.kt | 26 ++- 18 files changed, 754 insertions(+), 56 deletions(-) create mode 100644 components/model-catalog/definition-type/starter-type/node_type/component-remote-script-executor.json rename ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/{BluePrintMappings.kt => ApiDataUtils.kt} (63%) create mode 100644 ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutor.kt create mode 100644 ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorDSL.kt create mode 100644 ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorTest.kt diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-remote-script-executor.json b/components/model-catalog/definition-type/starter-type/node_type/component-remote-script-executor.json new file mode 100644 index 000000000..6909d20bc --- /dev/null +++ b/components/model-catalog/definition-type/starter-type/node_type/component-remote-script-executor.json @@ -0,0 +1,66 @@ +{ + "description": "Generic Remote Script Component Executor", + "version": "1.0.0", + "attributes": { + "response-data": { + "description": "Remote executed response data.", + "required": false, + "type": "json" + }, + "status": { + "description": "Remote execution status.", + "required": true, + "type": "string" + } + }, + "interfaces": { + "ComponentRemoteScriptExecutor": { + "operations": { + "process": { + "description": "ComponentRemoteScriptExecutor Operation", + "inputs": { + "blueprint-version": { + "description": "Blueprint version.", + "required": true, + "type": "string" + }, + "blueprint-name": { + "description": "Blueprint name.", + "required": true, + "type": "string" + }, + "selector": { + "description": "Remote GRPC selector or DSL reference or GRPC Json config.", + "required": true, + "type": "json" + }, + "blueprint-action": { + "description": "Blueprint action name.", + "required": true, + "type": "string" + }, + "timeout": { + "description": "Remote execution timeout in sec.", + "required": true, + "type": "integer", + "default": 180 + }, + "request-data": { + "description": "Dynamic Json Content or DSL Json reference.", + "required": false, + "type": "json" + } + }, + "outputs": { + "status": { + "description": "Status of the Component Execution ( success or failure )", + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" +} diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt b/ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt index 1f070d46d..50268d39b 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt +++ b/ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt @@ -34,6 +34,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServic import org.onap.ccsdk.cds.blueprintsprocessor.ssh.BluePrintSshLibConfiguration import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintScriptsServiceImpl import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService @@ -92,6 +93,12 @@ class ComponentCliExecutorTest { executionServiceInput.stepData = stepInputData val blueprintContext = mockk() + every { + blueprintContext.nodeTemplateOperationImplementation( + any(), any(), any() + ) + } returns Implementation() + every { bluePrintRuntime.bluePrintContext() } returns blueprintContext every { bluePrintRuntime.resolveNodeTemplateInterfaceOperationInputs( diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt index 7d81ef3dc..47cf34fad 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt +++ b/ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt @@ -30,6 +30,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFuncti import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentScriptExecutor import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils @@ -57,7 +58,17 @@ class ComponentRestconfExecutorTest { } payload = JacksonUtils.jsonNode("{}") as ObjectNode } + + val blueprintContext = mockk() + every { + blueprintContext.nodeTemplateOperationImplementation( + any(), any(), any() + ) + } returns Implementation() + val bluePrintRuntime = mockk("1234") + every { bluePrintRuntime.bluePrintContext() } returns blueprintContext + componentScriptExecutor.bluePrintRuntimeService = bluePrintRuntime componentScriptExecutor.stepName = "sample-step" @@ -65,7 +76,8 @@ class ComponentRestconfExecutorTest { operationInputs[BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE] = "activate-restconf".asJsonPrimitive() operationInputs[BluePrintConstants.PROPERTY_CURRENT_INTERFACE] = "interfaceName".asJsonPrimitive() operationInputs[BluePrintConstants.PROPERTY_CURRENT_OPERATION] = "operationName".asJsonPrimitive() - operationInputs[ComponentScriptExecutor.INPUT_SCRIPT_TYPE] = BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive() + operationInputs[ComponentScriptExecutor.INPUT_SCRIPT_TYPE] = + BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive() operationInputs[ComponentScriptExecutor.INPUT_SCRIPT_CLASS_REFERENCE] = "internal.scripts.TestRestconfConfigure".asJsonPrimitive() @@ -75,8 +87,6 @@ class ComponentRestconfExecutorTest { } executionServiceInput.stepData = stepInputData - val blueprintContext = mockk() - every { bluePrintRuntime.bluePrintContext() } returns blueprintContext every { bluePrintRuntime.resolveNodeTemplateInterfaceOperationInputs( "activate-restconf", diff --git a/ms/blueprintsprocessor/modules/commons/grpc-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/grpc/service/GrpcLoggerService.kt b/ms/blueprintsprocessor/modules/commons/grpc-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/grpc/service/GrpcLoggerService.kt index 510a21581..732f4fecf 100644 --- a/ms/blueprintsprocessor/modules/commons/grpc-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/grpc/service/GrpcLoggerService.kt +++ b/ms/blueprintsprocessor/modules/commons/grpc-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/grpc/service/GrpcLoggerService.kt @@ -23,6 +23,7 @@ import io.grpc.ServerCallHandler import org.onap.ccsdk.cds.blueprintsprocessor.grpc.getStringKey import org.onap.ccsdk.cds.blueprintsprocessor.grpc.putStringKeyValue import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_INVOCATION_ID import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_PARTNER_NAME import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_REQUEST_ID @@ -93,8 +94,7 @@ class GrpcLoggerService { fun grpcInvoking(requestHeader: Metadata) { requestHeader.putStringKeyValue(ONAP_REQUEST_ID, MDC.get("InvocationID").defaultToUUID()) requestHeader.putStringKeyValue(ONAP_INVOCATION_ID, UUID.randomUUID().toString()) - val partnerName = System.getProperty("APPNAME") ?: "BlueprintsProcessor" - requestHeader.putStringKeyValue(ONAP_PARTNER_NAME, partnerName) + requestHeader.putStringKeyValue(ONAP_PARTNER_NAME, BluePrintConstants.APP_NAME) } /** Used when server returns response */ diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/MessageLoggerService.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/MessageLoggerService.kt index 7ec70d91b..04b754b13 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/MessageLoggerService.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/MessageLoggerService.kt @@ -84,8 +84,7 @@ class MessageLoggerService { val localhost = InetAddress.getLocalHost() requestHeader.addHeader(BluePrintConstants.ONAP_REQUEST_ID, MDC.get("InvocationID").defaultToUUID()) requestHeader.addHeader(BluePrintConstants.ONAP_INVOCATION_ID, UUID.randomUUID().toString()) - val partnerName = System.getProperty("APPNAME") ?: "BlueprintsProcessor" - requestHeader.addHeader(BluePrintConstants.ONAP_PARTNER_NAME, partnerName) + requestHeader.addHeader(BluePrintConstants.ONAP_PARTNER_NAME, BluePrintConstants.APP_NAME) requestHeader.addHeader("ClientIPAddress", localhost.hostAddress) } diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/ApiDataExtensions.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/ApiDataExtensions.kt index af7109449..8e1b5b2ce 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/ApiDataExtensions.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/ApiDataExtensions.kt @@ -1,5 +1,6 @@ /* * Copyright © 2019 IBM. + * Modifications Copyright © 2018-2019 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. @@ -16,8 +17,13 @@ package org.onap.ccsdk.cds.blueprintsprocessor.core +import com.fasterxml.jackson.databind.JsonNode +import com.google.protobuf.Struct +import com.google.protobuf.util.JsonFormat import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString import org.onap.ccsdk.cds.controllerblueprints.core.asType +import org.onap.ccsdk.cds.controllerblueprints.core.jsonAsJsonType import kotlin.reflect.KClass fun ExecutionServiceInput.payloadAsType(clazzType: KClass): T { @@ -25,3 +31,25 @@ fun ExecutionServiceInput.payloadAsType(clazzType: KClass): T { val requestJsonNode = this.payload.get("$actionName-request") return requestJsonNode.asType(clazzType.java) } + +/** Convert Proto Struct to Json string */ +fun Struct.asJson(): String { + return JsonFormat.printer().print(this) +} + +/** Convert Proto Struct to Json node */ +fun Struct.asJsonType(): JsonNode { + return this.asJson().jsonAsJsonType() +} + +/** Convert Json node to Proto Struct */ +fun JsonNode.asProtoStruct(): Struct { + return this.asJsonString(false).asProtoStruct() +} + +/** Convert Json string to Proto Struct */ +fun String.asProtoStruct(): Struct { + val struct = Struct.newBuilder() + JsonFormat.parser().merge(this, struct) + return struct.build() +} diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/BluePrintMappings.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/ApiDataUtils.kt similarity index 63% rename from ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/BluePrintMappings.kt rename to ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/ApiDataUtils.kt index 59114de86..24ed45c52 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/BluePrintMappings.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/ApiDataUtils.kt @@ -1,5 +1,6 @@ /* * Copyright (C) 2019 Bell Canada. + * Modifications Copyright © 2018-2019 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. @@ -13,24 +14,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.onap.ccsdk.cds.blueprintsprocessor.core.utils import com.fasterxml.jackson.databind.node.ObjectNode -import com.google.common.base.Strings import com.google.protobuf.Struct import com.google.protobuf.util.JsonFormat +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ACTION_MODE_SYNC import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType import org.onap.ccsdk.cds.controllerblueprints.common.api.Flag import org.onap.ccsdk.cds.controllerblueprints.common.api.Status import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.core.utils.controllerDate +import org.onap.ccsdk.cds.controllerblueprints.core.utils.currentTimestamp +import org.onap.ccsdk.cds.controllerblueprints.core.utils.toControllerDate import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput -import java.text.SimpleDateFormat -import java.util.Date - -private val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") // ACTION IDENTIFIER @@ -59,8 +60,10 @@ fun org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader.toProto(): commonHeader.originatorId = this.originatorId commonHeader.requestId = this.requestId commonHeader.subRequestId = this.subRequestId - commonHeader.timestamp = this.timestamp.toString() - commonHeader.flag = this.flags?.toProto() + commonHeader.timestamp = this.timestamp.currentTimestamp() + if (this.flags != null) { + commonHeader.flag = this.flags!!.toProto() + } return commonHeader.build() } @@ -69,10 +72,10 @@ fun CommonHeader.toJava(): org.onap.ccsdk.cds.blueprintsprocessor.core.api.data. commonHeader.originatorId = this.originatorId commonHeader.requestId = this.requestId commonHeader.subRequestId = this.subRequestId - commonHeader.timestamp = if (!Strings.isNullOrEmpty(this.timestamp)) { - formatter.parse(this.timestamp) + commonHeader.timestamp = if (!this.timestamp.isNullOrEmpty()) { + this.timestamp!!.toControllerDate() } else { - Date() + controllerDate() } commonHeader.flags = this.flag?.toJava() return commonHeader @@ -128,3 +131,74 @@ fun org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput. executionServiceOuput.payload = struct.build() return executionServiceOuput.build() } + +/** Create proto common header with [requestId] [subRequestId] and [originator] */ +fun createCommonHeaderProto( + requestId: String, + subRequestId: String, + originator: String +) = CommonHeader.newBuilder() + .setTimestamp(currentTimestamp()) + .setOriginatorId(originator) + .setRequestId(requestId) + .setSubRequestId(subRequestId).build()!! + +/** Create proto action identifiers with [name] [version] and [action] */ +fun createActionIdentifiersProto( + name: String, + version: String, + action: String +) = ActionIdentifiers.newBuilder() + .setBlueprintName(name) + .setBlueprintVersion(version) + .setActionName(action) + .setMode(ACTION_MODE_SYNC) + .build()!! + +/** Create proto status with [message] and [code] */ +fun createStatus( + message: String, + code: Int +) = Status.newBuilder() + .setTimestamp(currentTimestamp()) + .setMessage(message) + .setCode(code) + .build()!! + +/** Create ExecutionServiceInput using [commonHeader], [actionIdentifier] and response payload [jsonContent] */ +fun createExecutionServiceInputProto( + commonHeader: CommonHeader, + actionIdentifier: ActionIdentifiers, + jsonContent: String +): ExecutionServiceInput { + + val payloadBuilder = ExecutionServiceInput.newBuilder().payloadBuilder + JsonFormat.parser().merge(jsonContent, payloadBuilder) + + return ExecutionServiceInput.newBuilder() + .setCommonHeader(commonHeader) + .setActionIdentifiers(actionIdentifier) + .setPayload(payloadBuilder.build()) + .build() +} + +/** Create ExecutionServiceOutput using [commonHeader], [actionIdentifier] [status]and + * response payload [jsonContent] + * */ +fun createExecutionServiceOutputProto( + commonHeader: CommonHeader, + actionIdentifier: ActionIdentifiers, + status: Status, + jsonContent: String +): ExecutionServiceOutput { + + val payloadBuilder = ExecutionServiceOutput.newBuilder().payloadBuilder + JsonFormat.parser().merge(jsonContent, payloadBuilder) + + return ExecutionServiceOutput.newBuilder() + .setCommonHeader(commonHeader) + .setActionIdentifiers(actionIdentifier) + .setStatus(status) + .setPayload(payloadBuilder.build()) + .build() +} diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/PayloadUtils.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/PayloadUtils.kt index d3669f634..426e43cda 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/PayloadUtils.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/PayloadUtils.kt @@ -18,29 +18,56 @@ package org.onap.ccsdk.cds.blueprintsprocessor.core.utils import com.fasterxml.jackson.databind.JsonNode import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString +import org.onap.ccsdk.cds.controllerblueprints.core.returnNullIfMissing import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils -class PayloadUtils { +object PayloadUtils { - companion object { + fun prepareRequestPayloadStr(workflowName: String, jsonNode: JsonNode): String { + return prepareRequestPayload(workflowName, jsonNode).asJsonString(false) + } - fun prepareInputsFromWorkflowPayload(bluePrintRuntimeService: BluePrintRuntimeService<*>, payload: JsonNode, workflowName: String) { - val input = payload.get("$workflowName-request") - bluePrintRuntimeService.assignWorkflowInputs(workflowName, input) - } + fun prepareRequestPayload(workflowName: String, jsonNode: JsonNode): JsonNode { + val objectNode = JacksonUtils.objectMapper.createObjectNode() + objectNode["$workflowName-request"] = jsonNode + return objectNode + } - fun prepareDynamicInputsFromWorkflowPayload(bluePrintRuntimeService: BluePrintRuntimeService<*>, payload: JsonNode, workflowName: String) { - val input = payload.get("$workflowName-request") - val propertyFields = input.get("$workflowName-properties") - prepareDynamicInputsFromComponentPayload(bluePrintRuntimeService, propertyFields) - } + fun getResponseDataFromPayload(workflowName: String, responsePayload: JsonNode): JsonNode { + return responsePayload.get("$workflowName-response").returnNullIfMissing() + ?: throw BluePrintProcessorException("failed to get property($workflowName-response)") + } + + fun prepareInputsFromWorkflowPayload( + bluePrintRuntimeService: BluePrintRuntimeService<*>, + payload: JsonNode, + workflowName: String + ) { + val input = payload.get("$workflowName-request") + bluePrintRuntimeService.assignWorkflowInputs(workflowName, input) + } + + fun prepareDynamicInputsFromWorkflowPayload( + bluePrintRuntimeService: BluePrintRuntimeService<*>, + payload: JsonNode, + workflowName: String + ) { + val input = payload.get("$workflowName-request") + val propertyFields = input.get("$workflowName-properties") + prepareDynamicInputsFromComponentPayload(bluePrintRuntimeService, propertyFields) + } - fun prepareDynamicInputsFromComponentPayload(bluePrintRuntimeService: BluePrintRuntimeService<*>, payload: JsonNode) { - payload.fields().forEach { property -> - val path = StringBuilder(BluePrintConstants.PATH_INPUTS) - .append(BluePrintConstants.PATH_DIVIDER).append(property.key).toString() - bluePrintRuntimeService.put(path, property.value) - } + fun prepareDynamicInputsFromComponentPayload( + bluePrintRuntimeService: BluePrintRuntimeService<*>, + payload: JsonNode + ) { + payload.fields().forEach { property -> + val path = StringBuilder(BluePrintConstants.PATH_INPUTS) + .append(BluePrintConstants.PATH_DIVIDER).append(property.key).toString() + bluePrintRuntimeService.put(path, property.value) } } } diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/BluePrintMappingsTest.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/BluePrintMappingsTest.kt index 4de40d7bf..e8bdbf9ef 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/BluePrintMappingsTest.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/BluePrintMappingsTest.kt @@ -8,6 +8,7 @@ import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType import org.onap.ccsdk.cds.controllerblueprints.common.api.Flag +import org.onap.ccsdk.cds.controllerblueprints.core.utils.currentTimestamp import org.springframework.test.context.junit4.SpringRunner import java.text.SimpleDateFormat @@ -98,7 +99,7 @@ class BluePrintMappingsTest { Assert.assertEquals(commonHeader.originatorId, commonHeader2.originatorId) Assert.assertEquals(commonHeader.requestId, commonHeader2.requestId) Assert.assertEquals(commonHeader.subRequestId, commonHeader2.subRequestId) - Assert.assertEquals(commonHeader.timestamp.toString(), commonHeader2.timestamp) + Assert.assertEquals(commonHeader.timestamp.currentTimestamp(), commonHeader2.timestamp) } @Test diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt index dbb98f849..313710745 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt @@ -26,6 +26,7 @@ import kotlinx.coroutines.newCoroutineContext import kotlinx.coroutines.reactor.ReactorContext import kotlinx.coroutines.reactor.asCoroutineContext import org.apache.http.message.BasicHeader +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_INVOCATION_ID import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_PARTNER_NAME import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_REQUEST_ID @@ -57,8 +58,7 @@ class RestLoggerService { fun httpInvoking(headers: Array) { headers.plusElement(BasicHeader(ONAP_REQUEST_ID, MDC.get("InvocationID").defaultToUUID())) headers.plusElement(BasicHeader(ONAP_INVOCATION_ID, UUID.randomUUID().toString())) - val partnerName = System.getProperty("APPNAME") ?: "BlueprintsProcessor" - headers.plusElement(BasicHeader(ONAP_PARTNER_NAME, partnerName)) + headers.plusElement(BasicHeader(ONAP_PARTNER_NAME, BluePrintConstants.APP_NAME)) } } @@ -85,8 +85,7 @@ class RestLoggerService { val resHeaders = response.headers resHeaders[ONAP_REQUEST_ID] = MDC.get("RequestID") resHeaders[ONAP_INVOCATION_ID] = MDC.get("InvocationID") - val partnerName = System.getProperty("APPNAME") ?: "BlueprintsProcessor" - resHeaders[ONAP_PARTNER_NAME] = partnerName + resHeaders[ONAP_PARTNER_NAME] = BluePrintConstants.APP_NAME } catch (e: Exception) { log.warn("couldn't set response headers", e) } finally { diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt index 1abac7f3d..e2a594b08 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt @@ -27,8 +27,8 @@ import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty +import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation import org.onap.ccsdk.cds.controllerblueprints.core.getAsString -import org.onap.ccsdk.cds.controllerblueprints.core.getOptionalAsInt import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintFunctionNode import org.onap.ccsdk.cds.controllerblueprints.core.jsonPathParse import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile @@ -49,13 +49,13 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode + lateinit var implementation: Implementation lateinit var processId: String lateinit var workflowName: String lateinit var stepName: String lateinit var interfaceName: String lateinit var operationName: String lateinit var nodeTemplateName: String - var timeout: Int = 180 var operationInputs: MutableMap = hashMapOf() override fun getName(): String { @@ -63,7 +63,7 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode { - val artifactDefinition = bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName) + val artifactDefinition = + bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName) val file = normalizedFile(bluePrintRuntimeService.bluePrintContext().rootPath, artifactDefinition.file) return file.readNBLines() } diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutor.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutor.kt new file mode 100644 index 000000000..6003cceab --- /dev/null +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutor.kt @@ -0,0 +1,106 @@ +/* + * Copyright © 2018-2019 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.services.execution + +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.asJsonType +import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.PayloadUtils +import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.createActionIdentifiersProto +import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.createCommonHeaderProto +import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.createExecutionServiceInputProto +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.stereotype.Component +import java.util.UUID + +/** + * This is generic Remote Script Component Executor function + * @author Brinda Santh + */ +@Component("component-remote-script-executor") +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +open class ComponentRemoteScriptExecutor( + private var streamingRemoteExecutionService: StreamingRemoteExecutionService< + org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput, + org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput> +) : AbstractComponentFunction() { + + companion object { + const val INPUT_SELECTOR = "selector" + const val INPUT_BLUEPRINT_NAME = "blueprint-name" + const val INPUT_BLUEPRINT_VERSION = "blueprint-version" + const val INPUT_BLUEPRINT_ACTION = "blueprint-action" + const val INPUT_TIMEOUT = "timeout" + const val INPUT_REQUEST_DATA = "request-data" + + const val ATTRIBUTE_RESPONSE_DATA = "response-data" + const val ATTRIBUTE_STATUS = "status" + + const val OUTPUT_STATUS = "status" + } + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + val selector = getOperationInput(INPUT_SELECTOR) + val blueprintName = getOperationInput(INPUT_BLUEPRINT_NAME).asText() + val blueprintVersion = getOperationInput(INPUT_BLUEPRINT_VERSION).asText() + val blueprintAction = getOperationInput(INPUT_BLUEPRINT_ACTION).asText() + val requestData = getOperationInput(INPUT_REQUEST_DATA) + val timeout = getOperationInput(INPUT_TIMEOUT).asLong() + + val requestPayload = PayloadUtils.prepareRequestPayloadStr(blueprintAction, requestData) + + val txId = UUID.randomUUID().toString() + val commonHeader = createCommonHeaderProto( + executionRequest.commonHeader.subRequestId, + txId, BluePrintConstants.APP_NAME + ) + val actionIdentifier = createActionIdentifiersProto(blueprintName, blueprintVersion, blueprintAction) + + val executionServiceInputProto = + createExecutionServiceInputProto(commonHeader, actionIdentifier, requestPayload) + + /** Invoke remote implementation using GRPC */ + val executionServiceOutputProto = + streamingRemoteExecutionService.sendNonInteractive(selector, txId, executionServiceInputProto, timeout) + + /** Set the response data */ + if (executionServiceOutputProto.payload != null) { + val outputData = PayloadUtils.getResponseDataFromPayload( + blueprintAction, + executionServiceOutputProto.payload.asJsonType() + ) + setAttribute(ATTRIBUTE_RESPONSE_DATA, outputData) + } + + /** set node template attribute */ + val statusMessage = executionServiceOutputProto.status.message + if (statusMessage == BluePrintConstants.STATUS_SUCCESS) { + setAttribute(ATTRIBUTE_STATUS, BluePrintConstants.STATUS_SUCCESS.asJsonPrimitive()) + } else { + val errorMessage = executionServiceOutputProto.status.errorMessage ?: "failed in remote execution" + throw BluePrintProcessorException(errorMessage) + } + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + bluePrintRuntimeService.getBluePrintError() + .addError("Failed in ComponentCliExecutor : ${runtimeException.message}") + } +} diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorDSL.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorDSL.kt new file mode 100644 index 000000000..0210e88ea --- /dev/null +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorDSL.kt @@ -0,0 +1,148 @@ +/* + * Copyright © 2018-2019 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.services.execution + +import com.fasterxml.jackson.databind.JsonNode +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType +import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate +import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeType +import org.onap.ccsdk.cds.controllerblueprints.core.dsl.AbstractNodeTemplateOperationImplBuilder +import org.onap.ccsdk.cds.controllerblueprints.core.dsl.PropertiesAssignmentBuilder +import org.onap.ccsdk.cds.controllerblueprints.core.dsl.nodeType + +/** Component Extensions **/ + +fun BluePrintTypes.nodeTypeComponentRemoteScriptExecutor(): NodeType { + return nodeType( + id = "component-remote-script-executor", version = BluePrintConstants.DEFAULT_VERSION_NUMBER, + derivedFrom = BluePrintConstants.MODEL_TYPE_NODE_COMPONENT, + description = "Generic Remote Script Component Executor" + ) { + /** Attribute definitions */ + attribute( + ComponentRemoteScriptExecutor.ATTRIBUTE_RESPONSE_DATA, BluePrintConstants.DATA_TYPE_JSON, false, + "Remote executed response data." + ) + attribute( + ComponentRemoteScriptExecutor.ATTRIBUTE_STATUS, BluePrintConstants.DATA_TYPE_STRING, true, + "Remote execution status." + ) + + /** Operation definitions */ + operation("ComponentRemoteScriptExecutor", "ComponentRemoteScriptExecutor Operation") { + inputs { + property( + ComponentRemoteScriptExecutor.INPUT_SELECTOR, BluePrintConstants.DATA_TYPE_JSON, + true, "Remote GRPC selector or DSL reference or GRPC Json config." + ) + property( + ComponentRemoteScriptExecutor.INPUT_BLUEPRINT_NAME, BluePrintConstants.DATA_TYPE_STRING, + true, "Blueprint name." + ) + property( + ComponentRemoteScriptExecutor.INPUT_BLUEPRINT_VERSION, BluePrintConstants.DATA_TYPE_STRING, + true, "Blueprint version." + ) + property( + ComponentRemoteScriptExecutor.INPUT_BLUEPRINT_ACTION, BluePrintConstants.DATA_TYPE_STRING, + true, "Blueprint action name." + ) + property( + ComponentRemoteScriptExecutor.INPUT_TIMEOUT, BluePrintConstants.DATA_TYPE_INTEGER, + true, "Remote execution timeout in sec." + ) { + defaultValue(180) + } + property( + ComponentRemoteScriptExecutor.INPUT_REQUEST_DATA, BluePrintConstants.DATA_TYPE_JSON, + false, "Dynamic Json Content or DSL Json reference." + ) + } + outputs { + property( + ComponentRemoteScriptExecutor.OUTPUT_STATUS, BluePrintConstants.DATA_TYPE_STRING, + true, "Status of the Component Execution ( success or failure )" + ) + } + } + } +} + +/** Component Builder */ +fun BluePrintTypes.nodeTemplateComponentRemoteScriptExecutor( + id: String, + description: String, + block: ComponentRemoteScriptExecutorNodeTemplateBuilder.() -> Unit +): + NodeTemplate { + return ComponentRemoteScriptExecutorNodeTemplateBuilder(id, description).apply(block).build() +} + +class ComponentRemoteScriptExecutorNodeTemplateBuilder(id: String, description: String) : + AbstractNodeTemplateOperationImplBuilder( + id, "component-remote-script-executor", + "ComponentRemoteScriptExecutor", + description + ) { + + class InputsBuilder : PropertiesAssignmentBuilder() { + + fun selector(selector: String) = selector(selector.asJsonPrimitive()) + + fun selector(selector: JsonNode) = property(ComponentRemoteScriptExecutor.INPUT_SELECTOR, selector) + + fun blueprintName(blueprintName: String) = property( + ComponentRemoteScriptExecutor.INPUT_BLUEPRINT_NAME, + blueprintName.asJsonPrimitive() + ) + + fun blueprintVersion(blueprintVersion: String) = property( + ComponentRemoteScriptExecutor.INPUT_BLUEPRINT_VERSION, + blueprintVersion.asJsonPrimitive() + ) + + fun blueprintAction(blueprintAction: String) = property( + ComponentRemoteScriptExecutor.INPUT_BLUEPRINT_ACTION, + blueprintAction.asJsonPrimitive() + ) + + fun timeout(timeout: Int) = property( + ComponentRemoteScriptExecutor.INPUT_TIMEOUT, + timeout.asJsonPrimitive() + ) + + fun requestData(requestData: String) = requestData(requestData.asJsonType()) + + fun requestData(requestData: JsonNode) { + property(ComponentRemoteScriptExecutor.INPUT_REQUEST_DATA, requestData) + } + } + + class OutputsBuilder : PropertiesAssignmentBuilder() { + + fun status(status: String) = status(status.asJsonPrimitive()) + + fun status(status: JsonNode) { + property(ComponentRemoteScriptExecutor.OUTPUT_STATUS, status) + } + } +} diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorTest.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorTest.kt new file mode 100644 index 000000000..2091e0366 --- /dev/null +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorTest.kt @@ -0,0 +1,196 @@ +/* + * Copyright © 2018-2019 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.services.execution + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.node.ObjectNode +import io.mockk.coEvery +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.runBlocking +import org.junit.Test +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ACTION_MODE_SYNC +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ActionIdentifiers +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData +import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.createExecutionServiceOutputProto +import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.createStatus +import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.toProto +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation +import org.onap.ccsdk.cds.controllerblueprints.core.jsonAsJsonType +import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext +import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput +import kotlin.test.assertNotNull + +class ComponentRemoteScriptExecutorTest { + + @Test + fun testNodeComponentRemoteScriptExecutorType() { + val nodeType = BluePrintTypes.nodeTypeComponentRemoteScriptExecutor() + assertNotNull(nodeType, "failed to generate nodeType Component Remote Script Executor") + } + + @Test + fun testNodeTemplateComponentRemoteScriptExecutor() { + + val nodeTemplate = BluePrintTypes.nodeTemplateComponentRemoteScriptExecutor( + "remote-sample", + "This is sample node template" + ) { + definedOperation(" Sample Operation") { + implementation(180, "SELF") + inputs { + selector("remote-script-executor") + blueprintName("sample") + blueprintVersion("1.0.0") + blueprintAction("sample-action") + timeout(120) + requestData("""{"key" :"value"}""") + } + outputs { + status("success") + } + } + } + assertNotNull(nodeTemplate, "failed to generate nodeTemplate Component Remote Script Executor") + } + + @Test + fun testComponentRemoteScriptExecutor() { + runBlocking { + /** Mock blueprint context */ + val blueprintContext = mockk() + every { blueprintContext.rootPath } returns normalizedPathName("target") + every { + blueprintContext.nodeTemplateOperationImplementation( + "remote-execute", "ComponentRemoteScriptExecutor", "process" + ) + } returns Implementation() + + val bluePrintRuntime = mockk("1234") + every { bluePrintRuntime.bluePrintContext() } returns blueprintContext + + val mockExecutionServiceInput = mockExecutionServiceInput(bluePrintRuntime) + + val mockStreamingRemoteExecutionService = mockk>() + + coEvery { + mockStreamingRemoteExecutionService.sendNonInteractive( + any(), + any(), + any(), + any() + ) + } returns mockExecutionServiceOutput(mockExecutionServiceInput) + + val componentRemoteScriptExecutor = ComponentRemoteScriptExecutor(mockStreamingRemoteExecutionService) + componentRemoteScriptExecutor.bluePrintRuntimeService = bluePrintRuntime + componentRemoteScriptExecutor.implementation = Implementation() + val componentRemoteScriptExecutorOutput = componentRemoteScriptExecutor.applyNB(mockExecutionServiceInput) + assertNotNull(componentRemoteScriptExecutorOutput, "failed to get executor output") + } + } + + private fun mockExecutionServiceInput(bluePrintRuntime: DefaultBluePrintRuntimeService): ExecutionServiceInput { + + val mapper = ObjectMapper() + val requestNode = mapper.createObjectNode() + requestNode.put("ip-address", "0.0.0.0") + requestNode.put("type", "grpc") + + val operationInputs = hashMapOf() + operationInputs[BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE] = "remote-execute".asJsonPrimitive() + operationInputs[BluePrintConstants.PROPERTY_CURRENT_INTERFACE] = + "ComponentRemoteScriptExecutor".asJsonPrimitive() + operationInputs[BluePrintConstants.PROPERTY_CURRENT_OPERATION] = "process".asJsonPrimitive() + + operationInputs[ComponentRemoteScriptExecutor.INPUT_SELECTOR] = "remote-script-executor".asJsonPrimitive() + operationInputs[ComponentRemoteScriptExecutor.INPUT_BLUEPRINT_NAME] = "sample-blueprint".asJsonPrimitive() + operationInputs[ComponentRemoteScriptExecutor.INPUT_BLUEPRINT_VERSION] = "1.0.0".asJsonPrimitive() + operationInputs[ComponentRemoteScriptExecutor.INPUT_BLUEPRINT_ACTION] = "remote-activate".asJsonPrimitive() + operationInputs[ComponentRemoteScriptExecutor.INPUT_TIMEOUT] = 120.asJsonPrimitive() + operationInputs[ComponentRemoteScriptExecutor.INPUT_REQUEST_DATA] = requestNode + + val stepInputData = StepData().apply { + name = "remote-execute" + properties = operationInputs + } + val executionServiceInput = ExecutionServiceInput().apply { + commonHeader = CommonHeader().apply { + requestId = "1234" + subRequestId = "1234-123" + originatorId = "test-client" + } + actionIdentifiers = ActionIdentifiers().apply { + blueprintName = "sample-blueprint" + blueprintVersion = "1.0.0" + actionName = "remote-activate" + mode = ACTION_MODE_SYNC + } + payload = """{}""".jsonAsJsonType() as ObjectNode + } + executionServiceInput.stepData = stepInputData + + every { + bluePrintRuntime.resolveNodeTemplateInterfaceOperationInputs( + "remote-execute", "ComponentRemoteScriptExecutor", "process" + ) + } returns operationInputs + + /** Mock Set Attributes */ + every { + bluePrintRuntime.setNodeTemplateAttributeValue( + "remote-execute", any(), any() + ) + } returns Unit + + val operationOutputs = hashMapOf() + every { + bluePrintRuntime.resolveNodeTemplateInterfaceOperationOutputs( + "remote-execute", "ComponentRemoteScriptExecutor", "process" + ) + } returns operationOutputs + + return executionServiceInput + } + + private fun mockExecutionServiceOutput(executionServiceInput: ExecutionServiceInput): ExecutionServiceOutput { + val actionName = executionServiceInput.actionIdentifiers.actionName + val responsePayload = """ + { + "$actionName-response" :{ + "key" : "value" + } + } + """.trimIndent() + return createExecutionServiceOutputProto( + executionServiceInput.commonHeader.toProto(), + executionServiceInput.actionIdentifiers.toProto(), + createStatus(BluePrintConstants.STATUS_SUCCESS, 200), + responsePayload + ) + } +} diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt index d6720427e..e013fa889 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt @@ -38,6 +38,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.nodeTypeCompone import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintScriptsServiceImpl import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext @@ -70,6 +71,11 @@ class AbstractComponentFunctionTest { fun init() { blueprintContext = mockk() every { blueprintContext.rootPath } returns normalizedPathName("target") + every { + blueprintContext.nodeTemplateOperationImplementation( + any(), any(), any() + ) + } returns Implementation() } @Test @@ -147,7 +153,7 @@ class AbstractComponentFunctionTest { * Mocked input for abstract function test. */ private fun getMockedInput(bluePrintRuntime: DefaultBluePrintRuntimeService): - ExecutionServiceInput { + ExecutionServiceInput { val mapper = ObjectMapper() val rootNode = mapper.createObjectNode() diff --git a/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/NodeTemplateExecutionService.kt b/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/NodeTemplateExecutionService.kt index 615a31c77..6a304e0c7 100644 --- a/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/NodeTemplateExecutionService.kt +++ b/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/NodeTemplateExecutionService.kt @@ -23,6 +23,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService import org.slf4j.LoggerFactory @@ -51,12 +52,12 @@ open class NodeTemplateExecutionService { val nodeTemplateImplementation = blueprintContext .nodeTemplateOperationImplementation(nodeTemplateName, interfaceName, operationName) - - val timeout: Int = nodeTemplateImplementation?.timeout ?: 180 + ?: Implementation() log.info( "executing node template($nodeTemplateName) component($componentName) " + - "interface($interfaceName) operation($operationName) with timeout($timeout) sec." + "interface($interfaceName) operation($operationName) on host (${nodeTemplateImplementation.operationHost}) " + + "with timeout(${nodeTemplateImplementation.timeout}) sec." ) // Get the Component Instance @@ -77,7 +78,6 @@ open class NodeTemplateExecutionService { stepInputs[BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE] = nodeTemplateName.asJsonPrimitive() stepInputs[BluePrintConstants.PROPERTY_CURRENT_INTERFACE] = interfaceName.asJsonPrimitive() stepInputs[BluePrintConstants.PROPERTY_CURRENT_OPERATION] = operationName.asJsonPrimitive() - stepInputs[BluePrintConstants.PROPERTY_CURRENT_TIMEOUT] = timeout.asJsonPrimitive() val stepInputData = StepData().apply { name = nodeTemplateName properties = stepInputs diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt index b97cb026a..669299534 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt @@ -24,6 +24,13 @@ package org.onap.ccsdk.cds.controllerblueprints.core */ object BluePrintConstants { + var APP_NAME = System.getProperty("APPNAME") + ?: System.getProperty("APP_NAME") + ?: System.getProperty("APPLICATION_NAME") + ?: "cds-controller-default" + + const val DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + const val RESPONSE_HEADER_MINOR_VERSION: String = "X-MinorVersion" const val RESPONSE_HEADER_PATCH_VERSION: String = "X-PatchVersion" const val RESPONSE_HEADER_LATEST_VERSION: String = "X-LatestVersion" diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/DateUtils.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/DateUtils.kt index e01ba805d..4fd907a5a 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/DateUtils.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/DateUtils.kt @@ -16,12 +16,32 @@ package org.onap.ccsdk.cds.controllerblueprints.core.utils +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import java.text.SimpleDateFormat import java.time.LocalDateTime import java.time.ZoneId import java.time.format.DateTimeFormatter +import java.util.Date + +fun controllerDate(): Date { + val localDateTime = LocalDateTime.now(ZoneId.systemDefault()) + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()) +} fun currentTimestamp(): String { - val now = LocalDateTime.now(ZoneId.systemDefault()) - val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - return formatter.format(now) + val localDateTime = LocalDateTime.now(ZoneId.systemDefault()) + val formatter = DateTimeFormatter.ofPattern(BluePrintConstants.DATE_TIME_PATTERN) + return formatter.format(localDateTime) +} + +/** Parse string date in CDS string format */ +fun String.toControllerDate(): Date { + val formatter = SimpleDateFormat(BluePrintConstants.DATE_TIME_PATTERN) + return formatter.parse(this) +} + +/** Return date to CDS string format */ +fun Date.currentTimestamp(): String { + val formatter = SimpleDateFormat(BluePrintConstants.DATE_TIME_PATTERN) + return formatter.format(this) } -- 2.16.6