From ccef0817d56715c307f4bf4a4878ea6cecc27f97 Mon Sep 17 00:00:00 2001 From: Lingxian Kong Date: Fri, 13 Nov 2015 16:50:18 +0800 Subject: [PATCH] Introduce openstackclient plugin Adds the code necessary for mistralclient to work as a plugin for openstackclient. Steps to test: - Make sure Keystone service is installed and Mistral service is registered in Keystone, please refer to Mistral documentation here[1]. The reason we need Keystone is because OpenStackClient always needs it for commands authentication. - Install python-mistralclient. - Install python-openstackclient, it will load Mistral commands via plugin mechanism. - Config environment variables (something like OS_AUTH_URL, etc.). - Run Mistral commands as you want, e.g. `openstack workflow list`. TODO: - update python-openstackclient documentation to let other projects know what objects our mistral project is using, to avoid potential conflicts in future. [1]: http://docs.openstack.org/developer/mistral/guides/configuration_guide.html Implements: blueprint mistral-osc-plugin Change-Id: Ic099aaec88377a76a17700c33fed944e52ec5633 --- mistralclient/api/v2/client.py | 11 ++- .../commands/v2/action_executions.py | 43 ++++------ mistralclient/commands/v2/actions.py | 26 ++++--- mistralclient/commands/v2/base.py | 2 +- mistralclient/commands/v2/cron_triggers.py | 17 ++-- mistralclient/commands/v2/environments.py | 23 +++--- mistralclient/commands/v2/executions.py | 32 ++++---- mistralclient/commands/v2/services.py | 4 +- mistralclient/commands/v2/tasks.py | 21 +++-- mistralclient/commands/v2/workbooks.py | 34 ++++---- mistralclient/commands/v2/workflows.py | 27 ++++--- mistralclient/osc/__init__.py | 0 mistralclient/osc/plugin.py | 66 ++++++++++++++++ mistralclient/shell.py | 10 +++ mistralclient/tests/unit/base.py | 2 +- .../tests/unit/v2/test_cli_action_execs.py | 67 +++++----------- .../tests/unit/v2/test_cli_actions.py | 68 ++++++++-------- .../tests/unit/v2/test_cli_cron_triggers.py | 27 +++---- .../tests/unit/v2/test_cli_environments.py | 32 ++++---- .../tests/unit/v2/test_cli_executions.py | 77 +++++++++--------- .../tests/unit/v2/test_cli_services.py | 5 +- mistralclient/tests/unit/v2/test_cli_tasks.py | 35 ++++----- .../tests/unit/v2/test_cli_workbooks.py | 54 ++++++------- .../tests/unit/v2/test_cli_workflows.py | 78 +++++++++---------- requirements.txt | 1 + setup.cfg | 62 +++++++++++++++ 26 files changed, 461 insertions(+), 363 deletions(-) create mode 100644 mistralclient/osc/__init__.py create mode 100644 mistralclient/osc/plugin.py diff --git a/mistralclient/api/v2/client.py b/mistralclient/api/v2/client.py index 6e92c15f..c9278a01 100644 --- a/mistralclient/api/v2/client.py +++ b/mistralclient/api/v2/client.py @@ -46,10 +46,13 @@ class Client(object): if not mistral_url: mistral_url = "http://localhost:8989/v2" - self.http_client = httpclient.HTTPClient(mistral_url, - auth_token, - project_id, - user_id) + self.http_client = httpclient.HTTPClient( + mistral_url, + auth_token, + project_id, + user_id + ) + # Create all resource managers. self.workbooks = workbooks.WorkbookManager(self) self.executions = executions.ExecutionManager(self) diff --git a/mistralclient/commands/v2/action_executions.py b/mistralclient/commands/v2/action_executions.py index 0e8f6235..78bec171 100644 --- a/mistralclient/commands/v2/action_executions.py +++ b/mistralclient/commands/v2/action_executions.py @@ -20,7 +20,6 @@ import logging from cliff import command from cliff import show -from mistralclient.api.v2 import action_executions from mistralclient.commands.v2 import base from mistralclient import utils @@ -119,9 +118,8 @@ class Create(show.ShowOne): except: action_input = json.load(open(parsed_args.input)) - action_ex = action_executions.ActionExecutionManager( - self.app.client - ).create( + mistral_client = self.app.client_manager.workflow_engine + action_ex = mistral_client.action_executions.create( parsed_args.name, action_input, **params @@ -152,9 +150,10 @@ class List(base.MistralLister): return parser def _get_resources(self, parsed_args): - return action_executions.ActionExecutionManager( - self.app.client - ).list(parsed_args.task_execution_id) + mistral_client = self.app.client_manager.workflow_engine + return mistral_client.action_executions.list( + parsed_args.task_execution_id + ) class Get(show.ShowOne): @@ -169,9 +168,8 @@ class Get(show.ShowOne): return parser def take_action(self, parsed_args): - execution = action_executions.ActionExecutionManager( - self.app.client - ).get(parsed_args.id) + mistral_client = self.app.client_manager.workflow_engine + execution = mistral_client.action_executions.get(parsed_args.id) return format(execution) @@ -205,9 +203,8 @@ class Update(show.ShowOne): except: output = json.load(open(parsed_args.output)) - execution = action_executions.ActionExecutionManager( - self.app.client - ).update( + mistral_client = self.app.client_manager.workflow_engine + execution = mistral_client.action_executions.update( parsed_args.id, parsed_args.state, output @@ -228,11 +225,8 @@ class GetOutput(command.Command): return parser def take_action(self, parsed_args): - output = action_executions.ActionExecutionManager( - self.app.client - ).get( - parsed_args.id - ).output + mistral_client = self.app.client_manager.workflow_engine + output = mistral_client.action_executions.get(parsed_args.id).output try: output = json.loads(output) @@ -256,11 +250,8 @@ class GetInput(command.Command): return parser def take_action(self, parsed_args): - result = action_executions.ActionExecutionManager( - self.app.client - ).get( - parsed_args.id - ).input + mistral_client = self.app.client_manager.workflow_engine + result = mistral_client.action_executions.get(parsed_args.id).input try: result = json.loads(result) @@ -286,12 +277,10 @@ class Delete(command.Command): return parser def take_action(self, parsed_args): - action_ex_mgr = action_executions.ActionExecutionManager( - self.app.client - ) + mistral_client = self.app.client_manager.workflow_engine utils.do_action_on_many( - lambda s: action_ex_mgr.delete(s), + lambda s: mistral_client.action_executions.delete(s), parsed_args.id, "Request to delete action execution %s has been accepted.", "Unable to delete the specified action execution(s)." diff --git a/mistralclient/commands/v2/actions.py b/mistralclient/commands/v2/actions.py index cfc5cb80..af68cf6b 100644 --- a/mistralclient/commands/v2/actions.py +++ b/mistralclient/commands/v2/actions.py @@ -20,7 +20,6 @@ import logging from cliff import command from cliff import show -from mistralclient.api.v2 import actions from mistralclient.commands.v2 import base from mistralclient import utils @@ -74,7 +73,9 @@ class List(base.MistralLister): return format_list def _get_resources(self, parsed_args): - return actions.ActionManager(self.app.client).list() + mistral_client = self.app.client_manager.workflow_engine + + return mistral_client.actions.list() class Get(show.ShowOne): @@ -88,8 +89,8 @@ class Get(show.ShowOne): return parser def take_action(self, parsed_args): - action = actions.ActionManager(self.app.client).get( - parsed_args.name) + mistral_client = self.app.client_manager.workflow_engine + action = mistral_client.actions.get(parsed_args.name) return format(action) @@ -123,7 +124,9 @@ class Create(base.MistralLister): def _get_resources(self, parsed_args): scope = 'public' if parsed_args.public else 'private' - return actions.ActionManager(self.app.client).create( + mistral_client = self.app.client_manager.workflow_engine + + return mistral_client.actions.create( parsed_args.definition.read(), scope=scope ) @@ -140,9 +143,10 @@ class Delete(command.Command): return parser def take_action(self, parsed_args): - action_mgr = actions.ActionManager(self.app.client) + mistral_client = self.app.client_manager.workflow_engine + utils.do_action_on_many( - lambda s: action_mgr.delete(s), + lambda s: mistral_client.actions.delete(s), parsed_args.name, "Request to delete action %s has been accepted.", "Unable to delete the specified action(s)." @@ -174,7 +178,9 @@ class Update(base.MistralLister): def _get_resources(self, parsed_args): scope = 'public' if parsed_args.public else 'private' - return actions.ActionManager(self.app.client).update( + mistral_client = self.app.client_manager.workflow_engine + + return mistral_client.actions.update( parsed_args.definition.read(), scope=scope ) @@ -191,7 +197,7 @@ class GetDefinition(command.Command): return parser def take_action(self, parsed_args): - definition = actions.ActionManager(self.app.client).get( - parsed_args.name).definition + mistral_client = self.app.client_manager.workflow_engine + definition = mistral_client.actions.get(parsed_args.name).definition self.app.stdout.write(definition or "\n") diff --git a/mistralclient/commands/v2/base.py b/mistralclient/commands/v2/base.py index 3e8239fc..a17f7002 100644 --- a/mistralclient/commands/v2/base.py +++ b/mistralclient/commands/v2/base.py @@ -15,10 +15,10 @@ # import abc +import textwrap from cliff import lister import six -import textwrap @six.add_metaclass(abc.ABCMeta) diff --git a/mistralclient/commands/v2/cron_triggers.py b/mistralclient/commands/v2/cron_triggers.py index 6537923d..1a999fa3 100644 --- a/mistralclient/commands/v2/cron_triggers.py +++ b/mistralclient/commands/v2/cron_triggers.py @@ -20,7 +20,6 @@ import logging from cliff import command from cliff import show -from mistralclient.api.v2 import cron_triggers from mistralclient.commands.v2 import base from mistralclient import utils @@ -79,7 +78,8 @@ class List(base.MistralLister): return format_list def _get_resources(self, parsed_args): - return cron_triggers.CronTriggerManager(self.app.client).list() + mistral_client = self.app.client_manager.workflow_engine + return mistral_client.cron_triggers.list() class Get(show.ShowOne): @@ -93,9 +93,9 @@ class Get(show.ShowOne): return parser def take_action(self, parsed_args): - mgr = cron_triggers.CronTriggerManager(self.app.client) + mistral_client = self.app.client_manager.workflow_engine - return format(mgr.get(parsed_args.name)) + return format(mistral_client.cron_triggers.get(parsed_args.name)) class Create(show.ShowOne): @@ -150,12 +150,12 @@ class Create(show.ShowOne): return {} def take_action(self, parsed_args): - mgr = cron_triggers.CronTriggerManager(self.app.client) + mistral_client = self.app.client_manager.workflow_engine wf_input = self._get_file_content_or_dict(parsed_args.workflow_input) wf_params = self._get_file_content_or_dict(parsed_args.params) - trigger = mgr.create( + trigger = mistral_client.cron_triggers.create( parsed_args.name, parsed_args.workflow_name, wf_input, @@ -179,9 +179,10 @@ class Delete(command.Command): return parser def take_action(self, parsed_args): - mgr = cron_triggers.CronTriggerManager(self.app.client) + mistral_client = self.app.client_manager.workflow_engine + utils.do_action_on_many( - lambda s: mgr.delete(s), + lambda s: mistral_client.cron_triggers.delete(s), parsed_args.name, "Request to delete cron trigger %s has been accepted.", "Unable to delete the specified cron trigger(s)." diff --git a/mistralclient/commands/v2/environments.py b/mistralclient/commands/v2/environments.py index 241aae9a..9c0b473d 100644 --- a/mistralclient/commands/v2/environments.py +++ b/mistralclient/commands/v2/environments.py @@ -20,7 +20,6 @@ from cliff import command from cliff import show import yaml -from mistralclient.api.v2 import environments from mistralclient.commands.v2 import base from mistralclient import utils @@ -108,7 +107,8 @@ class List(base.MistralLister): return format_list def _get_resources(self, parsed_args): - return environments.EnvironmentManager(self.app.client).list() + mistral_client = self.app.client_manager.workflow_engine + return mistral_client.environments.list() class Get(show.ShowOne): @@ -125,8 +125,8 @@ class Get(show.ShowOne): return parser def take_action(self, parsed_args): - environment = environments.EnvironmentManager(self.app.client).get( - parsed_args.name) + mistral_client = self.app.client_manager.workflow_engine + environment = mistral_client.environments.get(parsed_args.name) return format(environment) @@ -147,8 +147,9 @@ class Create(show.ShowOne): def take_action(self, parsed_args): data = load_file_content(parsed_args.file) - manager = environments.EnvironmentManager(self.app.client) - environment = manager.create(**data) + + mistral_client = self.app.client_manager.workflow_engine + environment = mistral_client.environments.create(**data) return format(environment) @@ -164,9 +165,10 @@ class Delete(command.Command): return parser def take_action(self, parsed_args): - env_mgr = environments.EnvironmentManager(self.app.client) + mistral_client = self.app.client_manager.workflow_engine + utils.do_action_on_many( - lambda s: env_mgr.delete(s), + lambda s: mistral_client.environments.delete(s), parsed_args.name, "Request to delete environment %s has been accepted.", "Unable to delete the specified environment(s)." @@ -189,7 +191,8 @@ class Update(show.ShowOne): def take_action(self, parsed_args): data = load_file_content(parsed_args.file) - manager = environments.EnvironmentManager(self.app.client) - environment = manager.update(**data) + + mistral_client = self.app.client_manager.workflow_engine + environment = mistral_client.environments.update(**data) return format(environment) diff --git a/mistralclient/commands/v2/executions.py b/mistralclient/commands/v2/executions.py index 8a10de10..10f45aec 100644 --- a/mistralclient/commands/v2/executions.py +++ b/mistralclient/commands/v2/executions.py @@ -20,7 +20,6 @@ import logging from cliff import command from cliff import show -from mistralclient.api.v2 import executions from mistralclient.commands.v2 import base from mistralclient import utils @@ -101,7 +100,8 @@ class List(base.MistralLister): return parser def _get_resources(self, parsed_args): - return executions.ExecutionManager(self.app.client).list( + mistral_client = self.app.client_manager.workflow_engine + return mistral_client.executions.list( marker=parsed_args.marker, limit=parsed_args.limit, sort_keys=parsed_args.sort_keys, @@ -120,8 +120,8 @@ class Get(show.ShowOne): return parser def take_action(self, parsed_args): - execution = executions.ExecutionManager(self.app.client).get( - parsed_args.id) + mistral_client = self.app.client_manager.workflow_engine + execution = mistral_client.executions.get(parsed_args.id) return format(execution) @@ -173,11 +173,14 @@ class Create(show.ShowOne): else: params = {} - execution = executions.ExecutionManager(self.app.client).create( + mistral_client = self.app.client_manager.workflow_engine + + execution = mistral_client.executions.create( parsed_args.workflow_name, wf_input, parsed_args.description, - **params) + **params + ) return format(execution) @@ -197,9 +200,10 @@ class Delete(command.Command): return parser def take_action(self, parsed_args): - exe_mgr = executions.ExecutionManager(self.app.client) + mistral_client = self.app.client_manager.workflow_engine + utils.do_action_on_many( - lambda s: exe_mgr.delete(s), + lambda s: mistral_client.executions.delete(s), parsed_args.id, "Request to delete execution %s has been accepted.", "Unable to delete the specified execution(s)." @@ -235,7 +239,9 @@ class Update(show.ShowOne): return parser def take_action(self, parsed_args): - execution = executions.ExecutionManager(self.app.client).update( + mistral_client = self.app.client_manager.workflow_engine + + execution = mistral_client.executions.update( parsed_args.id, parsed_args.state, parsed_args.description) @@ -254,8 +260,8 @@ class GetInput(command.Command): return parser def take_action(self, parsed_args): - ex_input = executions.ExecutionManager(self.app.client).get( - parsed_args.id).input + mistral_client = self.app.client_manager.workflow_engine + ex_input = mistral_client.executions.get(parsed_args.id).input try: ex_input = json.loads(ex_input) @@ -277,8 +283,8 @@ class GetOutput(command.Command): return parser def take_action(self, parsed_args): - output = executions.ExecutionManager(self.app.client).get( - parsed_args.id).output + mistral_client = self.app.client_manager.workflow_engine + output = mistral_client.executions.get(parsed_args.id).output try: output = json.loads(output) diff --git a/mistralclient/commands/v2/services.py b/mistralclient/commands/v2/services.py index 48eb8fe4..1ee26b75 100644 --- a/mistralclient/commands/v2/services.py +++ b/mistralclient/commands/v2/services.py @@ -14,7 +14,6 @@ import logging -from mistralclient.api.v2 import services from mistralclient.commands.v2 import base @@ -39,4 +38,5 @@ class List(base.MistralLister): return format_list def _get_resources(self, parsed_args): - return services.ServiceManager(self.app.client).list() + mistral_client = self.app.client_manager.workflow_engine + return mistral_client.services.list() diff --git a/mistralclient/commands/v2/tasks.py b/mistralclient/commands/v2/tasks.py index c73ca3e0..712b07ca 100644 --- a/mistralclient/commands/v2/tasks.py +++ b/mistralclient/commands/v2/tasks.py @@ -21,7 +21,6 @@ import logging from cliff import command from cliff import show -from mistralclient.api.v2 import tasks from mistralclient.commands.v2 import base LOG = logging.getLogger(__name__) @@ -75,9 +74,8 @@ class List(base.MistralLister): return format_list def _get_resources(self, parsed_args): - return tasks.TaskManager(self.app.client).list( - parsed_args.workflow_execution - ) + mistral_client = self.app.client_manager.workflow_engine + return mistral_client.tasks.list(parsed_args.workflow_execution) class Get(show.ShowOne): @@ -91,8 +89,8 @@ class Get(show.ShowOne): return parser def take_action(self, parsed_args): - execution = tasks.TaskManager(self.app.client).get( - parsed_args.id) + mistral_client = self.app.client_manager.workflow_engine + execution = mistral_client.tasks.get(parsed_args.id) return format(execution) @@ -109,8 +107,8 @@ class GetResult(command.Command): return parser def take_action(self, parsed_args): - result = tasks.TaskManager(self.app.client).get( - parsed_args.id).result + mistral_client = self.app.client_manager.workflow_engine + result = mistral_client.tasks.get(parsed_args.id).result try: result = json.loads(result) @@ -133,8 +131,8 @@ class GetPublished(command.Command): return parser def take_action(self, parsed_args): - result = tasks.TaskManager(self.app.client).get( - parsed_args.id).published + mistral_client = self.app.client_manager.workflow_engine + result = mistral_client.tasks.get(parsed_args.id).published try: result = json.loads(result) @@ -168,7 +166,8 @@ class Rerun(show.ShowOne): return parser def take_action(self, parsed_args): - execution = tasks.TaskManager(self.app.client).rerun( + mistral_client = self.app.client_manager.workflow_engine + execution = mistral_client.tasks.rerun( parsed_args.id, reset=(not parsed_args.resume) ) diff --git a/mistralclient/commands/v2/workbooks.py b/mistralclient/commands/v2/workbooks.py index 109ae6f0..315173e8 100644 --- a/mistralclient/commands/v2/workbooks.py +++ b/mistralclient/commands/v2/workbooks.py @@ -19,7 +19,6 @@ import logging from cliff import command from cliff import show -from mistralclient.api.v2 import workbooks from mistralclient.commands.v2 import base from mistralclient import utils @@ -60,7 +59,8 @@ class List(base.MistralLister): return format def _get_resources(self, parsed_args): - return workbooks.WorkbookManager(self.app.client).list() + mistral_client = self.app.client_manager.workflow_engine + return mistral_client.workbooks.list() class Get(show.ShowOne): @@ -77,8 +77,8 @@ class Get(show.ShowOne): return parser def take_action(self, parsed_args): - workbook = workbooks.WorkbookManager(self.app.client).get( - parsed_args.name) + mistral_client = self.app.client_manager.workflow_engine + workbook = mistral_client.workbooks.get(parsed_args.name) return format(workbook) @@ -98,8 +98,10 @@ class Create(show.ShowOne): return parser def take_action(self, parsed_args): - workbook = workbooks.WorkbookManager(self.app.client).create( - parsed_args.definition.read()) + mistral_client = self.app.client_manager.workflow_engine + workbook = mistral_client.workbooks.create( + parsed_args.definition.read() + ) return format(workbook) @@ -115,9 +117,9 @@ class Delete(command.Command): return parser def take_action(self, parsed_args): - wb_mgr = workbooks.WorkbookManager(self.app.client) + mistral_client = self.app.client_manager.workflow_engine utils.do_action_on_many( - lambda s: wb_mgr.delete(s), + lambda s: mistral_client.workbooks.delete(s), parsed_args.name, "Request to delete workbook %s has been accepted.", "Unable to delete the specified workbook(s)." @@ -139,8 +141,10 @@ class Update(show.ShowOne): return parser def take_action(self, parsed_args): - workbook = workbooks.WorkbookManager(self.app.client).update( - parsed_args.definition.read()) + mistral_client = self.app.client_manager.workflow_engine + workbook = mistral_client.workbooks.update( + parsed_args.definition.read() + ) return format(workbook) @@ -156,8 +160,8 @@ class GetDefinition(command.Command): return parser def take_action(self, parsed_args): - definition = workbooks.WorkbookManager(self.app.client).get( - parsed_args.name).definition + mistral_client = self.app.client_manager.workflow_engine + definition = mistral_client.workbooks.get(parsed_args.name).definition self.app.stdout.write(definition or "\n") @@ -191,7 +195,9 @@ class Validate(show.ShowOne): return parser def take_action(self, parsed_args): - result = workbooks.WorkbookManager(self.app.client).validate( - parsed_args.definition.read()) + mistral_client = self.app.client_manager.workflow_engine + result = mistral_client.workbooks.validate( + parsed_args.definition.read() + ) return self._format(result) diff --git a/mistralclient/commands/v2/workflows.py b/mistralclient/commands/v2/workflows.py index 86cedc20..11d498d7 100644 --- a/mistralclient/commands/v2/workflows.py +++ b/mistralclient/commands/v2/workflows.py @@ -19,7 +19,6 @@ import logging from cliff import command from cliff import show -from mistralclient.api.v2 import workflows from mistralclient.commands.v2 import base from mistralclient import utils @@ -67,7 +66,8 @@ class List(base.MistralLister): return format_list def _get_resources(self, parsed_args): - return workflows.WorkflowManager(self.app.client).list() + mistral_client = self.app.client_manager.workflow_engine + return mistral_client.workflows.list() class Get(show.ShowOne): @@ -81,7 +81,8 @@ class Get(show.ShowOne): return parser def take_action(self, parsed_args): - wf = workflows.WorkflowManager(self.app.client).get(parsed_args.name) + mistral_client = self.app.client_manager.workflow_engine + wf = mistral_client.workflows.get(parsed_args.name) return format(wf) @@ -115,8 +116,9 @@ class Create(base.MistralLister): def _get_resources(self, parsed_args): scope = 'public' if parsed_args.public else 'private' + mistral_client = self.app.client_manager.workflow_engine - return workflows.WorkflowManager(self.app.client).create( + return mistral_client.workflows.create( parsed_args.definition.read(), scope=scope ) @@ -133,9 +135,9 @@ class Delete(command.Command): return parser def take_action(self, parsed_args): - wf_mgr = workflows.WorkflowManager(self.app.client) + mistral_client = self.app.client_manager.workflow_engine utils.do_action_on_many( - lambda s: wf_mgr.delete(s), + lambda s: mistral_client.workflows.delete(s), parsed_args.name, "Request to delete workflow %s has been accepted.", "Unable to delete the specified workflow(s)." @@ -166,8 +168,9 @@ class Update(base.MistralLister): def _get_resources(self, parsed_args): scope = 'public' if parsed_args.public else 'private' + mistral_client = self.app.client_manager.workflow_engine - return workflows.WorkflowManager(self.app.client).update( + return mistral_client.workflows.update( parsed_args.definition.read(), scope=scope ) @@ -184,8 +187,8 @@ class GetDefinition(command.Command): return parser def take_action(self, parsed_args): - definition = workflows.WorkflowManager(self.app.client).get( - parsed_args.name).definition + mistral_client = self.app.client_manager.workflow_engine + definition = mistral_client.workflows.get(parsed_args.name).definition self.app.stdout.write(definition or "\n") @@ -219,7 +222,9 @@ class Validate(show.ShowOne): return parser def take_action(self, parsed_args): - result = workflows.WorkflowManager(self.app.client).validate( - parsed_args.definition.read()) + mistral_client = self.app.client_manager.workflow_engine + result = mistral_client.workflows.validate( + parsed_args.definition.read() + ) return self._format(result) diff --git a/mistralclient/osc/__init__.py b/mistralclient/osc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/mistralclient/osc/plugin.py b/mistralclient/osc/plugin.py new file mode 100644 index 00000000..b230427d --- /dev/null +++ b/mistralclient/osc/plugin.py @@ -0,0 +1,66 @@ +# +# 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 openstackclient.common import utils + +LOG = logging.getLogger(__name__) + +DEFAULT_WORKFLOW_API_VERSION = '2' +API_VERSION_OPTION = 'os_workflow_api_version' +API_NAME = 'workflow_engine' +API_VERSIONS = { + '2': 'mistralclient.api.v2.client.Client', +} + + +def make_client(instance): + """Returns a workflow_engine service client.""" + version = instance._api_version[API_NAME] + workflow_client = utils.get_client_class( + API_NAME, + version, + API_VERSIONS) + + LOG.debug('Instantiating workflow engine client: %s', workflow_client) + + if not instance._url: + instance._url = instance.get_endpoint_for_service_type( + 'workflowv2', + interface='publicURL' + ) + + client = workflow_client( + mistral_url=instance._url, + auth_token=instance.auth_ref.auth_token, + project_id=instance.auth_ref.project_id, + user_id=instance.auth_ref.user_id, + ) + + return client + + +def build_option_parser(parser): + """Hook to add global options.""" + parser.add_argument( + '--os-workflow-api-version', + metavar='', + default=utils.env( + 'OS_WORKFLOW_API_VERSION', + default=DEFAULT_WORKFLOW_API_VERSION), + help='Workflow API version, default=' + + DEFAULT_WORKFLOW_API_VERSION + + ' (Env: OS_WORKFLOW_API_VERSION)') + + return parser diff --git a/mistralclient/shell.py b/mistralclient/shell.py index b114d7ff..be5ae360 100644 --- a/mistralclient/shell.py +++ b/mistralclient/shell.py @@ -295,6 +295,16 @@ class MistralShell(app.App): auth_token=self.options.token, cacert=self.options.cacert) + # Adding client_manager variable to make mistral client work with + # unified openstack client. + ClientManager = type( + 'ClientManager', + (object,), + dict(workflow_engine=self.client) + ) + + self.client_manager = ClientManager() + def _set_shell_commands(self, cmds_dict): for k, v in cmds_dict.items(): self.command_manager.add_command(k, v) diff --git a/mistralclient/tests/unit/base.py b/mistralclient/tests/unit/base.py index 5989becb..c89d9f6c 100644 --- a/mistralclient/tests/unit/base.py +++ b/mistralclient/tests/unit/base.py @@ -70,7 +70,7 @@ class BaseClientTest(unittest2.TestCase): class BaseCommandTest(unittest2.TestCase): def setUp(self): self.app = mock.Mock() - self.app.client = mock.Mock() + self.client = self.app.client_manager.workflow_engine def call(self, command, app_args=[], prog_name=''): cmd = command(self.app, app_args) diff --git a/mistralclient/tests/unit/v2/test_cli_action_execs.py b/mistralclient/tests/unit/v2/test_cli_action_execs.py index 4e115dd2..c1acdbe0 100644 --- a/mistralclient/tests/unit/v2/test_cli_action_execs.py +++ b/mistralclient/tests/unit/v2/test_cli_action_execs.py @@ -50,11 +50,9 @@ ACTION_EX_WITH_INPUT = action_ex.ActionExecution( class TestCLIActionExecutions(base.BaseCommandTest): - @mock.patch( - 'mistralclient.api.v2.action_executions.ActionExecutionManager.create' - ) - def test_create(self, mock): - mock.return_value = ACTION_EX_WITH_OUTPUT + def test_create(self): + (self.client.action_executions.create. + return_value) = ACTION_EX_WITH_OUTPUT self.call( action_ex_cmd.Create, @@ -66,11 +64,9 @@ class TestCLIActionExecutions(base.BaseCommandTest): json.loads(self.app.stdout.write.call_args[0][0]) ) - @mock.patch( - 'mistralclient.api.v2.action_executions.ActionExecutionManager.create' - ) - def test_create_save_result(self, mock): - mock.return_value = ACTION_EX_WITH_OUTPUT + def test_create_save_result(self): + (self.client.action_executions.create. + return_value) = ACTION_EX_WITH_OUTPUT result = self.call( action_ex_cmd.Create, @@ -85,11 +81,8 @@ class TestCLIActionExecutions(base.BaseCommandTest): result[1] ) - @mock.patch( - 'mistralclient.api.v2.action_executions.ActionExecutionManager.update' - ) - def test_update(self, mock): - mock.return_value = ACTION_EX + def test_update(self): + self.client.action_executions.update.return_value = ACTION_EX result = self.call(action_ex_cmd.Update, app_args=['id', '--state', 'ERROR']) @@ -99,11 +92,8 @@ class TestCLIActionExecutions(base.BaseCommandTest): 'RUNNING somehow.', True), result[1] ) - @mock.patch( - 'mistralclient.api.v2.action_executions.ActionExecutionManager.list' - ) - def test_list(self, mock): - mock.return_value = (ACTION_EX,) + def test_list(self): + self.client.action_executions.list.return_value = (ACTION_EX,) result = self.call(action_ex_cmd.List) @@ -113,11 +103,8 @@ class TestCLIActionExecutions(base.BaseCommandTest): result[1] ) - @mock.patch( - 'mistralclient.api.v2.action_executions.ActionExecutionManager.get' - ) - def test_get(self, mock): - mock.return_value = ACTION_EX + def test_get(self): + self.client.action_executions.get.return_value = ACTION_EX result = self.call(action_ex_cmd.Get, app_args=['id']) @@ -126,11 +113,8 @@ class TestCLIActionExecutions(base.BaseCommandTest): 'RUNNING somehow.', True), result[1] ) - @mock.patch( - 'mistralclient.api.v2.action_executions.ActionExecutionManager.get' - ) - def test_get_output(self, mock): - mock.return_value = ACTION_EX_WITH_OUTPUT + def test_get_output(self): + self.client.action_executions.get.return_value = ACTION_EX_WITH_OUTPUT self.call(action_ex_cmd.GetOutput, app_args=['id']) @@ -139,11 +123,8 @@ class TestCLIActionExecutions(base.BaseCommandTest): json.loads(self.app.stdout.write.call_args[0][0]) ) - @mock.patch( - 'mistralclient.api.v2.action_executions.ActionExecutionManager.get' - ) - def test_get_input(self, mock): - mock.return_value = ACTION_EX_WITH_INPUT + def test_get_input(self): + self.client.action_executions.get.return_value = ACTION_EX_WITH_INPUT self.call(action_ex_cmd.GetInput, app_args=['id']) @@ -152,22 +133,16 @@ class TestCLIActionExecutions(base.BaseCommandTest): json.loads(self.app.stdout.write.call_args[0][0]) ) - @mock.patch( - 'mistralclient.api.v2.action_executions.ActionExecutionManager.delete' - ) - def test_delete(self, del_mock): + def test_delete(self): self.call(action_ex_cmd.Delete, app_args=['id']) - del_mock.assert_called_once_with('id') + self.client.action_executions.delete.assert_called_once_with('id') - @mock.patch( - 'mistralclient.api.v2.action_executions.ActionExecutionManager.delete' - ) - def test_delete_with_multi_names(self, del_mock): + def test_delete_with_multi_names(self): self.call(action_ex_cmd.Delete, app_args=['id1', 'id2']) - self.assertEqual(2, del_mock.call_count) + self.assertEqual(2, self.client.action_executions.delete.call_count) self.assertEqual( [mock.call('id1'), mock.call('id2')], - del_mock.call_args_list + self.client.action_executions.delete.call_args_list ) diff --git a/mistralclient/tests/unit/v2/test_cli_actions.py b/mistralclient/tests/unit/v2/test_cli_actions.py index 55affb43..c5b88d3b 100644 --- a/mistralclient/tests/unit/v2/test_cli_actions.py +++ b/mistralclient/tests/unit/v2/test_cli_actions.py @@ -51,9 +51,8 @@ ACTION_WITH_DEF = actions.Action(mock, ACTION_WITH_DEF_DICT) class TestCLIActionsV2(base.BaseCommandTest): @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.actions.ActionManager.create') - def test_create(self, mock, mock_open): - mock.return_value = (ACTION,) + def test_create(self, mock_open): + self.client.actions.create.return_value = (ACTION,) result = self.call(action_cmd.Create, app_args=['1.txt']) @@ -63,9 +62,8 @@ class TestCLIActionsV2(base.BaseCommandTest): ) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.actions.ActionManager.create') - def test_create_public(self, mock, mock_open): - mock.return_value = (ACTION,) + def test_create_public(self, mock_open): + self.client.actions.create.return_value = (ACTION,) result = self.call( action_cmd.Create, @@ -77,18 +75,23 @@ class TestCLIActionsV2(base.BaseCommandTest): result[1] ) - self.assertEqual('public', mock.call_args[1]['scope']) + self.assertEqual( + 'public', + self.client.actions.create.call_args[1]['scope'] + ) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.actions.ActionManager.create') - def test_create_long_input(self, mock, mock_open): + def test_create_long_input(self, mock_open): action_long_input_dict = ACTION_DICT.copy() long_input = ', '.join( ['var%s' % i for i in six.moves.xrange(10)] ) action_long_input_dict['input'] = long_input - workflow_long_input = actions.Action(mock, action_long_input_dict) - mock.return_value = (workflow_long_input,) + workflow_long_input = actions.Action( + mock.Mock(), + action_long_input_dict + ) + self.client.actions.create.return_value = (workflow_long_input,) result = self.call(action_cmd.Create, app_args=['1.txt']) @@ -99,9 +102,8 @@ class TestCLIActionsV2(base.BaseCommandTest): ) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.actions.ActionManager.update') - def test_update(self, mock, mock_open): - mock.return_value = (ACTION,) + def test_update(self, mock_open): + self.client.actions.update.return_value = (ACTION,) result = self.call(action_cmd.Update, app_args=['my_action.yaml']) @@ -111,9 +113,8 @@ class TestCLIActionsV2(base.BaseCommandTest): ) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.actions.ActionManager.update') - def test_update_public(self, mock, mock_open): - mock.return_value = (ACTION,) + def test_update_public(self, mock_open): + self.client.actions.update.return_value = (ACTION,) result = self.call( action_cmd.Update, @@ -125,11 +126,13 @@ class TestCLIActionsV2(base.BaseCommandTest): result[1] ) - self.assertEqual('public', mock.call_args[1]['scope']) + self.assertEqual( + 'public', + self.client.actions.update.call_args[1]['scope'] + ) - @mock.patch('mistralclient.api.v2.actions.ActionManager.list') - def test_list(self, mock): - mock.return_value = (ACTION,) + def test_list(self): + self.client.actions.list.return_value = (ACTION,) result = self.call(action_cmd.List) @@ -138,9 +141,8 @@ class TestCLIActionsV2(base.BaseCommandTest): result[1] ) - @mock.patch('mistralclient.api.v2.actions.ActionManager.get') - def test_get(self, mock): - mock.return_value = ACTION + def test_get(self): + self.client.actions.get.return_value = ACTION result = self.call(action_cmd.Get, app_args=['name']) @@ -149,26 +151,22 @@ class TestCLIActionsV2(base.BaseCommandTest): result[1] ) - @mock.patch('mistralclient.api.v2.actions.ActionManager.delete') - def test_delete(self, del_mock): + def test_delete(self): self.call(action_cmd.Delete, app_args=['name']) - del_mock.assert_called_once_with('name') + self.client.actions.delete.assert_called_once_with('name') - @mock.patch('mistralclient.api.v2.actions.ActionManager.delete') - def test_delete_with_multi_names(self, del_mock): + def test_delete_with_multi_names(self): self.call(action_cmd.Delete, app_args=['name1', 'name2']) - self.assertEqual(2, del_mock.call_count) + self.assertEqual(2, self.client.actions.delete.call_count) self.assertEqual( [mock.call('name1'), mock.call('name2')], - del_mock.call_args_list + self.client.actions.delete.call_args_list ) - @mock.patch('mistralclient.api.v2.actions.' - 'ActionManager.get') - def test_get_definition(self, mock): - mock.return_value = ACTION_WITH_DEF + def test_get_definition(self): + self.client.actions.get.return_value = ACTION_WITH_DEF self.call(action_cmd.GetDefinition, app_args=['name']) diff --git a/mistralclient/tests/unit/v2/test_cli_cron_triggers.py b/mistralclient/tests/unit/v2/test_cli_cron_triggers.py index 20e86fdd..fcfc9039 100644 --- a/mistralclient/tests/unit/v2/test_cli_cron_triggers.py +++ b/mistralclient/tests/unit/v2/test_cli_cron_triggers.py @@ -38,9 +38,8 @@ TRIGGER = cron_triggers.CronTrigger(mock, TRIGGER_DICT) class TestCLITriggersV2(base.BaseCommandTest): @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.cron_triggers.CronTriggerManager.create') - def test_create(self, mock, mock_open): - mock.return_value = TRIGGER + def test_create(self, mock_open): + self.client.cron_triggers.create.return_value = TRIGGER mock_open.return_value = mock.MagicMock(spec=open) result = self.call( @@ -58,9 +57,8 @@ class TestCLITriggersV2(base.BaseCommandTest): result[1] ) - @mock.patch('mistralclient.api.v2.cron_triggers.CronTriggerManager.list') - def test_list(self, mock): - mock.return_value = (TRIGGER,) + def test_list(self): + self.client.cron_triggers.list.return_value = (TRIGGER,) result = self.call(cron_triggers_cmd.List) @@ -72,9 +70,8 @@ class TestCLITriggersV2(base.BaseCommandTest): result[1] ) - @mock.patch('mistralclient.api.v2.cron_triggers.CronTriggerManager.get') - def test_get(self, mock): - mock.return_value = TRIGGER + def test_get(self): + self.client.cron_triggers.get.return_value = TRIGGER result = self.call(cron_triggers_cmd.Get, app_args=['name']) @@ -86,18 +83,16 @@ class TestCLITriggersV2(base.BaseCommandTest): result[1] ) - @mock.patch('mistralclient.api.v2.cron_triggers.CronTriggerManager.delete') - def test_delete(self, del_mock): + def test_delete(self): self.call(cron_triggers_cmd.Delete, app_args=['name']) - del_mock.assert_called_once_with('name') + self.client.cron_triggers.delete.assert_called_once_with('name') - @mock.patch('mistralclient.api.v2.cron_triggers.CronTriggerManager.delete') - def test_delete_with_multi_names(self, del_mock): + def test_delete_with_multi_names(self): self.call(cron_triggers_cmd.Delete, app_args=['name1', 'name2']) - self.assertEqual(2, del_mock.call_count) + self.assertEqual(2, self.client.cron_triggers.delete.call_count) self.assertEqual( [mock.call('name1'), mock.call('name2')], - del_mock.call_args_list + self.client.cron_triggers.delete.call_args_list ) diff --git a/mistralclient/tests/unit/v2/test_cli_environments.py b/mistralclient/tests/unit/v2/test_cli_environments.py index c7aff9d2..16a8dab5 100644 --- a/mistralclient/tests/unit/v2/test_cli_environments.py +++ b/mistralclient/tests/unit/v2/test_cli_environments.py @@ -51,9 +51,8 @@ EXPECTED_RESULT = (ENVIRONMENT_DICT['name'], class TestCLIEnvironmentsV2(base.BaseCommandTest): - @mock.patch('mistralclient.api.v2.environments.EnvironmentManager.create') - def _test_create(self, content, mock): - mock.return_value = ENVIRONMENT + def _test_create(self, content): + self.client.environments.create.return_value = ENVIRONMENT with tempfile.NamedTemporaryFile() as f: f.write(content.encode('utf-8')) @@ -69,9 +68,8 @@ class TestCLIEnvironmentsV2(base.BaseCommandTest): yml = yaml.dump(ENVIRONMENT_DICT, default_flow_style=False) self._test_create(yml) - @mock.patch('mistralclient.api.v2.environments.EnvironmentManager.update') - def _test_update(self, content, mock): - mock.return_value = ENVIRONMENT + def _test_update(self, content): + self.client.environments.update.return_value = ENVIRONMENT with tempfile.NamedTemporaryFile() as f: f.write(content.encode('utf-8')) @@ -93,9 +91,8 @@ class TestCLIEnvironmentsV2(base.BaseCommandTest): yml = yaml.dump(env, default_flow_style=False) self._test_update(yml) - @mock.patch('mistralclient.api.v2.environments.EnvironmentManager.list') - def test_list(self, mock): - mock.return_value = (ENVIRONMENT,) + def test_list(self): + self.client.environments.list.return_value = (ENVIRONMENT,) expected = (ENVIRONMENT_DICT['name'], ENVIRONMENT_DICT['description'], ENVIRONMENT_DICT['scope'], @@ -106,26 +103,23 @@ class TestCLIEnvironmentsV2(base.BaseCommandTest): self.assertListEqual([expected], result[1]) - @mock.patch('mistralclient.api.v2.environments.EnvironmentManager.get') - def test_get(self, mock): - mock.return_value = ENVIRONMENT + def test_get(self): + self.client.environments.get.return_value = ENVIRONMENT result = self.call(environment_cmd.Get, app_args=['name']) self.assertEqual(EXPECTED_RESULT, result[1]) - @mock.patch('mistralclient.api.v2.environments.EnvironmentManager.delete') - def test_delete(self, del_mock): + def test_delete(self): self.call(environment_cmd.Delete, app_args=['name']) - del_mock.assert_called_once_with('name') + self.client.environments.delete.assert_called_once_with('name') - @mock.patch('mistralclient.api.v2.environments.EnvironmentManager.delete') - def test_delete_with_multi_names(self, del_mock): + def test_delete_with_multi_names(self): self.call(environment_cmd.Delete, app_args=['name1', 'name2']) - self.assertEqual(2, del_mock.call_count) + self.assertEqual(2, self.client.environments.delete.call_count) self.assertEqual( [mock.call('name1'), mock.call('name2')], - del_mock.call_args_list + self.client.environments.delete.call_args_list ) diff --git a/mistralclient/tests/unit/v2/test_cli_executions.py b/mistralclient/tests/unit/v2/test_cli_executions.py index 183660b0..2e81855e 100644 --- a/mistralclient/tests/unit/v2/test_cli_executions.py +++ b/mistralclient/tests/unit/v2/test_cli_executions.py @@ -33,9 +33,8 @@ EXECUTION = executions.Execution(mock, { class TestCLIExecutionsV2(base.BaseCommandTest): - @mock.patch('mistralclient.api.v2.executions.ExecutionManager.create') - def test_create_wf_input_string(self, mock): - mock.return_value = EXECUTION + def test_create_wf_input_string(self): + self.client.executions.create.return_value = EXECUTION result = self.call(execution_cmd.Create, app_args=['id', '{ "context": true }']) @@ -43,9 +42,8 @@ class TestCLIExecutionsV2(base.BaseCommandTest): self.assertEqual(('123', 'some', '', 'RUNNING', None, '1', '1'), result[1]) - @mock.patch('mistralclient.api.v2.executions.ExecutionManager.create') - def test_create_wf_input_file(self, mock): - mock.return_value = EXECUTION + def test_create_wf_input_file(self): + self.client.executions.create.return_value = EXECUTION path = pkg.resource_filename('mistralclient', 'tests/unit/resources/ctx.json') result = self.call(execution_cmd.Create, @@ -54,9 +52,8 @@ class TestCLIExecutionsV2(base.BaseCommandTest): self.assertEqual(('123', 'some', '', 'RUNNING', None, '1', '1'), result[1]) - @mock.patch('mistralclient.api.v2.executions.ExecutionManager.create') - def test_create_with_description(self, mock): - mock.return_value = EXECUTION + def test_create_with_description(self): + self.client.executions.create.return_value = EXECUTION result = self.call(execution_cmd.Create, app_args=['id', '{ "context": true }', '-d', '']) @@ -64,9 +61,8 @@ class TestCLIExecutionsV2(base.BaseCommandTest): self.assertEqual(('123', 'some', '', 'RUNNING', None, '1', '1'), result[1]) - @mock.patch('mistralclient.api.v2.executions.ExecutionManager.update') - def test_update(self, mock): - mock.return_value = EXECUTION + def test_update(self): + self.client.executions.update.return_value = EXECUTION result = self.call(execution_cmd.Update, app_args=['id', '-s', 'SUCCESS']) @@ -74,53 +70,60 @@ class TestCLIExecutionsV2(base.BaseCommandTest): self.assertEqual(('123', 'some', '', 'RUNNING', None, '1', '1'), result[1]) - @mock.patch('mistralclient.api.v2.executions.ExecutionManager.list') - def test_list(self, mock): - mock.return_value = (EXECUTION,) + def test_list(self): + self.client.executions.list.return_value = (EXECUTION,) result = self.call(execution_cmd.List) self.assertEqual([('123', 'some', '', 'RUNNING', None, '1', '1')], result[1]) - @mock.patch('mistralclient.api.v2.executions.ExecutionManager.list') - def test_list_with_pagination(self, mock): + def test_list_with_pagination(self): + self.client.executions.list.return_value = (EXECUTION,) self.call(execution_cmd.List) - mock.assert_called_once_with(limit=None, marker='', - sort_dirs='asc', - sort_keys='created_at') + self.client.executions.list.assert_called_once_with( + limit=None, + marker='', + sort_dirs='asc', + sort_keys='created_at' + ) - self.call(execution_cmd.List, app_args=['--limit', '5', - '--sort_dirs', 'id, Workflow', - '--sort_keys', 'desc', - '--marker', 'abc']) + self.call( + execution_cmd.List, + app_args=[ + '--limit', '5', + '--sort_dirs', 'id, Workflow', + '--sort_keys', 'desc', + '--marker', 'abc' + ] + ) - mock.assert_called_with(limit=5, marker='abc', - sort_dirs='id, Workflow', - sort_keys='desc') + self.client.executions.list.assert_called_with( + limit=5, + marker='abc', + sort_dirs='id, Workflow', + sort_keys='desc' + ) - @mock.patch('mistralclient.api.v2.executions.ExecutionManager.get') - def test_get(self, mock): - mock.return_value = EXECUTION + def test_get(self): + self.client.executions.get.return_value = EXECUTION result = self.call(execution_cmd.Get, app_args=['id']) self.assertEqual(('123', 'some', '', 'RUNNING', None, '1', '1'), result[1]) - @mock.patch('mistralclient.api.v2.executions.ExecutionManager.delete') - def test_delete(self, del_mock): + def test_delete(self): self.call(execution_cmd.Delete, app_args=['id']) - del_mock.assert_called_once_with('id') + self.client.executions.delete.assert_called_once_with('id') - @mock.patch('mistralclient.api.v2.executions.ExecutionManager.delete') - def test_delete_with_multi_names(self, del_mock): + def test_delete_with_multi_names(self): self.call(execution_cmd.Delete, app_args=['id1', 'id2']) - self.assertEqual(2, del_mock.call_count) + self.assertEqual(2, self.client.executions.delete.call_count) self.assertEqual( [mock.call('id1'), mock.call('id2')], - del_mock.call_args_list + self.client.executions.delete.call_args_list ) diff --git a/mistralclient/tests/unit/v2/test_cli_services.py b/mistralclient/tests/unit/v2/test_cli_services.py index 1e3c4ad3..79228c0c 100644 --- a/mistralclient/tests/unit/v2/test_cli_services.py +++ b/mistralclient/tests/unit/v2/test_cli_services.py @@ -28,9 +28,8 @@ SERVICE = services.Service(mock, SERVICE_DICT) class TestCLIServicesV2(base.BaseCommandTest): - @mock.patch('mistralclient.api.v2.services.ServiceManager.list') - def test_list(self, mock): - mock.return_value = (SERVICE,) + def test_list(self): + self.client.services.list.return_value = (SERVICE,) expected = (SERVICE_DICT['name'], SERVICE_DICT['type'],) result = self.call(service_cmd.List) diff --git a/mistralclient/tests/unit/v2/test_cli_tasks.py b/mistralclient/tests/unit/v2/test_cli_tasks.py index 880d2bda..6b76f5f7 100644 --- a/mistralclient/tests/unit/v2/test_cli_tasks.py +++ b/mistralclient/tests/unit/v2/test_cli_tasks.py @@ -47,33 +47,29 @@ EXPECTED_TASK_RESULT = ('123', 'some', 'thing', '321', 'RUNNING', None) class TestCLITasksV2(base.BaseCommandTest): - @mock.patch('mistralclient.api.v2.tasks.TaskManager.list') - def test_list(self, mock): - mock.return_value = (TASK,) + def test_list(self): + self.client.tasks.list.return_value = (TASK,) result = self.call(task_cmd.List) self.assertEqual([EXPECTED_TASK_RESULT], result[1]) - @mock.patch('mistralclient.api.v2.tasks.TaskManager.list') - def test_list_with_workflow_execution(self, mock): - mock.return_value = (TASK,) + def test_list_with_workflow_execution(self): + self.client.tasks.list.return_value = (TASK,) result = self.call(task_cmd.List, app_args=['workflow_execution']) self.assertEqual([EXPECTED_TASK_RESULT], result[1]) - @mock.patch('mistralclient.api.v2.tasks.TaskManager.get') - def test_get(self, mock): - mock.return_value = TASK + def test_get(self): + self.client.tasks.get.return_value = TASK result = self.call(task_cmd.Get, app_args=['id']) self.assertEqual(EXPECTED_TASK_RESULT, result[1]) - @mock.patch('mistralclient.api.v2.tasks.TaskManager.get') - def test_get_result(self, mock): - mock.return_value = TASK_WITH_RESULT + def test_get_result(self): + self.client.tasks.get.return_value = TASK_WITH_RESULT self.call(task_cmd.GetResult, app_args=['id']) @@ -82,9 +78,8 @@ class TestCLITasksV2(base.BaseCommandTest): json.loads(self.app.stdout.write.call_args[0][0]) ) - @mock.patch('mistralclient.api.v2.tasks.TaskManager.get') - def test_get_published(self, mock): - mock.return_value = TASK_WITH_PUBLISHED + def test_get_published(self): + self.client.tasks.get.return_value = TASK_WITH_PUBLISHED self.call(task_cmd.GetPublished, app_args=['id']) @@ -93,17 +88,15 @@ class TestCLITasksV2(base.BaseCommandTest): json.loads(self.app.stdout.write.call_args[0][0]) ) - @mock.patch('mistralclient.api.v2.tasks.TaskManager.rerun') - def test_rerun(self, mock): - mock.return_value = TASK + def test_rerun(self): + self.client.tasks.rerun.return_value = TASK result = self.call(task_cmd.Rerun, app_args=['id']) self.assertEqual(EXPECTED_TASK_RESULT, result[1]) - @mock.patch('mistralclient.api.v2.tasks.TaskManager.rerun') - def test_rerun_no_reset(self, mock): - mock.return_value = TASK + def test_rerun_no_reset(self): + self.client.tasks.rerun.return_value = TASK result = self.call(task_cmd.Rerun, app_args=['id', '--resume']) diff --git a/mistralclient/tests/unit/v2/test_cli_workbooks.py b/mistralclient/tests/unit/v2/test_cli_workbooks.py index ec4db8c8..f2e5e43d 100644 --- a/mistralclient/tests/unit/v2/test_cli_workbooks.py +++ b/mistralclient/tests/unit/v2/test_cli_workbooks.py @@ -49,80 +49,70 @@ WORKBOOK_WITH_DEF = workbooks.Workbook(mock, WB_WITH_DEF_DICT) class TestCLIWorkbooksV2(base.BaseCommandTest): @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.create') - def test_create(self, mock, mock_open): - mock.return_value = WORKBOOK - mock_open.return_value = mock.MagicMock(spec=open) + def test_create(self, mock_open): + self.client.workbooks.create.return_value = WORKBOOK result = self.call(workbook_cmd.Create, app_args=['wb.yaml']) self.assertEqual(('a', 'a, b', '1', '1'), result[1]) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.update') - def test_update(self, mock, mock_open): - mock.return_value = WORKBOOK - mock_open.return_value = mock.MagicMock(spec=open) + def test_update(self, mock_open): + self.client.workbooks.update.return_value = WORKBOOK result = self.call(workbook_cmd.Update, app_args=['definition']) self.assertEqual(('a', 'a, b', '1', '1'), result[1]) - @mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.list') - def test_list(self, mock): - mock.return_value = (WORKBOOK,) + def test_list(self): + self.client.workbooks.list.return_value = (WORKBOOK,) result = self.call(workbook_cmd.List) self.assertEqual([('a', 'a, b', '1', '1')], result[1]) - @mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.get') - def test_get(self, mock): - mock.return_value = WORKBOOK + def test_get(self): + self.client.workbooks.get.return_value = WORKBOOK result = self.call(workbook_cmd.Get, app_args=['name']) self.assertEqual(('a', 'a, b', '1', '1'), result[1]) - @mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.delete') - def test_delete(self, del_mock): + def test_delete(self): self.call(workbook_cmd.Delete, app_args=['name']) - del_mock.assert_called_once_with('name') + self.client.workbooks.delete.assert_called_once_with('name') - @mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.delete') - def test_delete_with_multi_names(self, del_mock): + def test_delete_with_multi_names(self): self.call(workbook_cmd.Delete, app_args=['name1', 'name2']) - self.assertEqual(2, del_mock.call_count) + self.assertEqual(2, self.client.workbooks.delete.call_count) self.assertEqual( [mock.call('name1'), mock.call('name2')], - del_mock.call_args_list + self.client.workbooks.delete.call_args_list ) - @mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.get') - def test_get_definition(self, mock): - mock.return_value = WORKBOOK_WITH_DEF + def test_get_definition(self): + self.client.workbooks.get.return_value = WORKBOOK_WITH_DEF self.call(workbook_cmd.GetDefinition, app_args=['name']) self.app.stdout.write.assert_called_with(WB_DEF) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.validate') - def test_validate(self, mock, mock_open): - mock.return_value = {'valid': True} - mock_open.return_value = mock.MagicMock(spec=open) + def test_validate(self, mock_open): + self.client.workbooks.validate.return_value = {'valid': True} result = self.call(workbook_cmd.Validate, app_args=['wb.yaml']) self.assertEqual((True, None), result[1]) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workbooks.WorkbookManager.validate') - def test_validate_failed(self, mock, mock_open): - mock.return_value = {'valid': False, 'error': 'Invalid DSL...'} - mock_open.return_value = mock.MagicMock(spec=open) + def test_validate_failed(self, mock_open): + self.client.workbooks.validate.return_value = { + 'valid': False, + 'error': 'Invalid DSL...' + } result = self.call(workbook_cmd.Validate, app_args=['wb.yaml']) diff --git a/mistralclient/tests/unit/v2/test_cli_workflows.py b/mistralclient/tests/unit/v2/test_cli_workflows.py index cee9939f..28d5d4ec 100644 --- a/mistralclient/tests/unit/v2/test_cli_workflows.py +++ b/mistralclient/tests/unit/v2/test_cli_workflows.py @@ -47,18 +47,16 @@ WORKFLOW_WITH_DEF = workflows.Workflow(mock, WF_WITH_DEF_DICT) class TestCLIWorkflowsV2(base.BaseCommandTest): @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.create') - def test_create(self, mock, mock_open): - mock.return_value = (WORKFLOW,) + def test_create(self, mock_open): + self.client.workflows.create.return_value = (WORKFLOW,) result = self.call(workflow_cmd.Create, app_args=['1.txt']) self.assertEqual([('a', 'a, b', 'param', '1', '1')], result[1]) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.create') - def test_create_public(self, mock, mock_open): - mock.return_value = (WORKFLOW,) + def test_create_public(self, mock_open): + self.client.workflows.create.return_value = (WORKFLOW,) result = self.call( workflow_cmd.Create, @@ -67,18 +65,20 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): self.assertEqual([('a', 'a, b', 'param', '1', '1')], result[1]) - self.assertEqual('public', mock.call_args[1]['scope']) + self.assertEqual( + 'public', + self.client.workflows.create.call_args[1]['scope'] + ) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.create') - def test_create_long_input(self, mock, mock_open): + def test_create_long_input(self, mock_open): wf_long_input_dict = WORKFLOW_DICT.copy() long_input = ', '.join( ['var%s' % i for i in six.moves.xrange(10)] ) wf_long_input_dict['input'] = long_input workflow_long_input = workflows.Workflow(mock, wf_long_input_dict) - mock.return_value = (workflow_long_input,) + self.client.workflows.create.return_value = (workflow_long_input,) result = self.call(workflow_cmd.Create, app_args=['1.txt']) @@ -88,18 +88,16 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): ) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.update') - def test_update(self, mock, mock_open): - mock.return_value = (WORKFLOW,) + def test_update(self, mock_open): + self.client.workflows.update.return_value = (WORKFLOW,) result = self.call(workflow_cmd.Update, app_args=['1.txt']) self.assertEqual([('a', 'a, b', 'param', '1', '1')], result[1]) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.update') - def test_update_public(self, mock, mock_open): - mock.return_value = (WORKFLOW,) + def test_update_public(self, mock_open): + self.client.workflows.update.return_value = (WORKFLOW,) result = self.call( workflow_cmd.Update, @@ -108,64 +106,60 @@ class TestCLIWorkflowsV2(base.BaseCommandTest): self.assertEqual([('a', 'a, b', 'param', '1', '1')], result[1]) - self.assertEqual('public', mock.call_args[1]['scope']) + self.assertEqual( + 'public', + self.client.workflows.update.call_args[1]['scope'] + ) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.list') - def test_list(self, mock): - mock.return_value = (WORKFLOW,) + def test_list(self): + self.client.workflows.list.return_value = (WORKFLOW,) result = self.call(workflow_cmd.List) self.assertEqual([('a', 'a, b', 'param', '1', '1')], result[1]) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.get') - def test_get(self, mock): - mock.return_value = WORKFLOW + def test_get(self): + self.client.workflows.get.return_value = WORKFLOW result = self.call(workflow_cmd.Get, app_args=['name']) self.assertEqual(('a', 'a, b', 'param', '1', '1'), result[1]) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.delete') - def test_delete(self, del_mock): + def test_delete(self): self.call(workflow_cmd.Delete, app_args=['name']) - del_mock.assert_called_once_with('name') + self.client.workflows.delete.assert_called_once_with('name') - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.delete') - def test_delete_with_multi_names(self, del_mock): + def test_delete_with_multi_names(self): self.call(workflow_cmd.Delete, app_args=['name1', 'name2']) - self.assertEqual(2, del_mock.call_count) + self.assertEqual(2, self.client.workflows.delete.call_count) self.assertEqual( [mock.call('name1'), mock.call('name2')], - del_mock.call_args_list + self.client.workflows.delete.call_args_list ) - @mock.patch('mistralclient.api.v2.workflows.' - 'WorkflowManager.get') - def test_get_definition(self, mock): - mock.return_value = WORKFLOW_WITH_DEF + def test_get_definition(self): + self.client.workflows.get.return_value = WORKFLOW_WITH_DEF self.call(workflow_cmd.GetDefinition, app_args=['name']) self.app.stdout.write.assert_called_with(WF_DEF) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.validate') - def test_validate(self, mock, mock_open): - mock.return_value = {'valid': True} - mock_open.return_value = mock.MagicMock(spec=open) + def test_validate(self, mock_open): + self.client.workflows.validate.return_value = {'valid': True} result = self.call(workflow_cmd.Validate, app_args=['wf.yaml']) self.assertEqual((True, None), result[1]) @mock.patch('argparse.open', create=True) - @mock.patch('mistralclient.api.v2.workflows.WorkflowManager.validate') - def test_validate_failed(self, mock, mock_open): - mock.return_value = {'valid': False, 'error': 'Invalid DSL...'} - mock_open.return_value = mock.MagicMock(spec=open) + def test_validate_failed(self, mock_open): + self.client.workflows.validate.return_value = { + 'valid': False, + 'error': 'Invalid DSL...' + } result = self.call(workflow_cmd.Validate, app_args=['wf.yaml']) diff --git a/requirements.txt b/requirements.txt index 83c652c6..1f5f489b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,5 +4,6 @@ cliff>=1.14.0 # Apache-2.0 pbr>=1.6 python-keystoneclient!=1.8.0,>=1.6.0 +python-openstackclient>=1.5.0 PyYAML>=3.1.0 requests!=2.8.0,>=2.5.2 diff --git a/setup.cfg b/setup.cfg index 5b502199..bcc5b4b3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,6 +26,68 @@ packages = console_scripts = mistral = mistralclient.shell:main +openstack.cli.extension = + workflow_engine = mistralclient.osc.plugin + +openstack.workflow_engine.v2 = + workbook_list = mistralclient.commands.v2.workbooks:List + workbook_show = mistralclient.commands.v2.workbooks:Get + workbook_create = mistralclient.commands.v2.workbooks:Create + workbook_delete = mistralclient.commands.v2.workbooks:Delete + workbook_update = mistralclient.commands.v2.workbooks:Update + workbook_show_definition = mistralclient.commands.v2.workbooks:GetDefinition + workbook_validate = mistralclient.commands.v2.workbooks:Validate + + workflow_list = mistralclient.commands.v2.workflows:List + workflow_show = mistralclient.commands.v2.workflows:Get + workflow_create = mistralclient.commands.v2.workflows:Create + workflow_delete = mistralclient.commands.v2.workflows:Delete + workflow_update = mistralclient.commands.v2.workflows:Update + workflow_show_definition = mistralclient.commands.v2.workflows:GetDefinition + workflow_validate = mistralclient.commands.v2.workflows:Validate + + workflow_env_create = mistralclient.commands.v2.environments:Create + workflow_env_delete = mistralclient.commands.v2.environments:Delete + workflow_env_update = mistralclient.commands.v2.environments:Update + workflow_env_list = mistralclient.commands.v2.environments:List + workflow_env_show = mistralclient.commands.v2.environments:Get + + action_execution_run = mistralclient.commands.v2.action_executions:Create + action_execution_list = mistralclient.commands.v2.action_executions:List + action_execution_show = mistralclient.commands.v2.action_executions:Get + action_execution_show_input = mistralclient.commands.v2.action_executions:GetInput + action_execution_show_output = mistralclient.commands.v2.action_executions:GetOutput + action_execution_update = mistralclient.commands.v2.action_executions:Update + action_execution_delete = mistralclient.commands.v2.action_executions:Delete + + workflow_execution_create = mistralclient.commands.v2.executions:Create + workflow_execution_delete = mistralclient.commands.v2.executions:Delete + workflow_execution_update = mistralclient.commands.v2.executions:Update + workflow_execution_list = mistralclient.commands.v2.executions:List + workflow_execution_show = mistralclient.commands.v2.executions:Get + workflow_execution_show_input = mistralclient.commands.v2.executions:GetInput + workflow_execution_show_output = mistralclient.commands.v2.executions:GetOutput + + task_execution_list = mistralclient.commands.v2.tasks:List + task_execution_show = mistralclient.commands.v2.tasks:Get + task_execution_show_published = mistralclient.commands.v2.tasks:GetPublished + task_execution_show_result = mistralclient.commands.v2.tasks:GetResult + task_execution_rerun = mistralclient.commands.v2.tasks:Rerun + + action_definition_list = mistralclient.commands.v2.actions:List + action_definition_show = mistralclient.commands.v2.actions:Get + action_definition_create = mistralclient.commands.v2.actions:Create + action_definition_delete = mistralclient.commands.v2.actions:Delete + action_definition_update = mistralclient.commands.v2.actions:Update + action_definition_show_definition = mistralclient.commands.v2.actions:GetDefinition + + cron_trigger_list = mistralclient.commands.v2.cron_triggers:List + cron_trigger_show = mistralclient.commands.v2.cron_triggers:Get + cron_trigger_create = mistralclient.commands.v2.cron_triggers:Create + cron_trigger_delete = mistralclient.commands.v2.cron_triggers:Delete + + workflow_engine_service_list = mistralclient.commands.v2.services:List + [nosetests] cover-package = mistralclient