Support workflow id for execution CLI
Partially implements: blueprint support-id-in-workflow-operation Depends-On: I1b83eb75aa89484235e2150ab4f111da4ea766b7 Change-Id: I4b9b07e20a3ef734f62a545011c1a510effe747f
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from oslo_utils import uuidutils
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from mistralclient.api import base
|
from mistralclient.api import base
|
||||||
@@ -30,15 +31,19 @@ class Execution(base.Resource):
|
|||||||
class ExecutionManager(base.ResourceManager):
|
class ExecutionManager(base.ResourceManager):
|
||||||
resource_class = Execution
|
resource_class = Execution
|
||||||
|
|
||||||
def create(self, workflow_name, workflow_input=None, description='',
|
def create(self, workflow_identifier, workflow_input=None, description='',
|
||||||
**params):
|
**params):
|
||||||
self._ensure_not_empty(workflow_name=workflow_name)
|
self._ensure_not_empty(workflow_identifier=workflow_identifier)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'workflow_name': workflow_name,
|
|
||||||
'description': description
|
'description': description
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if uuidutils.is_uuid_like(workflow_identifier):
|
||||||
|
data.update({'workflow_id': workflow_identifier})
|
||||||
|
else:
|
||||||
|
data.update({'workflow_name': workflow_identifier})
|
||||||
|
|
||||||
if workflow_input:
|
if workflow_input:
|
||||||
if isinstance(workflow_input, six.string_types):
|
if isinstance(workflow_input, six.string_types):
|
||||||
data.update({'input': workflow_input})
|
data.update({'input': workflow_input})
|
||||||
@@ -50,15 +55,6 @@ class ExecutionManager(base.ResourceManager):
|
|||||||
|
|
||||||
return self._create('/executions', data)
|
return self._create('/executions', data)
|
||||||
|
|
||||||
def create_reverse_workflow(self, workflow_name, workflow_input,
|
|
||||||
task_name, **params):
|
|
||||||
params.update({'task_name': task_name})
|
|
||||||
|
|
||||||
return self.create(workflow_name, workflow_input, **params)
|
|
||||||
|
|
||||||
def create_direct_workflow(self, workflow_name, workflow_input, **params):
|
|
||||||
return self.create(workflow_name, workflow_input, **params)
|
|
||||||
|
|
||||||
def update(self, id, state, description=None, env=None):
|
def update(self, id, state, description=None, env=None):
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ def format_list(execution=None):
|
|||||||
def format(execution=None, lister=False):
|
def format(execution=None, lister=False):
|
||||||
columns = (
|
columns = (
|
||||||
'ID',
|
'ID',
|
||||||
'Workflow',
|
'Workflow ID',
|
||||||
|
'Workflow name',
|
||||||
'Description',
|
'Description',
|
||||||
'Task Execution ID',
|
'Task Execution ID',
|
||||||
'State',
|
'State',
|
||||||
@@ -51,6 +52,7 @@ def format(execution=None, lister=False):
|
|||||||
|
|
||||||
data = (
|
data = (
|
||||||
execution.id,
|
execution.id,
|
||||||
|
execution.workflow_id,
|
||||||
execution.workflow_name,
|
execution.workflow_name,
|
||||||
execution.description,
|
execution.description,
|
||||||
execution.task_execution_id or '<none>',
|
execution.task_execution_id or '<none>',
|
||||||
@@ -141,8 +143,9 @@ class Create(show.ShowOne):
|
|||||||
parser = super(Create, self).get_parser(prog_name)
|
parser = super(Create, self).get_parser(prog_name)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'workflow_name',
|
'workflow_identifier',
|
||||||
help='Workflow name'
|
help='Workflow ID or name. Workflow name will be deprecated since'
|
||||||
|
'Mitaka.'
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'workflow_input',
|
'workflow_input',
|
||||||
@@ -184,7 +187,7 @@ class Create(show.ShowOne):
|
|||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
execution = mistral_client.executions.create(
|
execution = mistral_client.executions.create(
|
||||||
parsed_args.workflow_name,
|
parsed_args.workflow_identifier,
|
||||||
wf_input,
|
wf_input,
|
||||||
parsed_args.description,
|
parsed_args.description,
|
||||||
**params
|
**params
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ class SimpleMistralCLITests(base.MistralCLIAuth):
|
|||||||
self.mistral('execution-list'))
|
self.mistral('execution-list'))
|
||||||
self.assertTableStruct(
|
self.assertTableStruct(
|
||||||
executions,
|
executions,
|
||||||
['ID', 'Workflow', 'State', 'Created at', 'Updated at']
|
['ID', 'Workflow name', 'Workflow ID', 'State', 'Created at',
|
||||||
|
'Updated at']
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_tasks_list(self):
|
def test_tasks_list(self):
|
||||||
@@ -413,17 +414,19 @@ class ExecutionCLITests(base_v2.MistralClientTestBase):
|
|||||||
exec_id = self.get_value_of_field(execution, 'ID')
|
exec_id = self.get_value_of_field(execution, 'ID')
|
||||||
self.assertTableStruct(execution, ['Field', 'Value'])
|
self.assertTableStruct(execution, ['Field', 'Value'])
|
||||||
|
|
||||||
wf = self.get_value_of_field(execution, 'Workflow')
|
wf_name = self.get_value_of_field(execution, 'Workflow name')
|
||||||
|
wf_id = self.get_value_of_field(execution, 'Workflow ID')
|
||||||
created_at = self.get_value_of_field(execution, 'Created at')
|
created_at = self.get_value_of_field(execution, 'Created at')
|
||||||
description = self.get_value_of_field(execution, 'Description')
|
description = self.get_value_of_field(execution, 'Description')
|
||||||
|
|
||||||
self.assertEqual(self.direct_wf['Name'], wf)
|
self.assertEqual(self.direct_wf['Name'], wf_name)
|
||||||
|
self.assertIsNotNone(wf_id)
|
||||||
self.assertIsNotNone(created_at)
|
self.assertIsNotNone(created_at)
|
||||||
self.assertEqual("execution test", description)
|
self.assertEqual("execution test", description)
|
||||||
|
|
||||||
execs = self.mistral_admin('execution-list')
|
execs = self.mistral_admin('execution-list')
|
||||||
self.assertIn(exec_id, [ex['ID'] for ex in execs])
|
self.assertIn(exec_id, [ex['ID'] for ex in execs])
|
||||||
self.assertIn(wf, [ex['Workflow'] for ex in execs])
|
self.assertIn(wf_name, [ex['Workflow name'] for ex in execs])
|
||||||
|
|
||||||
self.mistral_admin('execution-delete', params=exec_id)
|
self.mistral_admin('execution-delete', params=exec_id)
|
||||||
|
|
||||||
@@ -471,10 +474,12 @@ class ExecutionCLITests(base_v2.MistralClientTestBase):
|
|||||||
'execution-get', params='{0}'.format(exec_id))
|
'execution-get', params='{0}'.format(exec_id))
|
||||||
|
|
||||||
gotten_id = self.get_value_of_field(execution, 'ID')
|
gotten_id = self.get_value_of_field(execution, 'ID')
|
||||||
wf = self.get_value_of_field(execution, 'Workflow')
|
wf_name = self.get_value_of_field(execution, 'Workflow name')
|
||||||
|
wf_id = self.get_value_of_field(execution, 'Workflow ID')
|
||||||
|
|
||||||
|
self.assertIsNotNone(wf_id)
|
||||||
self.assertEqual(exec_id, gotten_id)
|
self.assertEqual(exec_id, gotten_id)
|
||||||
self.assertEqual(self.direct_wf['Name'], wf)
|
self.assertEqual(self.direct_wf['Name'], wf_name)
|
||||||
|
|
||||||
def test_execution_get_input(self):
|
def test_execution_get_input(self):
|
||||||
execution = self.execution_create(self.direct_wf['Name'])
|
execution = self.execution_create(self.direct_wf['Name'])
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ EXEC = executions.Execution(
|
|||||||
mock,
|
mock,
|
||||||
{
|
{
|
||||||
'id': '123',
|
'id': '123',
|
||||||
|
'workflow_id': '123e4567-e89b-12d3-a456-426655440000',
|
||||||
'workflow_name': 'some',
|
'workflow_name': 'some',
|
||||||
'description': '',
|
'description': '',
|
||||||
'state': 'RUNNING',
|
'state': 'RUNNING',
|
||||||
@@ -40,6 +41,7 @@ SUB_WF_EXEC = executions.Execution(
|
|||||||
mock,
|
mock,
|
||||||
{
|
{
|
||||||
'id': '456',
|
'id': '456',
|
||||||
|
'workflow_id': '123e4567-e89b-12d3-a456-426655440000',
|
||||||
'workflow_name': 'some_sub_wf',
|
'workflow_name': 'some_sub_wf',
|
||||||
'description': '',
|
'description': '',
|
||||||
'state': 'RUNNING',
|
'state': 'RUNNING',
|
||||||
@@ -50,8 +52,28 @@ SUB_WF_EXEC = executions.Execution(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
EX_RESULT = ('123', 'some', '', '<none>', 'RUNNING', None, '1', '1')
|
EX_RESULT = (
|
||||||
SUB_WF_EX_RESULT = ('456', 'some_sub_wf', '', 'abc', 'RUNNING', None, '1', '1')
|
'123',
|
||||||
|
'123e4567-e89b-12d3-a456-426655440000',
|
||||||
|
'some',
|
||||||
|
'',
|
||||||
|
'<none>',
|
||||||
|
'RUNNING',
|
||||||
|
None,
|
||||||
|
'1',
|
||||||
|
'1'
|
||||||
|
)
|
||||||
|
SUB_WF_EX_RESULT = (
|
||||||
|
'456',
|
||||||
|
'123e4567-e89b-12d3-a456-426655440000',
|
||||||
|
'some_sub_wf',
|
||||||
|
'',
|
||||||
|
'abc',
|
||||||
|
'RUNNING',
|
||||||
|
None,
|
||||||
|
'1',
|
||||||
|
'1'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestCLIExecutionsV2(base.BaseCommandTest):
|
class TestCLIExecutionsV2(base.BaseCommandTest):
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ from mistralclient.tests.unit.v2 import base
|
|||||||
|
|
||||||
EXEC = {
|
EXEC = {
|
||||||
'id': "123",
|
'id': "123",
|
||||||
|
'workflow_id': '123e4567-e89b-12d3-a456-426655440000',
|
||||||
'workflow_name': 'my_wf',
|
'workflow_name': 'my_wf',
|
||||||
'description': '',
|
'description': '',
|
||||||
'state': 'RUNNING',
|
'state': 'RUNNING',
|
||||||
@@ -37,6 +38,7 @@ EXEC = {
|
|||||||
|
|
||||||
SUB_WF_EXEC = {
|
SUB_WF_EXEC = {
|
||||||
'id': "456",
|
'id': "456",
|
||||||
|
'workflow_id': '123e4567-e89b-12d3-a456-426655440000',
|
||||||
'workflow_name': 'my_sub_wf',
|
'workflow_name': 'my_sub_wf',
|
||||||
'task_execution_id': "abc",
|
'task_execution_id': "abc",
|
||||||
'description': '',
|
'description': '',
|
||||||
@@ -69,12 +71,36 @@ class TestExecutionsV2(base.BaseClientV2Test):
|
|||||||
|
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertDictEqual(
|
||||||
executions.Execution(self.executions, EXEC).to_dict(),
|
executions.Execution(self.executions, EXEC).to_dict(),
|
||||||
ex.to_dict()
|
ex.to_dict()
|
||||||
)
|
)
|
||||||
|
|
||||||
mock.assert_called_once_with(URL_TEMPLATE, json.dumps(body))
|
self.assertEqual(URL_TEMPLATE, mock.call_args[0][0])
|
||||||
|
self.assertDictEqual(body, json.loads(mock.call_args[0][1]))
|
||||||
|
|
||||||
|
def test_create_with_workflow_id(self):
|
||||||
|
mock = self.mock_http_post(content=EXEC)
|
||||||
|
body = {
|
||||||
|
'workflow_id': EXEC['workflow_id'],
|
||||||
|
'description': '',
|
||||||
|
'input': json.dumps(EXEC['input']),
|
||||||
|
}
|
||||||
|
|
||||||
|
ex = self.executions.create(
|
||||||
|
EXEC['workflow_id'],
|
||||||
|
EXEC['input']
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIsNotNone(ex)
|
||||||
|
|
||||||
|
self.assertDictEqual(
|
||||||
|
executions.Execution(self.executions, EXEC).to_dict(),
|
||||||
|
ex.to_dict()
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(URL_TEMPLATE, mock.call_args[0][0])
|
||||||
|
self.assertDictEqual(body, json.loads(mock.call_args[0][1]))
|
||||||
|
|
||||||
@unittest2.expectedFailure
|
@unittest2.expectedFailure
|
||||||
def test_create_failure1(self):
|
def test_create_failure1(self):
|
||||||
@@ -99,15 +125,13 @@ class TestExecutionsV2(base.BaseClientV2Test):
|
|||||||
|
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertDictEqual(
|
||||||
executions.Execution(self.executions, EXEC).to_dict(),
|
executions.Execution(self.executions, EXEC).to_dict(),
|
||||||
ex.to_dict()
|
ex.to_dict()
|
||||||
)
|
)
|
||||||
|
|
||||||
mock.assert_called_once_with(
|
self.assertEqual(URL_TEMPLATE_ID % EXEC['id'], mock.call_args[0][0])
|
||||||
URL_TEMPLATE_ID % EXEC['id'],
|
self.assertDictEqual(body, json.loads(mock.call_args[0][1]))
|
||||||
json.dumps(body)
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_update_env(self):
|
def test_update_env(self):
|
||||||
mock = self.mock_http_put(content=EXEC)
|
mock = self.mock_http_put(content=EXEC)
|
||||||
@@ -126,15 +150,13 @@ class TestExecutionsV2(base.BaseClientV2Test):
|
|||||||
|
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertDictEqual(
|
||||||
executions.Execution(self.executions, EXEC).to_dict(),
|
executions.Execution(self.executions, EXEC).to_dict(),
|
||||||
ex.to_dict()
|
ex.to_dict()
|
||||||
)
|
)
|
||||||
|
|
||||||
mock.assert_called_once_with(
|
self.assertEqual(URL_TEMPLATE_ID % EXEC['id'], mock.call_args[0][0])
|
||||||
URL_TEMPLATE_ID % EXEC['id'],
|
self.assertDictEqual(body, json.loads(mock.call_args[0][1]))
|
||||||
json.dumps(body)
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_list(self):
|
def test_list(self):
|
||||||
mock = self.mock_http_get(content={'executions': [EXEC, SUB_WF_EXEC]})
|
mock = self.mock_http_get(content={'executions': [EXEC, SUB_WF_EXEC]})
|
||||||
@@ -143,12 +165,12 @@ class TestExecutionsV2(base.BaseClientV2Test):
|
|||||||
|
|
||||||
self.assertEqual(2, len(execution_list))
|
self.assertEqual(2, len(execution_list))
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertDictEqual(
|
||||||
executions.Execution(self.executions, EXEC).to_dict(),
|
executions.Execution(self.executions, EXEC).to_dict(),
|
||||||
execution_list[0].to_dict()
|
execution_list[0].to_dict()
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertDictEqual(
|
||||||
executions.Execution(self.executions, SUB_WF_EXEC).to_dict(),
|
executions.Execution(self.executions, SUB_WF_EXEC).to_dict(),
|
||||||
execution_list[1].to_dict()
|
execution_list[1].to_dict()
|
||||||
)
|
)
|
||||||
@@ -178,7 +200,7 @@ class TestExecutionsV2(base.BaseClientV2Test):
|
|||||||
|
|
||||||
ex = self.executions.get(EXEC['id'])
|
ex = self.executions.get(EXEC['id'])
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertDictEqual(
|
||||||
executions.Execution(self.executions, EXEC).to_dict(),
|
executions.Execution(self.executions, EXEC).to_dict(),
|
||||||
ex.to_dict()
|
ex.to_dict()
|
||||||
)
|
)
|
||||||
@@ -190,7 +212,7 @@ class TestExecutionsV2(base.BaseClientV2Test):
|
|||||||
|
|
||||||
ex = self.executions.get(SUB_WF_EXEC['id'])
|
ex = self.executions.get(SUB_WF_EXEC['id'])
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertDictEqual(
|
||||||
executions.Execution(self.executions, SUB_WF_EXEC).to_dict(),
|
executions.Execution(self.executions, SUB_WF_EXEC).to_dict(),
|
||||||
ex.to_dict()
|
ex.to_dict()
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user