Running new workflow based on existing execution.
This is the client side work which will allow the operator to execute a new workflow based on the input of the same running workflow. Depends-On: Iec3d9f3a71a98952860b972acd09ce80e0a849ff Change-Id: Ib725c68246f263bdbd31655114157cc737ab07f7 Signed-off-by: Vitalii Solodilov <mcdkr@yandex.ru>
This commit is contained in:
parent
e7b5d05ffd
commit
e2ff3df5e8
|
@ -0,0 +1,55 @@
|
||||||
|
Replicating Workflows with Mistral
|
||||||
|
==================================
|
||||||
|
|
||||||
|
The new command line switch '-s' will allow the operator to replicate / clone
|
||||||
|
an existing workflow execution based on its ID. Once id is given mistral will
|
||||||
|
create a new workflow execution based on the parameters of the first, which
|
||||||
|
will provide a simple approach to spawning a number of workflow executions
|
||||||
|
without having to specify inputs or parameters. Otherwise you can override
|
||||||
|
some of the parameters (e.g. some of the input variables)
|
||||||
|
|
||||||
|
Basic Usage
|
||||||
|
-----------
|
||||||
|
|
||||||
|
From the command line the operator will issue the following. The first step
|
||||||
|
would be to list the current executions, which is done with "execution-list".
|
||||||
|
The following step is to take the listed execution id and pass it to the source
|
||||||
|
execution switch "-s".
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
mistral execution-list
|
||||||
|
|
||||||
|
mistral execution-create -s <execution id>
|
||||||
|
|
||||||
|
Once the workflow execution is selected and the replicate command used you
|
||||||
|
should see a newly created workflow execution based on an existing one with
|
||||||
|
a new execution id.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
mistral execution-create -s 123e4567-e89b-12d3-a456-426655440000
|
||||||
|
|
||||||
|
+--------------------+---------------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+--------------------+---------------------------------------+
|
||||||
|
| ID | 123e4567-e89b-12d3-a456-77046883182e |
|
||||||
|
| | |
|
||||||
|
| Workflow ID | 123e4567-e89b-12d3-a456-45411dfa33af |
|
||||||
|
| | |
|
||||||
|
| Workflow name | some.workflow.name.goes.here |
|
||||||
|
| | |
|
||||||
|
| Workflow namespace | |
|
||||||
|
| | |
|
||||||
|
| Description | |
|
||||||
|
| | |
|
||||||
|
| Task Execution ID | <none> |
|
||||||
|
| | |
|
||||||
|
| State | RUNNING |
|
||||||
|
| | |
|
||||||
|
| State info | None |
|
||||||
|
| | |
|
||||||
|
| Created at | 2018-01-25 18:41:07 |
|
||||||
|
| | |
|
||||||
|
| Updated at | 2018-01-25 18:41:07 |
|
||||||
|
+--------------------+---------------------------------------+
|
|
@ -14,6 +14,7 @@ Using mistralclient
|
||||||
cli/cli_usage_with_openstack
|
cli/cli_usage_with_openstack
|
||||||
cli/cli_usage_with_keycloak
|
cli/cli_usage_with_keycloak
|
||||||
cli/cli_usage_without_auth
|
cli/cli_usage_without_auth
|
||||||
|
cli/cli_usage_source_execution
|
||||||
class_reference
|
class_reference
|
||||||
|
|
||||||
For information about using the mistral command-line client, see
|
For information about using the mistral command-line client, see
|
||||||
|
|
|
@ -31,18 +31,24 @@ class Execution(base.Resource):
|
||||||
class ExecutionManager(base.ResourceManager):
|
class ExecutionManager(base.ResourceManager):
|
||||||
resource_class = Execution
|
resource_class = Execution
|
||||||
|
|
||||||
def create(self, workflow_identifier, namespace='', workflow_input=None,
|
def create(self, workflow_identifier='', namespace='',
|
||||||
description='', **params):
|
workflow_input=None, description='', source_execution_id=None,
|
||||||
self._ensure_not_empty(workflow_identifier=workflow_identifier)
|
**params):
|
||||||
|
ident = workflow_identifier or source_execution_id
|
||||||
|
self._ensure_not_empty(workflow_identifier=ident)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'description': description
|
'description': description,
|
||||||
}
|
}
|
||||||
|
|
||||||
if uuidutils.is_uuid_like(workflow_identifier):
|
if uuidutils.is_uuid_like(source_execution_id):
|
||||||
data.update({'workflow_id': workflow_identifier})
|
data.update({'source_execution_id': source_execution_id})
|
||||||
else:
|
|
||||||
data.update({'workflow_name': workflow_identifier})
|
if workflow_identifier:
|
||||||
|
if uuidutils.is_uuid_like(workflow_identifier):
|
||||||
|
data.update({'workflow_id': workflow_identifier})
|
||||||
|
else:
|
||||||
|
data.update({'workflow_name': workflow_identifier})
|
||||||
|
|
||||||
if namespace:
|
if namespace:
|
||||||
data.update({'workflow_namespace': namespace})
|
data.update({'workflow_namespace': namespace})
|
||||||
|
|
|
@ -173,6 +173,7 @@ class Create(command.ShowOne):
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'workflow_identifier',
|
'workflow_identifier',
|
||||||
|
nargs='?',
|
||||||
help='Workflow ID or name. Workflow name will be deprecated since '
|
help='Workflow ID or name. Workflow name will be deprecated since '
|
||||||
'Mitaka.'
|
'Mitaka.'
|
||||||
)
|
)
|
||||||
|
@ -199,6 +200,14 @@ class Create(command.ShowOne):
|
||||||
default='',
|
default='',
|
||||||
help='Execution description'
|
help='Execution description'
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-s',
|
||||||
|
dest='source_execution_id',
|
||||||
|
nargs='?',
|
||||||
|
help="Workflow Execution id which will allow operators to create "
|
||||||
|
"a new workflow execution based on the previously successful "
|
||||||
|
"executed workflow. Example: mistral execution-create -s "
|
||||||
|
"123e4567-e89b-12d3-a456-426655440000")
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
@ -220,6 +229,7 @@ class Create(command.ShowOne):
|
||||||
parsed_args.namespace,
|
parsed_args.namespace,
|
||||||
wf_input,
|
wf_input,
|
||||||
parsed_args.description,
|
parsed_args.description,
|
||||||
|
parsed_args.source_execution_id,
|
||||||
**params
|
**params
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,8 @@ SUB_WF_EXEC = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SOURCE_EXEC = EXEC
|
||||||
|
SOURCE_EXEC['source_execution_id'] = EXEC['workflow_id']
|
||||||
URL_TEMPLATE = '/executions'
|
URL_TEMPLATE = '/executions'
|
||||||
URL_TEMPLATE_ID = '/executions/%s'
|
URL_TEMPLATE_ID = '/executions/%s'
|
||||||
|
|
||||||
|
@ -65,7 +67,7 @@ class TestExecutionsV2(base.BaseClientV2Test):
|
||||||
body = {
|
body = {
|
||||||
'workflow_name': EXEC['workflow_name'],
|
'workflow_name': EXEC['workflow_name'],
|
||||||
'description': '',
|
'description': '',
|
||||||
'input': json.dumps(EXEC['input']),
|
'input': json.dumps(EXEC['input'])
|
||||||
}
|
}
|
||||||
|
|
||||||
ex = self.executions.create(
|
ex = self.executions.create(
|
||||||
|
@ -91,7 +93,7 @@ class TestExecutionsV2(base.BaseClientV2Test):
|
||||||
body = {
|
body = {
|
||||||
'workflow_id': EXEC['workflow_id'],
|
'workflow_id': EXEC['workflow_id'],
|
||||||
'description': '',
|
'description': '',
|
||||||
'input': json.dumps(EXEC['input']),
|
'input': json.dumps(EXEC['input'])
|
||||||
}
|
}
|
||||||
|
|
||||||
ex = self.executions.create(
|
ex = self.executions.create(
|
||||||
|
@ -108,6 +110,29 @@ class TestExecutionsV2(base.BaseClientV2Test):
|
||||||
|
|
||||||
self.assertDictEqual(body, self.requests_mock.last_request.json())
|
self.assertDictEqual(body, self.requests_mock.last_request.json())
|
||||||
|
|
||||||
|
def test_create_with_source_execution_id(self):
|
||||||
|
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
|
||||||
|
json=SOURCE_EXEC,
|
||||||
|
status_code=201)
|
||||||
|
|
||||||
|
body = {
|
||||||
|
'description': '',
|
||||||
|
'source_execution_id': SOURCE_EXEC['source_execution_id']
|
||||||
|
}
|
||||||
|
|
||||||
|
ex = self.executions.create(
|
||||||
|
source_execution_id=SOURCE_EXEC['source_execution_id']
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIsNotNone(ex)
|
||||||
|
|
||||||
|
self.assertDictEqual(
|
||||||
|
executions.Execution(self.executions, SOURCE_EXEC).to_dict(),
|
||||||
|
ex.to_dict()
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertDictEqual(body, self.requests_mock.last_request.json())
|
||||||
|
|
||||||
def test_create_failure1(self):
|
def test_create_failure1(self):
|
||||||
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
|
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
|
||||||
json=EXEC,
|
json=EXEC,
|
||||||
|
|
Loading…
Reference in New Issue