Adds API to obtain action result
Also adds File type to core library for common convention type for files Partially implements: blueprint actions-return-result Change-Id: I5cbfb9ed6f4ae56e931815841f9c042f25a1d0ca
This commit is contained in:
parent
4c5a723331
commit
73f8368024
16
meta/io.murano/Classes/File.yaml
Normal file
16
meta/io.murano/Classes/File.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Namespaces:
|
||||||
|
=: io.murano
|
||||||
|
|
||||||
|
Name: File
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
base64Content:
|
||||||
|
Contract: $.string().notNull()
|
||||||
|
Default: ''
|
||||||
|
|
||||||
|
mimeType:
|
||||||
|
Contract: $.string().notNull()
|
||||||
|
Default: 'application/octet-stream'
|
||||||
|
|
||||||
|
filename:
|
||||||
|
Contract: $.string()
|
@ -20,6 +20,7 @@ Classes:
|
|||||||
io.murano.Exception: Exception.yaml
|
io.murano.Exception: Exception.yaml
|
||||||
io.murano.StackTrace: StackTrace.yaml
|
io.murano.StackTrace: StackTrace.yaml
|
||||||
io.murano.SharedIp: SharedIp.yaml
|
io.murano.SharedIp: SharedIp.yaml
|
||||||
|
io.murano.File: File.yaml
|
||||||
|
|
||||||
io.murano.system.SecurityGroupManager: SecurityGroupManager.yaml
|
io.murano.system.SecurityGroupManager: SecurityGroupManager.yaml
|
||||||
|
|
||||||
|
@ -30,12 +30,7 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class Controller(object):
|
class Controller(object):
|
||||||
def execute(self, request, environment_id, action_id, body):
|
def _validate_environment(self, unit, request, environment_id):
|
||||||
policy.check("execute_action", request.context, {})
|
|
||||||
|
|
||||||
LOG.debug('Action:Execute <ActionId: {0}>'.format(action_id))
|
|
||||||
|
|
||||||
unit = db_session.get_session()
|
|
||||||
environment = unit.query(models.Environment).get(environment_id)
|
environment = unit.query(models.Environment).get(environment_id)
|
||||||
|
|
||||||
if environment is None:
|
if environment is None:
|
||||||
@ -48,6 +43,14 @@ class Controller(object):
|
|||||||
'this tenant resources.'))
|
'this tenant resources.'))
|
||||||
raise exc.HTTPUnauthorized
|
raise exc.HTTPUnauthorized
|
||||||
|
|
||||||
|
def execute(self, request, environment_id, action_id, body):
|
||||||
|
policy.check("execute_action", request.context, {})
|
||||||
|
|
||||||
|
LOG.debug('Action:Execute <ActionId: {0}>'.format(action_id))
|
||||||
|
|
||||||
|
unit = db_session.get_session()
|
||||||
|
self._validate_environment(unit, request, environment_id)
|
||||||
|
|
||||||
# no new session can be opened if environment has deploying status
|
# no new session can be opened if environment has deploying status
|
||||||
env_status = envs.EnvironmentServices.get_status(environment_id)
|
env_status = envs.EnvironmentServices.get_status(environment_id)
|
||||||
if env_status in (states.EnvironmentStatus.DEPLOYING,
|
if env_status in (states.EnvironmentStatus.DEPLOYING,
|
||||||
@ -65,8 +68,18 @@ class Controller(object):
|
|||||||
'is invalid').format(session.id))
|
'is invalid').format(session.id))
|
||||||
raise exc.HTTPForbidden()
|
raise exc.HTTPForbidden()
|
||||||
|
|
||||||
actions.ActionServices.execute(action_id, session, unit,
|
task_id = actions.ActionServices.execute(
|
||||||
request.context.auth_token, body or {})
|
action_id, session, unit, request.context.auth_token, body or {})
|
||||||
|
return {'task_id': task_id}
|
||||||
|
|
||||||
|
def get_result(self, request, environment_id, task_id):
|
||||||
|
policy.check("execute_action", request.context, {})
|
||||||
|
|
||||||
|
LOG.debug('Action:GetResult <TaskId: {0}>'.format(task_id))
|
||||||
|
|
||||||
|
unit = db_session.get_session()
|
||||||
|
self._validate_environment(unit, request, environment_id)
|
||||||
|
return actions.ActionServices.get_result(environment_id, task_id, unit)
|
||||||
|
|
||||||
|
|
||||||
def create_resource():
|
def create_resource():
|
||||||
|
@ -147,6 +147,10 @@ class API(wsgi.Router):
|
|||||||
controller=actions_resource,
|
controller=actions_resource,
|
||||||
action='execute',
|
action='execute',
|
||||||
conditions={'method': ['POST']})
|
conditions={'method': ['POST']})
|
||||||
|
mapper.connect('/environments/{environment_id}/actions/{task_id}',
|
||||||
|
controller=actions_resource,
|
||||||
|
action='get_result',
|
||||||
|
conditions={'method': ['GET']})
|
||||||
|
|
||||||
catalog_resource = catalog.create_resource()
|
catalog_resource = catalog.create_resource()
|
||||||
mapper.connect('/catalog/packages/categories',
|
mapper.connect('/catalog/packages/categories',
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import eventlet.debug
|
import eventlet.debug
|
||||||
@ -25,7 +27,7 @@ from murano.common.helpers import token_sanitizer
|
|||||||
from murano.common import rpc
|
from murano.common import rpc
|
||||||
from murano.dsl import dsl_exception
|
from murano.dsl import dsl_exception
|
||||||
from murano.dsl import executor
|
from murano.dsl import executor
|
||||||
from murano.dsl import results_serializer
|
from murano.dsl import serializer
|
||||||
from murano.engine import auth_utils
|
from murano.engine import auth_utils
|
||||||
from murano.engine import client_manager
|
from murano.engine import client_manager
|
||||||
from murano.engine import environment
|
from murano.engine import environment
|
||||||
@ -51,13 +53,14 @@ class TaskProcessingEndpoint(object):
|
|||||||
LOG.info(_LI('Starting processing task: {task_desc}').format(
|
LOG.info(_LI('Starting processing task: {task_desc}').format(
|
||||||
task_desc=jsonutils.dumps(s_task)))
|
task_desc=jsonutils.dumps(s_task)))
|
||||||
|
|
||||||
result = task['model']
|
result = {'model': task['model']}
|
||||||
try:
|
try:
|
||||||
task_executor = TaskExecutor(task)
|
task_executor = TaskExecutor(task)
|
||||||
result = task_executor.execute()
|
result = task_executor.execute()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception(_LE('Error during task execution for tenant %s'),
|
LOG.exception(_LE('Error during task execution for tenant %s'),
|
||||||
task['tenant_id'])
|
task['tenant_id'])
|
||||||
|
result['action'] = TaskExecutor.exception_result(e)
|
||||||
msg_env = Environment(task['id'])
|
msg_env = Environment(task['id'])
|
||||||
reporter = status_reporter.StatusReporter()
|
reporter = status_reporter.StatusReporter()
|
||||||
reporter.initialize(msg_env)
|
reporter.initialize(msg_env)
|
||||||
@ -116,6 +119,13 @@ class TaskExecutor(object):
|
|||||||
self._create_trust()
|
self._create_trust()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# !!! please do not delete 2 commented lines of code below.
|
||||||
|
# Uncomment to make engine load packages from
|
||||||
|
# local folder rather than from API !!!
|
||||||
|
|
||||||
|
# pkg_loader = package_loader.DirectoryPackageLoader('./meta')
|
||||||
|
# return self._execute(pkg_loader)
|
||||||
|
|
||||||
murano_client_factory = lambda: \
|
murano_client_factory = lambda: \
|
||||||
self._environment.clients.get_murano_client(self._environment)
|
self._environment.clients.get_murano_client(self._environment)
|
||||||
with package_loader.ApiPackageLoader(
|
with package_loader.ApiPackageLoader(
|
||||||
@ -133,17 +143,21 @@ class TaskExecutor(object):
|
|||||||
obj = exc.load(self.model)
|
obj = exc.load(self.model)
|
||||||
|
|
||||||
self._validate_model(obj, self.action, class_loader)
|
self._validate_model(obj, self.action, class_loader)
|
||||||
|
action_result = None
|
||||||
|
exception = None
|
||||||
|
exception_traceback = None
|
||||||
try:
|
try:
|
||||||
# Skip execution of action in case no action is provided.
|
# Skip execution of action in case no action is provided.
|
||||||
# Model will be just loaded, cleaned-up and unloaded.
|
# Model will be just loaded, cleaned-up and unloaded.
|
||||||
# Most of the time this is used for deletion of environments.
|
# Most of the time this is used for deletion of environments.
|
||||||
if self.action:
|
if self.action:
|
||||||
self._invoke(exc)
|
action_result = self._invoke(exc)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
exception = e
|
||||||
if isinstance(e, dsl_exception.MuranoPlException):
|
if isinstance(e, dsl_exception.MuranoPlException):
|
||||||
LOG.error('\n' + e.format(prefix=' '))
|
LOG.error('\n' + e.format(prefix=' '))
|
||||||
else:
|
else:
|
||||||
|
exception_traceback = traceback.format_exc()
|
||||||
LOG.exception(
|
LOG.exception(
|
||||||
_LE("Exception %(exc)s occured"
|
_LE("Exception %(exc)s occured"
|
||||||
" during invocation of %(method)s"),
|
" during invocation of %(method)s"),
|
||||||
@ -152,10 +166,38 @@ class TaskExecutor(object):
|
|||||||
reporter.initialize(obj)
|
reporter.initialize(obj)
|
||||||
reporter.report_error(obj, str(e))
|
reporter.report_error(obj, str(e))
|
||||||
|
|
||||||
result = results_serializer.serialize(obj, exc)
|
model = serializer.serialize_model(obj, exc)
|
||||||
result['SystemData'] = self._environment.system_attributes
|
model['SystemData'] = self._environment.system_attributes
|
||||||
|
result = {
|
||||||
|
'model': model,
|
||||||
|
'action': {
|
||||||
|
'result': None,
|
||||||
|
'isException': False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if exception is not None:
|
||||||
|
result['action'] = TaskExecutor.exception_result(
|
||||||
|
exception, exception_traceback)
|
||||||
|
else:
|
||||||
|
result['action']['result'] = serializer.serialize_object(
|
||||||
|
action_result)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def exception_result(exception, exception_traceback):
|
||||||
|
record = {
|
||||||
|
'isException': True,
|
||||||
|
'result': {
|
||||||
|
'message': str(exception),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isinstance(exception, dsl_exception.MuranoPlException):
|
||||||
|
record['result']['details'] = exception.format()
|
||||||
|
else:
|
||||||
|
record['result']['details'] = exception_traceback
|
||||||
|
return record
|
||||||
|
|
||||||
def _validate_model(self, obj, action, class_loader):
|
def _validate_model(self, obj, action, class_loader):
|
||||||
if config.CONF.engine.enable_model_policy_enforcer:
|
if config.CONF.engine.enable_model_policy_enforcer:
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
@ -168,7 +210,7 @@ class TaskExecutor(object):
|
|||||||
method_name, args = self.action['method'], self.action['args']
|
method_name, args = self.action['method'], self.action['args']
|
||||||
|
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
obj.type.invoke(method_name, mpl_executor, obj, args)
|
return obj.type.invoke(method_name, mpl_executor, obj, args)
|
||||||
|
|
||||||
def _create_trust(self):
|
def _create_trust(self):
|
||||||
if not config.CONF.engine.use_trusts:
|
if not config.CONF.engine.use_trusts:
|
||||||
|
@ -44,6 +44,9 @@ class ResultEndpoint(object):
|
|||||||
LOG.debug('Got result from orchestration '
|
LOG.debug('Got result from orchestration '
|
||||||
'engine:\n{0}'.format(secure_result))
|
'engine:\n{0}'.format(secure_result))
|
||||||
|
|
||||||
|
model = result['model']
|
||||||
|
action_result = result.get('action', {})
|
||||||
|
|
||||||
unit = session.get_session()
|
unit = session.get_session()
|
||||||
environment = unit.query(models.Environment).get(environment_id)
|
environment = unit.query(models.Environment).get(environment_id)
|
||||||
|
|
||||||
@ -52,11 +55,11 @@ class ResultEndpoint(object):
|
|||||||
'specified environment not found in database'))
|
'specified environment not found in database'))
|
||||||
return
|
return
|
||||||
|
|
||||||
if result['Objects'] is None and result.get('ObjectsCopy', {}) is None:
|
if model['Objects'] is None and model.get('ObjectsCopy', {}) is None:
|
||||||
environments.EnvironmentServices.remove(environment_id)
|
environments.EnvironmentServices.remove(environment_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
environment.description = result
|
environment.description = model
|
||||||
if environment.description['Objects'] is not None:
|
if environment.description['Objects'] is not None:
|
||||||
environment.description['Objects']['services'] = \
|
environment.description['Objects']['services'] = \
|
||||||
environment.description['Objects'].pop('applications', [])
|
environment.description['Objects'].pop('applications', [])
|
||||||
@ -72,6 +75,7 @@ class ResultEndpoint(object):
|
|||||||
# close deployment
|
# close deployment
|
||||||
deployment = get_last_deployment(unit, environment.id)
|
deployment = get_last_deployment(unit, environment.id)
|
||||||
deployment.finished = timeutils.utcnow()
|
deployment.finished = timeutils.utcnow()
|
||||||
|
deployment.result = action_result
|
||||||
|
|
||||||
num_errors = unit.query(models.Status)\
|
num_errors = unit.query(models.Status)\
|
||||||
.filter_by(level='error', task_id=deployment.id).count()
|
.filter_by(level='error', task_id=deployment.id).count()
|
||||||
@ -112,7 +116,7 @@ class ResultEndpoint(object):
|
|||||||
_('Failed') if num_errors + num_warnings > 0 else _('Successful'),
|
_('Failed') if num_errors + num_warnings > 0 else _('Successful'),
|
||||||
', '.join(map(
|
', '.join(map(
|
||||||
lambda a: a['?']['type'],
|
lambda a: a['?']['type'],
|
||||||
result['Objects']['services']
|
model['Objects']['services']
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
LOG.info(message)
|
LOG.info(message)
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 006
|
||||||
|
Revises: None
|
||||||
|
Create Date: 2015-02-15 12:14:12
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '006'
|
||||||
|
down_revision = '005'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
MYSQL_ENGINE = 'InnoDB'
|
||||||
|
MYSQL_CHARSET = 'utf8'
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('task', sa.Column('result', sa.types.Text()))
|
||||||
|
# end Alembic commands #
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('task', 'result')
|
||||||
|
# end Alembic commands #
|
@ -133,6 +133,7 @@ class Task(Base, TimestampMixin):
|
|||||||
|
|
||||||
statuses = sa_orm.relationship("Status", backref='task',
|
statuses = sa_orm.relationship("Status", backref='task',
|
||||||
cascade='save-update, merge, delete')
|
cascade='save-update, merge, delete')
|
||||||
|
result = sa.Column(st.JsonBlob(), nullable=True, default={})
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
dictionary = super(Task, self).to_dict()
|
dictionary = super(Task, self).to_dict()
|
||||||
|
@ -38,3 +38,4 @@ def update_task(action, session, task, unit):
|
|||||||
with unit.begin():
|
with unit.begin():
|
||||||
unit.add(session)
|
unit.add(session)
|
||||||
unit.add(task_info)
|
unit.add(task_info)
|
||||||
|
return task_info.id
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import collections
|
||||||
import types
|
import types
|
||||||
|
|
||||||
import murano.dsl.helpers as helpers
|
import murano.dsl.helpers as helpers
|
||||||
@ -24,7 +25,20 @@ class ObjRef(object):
|
|||||||
self.ref_obj = obj
|
self.ref_obj = obj
|
||||||
|
|
||||||
|
|
||||||
def _serialize_tree(root_object, designer_attributes):
|
def serialize_object(obj):
|
||||||
|
if isinstance(obj, (collections.Sequence, collections.Set)):
|
||||||
|
return [serialize_object(t) for t in obj]
|
||||||
|
elif isinstance(obj, collections.Mapping):
|
||||||
|
result = {}
|
||||||
|
for key, value in obj.iteritems():
|
||||||
|
result[key] = serialize_object(value)
|
||||||
|
return result
|
||||||
|
elif isinstance(obj, murano_object.MuranoObject):
|
||||||
|
return _serialize_object(obj, None)[0]
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def _serialize_object(root_object, designer_attributes=None):
|
||||||
serialized_objects = set()
|
serialized_objects = set()
|
||||||
tree = _pass1_serialize(
|
tree = _pass1_serialize(
|
||||||
root_object, None, serialized_objects, designer_attributes)
|
root_object, None, serialized_objects, designer_attributes)
|
||||||
@ -32,15 +46,15 @@ def _serialize_tree(root_object, designer_attributes):
|
|||||||
return tree, serialized_objects
|
return tree, serialized_objects
|
||||||
|
|
||||||
|
|
||||||
def serialize(root_object, executor):
|
def serialize_model(root_object, executor):
|
||||||
if root_object is None:
|
if root_object is None:
|
||||||
tree = None
|
tree = None
|
||||||
tree_copy = None
|
tree_copy = None
|
||||||
attributes = []
|
attributes = []
|
||||||
else:
|
else:
|
||||||
tree, serialized_objects = _serialize_tree(
|
tree, serialized_objects = _serialize_object(
|
||||||
root_object, executor.object_store.designer_attributes)
|
root_object, executor.object_store.designer_attributes)
|
||||||
tree_copy, _ = _serialize_tree(root_object, None)
|
tree_copy, _ = _serialize_object(root_object, None)
|
||||||
attributes = executor.attribute_store.serialize(serialized_objects)
|
attributes = executor.attribute_store.serialize(serialized_objects)
|
||||||
|
|
||||||
return {
|
return {
|
@ -62,8 +62,9 @@ class ActionServices(object):
|
|||||||
task = ActionServices.create_action_task(
|
task = ActionServices.create_action_task(
|
||||||
action_name, target_obj, args,
|
action_name, target_obj, args,
|
||||||
environment, session, token)
|
environment, session, token)
|
||||||
actions_db.update_task(action_name, session, task, unit)
|
task_id = actions_db.update_task(action_name, session, task, unit)
|
||||||
rpc.engine().handle_task(task)
|
rpc.engine().handle_task(task)
|
||||||
|
return task_id
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def execute(action_id, session, unit, token, args={}):
|
def execute(action_id, session, unit, token, args={}):
|
||||||
@ -74,8 +75,9 @@ class ActionServices(object):
|
|||||||
if not action[1].get('enabled', True):
|
if not action[1].get('enabled', True):
|
||||||
raise ValueError('Cannot execute disabled action')
|
raise ValueError('Cannot execute disabled action')
|
||||||
|
|
||||||
ActionServices.submit_task(action[1]['name'], action[0],
|
return ActionServices.submit_task(
|
||||||
args, environment, session, token, unit)
|
action[1]['name'], action[0], args, environment,
|
||||||
|
session, token, unit)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def find_action(model, action_id):
|
def find_action(model, action_id):
|
||||||
@ -104,3 +106,9 @@ class ActionServices(object):
|
|||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_result(environment_id, task_id, unit):
|
||||||
|
task = unit.query(models.Task).filter_by(
|
||||||
|
id=task_id, environment_id=environment_id).first()
|
||||||
|
return task.result
|
||||||
|
@ -94,5 +94,4 @@ class TestActionsApi(tb.ControllerTest, tb.MuranoApiTestCase):
|
|||||||
|
|
||||||
self.mock_engine_rpc.handle_task.assert_called_once_with(rpc_task)
|
self.mock_engine_rpc.handle_task.assert_called_once_with(rpc_task)
|
||||||
|
|
||||||
# Should this be expected behavior?
|
self.assertIn('task_id', result)
|
||||||
self.assertEqual(None, result)
|
|
||||||
|
@ -135,6 +135,10 @@ class MuranoMigrationsCheckers(object):
|
|||||||
self.assertColumnExists(engine, 'environment-template', 'tenant_id')
|
self.assertColumnExists(engine, 'environment-template', 'tenant_id')
|
||||||
self.assertColumnExists(engine, 'environment-template', 'name')
|
self.assertColumnExists(engine, 'environment-template', 'name')
|
||||||
|
|
||||||
|
def _check_006(self, engine, data):
|
||||||
|
self.assertEqual('006', migration.version(engine))
|
||||||
|
self.assertColumnExists(engine, 'task', 'result')
|
||||||
|
|
||||||
|
|
||||||
class TestMigrationsMySQL(MuranoMigrationsCheckers,
|
class TestMigrationsMySQL(MuranoMigrationsCheckers,
|
||||||
base.BaseWalkMigrationTestCase,
|
base.BaseWalkMigrationTestCase,
|
||||||
|
@ -19,7 +19,7 @@ import types
|
|||||||
from murano.dsl import dsl_exception
|
from murano.dsl import dsl_exception
|
||||||
from murano.dsl import executor
|
from murano.dsl import executor
|
||||||
from murano.dsl import murano_object
|
from murano.dsl import murano_object
|
||||||
from murano.dsl import results_serializer
|
from murano.dsl import serializer
|
||||||
from murano.engine import environment
|
from murano.engine import environment
|
||||||
from murano.tests.unit.dsl.foundation import object_model
|
from murano.tests.unit.dsl.foundation import object_model
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ class Runner(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def serialized_model(self):
|
def serialized_model(self):
|
||||||
return results_serializer.serialize(self._root, self.executor)
|
return serializer.serialize_model(self._root, self.executor)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preserve_exception(self):
|
def preserve_exception(self):
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
from murano.dsl import murano_method
|
from murano.dsl import murano_method
|
||||||
from murano.dsl import results_serializer
|
from murano.dsl import serializer
|
||||||
from murano.services import actions
|
from murano.services import actions
|
||||||
from murano.tests.unit import base
|
from murano.tests.unit import base
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ class TestActionsSerializer(base.MuranoTestCase):
|
|||||||
'action3': {'name': 'name3', 'enabled': True},
|
'action3': {'name': 'name3', 'enabled': True},
|
||||||
}
|
}
|
||||||
|
|
||||||
result = results_serializer._merge_actions(old, new)
|
result = serializer._merge_actions(old, new)
|
||||||
|
|
||||||
self.assertEqual(2, len(result))
|
self.assertEqual(2, len(result))
|
||||||
self.assertNotIn('action1', result)
|
self.assertNotIn('action1', result)
|
||||||
@ -50,7 +50,7 @@ class TestActionsSerializer(base.MuranoTestCase):
|
|||||||
'action2': {'name': 'name3', 'enabled': True},
|
'action2': {'name': 'name3', 'enabled': True},
|
||||||
}
|
}
|
||||||
|
|
||||||
result = results_serializer._merge_actions(old, new)
|
result = serializer._merge_actions(old, new)
|
||||||
|
|
||||||
self.assertFalse(result['action1']['enabled'])
|
self.assertFalse(result['action1']['enabled'])
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ class TestActionsSerializer(base.MuranoTestCase):
|
|||||||
def test_object_actions_serialization(self):
|
def test_object_actions_serialization(self):
|
||||||
obj = self._get_mocked_obj()
|
obj = self._get_mocked_obj()
|
||||||
|
|
||||||
obj_actions = results_serializer._serialize_available_action(obj)
|
obj_actions = serializer._serialize_available_action(obj)
|
||||||
|
|
||||||
expected_result = {'name': 'method1', 'enabled': True}
|
expected_result = {'name': 'method1', 'enabled': True}
|
||||||
self.assertIn('id1_method1', obj_actions)
|
self.assertIn('id1_method1', obj_actions)
|
||||||
@ -84,13 +84,13 @@ class TestActionsSerializer(base.MuranoTestCase):
|
|||||||
|
|
||||||
def test_that_only_actions_are_serialized(self):
|
def test_that_only_actions_are_serialized(self):
|
||||||
obj = self._get_mocked_obj()
|
obj = self._get_mocked_obj()
|
||||||
obj_actions = results_serializer._serialize_available_action(obj)
|
obj_actions = serializer._serialize_available_action(obj)
|
||||||
self.assertNotIn('id1_method2', obj_actions)
|
self.assertNotIn('id1_method2', obj_actions)
|
||||||
|
|
||||||
def test_parent_actions_are_serialized(self):
|
def test_parent_actions_are_serialized(self):
|
||||||
obj = self._get_mocked_obj()
|
obj = self._get_mocked_obj()
|
||||||
|
|
||||||
obj_actions = results_serializer._serialize_available_action(obj)
|
obj_actions = serializer._serialize_available_action(obj)
|
||||||
|
|
||||||
expected_result = {'name': 'method3', 'enabled': True}
|
expected_result = {'name': 'method3', 'enabled': True}
|
||||||
self.assertIn('id1_method3', obj_actions)
|
self.assertIn('id1_method3', obj_actions)
|
||||||
|
Loading…
Reference in New Issue
Block a user