Add bi-directional GRPC python executor. 47/96147/3
authorBrinda Santh <bs2796@att.com>
Mon, 23 Sep 2019 14:10:58 +0000 (10:10 -0400)
committerBrinda Santh Muthuramalingam <bs2796@att.com>
Wed, 25 Sep 2019 16:01:44 +0000 (16:01 +0000)
Python based bidirectional communication script executor microservice.

Issue-ID: CCSDK-1747
Signed-off-by: Brinda Santh <bs2796@att.com>
Change-Id: If2e8f862ca4cb97d10714df2ab1cccccef2d576a

24 files changed:
.gitignore
components/model-catalog/proto-definition/proto/BluePrintCommon.proto
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingIntegrationTest.kt [new file with mode: 0644]
ms/pom.xml
ms/py-executor/blueprints_grpc/__init__.py [new file with mode: 0644]
ms/py-executor/blueprints_grpc/blueprint_processing_server.py [new file with mode: 0644]
ms/py-executor/blueprints_grpc/executor_utils.py [new file with mode: 0644]
ms/py-executor/blueprints_grpc/proto/BluePrintCommon_pb2.py [new file with mode: 0644]
ms/py-executor/blueprints_grpc/proto/BluePrintCommon_pb2_grpc.py [new file with mode: 0644]
ms/py-executor/blueprints_grpc/proto/BluePrintProcessing_pb2.py [new file with mode: 0644]
ms/py-executor/blueprints_grpc/proto/BluePrintProcessing_pb2_grpc.py [new file with mode: 0644]
ms/py-executor/blueprints_grpc/proto/__init__.py [new file with mode: 0644]
ms/py-executor/blueprints_grpc/request_header_validator_interceptor.py [new file with mode: 0644]
ms/py-executor/blueprints_grpc/script_executor_configuration.py [new file with mode: 0644]
ms/py-executor/configuration.ini [new file with mode: 0644]
ms/py-executor/docker/Dockerfile [new file with mode: 0644]
ms/py-executor/docker/distribution.xml [new file with mode: 0755]
ms/py-executor/docker/start.sh [new file with mode: 0755]
ms/py-executor/pom.xml [new file with mode: 0644]
ms/py-executor/requirements.txt [new file with mode: 0644]
ms/py-executor/server.py [new file with mode: 0644]
ms/py-executor/test/resources/sample-cba/1.0.0/Scripts/python/__init__.py [new file with mode: 0644]
ms/py-executor/test/resources/sample-cba/1.0.0/Scripts/python/module_utils.py [new file with mode: 0644]
ms/py-executor/test/resources/sample-cba/1.0.0/Scripts/python/sample_script.py [new file with mode: 0644]

index a60e7b9..48621bc 100644 (file)
@@ -146,6 +146,7 @@ cds-ui/server/public
 
 # Python generated class
 **/*py.class
+**/venv
 
 MacOS
 **/.DS_Store
index 9b24c50..ce90929 100644 (file)
@@ -37,4 +37,5 @@ enum EventType {
   EVENT_COMPONENT_PROCESSING = 1;
   EVENT_COMPONENT_NOTIFICATION = 2;
   EVENT_COMPONENT_EXECUTED = 3;
+  EVENT_COMPONENT_TRACE = 4;
 }
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingIntegrationTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingIntegrationTest.kt
new file mode 100644 (file)
index 0000000..8971ebd
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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.selfservice.api
+
+import com.google.protobuf.util.JsonFormat
+import io.grpc.stub.StreamObserver
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.onap.ccsdk.cds.blueprintsprocessor.grpc.GRPCLibConstants
+import org.onap.ccsdk.cds.blueprintsprocessor.grpc.TokenAuthGrpcClientProperties
+import org.onap.ccsdk.cds.blueprintsprocessor.grpc.service.TokenAuthGrpcClientService
+import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers
+import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader
+import org.onap.ccsdk.cds.controllerblueprints.core.logger
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc
+import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput
+import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput
+
+class BluePrintProcessingIntegrationTest {
+
+    private val log = logger(BluePrintProcessingIntegrationTest::class)
+
+    /** This is Integration test sample, Do not enable this test case in server build, this is for local desktop testing*/
+    //@Test
+    fun integrationTestGrpcManagement() {
+        runBlocking {
+            val tokenAuthGrpcClientProperties = TokenAuthGrpcClientProperties().apply {
+                host = "127.0.0.1"
+                port = 50052
+                type = GRPCLibConstants.TYPE_TOKEN_AUTH
+                token = "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw=="
+            }
+            val basicAuthGrpcClientService = TokenAuthGrpcClientService(tokenAuthGrpcClientProperties)
+            val channel = basicAuthGrpcClientService.channel()
+
+            val stub = BluePrintProcessingServiceGrpc.newStub(channel)
+            repeat(1) {
+                val requestObs = stub.process(object : StreamObserver<ExecutionServiceOutput> {
+                    override fun onNext(executionServiceOuput: ExecutionServiceOutput) {
+                        log.info("onNext Received {}", executionServiceOuput)
+                    }
+
+                    override fun onError(error: Throwable) {
+                        log.error("Fail to process message", error)
+                    }
+
+                    override fun onCompleted() {
+                        log.info("Done")
+                    }
+                })
+
+                val commonHeader = CommonHeader.newBuilder()
+                        .setTimestamp("2012-04-23T18:25:43.511Z")
+                        .setOriginatorId("System")
+                        .setRequestId("1234-$it")
+                        .setSubRequestId("1234-56").build()
+
+                val jsonContent = JacksonUtils.getClassPathFileContent("execution-input/sample-payload.json")
+                val payloadBuilder = ExecutionServiceInput.newBuilder().payloadBuilder
+                JsonFormat.parser().merge(jsonContent, payloadBuilder)
+
+                val actionIdentifier = ActionIdentifiers.newBuilder()
+                        .setActionName("SampleScript")
+                        .setBlueprintName("sample-cba")
+                        .setBlueprintVersion("1.0.0")
+                        .build()
+
+                val input = ExecutionServiceInput.newBuilder()
+                        .setCommonHeader(commonHeader)
+                        .setActionIdentifiers(actionIdentifier)
+                        .setPayload(payloadBuilder.build())
+                        .build()
+
+                requestObs.onNext(input)
+                requestObs.onCompleted()
+            }
+            delay(1000)
+            channel.shutdownNow()
+        }
+    }
+}
\ No newline at end of file
index ba5a5b0..5e8761b 100644 (file)
@@ -34,6 +34,7 @@
     <modules>
         <module>controllerblueprints</module>
         <module>blueprintsprocessor</module>
+        <module>py-executor</module>
         <module>command-executor</module>
         <module>sdclistener</module>
     </modules>
diff --git a/ms/py-executor/blueprints_grpc/__init__.py b/ms/py-executor/blueprints_grpc/__init__.py
new file mode 100644 (file)
index 0000000..726849f
--- /dev/null
@@ -0,0 +1,19 @@
+#  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.
+
+from .proto.BluePrintCommon_pb2 import *
+from .proto.BluePrintProcessing_pb2 import *
+from .script_executor_configuration import *
+from .executor_utils import *
+from .blueprint_processing_server import *
\ No newline at end of file
diff --git a/ms/py-executor/blueprints_grpc/blueprint_processing_server.py b/ms/py-executor/blueprints_grpc/blueprint_processing_server.py
new file mode 100644 (file)
index 0000000..0c432d4
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+#
+#  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.
+
+import logging
+from google.protobuf.json_format import MessageToJson
+from .proto import BluePrintProcessing_pb2_grpc as BluePrintProcessing_pb2_grpc
+from .script_executor_configuration import ScriptExecutorConfiguration
+from .executor_utils import instance_for_input
+
+
+class AbstractScriptFunction:
+
+    def set_context(self, context):
+        self.context = context
+
+    def process(self, request):
+        pass
+
+    def recover(self, runtime_exception, execution_request):
+        pass
+
+
+class BluePrintProcessingServer(BluePrintProcessing_pb2_grpc.BluePrintProcessingServiceServicer):
+
+    def __init__(self, configuration: ScriptExecutorConfiguration):
+        self.logger = logging.getLogger(self.__class__.__name__)
+        self.configuration = configuration
+
+    def process(self, request_iterator, context):
+        for request in request_iterator:
+            jsonObj = MessageToJson(request.payload)
+            self.logger.info(jsonObj)
+            # Get the Dynamic Process Instance based on request
+            instance: AbstractScriptFunction = instance_for_input(self.configuration, request)
+            instance.set_context(context)
+            return instance.process(request)
diff --git a/ms/py-executor/blueprints_grpc/executor_utils.py b/ms/py-executor/blueprints_grpc/executor_utils.py
new file mode 100644 (file)
index 0000000..224e35e
--- /dev/null
@@ -0,0 +1,138 @@
+#!/usr/bin/python
+#
+#  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.
+
+from google.protobuf.timestamp_pb2 import Timestamp
+from google.protobuf import struct_pb2
+from google.protobuf import json_format
+import sys, importlib, importlib.util, json, time, datetime
+import logging
+from .proto.BluePrintProcessing_pb2 import ExecutionServiceInput, ExecutionServiceOutput
+from .proto.BluePrintCommon_pb2 import Status, EVENT_COMPONENT_TRACE, EVENT_COMPONENT_PROCESSING, \
+    EVENT_COMPONENT_EXECUTED, EVENT_COMPONENT_NOTIFICATION
+from .script_executor_configuration import ScriptExecutorConfiguration
+
+logger = logging.getLogger("Utils")
+
+
+def current_time():
+    ts = time.time()
+    return datetime.datetime.fromtimestamp(ts).strftime("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
+
+
+def blueprint_id(input: ExecutionServiceInput):
+    blueprint_name = input.actionIdentifiers.blueprintName
+    blueprint_version = input.actionIdentifiers.blueprintVersion
+    return blueprint_name + '/' + blueprint_version
+
+
+def blueprint_location(config: ScriptExecutorConfiguration, input: ExecutionServiceInput):
+    blueprint_name = input.actionIdentifiers.blueprintName
+    blueprint_version = input.actionIdentifiers.blueprintVersion
+    return config.blueprints_processor('blueprintDeployPath') + '/' + blueprint_name + '/' + blueprint_version
+
+
+def instance_for_input(config: ScriptExecutorConfiguration, input: ExecutionServiceInput):
+    blueprint_name = input.actionIdentifiers.blueprintName
+    blueprint_version = input.actionIdentifiers.blueprintVersion
+    action_name = input.actionIdentifiers.actionName
+    # Get Blueprint python script location
+    script_location = blueprint_location(config, input) + '/' + 'Scripts/python/__init__.py'
+    logger.info(script_location)
+
+    # Create Dynamic Module Name
+    module_name = blueprint_name + '-' + blueprint_version
+    spec = importlib.util.spec_from_file_location(module_name, script_location)
+    logger.info(spec)
+    dynamic_module = importlib.util.module_from_spec(spec)
+    # Add blueprint modules
+    sys.modules[spec.name] = dynamic_module
+    spec.loader.exec_module(dynamic_module)
+    script_clazz = getattr(dynamic_module, action_name)
+    return script_clazz()
+
+
+def log_response(input: ExecutionServiceInput, message: str):
+    payload = struct_pb2.Struct()
+    payload['message'] = message
+    status = Status()
+    status.timestamp = current_time()
+    status.eventType = EVENT_COMPONENT_TRACE
+    return ExecutionServiceOutput(commonHeader=input.commonHeader,
+                                  actionIdentifiers=input.actionIdentifiers,
+                                  payload=payload, status=status)
+
+
+def send_notification(input: ExecutionServiceInput, message: str):
+    payload = struct_pb2.Struct()
+    payload['message'] = message
+    status = Status()
+    status.timestamp = current_time()
+    status.eventType = EVENT_COMPONENT_NOTIFICATION
+    return ExecutionServiceOutput(commonHeader=input.commonHeader,
+                                  actionIdentifiers=input.actionIdentifiers,
+                                  payload=payload, status=status)
+
+
+def ack_response(input: ExecutionServiceInput):
+    timestamp = Timestamp()
+    timestamp.GetCurrentTime()
+    response_common_header = input.commonHeader
+    status = Status()
+    status.timestamp = current_time()
+    status.eventType = EVENT_COMPONENT_PROCESSING
+    return ExecutionServiceOutput(commonHeader=response_common_header,
+                                  actionIdentifiers=input.actionIdentifiers,
+                                  status=status)
+
+
+def success_response(input: ExecutionServiceInput, property_json: json, code: int):
+    timestamp = Timestamp()
+    timestamp.GetCurrentTime()
+    status = Status()
+    status.timestamp = current_time()
+    status.eventType = EVENT_COMPONENT_EXECUTED
+    status.code = code
+    status.message = 'success'
+    payload_struct = create_response_payload_from_json(input.actionIdentifiers.actionName, property_json)
+    return ExecutionServiceOutput(commonHeader=input.commonHeader,
+                                  actionIdentifiers=input.actionIdentifiers, status=status, payload=payload_struct)
+
+
+def failure_response(input: ExecutionServiceInput, property_json: json, error_code: int,
+                     error_message: str):
+    timestamp = Timestamp()
+    timestamp.GetCurrentTime()
+    status = Status()
+    status.timestamp = current_time()
+    status.eventType = EVENT_COMPONENT_EXECUTED
+    status.code = error_code
+    status.message = 'failure'
+    payload_struct = create_response_payload_from_json(input.actionIdentifiers.actionName, property_json)
+    status.errorMessage = error_message
+    return ExecutionServiceOutput(commonHeader=input.commonHeader,
+                                  actionIdentifiers=input.actionIdentifiers, status=status, payload=payload_struct)
+
+
+def create_response_payload_from_json(action_name, property_json: json):
+    # Create response Pay load json from property Json
+    payload_key = action_name + '-response'
+    response_payload = {}
+    response_payload[payload_key] = property_json
+    response_payload_json = json.dumps(response_payload)
+    # Create Struct from Json
+    payload_struct = struct_pb2.Struct()
+    json_format.Parse(str(response_payload_json), payload_struct, ignore_unknown_fields=True)
+    return payload_struct
diff --git a/ms/py-executor/blueprints_grpc/proto/BluePrintCommon_pb2.py b/ms/py-executor/blueprints_grpc/proto/BluePrintCommon_pb2.py
new file mode 100644 (file)
index 0000000..db78b2b
--- /dev/null
@@ -0,0 +1,331 @@
+# -*- coding: utf-8 -*-
+
+#  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.
+
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: BluePrintCommon.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf.internal import enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='BluePrintCommon.proto',
+  package='org.onap.ccsdk.cds.controllerblueprints.common.api',
+  syntax='proto3',
+  serialized_options=_b('P\001'),
+  serialized_pb=_b('\n\x15\x42luePrintCommon.proto\x12\x32org.onap.ccsdk.cds.controllerblueprints.common.api\"\xa8\x01\n\x0c\x43ommonHeader\x12\x11\n\ttimestamp\x18\x01 \x01(\t\x12\x14\n\x0coriginatorId\x18\x17 \x01(\t\x12\x11\n\trequestId\x18\x03 \x01(\t\x12\x14\n\x0csubRequestId\x18\x04 \x01(\t\x12\x46\n\x04\x66lag\x18\x05 \x01(\x0b\x32\x38.org.onap.ccsdk.cds.controllerblueprints.common.api.Flag\"$\n\x04\x46lag\x12\x0f\n\x07isForce\x18\x01 \x01(\x08\x12\x0b\n\x03ttl\x18\x02 \x01(\x05\"f\n\x11\x41\x63tionIdentifiers\x12\x15\n\rblueprintName\x18\x01 \x01(\t\x12\x18\n\x10\x62lueprintVersion\x18\x02 \x01(\t\x12\x12\n\nactionName\x18\x03 \x01(\t\x12\x0c\n\x04mode\x18\x04 \x01(\t\"\xa2\x01\n\x06Status\x12\x0c\n\x04\x63ode\x18\x01 \x01(\x05\x12\x14\n\x0c\x65rrorMessage\x18\x02 \x01(\t\x12\x0f\n\x07message\x18\x03 \x01(\t\x12P\n\teventType\x18\x04 \x01(\x0e\x32=.org.onap.ccsdk.cds.controllerblueprints.common.api.EventType\x12\x11\n\ttimestamp\x18\x05 \x01(\t*\xa3\x01\n\tEventType\x12\x1b\n\x17\x45VENT_COMPONENT_FAILURE\x10\x00\x12\x1e\n\x1a\x45VENT_COMPONENT_PROCESSING\x10\x01\x12 \n\x1c\x45VENT_COMPONENT_NOTIFICATION\x10\x02\x12\x1c\n\x18\x45VENT_COMPONENT_EXECUTED\x10\x03\x12\x19\n\x15\x45VENT_COMPONENT_TRACE\x10\x04\x42\x02P\x01\x62\x06proto3')
+)
+
+_EVENTTYPE = _descriptor.EnumDescriptor(
+  name='EventType',
+  full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.EventType',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='EVENT_COMPONENT_FAILURE', index=0, number=0,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='EVENT_COMPONENT_PROCESSING', index=1, number=1,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='EVENT_COMPONENT_NOTIFICATION', index=2, number=2,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='EVENT_COMPONENT_EXECUTED', index=3, number=3,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='EVENT_COMPONENT_TRACE', index=4, number=4,
+      serialized_options=None,
+      type=None),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=556,
+  serialized_end=719,
+)
+_sym_db.RegisterEnumDescriptor(_EVENTTYPE)
+
+EventType = enum_type_wrapper.EnumTypeWrapper(_EVENTTYPE)
+EVENT_COMPONENT_FAILURE = 0
+EVENT_COMPONENT_PROCESSING = 1
+EVENT_COMPONENT_NOTIFICATION = 2
+EVENT_COMPONENT_EXECUTED = 3
+EVENT_COMPONENT_TRACE = 4
+
+
+
+_COMMONHEADER = _descriptor.Descriptor(
+  name='CommonHeader',
+  full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='timestamp', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader.timestamp', index=0,
+      number=1, 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),
+    _descriptor.FieldDescriptor(
+      name='originatorId', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader.originatorId', index=1,
+      number=23, 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),
+    _descriptor.FieldDescriptor(
+      name='requestId', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader.requestId', index=2,
+      number=3, 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),
+    _descriptor.FieldDescriptor(
+      name='subRequestId', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader.subRequestId', index=3,
+      number=4, 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),
+    _descriptor.FieldDescriptor(
+      name='flag', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader.flag', index=4,
+      number=5, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=78,
+  serialized_end=246,
+)
+
+
+_FLAG = _descriptor.Descriptor(
+  name='Flag',
+  full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.Flag',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='isForce', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.Flag.isForce', index=0,
+      number=1, type=8, cpp_type=7, label=1,
+      has_default_value=False, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='ttl', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.Flag.ttl', index=1,
+      number=2, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=248,
+  serialized_end=284,
+)
+
+
+_ACTIONIDENTIFIERS = _descriptor.Descriptor(
+  name='ActionIdentifiers',
+  full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='blueprintName', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers.blueprintName', index=0,
+      number=1, 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),
+    _descriptor.FieldDescriptor(
+      name='blueprintVersion', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers.blueprintVersion', index=1,
+      number=2, 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),
+    _descriptor.FieldDescriptor(
+      name='actionName', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers.actionName', index=2,
+      number=3, 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),
+    _descriptor.FieldDescriptor(
+      name='mode', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers.mode', index=3,
+      number=4, 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=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=286,
+  serialized_end=388,
+)
+
+
+_STATUS = _descriptor.Descriptor(
+  name='Status',
+  full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.Status',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='code', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.Status.code', index=0,
+      number=1, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='errorMessage', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.Status.errorMessage', index=1,
+      number=2, 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),
+    _descriptor.FieldDescriptor(
+      name='message', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.Status.message', index=2,
+      number=3, 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),
+    _descriptor.FieldDescriptor(
+      name='eventType', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.Status.eventType', index=3,
+      number=4, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='timestamp', full_name='org.onap.ccsdk.cds.controllerblueprints.common.api.Status.timestamp', 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=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=391,
+  serialized_end=553,
+)
+
+_COMMONHEADER.fields_by_name['flag'].message_type = _FLAG
+_STATUS.fields_by_name['eventType'].enum_type = _EVENTTYPE
+DESCRIPTOR.message_types_by_name['CommonHeader'] = _COMMONHEADER
+DESCRIPTOR.message_types_by_name['Flag'] = _FLAG
+DESCRIPTOR.message_types_by_name['ActionIdentifiers'] = _ACTIONIDENTIFIERS
+DESCRIPTOR.message_types_by_name['Status'] = _STATUS
+DESCRIPTOR.enum_types_by_name['EventType'] = _EVENTTYPE
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+CommonHeader = _reflection.GeneratedProtocolMessageType('CommonHeader', (_message.Message,), {
+  'DESCRIPTOR' : _COMMONHEADER,
+  '__module__' : 'BluePrintCommon_pb2'
+  # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader)
+  })
+_sym_db.RegisterMessage(CommonHeader)
+
+Flag = _reflection.GeneratedProtocolMessageType('Flag', (_message.Message,), {
+  'DESCRIPTOR' : _FLAG,
+  '__module__' : 'BluePrintCommon_pb2'
+  # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.common.api.Flag)
+  })
+_sym_db.RegisterMessage(Flag)
+
+ActionIdentifiers = _reflection.GeneratedProtocolMessageType('ActionIdentifiers', (_message.Message,), {
+  'DESCRIPTOR' : _ACTIONIDENTIFIERS,
+  '__module__' : 'BluePrintCommon_pb2'
+  # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers)
+  })
+_sym_db.RegisterMessage(ActionIdentifiers)
+
+Status = _reflection.GeneratedProtocolMessageType('Status', (_message.Message,), {
+  'DESCRIPTOR' : _STATUS,
+  '__module__' : 'BluePrintCommon_pb2'
+  # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.common.api.Status)
+  })
+_sym_db.RegisterMessage(Status)
+
+
+DESCRIPTOR._options = None
+# @@protoc_insertion_point(module_scope)
diff --git a/ms/py-executor/blueprints_grpc/proto/BluePrintCommon_pb2_grpc.py b/ms/py-executor/blueprints_grpc/proto/BluePrintCommon_pb2_grpc.py
new file mode 100644 (file)
index 0000000..0129ff9
--- /dev/null
@@ -0,0 +1,17 @@
+#  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.
+
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+import grpc
+
diff --git a/ms/py-executor/blueprints_grpc/proto/BluePrintProcessing_pb2.py b/ms/py-executor/blueprints_grpc/proto/BluePrintProcessing_pb2.py
new file mode 100644 (file)
index 0000000..36f8c41
--- /dev/null
@@ -0,0 +1,193 @@
+# -*- coding: utf-8 -*-
+
+#  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.
+
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: BluePrintProcessing.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2
+from blueprints_grpc.proto import BluePrintCommon_pb2 as BluePrintCommon__pb2
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='BluePrintProcessing.proto',
+  package='org.onap.ccsdk.cds.controllerblueprints.processing.api',
+  syntax='proto3',
+  serialized_options=_b('P\001'),
+  serialized_pb=_b('\n\x19\x42luePrintProcessing.proto\x12\x36org.onap.ccsdk.cds.controllerblueprints.processing.api\x1a\x1cgoogle/protobuf/struct.proto\x1a\x15\x42luePrintCommon.proto\"\xfb\x01\n\x15\x45xecutionServiceInput\x12V\n\x0c\x63ommonHeader\x18\x01 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader\x12`\n\x11\x61\x63tionIdentifiers\x18\x02 \x01(\x0b\x32\x45.org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers\x12(\n\x07payload\x18\x03 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xc8\x02\n\x16\x45xecutionServiceOutput\x12V\n\x0c\x63ommonHeader\x18\x01 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader\x12`\n\x11\x61\x63tionIdentifiers\x18\x02 \x01(\x0b\x32\x45.org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers\x12J\n\x06status\x18\x03 \x01(\x0b\x32:.org.onap.ccsdk.cds.controllerblueprints.common.api.Status\x12(\n\x07payload\x18\x04 \x01(\x0b\x32\x17.google.protobuf.Struct2\xcb\x01\n\x1a\x42luePrintProcessingService\x12\xac\x01\n\x07process\x12M.org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput\x1aN.org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput(\x01\x30\x01\x42\x02P\x01\x62\x06proto3')
+  ,
+  dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,BluePrintCommon__pb2.DESCRIPTOR,])
+
+
+
+
+_EXECUTIONSERVICEINPUT = _descriptor.Descriptor(
+  name='ExecutionServiceInput',
+  full_name='org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='commonHeader', full_name='org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput.commonHeader', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='actionIdentifiers', full_name='org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput.actionIdentifiers', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      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.processing.api.ExecutionServiceInput.payload', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=139,
+  serialized_end=390,
+)
+
+
+_EXECUTIONSERVICEOUTPUT = _descriptor.Descriptor(
+  name='ExecutionServiceOutput',
+  full_name='org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='commonHeader', full_name='org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput.commonHeader', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='actionIdentifiers', full_name='org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput.actionIdentifiers', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='status', full_name='org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput.status', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      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.processing.api.ExecutionServiceOutput.payload', index=3,
+      number=4, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=393,
+  serialized_end=721,
+)
+
+_EXECUTIONSERVICEINPUT.fields_by_name['commonHeader'].message_type = BluePrintCommon__pb2._COMMONHEADER
+_EXECUTIONSERVICEINPUT.fields_by_name['actionIdentifiers'].message_type = BluePrintCommon__pb2._ACTIONIDENTIFIERS
+_EXECUTIONSERVICEINPUT.fields_by_name['payload'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT
+_EXECUTIONSERVICEOUTPUT.fields_by_name['commonHeader'].message_type = BluePrintCommon__pb2._COMMONHEADER
+_EXECUTIONSERVICEOUTPUT.fields_by_name['actionIdentifiers'].message_type = BluePrintCommon__pb2._ACTIONIDENTIFIERS
+_EXECUTIONSERVICEOUTPUT.fields_by_name['status'].message_type = BluePrintCommon__pb2._STATUS
+_EXECUTIONSERVICEOUTPUT.fields_by_name['payload'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT
+DESCRIPTOR.message_types_by_name['ExecutionServiceInput'] = _EXECUTIONSERVICEINPUT
+DESCRIPTOR.message_types_by_name['ExecutionServiceOutput'] = _EXECUTIONSERVICEOUTPUT
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+ExecutionServiceInput = _reflection.GeneratedProtocolMessageType('ExecutionServiceInput', (_message.Message,), {
+  'DESCRIPTOR' : _EXECUTIONSERVICEINPUT,
+  '__module__' : 'BluePrintProcessing_pb2'
+  # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput)
+  })
+_sym_db.RegisterMessage(ExecutionServiceInput)
+
+ExecutionServiceOutput = _reflection.GeneratedProtocolMessageType('ExecutionServiceOutput', (_message.Message,), {
+  'DESCRIPTOR' : _EXECUTIONSERVICEOUTPUT,
+  '__module__' : 'BluePrintProcessing_pb2'
+  # @@protoc_insertion_point(class_scope:org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput)
+  })
+_sym_db.RegisterMessage(ExecutionServiceOutput)
+
+
+DESCRIPTOR._options = None
+
+_BLUEPRINTPROCESSINGSERVICE = _descriptor.ServiceDescriptor(
+  name='BluePrintProcessingService',
+  full_name='org.onap.ccsdk.cds.controllerblueprints.processing.api.BluePrintProcessingService',
+  file=DESCRIPTOR,
+  index=0,
+  serialized_options=None,
+  serialized_start=724,
+  serialized_end=927,
+  methods=[
+  _descriptor.MethodDescriptor(
+    name='process',
+    full_name='org.onap.ccsdk.cds.controllerblueprints.processing.api.BluePrintProcessingService.process',
+    index=0,
+    containing_service=None,
+    input_type=_EXECUTIONSERVICEINPUT,
+    output_type=_EXECUTIONSERVICEOUTPUT,
+    serialized_options=None,
+  ),
+])
+_sym_db.RegisterServiceDescriptor(_BLUEPRINTPROCESSINGSERVICE)
+
+DESCRIPTOR.services_by_name['BluePrintProcessingService'] = _BLUEPRINTPROCESSINGSERVICE
+
+# @@protoc_insertion_point(module_scope)
diff --git a/ms/py-executor/blueprints_grpc/proto/BluePrintProcessing_pb2_grpc.py b/ms/py-executor/blueprints_grpc/proto/BluePrintProcessing_pb2_grpc.py
new file mode 100644 (file)
index 0000000..a482f56
--- /dev/null
@@ -0,0 +1,60 @@
+#  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.
+
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+import grpc
+
+from blueprints_grpc.proto import BluePrintProcessing_pb2 as BluePrintProcessing__pb2
+
+
+class BluePrintProcessingServiceStub(object):
+  # missing associated documentation comment in .proto file
+  pass
+
+  def __init__(self, channel):
+    """Constructor.
+
+    Args:
+      channel: A grpc.Channel.
+    """
+    self.process = channel.stream_stream(
+        '/org.onap.ccsdk.cds.controllerblueprints.processing.api.BluePrintProcessingService/process',
+        request_serializer=BluePrintProcessing__pb2.ExecutionServiceInput.SerializeToString,
+        response_deserializer=BluePrintProcessing__pb2.ExecutionServiceOutput.FromString,
+        )
+
+
+class BluePrintProcessingServiceServicer(object):
+  # missing associated documentation comment in .proto file
+  pass
+
+  def process(self, request_iterator, context):
+    # missing associated documentation comment in .proto file
+    pass
+    context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+    context.set_details('Method not implemented!')
+    raise NotImplementedError('Method not implemented!')
+
+
+def add_BluePrintProcessingServiceServicer_to_server(servicer, server):
+  rpc_method_handlers = {
+      'process': grpc.stream_stream_rpc_method_handler(
+          servicer.process,
+          request_deserializer=BluePrintProcessing__pb2.ExecutionServiceInput.FromString,
+          response_serializer=BluePrintProcessing__pb2.ExecutionServiceOutput.SerializeToString,
+      ),
+  }
+  generic_handler = grpc.method_handlers_generic_handler(
+      'org.onap.ccsdk.cds.controllerblueprints.processing.api.BluePrintProcessingService', rpc_method_handlers)
+  server.add_generic_rpc_handlers((generic_handler,))
diff --git a/ms/py-executor/blueprints_grpc/proto/__init__.py b/ms/py-executor/blueprints_grpc/proto/__init__.py
new file mode 100644 (file)
index 0000000..b63c94c
--- /dev/null
@@ -0,0 +1,14 @@
+#  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.
+
diff --git a/ms/py-executor/blueprints_grpc/request_header_validator_interceptor.py b/ms/py-executor/blueprints_grpc/request_header_validator_interceptor.py
new file mode 100644 (file)
index 0000000..d9906ab
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+#
+# 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.
+# 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.
+#
+
+import grpc
+
+
+def _unary_unary_rpc_terminator(code, details):
+    def terminate(ignored_request, context):
+        context.abort(code, details)
+
+    return grpc.unary_unary_rpc_method_handler(terminate)
+
+
+class RequestHeaderValidatorInterceptor(grpc.ServerInterceptor):
+
+    def __init__(self, header, value, code, details):
+        self._header = header
+        self._value = value
+        self._terminator = _unary_unary_rpc_terminator(code, details)
+
+    def intercept_service(self, continuation, handler_call_details):
+        if (self._header, self._value) in handler_call_details.invocation_metadata:
+            return continuation(handler_call_details)
+        else:
+            return self._terminator
diff --git a/ms/py-executor/blueprints_grpc/script_executor_configuration.py b/ms/py-executor/blueprints_grpc/script_executor_configuration.py
new file mode 100644 (file)
index 0000000..2f0553b
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+#
+#  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.
+
+import os
+import logging
+import configparser
+from pathlib import Path, PurePath
+
+
+class ScriptExecutorConfiguration:
+
+    def __init__(self, file_path: str):
+        self.logger = logging.getLogger(self.__class__.__name__)
+        self.logger.info('loading configuration file : {}'.format(file_path))
+        self.config = configparser.ConfigParser(os.environ)
+        self.config.read(file_path, encoding='utf-8')
+
+    def get_section(self, section_name: str):
+        return self.config[section_name]
+
+    def get_property(self, section_name: str, property_name: str):
+        return self.config.get(section_name, property_name)
+
+    def script_executor_property(self, property_name: str):
+        return self.config.get('scriptExecutor', property_name)
+
+    def blueprints_processor(self, property_name: str):
+        return self.config.get('blueprintsprocessor', property_name)
+
+
+if __name__ == '__main__':
+    config_file = str(PurePath(Path().absolute())) + '/../configuration.ini'
+    scriptExecutorConfiguration = ScriptExecutorConfiguration(config_file)
+    blueprintDeployPath = scriptExecutorConfiguration.get_property('blueprintsprocessor', 'blueprintDeployPath')
+    print(blueprintDeployPath)
diff --git a/ms/py-executor/configuration.ini b/ms/py-executor/configuration.ini
new file mode 100644 (file)
index 0000000..8c36dd0
--- /dev/null
@@ -0,0 +1,11 @@
+[scriptExecutor]
+port=%(APP_PORT)s
+auth=%(BASIC_AUTH)s
+logFile=%(LOG_FILE)s
+maxWorkers=20
+
+[blueprintsprocessor]
+#blueprintDeployPath=test/resources
+blueprintDeployPath=/opt/app/onap/blueprints/deploy
+blueprintArchivePath=/opt/app/onap/blueprints/archive
+blueprintWorkingPath=/opt/app/onap/blueprints/work
diff --git a/ms/py-executor/docker/Dockerfile b/ms/py-executor/docker/Dockerfile
new file mode 100644 (file)
index 0000000..1121805
--- /dev/null
@@ -0,0 +1,18 @@
+FROM python:3.7-slim
+
+ENV HTTP_PROXY  ${HTTP_PROXY}
+ENV HTTPS_PROXY ${HTTPS_PROXY}
+
+RUN mkdir -p /opt/app/onap/logs/ && touch /opt/app/onap/logs/application.log
+
+COPY @project.build.finalName@-@assembly.id@.tar.gz /source.tar.gz
+RUN tar -xzf /source.tar.gz -C /tmp \
+ && cp -rf /tmp/@project.build.finalName@/opt / \
+ && rm -rf /source.tar.gz \
+ && rm -rf /tmp/@project.build.finalName@
+
+RUN pip install --no-cache-dir -r /opt/app/onap/requirements.txt
+
+VOLUME /opt/app/onap/blueprints/deploy/
+
+ENTRYPOINT /opt/app/onap/start.sh
\ No newline at end of file
diff --git a/ms/py-executor/docker/distribution.xml b/ms/py-executor/docker/distribution.xml
new file mode 100755 (executable)
index 0000000..8bd06c8
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
+    <id>${assembly.id}</id>
+    <formats>
+        <format>tar.gz</format>
+    </formats>
+    <fileSets>
+        <fileSet>
+            <directory>${project.basedir}</directory>
+            <outputDirectory>opt/app/onap/python</outputDirectory>
+            <includes>
+                <include>blueprints_grpc/**/*.py</include>
+                <include>*.py</include>
+            </includes>
+            <useDefaultExcludes>true</useDefaultExcludes>
+        </fileSet>
+        <fileSet>
+            <directory>${project.basedir}</directory>
+            <outputDirectory>opt/app/onap</outputDirectory>
+            <includes>
+                <include>requirements.txt</include>
+                <include>configuration.ini</include>
+            </includes>
+            <useDefaultExcludes>true</useDefaultExcludes>
+        </fileSet>
+        <fileSet>
+            <directory>${project.basedir}/docker</directory>
+            <outputDirectory>opt/app/onap</outputDirectory>
+            <includes>
+                <include>*.sh</include>
+            </includes>
+            <useDefaultExcludes>true</useDefaultExcludes>
+        </fileSet>
+    </fileSets>
+</assembly>
\ No newline at end of file
diff --git a/ms/py-executor/docker/start.sh b/ms/py-executor/docker/start.sh
new file mode 100755 (executable)
index 0000000..fd53d47
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# 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.
+# 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.
+#
+
+if [ -z "${APP_PORT}" ]
+then
+  echo "APP_PORT environment variable is not set, using default."
+  export APP_PORT=50052
+fi
+
+if [ -z "${BASIC_AUTH}" ]
+then
+  echo "BASIC_AUTH environment variable is not set, using default."
+  export BASIC_AUTH="Basic Y2NzZGthcHBzOmNjc2RrYXBwcw=="
+fi
+
+if [ -z "${LOG_FILE}" ]
+then
+  echo "LOG_FILE environment variable is not set, using default."
+  export LOG_FILE="application.log"
+fi
+
+if [ "${http_proxy}" ]
+then
+  echo "Setting http_proxy: ${http_proxy}"
+fi
+
+if [ "${https_proxy}" ]
+then
+  echo "Setting https_proxy: ${https_proxy}"
+fi
+
+cd /opt/app/onap/python/
+python server.py
\ No newline at end of file
diff --git a/ms/py-executor/pom.xml b/ms/py-executor/pom.xml
new file mode 100644 (file)
index 0000000..ef52898
--- /dev/null
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onap.ccsdk.cds</groupId>
+        <artifactId>ms</artifactId>
+        <version>0.7.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>py-executor</artifactId>
+
+    <name>Python Script Executor</name>
+    <description>Micro-service providing python environment with gRPC binding for python script execution</description>
+
+    <properties>
+        <assembly.id>maven</assembly.id>
+        <image.name>onap/ccsdk-py-executor</image.name>
+        <docker.push.phase>deploy</docker.push.phase>
+        <docker.verbose>true</docker.verbose>
+        <ccsdk.project.version>${project.version}</ccsdk.project.version>
+        <ccsdk.build.timestamp>${maven.build.timestamp}</ccsdk.build.timestamp>
+        <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
+                <executions>
+                    <execution>
+                        <id>copy-dockerfile</id>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <phase>validate</phase>
+                        <configuration>
+                            <outputDirectory>${project.basedir}/target/docker-stage</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>docker</directory>
+                                    <includes>
+                                        <include>Dockerfile</include>
+                                        <include>start.sh</include>
+                                    </includes>
+                                    <filtering>true</filtering>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <outputDirectory>${project.basedir}/target/docker-stage</outputDirectory>
+                    <descriptors>
+                        <descriptor>docker/distribution.xml</descriptor>
+                    </descriptors>
+                    <tarLongFileMode>posix</tarLongFileMode>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>${assembly.id}</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.groovy.maven</groupId>
+                <artifactId>gmaven-plugin</artifactId>
+                <version>1.0</version>
+                <executions>
+                    <execution>
+                        <phase>validate</phase>
+                        <goals>
+                            <goal>execute</goal>
+                        </goals>
+                        <configuration>
+                            <source>${basedir}/../../TagVersion.groovy</source>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>docker</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>io.fabric8</groupId>
+                        <artifactId>docker-maven-plugin</artifactId>
+                        <version>0.26.1</version>
+                        <inherited>false</inherited>
+                        <configuration>
+                            <images>
+                                <image>
+                                    <name>${image.name}</name>
+                                    <build>
+                                        <cleanup>try</cleanup>
+                                        <dockerFileDir>${basedir}/target/docker-stage</dockerFileDir>
+                                        <tags>
+                                            <tag>${project.docker.latestminortag.version}</tag>
+                                            <tag>${project.docker.latestfulltag.version}</tag>
+                                            <tag>${project.docker.latesttagtimestamp.version}</tag>
+                                        </tags>
+                                    </build>
+                                </image>
+                            </images>
+                            <verbose>true</verbose>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>generate-images</id>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>build</goal>
+                                </goals>
+                            </execution>
+                            <execution>
+                                <id>push-images</id>
+                                <phase>${docker.push.phase}</phase>
+                                <goals>
+                                    <goal>build</goal>
+                                    <goal>push</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/ms/py-executor/requirements.txt b/ms/py-executor/requirements.txt
new file mode 100644 (file)
index 0000000..6051e04
--- /dev/null
@@ -0,0 +1,6 @@
+grpcio==1.23.0
+grpcio-tools==1.23.0
+configparser==4.0.2
+requests==2.22.0
+ncclient==0.6.6
+ciscoconfparse==1.4.7
\ No newline at end of file
diff --git a/ms/py-executor/server.py b/ms/py-executor/server.py
new file mode 100644 (file)
index 0000000..5c149d9
--- /dev/null
@@ -0,0 +1,73 @@
+#!/usr/bin/python
+#
+#  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.
+#  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.
+
+from builtins import KeyboardInterrupt
+from concurrent import futures
+import logging
+import time
+import grpc
+from pathlib import Path, PurePath
+from blueprints_grpc import BluePrintProcessing_pb2_grpc
+from blueprints_grpc.request_header_validator_interceptor import RequestHeaderValidatorInterceptor
+from blueprints_grpc.blueprint_processing_server import BluePrintProcessingServer
+from blueprints_grpc import ScriptExecutorConfiguration
+
+logger = logging.getLogger("Server")
+
+_ONE_DAY_IN_SECONDS = 60 * 60 * 24
+
+
+def serve(configuration: ScriptExecutorConfiguration):
+    port = configuration.script_executor_property('port')
+    basic_auth = configuration.script_executor_property('auth')
+    maxWorkers = configuration.script_executor_property('maxWorkers')
+
+    header_validator = RequestHeaderValidatorInterceptor(
+        'authorization', basic_auth, grpc.StatusCode.UNAUTHENTICATED,
+        'Access denied!')
+
+    server = grpc.server(futures.ThreadPoolExecutor(max_workers=int(maxWorkers)),
+                         interceptors=(header_validator,))
+
+    BluePrintProcessing_pb2_grpc.add_BluePrintProcessingServiceServicer_to_server(
+        BluePrintProcessingServer(configuration), server)
+
+    server.add_insecure_port('[::]:' + port)
+    server.start()
+
+    logger.info("Command Executor Server started on %s" % port)
+
+    try:
+        while True:
+            time.sleep(_ONE_DAY_IN_SECONDS)
+    except KeyboardInterrupt:
+        server.stop(0)
+
+
+if __name__ == '__main__':
+    config_file = str(PurePath(Path().absolute())) + '/configuration.ini'
+    configuration = ScriptExecutorConfiguration(config_file)
+    logging_formater = '%(asctime)s - %(name)s - %(threadName)s - %(levelname)s - %(message)s'
+    logging.basicConfig(filename=configuration.script_executor_property('logFile'),
+                        level=logging.DEBUG,
+                        format=logging_formater)
+    console = logging.StreamHandler()
+    console.setLevel(logging.INFO)
+    formatter = logging.Formatter(logging_formater)
+    console.setFormatter(formatter)
+    logging.getLogger('').addHandler(console)
+    serve(configuration)
diff --git a/ms/py-executor/test/resources/sample-cba/1.0.0/Scripts/python/__init__.py b/ms/py-executor/test/resources/sample-cba/1.0.0/Scripts/python/__init__.py
new file mode 100644 (file)
index 0000000..82407c2
--- /dev/null
@@ -0,0 +1,16 @@
+#  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.
+
+from .sample_script import *
+from .module_utils import *
\ No newline at end of file
diff --git a/ms/py-executor/test/resources/sample-cba/1.0.0/Scripts/python/module_utils.py b/ms/py-executor/test/resources/sample-cba/1.0.0/Scripts/python/module_utils.py
new file mode 100644 (file)
index 0000000..627b6ee
--- /dev/null
@@ -0,0 +1,18 @@
+
+
+#  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.
+
+def say_hi():
+    print("successfully pinged")
\ No newline at end of file
diff --git a/ms/py-executor/test/resources/sample-cba/1.0.0/Scripts/python/sample_script.py b/ms/py-executor/test/resources/sample-cba/1.0.0/Scripts/python/sample_script.py
new file mode 100644 (file)
index 0000000..3af46b2
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+#
+#  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.
+
+import logging
+from blueprints_grpc import executor_utils
+from blueprints_grpc.blueprint_processing_server import AbstractScriptFunction
+from .module_utils import say_hi
+import json
+
+
+class SampleScript(AbstractScriptFunction):
+    def __init__(self):
+        self.logger = logging.getLogger(self.__class__.__name__)
+
+    def process(self, execution_request):
+        self.logger.info("Request Received in Script : {}".format(execution_request))
+        yield executor_utils.log_response(execution_request, "First message")
+        yield executor_utils.log_response(execution_request, "Second message")
+
+        # TO check , If this class could call other python files.
+        say_hi()
+
+        # Check Yield should be called from other methods.
+        yield from self.send_notification(execution_request)
+
+        response_data = """{
+        "property" : "value"
+         }
+        """
+        response_payload_json = json.loads(response_data)
+
+        yield executor_utils.success_response(execution_request, response_payload_json, 200)
+
+    def recover(self, runtime_exception, execution_request):
+        return None
+
+    def send_notification(self, execution_request):
+        yield executor_utils.send_notification(execution_request, "I am notification")