Add support for code sources and dynamic actions
* Adjust low-constraints.txt to fix more rigorous dependency check introduced in pip 20.3.0 (http://lists.openstack.org/pipermail/openstack-discuss/2020-December/019285.html) Depends-On: Ib5a53f1f1a185f0395ffae1ab0c401633fcdd0fc Change-Id: I28f5e2e201a0f1a2090ed6aff450f22a4fe846fe
This commit is contained in:
parent
668712eba2
commit
fc6f779b26
@ -20,11 +20,9 @@ eventlet==0.18.2
|
|||||||
extras==1.0.0
|
extras==1.0.0
|
||||||
fasteners==0.7.0
|
fasteners==0.7.0
|
||||||
fixtures==3.0.0
|
fixtures==3.0.0
|
||||||
flake8==2.5.5
|
|
||||||
future==0.16.0
|
future==0.16.0
|
||||||
futurist==1.2.0
|
futurist==1.2.0
|
||||||
greenlet==0.4.15
|
greenlet==0.4.15
|
||||||
hacking==0.12.0
|
|
||||||
idna==2.6
|
idna==2.6
|
||||||
imagesize==0.7.1
|
imagesize==0.7.1
|
||||||
iso8601==0.1.11
|
iso8601==0.1.11
|
||||||
@ -37,7 +35,6 @@ keystoneauth1==3.4.0
|
|||||||
kombu==4.0.0
|
kombu==4.0.0
|
||||||
linecache2==1.0.0
|
linecache2==1.0.0
|
||||||
MarkupSafe==1.1.1
|
MarkupSafe==1.1.1
|
||||||
mccabe==0.2.1
|
|
||||||
monotonic==0.6
|
monotonic==0.6
|
||||||
mox3==0.20.0
|
mox3==0.20.0
|
||||||
msgpack-python==0.4.0
|
msgpack-python==0.4.0
|
||||||
@ -72,7 +69,6 @@ positional==1.2.1
|
|||||||
prettytable==0.7.2
|
prettytable==0.7.2
|
||||||
pyasn1==0.1.8
|
pyasn1==0.1.8
|
||||||
pycparser==2.18
|
pycparser==2.18
|
||||||
pyflakes==0.8.1
|
|
||||||
Pygments==2.2.0
|
Pygments==2.2.0
|
||||||
pyinotify==0.9.6
|
pyinotify==0.9.6
|
||||||
pyOpenSSL==17.1.0
|
pyOpenSSL==17.1.0
|
||||||
|
@ -49,9 +49,11 @@ class Resource(object):
|
|||||||
return copy.deepcopy(self._data)
|
return copy.deepcopy(self._data)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
vals = ", ".join(["%s='%s'" % (n, v)
|
values = ", ".join(
|
||||||
for n, v in self._data.items()])
|
["%s='%s'" % (n, v) for n, v in self._data.items()]
|
||||||
return "%s [%s]" % (self.resource_name, vals)
|
)
|
||||||
|
|
||||||
|
return "%s [%s]" % (self.resource_name, values)
|
||||||
|
|
||||||
|
|
||||||
def _check_items(obj, searches):
|
def _check_items(obj, searches):
|
||||||
@ -130,9 +132,16 @@ class ResourceManager(object):
|
|||||||
|
|
||||||
def _validate(self, url, data, response_key=None, dump_json=True,
|
def _validate(self, url, data, response_key=None, dump_json=True,
|
||||||
headers=None, is_iter_resp=False):
|
headers=None, is_iter_resp=False):
|
||||||
return self._create(url, data, response_key, dump_json,
|
return self._create(
|
||||||
headers, is_iter_resp, resp_status_ok=200,
|
url,
|
||||||
as_class=False)
|
data,
|
||||||
|
response_key,
|
||||||
|
dump_json,
|
||||||
|
headers,
|
||||||
|
is_iter_resp,
|
||||||
|
resp_status_ok=200,
|
||||||
|
as_class=False
|
||||||
|
)
|
||||||
|
|
||||||
def _create(self, url, data, response_key=None, dump_json=True,
|
def _create(self, url, data, response_key=None, dump_json=True,
|
||||||
headers=None, is_iter_resp=False, resp_status_ok=201,
|
headers=None, is_iter_resp=False, resp_status_ok=201,
|
||||||
@ -149,9 +158,13 @@ class ResourceManager(object):
|
|||||||
self._raise_api_exception(resp)
|
self._raise_api_exception(resp)
|
||||||
|
|
||||||
resource = extract_json(resp, response_key)
|
resource = extract_json(resp, response_key)
|
||||||
|
|
||||||
if is_iter_resp:
|
if is_iter_resp:
|
||||||
return [self.resource_class(self, resource_data)
|
return [
|
||||||
for resource_data in resource]
|
self.resource_class(self, resource_data)
|
||||||
|
for resource_data in resource
|
||||||
|
]
|
||||||
|
|
||||||
return self.resource_class(self, resource) if as_class else resource
|
return self.resource_class(self, resource) if as_class else resource
|
||||||
|
|
||||||
def _update(self, url, data, response_key=None, dump_json=True,
|
def _update(self, url, data, response_key=None, dump_json=True,
|
||||||
@ -168,9 +181,13 @@ class ResourceManager(object):
|
|||||||
self._raise_api_exception(resp)
|
self._raise_api_exception(resp)
|
||||||
|
|
||||||
resource = extract_json(resp, response_key)
|
resource = extract_json(resp, response_key)
|
||||||
|
|
||||||
if is_iter_resp:
|
if is_iter_resp:
|
||||||
return [self.resource_class(self, resource_data)
|
return [
|
||||||
for resource_data in resource]
|
self.resource_class(self, resource_data)
|
||||||
|
for resource_data in resource
|
||||||
|
]
|
||||||
|
|
||||||
return self.resource_class(self, resource)
|
return self.resource_class(self, resource)
|
||||||
|
|
||||||
def _list(self, url, response_key=None, headers=None,
|
def _list(self, url, response_key=None, headers=None,
|
||||||
@ -186,8 +203,10 @@ class ResourceManager(object):
|
|||||||
|
|
||||||
resource_class = returned_res_cls or self.resource_class
|
resource_class = returned_res_cls or self.resource_class
|
||||||
|
|
||||||
return [resource_class(self, resource_data)
|
return [
|
||||||
for resource_data in extract_json(resp, response_key)]
|
resource_class(self, resource_data)
|
||||||
|
for resource_data in extract_json(resp, response_key)
|
||||||
|
]
|
||||||
|
|
||||||
def _get(self, url, response_key=None, headers=None):
|
def _get(self, url, response_key=None, headers=None):
|
||||||
try:
|
try:
|
||||||
@ -212,12 +231,17 @@ class ResourceManager(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def _raise_api_exception(resp):
|
def _raise_api_exception(resp):
|
||||||
try:
|
try:
|
||||||
error_data = (resp.headers.get("Server-Error-Message", None) or
|
error_data = (
|
||||||
get_json(resp).get("faultstring"))
|
resp.headers.get("Server-Error-Message", None)
|
||||||
|
or get_json(resp).get("faultstring")
|
||||||
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
error_data = resp.content
|
error_data = resp.content
|
||||||
raise APIException(error_code=resp.status_code,
|
|
||||||
error_message=error_data)
|
raise APIException(
|
||||||
|
error_code=resp.status_code,
|
||||||
|
error_message=error_data
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_json(response):
|
def get_json(response):
|
||||||
|
@ -31,6 +31,7 @@ class ActionManager(base.ResourceManager):
|
|||||||
# definition file
|
# definition file
|
||||||
definition = utils.get_contents_if_file(definition)
|
definition = utils.get_contents_if_file(definition)
|
||||||
url = '/actions?scope=%s' % scope
|
url = '/actions?scope=%s' % scope
|
||||||
|
|
||||||
if namespace:
|
if namespace:
|
||||||
url += '&namespace=%s' % namespace
|
url += '&namespace=%s' % namespace
|
||||||
|
|
||||||
@ -45,14 +46,18 @@ class ActionManager(base.ResourceManager):
|
|||||||
|
|
||||||
def update(self, definition, scope='private', id=None, namespace=''):
|
def update(self, definition, scope='private', id=None, namespace=''):
|
||||||
self._ensure_not_empty(definition=definition)
|
self._ensure_not_empty(definition=definition)
|
||||||
|
|
||||||
params = '?scope=%s' % scope
|
params = '?scope=%s' % scope
|
||||||
|
|
||||||
if namespace:
|
if namespace:
|
||||||
params += '&namespace=%s' % namespace
|
params += '&namespace=%s' % namespace
|
||||||
|
|
||||||
url = ('/actions/%s' % id if id else '/actions') + params
|
url = ('/actions/%s' % id if id else '/actions') + params
|
||||||
|
|
||||||
# If the specified definition is actually a file, read in the
|
# If the specified definition is actually a file, read in the
|
||||||
# definition file
|
# definition file
|
||||||
definition = utils.get_contents_if_file(definition)
|
definition = utils.get_contents_if_file(definition)
|
||||||
|
|
||||||
return self._update(
|
return self._update(
|
||||||
url,
|
url,
|
||||||
definition,
|
definition,
|
||||||
|
@ -20,7 +20,9 @@ from oslo_utils import importutils
|
|||||||
from mistralclient.api import httpclient
|
from mistralclient.api import httpclient
|
||||||
from mistralclient.api.v2 import action_executions
|
from mistralclient.api.v2 import action_executions
|
||||||
from mistralclient.api.v2 import actions
|
from mistralclient.api.v2 import actions
|
||||||
|
from mistralclient.api.v2 import code_sources
|
||||||
from mistralclient.api.v2 import cron_triggers
|
from mistralclient.api.v2 import cron_triggers
|
||||||
|
from mistralclient.api.v2 import dynamic_actions
|
||||||
from mistralclient.api.v2 import environments
|
from mistralclient.api.v2 import environments
|
||||||
from mistralclient.api.v2 import event_triggers
|
from mistralclient.api.v2 import event_triggers
|
||||||
from mistralclient.api.v2 import executions
|
from mistralclient.api.v2 import executions
|
||||||
@ -86,6 +88,11 @@ class Client(object):
|
|||||||
self.event_triggers = event_triggers.EventTriggerManager(http_client)
|
self.event_triggers = event_triggers.EventTriggerManager(http_client)
|
||||||
self.environments = environments.EnvironmentManager(http_client)
|
self.environments = environments.EnvironmentManager(http_client)
|
||||||
self.action_executions = action_executions.ActionExecutionManager(
|
self.action_executions = action_executions.ActionExecutionManager(
|
||||||
http_client)
|
http_client
|
||||||
|
)
|
||||||
self.services = services.ServiceManager(http_client)
|
self.services = services.ServiceManager(http_client)
|
||||||
self.members = members.MemberManager(http_client)
|
self.members = members.MemberManager(http_client)
|
||||||
|
self.code_sources = code_sources.CodeSourceManager(http_client)
|
||||||
|
self.dynamic_actions = dynamic_actions.DynamicActionManager(
|
||||||
|
http_client
|
||||||
|
)
|
||||||
|
88
mistralclient/api/v2/code_sources.py
Normal file
88
mistralclient/api/v2/code_sources.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# Copyright 2020 Nokia Software.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from mistralclient.api import base
|
||||||
|
from mistralclient import utils
|
||||||
|
|
||||||
|
|
||||||
|
class CodeSource(base.Resource):
|
||||||
|
resource_name = 'CodeSource'
|
||||||
|
|
||||||
|
|
||||||
|
class CodeSourceManager(base.ResourceManager):
|
||||||
|
resource_class = CodeSource
|
||||||
|
|
||||||
|
def create(self, name, content, namespace='', scope='private'):
|
||||||
|
self._ensure_not_empty(name=name, content=content)
|
||||||
|
|
||||||
|
# If the specified content is actually a file, read from it.
|
||||||
|
content = utils.get_contents_if_file(content)
|
||||||
|
|
||||||
|
return self._create(
|
||||||
|
'/code_sources?name=%s&scope=%s&namespace=%s' %
|
||||||
|
(name, scope, namespace),
|
||||||
|
content,
|
||||||
|
dump_json=False,
|
||||||
|
headers={'content-type': 'text/plain'}
|
||||||
|
)
|
||||||
|
|
||||||
|
def update(self, identifier, content, namespace='', scope='private'):
|
||||||
|
self._ensure_not_empty(identifier=identifier, content=content)
|
||||||
|
|
||||||
|
# If the specified content is actually a file, read from it.
|
||||||
|
content = utils.get_contents_if_file(content)
|
||||||
|
|
||||||
|
return self._update(
|
||||||
|
'/code_sources?identifier=%s&scope=%s&namespace=%s' %
|
||||||
|
(identifier, scope, namespace),
|
||||||
|
content,
|
||||||
|
dump_json=False,
|
||||||
|
headers={'content-type': 'text/plain'},
|
||||||
|
)
|
||||||
|
|
||||||
|
def list(self, namespace='', marker='', limit=None, sort_keys='',
|
||||||
|
sort_dirs='', fields='', **filters):
|
||||||
|
if namespace:
|
||||||
|
filters['namespace'] = namespace
|
||||||
|
|
||||||
|
query_string = self._build_query_params(
|
||||||
|
marker=marker,
|
||||||
|
limit=limit,
|
||||||
|
sort_keys=sort_keys,
|
||||||
|
sort_dirs=sort_dirs,
|
||||||
|
fields=fields,
|
||||||
|
filters=filters
|
||||||
|
)
|
||||||
|
|
||||||
|
return self._list(
|
||||||
|
'/code_sources%s' % query_string,
|
||||||
|
response_key='code_sources',
|
||||||
|
)
|
||||||
|
|
||||||
|
def get(self, identifier, namespace=''):
|
||||||
|
self._ensure_not_empty(identifier=identifier)
|
||||||
|
|
||||||
|
return self._get(
|
||||||
|
'/code_sources/%s?namespace=%s' % (identifier, namespace)
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete(self, identifier, namespace=None):
|
||||||
|
self._ensure_not_empty(identifier=identifier)
|
||||||
|
|
||||||
|
url = '/code_sources/%s' % identifier
|
||||||
|
|
||||||
|
if namespace:
|
||||||
|
url = url + '?namespace=%s' % namespace
|
||||||
|
|
||||||
|
self._delete(url)
|
105
mistralclient/api/v2/dynamic_actions.py
Normal file
105
mistralclient/api/v2/dynamic_actions.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# Copyright 2020 Nokia Software.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from mistralclient.api import base
|
||||||
|
|
||||||
|
|
||||||
|
class DynamicAction(base.Resource):
|
||||||
|
resource_name = 'DynamicAction'
|
||||||
|
|
||||||
|
|
||||||
|
class DynamicActionManager(base.ResourceManager):
|
||||||
|
resource_class = DynamicAction
|
||||||
|
|
||||||
|
def get(self, identifier, namespace=''):
|
||||||
|
self._ensure_not_empty(identifier=identifier)
|
||||||
|
|
||||||
|
return self._get(
|
||||||
|
'/dynamic_actions/%s?namespace=%s' % (identifier, namespace)
|
||||||
|
)
|
||||||
|
|
||||||
|
def create(self, name, class_name, code_source, scope='private',
|
||||||
|
namespace=''):
|
||||||
|
self._ensure_not_empty(
|
||||||
|
name=name,
|
||||||
|
class_name=class_name,
|
||||||
|
code_source=code_source
|
||||||
|
)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"name": name,
|
||||||
|
"class_name": class_name,
|
||||||
|
"scope": scope,
|
||||||
|
"namespace": namespace
|
||||||
|
}
|
||||||
|
|
||||||
|
if uuidutils.is_uuid_like(code_source):
|
||||||
|
data['code_source_id'] = code_source
|
||||||
|
else:
|
||||||
|
data['code_source_name'] = code_source
|
||||||
|
|
||||||
|
return self._create('/dynamic_actions', data)
|
||||||
|
|
||||||
|
def update(self, identifier, class_name=None, code_source=None,
|
||||||
|
scope='private', namespace=''):
|
||||||
|
self._ensure_not_empty(identifier=identifier)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'scope': scope,
|
||||||
|
'namespace': namespace
|
||||||
|
}
|
||||||
|
|
||||||
|
if uuidutils.is_uuid_like(identifier):
|
||||||
|
data['id'] = identifier
|
||||||
|
else:
|
||||||
|
data['name'] = identifier
|
||||||
|
|
||||||
|
if class_name:
|
||||||
|
data['class_name'] = class_name
|
||||||
|
|
||||||
|
if code_source:
|
||||||
|
if uuidutils.is_uuid_like(code_source):
|
||||||
|
data['code_source_id'] = code_source
|
||||||
|
else:
|
||||||
|
data['code_source_name'] = code_source
|
||||||
|
|
||||||
|
return self._update('/dynamic_actions', data)
|
||||||
|
|
||||||
|
def list(self, marker='', limit=None, sort_keys='', sort_dirs='',
|
||||||
|
fields='', namespace='', **filters):
|
||||||
|
if namespace:
|
||||||
|
filters['namespace'] = namespace
|
||||||
|
|
||||||
|
query_string = self._build_query_params(
|
||||||
|
marker=marker,
|
||||||
|
limit=limit,
|
||||||
|
sort_keys=sort_keys,
|
||||||
|
sort_dirs=sort_dirs,
|
||||||
|
fields=fields,
|
||||||
|
filters=filters
|
||||||
|
)
|
||||||
|
|
||||||
|
return self._list(
|
||||||
|
'/dynamic_actions%s' % query_string,
|
||||||
|
response_key='dynamic_actions',
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete(self, identifier, namespace=''):
|
||||||
|
self._ensure_not_empty(identifier=identifier)
|
||||||
|
|
||||||
|
self._delete(
|
||||||
|
'/dynamic_actions/%s?namespace=%s' % (identifier, namespace)
|
||||||
|
)
|
@ -28,11 +28,11 @@ class Execution(base.Resource):
|
|||||||
class ExecutionManager(base.ResourceManager):
|
class ExecutionManager(base.ResourceManager):
|
||||||
resource_class = Execution
|
resource_class = Execution
|
||||||
|
|
||||||
def create(self, workflow_identifier='', namespace='',
|
def create(self, wf_identifier='', namespace='',
|
||||||
workflow_input=None, description='', source_execution_id=None,
|
workflow_input=None, description='', source_execution_id=None,
|
||||||
**params):
|
**params):
|
||||||
self._ensure_not_empty(
|
self._ensure_not_empty(
|
||||||
workflow_identifier=workflow_identifier or source_execution_id
|
workflow_identifier=wf_identifier or source_execution_id
|
||||||
)
|
)
|
||||||
|
|
||||||
data = {'description': description}
|
data = {'description': description}
|
||||||
@ -40,11 +40,11 @@ class ExecutionManager(base.ResourceManager):
|
|||||||
if uuidutils.is_uuid_like(source_execution_id):
|
if uuidutils.is_uuid_like(source_execution_id):
|
||||||
data.update({'source_execution_id': source_execution_id})
|
data.update({'source_execution_id': source_execution_id})
|
||||||
|
|
||||||
if workflow_identifier:
|
if wf_identifier:
|
||||||
if uuidutils.is_uuid_like(workflow_identifier):
|
if uuidutils.is_uuid_like(wf_identifier):
|
||||||
data.update({'workflow_id': workflow_identifier})
|
data.update({'workflow_id': wf_identifier})
|
||||||
else:
|
else:
|
||||||
data.update({'workflow_name': workflow_identifier})
|
data.update({'workflow_name': wf_identifier})
|
||||||
|
|
||||||
if namespace:
|
if namespace:
|
||||||
data.update({'workflow_namespace': namespace})
|
data.update({'workflow_namespace': namespace})
|
||||||
|
@ -25,19 +25,19 @@ class WorkbookManager(base.ResourceManager):
|
|||||||
resource_class = Workbook
|
resource_class = Workbook
|
||||||
|
|
||||||
def _get_workbooks_url(self, resource=None, namespace=None, scope=None):
|
def _get_workbooks_url(self, resource=None, namespace=None, scope=None):
|
||||||
path = '/workbooks'
|
url = '/workbooks'
|
||||||
|
|
||||||
if resource:
|
if resource:
|
||||||
path += '/%s' % resource
|
url += '/%s' % resource
|
||||||
|
|
||||||
if scope and namespace:
|
if scope and namespace:
|
||||||
path += '?scope=%s&namespace=%s' % (scope, namespace)
|
url += '?scope=%s&namespace=%s' % (scope, namespace)
|
||||||
elif scope:
|
elif scope:
|
||||||
path += '?scope=%s' % scope
|
url += '?scope=%s' % scope
|
||||||
elif namespace:
|
elif namespace:
|
||||||
path += '?namespace=%s' % namespace
|
url += '?namespace=%s' % namespace
|
||||||
|
|
||||||
return path
|
return url
|
||||||
|
|
||||||
def create(self, definition, namespace='', scope='private'):
|
def create(self, definition, namespace='', scope='private'):
|
||||||
self._ensure_not_empty(definition=definition)
|
self._ensure_not_empty(definition=definition)
|
||||||
@ -78,8 +78,10 @@ class WorkbookManager(base.ResourceManager):
|
|||||||
namespace=namespace
|
namespace=namespace
|
||||||
)
|
)
|
||||||
|
|
||||||
return self._list('/workbooks{}'.format(query_string),
|
return self._list(
|
||||||
response_key='workbooks')
|
'/workbooks{}'.format(query_string),
|
||||||
|
response_key='workbooks'
|
||||||
|
)
|
||||||
|
|
||||||
def get(self, name, namespace=''):
|
def get(self, name, namespace=''):
|
||||||
self._ensure_not_empty(name=name)
|
self._ensure_not_empty(name=name)
|
||||||
|
@ -51,11 +51,13 @@ class ActionExecutionFormatter(base.MistralFormatter):
|
|||||||
columns = ActionExecutionFormatter.LIST_COLUMN_HEADING_NAMES
|
columns = ActionExecutionFormatter.LIST_COLUMN_HEADING_NAMES
|
||||||
else:
|
else:
|
||||||
columns = ActionExecutionFormatter.headings()
|
columns = ActionExecutionFormatter.headings()
|
||||||
|
|
||||||
if action_ex:
|
if action_ex:
|
||||||
if hasattr(action_ex, 'task_name'):
|
if hasattr(action_ex, 'task_name'):
|
||||||
task_name = action_ex.task_name
|
task_name = action_ex.task_name
|
||||||
else:
|
else:
|
||||||
task_name = None
|
task_name = None
|
||||||
|
|
||||||
data = (
|
data = (
|
||||||
action_ex.id,
|
action_ex.id,
|
||||||
action_ex.name,
|
action_ex.name,
|
||||||
@ -63,16 +65,19 @@ class ActionExecutionFormatter(base.MistralFormatter):
|
|||||||
action_ex.workflow_namespace,
|
action_ex.workflow_namespace,
|
||||||
task_name,
|
task_name,
|
||||||
action_ex.task_execution_id,
|
action_ex.task_execution_id,
|
||||||
action_ex.state,)
|
action_ex.state,
|
||||||
|
)
|
||||||
|
|
||||||
if not lister:
|
if not lister:
|
||||||
data += (action_ex.state_info,)
|
data += (action_ex.state_info,)
|
||||||
|
|
||||||
data += (
|
data += (
|
||||||
action_ex.accepted,
|
action_ex.accepted,
|
||||||
action_ex.created_at,
|
action_ex.created_at,
|
||||||
action_ex.updated_at or '<none>'
|
action_ex.updated_at or '<none>'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
data = (tuple('' for _ in range(len(columns))),)
|
data = (('',) * len(columns),)
|
||||||
|
|
||||||
return columns, data
|
return columns, data
|
||||||
|
|
||||||
@ -224,25 +229,30 @@ class Update(command.ShowOne):
|
|||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'id',
|
'id',
|
||||||
help='Action execution ID.')
|
help='Action execution ID.'
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--state',
|
'--state',
|
||||||
dest='state',
|
dest='state',
|
||||||
choices=['PAUSED', 'RUNNING', 'SUCCESS', 'ERROR', 'CANCELLED'],
|
choices=['PAUSED', 'RUNNING', 'SUCCESS', 'ERROR', 'CANCELLED'],
|
||||||
help='Action execution state')
|
help='Action execution state'
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--output',
|
'--output',
|
||||||
dest='output',
|
dest='output',
|
||||||
help='Action execution output')
|
help='Action execution output'
|
||||||
|
)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
output = None
|
output = None
|
||||||
|
|
||||||
if parsed_args.output:
|
if parsed_args.output:
|
||||||
output = utils.load_json(parsed_args.output)
|
output = utils.load_json(parsed_args.output)
|
||||||
|
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
execution = mistral_client.action_executions.update(
|
execution = mistral_client.action_executions.update(
|
||||||
parsed_args.id,
|
parsed_args.id,
|
||||||
parsed_args.state,
|
parsed_args.state,
|
||||||
@ -257,14 +267,17 @@ class GetOutput(command.Command):
|
|||||||
|
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super(GetOutput, self).get_parser(prog_name)
|
parser = super(GetOutput, self).get_parser(prog_name)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'id',
|
'id',
|
||||||
help='Action execution ID.')
|
help='Action execution ID.'
|
||||||
|
)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
output = mistral_client.action_executions.get(parsed_args.id).output
|
output = mistral_client.action_executions.get(parsed_args.id).output
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -281,6 +294,7 @@ class GetInput(command.Command):
|
|||||||
|
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super(GetInput, self).get_parser(prog_name)
|
parser = super(GetInput, self).get_parser(prog_name)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'id',
|
'id',
|
||||||
help='Action execution ID.'
|
help='Action execution ID.'
|
||||||
@ -290,6 +304,7 @@ class GetInput(command.Command):
|
|||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
result = mistral_client.action_executions.get(parsed_args.id).input
|
result = mistral_client.action_executions.get(parsed_args.id).input
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -113,9 +113,11 @@ class Get(command.ShowOne):
|
|||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
action = mistral_client.actions.get(
|
action = mistral_client.actions.get(
|
||||||
parsed_args.action,
|
parsed_args.action,
|
||||||
parsed_args.namespace)
|
parsed_args.namespace
|
||||||
|
)
|
||||||
|
|
||||||
return ActionFormatter.format(action)
|
return ActionFormatter.format(action)
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ class MistralLister(command.Lister, metaclass=abc.ABCMeta):
|
|||||||
f = self._get_format_function()
|
f = self._get_format_function()
|
||||||
|
|
||||||
ret = self._get_resources(parsed_args)
|
ret = self._get_resources(parsed_args)
|
||||||
|
|
||||||
if not isinstance(ret, list):
|
if not isinstance(ret, list):
|
||||||
ret = [ret]
|
ret = [ret]
|
||||||
|
|
||||||
|
251
mistralclient/commands/v2/code_sources.py
Normal file
251
mistralclient/commands/v2/code_sources.py
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
# Copyright 2020 Nokia Software.
|
||||||
|
#
|
||||||
|
# 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 argparse
|
||||||
|
|
||||||
|
from cliff import show
|
||||||
|
from osc_lib.command import command
|
||||||
|
|
||||||
|
from mistralclient.commands.v2 import base
|
||||||
|
from mistralclient import utils
|
||||||
|
|
||||||
|
|
||||||
|
class CodeSourceFormatter(base.MistralFormatter):
|
||||||
|
COLUMNS = [
|
||||||
|
('id', 'ID'),
|
||||||
|
('name', 'Name'),
|
||||||
|
('namespace', 'Namespace'),
|
||||||
|
('project_id', 'Project ID'),
|
||||||
|
('scope', 'Scope'),
|
||||||
|
('created_at', 'Created at'),
|
||||||
|
('updated_at', 'Updated at')
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def format(code_src=None, lister=False):
|
||||||
|
if code_src:
|
||||||
|
data = (
|
||||||
|
code_src.id,
|
||||||
|
code_src.name,
|
||||||
|
code_src.namespace,
|
||||||
|
code_src.project_id,
|
||||||
|
code_src.scope,
|
||||||
|
code_src.created_at
|
||||||
|
)
|
||||||
|
|
||||||
|
if hasattr(code_src, 'updated_at'):
|
||||||
|
data += (code_src.updated_at,)
|
||||||
|
else:
|
||||||
|
data += (None,)
|
||||||
|
else:
|
||||||
|
data = (('',) * len(CodeSourceFormatter.COLUMNS),)
|
||||||
|
|
||||||
|
return CodeSourceFormatter.headings(), data
|
||||||
|
|
||||||
|
|
||||||
|
class List(base.MistralLister):
|
||||||
|
"""List all workflows."""
|
||||||
|
|
||||||
|
def _get_format_function(self):
|
||||||
|
return CodeSourceFormatter.format_list
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(List, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def _get_resources(self, parsed_args):
|
||||||
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
|
return mistral_client.code_sources.list(
|
||||||
|
marker=parsed_args.marker,
|
||||||
|
limit=parsed_args.limit,
|
||||||
|
sort_keys=parsed_args.sort_keys,
|
||||||
|
sort_dirs=parsed_args.sort_dirs,
|
||||||
|
fields=CodeSourceFormatter.fields(),
|
||||||
|
**base.get_filters(parsed_args)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Get(show.ShowOne):
|
||||||
|
"""Show specific code source."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Get, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument('identifier', help='Code source ID or name.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default='',
|
||||||
|
help="Namespace to get the code source from.",
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
|
wf = mistral_client.code_sources.get(
|
||||||
|
parsed_args.identifier,
|
||||||
|
parsed_args.namespace
|
||||||
|
)
|
||||||
|
|
||||||
|
return CodeSourceFormatter.format(wf)
|
||||||
|
|
||||||
|
|
||||||
|
class Create(command.ShowOne):
|
||||||
|
"""Create new code source."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Create, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument('name', help='Code source name.')
|
||||||
|
parser.add_argument(
|
||||||
|
'content',
|
||||||
|
type=argparse.FileType('r'),
|
||||||
|
help='Code source content file.'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default='',
|
||||||
|
help="Namespace to create the code source within.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--public',
|
||||||
|
action='store_true',
|
||||||
|
help='With this flag the code source will be marked as "public".'
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
scope = 'public' if parsed_args.public else 'private'
|
||||||
|
|
||||||
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
|
code_source = mistral_client.code_sources.create(
|
||||||
|
parsed_args.name,
|
||||||
|
parsed_args.content.read(),
|
||||||
|
namespace=parsed_args.namespace,
|
||||||
|
scope=scope
|
||||||
|
)
|
||||||
|
|
||||||
|
return CodeSourceFormatter.format(code_source)
|
||||||
|
|
||||||
|
|
||||||
|
class Delete(command.Command):
|
||||||
|
"""Delete workflow."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Delete, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'identifier',
|
||||||
|
nargs='+',
|
||||||
|
help='Code source name or ID (can be repeated multiple times).'
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default=None,
|
||||||
|
help="Namespace to delete the code source(s) from.",
|
||||||
|
)
|
||||||
|
|
||||||
|
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.code_sources.delete(s, parsed_args.namespace),
|
||||||
|
parsed_args.identifier,
|
||||||
|
"Request to delete code source '%s' has been accepted.",
|
||||||
|
"Unable to delete the specified code source(s)."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Update(command.ShowOne):
|
||||||
|
"""Update workflow."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Update, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'identifier',
|
||||||
|
help='Code source identifier (name or ID).'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'content',
|
||||||
|
type=argparse.FileType('r'),
|
||||||
|
help='Code source content'
|
||||||
|
)
|
||||||
|
parser.add_argument('--id', help='Workflow ID.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default='',
|
||||||
|
help="Namespace of the workflow.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--public',
|
||||||
|
action='store_true',
|
||||||
|
help='With this flag workflow will be marked as "public".'
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
scope = 'public' if parsed_args.public else 'private'
|
||||||
|
|
||||||
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
|
code_src = mistral_client.code_sources.update(
|
||||||
|
parsed_args.identifier,
|
||||||
|
parsed_args.content.read(),
|
||||||
|
namespace=parsed_args.namespace,
|
||||||
|
scope=scope
|
||||||
|
)
|
||||||
|
|
||||||
|
return CodeSourceFormatter.format(code_src)
|
||||||
|
|
||||||
|
|
||||||
|
class GetContent(command.Command):
|
||||||
|
"""Show workflow definition."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(GetContent, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument('identifier', help='Code source ID or name.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default='',
|
||||||
|
help="Namespace to get the code source from.",
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
|
code_src = mistral_client.code_sources.get(
|
||||||
|
parsed_args.identifier,
|
||||||
|
parsed_args.namespace
|
||||||
|
)
|
||||||
|
|
||||||
|
self.app.stdout.write(code_src.content or "\n")
|
244
mistralclient/commands/v2/dynamic_actions.py
Normal file
244
mistralclient/commands/v2/dynamic_actions.py
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
# Copyright 2020 Nokia Software.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
from osc_lib.command import command
|
||||||
|
|
||||||
|
from mistralclient.commands.v2 import base
|
||||||
|
from mistralclient import utils
|
||||||
|
|
||||||
|
|
||||||
|
class DynamicActionFormatter(base.MistralFormatter):
|
||||||
|
COLUMNS = [
|
||||||
|
('id', 'ID'),
|
||||||
|
('name', 'Name'),
|
||||||
|
('class_name', 'Class'),
|
||||||
|
('code_source_id', 'Code source ID'),
|
||||||
|
('code_source_name', 'Code source name'),
|
||||||
|
('project_id', 'Project ID'),
|
||||||
|
('scope', 'Scope'),
|
||||||
|
('created_at', 'Created at'),
|
||||||
|
('updated_at', 'Updated at'),
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def format(action=None, lister=False):
|
||||||
|
if action:
|
||||||
|
data = (
|
||||||
|
action.id,
|
||||||
|
action.name,
|
||||||
|
action.class_name,
|
||||||
|
action.code_source_id,
|
||||||
|
action.code_source_name,
|
||||||
|
action.project_id,
|
||||||
|
action.scope,
|
||||||
|
action.created_at
|
||||||
|
)
|
||||||
|
|
||||||
|
if hasattr(action, 'updated_at'):
|
||||||
|
data += (action.updated_at,)
|
||||||
|
else:
|
||||||
|
data += (None,)
|
||||||
|
|
||||||
|
else:
|
||||||
|
data = (('',)*len(DynamicActionFormatter.COLUMNS),)
|
||||||
|
|
||||||
|
return DynamicActionFormatter.headings(), data
|
||||||
|
|
||||||
|
|
||||||
|
class List(base.MistralLister):
|
||||||
|
"""List all dynamic actions."""
|
||||||
|
|
||||||
|
def _get_format_function(self):
|
||||||
|
return DynamicActionFormatter.format_list
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(List, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default='',
|
||||||
|
help="Namespace of dynamic actions.",
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def _get_resources(self, parsed_args):
|
||||||
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
|
return mistral_client.dynamic_actions.list(
|
||||||
|
marker=parsed_args.marker,
|
||||||
|
limit=parsed_args.limit,
|
||||||
|
sort_keys=parsed_args.sort_keys,
|
||||||
|
sort_dirs=parsed_args.sort_dirs,
|
||||||
|
fields=DynamicActionFormatter.fields(),
|
||||||
|
namespace=parsed_args.namespace,
|
||||||
|
**base.get_filters(parsed_args)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Get(command.ShowOne):
|
||||||
|
"""Show specific dynamic action."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Get, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'identifier',
|
||||||
|
help='Dynamic action identifier (name or ID)'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default='',
|
||||||
|
help="Namespace to create the dynamic action within.",
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
|
action = mistral_client.dynamic_actions.get(
|
||||||
|
parsed_args.identifier,
|
||||||
|
parsed_args.namespace
|
||||||
|
)
|
||||||
|
|
||||||
|
return DynamicActionFormatter.format(action)
|
||||||
|
|
||||||
|
|
||||||
|
class Create(command.ShowOne):
|
||||||
|
"""Create new action."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Create, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument('name', help='Dynamic action name')
|
||||||
|
parser.add_argument('class_name', help='Dynamic action class name')
|
||||||
|
parser.add_argument('code_source', help='Code source ID or name')
|
||||||
|
parser.add_argument(
|
||||||
|
'--public',
|
||||||
|
action='store_true',
|
||||||
|
help='With this flag an action will be marked as "public".'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default='',
|
||||||
|
help="Namespace to create the action within.",
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
scope = 'public' if parsed_args.public else 'private'
|
||||||
|
|
||||||
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
|
dyn_action = mistral_client.dynamic_actions.create(
|
||||||
|
parsed_args.name,
|
||||||
|
parsed_args.class_name,
|
||||||
|
parsed_args.code_source,
|
||||||
|
namespace=parsed_args.namespace,
|
||||||
|
scope=scope
|
||||||
|
)
|
||||||
|
|
||||||
|
return DynamicActionFormatter.format(dyn_action)
|
||||||
|
|
||||||
|
|
||||||
|
class Delete(command.Command):
|
||||||
|
"""Delete action."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Delete, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'identifier',
|
||||||
|
nargs='+',
|
||||||
|
help="Dynamic action name or ID (can be repeated multiple times)."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default='',
|
||||||
|
help="Namespace of the dynamic action(s).",
|
||||||
|
)
|
||||||
|
|
||||||
|
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.dynamic_actions.delete(
|
||||||
|
s,
|
||||||
|
namespace=parsed_args.namespace
|
||||||
|
),
|
||||||
|
parsed_args.identifier,
|
||||||
|
"Request to delete dynamic action(s) %s has been accepted.",
|
||||||
|
"Unable to delete the specified dynamic action(s)."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Update(command.ShowOne):
|
||||||
|
"""Update dynamic action."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(Update, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'identifier',
|
||||||
|
help='Dynamic action identifier (ID or name)'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--class-name',
|
||||||
|
dest='class_name',
|
||||||
|
nargs='?',
|
||||||
|
help='Dynamic action class name.'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--code-source',
|
||||||
|
dest='code_source',
|
||||||
|
nargs='?',
|
||||||
|
help='Code source identifier (ID or name).'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--public',
|
||||||
|
action='store_true',
|
||||||
|
help='With this flag action will be marked as "public".'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--namespace',
|
||||||
|
nargs='?',
|
||||||
|
default='',
|
||||||
|
help="Namespace of the action.",
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
scope = 'public' if parsed_args.public else 'private'
|
||||||
|
|
||||||
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
|
dyn_action = mistral_client.dynamic_actions.update(
|
||||||
|
parsed_args.identifier,
|
||||||
|
class_name=parsed_args.class_name,
|
||||||
|
code_source=parsed_args.code_source,
|
||||||
|
scope=scope,
|
||||||
|
namespace=parsed_args.namespace
|
||||||
|
)
|
||||||
|
|
||||||
|
return DynamicActionFormatter.format(dyn_action)
|
@ -87,10 +87,7 @@ class Get(command.ShowOne):
|
|||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super(Get, self).get_parser(prog_name)
|
parser = super(Get, self).get_parser(prog_name)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument('environment', help='Environment name')
|
||||||
'environment',
|
|
||||||
help='Environment name'
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--export',
|
'--export',
|
||||||
|
@ -89,6 +89,7 @@ class List(base.MistralExecutionLister):
|
|||||||
|
|
||||||
def get_parser(self, parsed_args):
|
def get_parser(self, parsed_args):
|
||||||
parser = super(List, self).get_parser(parsed_args)
|
parser = super(List, self).get_parser(parsed_args)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--task',
|
'--task',
|
||||||
nargs='?',
|
nargs='?',
|
||||||
@ -146,8 +147,7 @@ class Create(command.ShowOne):
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'workflow_identifier',
|
'workflow_identifier',
|
||||||
nargs='?',
|
nargs='?',
|
||||||
help='Workflow ID or name. Workflow name will be deprecated since '
|
help='Workflow ID or name'
|
||||||
'Mitaka.'
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--namespace',
|
'--namespace',
|
||||||
@ -249,10 +249,7 @@ class Update(command.ShowOne):
|
|||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super(Update, self).get_parser(prog_name)
|
parser = super(Update, self).get_parser(prog_name)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument('id', help='Execution identifier')
|
||||||
'id',
|
|
||||||
help='Execution identifier'
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-s',
|
'-s',
|
||||||
|
@ -61,6 +61,7 @@ class List(base.MistralLister):
|
|||||||
|
|
||||||
def _get_resources(self, parsed_args):
|
def _get_resources(self, parsed_args):
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
return mistral_client.workbooks.list(
|
return mistral_client.workbooks.list(
|
||||||
marker=parsed_args.marker,
|
marker=parsed_args.marker,
|
||||||
limit=parsed_args.limit,
|
limit=parsed_args.limit,
|
||||||
@ -90,6 +91,7 @@ class Get(command.ShowOne):
|
|||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
workbook = mistral_client.workbooks.get(
|
workbook = mistral_client.workbooks.get(
|
||||||
parsed_args.workbook,
|
parsed_args.workbook,
|
||||||
parsed_args.namespace
|
parsed_args.namespace
|
||||||
@ -128,6 +130,7 @@ class Create(command.ShowOne):
|
|||||||
scope = 'public' if parsed_args.public else 'private'
|
scope = 'public' if parsed_args.public else 'private'
|
||||||
|
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
workbook = mistral_client.workbooks.create(
|
workbook = mistral_client.workbooks.create(
|
||||||
parsed_args.definition.read(),
|
parsed_args.definition.read(),
|
||||||
namespace=parsed_args.namespace,
|
namespace=parsed_args.namespace,
|
||||||
@ -155,9 +158,10 @@ class Delete(command.Command):
|
|||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
utils.do_action_on_many(
|
utils.do_action_on_many(
|
||||||
lambda s: mistral_client.workbooks.delete(s,
|
lambda s:
|
||||||
parsed_args.namespace),
|
mistral_client.workbooks.delete(s, parsed_args.namespace),
|
||||||
parsed_args.workbook,
|
parsed_args.workbook,
|
||||||
"Request to delete workbook %s has been accepted.",
|
"Request to delete workbook %s has been accepted.",
|
||||||
"Unable to delete the specified workbook(s)."
|
"Unable to delete the specified workbook(s)."
|
||||||
@ -193,6 +197,7 @@ class Update(command.ShowOne):
|
|||||||
scope = 'public' if parsed_args.public else 'private'
|
scope = 'public' if parsed_args.public else 'private'
|
||||||
|
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
workbook = mistral_client.workbooks.update(
|
workbook = mistral_client.workbooks.update(
|
||||||
parsed_args.definition.read(),
|
parsed_args.definition.read(),
|
||||||
namespace=parsed_args.namespace,
|
namespace=parsed_args.namespace,
|
||||||
@ -245,6 +250,7 @@ class Validate(command.ShowOne):
|
|||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
mistral_client = self.app.client_manager.workflow_engine
|
mistral_client = self.app.client_manager.workflow_engine
|
||||||
|
|
||||||
result = mistral_client.workbooks.validate(
|
result = mistral_client.workbooks.validate(
|
||||||
parsed_args.definition.read()
|
parsed_args.definition.read()
|
||||||
)
|
)
|
||||||
|
@ -29,7 +29,9 @@ from mistralclient.api import client
|
|||||||
from mistralclient.auth import auth_types
|
from mistralclient.auth import auth_types
|
||||||
import mistralclient.commands.v2.action_executions
|
import mistralclient.commands.v2.action_executions
|
||||||
import mistralclient.commands.v2.actions
|
import mistralclient.commands.v2.actions
|
||||||
|
import mistralclient.commands.v2.code_sources
|
||||||
import mistralclient.commands.v2.cron_triggers
|
import mistralclient.commands.v2.cron_triggers
|
||||||
|
import mistralclient.commands.v2.dynamic_actions
|
||||||
import mistralclient.commands.v2.environments
|
import mistralclient.commands.v2.environments
|
||||||
import mistralclient.commands.v2.event_triggers
|
import mistralclient.commands.v2.event_triggers
|
||||||
import mistralclient.commands.v2.executions
|
import mistralclient.commands.v2.executions
|
||||||
@ -581,12 +583,15 @@ class MistralShell(app.App):
|
|||||||
if (not self.options.project_domain_id and
|
if (not self.options.project_domain_id and
|
||||||
not self.options.project_domain_name):
|
not self.options.project_domain_name):
|
||||||
self.options.project_domain_id = "default"
|
self.options.project_domain_id = "default"
|
||||||
|
|
||||||
if (not self.options.user_domain_id and
|
if (not self.options.user_domain_id and
|
||||||
not self.options.user_domain_name):
|
not self.options.user_domain_name):
|
||||||
self.options.user_domain_id = "default"
|
self.options.user_domain_id = "default"
|
||||||
|
|
||||||
if (not self.options.target_project_domain_id and
|
if (not self.options.target_project_domain_id and
|
||||||
not self.options.target_project_domain_name):
|
not self.options.target_project_domain_name):
|
||||||
self.options.target_project_domain_id = "default"
|
self.options.target_project_domain_id = "default"
|
||||||
|
|
||||||
if (not self.options.target_user_domain_id and
|
if (not self.options.target_user_domain_id and
|
||||||
not self.options.target_user_domain_name):
|
not self.options.target_user_domain_name):
|
||||||
self.options.target_user_domain_id = "default"
|
self.options.target_user_domain_id = "default"
|
||||||
@ -603,6 +608,7 @@ class MistralShell(app.App):
|
|||||||
("You must provide a password "
|
("You must provide a password "
|
||||||
"via --os-password env[OS_PASSWORD]")
|
"via --os-password env[OS_PASSWORD]")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.client = self._create_client() if need_client else None
|
self.client = self._create_client() if need_client else None
|
||||||
|
|
||||||
# Adding client_manager variable to make mistral client work with
|
# Adding client_manager variable to make mistral client work with
|
||||||
@ -767,6 +773,26 @@ class MistralShell(app.App):
|
|||||||
'member-update': mistralclient.commands.v2.members.Update,
|
'member-update': mistralclient.commands.v2.members.Update,
|
||||||
'member-list': mistralclient.commands.v2.members.List,
|
'member-list': mistralclient.commands.v2.members.List,
|
||||||
'member-get': mistralclient.commands.v2.members.Get,
|
'member-get': mistralclient.commands.v2.members.Get,
|
||||||
|
'code-source-create':
|
||||||
|
mistralclient.commands.v2.code_sources.Create,
|
||||||
|
'code-source-get': mistralclient.commands.v2.code_sources.Get,
|
||||||
|
'code-source-update':
|
||||||
|
mistralclient.commands.v2.code_sources.Update,
|
||||||
|
'code-source-list': mistralclient.commands.v2.code_sources.List,
|
||||||
|
'code-source-delete':
|
||||||
|
mistralclient.commands.v2.code_sources.Delete,
|
||||||
|
'code-source-get-content':
|
||||||
|
mistralclient.commands.v2.code_sources.GetContent,
|
||||||
|
'dynamic-action-create':
|
||||||
|
mistralclient.commands.v2.dynamic_actions.Create,
|
||||||
|
'dynamic-action-get':
|
||||||
|
mistralclient.commands.v2.dynamic_actions.Get,
|
||||||
|
'dynamic-action-update':
|
||||||
|
mistralclient.commands.v2.dynamic_actions.Update,
|
||||||
|
'dynamic-action-list':
|
||||||
|
mistralclient.commands.v2.dynamic_actions.List,
|
||||||
|
'dynamic-action-delete':
|
||||||
|
mistralclient.commands.v2.dynamic_actions.Delete,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,9 +71,11 @@ URL_TEMPLATE_VALIDATE = '/workbooks/validate'
|
|||||||
|
|
||||||
class TestWorkbooksV2(base.BaseClientV2Test):
|
class TestWorkbooksV2(base.BaseClientV2Test):
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
|
self.requests_mock.post(
|
||||||
json=WORKBOOK,
|
self.TEST_URL + URL_TEMPLATE,
|
||||||
status_code=201)
|
json=WORKBOOK,
|
||||||
|
status_code=201
|
||||||
|
)
|
||||||
|
|
||||||
wb = self.workbooks.create(WB_DEF)
|
wb = self.workbooks.create(WB_DEF)
|
||||||
|
|
||||||
@ -86,9 +88,11 @@ class TestWorkbooksV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual('text/plain', last_request.headers['content-type'])
|
self.assertEqual('text/plain', last_request.headers['content-type'])
|
||||||
|
|
||||||
def test_create_with_file_uri(self):
|
def test_create_with_file_uri(self):
|
||||||
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
|
self.requests_mock.post(
|
||||||
json=WORKBOOK,
|
self.TEST_URL + URL_TEMPLATE,
|
||||||
status_code=201)
|
json=WORKBOOK,
|
||||||
|
status_code=201
|
||||||
|
)
|
||||||
|
|
||||||
# The contents of wb_v2.yaml must be identical to WB_DEF
|
# The contents of wb_v2.yaml must be identical to WB_DEF
|
||||||
path = pkg.resource_filename(
|
path = pkg.resource_filename(
|
||||||
@ -143,8 +147,10 @@ class TestWorkbooksV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual('text/plain', last_request.headers['content-type'])
|
self.assertEqual('text/plain', last_request.headers['content-type'])
|
||||||
|
|
||||||
def test_list(self):
|
def test_list(self):
|
||||||
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
|
self.requests_mock.get(
|
||||||
json={'workbooks': [WORKBOOK]})
|
self.TEST_URL + URL_TEMPLATE,
|
||||||
|
json={'workbooks': [WORKBOOK]}
|
||||||
|
)
|
||||||
|
|
||||||
workbook_list = self.workbooks.list()
|
workbook_list = self.workbooks.list()
|
||||||
|
|
||||||
@ -158,8 +164,10 @@ class TestWorkbooksV2(base.BaseClientV2Test):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_get(self):
|
def test_get(self):
|
||||||
url = self.TEST_URL + URL_TEMPLATE_NAME % 'wb'
|
self.requests_mock.get(
|
||||||
self.requests_mock.get(url, json=WORKBOOK)
|
self.TEST_URL + URL_TEMPLATE_NAME % 'wb',
|
||||||
|
json=WORKBOOK
|
||||||
|
)
|
||||||
|
|
||||||
wb = self.workbooks.get('wb')
|
wb = self.workbooks.get('wb')
|
||||||
|
|
||||||
@ -176,8 +184,10 @@ class TestWorkbooksV2(base.BaseClientV2Test):
|
|||||||
self.workbooks.delete('wb')
|
self.workbooks.delete('wb')
|
||||||
|
|
||||||
def test_validate(self):
|
def test_validate(self):
|
||||||
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
|
self.requests_mock.post(
|
||||||
json={'valid': True})
|
self.TEST_URL + URL_TEMPLATE_VALIDATE,
|
||||||
|
json={'valid': True}
|
||||||
|
)
|
||||||
|
|
||||||
result = self.workbooks.validate(WB_DEF)
|
result = self.workbooks.validate(WB_DEF)
|
||||||
|
|
||||||
@ -191,8 +201,10 @@ class TestWorkbooksV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual('text/plain', last_request.headers['content-type'])
|
self.assertEqual('text/plain', last_request.headers['content-type'])
|
||||||
|
|
||||||
def test_validate_with_file(self):
|
def test_validate_with_file(self):
|
||||||
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
|
self.requests_mock.post(
|
||||||
json={'valid': True})
|
self.TEST_URL + URL_TEMPLATE_VALIDATE,
|
||||||
|
json={'valid': True}
|
||||||
|
)
|
||||||
|
|
||||||
# The contents of wb_v2.yaml must be identical to WB_DEF
|
# The contents of wb_v2.yaml must be identical to WB_DEF
|
||||||
path = pkg.resource_filename(
|
path = pkg.resource_filename(
|
||||||
@ -218,8 +230,10 @@ class TestWorkbooksV2(base.BaseClientV2Test):
|
|||||||
"can't be specified both"
|
"can't be specified both"
|
||||||
}
|
}
|
||||||
|
|
||||||
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
|
self.requests_mock.post(
|
||||||
json=mock_result)
|
self.TEST_URL + URL_TEMPLATE_VALIDATE,
|
||||||
|
json=mock_result
|
||||||
|
)
|
||||||
|
|
||||||
result = self.workbooks.validate(INVALID_WB_DEF)
|
result = self.workbooks.validate(INVALID_WB_DEF)
|
||||||
|
|
||||||
@ -238,8 +252,10 @@ class TestWorkbooksV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual('text/plain', last_request.headers['content-type'])
|
self.assertEqual('text/plain', last_request.headers['content-type'])
|
||||||
|
|
||||||
def test_validate_api_failed(self):
|
def test_validate_api_failed(self):
|
||||||
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
|
self.requests_mock.post(
|
||||||
status_code=500)
|
self.TEST_URL + URL_TEMPLATE_VALIDATE,
|
||||||
|
status_code=500
|
||||||
|
)
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
api_base.APIException,
|
api_base.APIException,
|
||||||
|
@ -47,9 +47,11 @@ URL_TEMPLATE_NAME = '/workflows/%s'
|
|||||||
|
|
||||||
class TestWorkflowsV2(base.BaseClientV2Test):
|
class TestWorkflowsV2(base.BaseClientV2Test):
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_SCOPE,
|
self.requests_mock.post(
|
||||||
json={'workflows': [WORKFLOW]},
|
self.TEST_URL + URL_TEMPLATE_SCOPE,
|
||||||
status_code=201)
|
json={'workflows': [WORKFLOW]},
|
||||||
|
status_code=201
|
||||||
|
)
|
||||||
|
|
||||||
wfs = self.workflows.create(WF_DEF)
|
wfs = self.workflows.create(WF_DEF)
|
||||||
|
|
||||||
@ -62,9 +64,11 @@ class TestWorkflowsV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual('text/plain', last_request.headers['content-type'])
|
self.assertEqual('text/plain', last_request.headers['content-type'])
|
||||||
|
|
||||||
def test_create_with_file(self):
|
def test_create_with_file(self):
|
||||||
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_SCOPE,
|
self.requests_mock.post(
|
||||||
json={'workflows': [WORKFLOW]},
|
self.TEST_URL + URL_TEMPLATE_SCOPE,
|
||||||
status_code=201)
|
json={'workflows': [WORKFLOW]},
|
||||||
|
status_code=201
|
||||||
|
)
|
||||||
|
|
||||||
# The contents of wf_v2.yaml must be identical to WF_DEF
|
# The contents of wf_v2.yaml must be identical to WF_DEF
|
||||||
path = pkg.resource_filename(
|
path = pkg.resource_filename(
|
||||||
@ -83,8 +87,10 @@ class TestWorkflowsV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual('text/plain', last_request.headers['content-type'])
|
self.assertEqual('text/plain', last_request.headers['content-type'])
|
||||||
|
|
||||||
def test_update(self):
|
def test_update(self):
|
||||||
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_SCOPE,
|
self.requests_mock.put(
|
||||||
json={'workflows': [WORKFLOW]})
|
self.TEST_URL + URL_TEMPLATE_SCOPE,
|
||||||
|
json={'workflows': [WORKFLOW]}
|
||||||
|
)
|
||||||
|
|
||||||
wfs = self.workflows.update(WF_DEF)
|
wfs = self.workflows.update(WF_DEF)
|
||||||
|
|
||||||
@ -97,8 +103,10 @@ class TestWorkflowsV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual('text/plain', last_request.headers['content-type'])
|
self.assertEqual('text/plain', last_request.headers['content-type'])
|
||||||
|
|
||||||
def test_update_with_id(self):
|
def test_update_with_id(self):
|
||||||
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_NAME % '123',
|
self.requests_mock.put(
|
||||||
json=WORKFLOW)
|
self.TEST_URL + URL_TEMPLATE_NAME % '123',
|
||||||
|
json=WORKFLOW
|
||||||
|
)
|
||||||
|
|
||||||
wf = self.workflows.update(WF_DEF, id='123')
|
wf = self.workflows.update(WF_DEF, id='123')
|
||||||
|
|
||||||
@ -112,8 +120,10 @@ class TestWorkflowsV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual('text/plain', last_request.headers['content-type'])
|
self.assertEqual('text/plain', last_request.headers['content-type'])
|
||||||
|
|
||||||
def test_update_with_file_uri(self):
|
def test_update_with_file_uri(self):
|
||||||
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_SCOPE,
|
self.requests_mock.put(
|
||||||
json={'workflows': [WORKFLOW]})
|
self.TEST_URL + URL_TEMPLATE_SCOPE,
|
||||||
|
json={'workflows': [WORKFLOW]}
|
||||||
|
)
|
||||||
|
|
||||||
# The contents of wf_v2.yaml must be identical to WF_DEF
|
# The contents of wf_v2.yaml must be identical to WF_DEF
|
||||||
path = pkg.resource_filename(
|
path = pkg.resource_filename(
|
||||||
@ -136,8 +146,10 @@ class TestWorkflowsV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual('text/plain', last_request.headers['content-type'])
|
self.assertEqual('text/plain', last_request.headers['content-type'])
|
||||||
|
|
||||||
def test_list(self):
|
def test_list(self):
|
||||||
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
|
self.requests_mock.get(
|
||||||
json={'workflows': [WORKFLOW]})
|
self.TEST_URL + URL_TEMPLATE,
|
||||||
|
json={'workflows': [WORKFLOW]}
|
||||||
|
)
|
||||||
|
|
||||||
workflows_list = self.workflows.list()
|
workflows_list = self.workflows.list()
|
||||||
|
|
||||||
@ -151,9 +163,13 @@ class TestWorkflowsV2(base.BaseClientV2Test):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_list_with_pagination(self):
|
def test_list_with_pagination(self):
|
||||||
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
|
self.requests_mock.get(
|
||||||
json={'workflows': [WORKFLOW],
|
self.TEST_URL + URL_TEMPLATE,
|
||||||
'next': '/workflows?fake'})
|
json={
|
||||||
|
'workflows': [WORKFLOW],
|
||||||
|
'next': '/workflows?fake'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
workflows_list = self.workflows.list(
|
workflows_list = self.workflows.list(
|
||||||
limit=1,
|
limit=1,
|
||||||
@ -171,8 +187,10 @@ class TestWorkflowsV2(base.BaseClientV2Test):
|
|||||||
self.assertEqual(['asc'], last_request.qs['sort_dirs'])
|
self.assertEqual(['asc'], last_request.qs['sort_dirs'])
|
||||||
|
|
||||||
def test_list_with_no_limit(self):
|
def test_list_with_no_limit(self):
|
||||||
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
|
self.requests_mock.get(
|
||||||
json={'workflows': [WORKFLOW]})
|
self.TEST_URL + URL_TEMPLATE,
|
||||||
|
json={'workflows': [WORKFLOW]}
|
||||||
|
)
|
||||||
|
|
||||||
workflows_list = self.workflows.list(limit=-1)
|
workflows_list = self.workflows.list(limit=-1)
|
||||||
|
|
||||||
@ -184,6 +202,7 @@ class TestWorkflowsV2(base.BaseClientV2Test):
|
|||||||
|
|
||||||
def test_get(self):
|
def test_get(self):
|
||||||
url = self.TEST_URL + URL_TEMPLATE_NAME % 'wf'
|
url = self.TEST_URL + URL_TEMPLATE_NAME % 'wf'
|
||||||
|
|
||||||
self.requests_mock.get(url, json=WORKFLOW)
|
self.requests_mock.get(url, json=WORKFLOW)
|
||||||
|
|
||||||
wf = self.workflows.get('wf')
|
wf = self.workflows.get('wf')
|
||||||
@ -195,7 +214,9 @@ class TestWorkflowsV2(base.BaseClientV2Test):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
url = self.TEST_URL + URL_TEMPLATE_NAME % 'wf'
|
self.requests_mock.delete(
|
||||||
self.requests_mock.delete(url, status_code=204)
|
self.TEST_URL + URL_TEMPLATE_NAME % 'wf',
|
||||||
|
status_code=204
|
||||||
|
)
|
||||||
|
|
||||||
self.workflows.delete('wf')
|
self.workflows.delete('wf')
|
||||||
|
@ -31,6 +31,7 @@ def do_action_on_many(action, resources, success_msg, error_msg):
|
|||||||
for resource in resources:
|
for resource in resources:
|
||||||
try:
|
try:
|
||||||
action(resource)
|
action(resource)
|
||||||
|
|
||||||
print(success_msg % resource)
|
print(success_msg % resource)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
failure_flag = True
|
failure_flag = True
|
||||||
@ -73,10 +74,9 @@ def get_contents_if_file(contents_or_file_name):
|
|||||||
definition_url = contents_or_file_name
|
definition_url = contents_or_file_name
|
||||||
else:
|
else:
|
||||||
path = os.path.abspath(contents_or_file_name)
|
path = os.path.abspath(contents_or_file_name)
|
||||||
definition_url = parse.urljoin(
|
|
||||||
'file:',
|
definition_url = parse.urljoin('file:', request.pathname2url(path))
|
||||||
request.pathname2url(path)
|
|
||||||
)
|
|
||||||
return request.urlopen(definition_url).read().decode('utf8')
|
return request.urlopen(definition_url).read().decode('utf8')
|
||||||
except Exception:
|
except Exception:
|
||||||
return contents_or_file_name
|
return contents_or_file_name
|
||||||
|
14
setup.cfg
14
setup.cfg
@ -104,6 +104,20 @@ openstack.workflow_engine.v2 =
|
|||||||
resource_member_delete = mistralclient.commands.v2.members:Delete
|
resource_member_delete = mistralclient.commands.v2.members:Delete
|
||||||
resource_member_update = mistralclient.commands.v2.members:Update
|
resource_member_update = mistralclient.commands.v2.members:Update
|
||||||
|
|
||||||
|
code_source_list = mistralclient.commands.v2.code_sources:List
|
||||||
|
code_source_show = mistralclient.commands.v2.code_sources:Get
|
||||||
|
code_source_create = mistralclient.commands.v2.code_sources:Create
|
||||||
|
code_source_delete = mistralclient.commands.v2.code_sources:Delete
|
||||||
|
code_source_update = mistralclient.commands.v2.code_sources:Update
|
||||||
|
code_source_content_show = mistralclient.commands.v2.code_sources:GetContent
|
||||||
|
|
||||||
|
dynamic_action_list = mistralclient.commands.v2.dynamic_actions:List
|
||||||
|
dynamic_action_show = mistralclient.commands.v2.dynamic_actions:Get
|
||||||
|
dynamic_action_create = mistralclient.commands.v2.dynamic_actions:Create
|
||||||
|
dynamic_action_delete = mistralclient.commands.v2.dynamic_actions:Delete
|
||||||
|
dynamic_action_update = mistralclient.commands.v2.dynamic_actions:Update
|
||||||
|
|
||||||
|
|
||||||
mistralclient.auth =
|
mistralclient.auth =
|
||||||
# Standard Keystone authentication.
|
# Standard Keystone authentication.
|
||||||
keystone = mistralclient.auth.keystone:KeystoneAuthHandler
|
keystone = mistralclient.auth.keystone:KeystoneAuthHandler
|
||||||
|
Loading…
x
Reference in New Issue
Block a user