Add "fields" filter support on single objects
Change-Id: Iba0401445921f9ea7932628c05590472307ba83a Closes-Bug: #1718214 Signed-off-by: Xavier Hardy <xavier.hardy@corp.ovh.com> Co-Authored-By: Oleg Ovcharuk <vgvoleg@gmail.com> Signed-off-by: Oleg Ovcharuk <vgvoleg@gmail.com>
This commit is contained in:
parent
c820d6f365
commit
9c5324ce9a
|
@ -51,8 +51,13 @@ class Resource(wtypes.Base):
|
||||||
return cls.from_tuples(d.items())
|
return cls.from_tuples(d.items())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_db_model(cls, db_model):
|
def from_db_model(cls, db_model, fields=()):
|
||||||
return cls.from_tuples(db_model.iter_columns())
|
if isinstance(db_model, tuple):
|
||||||
|
db_tuples = zip(fields, db_model)
|
||||||
|
else:
|
||||||
|
db_tuples = db_model.iter_columns(fields=fields)
|
||||||
|
|
||||||
|
return cls.from_tuples(db_tuples)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""WSME based implementation of __str__."""
|
"""WSME based implementation of __str__."""
|
||||||
|
|
|
@ -79,6 +79,9 @@ class ActionsController(rest.RestController, hooks.HookController):
|
||||||
|
|
||||||
:param identifier: ID or name of the Action to get.
|
:param identifier: ID or name of the Action to get.
|
||||||
:param namespace: The namespace of the action.
|
:param namespace: The namespace of the action.
|
||||||
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
|
be returned. 'id' will be included automatically in
|
||||||
|
fields if it's not provided.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
acl.enforce('actions:get', context.ctx())
|
acl.enforce('actions:get', context.ctx())
|
||||||
|
@ -251,7 +254,7 @@ class ActionsController(rest.RestController, hooks.HookController):
|
||||||
Default: asc.
|
Default: asc.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param name: Optional. Keep only resources with a specific name.
|
:param name: Optional. Keep only resources with a specific name.
|
||||||
:param scope: Optional. Keep only resources with a specific scope.
|
:param scope: Optional. Keep only resources with a specific scope.
|
||||||
|
|
|
@ -52,25 +52,40 @@ def _load_deferred_output_field(action_ex):
|
||||||
|
|
||||||
# Use retries to prevent possible failures.
|
# Use retries to prevent possible failures.
|
||||||
@rest_utils.rest_retry_on_db_error
|
@rest_utils.rest_retry_on_db_error
|
||||||
def _get_action_execution(id):
|
def _get_action_execution(id, fields=()):
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
with db_api.transaction():
|
with db_api.transaction():
|
||||||
return _get_action_execution_resource(db_api.get_action_execution(id))
|
return _get_action_execution_resource(
|
||||||
|
db_api.get_action_execution(id),
|
||||||
|
fields=fields
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _get_action_execution_resource(action_ex):
|
def _get_action_execution_resource(action_ex, fields=()):
|
||||||
_load_deferred_output_field(action_ex)
|
_load_deferred_output_field(action_ex)
|
||||||
|
|
||||||
return _get_action_execution_resource_for_list(action_ex)
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
|
return _get_action_execution_resource_for_list(action_ex, fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def _get_action_execution_resource_for_list(action_ex):
|
def _get_action_execution_resource_for_list(action_ex, fields=()):
|
||||||
# TODO(nmakhotkin): Get rid of using dicts for constructing resources.
|
# TODO(nmakhotkin): Get rid of using dicts for constructing resources.
|
||||||
# TODO(nmakhotkin): Use db_model for this instead.
|
# TODO(nmakhotkin): Use db_model for this instead.
|
||||||
res = resources.ActionExecution.from_db_model(action_ex)
|
|
||||||
|
|
||||||
task_name = (action_ex.task_execution.name
|
# field_task_name_needed = 'task_name' in fields
|
||||||
if action_ex.task_execution else None)
|
# if field_task_name_needed:
|
||||||
setattr(res, 'task_name', task_name)
|
# fields.remove('task_name')
|
||||||
|
|
||||||
|
res = resources.ActionExecution.from_db_model(action_ex, fields=fields)
|
||||||
|
|
||||||
|
# if not fields or field_task_name_needed:
|
||||||
|
# task_name = (action_ex.task_execution.name
|
||||||
|
# if action_ex.task_execution else None)
|
||||||
|
# setattr(res, 'task_name', task_name)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -95,7 +110,7 @@ def _get_action_executions(task_execution_id=None, marker=None, limit=None,
|
||||||
or less than that of sort_keys.
|
or less than that of sort_keys.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param filters: Optional. A list of filters to apply to the result.
|
:param filters: Optional. A list of filters to apply to the result.
|
||||||
"""
|
"""
|
||||||
|
@ -124,17 +139,21 @@ def _get_action_executions(task_execution_id=None, marker=None, limit=None,
|
||||||
|
|
||||||
class ActionExecutionsController(rest.RestController):
|
class ActionExecutionsController(rest.RestController):
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.ActionExecution, wtypes.text)
|
@wsme_pecan.wsexpose(resources.ActionExecution, wtypes.text,
|
||||||
def get(self, id):
|
types.uniquelist)
|
||||||
|
def get(self, id, fields=None):
|
||||||
"""Return the specified action_execution.
|
"""Return the specified action_execution.
|
||||||
|
|
||||||
:param id: UUID of action execution to retrieve
|
:param id: UUID of action execution to retrieve
|
||||||
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
|
be returned. 'id' will be included automatically in
|
||||||
|
fields if it's not provided.
|
||||||
"""
|
"""
|
||||||
acl.enforce('action_executions:get', context.ctx())
|
acl.enforce('action_executions:get', context.ctx())
|
||||||
|
|
||||||
LOG.debug("Fetch action_execution [id=%s]", id)
|
LOG.debug("Fetch action_execution [id=%s]", id)
|
||||||
|
|
||||||
return _get_action_execution(id)
|
return _get_action_execution(id, fields=fields)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.ActionExecution,
|
@wsme_pecan.wsexpose(resources.ActionExecution,
|
||||||
|
@ -248,7 +267,7 @@ class ActionExecutionsController(rest.RestController):
|
||||||
or less than that of sort_keys.
|
or less than that of sort_keys.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param name: Optional. Keep only resources with a specific name.
|
:param name: Optional. Keep only resources with a specific name.
|
||||||
:param workflow_name: Optional. Keep only resources with a specific
|
:param workflow_name: Optional. Keep only resources with a specific
|
||||||
|
@ -379,7 +398,7 @@ class TasksActionExecutionController(rest.RestController):
|
||||||
or less than that of sort_keys.
|
or less than that of sort_keys.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param name: Optional. Keep only resources with a specific name.
|
:param name: Optional. Keep only resources with a specific name.
|
||||||
:param workflow_name: Optional. Keep only resources with a specific
|
:param workflow_name: Optional. Keep only resources with a specific
|
||||||
|
@ -444,15 +463,19 @@ class TasksActionExecutionController(rest.RestController):
|
||||||
)
|
)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.ActionExecution, wtypes.text, wtypes.text)
|
@wsme_pecan.wsexpose(resources.ActionExecution, wtypes.text, wtypes.text,
|
||||||
def get(self, task_execution_id, action_ex_id):
|
types.uniquelist)
|
||||||
|
def get(self, task_execution_id, action_ex_id, fields=()):
|
||||||
"""Return the specified action_execution.
|
"""Return the specified action_execution.
|
||||||
|
|
||||||
:param task_execution_id: Task execution UUID
|
:param task_execution_id: Task execution UUID
|
||||||
:param action_ex_id: Action execution UUID
|
:param action_ex_id: Action execution UUID
|
||||||
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
|
be returned. 'id' will be included automatically in
|
||||||
|
fields if it's not provided.
|
||||||
"""
|
"""
|
||||||
acl.enforce('action_executions:get', context.ctx())
|
acl.enforce('action_executions:get', context.ctx())
|
||||||
|
|
||||||
LOG.debug("Fetch action_execution [id=%s]", action_ex_id)
|
LOG.debug("Fetch action_execution [id=%s]", action_ex_id)
|
||||||
|
|
||||||
return _get_action_execution(action_ex_id)
|
return _get_action_execution(action_ex_id, fields=fields)
|
||||||
|
|
|
@ -187,8 +187,9 @@ class CodeSourcesController(rest.RestController, hooks.HookController):
|
||||||
)
|
)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.CodeSource, wtypes.text, wtypes.text)
|
@wsme_pecan.wsexpose(resources.CodeSource, wtypes.text,
|
||||||
def get(self, identifier, namespace=''):
|
wtypes.text, types.uniquelist)
|
||||||
|
def get(self, identifier, namespace='', fields=''):
|
||||||
"""Return a code source.
|
"""Return a code source.
|
||||||
|
|
||||||
:param identifier: Name or UUID of the code source to retrieve.
|
:param identifier: Name or UUID of the code source to retrieve.
|
||||||
|
@ -202,13 +203,17 @@ class CodeSourcesController(rest.RestController, hooks.HookController):
|
||||||
identifier,
|
identifier,
|
||||||
namespace
|
namespace
|
||||||
)
|
)
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
db_model = rest_utils.rest_retry_on_db_error(
|
db_model = rest_utils.rest_retry_on_db_error(
|
||||||
db_api.get_code_source)(
|
db_api.get_code_source)(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
namespace=namespace
|
namespace=namespace,
|
||||||
|
fields=fields
|
||||||
)
|
)
|
||||||
|
if fields:
|
||||||
|
return resources.CodeSource.from_tuples(zip(fields, db_model))
|
||||||
return resources.CodeSource.from_db_model(db_model)
|
return resources.CodeSource.from_db_model(db_model)
|
||||||
|
|
||||||
@rest_utils.wrap_pecan_controller_exception
|
@rest_utils.wrap_pecan_controller_exception
|
||||||
|
|
|
@ -31,22 +31,30 @@ LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
class CronTriggersController(rest.RestController):
|
class CronTriggersController(rest.RestController):
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.CronTrigger, wtypes.text)
|
@wsme_pecan.wsexpose(resources.CronTrigger,
|
||||||
def get(self, identifier):
|
wtypes.text, types.uniquelist)
|
||||||
|
def get(self, identifier, fields=''):
|
||||||
"""Returns the named cron_trigger.
|
"""Returns the named cron_trigger.
|
||||||
|
|
||||||
:param identifier: Id or name of cron trigger to retrieve
|
:param identifier: Id or name of cron trigger to retrieve
|
||||||
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
|
be returned. 'id' will be included automatically in
|
||||||
|
fields if it's not provided.
|
||||||
"""
|
"""
|
||||||
acl.enforce('cron_triggers:get', context.ctx())
|
acl.enforce('cron_triggers:get', context.ctx())
|
||||||
|
|
||||||
LOG.debug('Fetch cron trigger [identifier=%s]', identifier)
|
LOG.debug('Fetch cron trigger [identifier=%s]', identifier)
|
||||||
|
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
# Use retries to prevent possible failures.
|
# Use retries to prevent possible failures.
|
||||||
db_model = rest_utils.rest_retry_on_db_error(
|
db_model = rest_utils.rest_retry_on_db_error(
|
||||||
db_api.get_cron_trigger
|
db_api.get_cron_trigger
|
||||||
)(identifier)
|
)(identifier, fields=fields)
|
||||||
|
if fields:
|
||||||
return resources.CronTrigger.from_db_model(db_model)
|
return resources.CronTrigger.from_tuples(zip(fields, db_model))
|
||||||
|
return resources.CronTrigger.from_db_model(db_model, fields=fields)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(
|
@wsme_pecan.wsexpose(
|
||||||
|
@ -124,7 +132,7 @@ class CronTriggersController(rest.RestController):
|
||||||
or less than that of sort_keys.
|
or less than that of sort_keys.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param name: Optional. Keep only resources with a specific name.
|
:param name: Optional. Keep only resources with a specific name.
|
||||||
:param workflow_name: Optional. Keep only resources with a specific
|
:param workflow_name: Optional. Keep only resources with a specific
|
||||||
|
|
|
@ -208,8 +208,9 @@ class DynamicActionsController(rest.RestController, hooks.HookController):
|
||||||
)
|
)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.DynamicAction, wtypes.text, wtypes.text)
|
@wsme_pecan.wsexpose(resources.DynamicAction, wtypes.text,
|
||||||
def get(self, identifier, namespace=''):
|
wtypes.text, types.uniquelist)
|
||||||
|
def get(self, identifier, namespace='', fields=''):
|
||||||
"""Return the named action.
|
"""Return the named action.
|
||||||
|
|
||||||
:param identifier: Name or UUID of the action to retrieve.
|
:param identifier: Name or UUID of the action to retrieve.
|
||||||
|
@ -222,14 +223,19 @@ class DynamicActionsController(rest.RestController, hooks.HookController):
|
||||||
identifier,
|
identifier,
|
||||||
namespace
|
namespace
|
||||||
)
|
)
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
db_model = rest_utils.rest_retry_on_db_error(
|
db_model = rest_utils.rest_retry_on_db_error(
|
||||||
db_api.get_dynamic_action_definition
|
db_api.get_dynamic_action_definition
|
||||||
)(
|
)(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
namespace=namespace
|
namespace=namespace,
|
||||||
|
fields=fields
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if fields:
|
||||||
|
return resources.DynamicAction.from_tuples(zip(fields, db_model))
|
||||||
return resources.DynamicAction.from_db_model(db_model)
|
return resources.DynamicAction.from_db_model(db_model)
|
||||||
|
|
||||||
@rest_utils.wrap_pecan_controller_exception
|
@rest_utils.wrap_pecan_controller_exception
|
||||||
|
|
|
@ -59,7 +59,7 @@ class EnvironmentController(rest.RestController):
|
||||||
or less than that of sort_keys.
|
or less than that of sort_keys.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param name: Optional. Keep only resources with a specific name.
|
:param name: Optional. Keep only resources with a specific name.
|
||||||
:param description: Optional. Keep only resources with a specific
|
:param description: Optional. Keep only resources with a specific
|
||||||
|
@ -101,21 +101,28 @@ class EnvironmentController(rest.RestController):
|
||||||
)
|
)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.Environment, wtypes.text)
|
@wsme_pecan.wsexpose(resources.Environment, wtypes.text, types.uniquelist)
|
||||||
def get(self, name):
|
def get(self, name, fields=''):
|
||||||
"""Return the named environment.
|
"""Return the named environment.
|
||||||
|
|
||||||
:param name: Name of environment to retrieve
|
:param name: Name of environment to retrieve
|
||||||
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
|
be returned. 'id' will be included automatically in
|
||||||
|
fields if it's not provided.
|
||||||
"""
|
"""
|
||||||
acl.enforce('environments:get', context.ctx())
|
acl.enforce('environments:get', context.ctx())
|
||||||
|
|
||||||
LOG.debug("Fetch environment [name=%s]", name)
|
LOG.debug("Fetch environment [name=%s]", name)
|
||||||
|
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
# Use retries to prevent possible failures.
|
# Use retries to prevent possible failures.
|
||||||
r = rest_utils.create_db_retry_object()
|
r = rest_utils.create_db_retry_object()
|
||||||
db_model = r.call(db_api.get_environment, name)
|
db_model = r.call(db_api.get_environment, name, fields=fields)
|
||||||
|
if fields:
|
||||||
return resources.Environment.from_db_model(db_model)
|
return resources.Environment.from_tuples(zip(fields, db_model))
|
||||||
|
return resources.Environment.from_db_model(db_model, fields=fields)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(
|
@wsme_pecan.wsexpose(
|
||||||
|
|
|
@ -34,18 +34,22 @@ CREATE_MANDATORY = set(['exchange', 'topic', 'event', 'workflow_id'])
|
||||||
|
|
||||||
class EventTriggersController(rest.RestController):
|
class EventTriggersController(rest.RestController):
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.EventTrigger, types.uuid)
|
@wsme_pecan.wsexpose(resources.EventTrigger, types.uuid, types.uniquelist)
|
||||||
def get(self, id):
|
def get(self, id, fields=''):
|
||||||
"""Returns the specified event_trigger."""
|
"""Returns the specified event_trigger."""
|
||||||
acl.enforce('event_triggers:get', auth_ctx.ctx())
|
acl.enforce('event_triggers:get', auth_ctx.ctx())
|
||||||
|
|
||||||
LOG.debug('Fetch event trigger [id=%s]', id)
|
LOG.debug('Fetch event trigger [id=%s]', id)
|
||||||
|
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
# Use retries to prevent possible failures.
|
# Use retries to prevent possible failures.
|
||||||
r = rest_utils.create_db_retry_object()
|
r = rest_utils.create_db_retry_object()
|
||||||
db_model = r.call(db_api.get_event_trigger, id)
|
db_model = r.call(db_api.get_event_trigger, id, fields=fields)
|
||||||
|
if fields:
|
||||||
return resources.EventTrigger.from_db_model(db_model)
|
return resources.EventTrigger.from_tuples(zip(fields, db_model))
|
||||||
|
return resources.EventTrigger.from_db_model(db_model, fields=fields)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.EventTrigger, body=resources.EventTrigger,
|
@wsme_pecan.wsexpose(resources.EventTrigger, body=resources.EventTrigger,
|
||||||
|
|
|
@ -68,12 +68,20 @@ def _get_workflow_execution_resource(wf_ex):
|
||||||
|
|
||||||
# Use retries to prevent possible failures.
|
# Use retries to prevent possible failures.
|
||||||
@rest_utils.rest_retry_on_db_error
|
@rest_utils.rest_retry_on_db_error
|
||||||
def _get_workflow_execution(id, must_exist=True):
|
def _get_workflow_execution(id, must_exist=True, fields=None):
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
|
fields_tuple = rest_utils.fields_list_to_cls_fields_tuple(
|
||||||
|
db_models.WorkflowExecution,
|
||||||
|
fields
|
||||||
|
)
|
||||||
|
|
||||||
with db_api.transaction():
|
with db_api.transaction():
|
||||||
if must_exist:
|
if must_exist:
|
||||||
wf_ex = db_api.get_workflow_execution(id)
|
wf_ex = db_api.get_workflow_execution(id, fields=fields_tuple)
|
||||||
else:
|
else:
|
||||||
wf_ex = db_api.load_workflow_execution(id)
|
wf_ex = db_api.load_workflow_execution(id, fields=fields_tuple)
|
||||||
|
|
||||||
return rest_utils.load_deferred_fields(
|
return rest_utils.load_deferred_fields(
|
||||||
wf_ex,
|
wf_ex,
|
||||||
|
@ -90,19 +98,25 @@ class ExecutionsController(rest.RestController):
|
||||||
executions = sub_execution.SubExecutionsController()
|
executions = sub_execution.SubExecutionsController()
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.Execution, wtypes.text)
|
@wsme_pecan.wsexpose(resources.Execution, wtypes.text, types.uniquelist)
|
||||||
def get(self, id):
|
def get(self, id, fields=None):
|
||||||
"""Return the specified Execution.
|
"""Return the specified Execution.
|
||||||
|
|
||||||
:param id: UUID of execution to retrieve.
|
:param id: UUID of execution to retrieve.
|
||||||
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
|
be returned. 'id' will be included automatically in
|
||||||
|
fields if it's not provided.
|
||||||
"""
|
"""
|
||||||
acl.enforce("executions:get", context.ctx())
|
acl.enforce("executions:get", context.ctx())
|
||||||
|
|
||||||
LOG.debug("Fetch execution [id=%s]", id)
|
LOG.debug("Fetch execution [id=%s]", id)
|
||||||
|
|
||||||
wf_ex = _get_workflow_execution(id)
|
wf_ex = _get_workflow_execution(id, fields=fields)
|
||||||
|
|
||||||
resource = resources.Execution.from_db_model(wf_ex)
|
if fields:
|
||||||
|
return resources.Execution.from_tuples(zip(fields, wf_ex))
|
||||||
|
|
||||||
|
resource = resources.Execution.from_db_model(wf_ex, fields=fields)
|
||||||
|
|
||||||
resource.published_global = (
|
resource.published_global = (
|
||||||
data_flow.get_workflow_execution_published_global(wf_ex)
|
data_flow.get_workflow_execution_published_global(wf_ex)
|
||||||
|
@ -363,7 +377,7 @@ class ExecutionsController(rest.RestController):
|
||||||
or less than that of sort_keys.
|
or less than that of sort_keys.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param workflow_name: Optional. Keep only resources with a specific
|
:param workflow_name: Optional. Keep only resources with a specific
|
||||||
workflow name.
|
workflow name.
|
||||||
|
|
|
@ -159,8 +159,8 @@ class Workflow(resource.Resource, ScopedResource):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_db_model(cls, db_model):
|
def from_db_model(cls, db_model, fields=()):
|
||||||
obj = super(Workflow, cls).from_db_model(db_model)
|
obj = super(Workflow, cls).from_db_model(db_model, fields=fields)
|
||||||
|
|
||||||
obj.set_attributes_from_spec(db_model.get('spec'))
|
obj.set_attributes_from_spec(db_model.get('spec'))
|
||||||
|
|
||||||
|
|
|
@ -49,19 +49,22 @@ STATE_TYPES = wtypes.Enum(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _get_task_resource_with_result(task_ex):
|
def _get_task_resource_with_result(task_ex, fields=()):
|
||||||
task = resources.Task.from_db_model(task_ex)
|
task = resources.Task.from_db_model(task_ex, fields=fields)
|
||||||
|
if 'result' in fields or not fields:
|
||||||
task.result = json.dumps(data_flow.get_task_execution_result(task_ex))
|
task.result = json.dumps(data_flow.get_task_execution_result(task_ex))
|
||||||
|
|
||||||
return task
|
return task
|
||||||
|
|
||||||
|
|
||||||
# Use retries to prevent possible failures.
|
# Use retries to prevent possible failures.
|
||||||
@rest_utils.rest_retry_on_db_error
|
@rest_utils.rest_retry_on_db_error
|
||||||
def _get_task_execution(id):
|
def _get_task_execution(id, fields=()):
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
with db_api.transaction():
|
with db_api.transaction():
|
||||||
task_ex = db_api.get_task_execution(id)
|
task_ex = db_api.get_task_execution(id, fields=fields)
|
||||||
|
|
||||||
rest_utils.load_deferred_fields(task_ex, ['workflow_execution'])
|
rest_utils.load_deferred_fields(task_ex, ['workflow_execution'])
|
||||||
rest_utils.load_deferred_fields(
|
rest_utils.load_deferred_fields(
|
||||||
|
@ -74,7 +77,7 @@ def _get_task_execution(id):
|
||||||
['params']
|
['params']
|
||||||
)
|
)
|
||||||
|
|
||||||
return _get_task_resource_with_result(task_ex), task_ex
|
return _get_task_resource_with_result(task_ex, fields), task_ex
|
||||||
|
|
||||||
|
|
||||||
def get_published_global(task_ex, wf_ex=None):
|
def get_published_global(task_ex, wf_ex=None):
|
||||||
|
@ -141,7 +144,7 @@ class TaskExecutionsController(rest.RestController):
|
||||||
or less than that of sort_keys.
|
or less than that of sort_keys.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param workflow_name: Optional. Keep only resources with a specific
|
:param workflow_name: Optional. Keep only resources with a specific
|
||||||
workflow name.
|
workflow name.
|
||||||
|
@ -204,18 +207,26 @@ class TasksController(rest.RestController):
|
||||||
executions = sub_execution.SubExecutionsController()
|
executions = sub_execution.SubExecutionsController()
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.Task, wtypes.text)
|
@wsme_pecan.wsexpose(resources.Task, wtypes.text, types.uniquelist)
|
||||||
def get(self, id):
|
def get(self, id, fields=''):
|
||||||
"""Return the specified task.
|
"""Return the specified task.
|
||||||
|
|
||||||
:param id: UUID of task to retrieve
|
:param id: UUID of task to retrieve
|
||||||
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
|
be returned. 'id' will be included automatically in
|
||||||
|
fields if it's not provided.
|
||||||
"""
|
"""
|
||||||
acl.enforce('tasks:get', context.ctx())
|
acl.enforce('tasks:get', context.ctx())
|
||||||
LOG.debug("Fetch task [id=%s]", id)
|
LOG.debug("Fetch task [id=%s]", id)
|
||||||
|
|
||||||
task, task_ex = _get_task_execution(id)
|
task, task_ex = _get_task_execution(id, ())
|
||||||
|
task = _task_with_published_global(task, task_ex)
|
||||||
return _task_with_published_global(task, task_ex)
|
if fields:
|
||||||
|
if 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
task_dict = {field: task.to_dict()[field] for field in fields}
|
||||||
|
task = resources.Task.from_dict(task_dict)
|
||||||
|
return task
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.Tasks, types.uuid, int, types.uniquelist,
|
@wsme_pecan.wsexpose(resources.Tasks, types.uuid, int, types.uniquelist,
|
||||||
|
@ -249,7 +260,7 @@ class TasksController(rest.RestController):
|
||||||
or less than that of sort_keys.
|
or less than that of sort_keys.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param name: Optional. Keep only resources with a specific name.
|
:param name: Optional. Keep only resources with a specific name.
|
||||||
:param workflow_name: Optional. Keep only resources with a specific
|
:param workflow_name: Optional. Keep only resources with a specific
|
||||||
|
@ -412,7 +423,7 @@ class ExecutionTasksController(rest.RestController):
|
||||||
or less than that of sort_keys.
|
or less than that of sort_keys.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param name: Optional. Keep only resources with a specific name.
|
:param name: Optional. Keep only resources with a specific name.
|
||||||
:param workflow_name: Optional. Keep only resources with a specific
|
:param workflow_name: Optional. Keep only resources with a specific
|
||||||
|
|
|
@ -44,27 +44,36 @@ class WorkbooksController(rest.RestController, hooks.HookController):
|
||||||
)
|
)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.Workbook, wtypes.text, wtypes.text)
|
@wsme_pecan.wsexpose(resources.Workbook, wtypes.text, wtypes.text,
|
||||||
def get(self, name, namespace=''):
|
types.uniquelist)
|
||||||
|
def get(self, name, namespace='', fields=''):
|
||||||
"""Return the named workbook.
|
"""Return the named workbook.
|
||||||
|
|
||||||
:param name: Name of workbook to retrieve.
|
:param name: Name of workbook to retrieve.
|
||||||
:param namespace: Optional. Namespace of workbook to retrieve.
|
:param namespace: Optional. Namespace of workbook to retrieve.
|
||||||
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
|
be returned. 'id' will be included automatically in
|
||||||
|
fields if it's not provided.
|
||||||
"""
|
"""
|
||||||
acl.enforce('workbooks:get', context.ctx())
|
acl.enforce('workbooks:get', context.ctx())
|
||||||
|
|
||||||
LOG.debug("Fetch workbook [name=%s, namespace=%s]", name, namespace)
|
LOG.debug("Fetch workbook [name=%s, namespace=%s]", name, namespace)
|
||||||
|
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
# Use retries to prevent possible failures.
|
# Use retries to prevent possible failures.
|
||||||
r = rest_utils.create_db_retry_object()
|
r = rest_utils.create_db_retry_object()
|
||||||
|
|
||||||
db_model = r.call(
|
db_model = r.call(
|
||||||
db_api.get_workbook,
|
db_api.get_workbook,
|
||||||
name,
|
name,
|
||||||
namespace=namespace
|
namespace=namespace,
|
||||||
|
fields=fields
|
||||||
)
|
)
|
||||||
|
if fields:
|
||||||
return resources.Workbook.from_db_model(db_model)
|
return resources.Workbook.from_tuples(zip(fields, db_model))
|
||||||
|
return resources.Workbook.from_db_model(db_model, fields=fields)
|
||||||
|
|
||||||
@rest_utils.wrap_pecan_controller_exception
|
@rest_utils.wrap_pecan_controller_exception
|
||||||
@pecan.expose(content_type="text/plain")
|
@pecan.expose(content_type="text/plain")
|
||||||
|
@ -171,7 +180,7 @@ class WorkbooksController(rest.RestController, hooks.HookController):
|
||||||
Default: asc.
|
Default: asc.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param name: Optional. Keep only resources with a specific name.
|
:param name: Optional. Keep only resources with a specific name.
|
||||||
:param definition: Optional. Keep only resources with a specific
|
:param definition: Optional. Keep only resources with a specific
|
||||||
|
|
|
@ -77,26 +77,36 @@ class WorkflowsController(rest.RestController, hooks.HookController):
|
||||||
)
|
)
|
||||||
|
|
||||||
@rest_utils.wrap_wsme_controller_exception
|
@rest_utils.wrap_wsme_controller_exception
|
||||||
@wsme_pecan.wsexpose(resources.Workflow, wtypes.text, wtypes.text)
|
@wsme_pecan.wsexpose(resources.Workflow, wtypes.text, wtypes.text,
|
||||||
def get(self, identifier, namespace=''):
|
types.uniquelist)
|
||||||
|
def get(self, identifier, namespace='', fields=''):
|
||||||
"""Return the named workflow.
|
"""Return the named workflow.
|
||||||
|
|
||||||
:param identifier: Name or UUID of the workflow to retrieve.
|
:param identifier: Name or UUID of the workflow to retrieve.
|
||||||
:param namespace: Optional. Namespace of the workflow to retrieve.
|
:param namespace: Optional. Namespace of the workflow to retrieve.
|
||||||
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
|
be returned. 'id' will be included automatically in
|
||||||
|
fields if it's not provided.
|
||||||
"""
|
"""
|
||||||
acl.enforce('workflows:get', context.ctx())
|
acl.enforce('workflows:get', context.ctx())
|
||||||
|
|
||||||
LOG.debug("Fetch workflow [identifier=%s]", identifier)
|
LOG.debug("Fetch workflow [identifier=%s]", identifier)
|
||||||
|
|
||||||
|
if fields and 'id' not in fields:
|
||||||
|
fields.insert(0, 'id')
|
||||||
|
|
||||||
# Use retries to prevent possible failures.
|
# Use retries to prevent possible failures.
|
||||||
r = rest_utils.create_db_retry_object()
|
r = rest_utils.create_db_retry_object()
|
||||||
db_model = r.call(
|
db_model = r.call(
|
||||||
db_api.get_workflow_definition,
|
db_api.get_workflow_definition,
|
||||||
identifier,
|
identifier,
|
||||||
namespace=namespace
|
namespace=namespace,
|
||||||
|
fields=fields,
|
||||||
)
|
)
|
||||||
|
|
||||||
return resources.Workflow.from_db_model(db_model)
|
if fields:
|
||||||
|
return resources.Workflow.from_tuples(zip(fields, db_model))
|
||||||
|
return resources.Workflow.from_db_model(db_model, fields=fields)
|
||||||
|
|
||||||
@rest_utils.wrap_pecan_controller_exception
|
@rest_utils.wrap_pecan_controller_exception
|
||||||
@pecan.expose(content_type="text/plain")
|
@pecan.expose(content_type="text/plain")
|
||||||
|
@ -240,7 +250,7 @@ class WorkflowsController(rest.RestController, hooks.HookController):
|
||||||
Default: asc.
|
Default: asc.
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param name: Optional. Keep only resources with a specific name.
|
:param name: Optional. Keep only resources with a specific name.
|
||||||
:param namespace: Optional. Keep only resources with a specific
|
:param namespace: Optional. Keep only resources with a specific
|
||||||
|
|
|
@ -87,15 +87,18 @@ class _MistralModelBase(oslo_models.ModelBase, oslo_models.TimestampMixin):
|
||||||
if col.name not in unloaded and hasattr(self, col.name):
|
if col.name not in unloaded and hasattr(self, col.name):
|
||||||
yield col.name
|
yield col.name
|
||||||
|
|
||||||
def iter_columns(self):
|
def iter_columns(self, fields=()):
|
||||||
"""Returns an iterator for loaded columns.
|
"""Returns an iterator for loaded columns.
|
||||||
|
|
||||||
|
:param fields: names of fields to return
|
||||||
|
:type fields: tuple, list or set
|
||||||
:return: A generator function that generates
|
:return: A generator function that generates
|
||||||
tuples (column name, column value).
|
tuples (column name, column value).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for col_name in self.iter_column_names():
|
for col_name in self.iter_column_names():
|
||||||
yield col_name, getattr(self, col_name)
|
if not fields or col_name in fields:
|
||||||
|
yield col_name, getattr(self, col_name)
|
||||||
|
|
||||||
def get_clone(self):
|
def get_clone(self):
|
||||||
"""Clones current object, loads all fields and returns the result."""
|
"""Clones current object, loads all fields and returns the result."""
|
||||||
|
|
|
@ -524,17 +524,17 @@ def get_scheduled_jobs_count(**kwargs):
|
||||||
|
|
||||||
# Cron triggers.
|
# Cron triggers.
|
||||||
|
|
||||||
def get_cron_trigger(identifier):
|
def get_cron_trigger(identifier, fields=()):
|
||||||
return IMPL.get_cron_trigger(identifier)
|
return IMPL.get_cron_trigger(identifier, fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def get_cron_trigger_by_id(id):
|
def get_cron_trigger_by_id(id, fields=()):
|
||||||
return IMPL.get_cron_trigger_by_id(id)
|
return IMPL.get_cron_trigger_by_id(id, fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def load_cron_trigger(identifier):
|
def load_cron_trigger(identifier, fields=()):
|
||||||
"""Unlike get_cron_trigger this method is allowed to return None."""
|
"""Unlike get_cron_trigger this method is allowed to return None."""
|
||||||
return IMPL.load_cron_trigger(identifier)
|
return IMPL.load_cron_trigger(identifier, fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def get_cron_triggers(**kwargs):
|
def get_cron_triggers(**kwargs):
|
||||||
|
@ -593,13 +593,13 @@ def delete_cron_triggers(**kwargs):
|
||||||
|
|
||||||
# Environments.
|
# Environments.
|
||||||
|
|
||||||
def get_environment(name):
|
def get_environment(name, fields=()):
|
||||||
return IMPL.get_environment(name)
|
return IMPL.get_environment(name, fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def load_environment(name):
|
def load_environment(name, fields=()):
|
||||||
"""Unlike get_environment this method is allowed to return None."""
|
"""Unlike get_environment this method is allowed to return None."""
|
||||||
return IMPL.load_environment(name)
|
return IMPL.load_environment(name, fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def get_environments(limit=None, marker=None, sort_keys=None,
|
def get_environments(limit=None, marker=None, sort_keys=None,
|
||||||
|
@ -667,12 +667,12 @@ def delete_resource_members(**kwargs):
|
||||||
|
|
||||||
# Event triggers.
|
# Event triggers.
|
||||||
|
|
||||||
def get_event_trigger(id, insecure=False):
|
def get_event_trigger(id, insecure=False, fields=()):
|
||||||
return IMPL.get_event_trigger(id, insecure)
|
return IMPL.get_event_trigger(id, insecure, fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def load_event_trigger(id, insecure=False):
|
def load_event_trigger(id, insecure=False, fields=()):
|
||||||
return IMPL.load_event_trigger(id, insecure)
|
return IMPL.load_event_trigger(id, insecure, fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def get_event_triggers(insecure=False, limit=None, marker=None, sort_keys=None,
|
def get_event_triggers(insecure=False, limit=None, marker=None, sort_keys=None,
|
||||||
|
|
|
@ -307,6 +307,11 @@ def _get_db_object_by_name(model, name, columns=()):
|
||||||
|
|
||||||
|
|
||||||
def _get_db_object_by_id(model, id, insecure=False, columns=()):
|
def _get_db_object_by_id(model, id, insecure=False, columns=()):
|
||||||
|
columns = (
|
||||||
|
tuple([getattr(model, f) for f in columns if hasattr(model, f)])
|
||||||
|
if columns and isinstance(columns, list) else columns
|
||||||
|
)
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
b.model_query(model, columns=columns)
|
b.model_query(model, columns=columns)
|
||||||
if insecure
|
if insecure
|
||||||
|
@ -319,6 +324,10 @@ def _get_db_object_by_id(model, id, insecure=False, columns=()):
|
||||||
def _get_db_object_by_name_and_namespace_or_id(model, identifier,
|
def _get_db_object_by_name_and_namespace_or_id(model, identifier,
|
||||||
namespace=None, insecure=False,
|
namespace=None, insecure=False,
|
||||||
columns=()):
|
columns=()):
|
||||||
|
columns = (
|
||||||
|
tuple([getattr(model, f) for f in columns if hasattr(model, f)])
|
||||||
|
if columns and isinstance(columns, list) else columns
|
||||||
|
)
|
||||||
query = (
|
query = (
|
||||||
b.model_query(model, columns=columns)
|
b.model_query(model, columns=columns)
|
||||||
if insecure
|
if insecure
|
||||||
|
@ -1599,13 +1608,14 @@ def _get_completed_root_executions_query(columns):
|
||||||
|
|
||||||
|
|
||||||
@b.session_aware()
|
@b.session_aware()
|
||||||
def get_cron_trigger(identifier, session=None):
|
def get_cron_trigger(identifier, session=None, fields=()):
|
||||||
ctx = context.ctx()
|
ctx = context.ctx()
|
||||||
|
|
||||||
cron_trigger = _get_db_object_by_name_and_namespace_or_id(
|
cron_trigger = _get_db_object_by_name_and_namespace_or_id(
|
||||||
models.CronTrigger,
|
models.CronTrigger,
|
||||||
identifier,
|
identifier,
|
||||||
insecure=ctx.is_admin
|
insecure=ctx.is_admin,
|
||||||
|
columns=fields,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not cron_trigger:
|
if not cron_trigger:
|
||||||
|
@ -1617,10 +1627,11 @@ def get_cron_trigger(identifier, session=None):
|
||||||
|
|
||||||
|
|
||||||
@b.session_aware()
|
@b.session_aware()
|
||||||
def get_cron_trigger_by_id(id, session=None):
|
def get_cron_trigger_by_id(id, session=None, fields=()):
|
||||||
ctx = context.ctx()
|
ctx = context.ctx()
|
||||||
cron_trigger = _get_db_object_by_id(models.CronTrigger, id,
|
cron_trigger = _get_db_object_by_id(models.CronTrigger, id,
|
||||||
insecure=ctx.is_admin)
|
insecure=ctx.is_admin,
|
||||||
|
columns=fields)
|
||||||
if not cron_trigger:
|
if not cron_trigger:
|
||||||
raise exc.DBEntityNotFoundError(
|
raise exc.DBEntityNotFoundError(
|
||||||
"Cron trigger not found [id=%s]" % id
|
"Cron trigger not found [id=%s]" % id
|
||||||
|
@ -1630,10 +1641,11 @@ def get_cron_trigger_by_id(id, session=None):
|
||||||
|
|
||||||
|
|
||||||
@b.session_aware()
|
@b.session_aware()
|
||||||
def load_cron_trigger(identifier, session=None):
|
def load_cron_trigger(identifier, session=None, fields=()):
|
||||||
return _get_db_object_by_name_and_namespace_or_id(
|
return _get_db_object_by_name_and_namespace_or_id(
|
||||||
models.CronTrigger,
|
models.CronTrigger,
|
||||||
identifier
|
identifier,
|
||||||
|
columns=fields,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1744,8 +1756,8 @@ def delete_cron_triggers(session=None, **kwargs):
|
||||||
# Environments.
|
# Environments.
|
||||||
|
|
||||||
@b.session_aware()
|
@b.session_aware()
|
||||||
def get_environment(name, session=None):
|
def get_environment(name, session=None, fields=()):
|
||||||
env = _get_db_object_by_name(models.Environment, name)
|
env = _get_db_object_by_name(models.Environment, name, columns=fields)
|
||||||
|
|
||||||
if not env:
|
if not env:
|
||||||
raise exc.DBEntityNotFoundError(
|
raise exc.DBEntityNotFoundError(
|
||||||
|
@ -1756,8 +1768,8 @@ def get_environment(name, session=None):
|
||||||
|
|
||||||
|
|
||||||
@b.session_aware()
|
@b.session_aware()
|
||||||
def load_environment(name, session=None):
|
def load_environment(name, session=None, fields=()):
|
||||||
return _get_db_object_by_name(models.Environment, name)
|
return _get_db_object_by_name(models.Environment, name, columns=fields)
|
||||||
|
|
||||||
|
|
||||||
@b.session_aware()
|
@b.session_aware()
|
||||||
|
@ -1982,8 +1994,9 @@ def _get_accepted_resources(res_type):
|
||||||
# Event triggers.
|
# Event triggers.
|
||||||
|
|
||||||
@b.session_aware()
|
@b.session_aware()
|
||||||
def get_event_trigger(id, insecure=False, session=None):
|
def get_event_trigger(id, insecure=False, session=None, fields=()):
|
||||||
event_trigger = _get_db_object_by_id(models.EventTrigger, id, insecure)
|
event_trigger = _get_db_object_by_id(models.EventTrigger, id, insecure,
|
||||||
|
columns=fields)
|
||||||
|
|
||||||
if not event_trigger:
|
if not event_trigger:
|
||||||
raise exc.DBEntityNotFoundError(
|
raise exc.DBEntityNotFoundError(
|
||||||
|
@ -1994,8 +2007,9 @@ def get_event_trigger(id, insecure=False, session=None):
|
||||||
|
|
||||||
|
|
||||||
@b.session_aware()
|
@b.session_aware()
|
||||||
def load_event_trigger(id, insecure=False, session=None):
|
def load_event_trigger(id, insecure=False, session=None, fields=()):
|
||||||
return _get_db_object_by_id(models.EventTrigger, id, insecure)
|
return _get_db_object_by_id(models.EventTrigger, id, insecure,
|
||||||
|
columns=fields)
|
||||||
|
|
||||||
|
|
||||||
@b.session_aware()
|
@b.session_aware()
|
||||||
|
|
|
@ -226,9 +226,22 @@ class TestActionExecutionsController(base.APITest):
|
||||||
@mock.patch.object(db_api, 'get_action_execution', MOCK_ACTION)
|
@mock.patch.object(db_api, 'get_action_execution', MOCK_ACTION)
|
||||||
def test_get(self):
|
def test_get(self):
|
||||||
resp = self.app.get('/v2/action_executions/123')
|
resp = self.app.get('/v2/action_executions/123')
|
||||||
|
action_exec = copy.deepcopy(ACTION_EX)
|
||||||
|
del action_exec['task_name']
|
||||||
|
self.assertEqual(200, resp.status_int)
|
||||||
|
self.assertDictEqual(action_exec, resp.json)
|
||||||
|
|
||||||
|
@mock.patch('mistral.db.v2.api.get_action_execution')
|
||||||
|
def test_get_with_fields_filter(self, mocked_get):
|
||||||
|
mocked_get.return_value = (ACTION_EX['id'], ACTION_EX['name'],)
|
||||||
|
resp = self.app.get('/v2/action_executions/123?fields=name')
|
||||||
|
expected = {
|
||||||
|
'id': ACTION_EX['id'],
|
||||||
|
'name': ACTION_EX['name'],
|
||||||
|
}
|
||||||
|
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self.assertDictEqual(ACTION_EX, resp.json)
|
self.assertDictEqual(expected, resp.json)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'get_action_execution')
|
@mock.patch.object(db_api, 'get_action_execution')
|
||||||
def test_get_operational_error(self, mocked_get):
|
def test_get_operational_error(self, mocked_get):
|
||||||
|
@ -239,9 +252,10 @@ class TestActionExecutionsController(base.APITest):
|
||||||
]
|
]
|
||||||
|
|
||||||
resp = self.app.get('/v2/action_executions/123')
|
resp = self.app.get('/v2/action_executions/123')
|
||||||
|
action_exec = copy.deepcopy(ACTION_EX)
|
||||||
|
del action_exec['task_name']
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self.assertDictEqual(ACTION_EX, resp.json)
|
self.assertDictEqual(action_exec, resp.json)
|
||||||
|
|
||||||
def test_basic_get(self):
|
def test_basic_get(self):
|
||||||
resp = self.app.get('/v2/action_executions/')
|
resp = self.app.get('/v2/action_executions/')
|
||||||
|
@ -259,7 +273,7 @@ class TestActionExecutionsController(base.APITest):
|
||||||
resp = self.app.get('/v2/action_executions/123')
|
resp = self.app.get('/v2/action_executions/123')
|
||||||
|
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self.assertTrue('project_id' in resp.json)
|
self.assertIn('project_id', resp.json)
|
||||||
|
|
||||||
@mock.patch.object(oslo_client.OsloRPCClient, 'sync_call',
|
@mock.patch.object(oslo_client.OsloRPCClient, 'sync_call',
|
||||||
mock.MagicMock(side_effect=oslo_exc.MessagingTimeout))
|
mock.MagicMock(side_effect=oslo_exc.MessagingTimeout))
|
||||||
|
@ -561,11 +575,12 @@ class TestActionExecutionsController(base.APITest):
|
||||||
@mock.patch.object(db_api, 'get_action_executions', MOCK_ACTIONS)
|
@mock.patch.object(db_api, 'get_action_executions', MOCK_ACTIONS)
|
||||||
def test_get_all(self):
|
def test_get_all(self):
|
||||||
resp = self.app.get('/v2/action_executions')
|
resp = self.app.get('/v2/action_executions')
|
||||||
|
action_exec = copy.deepcopy(ACTION_EX)
|
||||||
|
del action_exec['task_name']
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
|
|
||||||
self.assertEqual(1, len(resp.json['action_executions']))
|
self.assertEqual(1, len(resp.json['action_executions']))
|
||||||
self.assertDictEqual(ACTION_EX, resp.json['action_executions'][0])
|
self.assertDictEqual(action_exec, resp.json['action_executions'][0])
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'get_action_executions')
|
@mock.patch.object(db_api, 'get_action_executions')
|
||||||
def test_get_all_operational_error(self, mocked_get_all):
|
def test_get_all_operational_error(self, mocked_get_all):
|
||||||
|
@ -576,11 +591,13 @@ class TestActionExecutionsController(base.APITest):
|
||||||
]
|
]
|
||||||
|
|
||||||
resp = self.app.get('/v2/action_executions')
|
resp = self.app.get('/v2/action_executions')
|
||||||
|
action_exec = copy.deepcopy(ACTION_EX)
|
||||||
|
del action_exec['task_name']
|
||||||
|
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
|
|
||||||
self.assertEqual(1, len(resp.json['action_executions']))
|
self.assertEqual(1, len(resp.json['action_executions']))
|
||||||
self.assertDictEqual(ACTION_EX, resp.json['action_executions'][0])
|
self.assertDictEqual(action_exec, resp.json['action_executions'][0])
|
||||||
|
|
||||||
@mock.patch.object(rest_utils, 'get_all',
|
@mock.patch.object(rest_utils, 'get_all',
|
||||||
return_value=resources.ActionExecutions())
|
return_value=resources.ActionExecutions())
|
||||||
|
|
|
@ -79,6 +79,18 @@ class TestCronTriggerController(base.APITest):
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self.assertDictEqual(TRIGGER, resp.json)
|
self.assertDictEqual(TRIGGER, resp.json)
|
||||||
|
|
||||||
|
@mock.patch('mistral.db.v2.api.get_cron_trigger')
|
||||||
|
def test_get_with_fields_filter(self, mocked_get):
|
||||||
|
mocked_get.return_value = (TRIGGER['id'], TRIGGER['name'],)
|
||||||
|
resp = self.app.get('/v2/cron_triggers/my_cron_trigger?fields=name')
|
||||||
|
expected = {
|
||||||
|
'id': TRIGGER['id'],
|
||||||
|
'name': TRIGGER['name'],
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(200, resp.status_int)
|
||||||
|
self.assertDictEqual(expected, resp.json)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'get_cron_trigger')
|
@mock.patch.object(db_api, 'get_cron_trigger')
|
||||||
def test_get_operational_error(self, mocked_get):
|
def test_get_operational_error(self, mocked_get):
|
||||||
mocked_get.side_effect = [
|
mocked_get.side_effect = [
|
||||||
|
|
|
@ -188,6 +188,20 @@ class TestEnvironmentController(base.APITest):
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self._assert_dict_equal(ENVIRONMENT, resp.json)
|
self._assert_dict_equal(ENVIRONMENT, resp.json)
|
||||||
|
|
||||||
|
@mock.patch('mistral.db.v2.api.get_environment')
|
||||||
|
def test_get_with_fields_filter(self, mocked_get):
|
||||||
|
mocked_get.return_value = (
|
||||||
|
ENVIRONMENT['id'], ENVIRONMENT['name'],
|
||||||
|
)
|
||||||
|
resp = self.app.get('/v2/environments/123?fields=name')
|
||||||
|
expected = {
|
||||||
|
'id': ENVIRONMENT['id'],
|
||||||
|
'name': ENVIRONMENT['name'],
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(200, resp.status_int)
|
||||||
|
self.assertDictEqual(expected, resp.json)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'get_environment')
|
@mock.patch.object(db_api, 'get_environment')
|
||||||
def test_get_operational_error(self, mocked_get):
|
def test_get_operational_error(self, mocked_get):
|
||||||
mocked_get.side_effect = [
|
mocked_get.side_effect = [
|
||||||
|
|
|
@ -77,6 +77,21 @@ class TestEventTriggerController(base.APITest):
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self.assertDictEqual(TRIGGER, resp.json)
|
self.assertDictEqual(TRIGGER, resp.json)
|
||||||
|
|
||||||
|
@mock.patch('mistral.db.v2.api.get_event_trigger')
|
||||||
|
def test_get_with_fields_filter(self, mocked_get):
|
||||||
|
mocked_get.return_value = (TRIGGER['id'], TRIGGER['name'],)
|
||||||
|
resp = self.app.get(
|
||||||
|
'/v2/event_triggers/09cc56a9-d15e-4494-a6e2-c4ec8bdaacae'
|
||||||
|
'?fields=name'
|
||||||
|
)
|
||||||
|
expected = {
|
||||||
|
'id': TRIGGER['id'],
|
||||||
|
'name': TRIGGER['name'],
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(200, resp.status_int)
|
||||||
|
self.assertDictEqual(expected, resp.json)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'get_event_trigger')
|
@mock.patch.object(db_api, 'get_event_trigger')
|
||||||
def test_get_operational_error(self, mocked_get):
|
def test_get_operational_error(self, mocked_get):
|
||||||
mocked_get.side_effect = [
|
mocked_get.side_effect = [
|
||||||
|
|
|
@ -169,6 +169,20 @@ class TestExecutionsController(base.APITest):
|
||||||
|
|
||||||
self.assertDictEqual(expected, resp.json)
|
self.assertDictEqual(expected, resp.json)
|
||||||
|
|
||||||
|
@mock.patch('mistral.db.v2.api.get_workflow_execution')
|
||||||
|
def test_get_with_fields_filter(self, mocked_get):
|
||||||
|
mocked_get.return_value = (
|
||||||
|
WF_EX_JSON_WITH_DESC['id'], WF_EX_JSON_WITH_DESC['description'],
|
||||||
|
)
|
||||||
|
resp = self.app.get('/v2/executions/123?fields=description')
|
||||||
|
expected = {
|
||||||
|
'id': WF_EX_JSON_WITH_DESC['id'],
|
||||||
|
'description': WF_EX_JSON_WITH_DESC['description'],
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(200, resp.status_int)
|
||||||
|
self.assertDictEqual(expected, resp.json)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'get_workflow_execution')
|
@mock.patch.object(db_api, 'get_workflow_execution')
|
||||||
def test_get_operational_error(self, mocked_get):
|
def test_get_operational_error(self, mocked_get):
|
||||||
mocked_get.side_effect = [
|
mocked_get.side_effect = [
|
||||||
|
@ -564,7 +578,8 @@ class TestExecutionsController(base.APITest):
|
||||||
self.assertEqual(201, resp.status_int)
|
self.assertEqual(201, resp.status_int)
|
||||||
self.assertDictEqual(expected_json, resp.json)
|
self.assertDictEqual(expected_json, resp.json)
|
||||||
|
|
||||||
load_wf_ex_func.assert_called_once_with(expected_json['id'])
|
load_wf_ex_func.assert_called_once_with(expected_json['id'],
|
||||||
|
fields=())
|
||||||
|
|
||||||
kwargs = json.loads(expected_json['params'])
|
kwargs = json.loads(expected_json['params'])
|
||||||
kwargs['description'] = expected_json['description']
|
kwargs['description'] = expected_json['description']
|
||||||
|
@ -600,7 +615,8 @@ class TestExecutionsController(base.APITest):
|
||||||
self.assertEqual(201, resp.status_int)
|
self.assertEqual(201, resp.status_int)
|
||||||
self.assertDictEqual(expected_json, resp.json)
|
self.assertDictEqual(expected_json, resp.json)
|
||||||
|
|
||||||
load_wf_ex_func.assert_called_once_with(expected_json['id'])
|
load_wf_ex_func.assert_called_once_with(expected_json['id'],
|
||||||
|
fields=())
|
||||||
|
|
||||||
# Note that "start_workflow" method on engine API should not be called
|
# Note that "start_workflow" method on engine API should not be called
|
||||||
# in this case because we passed execution ID to the endpoint and the
|
# in this case because we passed execution ID to the endpoint and the
|
||||||
|
|
|
@ -171,6 +171,18 @@ class TestTasksController(base.APITest):
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self.assertDictEqual(TASK, resp.json)
|
self.assertDictEqual(TASK, resp.json)
|
||||||
|
|
||||||
|
@mock.patch('mistral.db.v2.api.get_task_execution')
|
||||||
|
def test_get_with_fields_filter(self, mocked_get):
|
||||||
|
mocked_get.return_value = TASK_EX
|
||||||
|
resp = self.app.get('/v2/tasks/123?fields=name')
|
||||||
|
expected = {
|
||||||
|
'id': TASK['id'],
|
||||||
|
'name': TASK['name'],
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(200, resp.status_int)
|
||||||
|
self.assertDictEqual(expected, resp.json)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'get_task_execution')
|
@mock.patch.object(db_api, 'get_task_execution')
|
||||||
def test_get_operational_error(self, mocked_get):
|
def test_get_operational_error(self, mocked_get):
|
||||||
mocked_get.side_effect = [
|
mocked_get.side_effect = [
|
||||||
|
|
|
@ -169,6 +169,18 @@ class TestWorkbooksController(base.APITest):
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self.assertDictEqual(WORKBOOK, resp.json)
|
self.assertDictEqual(WORKBOOK, resp.json)
|
||||||
|
|
||||||
|
@mock.patch('mistral.db.v2.api.get_workbook')
|
||||||
|
def test_get_with_fields_filter(self, mocked_get):
|
||||||
|
mocked_get.return_value = (WORKBOOK['id'], WORKBOOK['name'],)
|
||||||
|
resp = self.app.get('/v2/workbooks/123?fields=name')
|
||||||
|
expected = {
|
||||||
|
'id': WORKBOOK['id'],
|
||||||
|
'name': WORKBOOK['name'],
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(200, resp.status_int)
|
||||||
|
self.assertDictEqual(expected, resp.json)
|
||||||
|
|
||||||
@mock.patch.object(db_api, "get_workbook", MOCK_WB_WITH_NAMESPACE)
|
@mock.patch.object(db_api, "get_workbook", MOCK_WB_WITH_NAMESPACE)
|
||||||
def test_get_with_namespace(self):
|
def test_get_with_namespace(self):
|
||||||
resp = self.app.get('/v2/workbooks/123?namespace=xyz')
|
resp = self.app.get('/v2/workbooks/123?namespace=xyz')
|
||||||
|
|
|
@ -264,6 +264,18 @@ class TestWorkflowsController(base.APITest):
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self.assertDictEqual(WF, resp_json)
|
self.assertDictEqual(WF, resp_json)
|
||||||
|
|
||||||
|
@mock.patch('mistral.db.v2.api.get_workflow_definition')
|
||||||
|
def test_get_with_fields_filter(self, mocked_get):
|
||||||
|
mocked_get.return_value = (WF['id'], WF['name'],)
|
||||||
|
resp = self.app.get('/v2/workflows/123?fields=name')
|
||||||
|
expected = {
|
||||||
|
'id': WF['id'],
|
||||||
|
'name': WF['name'],
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(200, resp.status_int)
|
||||||
|
self.assertDictEqual(expected, resp.json)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'get_workflow_definition')
|
@mock.patch.object(db_api, 'get_workflow_definition')
|
||||||
def test_get_operational_error(self, mocked_get):
|
def test_get_operational_error(self, mocked_get):
|
||||||
mocked_get.side_effect = [
|
mocked_get.side_effect = [
|
||||||
|
@ -886,4 +898,4 @@ class TestWorkflowsController(base.APITest):
|
||||||
resp = self.app.get(
|
resp = self.app.get(
|
||||||
'/v2/workflows/123e4567-e89b-12d3-a456-426655440000')
|
'/v2/workflows/123e4567-e89b-12d3-a456-426655440000')
|
||||||
self.assertEqual(200, resp.status_int)
|
self.assertEqual(200, resp.status_int)
|
||||||
self.assertTrue('project_id' in resp.json)
|
self.assertIn('project_id', resp.json)
|
||||||
|
|
|
@ -121,6 +121,14 @@ def validate_fields(fields, object_fields):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def fields_list_to_cls_fields_tuple(model, f):
|
||||||
|
if not f:
|
||||||
|
return ()
|
||||||
|
return tuple(
|
||||||
|
[getattr(model, str(field)) for field in f]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def filters_to_dict(**kwargs):
|
def filters_to_dict(**kwargs):
|
||||||
"""Return only non-null values
|
"""Return only non-null values
|
||||||
|
|
||||||
|
@ -157,7 +165,7 @@ def get_all(list_cls, cls, get_all_function, get_function,
|
||||||
Default: ['asc'].
|
Default: ['asc'].
|
||||||
:param fields: Optional. A specified list of fields of the resource to
|
:param fields: Optional. A specified list of fields of the resource to
|
||||||
be returned. 'id' will be included automatically in
|
be returned. 'id' will be included automatically in
|
||||||
fields if it's provided, since it will be used when
|
fields if it's not provided, since it will be used when
|
||||||
constructing 'next' link.
|
constructing 'next' link.
|
||||||
:param filters: Optional. A specified dictionary of filters to match.
|
:param filters: Optional. A specified dictionary of filters to match.
|
||||||
:param all_projects: Optional. Get resources of all projects.
|
:param all_projects: Optional. Get resources of all projects.
|
||||||
|
|
Loading…
Reference in New Issue