Resolve issues with circular dependency

* Resolved issues with circular dependencies
 * Updated objects namespaces to the new io.murano.* namespace
 * Resolved a few issues related to not included code from PoC
 * Renamed objects to more pythonic name (back to original actually)

Closes-bug: #1297146
Change-Id: I34641eca33c70908bd44b50f0956abda9d8dbfa7
This commit is contained in:
Serg Melikyan
2014-03-28 20:07:39 +04:00
parent 3621c57404
commit 5958cced52
37 changed files with 545 additions and 500 deletions

View File

@@ -1,3 +1,3 @@
Namespaces: Namespaces:
=: org.openstack.murano =: io.murano
Name: Application Name: Application

View File

@@ -1,6 +1,6 @@
Namespaces: Namespaces:
=: org.openstack.murano =: io.murano
sys: org.openstack.murano.system sys: io.murano.system
Name: Environment Name: Environment

View File

@@ -1,5 +1,5 @@
Namespaces: Namespaces:
=: org.openstack.murano =: io.murano
Name: Object Name: Object
Workflow: Workflow:

View File

@@ -22,13 +22,13 @@ from oslo.messaging import target
from muranoapi.common import config from muranoapi.common import config
from muranoapi.common.helpers import token_sanitizer from muranoapi.common.helpers import token_sanitizer
from muranoapi.common import rpc from muranoapi.common import rpc
from muranoapi.dsl import executor
from muranoapi.dsl import results_serializer
from muranoapi.engine import environment from muranoapi.engine import environment
from muranoapi.engine import executor from muranoapi.engine import simple_cloader
from muranoapi.engine import results_serializer import muranoapi.engine.system.system_objects as system_objects
from muranoapi.engine import system
from muranoapi.openstack.common.gettextutils import _ # noqa from muranoapi.openstack.common.gettextutils import _ # noqa
from muranoapi.openstack.common import log as logging from muranoapi.openstack.common import log as logging
from muranoapi import simple_cloader
RPC_SERVICE = None RPC_SERVICE = None
@@ -46,7 +46,7 @@ class TaskProcessingEndpoint(object):
env.tenant_id = task['Objects']['?']['tenant_id'] env.tenant_id = task['Objects']['?']['tenant_id']
cl = simple_cloader.SimpleClassLoader(config.CONF.metadata_dir) cl = simple_cloader.SimpleClassLoader(config.CONF.metadata_dir)
system.register(cl, config.CONF.metadata_dir) system_objects.register(cl, config.CONF.metadata_dir)
exc = executor.MuranoDslExecutor(cl, env) exc = executor.MuranoDslExecutor(cl, env)
obj = exc.load(task) obj = exc.load(task)

View File

View File

@@ -12,7 +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.
from muranoapi.engine import objects import muranoapi.dsl.murano_object as murano_object
class AttributeStore(object): class AttributeStore(object):
@@ -20,7 +20,7 @@ class AttributeStore(object):
self._attributes = {} self._attributes = {}
def set(self, tagged_object, owner_type, name, value): def set(self, tagged_object, owner_type, name, value):
if isinstance(value, objects.MuranoObject): if isinstance(value, murano_object.MuranoObject):
value = value.object_id value = value.object_id
key = (tagged_object.object_id, owner_type.name, name) key = (tagged_object.object_id, owner_type.name, name)

View File

@@ -18,13 +18,13 @@ import types
import yaql import yaql
import yaql.context import yaql.context
from muranoapi.engine import classes import muranoapi.dsl.exceptions as exceptions
from muranoapi.engine import exceptions import muranoapi.dsl.helpers as helpers
from muranoapi.engine import helpers import muranoapi.dsl.murano_class as murano_class
from muranoapi.engine import namespaces import muranoapi.dsl.murano_object as murano_object
from muranoapi.engine import objects import muranoapi.dsl.namespace_resolver as namespace_resolver
from muranoapi.engine import principal_objects import muranoapi.dsl.principal_objects as principal_objects
from muranoapi.engine import typespec import muranoapi.dsl.typespec as typespec
class MuranoClassLoader(object): class MuranoClassLoader(object):
@@ -43,22 +43,23 @@ class MuranoClassLoader(object):
else: else:
raise exceptions.NoClassFound(name) raise exceptions.NoClassFound(name)
namespace_resolver = namespaces.NamespaceResolver( namespaces = data.get('Namespaces', {})
data.get('Namespaces', {})) ns_resolver = namespace_resolver.NamespaceResolver(namespaces)
class_parents = data.get('Extends') class_parents = data.get('Extends')
if class_parents: if class_parents:
if not isinstance(class_parents, types.ListType): if not isinstance(class_parents, types.ListType):
class_parents = [class_parents] class_parents = [class_parents]
for i, parent in enumerate(class_parents): for i, parent_name in enumerate(class_parents):
class_parents[i] = self.get_class( full_name = ns_resolver.resolve_name(parent_name)
namespace_resolver.resolve_name(parent)) class_parents[i] = self.get_class(full_name)
type_obj = classes.MuranoClass(self, namespace_resolver, name,
type_obj = murano_class.MuranoClass(self, ns_resolver, name,
class_parents) class_parents)
p_iter = data.get('Properties', {}).iteritems() properties = data.get('Properties', {})
for property_name, property_spec in p_iter: for property_name, property_spec in properties.iteritems():
spec = typespec.PropertySpec(property_spec, namespace_resolver) spec = typespec.PropertySpec(property_spec, ns_resolver)
type_obj.add_property(property_name, spec) type_obj.add_property(property_name, spec)
for method_name, payload in data.get('Workflow', {}).iteritems(): for method_name, payload in data.get('Workflow', {}).iteritems():
@@ -96,16 +97,16 @@ class MuranoClassLoader(object):
else: else:
name = cls.__class__._murano_class_name name = cls.__class__._murano_class_name
murano_class = self.get_class(name, create_missing=True) m_class = self.get_class(name, create_missing=True)
if inspect.isclass(cls): if inspect.isclass(cls):
if issubclass(cls, objects.MuranoObject): if issubclass(cls, murano_object.MuranoObject):
murano_class.object_class = cls m_class.object_class = cls
else: else:
murano_class.object_class = type( mpc_name = 'mpc' + helpers.generate_id()
'mpc' + helpers.generate_id(), bases = (cls, murano_object.MuranoObject)
(cls, objects.MuranoObject), {}) m_class.object_class = type(mpc_name, bases, {})
for item in dir(cls): for item in dir(cls):
method = getattr(cls, item) method = getattr(cls, item)
if callable(method) and not item.startswith('_'): if callable(method) and not item.startswith('_'):
murano_class.add_method(item, method) m_class.add_method(item, method)

View File

@@ -18,23 +18,23 @@ import types
import uuid import uuid
import eventlet import eventlet
from eventlet import event as e_event import eventlet.event
from yaql import context as y_context import yaql.context
from muranoapi.engine import attribute_store as attr_store import muranoapi.dsl.attribute_store as attribute_store
from muranoapi.engine import exceptions import muranoapi.dsl.exceptions as exceptions
from muranoapi.engine import expressions import muranoapi.dsl.expressions as expressions
from muranoapi.engine import helpers import muranoapi.dsl.helpers as helpers
from muranoapi.engine import object_store import muranoapi.dsl.murano_object as murano_object
from muranoapi.engine import objects import muranoapi.dsl.object_store as object_store
from muranoapi.engine import yaql_functions import muranoapi.dsl.yaql_functions as yaql_functions
class MuranoDslExecutor(object): class MuranoDslExecutor(object):
def __init__(self, class_loader, environment=None): def __init__(self, class_loader, environment=None):
self._class_loader = class_loader self._class_loader = class_loader
self._object_store = object_store.ObjectStore(class_loader) self._object_store = object_store.ObjectStore(class_loader)
self._attribute_store = attr_store.AttributeStore() self._attribute_store = attribute_store.AttributeStore()
self._root_context = class_loader.create_root_context() self._root_context = class_loader.create_root_context()
self._root_context.set_data(self, '?executor') self._root_context.set_data(self, '?executor')
self._root_context.set_data(self._class_loader, '?classLoader') self._root_context.set_data(self._class_loader, '?classLoader')
@@ -43,7 +43,7 @@ class MuranoDslExecutor(object):
self._root_context.set_data(self._attribute_store, '?attributeStore') self._root_context.set_data(self._attribute_store, '?attributeStore')
self._locks = {} self._locks = {}
yaql_functions.register(self._root_context) yaql_functions.register(self._root_context)
self._root_context = y_context.Context(self._root_context) self._root_context = yaql.context.Context(self._root_context)
@property @property
def object_store(self): def object_store(self):
@@ -80,7 +80,6 @@ class MuranoDslExecutor(object):
params = self._evaluate_parameters( params = self._evaluate_parameters(
arguments_scheme, context, this, *args) arguments_scheme, context, this, *args)
except Exception: except Exception:
# TODO(slagun): print exception
params = self._evaluate_parameters( params = self._evaluate_parameters(
arguments_scheme, context, this, *args) arguments_scheme, context, this, *args)
delegates.append(functools.partial( delegates.append(functools.partial(
@@ -118,7 +117,7 @@ class MuranoDslExecutor(object):
body, this, params, murano_class, context) body, this, params, murano_class, context)
event.wait() event.wait()
event = e_event.Event() event = eventlet.event.Event()
self._locks[(method_id, this_id)] = (event, thread_marker) self._locks[(method_id, this_id)] = (event, thread_marker)
gt = eventlet.spawn(self._invoke_method_implementation_gt, body, gt = eventlet.spawn(self._invoke_method_implementation_gt, body,
this, params, murano_class, context, this, params, murano_class, context,
@@ -191,13 +190,13 @@ class MuranoDslExecutor(object):
new_context.set_data(murano_class, '?type') new_context.set_data(murano_class, '?type')
new_context.set_data(context, '?callerContext') new_context.set_data(context, '?callerContext')
@y_context.EvalArg('obj', arg_type=objects.MuranoObject) @yaql.context.EvalArg('obj', arg_type=murano_object.MuranoObject)
@y_context.EvalArg('property_name', arg_type=str) @yaql.context.EvalArg('property_name', arg_type=str)
def obj_attribution(obj, property_name): def obj_attribution(obj, property_name):
return obj.get_property(property_name, murano_class) return obj.get_property(property_name, murano_class)
@y_context.EvalArg('prefix', str) @yaql.context.EvalArg('prefix', str)
@y_context.EvalArg('name', str) @yaql.context.EvalArg('name', str)
def validate(prefix, name): def validate(prefix, name):
return murano_class.namespace_resolver.resolve_name( return murano_class.namespace_resolver.resolve_name(
'%s:%s' % (prefix, name)) '%s:%s' % (prefix, name))

View File

@@ -14,10 +14,9 @@
import types import types
from muranoapi.engine import helpers import muranoapi.dsl.helpers as helpers
from muranoapi.engine import lhs_expression as lhs import muranoapi.dsl.lhs_expression as lhs_expression
from muranoapi.engine import yaql_expression import muranoapi.dsl.yaql_expression as yaql_expression
_macros = [] _macros = []
@@ -44,7 +43,7 @@ class Statement(DslExpression):
else: else:
raise SyntaxError() raise SyntaxError()
self._destination = None if not key else lhs.LhsExpression(key) self._destination = lhs_expression.LhsExpression(key) if key else None
self._expression = value self._expression = value
@property @property

View File

@@ -14,105 +14,39 @@
import collections import collections
import re import re
import sys
import types import types
import uuid import uuid
import deep import deep
from eventlet import greenpool import eventlet.greenpool
import yaql import yaql.expressions
from muranoapi.engine import consts import muranoapi.dsl.murano_object
from muranoapi.engine import yaql_expression import muranoapi.dsl.yaql_expression as yaql_expression
def merge_lists(list1, list2): def serialize(value, memo=None):
result = [] if memo is None:
for item in list1 + list2: memo = set()
exists = False if isinstance(value, types.DictionaryType):
for old_item in result:
if deep.diff(item, old_item) is None:
exists = True
break
if not exists:
result.append(item)
return result
def merge_dicts(dict1, dict2, max_levels=0):
result = {} result = {}
for key, value in dict1.items(): for d_key, d_value in value.iteritems():
result[key] = value result[d_key] = serialize(d_value, memo)
if key in dict2:
other_value = dict2[key]
if type(other_value) != type(value):
raise TypeError()
if max_levels != 1 and isinstance(
other_value, types.DictionaryType):
result[key] = merge_dicts(
value, other_value,
0 if max_levels == 0 else max_levels - 1)
elif max_levels != 1 and isinstance(
other_value, types.ListType):
result[key] = merge_lists(value, other_value)
else:
result[key] = other_value
for key, value in dict2.items():
if key not in result:
result[key] = value
return result return result
elif isinstance(value, muranoapi.dsl.murano_object.MuranoObject):
if not value.object_id in memo:
memo.add(value.object_id)
return serialize(value.to_dictionary(), memo)
else:
return value.object_id
elif isinstance(value, types.ListType):
return [serialize(t, memo) for t in value]
else:
return value
def parallel_select(collection, func): def evaluate(value, context, max_depth=sys.maxint):
gp = greenpool.GreenPool()
return list(gp.imap(func, collection))
def to_python_codestyle(name):
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def enum(**enums):
return type('Enum', (), enums)
def get_executor(context):
return context.get_data('$?executor')
def get_class_loader(context):
return context.get_data('$?classLoader')
def get_type(context):
return context.get_data('$?type')
def get_environment(context):
return context.get_data('$?environment')
def get_object_store(context):
return context.get_data('$?objectStore')
def get_this(context):
return context.get_data('$?this')
def get_caller_context(context):
return context.get_data('$?callerContext')
def get_attribute_store(context):
return context.get_data('$?attributeStore')
def generate_id():
return uuid.uuid4().hex
def evaluate(value, context, max_depth=consts.EVALUATION_MAX_DEPTH):
if isinstance(value, (yaql_expression.YaqlExpression, if isinstance(value, (yaql_expression.YaqlExpression,
yaql.expressions.Expression)): yaql.expressions.Expression)):
func = lambda: evaluate(value.evaluate(context), context, 1) func = lambda: evaluate(value.evaluate(context), context, 1)
@@ -156,3 +90,90 @@ def needs_evaluation(value):
if needs_evaluation(t): if needs_evaluation(t):
return True return True
return False return False
def merge_lists(list1, list2):
result = []
for item in list1 + list2:
exists = False
for old_item in result:
if deep.diff(item, old_item) is None:
exists = True
break
if not exists:
result.append(item)
return result
def merge_dicts(dict1, dict2, max_levels=0):
result = {}
for key, value in dict1.items():
result[key] = value
if key in dict2:
other_value = dict2[key]
if type(other_value) != type(value):
raise TypeError()
if max_levels != 1 and isinstance(
other_value, types.DictionaryType):
result[key] = merge_dicts(
value, other_value,
0 if max_levels == 0 else max_levels - 1)
elif max_levels != 1 and isinstance(
other_value, types.ListType):
result[key] = merge_lists(value, other_value)
else:
result[key] = other_value
for key, value in dict2.items():
if key not in result:
result[key] = value
return result
def generate_id():
return uuid.uuid4().hex
def parallel_select(collection, func):
gpool = eventlet.greenpool.GreenPool()
return list(gpool.imap(func, collection))
def to_python_codestyle(name):
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def enum(**enums):
return type('Enum', (), enums)
def get_executor(context):
return context.get_data('$?executor')
def get_class_loader(context):
return context.get_data('$?classLoader')
def get_type(context):
return context.get_data('$?type')
def get_environment(context):
return context.get_data('$?environment')
def get_object_store(context):
return context.get_data('$?objectStore')
def get_this(context):
return context.get_data('$?this')
def get_caller_context(context):
return context.get_data('$?callerContext')
def get_attribute_store(context):
return context.get_data('$?attributeStore')

View File

@@ -15,12 +15,12 @@
import types import types
import yaql import yaql
from yaql import context as y_context import yaql.context
import yaql.expressions import yaql.expressions
from muranoapi.engine import objects import muranoapi.dsl.murano_object as murano_object
from muranoapi.engine import type_scheme import muranoapi.dsl.type_scheme as type_scheme
from muranoapi.engine import yaql_expression as y_expression import muranoapi.dsl.yaql_expression as yaql_expression
class LhsExpression(object): class LhsExpression(object):
@@ -36,7 +36,7 @@ class LhsExpression(object):
self._setter(value) self._setter(value)
def __init__(self, expression): def __init__(self, expression):
if isinstance(expression, (y_expression.YaqlExpression, if isinstance(expression, (yaql_expression.YaqlExpression,
yaql.expressions.Expression)): yaql.expressions.Expression)):
self._expression = expression self._expression = expression
else: else:
@@ -51,7 +51,7 @@ class LhsExpression(object):
elif isinstance(src, types.ListType) and isinstance( elif isinstance(src, types.ListType) and isinstance(
key, types.IntType): key, types.IntType):
return src[key] return src[key]
elif isinstance(src, objects.MuranoObject) and isinstance( elif isinstance(src, murano_object.MuranoObject) and isinstance(
key, types.StringTypes): key, types.StringTypes):
self._current_obj = src self._current_obj = src
self._current_obj_name = key self._current_obj_name = key
@@ -89,7 +89,7 @@ class LhsExpression(object):
src[key] = old_value src[key] = old_value
raise e raise e
elif isinstance(src, objects.MuranoObject) and isinstance( elif isinstance(src, murano_object.MuranoObject) and isinstance(
key, types.StringTypes): key, types.StringTypes):
self._current_spec = src.type.find_property(key) self._current_spec = src.type.find_property(key)
src.set_property(key, value, murano_class) src.set_property(key, value, murano_class)
@@ -107,20 +107,20 @@ class LhsExpression(object):
return LhsExpression.Property( return LhsExpression.Property(
lambda: root_context.get_data(path), set_data) lambda: root_context.get_data(path), set_data)
@y_context.EvalArg('this', arg_type=LhsExpression.Property) @yaql.context.EvalArg('this', arg_type=LhsExpression.Property)
def attribution(this, arg_name): def attribution(this, arg_name):
arg_name = arg_name() arg_name = arg_name()
return LhsExpression.Property( return LhsExpression.Property(
lambda: _get_value(this.get(), arg_name), lambda: _get_value(this.get(), arg_name),
lambda value: _set_value(this.get(), arg_name, value)) lambda value: _set_value(this.get(), arg_name, value))
@y_context.EvalArg("this", LhsExpression.Property) @yaql.context.EvalArg("this", LhsExpression.Property)
def indexation(this, index): def indexation(this, index):
return LhsExpression.Property( return LhsExpression.Property(
lambda: _get_value(this.get(), index()), lambda: _get_value(this.get(), index()),
lambda value: _set_value(this.get(), index(), value)) lambda value: _set_value(this.get(), index(), value))
context = y_context.Context() context = yaql.context.Context()
context.register_function(get_context_data, '#get_context_data') context.register_function(get_context_data, '#get_context_data')
context.register_function(attribution, '#operator_.') context.register_function(attribution, '#operator_.')
context.register_function(indexation, "where") context.register_function(indexation, "where")

View File

@@ -14,13 +14,13 @@
import types import types
from eventlet import greenpool import eventlet.greenpool as greenpool
from yaql import context as y_context import yaql.context
from muranoapi.engine import exceptions import muranoapi.dsl.exceptions as exceptions
from muranoapi.engine import expressions import muranoapi.dsl.expressions as expressions
from muranoapi.engine import helpers import muranoapi.dsl.helpers as helpers
from muranoapi.engine import yaql_expression import muranoapi.dsl.yaql_expression as yaql_expression
class CodeBlock(expressions.DslExpression): class CodeBlock(expressions.DslExpression):
@@ -81,10 +81,10 @@ class ParallelMacro(CodeBlock):
def execute(self, context, murano_class): def execute(self, context, murano_class):
if not self.code_block: if not self.code_block:
return return
gp = greenpool.GreenPool(helpers.evaluate(self._limit, context)) gpool = greenpool.GreenPool(helpers.evaluate(self._limit, context))
for expr in self.code_block: for expr in self.code_block:
gp.spawn_n(expr.execute, context, murano_class) gpool.spawn_n(expr.execute, context, murano_class)
gp.waitall() gpool.waitall()
class IfMacro(expressions.DslExpression): class IfMacro(expressions.DslExpression):
@@ -136,7 +136,7 @@ class ForMacro(expressions.DslExpression):
def execute(self, context, murano_class): def execute(self, context, murano_class):
collection = helpers.evaluate(self._collection, context) collection = helpers.evaluate(self._collection, context)
child_context = y_context.Context(context) child_context = yaql.context.Context(context)
for t in collection: for t in collection:
child_context.set_data(t, self._var) child_context.set_data(t, self._var)
try: try:
@@ -189,8 +189,7 @@ class SwitchMacro(expressions.DslExpression):
def execute(self, context, murano_class): def execute(self, context, murano_class):
matched = False matched = False
for key, value in self._switch.iteritems(): for key, value in self._switch.iteritems():
if not isinstance(key, if not isinstance(key, (yaql_expression.YaqlExpression,
(yaql_expression.YaqlExpression,
types.BooleanType)): types.BooleanType)):
raise SyntaxError() raise SyntaxError()
res = helpers.evaluate(key, context) res = helpers.evaluate(key, context)
@@ -198,7 +197,7 @@ class SwitchMacro(expressions.DslExpression):
raise TypeError() raise TypeError()
if res: if res:
matched = True matched = True
child_context = y_context.Context(context) child_context = yaql.context.Context(context)
CodeBlock(value).execute(child_context, murano_class) CodeBlock(value).execute(child_context, murano_class)
if self._default is not None and not matched: if self._default is not None and not matched:
@@ -210,7 +209,7 @@ class DoMacro(expressions.DslExpression):
self._code = CodeBlock(Do) self._code = CodeBlock(Do)
def execute(self, context, murano_class): def execute(self, context, murano_class):
child_context = y_context.Context(context) child_context = yaql.context.Context(context)
self._code.execute(child_context, murano_class) self._code.execute(child_context, murano_class)

View File

@@ -15,10 +15,10 @@
import collections import collections
import inspect import inspect
from muranoapi.engine import helpers import muranoapi.dsl.helpers as helpers
from muranoapi.engine import methods as engine_methods import muranoapi.dsl.murano_method as murano_method
from muranoapi.engine import objects import muranoapi.dsl.murano_object as murano_object
from muranoapi.engine import typespec import muranoapi.dsl.typespec as typespec
def classname(name): def classname(name):
@@ -35,16 +35,17 @@ class MuranoClass(object):
self._namespace_resolver = namespace_resolver self._namespace_resolver = namespace_resolver
self._name = namespace_resolver.resolve_name(name) self._name = namespace_resolver.resolve_name(name)
self._properties = {} self._properties = {}
if self._name == 'org.openstack.murano.Object': if self._name == 'io.murano.Object':
self._parents = [] self._parents = []
else: else:
self._parents = parents if parents is not None else [ self._parents = parents or [
class_loader.get_class('org.openstack.murano.Object')] class_loader.get_class('io.murano.Object')]
self.object_class = type(
'mc' + helpers.generate_id(), class_name = 'mc' + helpers.generate_id()
tuple([p.object_class for p in self._parents]) or ( parents_class = [p.object_class for p in self._parents]
objects.MuranoObject,), bases = tuple(parents_class) or (murano_object.MuranoObject,)
{})
self.object_class = type(class_name, bases, {})
@property @property
def name(self): def name(self):
@@ -58,6 +59,19 @@ class MuranoClass(object):
def parents(self): def parents(self):
return self._parents return self._parents
@property
def methods(self):
return self._methods
def get_method(self, name):
return self._methods.get(name)
def add_method(self, name, payload):
method = murano_method.MuranoMethod(self._namespace_resolver,
self, name, payload)
self._methods[name] = method
return method
@property @property
def properties(self): def properties(self):
return self._properties.keys() return self._properties.keys()
@@ -71,6 +85,7 @@ class MuranoClass(object):
return self._properties[name] return self._properties[name]
def find_method(self, name): def find_method(self, name):
#resolved_name = self._namespace_resolver.resolve_name(name, self.name)
if name in self._methods: if name in self._methods:
return [(self, name)] return [(self, name)]
if not self._parents: if not self._parents:
@@ -88,27 +103,12 @@ class MuranoClass(object):
types.extend(mc.parents) types.extend(mc.parents)
return None return None
@property
def methods(self):
return self._methods
def get_method(self, name):
return self._methods.get(name)
def add_method(self, name, payload):
#name = self._namespace_resolver.resolve_name(name, self.name)
method = engine_methods.MuranoMethod(
self._namespace_resolver,
self, name, payload)
self._methods[name] = method
return method
def invoke(self, name, executor, this, parameters): def invoke(self, name, executor, this, parameters):
args = executor.to_yaql_args(parameters) args = executor.to_yaql_args(parameters)
return executor.invoke_method(name, this, None, self, *args) return executor.invoke_method(name, this, None, self, *args)
def is_compatible(self, obj): def is_compatible(self, obj):
if isinstance(obj, objects.MuranoObject): if isinstance(obj, murano_object.MuranoObject):
return self.is_compatible(obj.type) return self.is_compatible(obj.type)
if obj is self: if obj is self:
return True return True

View File

@@ -13,13 +13,16 @@
# under the License. # under the License.
import inspect import inspect
import ordereddict
import types import types
import muranoapi.dsl.macros as macros
import muranoapi.dsl.typespec as typespec
import muranoapi.dsl.yaql_expression as yaql_expression
from muranoapi.engine import macros try:
from muranoapi.engine import typespec from collections import OrderedDict # noqa
from muranoapi.engine import yaql_expression except ImportError: # python2.6
from ordereddict import OrderedDict # noqa
class MuranoMethod(object): class MuranoMethod(object):
@@ -38,7 +41,7 @@ class MuranoMethod(object):
if isinstance(arguments_scheme, types.DictionaryType): if isinstance(arguments_scheme, types.DictionaryType):
arguments_scheme = [{key: value} for key, value in arguments_scheme = [{key: value} for key, value in
arguments_scheme.iteritems()] arguments_scheme.iteritems()]
self._arguments_scheme = ordereddict.OrderedDict() self._arguments_scheme = OrderedDict()
for record in arguments_scheme: for record in arguments_scheme:
if not isinstance(record, types.DictionaryType) \ if not isinstance(record, types.DictionaryType) \
or len(record) > 1: or len(record) > 1:
@@ -74,7 +77,7 @@ class MuranoMethod(object):
defaults = func_info.defaults or tuple() defaults = func_info.defaults or tuple()
for i in xrange(len(defaults)): for i in xrange(len(defaults)):
data[i + len(data) - len(defaults)][1]['Default'] = defaults[i] data[i + len(data) - len(defaults)][1]['Default'] = defaults[i]
result = ordereddict.OrderedDict([ result = OrderedDict([
(name, typespec.ArgumentSpec( (name, typespec.ArgumentSpec(
declaration, self._namespace_resolver)) declaration, self._namespace_resolver))
for name, declaration in data]) for name, declaration in data])

View File

@@ -12,20 +12,25 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from yaql import context import types
from muranoapi.engine import consts import yaml
from muranoapi.engine import exceptions import yaql.context
from muranoapi.engine import helpers
import muranoapi.dsl.exceptions as exceptions
import muranoapi.dsl.helpers
import muranoapi.dsl.type_scheme as type_scheme
import muranoapi.dsl.typespec as typespec
class MuranoObject(object): class MuranoObject(object):
def __init__(self, murano_class, parent_obj, object_store, context, def __init__(self, murano_class, parent_obj, object_store, context,
object_id=None, known_classes=None, defaults=None): object_id=None, known_classes=None, defaults=None):
if known_classes is None: if known_classes is None:
known_classes = {} known_classes = {}
self.__parent_obj = parent_obj self.__parent_obj = parent_obj
self.__object_id = object_id or helpers.generate_id() self.__object_id = object_id or muranoapi.dsl.helpers.generate_id()
self.__type = murano_class self.__type = murano_class
self.__properties = {} self.__properties = {}
self.__object_store = object_store self.__object_store = object_store
@@ -35,13 +40,13 @@ class MuranoObject(object):
known_classes[murano_class.name] = self known_classes[murano_class.name] = self
for parent_class in murano_class.parents: for parent_class in murano_class.parents:
name = parent_class.name name = parent_class.name
if not name in known_classes: if name not in known_classes:
obj = parent_class.new( obj = parent_class.new(parent_obj, object_store, context,
parent_obj, object_store, context, None, None, object_id=self.__object_id,
object_id=self.__object_id,
known_classes=known_classes, known_classes=known_classes,
defaults=defaults) defaults=defaults)
known_classes[name] = self.__parents[name] = obj
self.__parents[name] = known_classes[name] = obj
else: else:
self.__parents[name] = known_classes[name] self.__parents[name] = known_classes[name]
@@ -50,11 +55,12 @@ class MuranoObject(object):
for i in xrange(2): for i in xrange(2):
for property_name in self.__type.properties: for property_name in self.__type.properties:
spec = self.__type.get_property(property_name) spec = self.__type.get_property(property_name)
if i == 0 and helpers.needs_evaluation(spec.default) \ needs_evaluation = muranoapi.dsl.helpers.needs_evaluation
or i == 1 and property_name in used_names: if i == 0 and needs_evaluation(spec.default) or i == 1\
and property_name in used_names:
continue continue
used_names.add(property_name) used_names.add(property_name)
property_value = kwargs.get(property_name, consts.NoValue) property_value = kwargs.get(property_name, type_scheme.NoValue)
self.set_property(property_name, property_value) self.set_property(property_name, property_value)
for parent in self.__parents.values(): for parent in self.__parents.values():
parent.initialize(**kwargs) parent.initialize(**kwargs)
@@ -123,14 +129,15 @@ class MuranoObject(object):
def __set_property(self, key, value, caller_class=None): def __set_property(self, key, value, caller_class=None):
if key in self.__type.properties: if key in self.__type.properties:
spec = self.__type.get_property(key) spec = self.__type.get_property(key)
if (caller_class is not None and if caller_class is not None \
not caller_class.is_compatible(self)): and (spec.type not in typespec.PropertyTypes.Writable
or not caller_class.is_compatible(self)):
raise exceptions.NoWriteAccess(key) raise exceptions.NoWriteAccess(key)
default = self.__defaults.get(key, spec.default) default = self.__defaults.get(key, spec.default)
child_context = context.Context(parent_context=self.__context) child_context = yaql.context.Context(parent_context=self.__context)
child_context.set_data(self) child_context.set_data(self)
default = helpers.evaluate(default, child_context, 1) default = muranoapi.dsl.helpers.evaluate(default, child_context, 1)
self.__properties[key] = spec.validate( self.__properties[key] = spec.validate(
value, self, self.__context, self.__object_store, default) value, self, self.__context, self.__object_store, default)
@@ -143,12 +150,42 @@ class MuranoObject(object):
continue continue
raise AttributeError(key) raise AttributeError(key)
def cast(self, _type): def cast(self, type):
if self.type == _type: if self.type == type:
return self return self
for parent in self.__parents.values(): for parent in self.__parents.values():
try: try:
return parent.cast(_type) return parent.cast(type)
except TypeError: except TypeError:
continue continue
raise TypeError('Cannot cast') raise TypeError('Cannot cast')
def __repr__(self):
return yaml.safe_dump(muranoapi.dsl.helpers.serialize(self))
def to_dictionary(self, include_hidden=False):
result = {}
for parent in self.__parents.values():
result.update(parent.to_dictionary(include_hidden))
result.update({'?': {'type': self.type.name, 'id': self.object_id}})
if include_hidden:
result.update(self.__properties)
else:
for property_name in self.type.properties:
if property_name in self.__properties:
spec = self.type.get_property(property_name)
if spec.type != typespec.PropertyTypes.Runtime:
result[property_name] = \
self.__properties[property_name]
return result
def __merge_default(self, src, defaults):
if src is None:
return
if type(src) != type(defaults):
raise ValueError()
if isinstance(defaults, types.DictionaryType):
for key, value in defaults.iteritems():
src_value = src.get(key)
if src_value is None:
continue

View File

@@ -14,7 +14,7 @@
import inspect import inspect
from muranoapi.engine import helpers import muranoapi.dsl.helpers as helpers
class ObjectStore(object): class ObjectStore(object):
@@ -48,7 +48,6 @@ class ObjectStore(object):
if '?' not in value or 'type' not in value['?']: if '?' not in value or 'type' not in value['?']:
raise ValueError() raise ValueError()
system_key = value['?'] system_key = value['?']
#del value['?']
object_id = system_key['id'] object_id = system_key['id']
obj_type = system_key['type'] obj_type = system_key['type']
class_obj = self._class_loader.get_class(obj_type) class_obj = self._class_loader.get_class(obj_type)
@@ -83,5 +82,4 @@ class ObjectStore(object):
methods = obj.type.find_method('initialize') methods = obj.type.find_method('initialize')
for cls, method in methods: for cls, method in methods:
cls.invoke(method, executor, obj, {}) cls.invoke(method, executor, obj, {})
# self._store.update(tmp_store._store)
return obj return obj

View File

@@ -0,0 +1,6 @@
import muranoapi.dsl.principal_objects.sys_object
def register(class_loader):
sys_object = muranoapi.dsl.principal_objects.sys_object
class_loader.import_class(sys_object.SysObject)

View File

@@ -12,16 +12,16 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from muranoapi.engine import classes import muranoapi.dsl.helpers as helpers
from muranoapi.engine import helpers import muranoapi.dsl.murano_class as murano_class
@classes.classname('org.openstack.murano.Object') @murano_class.classname('io.murano.Object')
class SysObject(object): class SysObject(object):
def setAttr(self, _context, name, value, owner=None): def setAttr(self, _context, name, value, owner=None):
if owner is None: if owner is None:
owner = helpers.get_type(helpers.get_caller_context(_context)) owner = helpers.get_type(helpers.get_caller_context(_context))
if not isinstance(owner, classes.MuranoClass): if not isinstance(owner, murano_class.MuranoClass):
raise TypeError() raise TypeError()
attribute_store = helpers.get_attribute_store(_context) attribute_store = helpers.get_attribute_store(_context)
@@ -30,7 +30,7 @@ class SysObject(object):
def getAttr(self, _context, name, owner=None): def getAttr(self, _context, name, owner=None):
if owner is None: if owner is None:
owner = helpers.get_type(helpers.get_caller_context(_context)) owner = helpers.get_type(helpers.get_caller_context(_context))
if not isinstance(owner, classes.MuranoClass): if not isinstance(owner, murano_class.MuranoClass):
raise TypeError() raise TypeError()
attribute_store = helpers.get_attribute_store(_context) attribute_store = helpers.get_attribute_store(_context)

View File

@@ -14,7 +14,7 @@
import types import types
from muranoapi.engine import objects import muranoapi.dsl.murano_object as murano_object
class ObjRef(object): class ObjRef(object):
@@ -45,7 +45,7 @@ def _pass1_serialize(value, parent, serialized_objects):
if isinstance(value, (types.StringTypes, types.IntType, types.FloatType, if isinstance(value, (types.StringTypes, types.IntType, types.FloatType,
types.BooleanType, types.NoneType)): types.BooleanType, types.NoneType)):
return value return value
elif isinstance(value, objects.MuranoObject): elif isinstance(value, murano_object.MuranoObject):
if not _cmp_objects(value.parent, parent) \ if not _cmp_objects(value.parent, parent) \
or value.object_id in serialized_objects: or value.object_id in serialized_objects:
return ObjRef(value) return ObjRef(value)

View File

@@ -16,12 +16,14 @@ import sys
import types import types
import uuid import uuid
from yaql import context as y_context import yaql.context
from muranoapi.engine import consts import muranoapi.dsl.helpers
from muranoapi.engine import helpers import muranoapi.dsl.murano_object
from muranoapi.engine import objects import muranoapi.dsl.yaql_expression as yaql_expression
from muranoapi.engine import yaql_expression
NoValue = object()
class TypeScheme(object): class TypeScheme(object):
@@ -37,7 +39,7 @@ class TypeScheme(object):
namespace_resolver, default): namespace_resolver, default):
def _int(value): def _int(value):
value = value() value = value()
if value is consts.NoValue: if value is NoValue:
value = default value = default
if value is None: if value is None:
return None return None
@@ -48,7 +50,7 @@ class TypeScheme(object):
def _string(value): def _string(value):
value = value() value = value()
if value is consts.NoValue: if value is NoValue:
value = default value = default
if value is None: if value is None:
return None return None
@@ -59,7 +61,7 @@ class TypeScheme(object):
def _bool(value): def _bool(value):
value = value() value = value()
if value is consts.NoValue: if value is NoValue:
value = default value = default
if value is None: if value is None:
return None return None
@@ -85,8 +87,11 @@ class TypeScheme(object):
else: else:
raise TypeError(value) raise TypeError(value)
@y_context.EvalArg('obj', arg_type=(objects.MuranoObject, @yaql.context.EvalArg('obj', arg_type=(
TypeScheme.ObjRef, types.NoneType)) muranoapi.dsl.murano_object.MuranoObject,
TypeScheme.ObjRef,
types.NoneType
))
def _owned(obj): def _owned(obj):
if isinstance(obj, TypeScheme.ObjRef): if isinstance(obj, TypeScheme.ObjRef):
return obj return obj
@@ -98,8 +103,11 @@ class TypeScheme(object):
else: else:
raise TypeError() raise TypeError()
@y_context.EvalArg('obj', arg_type=(objects.MuranoObject, @yaql.context.EvalArg('obj', arg_type=(
TypeScheme.ObjRef, types.NoneType)) muranoapi.dsl.murano_object.MuranoObject,
TypeScheme.ObjRef,
types.NoneType
))
def _not_owned(obj): def _not_owned(obj):
if isinstance(obj, TypeScheme.ObjRef): if isinstance(obj, TypeScheme.ObjRef):
return obj return obj
@@ -111,12 +119,12 @@ class TypeScheme(object):
else: else:
return obj return obj
@y_context.EvalArg('name', arg_type=str) @yaql.context.EvalArg('name', arg_type=str)
def _class(value, name): def _class(value, name):
return _class2(value, name, None) return _class2(value, name, None)
@y_context.EvalArg('name', arg_type=str) @yaql.context.EvalArg('name', arg_type=str)
@y_context.EvalArg('default_name', arg_type=(str, types.NoneType)) @yaql.context.EvalArg('default_name', arg_type=(str, types.NoneType))
def _class2(value, name, default_name): def _class2(value, name, default_name):
name = namespace_resolver.resolve_name(name) name = namespace_resolver.resolve_name(name)
if not default_name: if not default_name:
@@ -124,20 +132,20 @@ class TypeScheme(object):
else: else:
default_name = namespace_resolver.resolve_name(default_name) default_name = namespace_resolver.resolve_name(default_name)
value = value() value = value()
if value is consts.NoValue: if value is NoValue:
value = default value = default
if isinstance(default, types.DictionaryType): if isinstance(default, types.DictionaryType):
value = {'?': { value = {'?': {
'id': uuid.uuid4().hex, 'id': uuid.uuid4().hex,
'type': default_name 'type': default_name
}} }}
class_loader = helpers.get_class_loader(root_context) class_loader = muranoapi.dsl.helpers.get_class_loader(root_context)
murano_class = class_loader.get_class(name) murano_class = class_loader.get_class(name)
if not murano_class: if not murano_class:
raise TypeError() raise TypeError()
if value is None: if value is None:
return None return None
if isinstance(value, objects.MuranoObject): if isinstance(value, muranoapi.dsl.murano_object.MuranoObject):
obj = value obj = value
elif isinstance(value, types.DictionaryType): elif isinstance(value, types.DictionaryType):
obj = object_store.load(value, this, root_context, obj = object_store.load(value, this, root_context,
@@ -155,13 +163,13 @@ class TypeScheme(object):
raise TypeError() raise TypeError()
return obj return obj
@y_context.EvalArg('prefix', str) @yaql.context.EvalArg('prefix', str)
@y_context.EvalArg('name', str) @yaql.context.EvalArg('name', str)
def _validate(prefix, name): def _validate(prefix, name):
return namespace_resolver.resolve_name( return namespace_resolver.resolve_name(
'%s:%s' % (prefix, name)) '%s:%s' % (prefix, name))
context = y_context.Context(parent_context=root_context) context = yaql.context.Context(parent_context=root_context)
context.register_function(_validate, '#validate') context.register_function(_validate, '#validate')
context.register_function(_int, 'int') context.register_function(_int, 'int')
context.register_function(_string, 'string') context.register_function(_string, 'string')
@@ -176,7 +184,7 @@ class TypeScheme(object):
return context return context
def _map_dict(self, data, spec, context): def _map_dict(self, data, spec, context):
if data is None or data is consts.NoValue: if data is None or data is NoValue:
data = {} data = {}
if not isinstance(data, types.DictionaryType): if not isinstance(data, types.DictionaryType):
raise TypeError() raise TypeError()
@@ -205,7 +213,7 @@ class TypeScheme(object):
def _map_list(self, data, spec, context): def _map_list(self, data, spec, context):
if not isinstance(data, types.ListType): if not isinstance(data, types.ListType):
if data is None or data is consts.NoValue: if data is None or data is NoValue:
data = [] data = []
else: else:
data = [data] data = [data]
@@ -239,7 +247,7 @@ class TypeScheme(object):
return data return data
def _map(self, data, spec, context): def _map(self, data, spec, context):
child_context = y_context.Context(parent_context=context) child_context = yaql.context.Context(parent_context=context)
if isinstance(spec, yaql_expression.YaqlExpression): if isinstance(spec, yaql_expression.YaqlExpression):
child_context.set_data(data) child_context.set_data(data)
return spec.evaluate(context=child_context) return spec.evaluate(context=child_context)
@@ -258,6 +266,6 @@ class TypeScheme(object):
context, this, object_store, namespace_resolver, context, this, object_store, namespace_resolver,
default) default)
result = self._map(data, self._spec, context) result = self._map(data, self._spec, context)
if result is consts.NoValue: if result is NoValue:
raise TypeError('No type specified') raise TypeError('No type specified')
return result return result

View File

@@ -12,7 +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.
from muranoapi.engine import type_scheme import muranoapi.dsl.type_scheme as type_scheme
class PropertyTypes(object): class PropertyTypes(object):

View File

@@ -12,21 +12,21 @@
# 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 eventlet
import itertools import itertools
import types import types
from yaql import context as y_context import eventlet
import yaql.context
import yaql.exceptions import yaql.exceptions
from muranoapi.engine import exceptions import muranoapi.dsl.exceptions as exceptions
from muranoapi.engine import helpers import muranoapi.dsl.helpers as helpers
from muranoapi.engine import objects import muranoapi.dsl.murano_object as murano_object
def _resolve(name, obj): def _resolve(name, obj):
@y_context.EvalArg('this', objects.MuranoObject) @yaql.context.EvalArg('this', murano_object.MuranoObject)
@y_context.ContextAware() @yaql.context.ContextAware()
def invoke(context, this, *args): def invoke(context, this, *args):
try: try:
executor = helpers.get_executor(context) executor = helpers.get_executor(context)
@@ -38,20 +38,20 @@ def _resolve(name, obj):
except exceptions.AmbiguousMethodName: except exceptions.AmbiguousMethodName:
raise yaql.exceptions.YaqlExecutionException() raise yaql.exceptions.YaqlExecutionException()
if not isinstance(obj, objects.MuranoObject): if not isinstance(obj, murano_object.MuranoObject):
return None return None
return invoke return invoke
@y_context.EvalArg('value', objects.MuranoObject) @yaql.context.EvalArg('value', murano_object.MuranoObject)
def _id(value): def _id(value):
return value.object_id return value.object_id
@y_context.EvalArg('value', objects.MuranoObject) @yaql.context.EvalArg('value', murano_object.MuranoObject)
@y_context.EvalArg('type', str) @yaql.context.EvalArg('type', str)
@y_context.ContextAware() @yaql.context.ContextAware()
def _cast(context, value, type): def _cast(context, value, type):
if not '.' in type: if not '.' in type:
murano_class = context.get_data('$?type') murano_class = context.get_data('$?type')
@@ -60,8 +60,8 @@ def _cast(context, value, type):
return value.cast(class_loader.get_class(type)) return value.cast(class_loader.get_class(type))
@y_context.EvalArg('name', str) @yaql.context.EvalArg('name', str)
@y_context.ContextAware() @yaql.context.ContextAware()
def _new(context, name, *args): def _new(context, name, *args):
murano_class = helpers.get_type(context) murano_class = helpers.get_type(context)
name = murano_class.namespace_resolver.resolve_name(name) name = murano_class.namespace_resolver.resolve_name(name)
@@ -79,38 +79,38 @@ def _new(context, name, *args):
object_store = helpers.get_object_store(context) object_store = helpers.get_object_store(context)
class_loader = helpers.get_class_loader(context) class_loader = helpers.get_class_loader(context)
new_context = y_context.Context(parent_context=context) new_context = yaql.context.Context(parent_context=context)
for key, value in parameters.iteritems(): for key, value in parameters.iteritems():
new_context.set_data(value, key) new_context.set_data(value, key)
return class_loader.get_class(name).new( return class_loader.get_class(name).new(
None, object_store, new_context, parameters=parameters) None, object_store, new_context, parameters=parameters)
@y_context.EvalArg('value', objects.MuranoObject) @yaql.context.EvalArg('value', murano_object.MuranoObject)
def _super(value): def _super(value):
return [value.cast(type) for type in value.type.parents] return [value.cast(type) for type in value.type.parents]
@y_context.EvalArg('value', objects.MuranoObject) @yaql.context.EvalArg('value', murano_object.MuranoObject)
def _super2(value, func): def _super2(value, func):
return itertools.imap(func, _super(value)) return itertools.imap(func, _super(value))
@y_context.EvalArg('value', objects.MuranoObject) @yaql.context.EvalArg('value', murano_object.MuranoObject)
def _psuper2(value, func): def _psuper2(value, func):
helpers.parallel_select(_super(value), func) helpers.parallel_select(_super(value), func)
@y_context.EvalArg('value', object) @yaql.context.EvalArg('value', object)
def _require(value): def _require(value):
if value is None: if value is None:
raise ValueError() raise ValueError()
return value return value
@y_context.EvalArg('obj', objects.MuranoObject) @yaql.context.EvalArg('obj', murano_object.MuranoObject)
@y_context.EvalArg('class_name', str) @yaql.context.EvalArg('class_name', str)
@y_context.ContextAware() @yaql.context.ContextAware()
def _get_container(context, obj, class_name): def _get_container(context, obj, class_name):
namespace_resolver = helpers.get_type(context).namespace_resolver namespace_resolver = helpers.get_type(context).namespace_resolver
class_loader = helpers.get_class_loader(context) class_loader = helpers.get_class_loader(context)
@@ -124,7 +124,7 @@ def _get_container(context, obj, class_name):
return None return None
@y_context.EvalArg('seconds', (int, float)) @yaql.context.EvalArg('seconds', (int, float))
def _sleep(seconds): def _sleep(seconds):
eventlet.sleep(seconds) eventlet.sleep(seconds)

View File

@@ -1,18 +0,0 @@
# Copyright (c) 2014 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.
NoValue = object()
EVALUATION_MAX_DEPTH = 100

View File

@@ -1,19 +0,0 @@
# Copyright (c) 2014 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.
from muranoapi.engine.principal_objects import sys_object
def register(class_loader):
class_loader.import_class(sys_object.SysObject)

View File

@@ -17,9 +17,9 @@ import os.path
import yaml import yaml
from muranoapi.engine import class_loader import muranoapi.dsl.class_loader as class_loader
from muranoapi.engine.system import yaql_functions import muranoapi.dsl.yaql_expression as yaql_expression
from muranoapi.engine import yaql_expression import muranoapi.engine.system.yaql_functions as yaql_functions
def yaql_constructor(loader, node): def yaql_constructor(loader, node):

View File

@@ -1,48 +0,0 @@
# Copyright (c) 2013 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 inspect
from muranoapi.engine import classes
from muranoapi.engine.system import agent
from muranoapi.engine.system import agent_listener
from muranoapi.engine.system import heat_stack
from muranoapi.engine.system import resource_manager
def _auto_register(class_loader):
globs = globals().copy()
for module_name, value in globs.iteritems():
if inspect.ismodule(value):
for class_name in dir(value):
class_def = getattr(value, class_name)
if inspect.isclass(class_def) and hasattr(
class_def, '_murano_class_name'):
class_loader.import_class(class_def)
def register(class_loader, path):
_auto_register(class_loader)
@classes.classname('org.openstack.murano.system.Resources')
class ResourceManagerWrapper(resource_manager.ResourceManager):
def initialize(self, _context, _class=None):
super(ResourceManagerWrapper, self).initialize(
path, _context, _class)
class_loader.import_class(agent.Agent)
class_loader.import_class(agent_listener.AgentListener)
class_loader.import_class(heat_stack.HeatStack)
class_loader.import_class(ResourceManagerWrapper)

View File

@@ -20,11 +20,11 @@ import uuid
import eventlet.event import eventlet.event
from muranoapi.common import messaging import muranoapi.common.messaging as messaging
from muranoapi.engine import classes import muranoapi.dsl.murano_class as murano_class
from muranoapi.engine import objects import muranoapi.dsl.murano_object as murano_object
from muranoapi.engine.system import common import muranoapi.dsl.yaql_expression as yaql_expression
from muranoapi.engine import yaql_expression import muranoapi.engine.system.common as common
class AgentException(Exception): class AgentException(Exception):
@@ -32,11 +32,11 @@ class AgentException(Exception):
self.message_info = message_info self.message_info = message_info
@classes.classname('org.openstack.murano.system.Agent') @murano_class.classname('io.murano.system.Agent')
class Agent(objects.MuranoObject): class Agent(murano_object.MuranoObject):
def initialize(self, _context, host): def initialize(self, _context, host):
environment = yaql_expression.YaqlExpression( environment = yaql_expression.YaqlExpression(
"$host.find('org.openstack.murano.Environment').require()" "$host.find('io.murano.Environment').require()"
).evaluate(_context) ).evaluate(_context)
self._queue = str('e%s-h%s' % ( self._queue = str('e%s-h%s' % (

View File

@@ -15,13 +15,13 @@
import eventlet import eventlet
from muranoapi.engine import classes import muranoapi.dsl.murano_class as murano_class
from muranoapi.engine import objects import muranoapi.dsl.murano_object as murano_object
from muranoapi.engine.system import common import muranoapi.engine.system.common as common
@classes.classname('org.openstack.murano.system.AgentListener') @murano_class.classname('io.murano.system.AgentListener')
class AgentListener(objects.MuranoObject): class AgentListener(murano_object.MuranoObject):
def initialize(self, _context, name): def initialize(self, _context, name):
self._results_queue = str('-execution-results-%s' % name.lower()) self._results_queue = str('-execution-results-%s' % name.lower())
self._subscriptions = {} self._subscriptions = {}

View File

@@ -13,8 +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.
from muranoapi.common import config import muranoapi.common.config as config
from muranoapi.common import messaging import muranoapi.common.messaging as messaging
def create_rmq_client(): def create_rmq_client():

View File

@@ -14,21 +14,23 @@
# limitations under the License. # limitations under the License.
import eventlet import eventlet
from heatclient import client as hclient import heatclient.client as hclient
from heatclient import exc as heat_exc import heatclient.exc as heat_exc
from keystoneclient.v2_0 import client as ksclient import keystoneclient.v2_0.client as ksclient
from muranoapi.common import config
from muranoapi.engine import classes import muranoapi.common.config as config
from muranoapi.engine import helpers
from muranoapi.engine import objects import muranoapi.dsl.helpers as helpers
from muranoapi.openstack.common import log as logging import muranoapi.dsl.murano_class as murano_class
import muranoapi.dsl.murano_object as murano_object
import muranoapi.openstack.common.log as logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@classes.classname('org.openstack.murano.system.HeatStack') @murano_class.classname('io.murano.system.HeatStack')
class HeatStack(objects.MuranoObject): class HeatStack(murano_object.MuranoObject):
def initialize(self, _context, name): def initialize(self, _context, name):
self._name = name self._name = name
self._template = None self._template = None

View File

@@ -17,10 +17,10 @@ import json as jsonlib
import os.path import os.path
import yaml as yamllib import yaml as yamllib
from muranoapi.engine import objects import muranoapi.dsl.murano_object as murano_object
class ResourceManager(objects.MuranoObject): class ResourceManager(murano_object.MuranoObject):
def initialize(self, base_path, _context, _class): def initialize(self, base_path, _context, _class):
if _class is None: if _class is None:
_class = _context.get_data('$') _class = _context.get_data('$')

View File

@@ -0,0 +1,48 @@
# Copyright (c) 2013 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 inspect
import muranoapi.dsl.murano_class as murano_class
import muranoapi.engine.system.agent as agent
import muranoapi.engine.system.agent_listener as agent_listener
import muranoapi.engine.system.heat_stack as heat_stack
import muranoapi.engine.system.resource_manager as resource_manager
def _auto_register(class_loader):
globs = globals().copy()
for module_name, value in globs.iteritems():
if inspect.ismodule(value):
for class_name in dir(value):
class_def = getattr(value, class_name)
if inspect.isclass(class_def) and hasattr(
class_def, '_murano_class_name'):
class_loader.import_class(class_def)
def register(class_loader, path):
_auto_register(class_loader)
@murano_class.classname('io.murano.system.Resources')
class ResourceManagerWrapper(resource_manager.ResourceManager):
def initialize(self, _context, _class=None):
super(ResourceManagerWrapper, self).initialize(
path, _context, _class)
class_loader.import_class(agent.Agent)
class_loader.import_class(agent_listener.AgentListener)
class_loader.import_class(heat_stack.HeatStack)
class_loader.import_class(ResourceManagerWrapper)

View File

@@ -17,10 +17,10 @@ import base64
import re import re
import types import types
from yaql import context import yaql.context
from muranoapi.common import config as cfg import muranoapi.common.config as cfg
from muranoapi.engine import helpers import muranoapi.dsl.helpers as helpers
def _transform_json(json, mappings): def _transform_json(json, mappings):
@@ -62,20 +62,20 @@ def _convert_macro_parameter(macro, mappings):
return mappings[macro] return mappings[macro]
@context.EvalArg('format', types.StringTypes) @yaql.context.EvalArg('format', types.StringTypes)
def _format(format, *args): def _format(format, *args):
return format.format(*[t() for t in args]) return format.format(*[t() for t in args])
@context.EvalArg('src', types.StringTypes) @yaql.context.EvalArg('src', types.StringTypes)
@context.EvalArg('substring', types.StringTypes) @yaql.context.EvalArg('substring', types.StringTypes)
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
def _replace_str(src, substring, value): def _replace_str(src, substring, value):
return src.replace(substring, value) return src.replace(substring, value)
@context.EvalArg('src', types.StringTypes) @yaql.context.EvalArg('src', types.StringTypes)
@context.EvalArg('replacements', dict) @yaql.context.EvalArg('replacements', dict)
def _replace_dict(src, replacements): def _replace_dict(src, replacements):
for key, value in replacements.iteritems(): for key, value in replacements.iteritems():
if isinstance(src, str): if isinstance(src, str):
@@ -97,74 +97,74 @@ def _coalesce(*args):
return None return None
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
def _base64encode(value): def _base64encode(value):
return base64.b64encode(value) return base64.b64encode(value)
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
def _base64decode(value): def _base64decode(value):
return base64.b64decode(value) return base64.b64decode(value)
@context.EvalArg('group', types.StringTypes) @yaql.context.EvalArg('group', types.StringTypes)
@context.EvalArg('setting', types.StringTypes) @yaql.context.EvalArg('setting', types.StringTypes)
def _config(group, setting): def _config(group, setting):
return cfg.CONF[group][setting] return cfg.CONF[group][setting]
@context.EvalArg('setting', types.StringTypes) @yaql.context.EvalArg('setting', types.StringTypes)
def _config_default(setting): def _config_default(setting):
return cfg.CONF[setting] return cfg.CONF[setting]
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
def _upper(value): def _upper(value):
return value.upper() return value.upper()
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
def _lower(value): def _lower(value):
return value.lower() return value.lower()
@context.EvalArg('separator', types.StringTypes) @yaql.context.EvalArg('separator', types.StringTypes)
def _join(separator, *args): def _join(separator, *args):
return separator.join([t() for t in args]) return separator.join([t() for t in args])
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
@context.EvalArg('separator', types.StringTypes) @yaql.context.EvalArg('separator', types.StringTypes)
def _split(value, separator): def _split(value, separator):
return value.split(separator) return value.split(separator)
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
@context.EvalArg('prefix', types.StringTypes) @yaql.context.EvalArg('prefix', types.StringTypes)
def _startswith(value, prefix): def _startswith(value, prefix):
return value.startswith(prefix) return value.startswith(prefix)
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
@context.EvalArg('suffix', types.StringTypes) @yaql.context.EvalArg('suffix', types.StringTypes)
def _endswith(value, suffix): def _endswith(value, suffix):
return value.endswith(suffix) return value.endswith(suffix)
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
def _trim(value): def _trim(value):
return value.strip() return value.strip()
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
@context.EvalArg('pattern', types.StringTypes) @yaql.context.EvalArg('pattern', types.StringTypes)
def _mathces(value, pattern): def _mathces(value, pattern):
return re.match(pattern, value) is not None return re.match(pattern, value) is not None
@context.EvalArg('value', types.StringTypes) @yaql.context.EvalArg('value', types.StringTypes)
@context.EvalArg('index', int) @yaql.context.EvalArg('index', int)
@context.EvalArg('length', int) @yaql.context.EvalArg('length', int)
def _substr(value, index=0, length=-1): def _substr(value, index=0, length=-1):
if length < 0: if length < 0:
return value[index:] return value[index:]

View File

@@ -19,44 +19,44 @@ import mock
import unittest2 as unittest import unittest2 as unittest
import yaql import yaql
from muranoapi.engine import classes import muranoapi.dsl.exceptions as exceptions
from muranoapi.engine import exceptions import muranoapi.dsl.helpers as helpers
from muranoapi.engine import helpers import muranoapi.dsl.murano_class as murano_class
from muranoapi.engine import namespaces import muranoapi.dsl.murano_object as murano_object
from muranoapi.engine import objects import muranoapi.dsl.namespace_resolver as ns_resolver
from muranoapi.engine import typespec import muranoapi.dsl.typespec as typespec
from muranoapi.engine import yaql_expression import muranoapi.dsl.yaql_expression as yaql_expression
ROOT_CLASS = 'org.openstack.murano.Object' ROOT_CLASS = 'io.murano.Object'
class TestNamespaceResolving(unittest.TestCase): class TestNamespaceResolving(unittest.TestCase):
def test_fails_w_empty_name(self): def test_fails_w_empty_name(self):
resolver = namespaces.NamespaceResolver({'=': 'com.example.murano'}) resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
self.assertRaises(ValueError, resolver.resolve_name, None) self.assertRaises(ValueError, resolver.resolve_name, None)
def test_fails_w_unknown_prefix(self): def test_fails_w_unknown_prefix(self):
resolver = namespaces.NamespaceResolver({'=': 'com.example.murano'}) resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
name = 'unknown_prefix:example.murano' name = 'unknown_prefix:example.murano'
self.assertRaises(KeyError, resolver.resolve_name, name) self.assertRaises(KeyError, resolver.resolve_name, name)
def test_fails_w_prefix_wo_name(self): def test_fails_w_prefix_wo_name(self):
resolver = namespaces.NamespaceResolver({'=': 'com.example.murano'}) resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
name = 'sys:' name = 'sys:'
self.assertRaises(NameError, resolver.resolve_name, name) self.assertRaises(NameError, resolver.resolve_name, name)
def test_fails_w_excessive_prefix(self): def test_fails_w_excessive_prefix(self):
ns = {'sys': 'com.example.murano.system'} ns = {'sys': 'com.example.murano.system'}
resolver = namespaces.NamespaceResolver(ns) resolver = ns_resolver.NamespaceResolver(ns)
invalid_name = 'sys:excessive_ns:muranoResource' invalid_name = 'sys:excessive_ns:muranoResource'
self.assertRaises(NameError, resolver.resolve_name, invalid_name) self.assertRaises(NameError, resolver.resolve_name, invalid_name)
def test_cuts_empty_prefix(self): def test_cuts_empty_prefix(self):
resolver = namespaces.NamespaceResolver({'=': 'com.example.murano'}) resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
# name without prefix delimiter # name without prefix delimiter
name = 'some.arbitrary.name' name = 'some.arbitrary.name'
@@ -66,7 +66,7 @@ class TestNamespaceResolving(unittest.TestCase):
def test_resolves_specified_ns_prefix(self): def test_resolves_specified_ns_prefix(self):
ns = {'sys': 'com.example.murano.system'} ns = {'sys': 'com.example.murano.system'}
resolver = namespaces.NamespaceResolver(ns) resolver = ns_resolver.NamespaceResolver(ns)
short_name, full_name = 'sys:File', 'com.example.murano.system.File' short_name, full_name = 'sys:File', 'com.example.murano.system.File'
resolved_name = resolver.resolve_name(short_name) resolved_name = resolver.resolve_name(short_name)
@@ -74,7 +74,7 @@ class TestNamespaceResolving(unittest.TestCase):
self.assertEqual(full_name, resolved_name) self.assertEqual(full_name, resolved_name)
def test_resolves_current_ns(self): def test_resolves_current_ns(self):
resolver = namespaces.NamespaceResolver({'=': 'com.example.murano'}) resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
short_name, full_name = 'Resource', 'com.example.murano.Resource' short_name, full_name = 'Resource', 'com.example.murano.Resource'
resolved_name = resolver.resolve_name(short_name) resolved_name = resolver.resolve_name(short_name)
@@ -82,21 +82,21 @@ class TestNamespaceResolving(unittest.TestCase):
self.assertEqual(full_name, resolved_name) self.assertEqual(full_name, resolved_name)
def test_resolves_explicit_base(self): def test_resolves_explicit_base(self):
resolver = namespaces.NamespaceResolver({'=': 'com.example.murano'}) resolver = ns_resolver.NamespaceResolver({'=': 'com.example.murano'})
resolved_name = resolver.resolve_name('Resource', relative='com.base') resolved_name = resolver.resolve_name('Resource', relative='com.base')
self.assertEqual('com.base.Resource', resolved_name) self.assertEqual('com.base.Resource', resolved_name)
def test_resolves_explicit_base_w_empty_namespaces(self): def test_resolves_explicit_base_w_empty_namespaces(self):
resolver = namespaces.NamespaceResolver({}) resolver = ns_resolver.NamespaceResolver({})
resolved_name = resolver.resolve_name('File', 'com.base') resolved_name = resolver.resolve_name('File', 'com.base')
self.assertEqual('com.base.File', resolved_name) self.assertEqual('com.base.File', resolved_name)
def test_resolves_w_empty_namespaces(self): def test_resolves_w_empty_namespaces(self):
resolver = namespaces.NamespaceResolver({}) resolver = ns_resolver.NamespaceResolver({})
resolved_name = resolver.resolve_name('Resource') resolved_name = resolver.resolve_name('Resource')
@@ -114,38 +114,38 @@ class TestClassesManipulation(unittest.TestCase):
resolver = mock.Mock(resolve_name=lambda name: name) resolver = mock.Mock(resolve_name=lambda name: name)
def test_class_name(self): def test_class_name(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
self.assertEqual(ROOT_CLASS, cls.name) self.assertEqual(ROOT_CLASS, cls.name)
def test_class_namespace_resolver(self): def test_class_namespace_resolver(self):
resolver = namespaces.NamespaceResolver({}) resolver = ns_resolver.NamespaceResolver({})
cls = classes.MuranoClass(None, resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, resolver, ROOT_CLASS)
self.assertEqual(resolver, cls.namespace_resolver) self.assertEqual(resolver, cls.namespace_resolver)
def test_root_class_has_no_parents(self): def test_root_class_has_no_parents(self):
root_class = classes.MuranoClass( root_class = murano_class.MuranoClass(
None, self.resolver, ROOT_CLASS, ['You should not see me!']) None, self.resolver, ROOT_CLASS, ['You should not see me!'])
self.assertEqual([], root_class.parents) self.assertEqual([], root_class.parents)
def test_non_root_class_resolves_parents(self): def test_non_root_class_resolves_parents(self):
root_cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) root_cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
class_loader = mock.Mock(get_class=lambda name: root_cls) class_loader = mock.Mock(get_class=lambda name: root_cls)
desc_cls1 = classes.MuranoClass(class_loader, self.resolver, 'Obj') desc_cl1 = murano_class.MuranoClass(class_loader, self.resolver, 'Obj')
desc_cls2 = classes.MuranoClass( desc_cl2 = murano_class.MuranoClass(
class_loader, self.resolver, 'Obj', [root_cls]) class_loader, self.resolver, 'Obj', [root_cls])
self.assertEqual([root_cls], desc_cls1.parents) self.assertEqual([root_cls], desc_cl1.parents)
self.assertEqual([root_cls], desc_cls2.parents) self.assertEqual([root_cls], desc_cl2.parents)
def test_class_initial_properties(self): def test_class_initial_properties(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
self.assertEqual([], cls.properties) self.assertEqual([], cls.properties)
def test_fails_add_incompatible_property_to_class(self): def test_fails_add_incompatible_property_to_class(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
kwargs = {'name': 'sampleProperty', 'property_typespec': {}} kwargs = {'name': 'sampleProperty', 'property_typespec': {}}
self.assertRaises(TypeError, cls.add_property, **kwargs) self.assertRaises(TypeError, cls.add_property, **kwargs)
@@ -153,7 +153,7 @@ class TestClassesManipulation(unittest.TestCase):
@unittest.skip @unittest.skip
def test_add_property_to_class(self): def test_add_property_to_class(self):
prop = typespec.PropertySpec({'Default': 1}, self.resolver) prop = typespec.PropertySpec({'Default': 1}, self.resolver)
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls.add_property('firstPrime', prop) cls.add_property('firstPrime', prop)
class_properties = cls.properties class_properties = cls.properties
@@ -171,10 +171,12 @@ class TestClassesManipulation(unittest.TestCase):
self.resolver) self.resolver)
child_prop = typespec.PropertySpec({'Default': 'Child'}, child_prop = typespec.PropertySpec({'Default': 'Child'},
self.resolver) self.resolver)
root = classes.MuranoClass(None, self.resolver, ROOT_CLASS) root = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
mother = classes.MuranoClass(None, self.resolver, 'Mother', [root]) mother = murano_class.MuranoClass(None, self.resolver,
father = classes.MuranoClass(None, self.resolver, 'Father', [root]) 'Mother', [root])
child = classes.MuranoClass( father = murano_class.MuranoClass(None, self.resolver,
'Father', [root])
child = murano_class.MuranoClass(
None, self.resolver, 'Child', [mother, father]) None, self.resolver, 'Child', [mother, father])
root.add_property('Void', void_prop) root.add_property('Void', void_prop)
@@ -188,11 +190,11 @@ class TestClassesManipulation(unittest.TestCase):
self.assertEqual(void_prop, child.find_property('Void')) self.assertEqual(void_prop, child.find_property('Void'))
def test_class_is_compatible(self): def test_class_is_compatible(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
descendant_cls = classes.MuranoClass( descendant_cls = murano_class.MuranoClass(
None, self.resolver, 'DescendantCls', [cls]) None, self.resolver, 'DescendantCls', [cls])
obj = mock.Mock(spec=objects.MuranoObject) obj = mock.Mock(spec=murano_object.MuranoObject)
descendant_obj = mock.Mock(spec=objects.MuranoObject) descendant_obj = mock.Mock(spec=murano_object.MuranoObject)
obj.type = cls obj.type = cls
descendant_obj.type = descendant_cls descendant_obj.type = descendant_cls
descendant_obj.parents = [obj] descendant_obj.parents = [obj]
@@ -202,7 +204,7 @@ class TestClassesManipulation(unittest.TestCase):
self.assertFalse(descendant_cls.is_compatible(obj)) self.assertFalse(descendant_cls.is_compatible(obj))
def test_new_method_calls_initialize(self): def test_new_method_calls_initialize(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls.object_class = mock.Mock() cls.object_class = mock.Mock()
with mock.patch('inspect.getargspec') as spec_mock: with mock.patch('inspect.getargspec') as spec_mock:
@@ -212,7 +214,7 @@ class TestClassesManipulation(unittest.TestCase):
self.assertTrue(obj.initialize.called) self.assertTrue(obj.initialize.called)
def test_new_method_not_calls_initialize(self): def test_new_method_not_calls_initialize(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls.object_class = mock.Mock() cls.object_class = mock.Mock()
obj = cls.new(None, None, None) obj = cls.new(None, None, None)
@@ -228,7 +230,7 @@ class TestObjectsManipulation(unittest.TestCase):
self.cls.parents = [] self.cls.parents = []
def test_object_valid_type_instantiation(self): def test_object_valid_type_instantiation(self):
obj = objects.MuranoObject(self.cls, None, None, None) obj = murano_object.MuranoObject(self.cls, None, None, None)
self.assertEqual(self.cls, obj.type) self.assertEqual(self.cls, obj.type)
@@ -239,11 +241,12 @@ class TestObjectsManipulation(unittest.TestCase):
pass pass
def test_object_parent_properties_initialization(self): def test_object_parent_properties_initialization(self):
root = classes.MuranoClass(None, self.resolver, ROOT_CLASS) root = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls = classes.MuranoClass(None, self.resolver, 'SomeClass', [root]) cls = murano_class.MuranoClass(None, self.resolver,
'SomeClass', [root])
root.new = mock.Mock() root.new = mock.Mock()
init_kwargs = {'theArg': 0} init_kwargs = {'theArg': 0}
obj = objects.MuranoObject(cls, None, None, None) obj = murano_object.MuranoObject(cls, None, None, None)
expected_calls = [mock.call().initialize(**init_kwargs)] expected_calls = [mock.call().initialize(**init_kwargs)]
obj.initialize(**init_kwargs) obj.initialize(**init_kwargs)
@@ -253,35 +256,36 @@ class TestObjectsManipulation(unittest.TestCase):
def test_object_id(self): def test_object_id(self):
_id = 'some_id' _id = 'some_id'
patch_at = 'muranoapi.engine.objects.helpers.generate_id' patch_at = 'muranoapi.dsl.helpers.generate_id'
obj = objects.MuranoObject(self.cls, None, None, None, object_id=_id) obj = murano_object.MuranoObject(self.cls, None, None, None,
object_id=_id)
with mock.patch(patch_at) as gen_id_mock: with mock.patch(patch_at) as gen_id_mock:
gen_id_mock.return_value = _id gen_id_mock.return_value = _id
obj1 = objects.MuranoObject(self.cls, None, None, None) obj1 = murano_object.MuranoObject(self.cls, None, None, None)
self.assertEqual(_id, obj.object_id) self.assertEqual(_id, obj.object_id)
self.assertEqual(_id, obj1.object_id) self.assertEqual(_id, obj1.object_id)
def test_parent_obj(self): def test_parent_obj(self):
parent = mock.Mock() parent = mock.Mock()
obj = objects.MuranoObject(self.cls, parent, None, None) obj = murano_object.MuranoObject(self.cls, parent, None, None)
self.assertEqual(parent, obj.parent) self.assertEqual(parent, obj.parent)
@unittest.skip @unittest.skip
def test_fails_internal_property_access(self): def test_fails_internal_property_access(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls.add_property('__hidden', cls.add_property('__hidden',
typespec.PropertySpec({'Default': 10}, self.resolver)) typespec.PropertySpec({'Default': 10}, self.resolver))
obj = objects.MuranoObject(cls, None, None, None) obj = murano_object.MuranoObject(cls, None, None, None)
self.assertRaises(AttributeError, lambda: obj.__hidden) self.assertRaises(AttributeError, lambda: obj.__hidden)
@unittest.skip @unittest.skip
def test_proper_property_access(self): def test_proper_property_access(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls.add_property('someProperty', cls.add_property('someProperty',
typespec.PropertySpec({'Default': 0}, self.resolver)) typespec.PropertySpec({'Default': 0}, self.resolver))
@@ -291,8 +295,9 @@ class TestObjectsManipulation(unittest.TestCase):
@unittest.skip @unittest.skip
def test_parent_class_property_access(self): def test_parent_class_property_access(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
child_cls = classes.MuranoClass(None, self.resolver, 'Child', [cls]) child_cls = murano_class.MuranoClass(None, self.resolver,
'Child', [cls])
cls.add_property('anotherProperty', cls.add_property('anotherProperty',
typespec.PropertySpec({'Default': 0}, self.resolver)) typespec.PropertySpec({'Default': 0}, self.resolver))
@@ -302,10 +307,12 @@ class TestObjectsManipulation(unittest.TestCase):
@unittest.skip @unittest.skip
def test_fails_on_parents_property_collision(self): def test_fails_on_parents_property_collision(self):
root = classes.MuranoClass(None, self.resolver, ROOT_CLASS) root = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
mother = classes.MuranoClass(None, self.resolver, 'Mother', [root]) mother = murano_class.MuranoClass(None, self.resolver,
father = classes.MuranoClass(None, self.resolver, 'Father', [root]) 'Mother', [root])
child = classes.MuranoClass( father = murano_class.MuranoClass(None, self.resolver,
'Father', [root])
child = murano_class.MuranoClass(
None, self.resolver, 'Child', [mother, father]) None, self.resolver, 'Child', [mother, father])
mother.add_property( mother.add_property(
@@ -319,13 +326,13 @@ class TestObjectsManipulation(unittest.TestCase):
self.assertRaises(LookupError, lambda: obj.conflictProp) self.assertRaises(LookupError, lambda: obj.conflictProp)
def test_fails_setting_undeclared_property(self): def test_fails_setting_undeclared_property(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
obj = cls.new(None, None, None, {}) obj = cls.new(None, None, None, {})
self.assertRaises(AttributeError, obj.set_property, 'newOne', 10) self.assertRaises(AttributeError, obj.set_property, 'newOne', 10)
def test_set_undeclared_property_as_internal(self): def test_set_undeclared_property_as_internal(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
obj = cls.new(None, None, None, {}) obj = cls.new(None, None, None, {})
obj.cast = mock.Mock(return_value=obj) obj.cast = mock.Mock(return_value=obj)
prop_value = 10 prop_value = 10
@@ -337,7 +344,7 @@ class TestObjectsManipulation(unittest.TestCase):
@unittest.skip @unittest.skip
def test_fails_forbidden_set_property(self): def test_fails_forbidden_set_property(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls.add_property('someProperty', cls.add_property('someProperty',
typespec.PropertySpec({'Default': 0}, self.resolver)) typespec.PropertySpec({'Default': 0}, self.resolver))
cls.is_compatible = mock.Mock(return_value=False) cls.is_compatible = mock.Mock(return_value=False)
@@ -348,7 +355,7 @@ class TestObjectsManipulation(unittest.TestCase):
@unittest.skip @unittest.skip
def test_set_property(self): def test_set_property(self):
cls = classes.MuranoClass(None, self.resolver, ROOT_CLASS) cls = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls.add_property('someProperty', cls.add_property('someProperty',
typespec.PropertySpec({'Default': 0}, self.resolver)) typespec.PropertySpec({'Default': 0}, self.resolver))
obj = cls.new(None, None, None, {}) obj = cls.new(None, None, None, {})
@@ -362,8 +369,9 @@ class TestObjectsManipulation(unittest.TestCase):
@unittest.skip @unittest.skip
def test_set_parent_property(self): def test_set_parent_property(self):
root = classes.MuranoClass(None, self.resolver, ROOT_CLASS) root = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls = classes.MuranoClass(None, self.resolver, 'SomeClass', [root]) cls = murano_class.MuranoClass(None, self.resolver,
'SomeClass', [root])
root.add_property('rootProperty', root.add_property('rootProperty',
typespec.PropertySpec({'Default': 0}, self.resolver)) typespec.PropertySpec({'Default': 0}, self.resolver))
obj = cls.new(None, None, None, {}) obj = cls.new(None, None, None, {})
@@ -375,10 +383,11 @@ class TestObjectsManipulation(unittest.TestCase):
self.assertEqual(20, obj.rootProperty) self.assertEqual(20, obj.rootProperty)
@unittest.skip
def test_object_up_cast(self): def test_object_up_cast(self):
root = classes.MuranoClass(None, self.resolver, ROOT_CLASS) root = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
root_alt = classes.MuranoClass(None, self.resolver, 'RootAlt', []) root_alt = murano_class.MuranoClass(None, self.resolver, 'RootAlt', [])
cls = classes.MuranoClass( cls = murano_class.MuranoClass(
None, self.resolver, 'SomeClass', [root, root_alt]) None, self.resolver, 'SomeClass', [root, root_alt])
root_obj = root.new(None, None, None) root_obj = root.new(None, None, None)
cls_obj = cls.new(None, None, None) cls_obj = cls.new(None, None, None)
@@ -394,8 +403,8 @@ class TestObjectsManipulation(unittest.TestCase):
self.assertEqual(root_alt, cls_obj_casted2root_alt.type) self.assertEqual(root_alt, cls_obj_casted2root_alt.type)
def test_fails_object_down_cast(self): def test_fails_object_down_cast(self):
root = classes.MuranoClass(None, self.resolver, ROOT_CLASS) root = murano_class.MuranoClass(None, self.resolver, ROOT_CLASS)
cls = classes.MuranoClass( cls = murano_class.MuranoClass(
None, self.resolver, 'SomeClass', [root]) None, self.resolver, 'SomeClass', [root])
root_obj = root.new(None, None, None) root_obj = root.new(None, None, None)