From db428c0858a3e786f5fd8fc3db544f9220b31afa Mon Sep 17 00:00:00 2001 From: Michal Gershenzon Date: Fri, 28 Jul 2017 16:57:33 +0000 Subject: [PATCH] Create and run a workflow within a namespace Add --namespace flag to workflow and execution operations. Also Add Namespace and Workflow namespace to the tables the users gets after some cli calls. Partially-Implements: blueprint create-and-run-workflows-within-a-namespace Change-Id: Ieb7302870520f5491e94a9bf6759082e2aa4a450 --- functionaltests/resources/v2/async.yaml | 8 + .../v2/for_namespaces/lowest_level_wf.yaml | 8 + .../v2/for_namespaces/middle_wf.yaml | 8 + .../v2/for_namespaces/top_level_wf.yaml | 8 + mistralclient/api/v2/executions.py | 7 +- mistralclient/api/v2/workflows.py | 30 ++- .../commands/v2/action_executions.py | 4 + mistralclient/commands/v2/executions.py | 9 + mistralclient/commands/v2/tasks.py | 2 + mistralclient/commands/v2/workflows.py | 33 ++- .../tests/functional/cli/v2/base_v2.py | 22 +- .../tests/functional/cli/v2/cli_tests_v2.py | 244 +++++++++++++++++- .../tests/unit/v2/test_cli_action_execs.py | 8 +- .../tests/unit/v2/test_cli_executions.py | 7 +- mistralclient/tests/unit/v2/test_cli_tasks.py | 3 +- .../tests/unit/v2/test_cli_workflows.py | 21 +- .../tests/unit/v2/test_executions.py | 5 +- mistralclient/tests/unit/v2/test_workflows.py | 2 +- 18 files changed, 396 insertions(+), 33 deletions(-) create mode 100644 functionaltests/resources/v2/async.yaml create mode 100644 functionaltests/resources/v2/for_namespaces/lowest_level_wf.yaml create mode 100644 functionaltests/resources/v2/for_namespaces/middle_wf.yaml create mode 100644 functionaltests/resources/v2/for_namespaces/top_level_wf.yaml diff --git a/functionaltests/resources/v2/async.yaml b/functionaltests/resources/v2/async.yaml new file mode 100644 index 00000000..e0c6f1ce --- /dev/null +++ b/functionaltests/resources/v2/async.yaml @@ -0,0 +1,8 @@ +--- +version: '2.0' + +async_wf: + type: direct + tasks: + async_task: + action: std.async_noop diff --git a/functionaltests/resources/v2/for_namespaces/lowest_level_wf.yaml b/functionaltests/resources/v2/for_namespaces/lowest_level_wf.yaml new file mode 100644 index 00000000..7a159df3 --- /dev/null +++ b/functionaltests/resources/v2/for_namespaces/lowest_level_wf.yaml @@ -0,0 +1,8 @@ +--- +version: '2.0' + +lowest_level_wf: + type: direct + tasks: + hello: + action: std.noop diff --git a/functionaltests/resources/v2/for_namespaces/middle_wf.yaml b/functionaltests/resources/v2/for_namespaces/middle_wf.yaml new file mode 100644 index 00000000..4c2d08d2 --- /dev/null +++ b/functionaltests/resources/v2/for_namespaces/middle_wf.yaml @@ -0,0 +1,8 @@ +--- +version: '2.0' + +middle_wf: + type: direct + tasks: + hello: + workflow: lowest_level_wf diff --git a/functionaltests/resources/v2/for_namespaces/top_level_wf.yaml b/functionaltests/resources/v2/for_namespaces/top_level_wf.yaml new file mode 100644 index 00000000..bd47da9f --- /dev/null +++ b/functionaltests/resources/v2/for_namespaces/top_level_wf.yaml @@ -0,0 +1,8 @@ +--- +version: '2.0' + +top_level_wf: + type: direct + tasks: + hello: + workflow: middle_wf diff --git a/mistralclient/api/v2/executions.py b/mistralclient/api/v2/executions.py index 137a4e03..6d9fc28d 100644 --- a/mistralclient/api/v2/executions.py +++ b/mistralclient/api/v2/executions.py @@ -31,8 +31,8 @@ class Execution(base.Resource): class ExecutionManager(base.ResourceManager): resource_class = Execution - def create(self, workflow_identifier, workflow_input=None, description='', - **params): + def create(self, workflow_identifier, namespace='', workflow_input=None, + description='', **params): self._ensure_not_empty(workflow_identifier=workflow_identifier) data = { @@ -44,6 +44,9 @@ class ExecutionManager(base.ResourceManager): else: data.update({'workflow_name': workflow_identifier}) + if namespace: + data.update({'workflow_namespace': namespace}) + if workflow_input: if isinstance(workflow_input, six.string_types): data.update({'input': workflow_input}) diff --git a/mistralclient/api/v2/workflows.py b/mistralclient/api/v2/workflows.py index e6bbbefb..97950913 100644 --- a/mistralclient/api/v2/workflows.py +++ b/mistralclient/api/v2/workflows.py @@ -29,7 +29,7 @@ class Workflow(base.Resource): class WorkflowManager(base.ResourceManager): resource_class = Workflow - def create(self, definition, scope='private'): + def create(self, definition, namespace='', scope='private'): self._ensure_not_empty(definition=definition) # If the specified definition is actually a file, read in the @@ -37,7 +37,7 @@ class WorkflowManager(base.ResourceManager): definition = utils.get_contents_if_file(definition) resp = self.http_client.post( - '/workflows?scope=%s' % scope, + '/workflows?scope=%s&namespace=%s' % (scope, namespace), definition, headers={'content-type': 'text/plain'} ) @@ -48,7 +48,7 @@ class WorkflowManager(base.ResourceManager): return [self.resource_class(self, resource_data) for resource_data in base.extract_json(resp, 'workflows')] - def update(self, definition, scope='private', id=None): + def update(self, definition, namespace='', scope='private', id=None): self._ensure_not_empty(definition=definition) url_pre = ('/workflows/%s' % id) if id else '/workflows' @@ -58,7 +58,7 @@ class WorkflowManager(base.ResourceManager): definition = utils.get_contents_if_file(definition) resp = self.http_client.put( - '%s?scope=%s' % (url_pre, scope), + '%s?namespace=%s&scope=%s' % (url_pre, namespace, scope), definition, headers={'content-type': 'text/plain'} ) @@ -72,10 +72,13 @@ class WorkflowManager(base.ResourceManager): return [self.resource_class(self, resource_data) for resource_data in base.extract_json(resp, 'workflows')] - def list(self, marker='', limit=None, sort_keys='', sort_dirs='', - **filters): + def list(self, namespace='', marker='', limit=None, sort_keys='', + sort_dirs='', **filters): qparams = {} + if namespace: + qparams['namespace'] = namespace + if marker: qparams['marker'] = marker @@ -99,15 +102,22 @@ class WorkflowManager(base.ResourceManager): response_key='workflows', ) - def get(self, identifier): + def get(self, identifier, namespace=''): self._ensure_not_empty(identifier=identifier) - return self._get('/workflows/%s' % identifier) + return self._get( + '/workflows/%s?namespace=%s' % (identifier, namespace) + ) - def delete(self, identifier): + def delete(self, identifier, namespace=None): self._ensure_not_empty(identifier=identifier) - self._delete('/workflows/%s' % identifier) + path = '/workflows/%s' % identifier + + if namespace: + path = path + '?namespace=%s' % namespace + + self._delete(path) def validate(self, definition): self._ensure_not_empty(definition=definition) diff --git a/mistralclient/commands/v2/action_executions.py b/mistralclient/commands/v2/action_executions.py index ccffccba..195cf9eb 100644 --- a/mistralclient/commands/v2/action_executions.py +++ b/mistralclient/commands/v2/action_executions.py @@ -30,6 +30,7 @@ def format_list(action_ex=None): 'ID', 'Name', 'Workflow name', + 'Workflow namespace', 'Task name', 'Task ID', 'State', @@ -43,6 +44,7 @@ def format_list(action_ex=None): action_ex.id, action_ex.name, action_ex.workflow_name, + action_ex.workflow_namespace, action_ex.task_name if hasattr(action_ex, 'task_name') else None, action_ex.task_execution_id, action_ex.state, @@ -61,6 +63,7 @@ def format(action_ex=None): 'ID', 'Name', 'Workflow name', + 'Workflow namespace', 'Task name', 'Task ID', 'State', @@ -75,6 +78,7 @@ def format(action_ex=None): action_ex.id, action_ex.name, action_ex.workflow_name, + action_ex.workflow_namespace, action_ex.task_name if hasattr(action_ex, 'task_name') else None, action_ex.task_execution_id, action_ex.state, diff --git a/mistralclient/commands/v2/executions.py b/mistralclient/commands/v2/executions.py index e3ad0e0e..ad50daff 100644 --- a/mistralclient/commands/v2/executions.py +++ b/mistralclient/commands/v2/executions.py @@ -38,6 +38,7 @@ def format(execution=None, lister=False): 'ID', 'Workflow ID', 'Workflow name', + 'Workflow namespace', 'Description', 'Task Execution ID', 'State', @@ -55,6 +56,7 @@ def format(execution=None, lister=False): execution.id, execution.workflow_id, execution.workflow_name, + execution.workflow_namespace, execution.description, execution.task_execution_id or '', execution.state, @@ -174,6 +176,12 @@ class Create(command.ShowOne): help='Workflow ID or name. Workflow name will be deprecated since ' 'Mitaka.' ) + parser.add_argument( + '--namespace', + nargs='?', + default='', + help="Workflow namespace." + ) parser.add_argument( 'workflow_input', nargs='?', @@ -209,6 +217,7 @@ class Create(command.ShowOne): execution = mistral_client.executions.create( parsed_args.workflow_identifier, + parsed_args.namespace, wf_input, parsed_args.description, **params diff --git a/mistralclient/commands/v2/tasks.py b/mistralclient/commands/v2/tasks.py index b22d6ced..c25c1013 100644 --- a/mistralclient/commands/v2/tasks.py +++ b/mistralclient/commands/v2/tasks.py @@ -32,6 +32,7 @@ class TaskFormatter(object): ('id', 'ID'), ('name', 'Name'), ('workflow_name', 'Workflow name'), + ('workflow_namespace', 'Workflow namespace'), ('workflow_execution_id', 'Execution ID'), ('state', 'State'), ('state_info', 'State info'), @@ -56,6 +57,7 @@ class TaskFormatter(object): task.id, task.name, task.workflow_name, + task.workflow_namespace, task.workflow_execution_id, task.state, state_info, diff --git a/mistralclient/commands/v2/workflows.py b/mistralclient/commands/v2/workflows.py index 46a24c04..956b8d95 100644 --- a/mistralclient/commands/v2/workflows.py +++ b/mistralclient/commands/v2/workflows.py @@ -30,6 +30,7 @@ def format(workflow=None, lister=False): columns = ( 'ID', 'Name', + 'Namespace', 'Project ID', 'Tags', 'Input', @@ -43,6 +44,7 @@ def format(workflow=None, lister=False): data = ( workflow.id, workflow.name, + workflow.namespace, workflow.project_id, base.wrap(', '.join(tags)) or '', workflow.input if not lister else base.cut(workflow.input), @@ -113,6 +115,12 @@ class Create(base.MistralLister): type=argparse.FileType('r'), help='Workflow definition file.' ) + parser.add_argument( + '--namespace', + nargs='?', + default='', + help="Namespace to create the workflow within.", + ) parser.add_argument( '--public', action='store_true', @@ -135,6 +143,7 @@ class Create(base.MistralLister): return mistral_client.workflows.create( parsed_args.definition.read(), + namespace=parsed_args.namespace, scope=scope ) @@ -151,12 +160,21 @@ class Delete(command.Command): help='Name or ID of workflow(s).' ) + parser.add_argument( + '--namespace', + nargs='?', + default=None, + help="Parent task execution ID associated with workflow " + "execution list.", + ) + return parser def take_action(self, parsed_args): mistral_client = self.app.client_manager.workflow_engine utils.do_action_on_many( - lambda s: mistral_client.workflows.delete(s), + lambda s: mistral_client.workflows.delete(s, + parsed_args.namespace), parsed_args.workflow, "Request to delete workflow %s has been accepted.", "Unable to delete the specified workflow(s)." @@ -174,7 +192,17 @@ class Update(base.MistralLister): type=argparse.FileType('r'), help='Workflow definition' ) + parser.add_argument('--id', help='Workflow ID.') + + parser.add_argument( + '--namespace', + nargs='?', + default='', + help="Parent task execution ID associated with workflow " + "execution list.", + ) + parser.add_argument( '--public', action='store_true', @@ -193,7 +221,8 @@ class Update(base.MistralLister): return mistral_client.workflows.update( parsed_args.definition.read(), scope=scope, - id=parsed_args.id + id=parsed_args.id, + namespace=parsed_args.namespace ) diff --git a/mistralclient/tests/functional/cli/v2/base_v2.py b/mistralclient/tests/functional/cli/v2/base_v2.py index 808082bc..4f0d69ca 100644 --- a/mistralclient/tests/functional/cli/v2/base_v2.py +++ b/mistralclient/tests/functional/cli/v2/base_v2.py @@ -54,6 +54,22 @@ class MistralClientTestBase(base.MistralCLIAuth, base.MistralCLIAltAuth): cls.wf_wrapping_wf = os.path.relpath( 'functionaltests/resources/v2/wf_wrapping_wf_v2.yaml', os.getcwd() ) + cls.top_level_wf = os.path.relpath( + 'functionaltests/resources/v2/for_namespaces/top_level_wf.yaml', + os.getcwd() + ) + cls.middle_wf = os.path.relpath( + 'functionaltests/resources/v2/for_namespaces/middle_wf.yaml', + os.getcwd() + ) + cls.lowest_level_wf = os.path.relpath( + 'functionaltests/resources/v2/for_namespaces/lowest_level_wf.yaml', + os.getcwd() + ) + cls.async_wf_def = os.path.relpath( + 'functionaltests/resources/v2/async.yaml', + os.getcwd() + ) cls.act_def = os.path.relpath( 'functionaltests/resources/v2/action_v2.yaml', os.getcwd() @@ -120,12 +136,16 @@ class MistralClientTestBase(base.MistralCLIAuth, base.MistralCLIAltAuth): return wb - def workflow_create(self, wf_def, admin=True, scope='private'): + def workflow_create(self, wf_def, namespace='', admin=True, + scope='private'): params = '{0}'.format(wf_def) if scope == 'public': params += ' --public' + if namespace: + params += " --namespace " + namespace + wf = self.mistral_cli( admin, 'workflow-create', diff --git a/mistralclient/tests/functional/cli/v2/cli_tests_v2.py b/mistralclient/tests/functional/cli/v2/cli_tests_v2.py index 02add6fd..5c2b2c91 100644 --- a/mistralclient/tests/functional/cli/v2/cli_tests_v2.py +++ b/mistralclient/tests/functional/cli/v2/cli_tests_v2.py @@ -256,6 +256,35 @@ class WorkflowCLITests(base_v2.MistralClientTestBase): for wf in wf_names: self.assertNotIn(wf, [workflow['Name'] for workflow in wfs]) + def test_workflow_within_namespace_create_delete(self): + params = self.wf_def + ' --namespace abcdef' + init_wfs = self.mistral_admin('workflow-create', params=params) + + wf_names = [wf['Name'] for wf in init_wfs] + + self.assertTableStruct(init_wfs, ['Name', 'Created at', 'Updated at']) + + wfs = self.mistral_admin('workflow-list') + self.assertIn(wf_names[0], [workflow['Name'] for workflow in wfs]) + + for wf_name in wf_names: + self.mistral_admin( + 'workflow-delete', + params=wf_name+' --namespace abcdef' + ) + + wfs = self.mistral_admin('workflow-list') + for wf in wf_names: + self.assertNotIn(wf, [workflow['Name'] for workflow in wfs]) + + init_wfs = self.mistral_admin('workflow-create', params=params) + wf_ids = [wf['ID'] for wf in init_wfs] + for wf_id in wf_ids: + self.mistral_admin('workflow-delete', params=wf_id) + + for wf in wf_names: + self.assertNotIn(wf, [workflow['Name'] for workflow in wfs]) + def test_create_wf_with_tags(self): init_wfs = self.workflow_create(self.wf_def) wf_name = init_wfs[1]['Name'] @@ -357,6 +386,96 @@ class WorkflowCLITests(base_v2.MistralClientTestBase): updated_wf_info['Updated at'] ) + def test_workflow_update_within_namespace(self): + namespace = 'abc' + wf = self.workflow_create(self.wf_def, namespace=namespace) + + wf_name = wf[0]['Name'] + wf_id = wf[0]['ID'] + wf_namespace = wf[0]['Namespace'] + created_wf_info = self.get_item_info( + get_from=wf, + get_by='Name', + value=wf_name + ) + + # Update a workflow with definition unchanged. + upd_wf = self.mistral_admin( + 'workflow-update', + params='{0} --namespace {1}'.format(self.wf_def, namespace) + ) + + self.assertTableStruct(upd_wf, ['Name', 'Created at', 'Updated at']) + + updated_wf_info = self.get_item_info( + get_from=upd_wf, + get_by='Name', + value=wf_name + ) + + self.assertEqual(wf_name, upd_wf[0]['Name']) + self.assertEqual(namespace, wf_namespace) + self.assertEqual(wf_namespace, upd_wf[0]['Namespace']) + self.assertEqual( + created_wf_info['Created at'].split(".")[0], + updated_wf_info['Created at'] + ) + self.assertEqual( + created_wf_info['Updated at'], + updated_wf_info['Updated at'] + ) + + # Update a workflow with definition changed. + upd_wf = self.mistral_admin( + 'workflow-update', + params='{0} --namespace {1}'.format( + self.wf_with_delay_def, + namespace + ) + ) + + self.assertTableStruct(upd_wf, ['Name', 'Created at', 'Updated at']) + + updated_wf_info = self.get_item_info( + get_from=upd_wf, + get_by='Name', + value=wf_name + ) + + self.assertEqual(wf_name, upd_wf[0]['Name']) + self.assertEqual( + created_wf_info['Created at'].split(".")[0], + updated_wf_info['Created at'] + ) + self.assertNotEqual( + created_wf_info['Updated at'], + updated_wf_info['Updated at'] + ) + + # Update a workflow with uuid. + upd_wf = self.mistral_admin( + 'workflow-update', + params='{0} --id {1}'.format(self.wf_with_delay_def, wf_id) + ) + + self.assertTableStruct(upd_wf, ['Name', 'Created at', 'Updated at']) + + updated_wf_info = self.get_item_info( + get_from=upd_wf, + get_by='ID', + value=wf_id + ) + + self.assertEqual(wf_name, upd_wf[0]['Name']) + self.assertEqual( + created_wf_info['Created at'].split(".")[0], + updated_wf_info['Created at'] + ) + self.assertNotEqual( + created_wf_info['Updated at'], + updated_wf_info['Updated at'] + ) + def test_workflow_update_truncate_input(self): input_value = "very_long_input_parameter_name_that_should_be_truncated" @@ -476,6 +595,7 @@ class ExecutionCLITests(base_v2.MistralClientTestBase): super(ExecutionCLITests, self).setUp() wfs = self.workflow_create(self.wf_def) + self.async_wf = self.workflow_create(self.async_wf_def)[0] self.direct_wf = wfs[0] self.reverse_wf = wfs[1] @@ -483,7 +603,64 @@ class ExecutionCLITests(base_v2.MistralClientTestBase): self.create_file('input', '{\n "farewell": "Bye"\n}\n') self.create_file('task_name', '{\n "task_name": "goodbye"\n}\n') + def test_execution_by_id_of_workflow_within_namespace(self): + namespace = 'abc' + + wfs = self.workflow_create(self.lowest_level_wf, namespace=namespace) + + wf_def_name = wfs[0]['Name'] + wf_id = wfs[0]['ID'] + + execution = self.execution_create(wf_id) + + self.assertTableStruct(execution, ['Field', 'Value']) + + wf_name = self.get_field_value(execution, 'Workflow name') + wf_namespace = self.get_field_value(execution, 'Workflow namespace') + wf_id = self.get_field_value(execution, 'Workflow ID') + + self.assertEqual(wf_def_name, wf_name) + self.assertEqual(namespace, wf_namespace) + self.assertIsNotNone(wf_id) + + def test_execution_within_namespace_create_delete(self): + namespace = 'abc' + + self.workflow_create(self.lowest_level_wf) + self.workflow_create(self.lowest_level_wf, namespace=namespace) + self.workflow_create(self.middle_wf, namespace=namespace) + self.workflow_create(self.top_level_wf) + wfs = self.workflow_create(self.top_level_wf, namespace=namespace) + + top_wf_name = wfs[0]['Name'] + execution = self.mistral_admin( + 'execution-create', + params='{0} --namespace {1}'.format(top_wf_name, namespace) + ) + exec_id = self.get_field_value(execution, 'ID') + + self.assertTableStruct(execution, ['Field', 'Value']) + + wf_name = self.get_field_value(execution, 'Workflow name') + wf_namespace = self.get_field_value(execution, 'Workflow namespace') + wf_id = self.get_field_value(execution, 'Workflow ID') + created_at = self.get_field_value(execution, 'Created at') + + self.assertEqual(top_wf_name, wf_name) + self.assertEqual(namespace, wf_namespace) + self.assertIsNotNone(wf_id) + self.assertIsNotNone(created_at) + + execs = self.mistral_admin('execution-list') + + self.assertIn(exec_id, [ex['ID'] for ex in execs]) + self.assertIn(wf_name, [ex['Workflow name'] for ex in execs]) + self.assertIn(namespace, [ex['Workflow namespace'] for ex in execs]) + + self.mistral_admin('execution-delete', params=exec_id) + def test_execution_create_delete(self): + execution = self.mistral_admin( 'execution-create', params='{0} -d "execution test"'.format(self.direct_wf['Name']) @@ -522,7 +699,7 @@ class ExecutionCLITests(base_v2.MistralClientTestBase): self.assertTrue(result) def test_execution_update(self): - execution = self.execution_create(self.direct_wf['Name']) + execution = self.execution_create(self.async_wf['Name']) exec_id = self.get_field_value(execution, 'ID') status = self.get_field_value(execution, 'State') @@ -917,9 +1094,41 @@ class TaskCLITests(base_v2.MistralClientTestBase): fetched_task = self.mistral_admin('task-get', params=created_task_id) fetched_task_id = self.get_field_value(fetched_task, 'ID') + fetched_task_wf_namespace = self.get_field_value( + fetched_task, + 'Workflow namespace' + ) task_execution_id = self.get_field_value(fetched_task, 'Execution ID') self.assertEqual(created_task_id, fetched_task_id) + self.assertEqual('', fetched_task_wf_namespace) + self.assertEqual(wf_ex_id, task_execution_id) + + def test_task_get_list_within_namespace(self): + namespace = 'aaa' + self.workflow_create(self.wf_def, namespace=namespace) + wf_ex = self.execution_create( + self.direct_wf['Name'] + ' --namespace ' + namespace + ) + + wf_ex_id = self.get_field_value(wf_ex, 'ID') + + tasks = self.mistral_admin('task-list', params=wf_ex_id) + + created_task_id = tasks[-1]['ID'] + created_wf_namespace = tasks[-1]['Workflow namespace'] + + fetched_task = self.mistral_admin('task-get', params=created_task_id) + fetched_task_id = self.get_field_value(fetched_task, 'ID') + fetched_task_wf_namespace = self.get_field_value( + fetched_task, + 'Workflow namespace' + ) + task_execution_id = self.get_field_value(fetched_task, 'Execution ID') + + self.assertEqual(created_task_id, fetched_task_id) + self.assertEqual(namespace, created_wf_namespace) + self.assertEqual(created_wf_namespace, fetched_task_wf_namespace) self.assertEqual(wf_ex_id, task_execution_id) def test_task_list_with_filter(self): @@ -1377,6 +1586,39 @@ class ActionExecutionCLITests(base_v2.MistralClientTestBase): self.assertEqual(self.direct_wf['Name'], act_ex['Workflow name']) self.assertEqual('SUCCESS', act_ex['State']) + def test_act_execution_get_list_within_namespace(self): + namespace = 'bbb' + self.workflow_create(self.wf_def, namespace=namespace) + wf_ex = self.execution_create( + self.direct_wf['Name'] + ' --namespace ' + namespace + ) + exec_id = self.get_field_value(wf_ex, 'ID') + self.wait_execution_success(exec_id) + task = self.mistral_admin('task-list', params=exec_id)[0] + + act_ex_from_list = self.mistral_admin( + 'action-execution-list', + params=task['ID'] + )[0] + + act_ex = self.mistral_admin( + 'action-execution-get', + params=act_ex_from_list['ID'] + ) + + wf_name = self.get_field_value(act_ex, 'Workflow name') + wf_namespace = self.get_field_value(act_ex, 'Workflow namespace') + status = self.get_field_value(act_ex, 'State') + + self.assertEqual( + act_ex_from_list['ID'], + self.get_field_value(act_ex, 'ID') + ) + self.assertEqual(self.direct_wf['Name'], wf_name) + self.assertEqual('SUCCESS', status) + self.assertEqual(namespace, wf_namespace) + self.assertEqual(namespace, act_ex_from_list['Workflow namespace']) + def test_act_execution_create_delete(self): action_ex = self.mistral_admin( 'run-action', diff --git a/mistralclient/tests/unit/v2/test_cli_action_execs.py b/mistralclient/tests/unit/v2/test_cli_action_execs.py index 49db348d..1434a7a8 100644 --- a/mistralclient/tests/unit/v2/test_cli_action_execs.py +++ b/mistralclient/tests/unit/v2/test_cli_action_execs.py @@ -30,6 +30,7 @@ ACTION_EX_DICT = { 'id': '123', 'name': 'some', 'workflow_name': 'thing', + 'workflow_namespace': '', 'task_name': 'task1', 'task_execution_id': "1-2-3-4", 'state': 'RUNNING', @@ -86,7 +87,7 @@ class TestCLIActionExecutions(base.BaseCommandTest): ) self.assertEqual( - ('123', 'some', 'thing', 'task1', '1-2-3-4', 'RUNNING', + ('123', 'some', 'thing', '', 'task1', '1-2-3-4', 'RUNNING', 'RUNNING somehow.', True, '1', '1'), result[1] ) @@ -142,6 +143,7 @@ class TestCLIActionExecutions(base.BaseCommandTest): action_ex_dict['id'], action_ex_dict['name'], action_ex_dict['workflow_name'], + action_ex_dict['workflow_namespace'], action_ex_dict['task_name'], action_ex_dict['task_execution_id'], action_ex_dict['state'], @@ -178,7 +180,7 @@ class TestCLIActionExecutions(base.BaseCommandTest): result = self.call(action_ex_cmd.List) self.assertEqual( - [('123', 'some', 'thing', 'task1', '1-2-3-4', 'RUNNING', True, + [('123', 'some', 'thing', '', 'task1', '1-2-3-4', 'RUNNING', True, '1', '1')], result[1] ) @@ -189,7 +191,7 @@ class TestCLIActionExecutions(base.BaseCommandTest): result = self.call(action_ex_cmd.Get, app_args=['id']) self.assertEqual( - ('123', 'some', 'thing', 'task1', '1-2-3-4', 'RUNNING', + ('123', 'some', 'thing', '', 'task1', '1-2-3-4', 'RUNNING', 'RUNNING somehow.', True, '1', '1'), result[1] ) diff --git a/mistralclient/tests/unit/v2/test_cli_executions.py b/mistralclient/tests/unit/v2/test_cli_executions.py index f65368dd..dbb53c15 100644 --- a/mistralclient/tests/unit/v2/test_cli_executions.py +++ b/mistralclient/tests/unit/v2/test_cli_executions.py @@ -32,6 +32,7 @@ EXEC = executions.Execution( 'id': '123', 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', 'workflow_name': 'some', + 'workflow_namespace': '', 'description': '', 'state': 'RUNNING', 'state_info': None, @@ -47,6 +48,7 @@ SUB_WF_EXEC = executions.Execution( 'id': '456', 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', 'workflow_name': 'some_sub_wf', + 'workflow_namespace': '', 'description': '', 'state': 'RUNNING', 'state_info': None, @@ -61,6 +63,7 @@ EX_RESULT = ( '123e4567-e89b-12d3-a456-426655440000', 'some', '', + '', '', 'RUNNING', None, @@ -73,6 +76,7 @@ SUB_WF_EX_RESULT = ( '123e4567-e89b-12d3-a456-426655440000', 'some_sub_wf', '', + '', 'abc', 'RUNNING', None, @@ -154,6 +158,7 @@ class TestCLIExecutionsV2(base.BaseCommandTest): 'id': '123', 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', 'workflow_name': 'some', + 'workflow_namespace': '', 'description': '', 'state': state, 'state_info': None, @@ -164,7 +169,7 @@ class TestCLIExecutionsV2(base.BaseCommandTest): ) ex_result = list(EX_RESULT) - ex_result[5] = state + ex_result[6] = state ex_result = tuple(ex_result) result = self.call( diff --git a/mistralclient/tests/unit/v2/test_cli_tasks.py b/mistralclient/tests/unit/v2/test_cli_tasks.py index bb707ae4..0d2e10f5 100644 --- a/mistralclient/tests/unit/v2/test_cli_tasks.py +++ b/mistralclient/tests/unit/v2/test_cli_tasks.py @@ -28,6 +28,7 @@ TASK_DICT = { 'id': '123', 'name': 'some', 'workflow_name': 'thing', + 'workflow_namespace': '', 'workflow_execution_id': '321', 'state': 'RUNNING', 'state_info': None, @@ -48,7 +49,7 @@ TASK_WITH_RESULT = tasks.Task(mock, TASK_WITH_RESULT_DICT) TASK_WITH_PUBLISHED = tasks.Task(mock, TASK_WITH_PUBLISHED_DICT) EXPECTED_TASK_RESULT = ( - '123', 'some', 'thing', '321', 'RUNNING', None, '1', '1' + '123', 'some', 'thing', '', '321', 'RUNNING', None, '1', '1' ) diff --git a/mistralclient/tests/unit/v2/test_cli_workflows.py b/mistralclient/tests/unit/v2/test_cli_workflows.py index 38c5fa55..61bec752 100644 --- a/mistralclient/tests/unit/v2/test_cli_workflows.py +++ b/mistralclient/tests/unit/v2/test_cli_workflows.py @@ -25,6 +25,7 @@ from mistralclient.tests.unit import base WORKFLOW_DICT = { 'id': '1-2-3-4', 'name': 'a', + 'namespace': '', 'project_id': '12345', 'tags': ['a', 'b'], 'input': 'param', @@ -55,7 +56,7 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): result = self.call(workflow_cmd.Create, app_args=['1.txt']) self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], + [('1-2-3-4', 'a', '', '12345', 'a, b', 'param', '1', '1')], result[1] ) @@ -69,7 +70,7 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): ) self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], + [('1-2-3-4', 'a', '', '12345', 'a, b', 'param', '1', '1')], result[1] ) @@ -91,7 +92,7 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): result = self.call(workflow_cmd.Create, app_args=['1.txt']) self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', cmd_base.cut(long_input), + [('1-2-3-4', 'a', '', '12345', 'a, b', cmd_base.cut(long_input), '1', '1')], result[1] ) @@ -103,7 +104,7 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): result = self.call(workflow_cmd.Update, app_args=['1.txt']) self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], + [('1-2-3-4', 'a', '', '12345', 'a, b', 'param', '1', '1')], result[1] ) @@ -117,7 +118,7 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): ) self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], + [('1-2-3-4', 'a', '', '12345', 'a, b', 'param', '1', '1')], result[1] ) @@ -136,7 +137,7 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): ) self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], + [('1-2-3-4', 'a', '', '12345', 'a, b', 'param', '1', '1')], result[1] ) @@ -146,7 +147,7 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): result = self.call(workflow_cmd.List) self.assertEqual( - [('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1')], + [('1-2-3-4', 'a', '', '12345', 'a, b', 'param', '1', '1')], result[1] ) @@ -156,21 +157,21 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): result = self.call(workflow_cmd.Get, app_args=['name']) self.assertEqual( - ('1-2-3-4', 'a', '12345', 'a, b', 'param', '1', '1'), + ('1-2-3-4', 'a', '', '12345', 'a, b', 'param', '1', '1'), result[1] ) def test_delete(self): self.call(workflow_cmd.Delete, app_args=['name']) - self.client.workflows.delete.assert_called_once_with('name') + self.client.workflows.delete.assert_called_once_with('name', None) def test_delete_with_multi_names(self): self.call(workflow_cmd.Delete, app_args=['name1', 'name2']) self.assertEqual(2, self.client.workflows.delete.call_count) self.assertEqual( - [mock.call('name1'), mock.call('name2')], + [mock.call('name1', None), mock.call('name2', None)], self.client.workflows.delete.call_args_list ) diff --git a/mistralclient/tests/unit/v2/test_executions.py b/mistralclient/tests/unit/v2/test_executions.py index 77296e3d..9722fc26 100644 --- a/mistralclient/tests/unit/v2/test_executions.py +++ b/mistralclient/tests/unit/v2/test_executions.py @@ -25,6 +25,7 @@ EXEC = { 'id': "123", 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', 'workflow_name': 'my_wf', + 'workflow_namespace': '', 'description': '', 'state': 'RUNNING', 'input': { @@ -39,6 +40,7 @@ SUB_WF_EXEC = { 'id': "456", 'workflow_id': '123e4567-e89b-12d3-a456-426655440000', 'workflow_name': 'my_sub_wf', + 'workflow_namespace': '', 'task_execution_id': "abc", 'description': '', 'state': 'RUNNING', @@ -68,6 +70,7 @@ class TestExecutionsV2(base.BaseClientV2Test): ex = self.executions.create( EXEC['workflow_name'], + EXEC['workflow_namespace'], EXEC['input'] ) @@ -93,7 +96,7 @@ class TestExecutionsV2(base.BaseClientV2Test): ex = self.executions.create( EXEC['workflow_id'], - EXEC['input'] + workflow_input=EXEC['input'] ) self.assertIsNotNone(ex) diff --git a/mistralclient/tests/unit/v2/test_workflows.py b/mistralclient/tests/unit/v2/test_workflows.py index fb5cac77..bfeb4f0f 100644 --- a/mistralclient/tests/unit/v2/test_workflows.py +++ b/mistralclient/tests/unit/v2/test_workflows.py @@ -106,7 +106,7 @@ class TestWorkflowsV2(base.BaseClientV2Test): last_request = self.requests_mock.last_request - self.assertEqual('scope=private', last_request.query) + self.assertEqual('namespace=&scope=private', last_request.query) self.assertEqual(WF_DEF, last_request.text) self.assertEqual('text/plain', last_request.headers['content-type'])