From 35ab81bb9ff203e14116de10bc2735ffb2883f67 Mon Sep 17 00:00:00 2001 From: Serge Simard Date: Thu, 24 Oct 2019 01:42:27 -0400 Subject: [PATCH] Improve Remote Python Executor error handling and allow for structured response Issue-ID: CCSDK-1855 Signed-off-by: Serge Simard Change-Id: I924918fb06a5a0f118772dedaa41c536c7eca9e7 Signed-off-by: Serge Simard --- .../remote_scripts/Definitions/node_types.json | 8 +++ .../remote_scripts/Definitions/remote_scripts.json | 8 +++ .../remote_scripts/Scripts/python/SamplePython.py | 12 +++- .../remote_scripts/TOSCA-Metadata/TOSCA.meta | 3 +- .../component-remote-python-executor.json | 4 ++ .../proto-definition/proto/CommandExecutor.proto | 2 + .../executor/ComponentRemotePythonExecutor.kt | 50 ++++++++++++--- .../executor/ComponentRemotePythonExecutorTest.kt | 2 + .../core/api/data/BlueprintRemoteProcessorData.kt | 3 +- .../execution/RemoteScriptExecutionService.kt | 4 +- .../src/main/python/cds_utils/__init__.py | 0 .../src/main/python/cds_utils/payload_coder.py | 13 ++++ .../src/main/python/command_executor_handler.py | 33 ++++++++-- .../src/main/python/command_executor_server.py | 27 +++++--- .../src/main/python/proto/CommandExecutor_pb2.py | 72 +++++++++++++--------- ms/command-executor/src/main/python/utils.py | 12 ++-- 16 files changed, 192 insertions(+), 61 deletions(-) create mode 100644 ms/command-executor/src/main/python/cds_utils/__init__.py create mode 100644 ms/command-executor/src/main/python/cds_utils/payload_coder.py diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json index 4945da889..a47c13c47 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json @@ -14,6 +14,14 @@ "entry_schema": { "type": "string" } + }, + "status": { + "required": true, + "type": "string" + }, + "response-data": { + "required": false, + "type": "json" } }, "capabilities" : { diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/remote_scripts.json b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/remote_scripts.json index 192106e95..fe0f59243 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/remote_scripts.json +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/remote_scripts.json @@ -83,6 +83,14 @@ "execute-command-logs" ] } + }, + "execute-command-status": { + "type": "string", + "value": { "get_attribute": ["execute-remote-python", "status"]} + }, + "execute-command-payload": { + "type": "json", + "value": { "get_attribute": ["execute-remote-python", "response-data"]} } } }, diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Scripts/python/SamplePython.py b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Scripts/python/SamplePython.py index 5e20e2291..fae5855cf 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Scripts/python/SamplePython.py +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Scripts/python/SamplePython.py @@ -2,4 +2,14 @@ import sys -print(sys.argv[1]) \ No newline at end of file +#Optional : import this utility class if returning payload +from cds_utils.payload_coder import send_response_data_payload + +# Do your work... using try .. except to handle errors and return False if error +print(sys.argv[1]) + +# Optional : return a JSON payload to the be published under the response-data output attribute +send_response_data_payload({"étudiant": ["Mélanie", "Joséphine"]}) + +# Always return a boolean indicating success or not.. +sys.exit(True) \ No newline at end of file diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/TOSCA-Metadata/TOSCA.meta b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/TOSCA-Metadata/TOSCA.meta index 5ca8aa031..2c3a91f28 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/TOSCA-Metadata/TOSCA.meta +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/TOSCA-Metadata/TOSCA.meta @@ -2,4 +2,5 @@ TOSCA-Meta-File-Version: 1.0.0 CSAR-Version: 1.0 Created-By: Brinda Santh Entry-Definitions: Definitions/remote_scripts.json -Template-Tags: Brinda Santh, remote_scripts \ No newline at end of file +Template-Tags: Brinda Santh, remote_scripts +Content-Type: application/vnd.oasis.bpmn diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json b/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json index 1c8011382..acaea4e7b 100644 --- a/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json +++ b/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json @@ -2,6 +2,10 @@ "description": "This is Remote Python Execution Component.", "version": "1.0.0", "attributes": { + "status": { + "required": true, + "type": "string" + }, "prepare-environment-logs": { "required": false, "type": "string" diff --git a/components/model-catalog/proto-definition/proto/CommandExecutor.proto b/components/model-catalog/proto-definition/proto/CommandExecutor.proto index fd2d4f305..ac6921965 100644 --- a/components/model-catalog/proto-definition/proto/CommandExecutor.proto +++ b/components/model-catalog/proto-definition/proto/CommandExecutor.proto @@ -40,6 +40,7 @@ message ExecutionOutput { repeated string response = 2; ResponseStatus status = 3; google.protobuf.Timestamp timestamp = 4; + string payload = 5; } enum ResponseStatus { @@ -55,6 +56,7 @@ message Packages { enum PackageType { pip = 0; ansible_galaxy = 1; + utilities = 2; } service CommandExecutorService { diff --git a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt index 2a227ebe1..6b1f186c9 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt @@ -46,6 +46,7 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic const val INPUT_PACKAGES = "packages" const val DEFAULT_SELECTOR = "remote-python" + const val ATTRIBUTE_EXEC_CMD_STATUS = "status" const val ATTRIBUTE_PREPARE_ENV_LOG = "prepare-environment-logs" const val ATTRIBUTE_EXEC_CMD_LOG = "execute-command-logs" const val ATTRIBUTE_RESPONSE_DATA = "response-data" @@ -53,7 +54,7 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic override suspend fun processNB(executionRequest: ExecutionServiceInput) { - log.info("Processing : $operationInputs") + log.debug("Processing : $operationInputs") val bluePrintContext = bluePrintRuntimeService.bluePrintContext() val blueprintName = bluePrintContext.name() @@ -109,12 +110,17 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic ) val prepareEnvOutput = remoteScriptExecutionService.prepareEnv(prepareEnvInput) log.info("$ATTRIBUTE_PREPARE_ENV_LOG - ${prepareEnvOutput.response}") - setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, JacksonUtils.jsonNodeFromObject(prepareEnvOutput.response)) + val logs = JacksonUtils.jsonNodeFromObject(prepareEnvOutput.response) + setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, logs) setAttribute(ATTRIBUTE_EXEC_CMD_LOG, "N/A".asJsonPrimitive()) - check(prepareEnvOutput.status == StatusType.SUCCESS) { - "failed to get prepare remote env response status for requestId(${prepareEnvInput.requestId})" + + if (prepareEnvOutput.status != StatusType.SUCCESS) { + setNodeOutputErrors(prepareEnvOutput.status.name, logs) + } else { + setNodeOutputProperties(prepareEnvOutput.status.name.asJsonPrimitive(), logs, "".asJsonPrimitive()) } } + // Populate command execution properties and pass it to the remote server val properties = dynamicProperties?.returnNullIfMissing()?.rootFieldsToMap() ?: hashMapOf() @@ -124,10 +130,13 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic command = scriptCommand, properties = properties) val remoteExecutionOutput = remoteScriptExecutionService.executeCommand(remoteExecutionInput) - log.info("$ATTRIBUTE_EXEC_CMD_LOG - ${remoteExecutionOutput.response}") - setAttribute(ATTRIBUTE_EXEC_CMD_LOG, JacksonUtils.jsonNodeFromObject(remoteExecutionOutput.response)) - check(remoteExecutionOutput.status == StatusType.SUCCESS) { - "failed to get prepare remote command response status for requestId(${remoteExecutionOutput.requestId})" + + val logs = JacksonUtils.jsonNodeFromObject(remoteExecutionOutput.response) + if (remoteExecutionOutput.status != StatusType.SUCCESS) { + setNodeOutputErrors(remoteExecutionOutput.status.name,logs, remoteExecutionOutput.payload) + } else { + setNodeOutputProperties(remoteExecutionOutput.status.name.asJsonPrimitive(), logs, + remoteExecutionOutput.payload) } } catch (e: Exception) { @@ -139,7 +148,7 @@ 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 ComponentRemotePythonExecutor : ${runtimeException.message}") } private fun formatNestedJsonNode(node: JsonNode): String { @@ -151,4 +160,27 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic } return sb.toString() } + + /** + * Utility function to set the output properties of the executor node + */ + private fun setNodeOutputProperties(status: JsonNode, message: JsonNode, artifacts: JsonNode) { + setAttribute(ATTRIBUTE_EXEC_CMD_STATUS, status) + log.info("Executor status : $status") + setAttribute(ATTRIBUTE_RESPONSE_DATA, artifacts) + log.info("Executor artifacts: $artifacts") + setAttribute(ATTRIBUTE_EXEC_CMD_LOG, message) + log.info("Executor message : $message") + } + + /** + * Utility function to set the output properties and errors of the executor node, in cas of errors + */ + private fun setNodeOutputErrors(status: String, message: JsonNode, artifacts: JsonNode = "".asJsonPrimitive() ) { + setAttribute(ATTRIBUTE_EXEC_CMD_STATUS, status.asJsonPrimitive()) + setAttribute(ATTRIBUTE_EXEC_CMD_LOG, message) + setAttribute(ATTRIBUTE_RESPONSE_DATA, artifacts) + + addError(status, ATTRIBUTE_EXEC_CMD_LOG, message.asText()) + } } diff --git a/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt b/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt index d103bbf08..89af42579 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt @@ -194,6 +194,7 @@ class MockRemoteScriptExecutionService : RemoteScriptExecutionService { assertNotNull(prepareEnvInput.packages, "failed to get packages") val remoteScriptExecutionOutput = mockk() + every { remoteScriptExecutionOutput.payload } returns "payload".asJsonPrimitive() every { remoteScriptExecutionOutput.response } returns listOf("prepared successfully") every { remoteScriptExecutionOutput.status } returns StatusType.SUCCESS return remoteScriptExecutionOutput @@ -203,6 +204,7 @@ class MockRemoteScriptExecutionService : RemoteScriptExecutionService { assertEquals(remoteExecutionInput.requestId, "123456-1000", "failed to match request id") val remoteScriptExecutionOutput = mockk() + every { remoteScriptExecutionOutput.payload } returns "payload".asJsonPrimitive() every { remoteScriptExecutionOutput.response } returns listOf("processed successfully") every { remoteScriptExecutionOutput.status } returns StatusType.SUCCESS return remoteScriptExecutionOutput diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt index 2f9ea4a25..d63f34ced 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt @@ -39,7 +39,8 @@ data class RemoteScriptExecutionInput(var requestId: String, data class RemoteScriptExecutionOutput(var requestId: String, var response: List, var status: StatusType = StatusType.SUCCESS, - var timestamp: Date = Date()) + var timestamp: Date = Date(), + var payload: JsonNode) data class PrepareRemoteEnvInput(var requestId: String, var correlationId: String? = null, diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt index b0e3e4701..d6146e111 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt @@ -25,6 +25,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.* import org.onap.ccsdk.cds.blueprintsprocessor.grpc.service.BluePrintGrpcClientService import org.onap.ccsdk.cds.blueprintsprocessor.grpc.service.BluePrintGrpcLibPropertyService import org.onap.ccsdk.cds.controllerblueprints.command.api.* +import org.onap.ccsdk.cds.controllerblueprints.core.jsonAsJsonType import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.slf4j.LoggerFactory import org.springframework.beans.factory.config.ConfigurableBeanFactory @@ -154,7 +155,8 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi return RemoteScriptExecutionOutput( requestId = this.requestId, response = this.responseList, - status = StatusType.valueOf(this.status.name) + status = StatusType.valueOf(this.status.name), + payload = payload.jsonAsJsonType() ) } diff --git a/ms/command-executor/src/main/python/cds_utils/__init__.py b/ms/command-executor/src/main/python/cds_utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ms/command-executor/src/main/python/cds_utils/payload_coder.py b/ms/command-executor/src/main/python/cds_utils/payload_coder.py new file mode 100644 index 000000000..951262172 --- /dev/null +++ b/ms/command-executor/src/main/python/cds_utils/payload_coder.py @@ -0,0 +1,13 @@ +import json +from email.mime import multipart +from email.mime import text +import email.parser + +def send_response_data_payload(json_payload): + m = multipart.MIMEMultipart("form-data") + data = text.MIMEText("response_payload", "json", "utf8") + data.set_payload(json.JSONEncoder().encode(json_payload)) + m.attach(data) + print("BEGIN_EXTRA_PAYLOAD") + print(m.as_string()) + print("END_EXTRA_PAYLOAD") \ No newline at end of file diff --git a/ms/command-executor/src/main/python/command_executor_handler.py b/ms/command-executor/src/main/python/command_executor_handler.py index 972dad627..c920dda89 100644 --- a/ms/command-executor/src/main/python/command_executor_handler.py +++ b/ms/command-executor/src/main/python/command_executor_handler.py @@ -25,6 +25,8 @@ import virtualenv import venv import utils import proto.CommandExecutor_pb2 as CommandExecutor_pb2 +import email.parser +import json REQUIREMENTS_TXT = "requirements.txt" @@ -75,6 +77,10 @@ class CommandExecutorHandler(): else: cmd = cmd + "; " + request.command + " " + re.escape(MessageToJson(request.properties)) + payload_result = {} + payload_section = [] + is_payload_section = False + try: with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, bufsize=1, universal_newlines=True) as newProcess: @@ -82,19 +88,36 @@ class CommandExecutorHandler(): output = newProcess.stdout.readline() if output == '' and newProcess.poll() is not None: break - if output: + if output.startswith('BEGIN_EXTRA_PAYLOAD'): + is_payload_section = True + output = newProcess.stdout.readline() + if output.startswith('END_EXTRA_PAYLOAD'): + is_payload_section = False + output = '' + payload = '\n'.join(payload_section) + msg = email.parser.Parser().parsestr(payload) + for part in msg.get_payload(): + payload_result = json.loads(part.get_payload()) + if output and not is_payload_section: self.logger.info(output.strip()) results.append(output.strip()) - rc = newProcess.poll() + else: + payload_section.append(output.strip()) + rc = newProcess.poll() except Exception as e: self.logger.info("{} - Failed to execute command. Error: {}".format(self.blueprint_id, e)) results.append(e) - return False + payload_result["cds_return_code"] = False + return payload_result # deactivate_venv(blueprint_id) - return True + + payload_result["cds_return_code"] = rc + return payload_result def install_packages(self, request, type, f, results): + success = self.install_python_packages('UTILITY', results) + for package in request.packages: if package.type == type: f.write("Installed %s packages:\r\n" % CommandExecutor_pb2.PackageType.Name(type)) @@ -116,6 +139,8 @@ class CommandExecutorHandler(): if REQUIREMENTS_TXT == package: command = ["pip", "install", "-r", self.venv_home + "/Environments/" + REQUIREMENTS_TXT] + elif package == 'UTILITY': + command = ["cp", "-r", "./cds_utils", self.venv_home + "/lib/python3.6/site-packages/"] else: command = ["pip", "install", package] diff --git a/ms/command-executor/src/main/python/command_executor_server.py b/ms/command-executor/src/main/python/command_executor_server.py index 6266141d9..577c8a0ca 100644 --- a/ms/command-executor/src/main/python/command_executor_server.py +++ b/ms/command-executor/src/main/python/command_executor_server.py @@ -16,7 +16,7 @@ # limitations under the License. # import logging - +import os, sys import proto.CommandExecutor_pb2_grpc as CommandExecutor_pb2_grpc from command_executor_handler import CommandExecutorHandler @@ -39,19 +39,26 @@ class CommandExecutorServer(CommandExecutor_pb2_grpc.CommandExecutorServiceServi handler = CommandExecutorHandler(request) if not handler.prepare_env(request, results): self.logger.info("{} - Failed to prepare python environment. {}".format(blueprint_id, results)) - return utils.build_response(request, results, False) + return utils.build_response(request, results, {}, False) self.logger.info("{} - Package installation logs {}".format(blueprint_id, results)) - return utils.build_response(request, results) + return utils.build_response(request, results, {}, True) def executeCommand(self, request, context): blueprint_id = utils.get_blueprint_id(request) self.logger.info("{} - Received executeCommand request".format(blueprint_id)) - self.logger.info(request) + if os.environ.get('CE_DEBUG','false') == "true": + self.logger.info(request) - results = [] + log_results = [] + payload_result = {} handler = CommandExecutorHandler(request) - if not handler.execute_command(request, results): - self.logger.info("{} - Failed to executeCommand. {}".format(blueprint_id, results)) - return utils.build_response(request, results, False) - self.logger.info("{} - Execution finished successfully.".format(blueprint_id)) - return utils.build_response(request, results) + payload_result = handler.execute_command(request, log_results) + if not payload_result["cds_return_code"]: + self.logger.info("{} - Failed to executeCommand. {}".format(blueprint_id, log_results)) + else: + self.logger.info("{} - Execution finished successfully.".format(blueprint_id)) + + ret = utils.build_response(request, log_results, payload_result, payload_result["cds_return_code"]) + self.logger.info("Payload returned %s" % payload_result) + + return ret \ No newline at end of file diff --git a/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py b/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py index 478e00959..4edfc6cd5 100644 --- a/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py +++ b/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py @@ -23,7 +23,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( package='org.onap.ccsdk.cds.controllerblueprints.command.api', syntax='proto3', serialized_options=_b('P\001'), - serialized_pb=_b('\n\x15\x43ommandExecutor.proto\x12\x33org.onap.ccsdk.cds.controllerblueprints.command.api\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8f\x02\n\x0e\x45xecutionInput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x15\n\rcorrelationId\x18\x02 \x01(\t\x12U\n\x0bidentifiers\x18\x03 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\t\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xd0\x02\n\x0fPrepareEnvInput\x12U\n\x0bidentifiers\x18\x01 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x11\n\trequestId\x18\x02 \x01(\t\x12\x15\n\rcorrelationId\x18\x03 \x01(\t\x12O\n\x08packages\x18\x04 \x03(\x0b\x32=.org.onap.ccsdk.cds.controllerblueprints.command.api.Packages\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\">\n\x0bIdentifiers\x12\x15\n\rblueprintName\x18\x01 \x01(\t\x12\x18\n\x10\x62lueprintVersion\x18\x02 \x01(\t\"\xba\x01\n\x0f\x45xecutionOutput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x03(\t\x12S\n\x06status\x18\x03 \x01(\x0e\x32\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ResponseStatus\x12-\n\ttimestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"k\n\x08Packages\x12N\n\x04type\x18\x01 \x01(\x0e\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.PackageType\x12\x0f\n\x07package\x18\x02 \x03(\t**\n\x0eResponseStatus\x12\x0b\n\x07SUCCESS\x10\x00\x12\x0b\n\x07\x46\x41ILURE\x10\x01**\n\x0bPackageType\x12\x07\n\x03pip\x10\x00\x12\x12\n\x0e\x61nsible_galaxy\x10\x01\x32\xd1\x02\n\x16\x43ommandExecutorService\x12\x98\x01\n\nprepareEnv\x12\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput\x12\x9b\x01\n\x0e\x65xecuteCommand\x12\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutputB\x02P\x01\x62\x06proto3') + serialized_pb=_b('\n\x15\x43ommandExecutor.proto\x12\x33org.onap.ccsdk.cds.controllerblueprints.command.api\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8f\x02\n\x0e\x45xecutionInput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x15\n\rcorrelationId\x18\x02 \x01(\t\x12U\n\x0bidentifiers\x18\x03 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\t\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xd0\x02\n\x0fPrepareEnvInput\x12U\n\x0bidentifiers\x18\x01 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x11\n\trequestId\x18\x02 \x01(\t\x12\x15\n\rcorrelationId\x18\x03 \x01(\t\x12O\n\x08packages\x18\x04 \x03(\x0b\x32=.org.onap.ccsdk.cds.controllerblueprints.command.api.Packages\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\">\n\x0bIdentifiers\x12\x15\n\rblueprintName\x18\x01 \x01(\t\x12\x18\n\x10\x62lueprintVersion\x18\x02 \x01(\t\"\xcb\x01\n\x0f\x45xecutionOutput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x03(\t\x12S\n\x06status\x18\x03 \x01(\x0e\x32\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ResponseStatus\x12-\n\ttimestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07payload\x18\x05 \x01(\t\"k\n\x08Packages\x12N\n\x04type\x18\x01 \x01(\x0e\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.PackageType\x12\x0f\n\x07package\x18\x02 \x03(\t**\n\x0eResponseStatus\x12\x0b\n\x07SUCCESS\x10\x00\x12\x0b\n\x07\x46\x41ILURE\x10\x01*9\n\x0bPackageType\x12\x07\n\x03pip\x10\x00\x12\x12\n\x0e\x61nsible_galaxy\x10\x01\x12\r\n\tutilities\x10\x02\x32\xd1\x02\n\x16\x43ommandExecutorService\x12\x98\x01\n\nprepareEnv\x12\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput\x12\x9b\x01\n\x0e\x65xecuteCommand\x12\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutputB\x02P\x01\x62\x06proto3') , dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,]) @@ -44,8 +44,8 @@ _RESPONSESTATUS = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=1116, - serialized_end=1158, + serialized_start=1133, + serialized_end=1175, ) _sym_db.RegisterEnumDescriptor(_RESPONSESTATUS) @@ -64,11 +64,15 @@ _PACKAGETYPE = _descriptor.EnumDescriptor( name='ansible_galaxy', index=1, number=1, serialized_options=None, type=None), + _descriptor.EnumValueDescriptor( + name='utilities', index=2, number=2, + serialized_options=None, + type=None), ], containing_type=None, serialized_options=None, - serialized_start=1160, - serialized_end=1202, + serialized_start=1177, + serialized_end=1234, ) _sym_db.RegisterEnumDescriptor(_PACKAGETYPE) @@ -77,6 +81,7 @@ SUCCESS = 0 FAILURE = 1 pip = 0 ansible_galaxy = 1 +utilities = 2 @@ -299,6 +304,13 @@ _EXECUTIONOUTPUT = _descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='payload', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput.payload', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -312,7 +324,7 @@ _EXECUTIONOUTPUT = _descriptor.Descriptor( oneofs=[ ], serialized_start=819, - serialized_end=1005, + serialized_end=1022, ) @@ -349,8 +361,8 @@ _PACKAGES = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1007, - serialized_end=1114, + serialized_start=1024, + serialized_end=1131, ) _EXECUTIONINPUT.fields_by_name['identifiers'].message_type = _IDENTIFIERS @@ -372,39 +384,39 @@ DESCRIPTOR.enum_types_by_name['ResponseStatus'] = _RESPONSESTATUS DESCRIPTOR.enum_types_by_name['PackageType'] = _PACKAGETYPE _sym_db.RegisterFileDescriptor(DESCRIPTOR) -ExecutionInput = _reflection.GeneratedProtocolMessageType('ExecutionInput', (_message.Message,), dict( - DESCRIPTOR = _EXECUTIONINPUT, - __module__ = 'CommandExecutor_pb2' +ExecutionInput = _reflection.GeneratedProtocolMessageType('ExecutionInput', (_message.Message,), { + 'DESCRIPTOR' : _EXECUTIONINPUT, + '__module__' : 'CommandExecutor_pb2' # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput) - )) + }) _sym_db.RegisterMessage(ExecutionInput) -PrepareEnvInput = _reflection.GeneratedProtocolMessageType('PrepareEnvInput', (_message.Message,), dict( - DESCRIPTOR = _PREPAREENVINPUT, - __module__ = 'CommandExecutor_pb2' +PrepareEnvInput = _reflection.GeneratedProtocolMessageType('PrepareEnvInput', (_message.Message,), { + 'DESCRIPTOR' : _PREPAREENVINPUT, + '__module__' : 'CommandExecutor_pb2' # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput) - )) + }) _sym_db.RegisterMessage(PrepareEnvInput) -Identifiers = _reflection.GeneratedProtocolMessageType('Identifiers', (_message.Message,), dict( - DESCRIPTOR = _IDENTIFIERS, - __module__ = 'CommandExecutor_pb2' +Identifiers = _reflection.GeneratedProtocolMessageType('Identifiers', (_message.Message,), { + 'DESCRIPTOR' : _IDENTIFIERS, + '__module__' : 'CommandExecutor_pb2' # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers) - )) + }) _sym_db.RegisterMessage(Identifiers) -ExecutionOutput = _reflection.GeneratedProtocolMessageType('ExecutionOutput', (_message.Message,), dict( - DESCRIPTOR = _EXECUTIONOUTPUT, - __module__ = 'CommandExecutor_pb2' +ExecutionOutput = _reflection.GeneratedProtocolMessageType('ExecutionOutput', (_message.Message,), { + 'DESCRIPTOR' : _EXECUTIONOUTPUT, + '__module__' : 'CommandExecutor_pb2' # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput) - )) + }) _sym_db.RegisterMessage(ExecutionOutput) -Packages = _reflection.GeneratedProtocolMessageType('Packages', (_message.Message,), dict( - DESCRIPTOR = _PACKAGES, - __module__ = 'CommandExecutor_pb2' +Packages = _reflection.GeneratedProtocolMessageType('Packages', (_message.Message,), { + 'DESCRIPTOR' : _PACKAGES, + '__module__' : 'CommandExecutor_pb2' # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.command.api.Packages) - )) + }) _sym_db.RegisterMessage(Packages) @@ -416,8 +428,8 @@ _COMMANDEXECUTORSERVICE = _descriptor.ServiceDescriptor( file=DESCRIPTOR, index=0, serialized_options=None, - serialized_start=1205, - serialized_end=1542, + serialized_start=1237, + serialized_end=1574, methods=[ _descriptor.MethodDescriptor( name='prepareEnv', diff --git a/ms/command-executor/src/main/python/utils.py b/ms/command-executor/src/main/python/utils.py index 4314b287d..a3748eb17 100644 --- a/ms/command-executor/src/main/python/utils.py +++ b/ms/command-executor/src/main/python/utils.py @@ -16,7 +16,7 @@ from google.protobuf.timestamp_pb2 import Timestamp import proto.CommandExecutor_pb2 as CommandExecutor_pb2 - +import json def get_blueprint_id(request): blueprint_name = request.identifiers.blueprintName @@ -24,7 +24,7 @@ def get_blueprint_id(request): return blueprint_name + '/' + blueprint_version -def build_response(request, results, is_success=True): +def build_response(request, log_results, payload_return, is_success=False): if is_success: status = CommandExecutor_pb2.SUCCESS else: @@ -32,5 +32,9 @@ def build_response(request, results, is_success=True): timestamp = Timestamp() timestamp.GetCurrentTime() - return CommandExecutor_pb2.ExecutionOutput(requestId=request.requestId, response=results, status=status, - timestamp=timestamp) + + if 'cds_return_code' in payload_return: + payload_return.pop('cds_return_code') + payload_str = json.dumps(payload_return) + return CommandExecutor_pb2.ExecutionOutput(requestId=request.requestId, response=log_results, status=status, + payload=payload_str, timestamp=timestamp) -- 2.16.6