Rework remote command arguments 38/86038/5
authorBrinda Santh <brindasanth@in.ibm.com>
Tue, 23 Apr 2019 10:36:54 +0000 (16:06 +0530)
committerAlexis de Talhouët <adetalhouet89@gmail.com>
Wed, 24 Apr 2019 13:43:37 +0000 (09:43 -0400)
Change-Id: Ibd24ce87ed67aee6ae1a66fc9ec6af35bee5008a
Issue-ID: CCSDK-1215
Signed-off-by: Brinda Santh <brindasanth@in.ibm.com>
components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json
components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/remote_scripts.json
components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json
ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt
ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/CustomFunctions.kt

index e5b8b30..a66e3bc 100644 (file)
@@ -46,7 +46,7 @@
                 },
                 "packages": {
                   "description": "Packages to install based on type.",
-                  "required": true,
+                  "required": false,
                   "type" : "list",
                   "entry_schema" : {
                     "type" : "dt-system-packages"
index 48992bd..4c3ece3 100644 (file)
   ],
   "dsl_definitions": {
     "execute-argument-properties": {
-      "input": {
-        "get_input": "input"
-      }
+      "input": "data"
+    },
+    "remote-argument-properties": {
+      "arg-0": "-a",
+      "arg-1": "sample-data 1",
+      "arg-4": "sample-data 4",
+      "arg-3": "sample-data 3",
+      "arg-2": "-b"
     }
   },
   "topology_template": {
                   "primary": "component-script"
                 },
                 "inputs": {
-                  "command": "python SamplePython.py $input",
+                  "command": "python SamplePython.py",
                   "packages": [
                     {
                       "type": "pip",
                       ]
                     }
                   ],
-                  "argument-properties": "*execute-argument-properties"
+                  "argument-properties": "*remote-argument-properties",
+                  "dynamic-properties": "*execute-argument-properties"
                 }
               }
             }
index 09b371c..e14b63e 100644 (file)
@@ -44,7 +44,7 @@
             },
             "packages": {
               "description": "Packages to install based on type.",
-              "required": true,
+              "required": false,
               "type" : "list",
               "entry_schema" : {
                 "type" : "dt-system-packages"
index df92d71..df9b014 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor
 
-import com.fasterxml.jackson.databind.node.MissingNode
-import com.fasterxml.jackson.databind.node.NullNode
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.*
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceConstant
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.RemoteScriptExecutionService
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
-import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
-import org.onap.ccsdk.cds.controllerblueprints.core.checkFileExists
-import org.onap.ccsdk.cds.controllerblueprints.core.checkNotBlank
+import org.onap.ccsdk.cds.controllerblueprints.core.*
 import org.onap.ccsdk.cds.controllerblueprints.core.data.OperationAssignment
-import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
-import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintVelocityTemplateService
-import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.slf4j.LoggerFactory
 import org.springframework.beans.factory.config.ConfigurableBeanFactory
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
 import org.springframework.context.annotation.Scope
 import org.springframework.stereotype.Component
-import java.lang.Exception
 
 @ConditionalOnBean(name = [ExecutionServiceConstant.SERVICE_GRPC_REMOTE_SCRIPT_EXECUTION])
 @Component("component-remote-python-executor")
@@ -65,13 +56,13 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic
         val blueprintVersion = bluePrintContext.version()
 
         val operationAssignment: OperationAssignment = bluePrintContext
-            .nodeTemplateInterfaceOperation(nodeTemplateName, interfaceName, operationName)
+                .nodeTemplateInterfaceOperation(nodeTemplateName, interfaceName, operationName)
 
         val artifactName: String = operationAssignment.implementation?.primary
-            ?: throw BluePrintProcessorException("missing primary field to get artifact name for node template ($nodeTemplateName)")
+                ?: throw BluePrintProcessorException("missing primary field to get artifact name for node template ($nodeTemplateName)")
 
         val artifactDefinition =
-            bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
+                bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
 
         checkNotBlank(artifactDefinition.file) { "couldn't get python script path($artifactName)" }
 
@@ -80,24 +71,28 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic
         checkFileExists(pythonScript) { "python script(${pythonScript.absolutePath}) doesn't exists" }
 
         val endPointSelector = getOperationInput(INPUT_ENDPOINT_SELECTOR)
-        val dynamicProperties = getOperationInput(INPUT_DYNAMIC_PROPERTIES)
-        val packages = getOperationInput(INPUT_PACKAGES)
-        val argumentProperties = getOperationInput(INPUT_ARGUMENT_PROPERTIES)
+        val dynamicProperties = getOptionalOperationInput(INPUT_DYNAMIC_PROPERTIES)
+        val packages = getOptionalOperationInput(INPUT_PACKAGES)?.returnNullIfMissing()
 
-        var command = getOperationInput(INPUT_COMMAND).asText()
-        command = command.replace(pythonScript.name, pythonScript.absolutePath)
-        val scriptCommand = BluePrintVelocityTemplateService.generateContent(command, json = JacksonUtils.getJson(argumentProperties))
+        val args = getOptionalOperationInput(INPUT_ARGUMENT_PROPERTIES)?.returnNullIfMissing()
+                ?.rootFieldsToMap()?.toSortedMap()?.values?.map { it.textValue() }?.joinToString(" ")
+
+        val command = getOperationInput(INPUT_COMMAND).asText()
+        var scriptCommand = command.replace(pythonScript.name, pythonScript.absolutePath)
+        if (args != null && args.isNotEmpty()) {
+            scriptCommand = scriptCommand.plus(" ").plus(args)
+        }
 
         try {
             // Open GRPC Connection
             remoteScriptExecutionService.init(endPointSelector.asText())
 
             // If packages are defined, then install in remote server
-            if (packages !is MissingNode && packages !is NullNode) {
+            if (packages != null) {
                 val prepareEnvInput = PrepareRemoteEnvInput(requestId = processId,
-                    remoteIdentifier = RemoteIdentifier(blueprintName = blueprintName,
-                        blueprintVersion = blueprintVersion),
-                    packages = packages
+                        remoteIdentifier = RemoteIdentifier(blueprintName = blueprintName,
+                                blueprintVersion = blueprintVersion),
+                        packages = packages
                 )
                 val prepareEnvOutput = remoteScriptExecutionService.prepareEnv(prepareEnvInput)
                 setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, prepareEnvOutput.response.asJsonPrimitive())
@@ -105,11 +100,14 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic
                     "failed to get prepare remote env response status for requestId(${prepareEnvInput.requestId})"
                 }
             }
+            // Populate command execution properties and pass it to the remote server
+            val properties = dynamicProperties?.returnNullIfMissing()?.rootFieldsToMap() ?: hashMapOf()
 
             val remoteExecutionInput = RemoteScriptExecutionInput(
-                requestId = processId,
-                remoteIdentifier = RemoteIdentifier(blueprintName = blueprintName, blueprintVersion = blueprintVersion),
-                command = scriptCommand)
+                    requestId = processId,
+                    remoteIdentifier = RemoteIdentifier(blueprintName = blueprintName, blueprintVersion = blueprintVersion),
+                    command = scriptCommand,
+                    properties = properties)
             val remoteExecutionOutput = remoteScriptExecutionService.executeCommand(remoteExecutionInput)
             setAttribute(ATTRIBUTE_EXEC_CMD_LOG, remoteExecutionOutput.response.asJsonPrimitive())
             check(remoteExecutionOutput.status == StatusType.SUCCESS) {
@@ -125,6 +123,6 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
         bluePrintRuntimeService.getBluePrintError()
-            .addError("Failed in ComponentJythonExecutor : ${runtimeException.message}")
+                .addError("Failed in ComponentJythonExecutor : ${runtimeException.message}")
     }
 }
\ No newline at end of file
index 03616d5..0c5a947 100644 (file)
@@ -71,6 +71,7 @@ class MockRemoteScriptExecutionService : RemoteScriptExecutionService {
         assertNotNull(prepareEnvInput.packages, "failed to get packages")
 
         val remoteScriptExecutionOutput = mockk<RemoteScriptExecutionOutput>()
+        every { remoteScriptExecutionOutput.response } returns "prepared successfully"
         every { remoteScriptExecutionOutput.status } returns StatusType.SUCCESS
         return remoteScriptExecutionOutput
     }
@@ -79,6 +80,7 @@ class MockRemoteScriptExecutionService : RemoteScriptExecutionService {
         assertEquals(remoteExecutionInput.requestId, "123456-1000", "failed to match request id")
 
         val remoteScriptExecutionOutput = mockk<RemoteScriptExecutionOutput>()
+        every { remoteScriptExecutionOutput.response } returns "processed successfully"
         every { remoteScriptExecutionOutput.status } returns StatusType.SUCCESS
         return remoteScriptExecutionOutput
     }
index 12f6bc4..23588d2 100644 (file)
@@ -24,10 +24,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutp
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.Status
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
 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.getAsString
+import org.onap.ccsdk.cds.controllerblueprints.core.*
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintFunctionNode
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.slf4j.LoggerFactory
@@ -133,6 +130,10 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
                 ?: throw BluePrintProcessorException("couldn't get the operation input($key) value.")
     }
 
+    fun getOptionalOperationInput(key: String): JsonNode? {
+        return operationInputs[key]
+    }
+
     fun setAttribute(key: String, value: JsonNode) {
         bluePrintRuntimeService.setNodeTemplateAttributeValue(nodeTemplateName, key, value)
     }
index 72c2c1d..0e45232 100644 (file)
@@ -101,6 +101,12 @@ fun ArrayNode.asListOfString(): List<String> {
     return JacksonUtils.getListFromJsonNode(this, String::class.java)
 }
 
+fun JsonNode.returnNullIfMissing(): JsonNode? {
+    return if (this is NullNode || this is MissingNode) {
+        null
+    } else this
+}
+
 /**
  * Convert Json to map of json node, the root fields will be map keys
  */