Repository: incubator-ariatosca Updated Branches: refs/heads/ARIA-180-convert-parameter-to-one-to-many 133976eae -> 798e5583e (forced update)
Add Argument and Configuration models Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/798e5583 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/798e5583 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/798e5583 Branch: refs/heads/ARIA-180-convert-parameter-to-one-to-many Commit: 798e5583ecba8d5fc34a83bede010d1b9f691992 Parents: fdda757 Author: Avia Efrat <a...@gigaspaces.com> Authored: Thu Jun 1 17:09:22 2017 +0300 Committer: Avia Efrat <a...@gigaspaces.com> Committed: Sun Jun 4 11:17:53 2017 +0300 ---------------------------------------------------------------------- aria/modeling/mixins.py | 216 ++++++++++++++++- aria/modeling/models.py | 17 +- aria/modeling/orchestration.py | 35 ++- aria/modeling/service_common.py | 243 +++---------------- aria/modeling/service_instance.py | 44 ++-- aria/modeling/service_template.py | 28 +-- aria/modeling/utils.py | 6 +- .../context/collection_instrumentation.py | 10 +- .../execution_plugin/instantiation.py | 36 +-- aria/orchestrator/workflow_runner.py | 4 +- aria/orchestrator/workflows/api/task.py | 6 +- examples/hello-world/helloworld.yaml | 7 +- .../simple_v1_0/modeling/__init__.py | 8 +- tests/mock/models.py | 4 +- tests/mock/topology.py | 8 +- tests/modeling/test_models.py | 3 +- .../context/test_collection_instrumentation.py | 64 ++--- tests/orchestrator/context/test_toolbelt.py | 2 +- tests/orchestrator/test_workflow_runner.py | 6 +- .../workflows/executor/test_executor.py | 2 +- 20 files changed, 417 insertions(+), 332 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/modeling/mixins.py ---------------------------------------------------------------------- diff --git a/aria/modeling/mixins.py b/aria/modeling/mixins.py index 38c812d..9a88f81 100644 --- a/aria/modeling/mixins.py +++ b/aria/modeling/mixins.py @@ -23,10 +23,14 @@ from sqlalchemy.ext import associationproxy from sqlalchemy import ( Column, Integer, - Text + Text, + PickleType ) -from . import utils +from ..parser.consumption import ConsumptionContext +from ..utils import console, collections, caching, formatting +from ..utils.type import canonical_type_name, full_type_name +from . import utils, functions class ModelMixin(object): @@ -140,3 +144,211 @@ class TemplateModelMixin(InstanceModelMixin): def instantiate(self, container): raise NotImplementedError + + +class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods): + """ + Represents a typed value. The value can contain nested intrinsic functions. + + This model can be used as the ``container_holder`` argument for :func:`functions.evaluate`. + + :ivar name: Name + :vartype name: basestring + :ivar type_name: Type name + :vartype type_name: basestring + :ivar value: Value + :ivar description: Description + :vartype description: basestring + """ + + __tablename__ = 'parameter' + + name = Column(Text) + type_name = Column(Text) + description = Column(Text) + _value = Column(PickleType) + + @property + def value(self): + value = self._value + if value is not None: + evaluation = functions.evaluate(value, self) + if evaluation is not None: + value = evaluation.value + return value + + @value.setter + def value(self, value): + self._value = value + + @property + @caching.cachedmethod + def owner(self): + """ + The sole owner of this parameter, which is another model that relates to it. + + *All* parameters should have an owner model. In case this property method fails to find + it, it will raise a ValueError, which should signify an abnormal, orphaned parameter. + """ + + # Find first non-null relationship + for the_relationship in self.__mapper__.relationships: + v = getattr(self, the_relationship.key) + if v: + return v + + raise ValueError('orphaned {class_name}: does not have an owner: {name}'.format( + class_name=type(self).__name__, name=self.name)) + + @property + @caching.cachedmethod + def container(self): # pylint: disable=too-many-return-statements,too-many-branches + """ + The logical container for this parameter, which would be another model: service, node, + group, or policy (or their templates). + + The logical container is equivalent to the ``SELF`` keyword used by intrinsic functions in + TOSCA. + + *All* parameters should have a container model. In case this property method fails to find + it, it will raise a ValueError, which should signify an abnormal, orphaned parameter. + """ + + from . import models + + container = self.owner + + # Extract interface from operation + if isinstance(container, models.Operation): + container = container.interface + elif isinstance(container, models.OperationTemplate): + container = container.interface_template + + # Extract from other models + if isinstance(container, models.Interface): + container = container.node or container.group or container.relationship + elif isinstance(container, models.InterfaceTemplate): + container = container.node_template or container.group_template \ + or container.relationship_template + elif isinstance(container, models.Capability) or isinstance(container, models.Artifact): + container = container.node + elif isinstance(container, models.CapabilityTemplate) \ + or isinstance(container, models.ArtifactTemplate): + container = container.node_template + elif isinstance(container, models.Task): + container = container.actor + + # Extract node from relationship + if isinstance(container, models.Relationship): + container = container.source_node + elif isinstance(container, models.RelationshipTemplate): + container = container.requirement_template.node_template + + if container is not None: + return container + + raise ValueError('orphaned parameter: does not have a container: {0}'.format(self.name)) + + @property + @caching.cachedmethod + def service(self): + """ + The :class:`Service` containing this parameter, or None if not contained in a service. + """ + + from . import models + container = self.container + if isinstance(container, models.Service): + return container + elif hasattr(container, 'service'): + return container.service + return None + + @property + @caching.cachedmethod + def service_template(self): + """ + The :class:`ServiceTemplate` containing this parameter, or None if not contained in a + service template. + """ + + from . import models + container = self.container + if isinstance(container, models.ServiceTemplate): + return container + elif hasattr(container, 'service_template'): + return container.service_template + return None + + @property + def as_raw(self): + return collections.OrderedDict(( + ('name', self.name), + ('type_name', self.type_name), + ('value', self.value), + ('description', self.description))) + + def instantiate(self, container): + return self.__class__(name=self.name, # pylint: disable=unexpected-keyword-arg + type_name=self.type_name, + _value=self._value, + description=self.description) + + def coerce_values(self, report_issues): + value = self._value + if value is not None: + evaluation = functions.evaluate(value, self, report_issues) + if (evaluation is not None) and evaluation.final: + # A final evaluation can safely replace the existing value + self._value = evaluation.value + + def dump(self): + context = ConsumptionContext.get_thread_local() + if self.type_name is not None: + console.puts('{0}: {1} ({2})'.format( + context.style.property(self.name), + context.style.literal(formatting.as_raw(self.value)), + context.style.type(self.type_name))) + else: + console.puts('{0}: {1}'.format( + context.style.property(self.name), + context.style.literal(formatting.as_raw(self.value)))) + if self.description: + console.puts(context.style.meta(self.description)) + + @property + def unwrapped(self): + return self.name, self.value + + @classmethod + def wrap(cls, name, value, description=None): + """ + Wraps an arbitrary value as a parameter. The type will be guessed via introspection. + + For primitive types, we will prefer their TOSCA aliases. See the `TOSCA Simple Profile v1.0 + cos01 specification <http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01 + /TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Toc373867862>`__ + + :param name: Parameter name + :type name: basestring + :param value: Parameter value + :param description: Description (optional) + :type description: basestring + """ + + type_name = canonical_type_name(value) + if type_name is None: + type_name = full_type_name(value) + return cls(name=name, # pylint: disable=unexpected-keyword-arg + type_name=type_name, + value=value, + description=description) + + def as_other_parameter_model(self, other_model_cls): + + name, value = self.unwrapped + return other_model_cls.wrap(name, value) + + def as_argument(self): + from . import models + return self.as_other_parameter_model(models.Argument) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/modeling/models.py ---------------------------------------------------------------------- diff --git a/aria/modeling/models.py b/aria/modeling/models.py index bfa0ece..4102090 100644 --- a/aria/modeling/models.py +++ b/aria/modeling/models.py @@ -73,6 +73,7 @@ __all__ = ( # Common service models 'Input', + 'Configuration', 'Output', 'Property', 'Attribute', @@ -83,7 +84,8 @@ __all__ = ( 'Execution', 'Plugin', 'Task', - 'Log' + 'Log', + 'Argument' ) @@ -214,6 +216,10 @@ class Input(aria_declarative_base, service_common.InputBase): pass +class Configuration(aria_declarative_base, service_common.ConfigurationBase): + pass + + class Output(aria_declarative_base, service_common.OutputBase): pass @@ -253,6 +259,11 @@ class Task(aria_declarative_base, orchestration.TaskBase): class Log(aria_declarative_base, orchestration.LogBase): pass + +class Argument(aria_declarative_base, orchestration.ArgumentBase): + pass + + # endregion @@ -293,6 +304,7 @@ models_to_register = [ # Common service models Input, + Configuration, Output, Property, Attribute, @@ -303,5 +315,6 @@ models_to_register = [ Execution, Plugin, Task, - Log + Log, + Argument ] http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/modeling/orchestration.py ---------------------------------------------------------------------- diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py index 0cee682..995c8c2 100644 --- a/aria/modeling/orchestration.py +++ b/aria/modeling/orchestration.py @@ -39,7 +39,7 @@ from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.declarative import declared_attr from ..orchestrator.exceptions import (TaskAbortException, TaskRetryException) -from .mixins import ModelMixin +from .mixins import ModelMixin, ParameterMixin from . import ( relationship, types as modeling_types @@ -233,7 +233,7 @@ class TaskBase(ModelMixin): :ivar function: Python path to an ``@operation`` function :vartype function: basestring :ivar arguments: Arguments that can be used by this task - :vartype arguments: {basestring: :class:`Parameter`} + :vartype arguments: {basestring: :class:`Argument`} :ivar max_attempts: Maximum number of retries allowed in case of failure :vartype max_attempts: int :ivar retry_interval: Interval between retries (in seconds) @@ -301,7 +301,7 @@ class TaskBase(ModelMixin): @declared_attr def arguments(cls): - return relationship.many_to_many(cls, 'parameter', prefix='arguments', dict_key='name') + return relationship.one_to_many(cls, 'argument', dict_key='name') function = Column(String) max_attempts = Column(Integer, default=1) @@ -433,3 +433,32 @@ class LogBase(ModelMixin): def __repr__(self): name = (self.task.actor if self.task else self.execution).name return '{name}: {self.msg}'.format(name=name, self=self) + + +class ArgumentBase(ParameterMixin): + + __tablename__ = 'argument' + + # region foreign keys + + @declared_attr + def task_fk(cls): + return relationship.foreign_key('task', nullable=True) + + @declared_attr + def operation_fk(cls): + return relationship.foreign_key('operation', nullable=True) + + # endregion + + # region many_to_one relationships + + @declared_attr + def task(cls): + return relationship.many_to_one(cls, 'task') + + @declared_attr + def operation(cls): + return relationship.many_to_one(cls, 'operation') + + # endregion http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/modeling/service_common.py ---------------------------------------------------------------------- diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py index 07b45a4..d305f7a 100644 --- a/aria/modeling/service_common.py +++ b/aria/modeling/service_common.py @@ -18,220 +18,18 @@ from sqlalchemy import ( Column, Text, - PickleType ) from sqlalchemy.ext.declarative import declared_attr from ..parser.consumption import ConsumptionContext -from ..utils import (collections, formatting, console, caching) -from ..utils.type import (canonical_type_name, full_type_name) -from .mixins import (InstanceModelMixin, TemplateModelMixin) +from ..utils import (collections, formatting, console) +from .mixins import (InstanceModelMixin, TemplateModelMixin, ParameterMixin) from . import ( relationship, - functions ) -class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods): - """ - Represents a typed value. The value can contain nested intrinsic functions. - - This model can be used as the ``container_holder`` argument for :func:`functions.evaluate`. - - :ivar name: Name - :vartype name: basestring - :ivar type_name: Type name - :vartype type_name: basestring - :ivar value: Value - :ivar description: Description - :vartype description: basestring - """ - - __tablename__ = 'parameter' - - name = Column(Text) - type_name = Column(Text) - description = Column(Text) - _value = Column(PickleType) - - @property - def value(self): - value = self._value - if value is not None: - evaluation = functions.evaluate(value, self) - if evaluation is not None: - value = evaluation.value - return value - - @value.setter - def value(self, value): - self._value = value - - @property - @caching.cachedmethod - def owner(self): - """ - The sole owner of this parameter, which is another model that relates to it. - - *All* parameters should have an owner model. In case this property method fails to find - it, it will raise a ValueError, which should signify an abnormal, orphaned parameter. - """ - - # Find first non-null relationship - for the_relationship in self.__mapper__.relationships: - v = getattr(self, the_relationship.key) - if v: - return v - - raise ValueError('orphaned {class_name}: does not have an owner: {name}'.format( - class_name=type(self).__name__, name=self.name)) - - @property - @caching.cachedmethod - def container(self): # pylint: disable=too-many-return-statements,too-many-branches - """ - The logical container for this parameter, which would be another model: service, node, - group, or policy (or their templates). - - The logical container is equivalent to the ``SELF`` keyword used by intrinsic functions in - TOSCA. - - *All* parameters should have a container model. In case this property method fails to find - it, it will raise a ValueError, which should signify an abnormal, orphaned parameter. - """ - - from . import models - - container = self.owner - - # Extract interface from operation - if isinstance(container, models.Operation): - container = container.interface - elif isinstance(container, models.OperationTemplate): - container = container.interface_template - - # Extract from other models - if isinstance(container, models.Interface): - container = container.node or container.group or container.relationship - elif isinstance(container, models.InterfaceTemplate): - container = container.node_template or container.group_template \ - or container.relationship_template - elif isinstance(container, models.Capability) or isinstance(container, models.Artifact): - container = container.node - elif isinstance(container, models.CapabilityTemplate) \ - or isinstance(container, models.ArtifactTemplate): - container = container.node_template - elif isinstance(container, models.Task): - container = container.actor - - # Extract node from relationship - if isinstance(container, models.Relationship): - container = container.source_node - elif isinstance(container, models.RelationshipTemplate): - container = container.requirement_template.node_template - - if container is not None: - return container - - raise ValueError('orphaned parameter: does not have a container: {0}'.format(self.name)) - - @property - @caching.cachedmethod - def service(self): - """ - The :class:`Service` containing this parameter, or None if not contained in a service. - """ - - from . import models - container = self.container - if isinstance(container, models.Service): - return container - elif hasattr(container, 'service'): - return container.service - return None - - @property - @caching.cachedmethod - def service_template(self): - """ - The :class:`ServiceTemplate` containing this parameter, or None if not contained in a - service template. - """ - - from . import models - container = self.container - if isinstance(container, models.ServiceTemplate): - return container - elif hasattr(container, 'service_template'): - return container.service_template - return None - - @property - def as_raw(self): - return collections.OrderedDict(( - ('name', self.name), - ('type_name', self.type_name), - ('value', self.value), - ('description', self.description))) - - def instantiate(self, container): - return self.__class__(name=self.name, # pylint: disable=unexpected-keyword-arg - type_name=self.type_name, - _value=self._value, - description=self.description) - - def coerce_values(self, report_issues): - value = self._value - if value is not None: - evaluation = functions.evaluate(value, self, report_issues) - if (evaluation is not None) and evaluation.final: - # A final evaluation can safely replace the existing value - self._value = evaluation.value - - def dump(self): - context = ConsumptionContext.get_thread_local() - if self.type_name is not None: - console.puts('{0}: {1} ({2})'.format( - context.style.property(self.name), - context.style.literal(formatting.as_raw(self.value)), - context.style.type(self.type_name))) - else: - console.puts('{0}: {1}'.format( - context.style.property(self.name), - context.style.literal(formatting.as_raw(self.value)))) - if self.description: - console.puts(context.style.meta(self.description)) - - @property - def unwrapped(self): - return self.name, self.value - - @classmethod - def wrap(cls, name, value, description=None): - """ - Wraps an arbitrary value as a parameter. The type will be guessed via introspection. - - For primitive types, we will prefer their TOSCA aliases. See the `TOSCA Simple Profile v1.0 - cos01 specification <http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01 - /TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Toc373867862>`__ - - :param name: Parameter name - :type name: basestring - :param value: Parameter value - :param description: Description (optional) - :type description: basestring - """ - - type_name = canonical_type_name(value) - if type_name is None: - type_name = full_type_name(value) - return cls(name=name, # pylint: disable=unexpected-keyword-arg - type_name=type_name, - value=value, - description=description) - - -class OutputBase(ParameterMixin, TemplateModelMixin, caching.HasCachedMethods): +class OutputBase(ParameterMixin): __tablename__ = 'output' @@ -260,7 +58,7 @@ class OutputBase(ParameterMixin, TemplateModelMixin, caching.HasCachedMethods): # endregion -class InputBase(ParameterMixin, TemplateModelMixin, caching.HasCachedMethods): +class InputBase(ParameterMixin): __tablename__ = 'input' @@ -330,14 +128,39 @@ class InputBase(ParameterMixin, TemplateModelMixin, caching.HasCachedMethods): def execution(cls): return relationship.many_to_one(cls, 'execution') + # endregion + + +class ConfigurationBase(ParameterMixin): + + __tablename__ = 'configuration' + + # region foreign keys + + @declared_attr + def operation_template_fk(cls): + return relationship.foreign_key('operation_template', nullable=True) + + @declared_attr + def operation_fk(cls): + return relationship.foreign_key('operation', nullable=True) + + # endregion + + # region many_to_one relationships + @declared_attr - def task(cls): - return relationship.many_to_one(cls, 'task') + def operation_template(cls): + return relationship.many_to_one(cls, 'operation_template') + + @declared_attr + def operation(cls): + return relationship.many_to_one(cls, 'operation') # endregion -class PropertyBase(ParameterMixin, TemplateModelMixin, caching.HasCachedMethods): +class PropertyBase(ParameterMixin): __tablename__ = 'property' @@ -445,7 +268,7 @@ class PropertyBase(ParameterMixin, TemplateModelMixin, caching.HasCachedMethods) # endregion -class AttributeBase(ParameterMixin, TemplateModelMixin, caching.HasCachedMethods): +class AttributeBase(ParameterMixin): __tablename__ = 'attribute' http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/modeling/service_instance.py ---------------------------------------------------------------------- diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py index 6a6fa86..2bf9872 100644 --- a/aria/modeling/service_instance.py +++ b/aria/modeling/service_instance.py @@ -338,7 +338,7 @@ class NodeBase(InstanceModelMixin): :ivar host: Host node (can be self) :vartype host: :class:`Node` :ivar state: The state of the node, according to to the TOSCA-defined node states - :vartype stateg: string + :vartype state: string :ivar version: Used by `aria.storage.instrumentation` :vartype version: int :ivar service: Containing service @@ -1621,15 +1621,15 @@ class OperationBase(InstanceModelMixin): :ivar dependencies: Dependency strings (interpreted by the plugin) :vartype dependencies: [basestring] :ivar inputs: Input that can be used by this operation - :vartype inputs: {basestring: :class:`Parameter`} + :vartype inputs: {basestring: :class:`Input`} :ivar plugin: Associated plugin :vartype plugin: :class:`Plugin` - :ivar configuration: Configuration (interpreted by the plugin) - :vartype configuration: {basestring, :class:`Parameter`} + :ivar configurations: Configuration (interpreted by the plugin) + :vartype configurations: {basestring, :class:`Configuration`} :ivar function: Name of the operation function :vartype function: basestring :ivar arguments: Arguments to send to the operation function - :vartype arguments: {basestring: :class:`Parameter`} + :vartype arguments: {basestring: :class:`Argument`} :ivar executor: Name of executor to run the operation with :vartype executor: basestring :ivar max_attempts: Maximum number of attempts allowed in case of failure @@ -1691,6 +1691,14 @@ class OperationBase(InstanceModelMixin): def inputs(cls): return relationship.one_to_many(cls, 'input', dict_key='name') + @declared_attr + def configurations(cls): + return relationship.one_to_many(cls, 'configuration', dict_key='name') + + @declared_attr + def arguments(cls): + return relationship.one_to_many(cls, 'argument', dict_key='name') + # endregion # region many_to_one relationships @@ -1711,14 +1719,6 @@ class OperationBase(InstanceModelMixin): # region many_to_many relationships - @declared_attr - def configuration(cls): - return relationship.many_to_many(cls, 'parameter', prefix='configuration', dict_key='name') - - @declared_attr - def arguments(cls): - return relationship.many_to_many(cls, 'parameter', prefix='arguments', dict_key='name') - # endregion description = Column(Text) @@ -1742,11 +1742,19 @@ class OperationBase(InstanceModelMixin): # In the future plugins may be able to add their own "configure_operation" hook that # can validate the configuration and otherwise create specially derived arguments. For # now, we just send all configuration parameters as arguments without validation. - utils.instantiate_dict(self, self.arguments, self.configuration) + configurations_as_arguments = {} + for configuration in self.configurations.itervalues(): + configurations_as_arguments[configuration.name] = configuration.as_argument() + + utils.instantiate_dict(self, self.arguments, configurations_as_arguments) # Send all inputs as extra arguments # Note that they will override existing arguments of the same names - utils.instantiate_dict(self, self.arguments, self.inputs) + inputs_as_arguments = {} + for input in self.inputs.itervalues(): + inputs_as_arguments[input.name] = input.as_argument() + + utils.instantiate_dict(self, self.arguments, inputs_as_arguments) # Check for reserved arguments from ..orchestrator.decorators import OPERATION_DECORATOR_RESERVED_ARGUMENTS @@ -1773,12 +1781,12 @@ class OperationBase(InstanceModelMixin): def validate(self): # TODO must be associated with either interface or service utils.validate_dict_values(self.inputs) - utils.validate_dict_values(self.configuration) + utils.validate_dict_values(self.configurations) utils.validate_dict_values(self.arguments) def coerce_values(self, report_issues): utils.coerce_dict_values(self.inputs, report_issues) - utils.coerce_dict_values(self.configuration, report_issues) + utils.coerce_dict_values(self.configurations, report_issues) utils.coerce_dict_values(self.arguments, report_issues) def dump(self): @@ -1805,7 +1813,7 @@ class OperationBase(InstanceModelMixin): if self.plugin is not None: console.puts('Plugin: {0}'.format( context.style.literal(self.plugin.name))) - utils.dump_dict_values(self.configuration, 'Configuration') + utils.dump_dict_values(self.configurations, 'Configuration') if self.function is not None: console.puts('Function: {0}'.format(context.style.literal(self.function))) utils.dump_dict_values(self.arguments, 'Arguments') http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/modeling/service_template.py ---------------------------------------------------------------------- diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py index 663e75b..4d1e837 100644 --- a/aria/modeling/service_template.py +++ b/aria/modeling/service_template.py @@ -287,7 +287,7 @@ class ServiceTemplateBase(TemplateModelMixin): service_template=self) context.modeling.instance = service - service.inputs = utils.merge_parameter_values(inputs, self.inputs) + service.inputs = utils.merge_parameter_values(inputs, self.inputs, model_cls=models.Input) # TODO: now that we have inputs, we should scan properties and inputs and evaluate functions for plugin_specification in self.plugin_specifications.itervalues(): @@ -1745,11 +1745,11 @@ class OperationTemplateBase(TemplateModelMixin): :ivar dependencies: Dependency strings (interpreted by the plugin) :vartype dependencies: [basestring] :ivar inputs: Inputs that can be used by this operation - :vartype inputs: {basestring: :class:`Parameter`} + :vartype inputs: {basestring: :class:`Input`} :ivar plugin_specification: Associated plugin :vartype plugin_specification: :class:`PluginSpecification` - :ivar configuration: Configuration (interpreted by the plugin) - :vartype configuration: {basestring, :class:`Parameter`} + :ivar configurations: Configuration (interpreted by the plugin) + :vartype configurations: {basestring, :class:`Configuration`} :ivar function: Name of the operation function :vartype function: basestring :ivar executor: Name of executor to run the operation with @@ -1814,6 +1814,10 @@ class OperationTemplateBase(TemplateModelMixin): def operations(cls): return relationship.one_to_many(cls, 'operation') + @declared_attr + def configurations(cls): + return relationship.one_to_many(cls, 'configuration', dict_key='name') + # endregion # region many_to_one relationships @@ -1831,14 +1835,6 @@ class OperationTemplateBase(TemplateModelMixin): # region many_to_many relationships - @declared_attr - def inputs(cls): - return relationship.many_to_many(cls, 'input', dict_key='name') - - @declared_attr - def configuration(cls): - return relationship.many_to_many(cls, 'parameter', prefix='configuration', dict_key='name') - # endregion description = Column(Text) @@ -1879,17 +1875,17 @@ class OperationTemplateBase(TemplateModelMixin): operation_template=self) utils.instantiate_dict(container, operation.inputs, self.inputs) - utils.instantiate_dict(container, operation.configuration, self.configuration) + utils.instantiate_dict(container, operation.configurations, self.configurations) return operation def validate(self): utils.validate_dict_values(self.inputs) - utils.validate_dict_values(self.configuration) + utils.validate_dict_values(self.configurations) def coerce_values(self, report_issues): utils.coerce_dict_values(self.inputs, report_issues) - utils.coerce_dict_values(self.configuration, report_issues) + utils.coerce_dict_values(self.configurations, report_issues) def dump(self): context = ConsumptionContext.get_thread_local() @@ -1914,7 +1910,7 @@ class OperationTemplateBase(TemplateModelMixin): if self.plugin_specification is not None: console.puts('Plugin specification: {0}'.format( context.style.literal(self.plugin_specification.name))) - utils.dump_dict_values(self.configuration, 'Configuration') + utils.dump_dict_values(self.configurations, 'Configuration') if self.function is not None: console.puts('Function: {0}'.format(context.style.literal(self.function))) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/modeling/utils.py ---------------------------------------------------------------------- diff --git a/aria/modeling/utils.py b/aria/modeling/utils.py index 66e9c99..43be410 100644 --- a/aria/modeling/utils.py +++ b/aria/modeling/utils.py @@ -53,7 +53,7 @@ class NodeTemplateContainerHolder(object): return self.container.service_template -def merge_parameter_values(parameter_values, declared_parameters): +def merge_parameter_values(parameter_values, declared_parameters, model_cls): """ Merges parameter values according to those declared by a type. @@ -74,8 +74,6 @@ def merge_parameter_values(parameter_values, declared_parameters): ``parameter_values`` does not match its type in ``declared_parameters`` """ - from . import models - parameter_values = parameter_values or {} undeclared_names = list(set(parameter_values.keys()).difference(declared_parameters.keys())) @@ -106,7 +104,7 @@ def merge_parameter_values(parameter_values, declared_parameters): pass # Wrap in Parameter model - parameters[declared_parameter_name] = models.Parameter( # pylint: disable=unexpected-keyword-arg + parameters[declared_parameter_name] = model_cls( # pylint: disable=unexpected-keyword-arg name=declared_parameter_name, type_name=type_name, description=declared_parameter.description, http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/orchestrator/context/collection_instrumentation.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/context/collection_instrumentation.py b/aria/orchestrator/context/collection_instrumentation.py index 91cfd35..8f80d4a 100644 --- a/aria/orchestrator/context/collection_instrumentation.py +++ b/aria/orchestrator/context/collection_instrumentation.py @@ -84,7 +84,7 @@ class _InstrumentedCollection(object): :param value: :return: """ - if isinstance(value, models.Parameter): + if isinstance(value, models.Attribute): return value.value return value @@ -96,10 +96,10 @@ class _InstrumentedCollection(object): :param value: :return: """ - if isinstance(value, models.Parameter): + if isinstance(value, models.Attribute): return value # If it is not wrapped - return models.Parameter.wrap(key, value) + return models.Attribute.wrap(key, value) def __setitem__(self, key, value): """ @@ -112,7 +112,7 @@ class _InstrumentedCollection(object): if self._is_top_level: # We are at the top level field = getattr(self._parent, self._field_name) - mapi = getattr(self._model, models.Parameter.__modelname__) + mapi = getattr(self._model, models.Attribute.__modelname__) value = self._set_field(field, key, value if key in field else self._encapsulate_value(key, value)) @@ -131,7 +131,7 @@ class _InstrumentedCollection(object): """ if isinstance(value, _InstrumentedCollection): value = value._raw - if key in collection and isinstance(collection[key], models.Parameter): + if key in collection and isinstance(collection[key], models.Attribute): if isinstance(collection[key], _InstrumentedCollection): self._del(collection, key) collection[key].value = value http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/orchestrator/execution_plugin/instantiation.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/execution_plugin/instantiation.py b/aria/orchestrator/execution_plugin/instantiation.py index 9b5152d..b067e8c 100644 --- a/aria/orchestrator/execution_plugin/instantiation.py +++ b/aria/orchestrator/execution_plugin/instantiation.py @@ -42,7 +42,7 @@ def configure_operation(operation): # Any remaining un-handled configuration parameters will become extra arguments, available as # kwargs in either "run_script_locally" or "run_script_with_ssh" - for key, value in operation.configuration.iteritems(): + for key, value in operation.configurations.iteritems(): if key not in ('process', 'ssh'): operation.arguments[key] = value.instantiate(None) @@ -52,11 +52,11 @@ def _configure_common(operation): Local and remote operations. """ - from ...modeling.models import Parameter - operation.arguments['script_path'] = Parameter.wrap('script_path', operation.implementation, - 'Relative path to the executable file.') - operation.arguments['process'] = Parameter.wrap('process', _get_process(operation), - 'Sub-process configuration.') + from ...modeling.models import Argument + operation.arguments['script_path'] = Argument.wrap('script_path', operation.implementation, + 'Relative path to the executable file.') + operation.arguments['process'] = Argument.wrap('process', _get_process(operation), + 'Sub-process configuration.') def _configure_local(operation): @@ -74,7 +74,7 @@ def _configure_remote(operation): Remote SSH operation via Fabric. """ - from ...modeling.models import Parameter + from ...modeling.models import Argument from . import operations ssh = _get_ssh(operation) @@ -88,11 +88,11 @@ def _configure_remote(operation): if ('password' not in ssh) and ('key' not in ssh) and ('key_filename' not in ssh): ssh['password'] = default_password - operation.arguments['use_sudo'] = Parameter.wrap('use_sudo', ssh.get('use_sudo', False), - 'Whether to execute with sudo.') + operation.arguments['use_sudo'] = Argument.wrap('use_sudo', ssh.get('use_sudo', False), + 'Whether to execute with sudo.') - operation.arguments['hide_output'] = Parameter.wrap('hide_output', ssh.get('hide_output', []), - 'Hide output of these Fabric groups.') + operation.arguments['hide_output'] = Argument.wrap('hide_output', ssh.get('hide_output', []), + 'Hide output of these Fabric groups.') fabric_env = {} if 'warn_only' in ssh: @@ -121,16 +121,17 @@ def _configure_remote(operation): .format(operation.implementation), level=validation.Issue.BETWEEN_TYPES) - operation.arguments['fabric_env'] = Parameter.wrap('fabric_env', fabric_env, - 'Fabric configuration.') + operation.arguments['fabric_env'] = Argument.wrap('fabric_env', fabric_env, + 'Fabric configuration.') operation.function = '{0}.{1}'.format(operations.__name__, operations.run_script_with_ssh.__name__) def _get_process(operation): - value = operation.configuration.get('process')._value \ - if 'process' in operation.configuration else None + value = (operation.configurations.get('process')._value + if 'process' in operation.configurations + else None) if value is None: return {} _validate_type(value, dict, 'process') @@ -155,8 +156,9 @@ def _get_process(operation): def _get_ssh(operation): - value = operation.configuration.get('ssh')._value \ - if 'ssh' in operation.configuration else None + value = (operation.configurations.get('ssh')._value + if 'ssh' in operation.configurations + else None) if value is None: return {} _validate_type(value, dict, 'ssh') http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/orchestrator/workflow_runner.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/workflow_runner.py b/aria/orchestrator/workflow_runner.py index 15a55b0..848c59b 100644 --- a/aria/orchestrator/workflow_runner.py +++ b/aria/orchestrator/workflow_runner.py @@ -120,7 +120,9 @@ class WorkflowRunner(object): else: workflow_inputs = self.service.workflows[self._workflow_name].inputs - execution.inputs = modeling_utils.merge_parameter_values(inputs, workflow_inputs) + execution.inputs = modeling_utils.merge_parameter_values(inputs, + workflow_inputs, + model_cls=models.Input) # TODO: these two following calls should execute atomically self._validate_no_active_executions(execution) self._model_storage.execution.put(execution) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/aria/orchestrator/workflows/api/task.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/workflows/api/task.py b/aria/orchestrator/workflows/api/task.py index feacaf4..bcba56e 100644 --- a/aria/orchestrator/workflows/api/task.py +++ b/aria/orchestrator/workflows/api/task.py @@ -70,7 +70,7 @@ class OperationTask(BaseTask): :ivar function: path to Python function :vartype function: basestring :ivar arguments: arguments to send to Python function - :vartype arguments: {basestring, :class:`aria.modeling.models.Parameter`} + :vartype arguments: {basestring, :class:`aria.modeling.models.Argument`} :ivar ignore_failure: whether to ignore failures :vartype ignore_failure: bool :ivar max_attempts: maximum number of attempts allowed in case of failure @@ -139,7 +139,9 @@ class OperationTask(BaseTask): operation = self.actor.interfaces[self.interface_name].operations[self.operation_name] self.plugin = operation.plugin self.function = operation.function - self.arguments = modeling_utils.merge_parameter_values(arguments, operation.arguments) + self.arguments = modeling_utils.merge_parameter_values(arguments, + operation.arguments, + model_cls=models.Argument) def __repr__(self): return self.name http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/examples/hello-world/helloworld.yaml ---------------------------------------------------------------------- diff --git a/examples/hello-world/helloworld.yaml b/examples/hello-world/helloworld.yaml index 55c5030..be78401 100644 --- a/examples/hello-world/helloworld.yaml +++ b/examples/hello-world/helloworld.yaml @@ -29,9 +29,4 @@ topology_template: Standard: configure: scripts/configure.sh start: scripts/start.sh - stop: scripts/stop.sh - - outputs: - test_output: - description: description_of_test_output - value: value_of_test_output + stop: scripts/stop.sh \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py index 3c71cf1..2d50ad5 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py @@ -37,7 +37,7 @@ from aria.modeling.models import (Type, ServiceTemplate, NodeTemplate, GroupTemplate, PolicyTemplate, SubstitutionTemplate, SubstitutionTemplateMapping, InterfaceTemplate, OperationTemplate, ArtifactTemplate, Metadata, Input, Output, Property, - Attribute, PluginSpecification) + Attribute, Configuration, PluginSpecification) from .parameters import coerce_parameter_value from .constraints import (Equal, GreaterThan, GreaterOrEqual, LessThan, LessOrEqual, InRange, @@ -424,10 +424,10 @@ def create_operation_template_model(context, service_template, operation): model.dependencies = [] model.dependencies.append(dependency) - # Convert configuration to Parameter models + # Convert configuration to Configuration models for key, value in configuration.iteritems(): - model.configuration[key] = Parameter.wrap(key, value, - description='Operation configuration.') + model.configurations[key] = Configuration.wrap(key, value, + description='Operation configuration.') inputs = operation.inputs if inputs: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/tests/mock/models.py ---------------------------------------------------------------------- diff --git a/tests/mock/models.py b/tests/mock/models.py index 93d4352..f7f95b8 100644 --- a/tests/mock/models.py +++ b/tests/mock/models.py @@ -120,7 +120,7 @@ def create_node_with_dependencies(include_attribute=False): node_template.service_template.services[0] = create_service(node_template.service_template) node = create_node(node_template, node_template.service_template.services[0]) if include_attribute: - node.attributes['attribute1'] = models.Parameter.wrap('attribute1', 'value1') # pylint: disable=unsubscriptable-object + node.attributes['attribute1'] = models.Attribute.wrap('attribute1', 'value1') # pylint: disable=unsubscriptable-object return node @@ -227,7 +227,7 @@ def create_interface(service, interface_name, operation_name, operation_kwargs=N if operation_kwargs and operation_kwargs.get('arguments'): operation_kwargs['arguments'] = dict( - (argument_name, models.Parameter.wrap(argument_name, argument_value)) + (argument_name, models.Argument.wrap(argument_name, argument_value)) for argument_name, argument_value in operation_kwargs['arguments'].iteritems() if argument_value is not None) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/tests/mock/topology.py ---------------------------------------------------------------------- diff --git a/tests/mock/topology.py b/tests/mock/topology.py index ab08dbd..9f0521f 100644 --- a/tests/mock/topology.py +++ b/tests/mock/topology.py @@ -28,8 +28,8 @@ def create_simple_topology_single_node(model_storage, create_operation): 'Standard', 'create', operation_kwargs=dict( function=create_operation, - arguments={'key': aria_models.Parameter.wrap('key', 'create'), - 'value': aria_models.Parameter.wrap('value', True)}) + arguments={'key': aria_models.Argument.wrap('key', 'create'), + 'value': aria_models.Argument.wrap('value', True)}) ) node_template.interface_templates[interface_template.name] = interface_template # pylint: disable=unsubscriptable-object @@ -39,8 +39,8 @@ def create_simple_topology_single_node(model_storage, create_operation): 'Standard', 'create', operation_kwargs=dict( function=create_operation, - arguments={'key': aria_models.Parameter.wrap('key', 'create'), - 'value': aria_models.Parameter.wrap('value', True)}) + arguments={'key': aria_models.Argument.wrap('key', 'create'), + 'value': aria_models.Argument.wrap('value', True)}) ) node.interfaces[interface.name] = interface # pylint: disable=unsubscriptable-object http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/tests/modeling/test_models.py ---------------------------------------------------------------------- diff --git a/tests/modeling/test_models.py b/tests/modeling/test_models.py index a38ec2b..f2acc73 100644 --- a/tests/modeling/test_models.py +++ b/tests/modeling/test_models.py @@ -37,6 +37,7 @@ from aria.modeling.models import ( NodeTemplate, Node, Property, + Attribute, Type ) @@ -640,7 +641,7 @@ class TestNodeHostAddress(object): if host_address is not None: host_address = host_address.value if host_address: - kwargs.setdefault('attributes', {})['ip'] = Parameter.wrap('ip', host_address) + kwargs.setdefault('attributes', {})['ip'] = Attribute.wrap('ip', host_address) if is_host: kwargs['host_fk'] = 1 elif host_fk: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/tests/orchestrator/context/test_collection_instrumentation.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_collection_instrumentation.py b/tests/orchestrator/context/test_collection_instrumentation.py index 3ee5a44..1e6214a 100644 --- a/tests/orchestrator/context/test_collection_instrumentation.py +++ b/tests/orchestrator/context/test_collection_instrumentation.py @@ -15,7 +15,7 @@ import pytest -from aria.modeling.models import Parameter +from aria.modeling.models import Attribute from aria.orchestrator.context import collection_instrumentation @@ -28,7 +28,7 @@ class MockActor(object): class MockModel(object): def __init__(self): - self.parameter = type('MockModel', (object, ), {'model_cls': Parameter, + self.attribute = type('MockModel', (object, ), {'model_cls': Attribute, 'put': lambda *args, **kwargs: None, 'update': lambda *args, **kwargs: None})() @@ -57,16 +57,16 @@ class TestDict(CollectionInstrumentation): def test_keys(self, actor, dict_): dict_.update( { - 'key1': Parameter.wrap('key1', 'value1'), - 'key2': Parameter.wrap('key2', 'value2') + 'key1': Attribute.wrap('key1', 'value1'), + 'key2': Attribute.wrap('key2', 'value2') } ) assert sorted(dict_.keys()) == sorted(['key1', 'key2']) == sorted(actor.dict_.keys()) def test_values(self, actor, dict_): dict_.update({ - 'key1': Parameter.wrap('key1', 'value1'), - 'key2': Parameter.wrap('key1', 'value2') + 'key1': Attribute.wrap('key1', 'value1'), + 'key2': Attribute.wrap('key1', 'value2') }) assert (sorted(dict_.values()) == sorted(['value1', 'value2']) == @@ -74,34 +74,34 @@ class TestDict(CollectionInstrumentation): def test_items(self, dict_): dict_.update({ - 'key1': Parameter.wrap('key1', 'value1'), - 'key2': Parameter.wrap('key1', 'value2') + 'key1': Attribute.wrap('key1', 'value1'), + 'key2': Attribute.wrap('key1', 'value2') }) assert sorted(dict_.items()) == sorted([('key1', 'value1'), ('key2', 'value2')]) def test_iter(self, actor, dict_): dict_.update({ - 'key1': Parameter.wrap('key1', 'value1'), - 'key2': Parameter.wrap('key1', 'value2') + 'key1': Attribute.wrap('key1', 'value1'), + 'key2': Attribute.wrap('key1', 'value2') }) assert sorted(list(dict_)) == sorted(['key1', 'key2']) == sorted(actor.dict_.keys()) def test_bool(self, dict_): assert not dict_ dict_.update({ - 'key1': Parameter.wrap('key1', 'value1'), - 'key2': Parameter.wrap('key1', 'value2') + 'key1': Attribute.wrap('key1', 'value1'), + 'key2': Attribute.wrap('key1', 'value2') }) assert dict_ def test_set_item(self, actor, dict_): - dict_['key1'] = Parameter.wrap('key1', 'value1') + dict_['key1'] = Attribute.wrap('key1', 'value1') assert dict_['key1'] == 'value1' == actor.dict_['key1'].value - assert isinstance(actor.dict_['key1'], Parameter) + assert isinstance(actor.dict_['key1'], Attribute) def test_nested(self, actor, dict_): dict_['key'] = {} - assert isinstance(actor.dict_['key'], Parameter) + assert isinstance(actor.dict_['key'], Attribute) assert dict_['key'] == actor.dict_['key'].value == {} dict_['key']['inner_key'] = 'value' @@ -112,7 +112,7 @@ class TestDict(CollectionInstrumentation): assert dict_['key'].keys() == ['inner_key'] assert dict_['key'].values() == ['value'] assert dict_['key'].items() == [('inner_key', 'value')] - assert isinstance(actor.dict_['key'], Parameter) + assert isinstance(actor.dict_['key'], Attribute) assert isinstance(dict_['key'], collection_instrumentation._InstrumentedDict) dict_['key'].update({'updated_key': 'updated_value'}) @@ -123,7 +123,7 @@ class TestDict(CollectionInstrumentation): assert sorted(dict_['key'].values()) == sorted(['value', 'updated_value']) assert sorted(dict_['key'].items()) == sorted([('inner_key', 'value'), ('updated_key', 'updated_value')]) - assert isinstance(actor.dict_['key'], Parameter) + assert isinstance(actor.dict_['key'], Attribute) assert isinstance(dict_['key'], collection_instrumentation._InstrumentedDict) dict_.update({'key': 'override_value'}) @@ -131,12 +131,12 @@ class TestDict(CollectionInstrumentation): assert 'key' in dict_ assert dict_['key'] == 'override_value' assert len(actor.dict_) == 1 - assert isinstance(actor.dict_['key'], Parameter) + assert isinstance(actor.dict_['key'], Attribute) assert actor.dict_['key'].value == 'override_value' def test_get_item(self, actor, dict_): - dict_['key1'] = Parameter.wrap('key1', 'value1') - assert isinstance(actor.dict_['key1'], Parameter) + dict_['key1'] = Attribute.wrap('key1', 'value1') + assert isinstance(actor.dict_['key1'], Attribute) def test_update(self, actor, dict_): dict_['key1'] = 'value1' @@ -145,7 +145,7 @@ class TestDict(CollectionInstrumentation): dict_.update(new_dict) assert len(dict_) == 2 assert dict_['key2'] == 'value2' - assert isinstance(actor.dict_['key2'], Parameter) + assert isinstance(actor.dict_['key2'], Attribute) new_dict = {} new_dict.update(dict_) @@ -172,20 +172,20 @@ class TestDict(CollectionInstrumentation): class TestList(CollectionInstrumentation): def test_append(self, actor, list_): - list_.append(Parameter.wrap('name', 'value1')) + list_.append(Attribute.wrap('name', 'value1')) list_.append('value2') assert len(actor.list_) == 2 assert len(list_) == 2 - assert isinstance(actor.list_[0], Parameter) + assert isinstance(actor.list_[0], Attribute) assert list_[0] == 'value1' - assert isinstance(actor.list_[1], Parameter) + assert isinstance(actor.list_[1], Attribute) assert list_[1] == 'value2' list_[0] = 'new_value1' list_[1] = 'new_value2' - assert isinstance(actor.list_[1], Parameter) - assert isinstance(actor.list_[1], Parameter) + assert isinstance(actor.list_[1], Attribute) + assert isinstance(actor.list_[1], Attribute) assert list_[0] == 'new_value1' assert list_[1] == 'new_value2' @@ -214,12 +214,12 @@ class TestList(CollectionInstrumentation): list_.append([]) list_[0].append('inner_item') - assert isinstance(actor.list_[0], Parameter) + assert isinstance(actor.list_[0], Attribute) assert len(list_) == 1 assert list_[0][0] == 'inner_item' list_[0].append('new_item') - assert isinstance(actor.list_[0], Parameter) + assert isinstance(actor.list_[0], Attribute) assert len(list_) == 1 assert list_[0][1] == 'new_item' @@ -231,23 +231,23 @@ class TestDictList(CollectionInstrumentation): def test_dict_in_list(self, actor, list_): list_.append({}) assert len(list_) == 1 - assert isinstance(actor.list_[0], Parameter) + assert isinstance(actor.list_[0], Attribute) assert actor.list_[0].value == {} list_[0]['key'] = 'value' assert list_[0]['key'] == 'value' assert len(actor.list_) == 1 - assert isinstance(actor.list_[0], Parameter) + assert isinstance(actor.list_[0], Attribute) assert actor.list_[0].value['key'] == 'value' def test_list_in_dict(self, actor, dict_): dict_['key'] = [] assert len(dict_) == 1 - assert isinstance(actor.dict_['key'], Parameter) + assert isinstance(actor.dict_['key'], Attribute) assert actor.dict_['key'].value == [] dict_['key'].append('value') assert dict_['key'][0] == 'value' assert len(actor.dict_) == 1 - assert isinstance(actor.dict_['key'], Parameter) + assert isinstance(actor.dict_['key'], Attribute) assert actor.dict_['key'].value[0] == 'value' http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/tests/orchestrator/context/test_toolbelt.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/context/test_toolbelt.py b/tests/orchestrator/context/test_toolbelt.py index 326ce83..4de9e55 100644 --- a/tests/orchestrator/context/test_toolbelt.py +++ b/tests/orchestrator/context/test_toolbelt.py @@ -94,7 +94,7 @@ def test_host_ip(workflow_context, executor, dataholder): operation_kwargs=dict(function=op_path(host_ip, module_path=__name__), arguments=arguments) ) dependency_node.interfaces[interface.name] = interface - dependency_node.attributes['ip'] = models.Parameter.wrap('ip', '1.1.1.1') + dependency_node.attributes['ip'] = models.Attribute.wrap('ip', '1.1.1.1') workflow_context.model.node.update(dependency_node) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/tests/orchestrator/test_workflow_runner.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/test_workflow_runner.py b/tests/orchestrator/test_workflow_runner.py index 9d3698f..c5a62ae 100644 --- a/tests/orchestrator/test_workflow_runner.py +++ b/tests/orchestrator/test_workflow_runner.py @@ -255,12 +255,16 @@ def _setup_mock_workflow_in_service(request, inputs=None): source = workflow_mocks.__file__ resource.service_template.upload(str(service.service_template.id), source) mock_workflow_name = 'test_workflow' + arguments = {} + if inputs: + for input in inputs.itervalues(): + arguments[input.name] = input.as_argument() workflow = models.Operation( name=mock_workflow_name, service=service, function='workflow.mock_workflow', inputs=inputs or {}, - arguments=inputs or {}) + arguments=arguments) service.workflows[mock_workflow_name] = workflow return mock_workflow_name http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/798e5583/tests/orchestrator/workflows/executor/test_executor.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/workflows/executor/test_executor.py b/tests/orchestrator/workflows/executor/test_executor.py index 9ddaef4..3079c60 100644 --- a/tests/orchestrator/workflows/executor/test_executor.py +++ b/tests/orchestrator/workflows/executor/test_executor.py @@ -47,7 +47,7 @@ def execute_and_assert(executor, storage=None): successful_task = MockTask(_get_function(mock_successful_task), storage=storage) failing_task = MockTask(_get_function(mock_failing_task), storage=storage) task_with_inputs = MockTask(_get_function(mock_task_with_input), - arguments={'input': models.Parameter.wrap('input', 'value')}, + arguments={'input': models.Argument.wrap('input', 'value')}, storage=storage) for task in [successful_task, failing_task, task_with_inputs]: