Remote Script Executor Component 34/99034/3
authorBrinda Santh <bs2796@att.com>
Tue, 3 Dec 2019 00:04:13 +0000 (19:04 -0500)
committerBrinda Santh Muthuramalingam <bs2796@att.com>
Fri, 6 Dec 2019 17:46:13 +0000 (17:46 +0000)
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 <bs2796@att.com>
Change-Id: I41a429eb21a050e5ab512a7a73a394b975543f31

18 files changed:
components/model-catalog/definition-type/starter-type/node_type/component-remote-script-executor.json [new file with mode: 0644]
ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt
ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt
ms/blueprintsprocessor/modules/commons/grpc-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/grpc/service/GrpcLoggerService.kt
ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/MessageLoggerService.kt
ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/ApiDataExtensions.kt
ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/ApiDataUtils.kt [moved from ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/BluePrintMappings.kt with 63% similarity]
ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/PayloadUtils.kt
ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/utils/BluePrintMappingsTest.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestLoggerService.kt
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutor.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorDSL.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutorTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/NodeTemplateExecutionService.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/DateUtils.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 (file)
index 0000000..6909d20
--- /dev/null
@@ -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"
+}
index 1f070d4..50268d3 100644 (file)
@@ -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<BluePrintContext>()
+            every {
+                blueprintContext.nodeTemplateOperationImplementation(
+                    any(), any(), any()
+                )
+            } returns Implementation()
+
             every { bluePrintRuntime.bluePrintContext() } returns blueprintContext
             every {
                 bluePrintRuntime.resolveNodeTemplateInterfaceOperationInputs(
index 7d81ef3..47cf34f 100644 (file)
@@ -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<BluePrintContext>()
+            every {
+                blueprintContext.nodeTemplateOperationImplementation(
+                    any(), any(), any()
+                )
+            } returns Implementation()
+
             val bluePrintRuntime = mockk<DefaultBluePrintRuntimeService>("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<BluePrintContext>()
-            every { bluePrintRuntime.bluePrintContext() } returns blueprintContext
             every {
                 bluePrintRuntime.resolveNodeTemplateInterfaceOperationInputs(
                     "activate-restconf",
index 510a215..732f4fe 100644 (file)
@@ -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 */
index 7ec70d9..04b754b 100644 (file)
@@ -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)
     }
 
index af71094..8e1b5b2 100644 (file)
@@ -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.
 
 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 <T : Any> ExecutionServiceInput.payloadAsType(clazzType: KClass<T>): T {
@@ -25,3 +31,25 @@ fun <T : Any> ExecutionServiceInput.payloadAsType(clazzType: KClass<T>): 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()
+}
@@ -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.
  * 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()
+}
index d3669f6..426e43c 100644 (file)
@@ -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)
         }
     }
 }
index 4de40d7..e8bdbf9 100644 (file)
@@ -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
index dbb98f8..3137107 100644 (file)
@@ -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<BasicHeader>) {
             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 {
index 1abac7f..e2a594b 100644 (file)
@@ -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<ExecutionServic
     lateinit var executionServiceInput: ExecutionServiceInput
     var executionServiceOutput = ExecutionServiceOutput()
     lateinit var bluePrintRuntimeService: BluePrintRuntimeService<*>
+    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<String, JsonNode> = hashMapOf()
 
     override fun getName(): String {
@@ -63,7 +63,7 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
     }
 
     override suspend fun prepareRequestNB(executionRequest: ExecutionServiceInput): ExecutionServiceInput {
-        checkNotNull(bluePrintRuntimeService) { "failed to prepare blueprint runtime" }
+        check(this::bluePrintRuntimeService.isInitialized) { "failed to prepare blueprint runtime" }
         checkNotNull(executionRequest.stepData) { "failed to get step info" }
 
         // Get the Step Name and Step Inputs
@@ -91,14 +91,17 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
         operationName = this.operationInputs.getAsString(BluePrintConstants.PROPERTY_CURRENT_OPERATION)
         check(operationName.isNotEmpty()) { "couldn't get Operation name for step($stepName)" }
 
+        /** Get the Implementation Details */
+        implementation = bluePrintRuntimeService.bluePrintContext()
+            .nodeTemplateOperationImplementation(nodeTemplateName, interfaceName, operationName)
+            ?: Implementation()
+        check(this::implementation.isInitialized) { "failed to prepare implementation" }
+
         val operationResolvedProperties = bluePrintRuntimeService
             .resolveNodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName)
 
         this.operationInputs.putAll(operationResolvedProperties)
 
-        val timeout = this.operationInputs.getOptionalAsInt(BluePrintConstants.PROPERTY_CURRENT_TIMEOUT)
-        timeout?.let { this.timeout = timeout }
-
         return executionRequest
     }
 
@@ -106,7 +109,7 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
         log.info("Preparing Response...")
         executionServiceOutput.commonHeader = executionServiceInput.commonHeader
         executionServiceOutput.actionIdentifiers = executionServiceInput.actionIdentifiers
-        var status = Status()
+        val status = Status()
         try {
             // Resolve the Output Expression
             val stepOutputs = bluePrintRuntimeService
@@ -130,7 +133,7 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
     override suspend fun applyNB(executionServiceInput: ExecutionServiceInput): ExecutionServiceOutput {
         try {
             prepareRequestNB(executionServiceInput)
-            withTimeout((timeout * 1000).toLong()) {
+            withTimeout((implementation.timeout * 1000).toLong()) {
                 processNB(executionServiceInput)
             }
         } catch (runtimeException: RuntimeException) {
@@ -191,7 +194,8 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
     }
 
     suspend fun readLinesFromArtifact(artifactName: String): List<String> {
-        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 (file)
index 0000000..6003cce
--- /dev/null
@@ -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 (file)
index 0000000..0210e88
--- /dev/null
@@ -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<PropertiesAssignmentBuilder,
+        ComponentRemoteScriptExecutorNodeTemplateBuilder.InputsBuilder,
+        ComponentRemoteScriptExecutorNodeTemplateBuilder.OutputsBuilder>(
+        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 (file)
index 0000000..2091e03
--- /dev/null
@@ -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<BluePrintContext>()
+            every { blueprintContext.rootPath } returns normalizedPathName("target")
+            every {
+                blueprintContext.nodeTemplateOperationImplementation(
+                    "remote-execute", "ComponentRemoteScriptExecutor", "process"
+                )
+            } returns Implementation()
+
+            val bluePrintRuntime = mockk<DefaultBluePrintRuntimeService>("1234")
+            every { bluePrintRuntime.bluePrintContext() } returns blueprintContext
+
+            val mockExecutionServiceInput = mockExecutionServiceInput(bluePrintRuntime)
+
+            val mockStreamingRemoteExecutionService = mockk<StreamingRemoteExecutionService<
+                org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput,
+                org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput>>()
+
+            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<String, JsonNode>()
+        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<String, JsonNode>()
+        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
+        )
+    }
+}
index d672042..e013fa8 100644 (file)
@@ -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<BluePrintContext>()
         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()
index 615a31c..6a304e0 100644 (file)
@@ -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
index b97cb02..6692995 100644 (file)
@@ -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"
index e01ba80..4fd907a 100644 (file)
 
 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)
 }