diff --git a/connect/eaas/core/dataclasses.py b/connect/eaas/core/dataclasses.py index 7ed05ea..84845f5 100644 --- a/connect/eaas/core/dataclasses.py +++ b/connect/eaas/core/dataclasses.py @@ -42,8 +42,8 @@ class ResultType: class MessageType: - EXTENSION = 'extension' - SETTINGS = 'settings' + SETUP_REQUEST = 'setup_request' + SETUP_RESPONSE = 'setup_response' TASK = 'task' PAUSE = 'pause' RESUME = 'resume' @@ -56,32 +56,31 @@ class MessageType: class TaskOptions(BaseModel): task_id: str task_category: str - result: Optional[str] - countdown: int = 0 - runtime: float = 0.0 - output: Optional[str] correlation_id: Optional[str] reply_to: Optional[str] +class TaskOutput(BaseModel): + result: str + data: Optional[Any] + countdown: int = 0 + runtime: float = 0.0 + error: Optional[str] + + class TaskInput(BaseModel): event_type: str object_id: str data: Optional[Any] -class TaskPayload(BaseModel): +class Task(BaseModel): options: TaskOptions input: TaskInput + output: Optional[TaskOutput] -class Logging(BaseModel): - logging_api_key: Optional[str] - log_level: Optional[str] - runner_log_level: Optional[str] - - -class Service(BaseModel): +class LogMeta(BaseModel): account_id: Optional[str] account_name: Optional[str] service_id: Optional[str] @@ -90,12 +89,18 @@ class Service(BaseModel): hub_id: Optional[str] -class SettingsPayload(BaseModel): +class Logging(BaseModel): + logging_api_key: Optional[str] + log_level: Optional[str] + runner_log_level: Optional[str] + meta: Optional[LogMeta] + + +class SetupResponse(BaseModel): variables: Optional[dict] # delete after stop using version 1 environment_type: Optional[str] logging: Optional[Logging] - service: Optional[Service] class Schedulable(BaseModel): @@ -109,7 +114,7 @@ class Repository(BaseModel): changelog_url: Optional[str] -class ExtensionPayload(BaseModel): +class SetupRequest(BaseModel): # for version 1 'capabilities' renaming to 'event_subscriptions' event_subscriptions: dict variables: Optional[list] @@ -121,24 +126,24 @@ class ExtensionPayload(BaseModel): class Message(BaseModel): version: Literal[1, 2] = 1 message_type: str - data: Union[TaskPayload, ExtensionPayload, SettingsPayload, None] + data: Union[Task, SetupRequest, SetupResponse, None] -def transform_data(message_type, data): +def transform_data_from_v1(message_type, data): if message_type == MessageType.CONFIGURATION: - message_type = MessageType.SETTINGS + message_type = MessageType.SETUP_RESPONSE data.update( variables=data.get('configuration'), - logging=Logging(**data).dict(), - service=Service(**data).dict(), + logging=Logging(**data, meta=LogMeta(**data).dict()).dict(), ) elif message_type == MessageType.TASK: data.update( options=TaskOptions(**data).dict(), input=TaskInput(**data, event_type=data['task_type']).dict(), + output=TaskOutput(**data, error=data['output']).dict(), ) elif message_type == MessageType.CAPABILITIES: - message_type = MessageType.EXTENSION + message_type = MessageType.SETUP_REQUEST data.update( event_subscriptions=data.get('capabilities'), repository=Repository(**data).dict(), @@ -147,36 +152,43 @@ def transform_data(message_type, data): return message_type, data -def transform_data_to_legacy(message_type, data): - if message_type == MessageType.SETTINGS: +def transform_data_to_v1(message_type, data): + if message_type == MessageType.SETUP_RESPONSE: message_type = MessageType.CONFIGURATION - if 'service' in data: - products = data['service'].get('products', []) - data['service']['product_id'] = products[0] if products and len(products) > 0 else None - data['service'].pop('products', None) - + logging = data.get('logging', {}) + log_meta = logging.pop('meta', {}) + if log_meta: + products = log_meta.get('products', []) + log_meta['product_id'] = products[0] if products and len(products) > 0 else None + log_meta.pop('products', None) data.update( configuration=data.get('variables'), - **data.get('logging', {}), - **data.get('service', {}), + **logging, + **log_meta, ) data.pop('logging', None) - data.pop('service', None) data.pop('variables', None) elif message_type == MessageType.TASK: + input = data.pop('input', {}) + input.pop('data', None) + output = data.pop('output', {}) + error = output.pop('error', None) + task_output_data = output.pop('data', None) data.update( - task_type=data['input']['event_type'], - **data.get('input', {}), + task_type=input.get('event_type'), + data=task_output_data, + output=error, + **input, **data.get('options', {}), + **output, ) data.pop('event_type', None) - data.pop('input', None) data.pop('options', None) - elif message_type == MessageType.EXTENSION: + elif message_type == MessageType.SETUP_REQUEST: message_type = MessageType.CAPABILITIES data.update( capabilities=data.get('event_subscriptions'), @@ -195,9 +207,13 @@ def parse_message(payload): data = payload.get('data') if version == 1: - message_type, data = transform_data(message_type, data) + message_type, data = transform_data_from_v1(message_type, data) - if message_type not in [MessageType.TASK, MessageType.EXTENSION, MessageType.SETTINGS]: + if message_type not in ( + MessageType.TASK, + MessageType.SETUP_REQUEST, + MessageType.SETUP_RESPONSE, + ): data = None return Message(version=version, message_type=message_type, data=data) diff --git a/pyproject.toml b/pyproject.toml index 5afe551..1554edc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "connect-eaas-core" -version = "25.0.0" +version = "1.4.0" description = "Connect Eaas Core" authors = ["CloudBlue LLC"] license = "Apache-2.0" diff --git a/tests/connect/eaas/core/test_dataclasses.py b/tests/connect/eaas/core/test_dataclasses.py index abf95fc..346a396 100644 --- a/tests/connect/eaas/core/test_dataclasses.py +++ b/tests/connect/eaas/core/test_dataclasses.py @@ -1,17 +1,19 @@ +import copy + from connect.eaas.core.dataclasses import ( - ExtensionPayload, Logging, + LogMeta, Message, MessageType, parse_message, Repository, Schedulable, - Service, - SettingsPayload, + SetupRequest, + SetupResponse, + Task, TaskInput, TaskOptions, - TaskPayload, - transform_data_to_legacy, + transform_data_to_v1, ) @@ -19,10 +21,6 @@ 'options': { 'task_id': 'task_id', 'task_category': 'task_category', - 'result': 'result', - 'countdown': 10, - 'runtime': 3.2, - 'output': 'output', 'correlation_id': 'correlation_id', 'reply_to': 'reply_to', }, @@ -31,8 +29,15 @@ 'object_id': 'object_id', 'data': {'data': 'value'}, }, + 'output': { + 'result': 'result', + 'countdown': 10, + 'runtime': 3.2, + 'error': 'output', + 'data': {'data': 'value'}, + }, } -TASK_DATA_LEGACY = { +TASK_DATA_V1 = { 'task_id': 'task_id', 'task_category': 'task_category', 'task_type': 'task_type', @@ -46,7 +51,7 @@ 'reply_to': 'reply_to', } -EXTENSION_DATA = { +SETUP_REQUEST_DATA = { 'event_subscriptions': {'test': 'data'}, 'variables': [{'foo': 'value', 'bar': 'value'}], 'schedulables': [{'method': 'method_name', 'name': 'Name', 'description': 'Description'}], @@ -56,7 +61,7 @@ }, 'runner_version': '3', } -EXTENSION_DATA_LEGACY = { +SETUP_REQUEST_DATA_V1 = { 'capabilities': {'test': 'data'}, 'variables': [{'foo': 'value', 'bar': 'value'}], 'schedulables': [{'method': 'method_name', 'name': 'Name', 'description': 'Description'}], @@ -65,23 +70,23 @@ 'runner_version': '3', } -SETTINGS_DATA = { +SETUP_RESPONSE_DATA = { 'variables': {'conf1': 'val1'}, 'environment_type': 'environ-type', 'logging': { 'logging_api_key': 'logging-token', 'log_level': 'log-level', 'runner_log_level': 'runner-log-level', - }, - 'service': { - 'account_id': 'account_id', - 'account_name': 'account_name', - 'service_id': 'service_id', - 'products': None, - 'hub_id': None, + 'meta': { + 'account_id': 'account_id', + 'account_name': 'account_name', + 'service_id': 'service_id', + 'products': None, + 'hub_id': None, + }, }, } -SETTNIGS_DATA_LEGACY = { +SETUP_RESPONSE_DATA_V1 = { 'configuration': {'conf1': 'val1'}, 'logging_api_key': 'logging-token', 'environment_type': 'environ-type', @@ -99,14 +104,14 @@ def test_parse_task_message(): msg_data = { 'version': 2, 'message_type': 'task', - 'data': TASK_DATA, + 'data': copy.deepcopy(TASK_DATA), } message = parse_message(msg_data) assert isinstance(message, Message) assert message.message_type == MessageType.TASK - assert isinstance(message.data, TaskPayload) + assert isinstance(message.data, Task) assert message.dict() == msg_data assert isinstance(message.data.options, TaskOptions) assert isinstance(message.data.input, TaskInput) @@ -115,26 +120,26 @@ def test_parse_task_message(): def test_parse_settings_message(): msg_data = { 'version': 2, - 'message_type': 'settings', - 'data': SETTINGS_DATA, + 'message_type': 'setup_response', + 'data': copy.deepcopy(SETUP_RESPONSE_DATA), } message = parse_message(msg_data) assert isinstance(message, Message) - assert message.message_type == MessageType.SETTINGS - assert isinstance(message.data, SettingsPayload) + assert message.message_type == MessageType.SETUP_RESPONSE + assert isinstance(message.data, SetupResponse) assert message.dict() == msg_data assert isinstance(message.data.logging, Logging) - assert isinstance(message.data.service, Service) + assert isinstance(message.data.logging.meta, LogMeta) def test_parse_extension_message(): msg_data = { 'version': 2, - 'message_type': 'extension', + 'message_type': 'setup_request', 'data': { - **EXTENSION_DATA, + **copy.deepcopy(SETUP_REQUEST_DATA), 'variables': None, 'schedulables': None, 'runner_version': None, @@ -144,8 +149,8 @@ def test_parse_extension_message(): message = parse_message(msg_data) assert isinstance(message, Message) - assert message.message_type == MessageType.EXTENSION - assert isinstance(message.data, ExtensionPayload) + assert message.message_type == MessageType.SETUP_REQUEST + assert isinstance(message.data, SetupRequest) assert message.dict() == msg_data assert isinstance(message.data.repository, Repository) @@ -153,8 +158,8 @@ def test_parse_extension_message(): def test_parse_extension_message_with_vars_and_schedulables(): msg_data = { 'version': 2, - 'message_type': 'extension', - 'data': EXTENSION_DATA, + 'message_type': 'setup_request', + 'data': SETUP_REQUEST_DATA, } message = parse_message(msg_data) @@ -180,7 +185,7 @@ def test_parse_pause_message(): def test_transform_v1_task_data(): msg_data_v1 = { 'message_type': 'task', - 'data': {**TASK_DATA_LEGACY}, + 'data': copy.deepcopy(TASK_DATA_V1), } message = parse_message(msg_data_v1) @@ -188,7 +193,7 @@ def test_transform_v1_task_data(): assert isinstance(message, Message) assert message.version == 1 assert message.message_type == MessageType.TASK - assert isinstance(message.data, TaskPayload) + assert isinstance(message.data, Task) assert message.dict()['data'] == TASK_DATA @@ -196,72 +201,72 @@ def test_transform_v1_task_data(): def test_transform_v1_settings_data(): msg_data_v1 = { 'message_type': 'configuration', - 'data': {**SETTNIGS_DATA_LEGACY}, + 'data': copy.deepcopy(SETUP_RESPONSE_DATA_V1), } message = parse_message(msg_data_v1) assert isinstance(message, Message) assert message.version == 1 - assert message.message_type == MessageType.SETTINGS - assert isinstance(message.data, SettingsPayload) + assert message.message_type == MessageType.SETUP_RESPONSE + assert isinstance(message.data, SetupResponse) - assert message.dict()['data'] == SETTINGS_DATA + assert message.dict()['data'] == SETUP_RESPONSE_DATA def test_transform_v1_extension_data(): msg_data_v1 = { 'message_type': 'capabilities', - 'data': {**EXTENSION_DATA_LEGACY}, + 'data': copy.deepcopy(SETUP_REQUEST_DATA_V1), } message = parse_message(msg_data_v1) assert isinstance(message, Message) assert message.version == 1 - assert message.message_type == MessageType.EXTENSION - assert isinstance(message.data, ExtensionPayload) + assert message.message_type == MessageType.SETUP_REQUEST + assert isinstance(message.data, SetupRequest) - assert message.dict()['data'] == EXTENSION_DATA + assert message.dict()['data'] == SETUP_REQUEST_DATA def test_transform_extension_data_to_legacy(): - message_type, transformed_data = transform_data_to_legacy( - message_type=MessageType.EXTENSION, - data={**EXTENSION_DATA}, + message_type, transformed_data = transform_data_to_v1( + message_type=MessageType.SETUP_REQUEST, + data=copy.deepcopy(SETUP_REQUEST_DATA), ) assert message_type == MessageType.CAPABILITIES - assert transformed_data == EXTENSION_DATA_LEGACY + assert transformed_data == SETUP_REQUEST_DATA_V1 def test_transform_settings_data_to_legacy(): - message_type, transformed_data = transform_data_to_legacy( - message_type=MessageType.SETTINGS, - data={**SETTINGS_DATA}, + message_type, transformed_data = transform_data_to_v1( + message_type=MessageType.SETUP_RESPONSE, + data=copy.deepcopy(SETUP_RESPONSE_DATA), ) assert message_type == MessageType.CONFIGURATION - assert transformed_data == SETTNIGS_DATA_LEGACY + assert transformed_data == SETUP_RESPONSE_DATA_V1 def test_transform_settings_data_to_legacy_with_product(): - new_settings = {**SETTINGS_DATA} - new_settings['service']['products'] = ['PRD-000'] - message_type, transformed_data = transform_data_to_legacy( - message_type=MessageType.SETTINGS, + new_settings = copy.deepcopy(SETUP_RESPONSE_DATA) + new_settings['logging']['meta']['products'] = ['PRD-000'] + message_type, transformed_data = transform_data_to_v1( + message_type=MessageType.SETUP_RESPONSE, data=new_settings, ) - legacy_settings = {**SETTNIGS_DATA_LEGACY} + legacy_settings = copy.deepcopy(SETUP_RESPONSE_DATA_V1) legacy_settings['product_id'] = 'PRD-000' assert message_type == MessageType.CONFIGURATION assert transformed_data == legacy_settings def test_transform_task_data_to_legacy(): - message_type, transformed_data = transform_data_to_legacy( + message_type, transformed_data = transform_data_to_v1( message_type=MessageType.TASK, - data={**TASK_DATA}, + data=copy.deepcopy(TASK_DATA), ) - assert transformed_data == TASK_DATA_LEGACY + assert transformed_data == TASK_DATA_V1