mistral/mistral/api/controllers/v2/action_execution.py

168 lines
5.4 KiB
Python

# -*- coding: utf-8 -*-
#
# Copyright 2015 - Mirantis, Inc.
#
# 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 json
from pecan import rest
from wsme import types as wtypes
import wsmeext.pecan as wsme_pecan
from mistral.api.controllers import resource
from mistral.db.v2 import api as db_api
# TODO(nmakhotkin) Uncomment these lines after refactoring.
from mistral.engine1 import rpc
from mistral import exceptions as exc
from mistral.openstack.common import log as logging
from mistral.utils import rest_utils
from mistral.workflow import states
from mistral.workflow import utils as wf_utils
LOG = logging.getLogger(__name__)
class ActionExecution(resource.Resource):
"""ActionExecution resource."""
id = wtypes.text
workflow_name = wtypes.text
task_execution_id = wtypes.text
state = wtypes.text
state_info = wtypes.text
tags = [wtypes.text]
name = wtypes.text
accepted = bool
input = wtypes.text
output = wtypes.text
created_at = wtypes.text
updated_at = wtypes.text
@classmethod
def from_dict(cls, d):
e = cls()
for key, val in d.items():
if hasattr(e, key):
# Nonetype check for dictionary must be explicit.
if val is not None and (
key == 'input' or key == 'output'):
val = json.dumps(val)
setattr(e, key, val)
return e
@classmethod
def sample(cls):
return cls(
id='123e4567-e89b-12d3-a456-426655440000',
workflow_name='flow',
workflow_execution_id='653e4127-e89b-12d3-a456-426655440076',
task_execution_id='343e45623-e89b-12d3-a456-426655440090',
state=states.SUCCESS,
state_info=states.SUCCESS,
tags=['foo', 'fee'],
definition_name='std.echo',
accepted=True,
input='{"first_name": "John", "last_name": "Doe"}',
output='{"some_output": "Hello, John Doe!"}',
created_at='1970-01-01T00:00:00.000000',
updated_at='1970-01-01T00:00:00.000000'
)
class ActionExecutions(resource.Resource):
"""A collection of action_executions."""
action_executions = [ActionExecution]
@classmethod
def sample(cls):
return cls(action_executions=[ActionExecution.sample()])
class ActionExecutionsController(rest.RestController):
@rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(ActionExecution, wtypes.text)
def get(self, id):
"""Return the specified action_execution."""
LOG.info("Fetch action_execution [id=%s]" % id)
db_model = db_api.get_action_execution(id)
return ActionExecution.from_dict(db_model.to_dict())
@rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(ActionExecution, wtypes.text, body=ActionExecution)
def put(self, id, action_execution):
"""Update the specified action_execution."""
LOG.info(
"Update action_execution [id=%s, action_execution=%s]"
% (id, action_execution)
)
# Client must provide a valid json. It shouldn't necessarily be an
# object but it should be json complaint so strings have to be escaped.
output = None
if action_execution.output:
try:
output = json.loads(action_execution.output)
except (ValueError, TypeError) as e:
raise exc.InvalidResultException(str(e))
if action_execution.state == states.SUCCESS:
result = wf_utils.Result(data=output)
elif action_execution.state == states.ERROR:
result = wf_utils.Result(error=output)
else:
raise exc.InvalidResultException(
"Error. Expected on of %s, actual: %s" %
([states.SUCCESS, states.ERROR], action_execution.state)
)
values = rpc.get_engine_client().on_action_complete(id, result)
return ActionExecution.from_dict(values)
@wsme_pecan.wsexpose(ActionExecutions)
def get_all(self):
"""Return all action_executions within the execution."""
LOG.info("Fetch action_executions")
action_executions = [ActionExecution.from_dict(db_model.to_dict())
for db_model in db_api.get_action_executions()]
return ActionExecutions(action_executions=action_executions)
class TasksActionExecutionController(rest.RestController):
@wsme_pecan.wsexpose(ActionExecutions, wtypes.text)
def get_all(self, task_execution_id):
"""Return all action executions within the task execution."""
LOG.info("Fetch action executions")
action_execs = db_api.get_action_executions(
task_execution_id=task_execution_id
)
return ActionExecutions(
action_executions=[ActionExecution.from_dict(db_model.to_dict())
for db_model in action_execs]
)