You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ariatosca.apache.org by em...@apache.org on 2017/03/10 22:57:53 UTC
[3/6] incubator-ariatosca git commit: Separate plugin specification
form plugin; move dry support to CLI; various renames and refactorings
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index 092de51..c9a02eb 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -30,7 +30,7 @@ from sqlalchemy.ext.declarative import declared_attr
from ..parser import validation
from ..utils import collections, formatting, console
-from .bases import TemplateModelMixin
+from .mixins import TemplateModelMixin
from . import (
utils,
types as modeling_types
@@ -64,10 +64,10 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
:vartype inputs: {basestring: :class:`Parameter`}
:ivar outputs: These parameters are filled in after service installation
:vartype outputs: {basestring: :class:`Parameter`}
- :ivar operation_templates: Custom operations that can be performed on the service
- :vartype operation_templates: {basestring: :class:`OperationTemplate`}
- :ivar plugins: Plugins required by services
- :vartype plugins: {basestring: :class:`Plugin`}
+ :ivar workflow_templates: Custom workflows that can be performed on the service
+ :vartype workflow_templates: {basestring: :class:`OperationTemplate`}
+ :ivar plugin_specifications: Plugins required by services
+ :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
:ivar node_types: Base for the node type hierarchy
:vartype node_types: :class:`Type`
:ivar group_types: Base for the group type hierarchy
@@ -82,8 +82,8 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
:vartype interface_types: :class:`Type`
:ivar artifact_types: Base for the artifact type hierarchy
:vartype artifact_types: :class:`Type`
- :ivar plugins: Plugins required to be installed
- :vartype plugins: {basestring: :class:`Plugin`}
+ :ivar plugin_specifications: Plugins required to be installed
+ :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
:ivar created_at: Creation timestamp
:vartype created_at: :class:`datetime.datetime`
:ivar updated_at: Update timestamp
@@ -101,69 +101,73 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
@declared_attr
def meta_data(cls):
# Warning! We cannot use the attr name "metadata" because it's used by SqlAlchemy!
- return cls.many_to_many_relationship('metadata', dict_key='name')
+ return cls._create_many_to_many_relationship('metadata', dict_key='name')
@declared_attr
def node_templates(cls):
- return cls.one_to_many_relationship('node_template')
+ return cls._create_one_to_many_relationship('node_template')
@declared_attr
def group_templates(cls):
- return cls.one_to_many_relationship('group_template')
+ return cls._create_one_to_many_relationship('group_template')
@declared_attr
def policy_templates(cls):
- return cls.one_to_many_relationship('policy_template')
+ return cls._create_one_to_many_relationship('policy_template')
@declared_attr
def substitution_template(cls):
- return cls.one_to_one_relationship('substitution_template')
+ return cls._create_one_to_one_relationship('substitution_template')
@declared_attr
def inputs(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='inputs',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='inputs',
+ dict_key='name')
@declared_attr
def outputs(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='outputs',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='outputs',
+ dict_key='name')
@declared_attr
- def operation_templates(cls):
- return cls.one_to_many_relationship('operation_template', dict_key='name')
+ def workflow_templates(cls):
+ return cls._create_one_to_many_relationship('operation_template', dict_key='name')
@declared_attr
- def plugins(cls):
- return cls.one_to_many_relationship('plugin')
+ def plugin_specifications(cls):
+ return cls._create_one_to_many_relationship('plugin_specification')
@declared_attr
def node_types(cls):
- return cls.one_to_one_relationship('type', key='node_type_fk', backreference='')
+ return cls._create_one_to_one_relationship('type', key='node_type_fk', backreference='')
@declared_attr
def group_types(cls):
- return cls.one_to_one_relationship('type', key='group_type_fk', backreference='')
+ return cls._create_one_to_one_relationship('type', key='group_type_fk', backreference='')
@declared_attr
def policy_types(cls):
- return cls.one_to_one_relationship('type', key='policy_type_fk', backreference='')
+ return cls._create_one_to_one_relationship('type', key='policy_type_fk', backreference='')
@declared_attr
def relationship_types(cls):
- return cls.one_to_one_relationship('type', key='relationship_type_fk', backreference='')
+ return cls._create_one_to_one_relationship('type', key='relationship_type_fk',
+ backreference='')
@declared_attr
def capability_types(cls):
- return cls.one_to_one_relationship('type', key='capability_type_fk', backreference='')
+ return cls._create_one_to_one_relationship('type', key='capability_type_fk',
+ backreference='')
@declared_attr
def interface_types(cls):
- return cls.one_to_one_relationship('type', key='interface_type_fk', backreference='')
+ return cls._create_one_to_one_relationship('type', key='interface_type_fk',
+ backreference='')
@declared_attr
def artifact_types(cls):
- return cls.one_to_one_relationship('type', key='artifact_type_fk', backreference='')
+ return cls._create_one_to_one_relationship('type', key='artifact_type_fk',
+ backreference='')
# region orchestration
@@ -186,42 +190,42 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
# ServiceTemplate one-to-one to SubstitutionTemplate
@declared_attr
def substitution_template_fk(cls):
- return cls.foreign_key('substitution_template', nullable=True)
+ return cls._create_foreign_key('substitution_template', nullable=True)
# ServiceTemplate one-to-one to Type
@declared_attr
def node_type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# ServiceTemplate one-to-one to Type
@declared_attr
def group_type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# ServiceTemplate one-to-one to Type
@declared_attr
def policy_type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# ServiceTemplate one-to-one to Type
@declared_attr
def relationship_type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# ServiceTemplate one-to-one to Type
@declared_attr
def capability_type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# ServiceTemplate one-to-one to Type
@declared_attr
def interface_type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# ServiceTemplate one-to-one to Type
@declared_attr
def artifact_type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# endregion
@@ -250,7 +254,7 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
('substitution_template', formatting.as_raw(self.substitution_template)),
('inputs', formatting.as_raw_dict(self.inputs)),
('outputs', formatting.as_raw_dict(self.outputs)),
- ('operation_templates', formatting.as_raw_list(self.operation_templates))))
+ ('workflow_templates', formatting.as_raw_list(self.workflow_templates))))
@property
def types_as_raw(self):
@@ -283,7 +287,7 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
utils.instantiate_list(context, self, service.groups, self.group_templates)
utils.instantiate_list(context, self, service.policies, self.policy_templates)
- utils.instantiate_dict(context, self, service.operations, self.operation_templates)
+ utils.instantiate_dict(context, self, service.workflows, self.workflow_templates)
if self.substitution_template is not None:
service.substitution = self.substitution_template.instantiate(context, container)
@@ -308,7 +312,7 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
self.substitution_template.validate(context)
utils.validate_dict_values(context, self.inputs)
utils.validate_dict_values(context, self.outputs)
- utils.validate_dict_values(context, self.operation_templates)
+ utils.validate_dict_values(context, self.workflow_templates)
if self.node_types is not None:
self.node_types.validate(context)
if self.group_types is not None:
@@ -333,7 +337,7 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
self.substitution_template.coerce_values(context, container, report_issues)
utils.coerce_dict_values(context, container, self.inputs, report_issues)
utils.coerce_dict_values(context, container, self.outputs, report_issues)
- utils.coerce_dict_values(context, container, self.operation_templates, report_issues)
+ utils.coerce_dict_values(context, container, self.workflow_templates, report_issues)
def dump(self, context):
if self.description is not None:
@@ -349,7 +353,7 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
self.substitution_template.dump(context)
utils.dump_dict_values(context, self.inputs, 'Inputs')
utils.dump_dict_values(context, self.outputs, 'Outputs')
- utils.dump_dict_values(context, self.operation_templates, 'Operation templates')
+ utils.dump_dict_values(context, self.workflow_templates, 'Workflow templates')
def dump_types(self, context):
if self.node_types.children:
@@ -407,8 +411,8 @@ class NodeTemplateBase(TemplateModelMixin):
:vartype requirement_templates: [:class:`RequirementTemplate`]
:ivar target_node_template_constraints: Constraints for filtering relationship targets
:vartype target_node_template_constraints: [:class:`FunctionType`]
- :ivar plugins: Plugins required to be installed on the node's host
- :vartype plugins: {basestring: :class:`Plugin`}
+ :ivar plugin_specifications: Plugins required to be installed on the node's host
+ :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
:ivar service_template: Containing service template
:vartype service_template: :class:`ServiceTemplate`
@@ -426,7 +430,7 @@ class NodeTemplateBase(TemplateModelMixin):
@declared_attr
def type(cls):
- return cls.many_to_one_relationship('type')
+ return cls._create_many_to_one_relationship('type')
description = Column(Text)
default_instances = Column(Integer, default=1)
@@ -435,32 +439,32 @@ class NodeTemplateBase(TemplateModelMixin):
@declared_attr
def properties(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='properties',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='properties',
+ dict_key='name')
@declared_attr
def interface_templates(cls):
- return cls.one_to_many_relationship('interface_template', dict_key='name')
+ return cls._create_one_to_many_relationship('interface_template', dict_key='name')
@declared_attr
def artifact_templates(cls):
- return cls.one_to_many_relationship('artifact_template', dict_key='name')
+ return cls._create_one_to_many_relationship('artifact_template', dict_key='name')
@declared_attr
def capability_templates(cls):
- return cls.one_to_many_relationship('capability_template', dict_key='name')
+ return cls._create_one_to_many_relationship('capability_template', dict_key='name')
@declared_attr
def requirement_templates(cls):
- return cls.one_to_many_relationship('requirement_template',
- foreign_key='node_template_fk',
- backreference='node_template')
+ return cls._create_one_to_many_relationship('requirement_template',
+ foreign_key='node_template_fk',
+ backreference='node_template')
target_node_template_constraints = Column(modeling_types.StrictList(FunctionType))
@declared_attr
- def plugins(cls):
- return cls.many_to_many_relationship('plugin')
+ def plugin_specifications(cls):
+ return cls._create_many_to_many_relationship('plugin_specification')
# region foreign_keys
@@ -470,12 +474,12 @@ class NodeTemplateBase(TemplateModelMixin):
# NodeTemplate many-to-one to Type
@declared_attr
def type_fk(cls):
- return cls.foreign_key('type')
+ return cls._create_foreign_key('type')
# ServiceTemplate one-to-many to NodeTemplate
@declared_attr
def service_template_fk(cls):
- return cls.foreign_key('service_template')
+ return cls._create_foreign_key('service_template')
# endregion
@@ -579,22 +583,22 @@ class GroupTemplateBase(TemplateModelMixin):
@declared_attr
def type(cls):
- return cls.many_to_one_relationship('type')
+ return cls._create_many_to_one_relationship('type')
description = Column(Text)
@declared_attr
def node_templates(cls):
- return cls.many_to_many_relationship('node_template')
+ return cls._create_many_to_many_relationship('node_template')
@declared_attr
def properties(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='properties',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='properties',
+ dict_key='name')
@declared_attr
def interface_templates(cls):
- return cls.one_to_many_relationship('interface_template', dict_key='name')
+ return cls._create_one_to_many_relationship('interface_template', dict_key='name')
# region foreign keys
@@ -604,12 +608,12 @@ class GroupTemplateBase(TemplateModelMixin):
# GroupTemplate many-to-one to Type
@declared_attr
def type_fk(cls):
- return cls.foreign_key('type')
+ return cls._create_foreign_key('type')
# ServiceTemplate one-to-many to GroupTemplate
@declared_attr
def service_template_fk(cls):
- return cls.foreign_key('service_template')
+ return cls._create_foreign_key('service_template')
# endregion
@@ -684,22 +688,22 @@ class PolicyTemplateBase(TemplateModelMixin):
@declared_attr
def type(cls):
- return cls.many_to_one_relationship('type')
+ return cls._create_many_to_one_relationship('type')
description = Column(Text)
@declared_attr
def node_templates(cls):
- return cls.many_to_many_relationship('node_template')
+ return cls._create_many_to_many_relationship('node_template')
@declared_attr
def group_templates(cls):
- return cls.many_to_many_relationship('group_template')
+ return cls._create_many_to_many_relationship('group_template')
@declared_attr
def properties(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='properties',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='properties',
+ dict_key='name')
# region foreign keys
@@ -709,12 +713,12 @@ class PolicyTemplateBase(TemplateModelMixin):
# PolicyTemplate many-to-one to Type
@declared_attr
def type_fk(cls):
- return cls.foreign_key('type')
+ return cls._create_foreign_key('type')
# ServiceTemplate one-to-many to PolicyTemplate
@declared_attr
def service_template_fk(cls):
- return cls.foreign_key('service_template')
+ return cls._create_foreign_key('service_template')
# endregion
@@ -781,11 +785,12 @@ class SubstitutionTemplateBase(TemplateModelMixin):
@declared_attr
def node_type(cls):
- return cls.many_to_one_relationship('type')
+ return cls._create_many_to_one_relationship('type')
@declared_attr
def mappings(cls):
- return cls.one_to_many_relationship('substitution_template_mapping', dict_key='name')
+ return cls._create_one_to_many_relationship('substitution_template_mapping',
+ dict_key='name')
# region foreign keys
@@ -794,7 +799,7 @@ class SubstitutionTemplateBase(TemplateModelMixin):
# SubstitutionTemplate many-to-one to Type
@declared_attr
def node_type_fk(cls):
- return cls.foreign_key('type')
+ return cls._create_foreign_key('type')
# endregion
@@ -847,15 +852,15 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
@declared_attr
def node_template(cls):
- return cls.one_to_one_relationship('node_template')
+ return cls._create_one_to_one_relationship('node_template')
@declared_attr
def capability_template(cls):
- return cls.one_to_one_relationship('capability_template')
+ return cls._create_one_to_one_relationship('capability_template')
@declared_attr
def requirement_template(cls):
- return cls.one_to_one_relationship('requirement_template')
+ return cls._create_one_to_one_relationship('requirement_template')
# region foreign keys
@@ -867,22 +872,22 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
# SubstitutionTemplate one-to-many to SubstitutionTemplateMapping
@declared_attr
def substitution_template_fk(cls):
- return cls.foreign_key('substitution_template')
+ return cls._create_foreign_key('substitution_template')
# SubstitutionTemplate one-to-one to NodeTemplate
@declared_attr
def node_template_fk(cls):
- return cls.foreign_key('node_template')
+ return cls._create_foreign_key('node_template')
# SubstitutionTemplate one-to-one to CapabilityTemplate
@declared_attr
def capability_template_fk(cls):
- return cls.foreign_key('capability_template', nullable=True)
+ return cls._create_foreign_key('capability_template', nullable=True)
# SubstitutionTemplate one-to-one to RequirementTemplate
@declared_attr
def requirement_template_fk(cls):
- return cls.foreign_key('requirement_template', nullable=True)
+ return cls._create_foreign_key('requirement_template', nullable=True)
# endregion
@@ -965,24 +970,25 @@ class RequirementTemplateBase(TemplateModelMixin):
@declared_attr
def target_node_type(cls):
- return cls.many_to_one_relationship('type', key='target_node_type_fk', backreference='')
+ return cls._create_many_to_one_relationship('type', key='target_node_type_fk',
+ backreference='')
@declared_attr
def target_node_template(cls):
- return cls.one_to_one_relationship('node_template', key='target_node_template_fk',
- backreference='')
+ return cls._create_one_to_one_relationship('node_template', key='target_node_template_fk',
+ backreference='')
@declared_attr
def target_capability_type(cls):
- return cls.one_to_one_relationship('type', key='target_capability_type_fk',
- backreference='')
+ return cls._create_one_to_one_relationship('type', key='target_capability_type_fk',
+ backreference='')
target_capability_name = Column(Text)
target_node_template_constraints = Column(modeling_types.StrictList(FunctionType))
@declared_attr
def relationship_template(cls):
- return cls.one_to_one_relationship('relationship_template')
+ return cls._create_one_to_one_relationship('relationship_template')
# region foreign keys
@@ -995,27 +1001,27 @@ class RequirementTemplateBase(TemplateModelMixin):
# RequirementTemplate many-to-one to Type
@declared_attr
def target_node_type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# RequirementTemplate one-to-one to NodeTemplate
@declared_attr
def target_node_template_fk(cls):
- return cls.foreign_key('node_template', nullable=True)
+ return cls._create_foreign_key('node_template', nullable=True)
# RequirementTemplate one-to-one to NodeTemplate
@declared_attr
def target_capability_type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# NodeTemplate one-to-many to RequirementTemplate
@declared_attr
def node_template_fk(cls):
- return cls.foreign_key('node_template')
+ return cls._create_foreign_key('node_template')
# RequirementTemplate one-to-one to RelationshipTemplate
@declared_attr
def relationship_template_fk(cls):
- return cls.foreign_key('relationship_template', nullable=True)
+ return cls._create_foreign_key('relationship_template', nullable=True)
# endregion
@@ -1146,18 +1152,18 @@ class RelationshipTemplateBase(TemplateModelMixin):
@declared_attr
def type(cls):
- return cls.many_to_one_relationship('type')
+ return cls._create_many_to_one_relationship('type')
description = Column(Text)
@declared_attr
def properties(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='properties',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='properties',
+ dict_key='name')
@declared_attr
def interface_templates(cls):
- return cls.one_to_many_relationship('interface_template', dict_key='name')
+ return cls._create_one_to_many_relationship('interface_template', dict_key='name')
# region foreign keys
@@ -1166,7 +1172,7 @@ class RelationshipTemplateBase(TemplateModelMixin):
# RelationshipTemplate many-to-one to Type
@declared_attr
def type_fk(cls):
- return cls.foreign_key('type', nullable=True)
+ return cls._create_foreign_key('type', nullable=True)
# endregion
@@ -1243,7 +1249,7 @@ class CapabilityTemplateBase(TemplateModelMixin):
@declared_attr
def type(cls):
- return cls.many_to_one_relationship('type')
+ return cls._create_many_to_one_relationship('type')
description = Column(Text)
min_occurrences = Column(Integer, default=None) # optional
@@ -1251,12 +1257,12 @@ class CapabilityTemplateBase(TemplateModelMixin):
@declared_attr
def valid_source_node_types(cls):
- return cls.many_to_many_relationship('type', table_prefix='valid_sources')
+ return cls._create_many_to_many_relationship('type', table_prefix='valid_sources')
@declared_attr
def properties(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='properties',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='properties',
+ dict_key='name')
# region foreign keys
@@ -1266,12 +1272,12 @@ class CapabilityTemplateBase(TemplateModelMixin):
# CapabilityTemplate many-to-one to Type
@declared_attr
def type_fk(cls):
- return cls.foreign_key('type')
+ return cls._create_foreign_key('type')
# NodeTemplate one-to-many to CapabilityTemplate
@declared_attr
def node_template_fk(cls):
- return cls.foreign_key('node_template')
+ return cls._create_foreign_key('node_template')
# endregion
@@ -1375,17 +1381,17 @@ class InterfaceTemplateBase(TemplateModelMixin):
@declared_attr
def type(cls):
- return cls.many_to_one_relationship('type')
+ return cls._create_many_to_one_relationship('type')
description = Column(Text)
@declared_attr
def inputs(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='inputs',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='inputs',
+ dict_key='name')
@declared_attr
def operation_templates(cls):
- return cls.one_to_many_relationship('operation_template', dict_key='name')
+ return cls._create_one_to_many_relationship('operation_template', dict_key='name')
# region foreign keys
@@ -1397,22 +1403,22 @@ class InterfaceTemplateBase(TemplateModelMixin):
# InterfaceTemplate many-to-one to Type
@declared_attr
def type_fk(cls):
- return cls.foreign_key('type')
+ return cls._create_foreign_key('type')
# NodeTemplate one-to-many to InterfaceTemplate
@declared_attr
def node_template_fk(cls):
- return cls.foreign_key('node_template', nullable=True)
+ return cls._create_foreign_key('node_template', nullable=True)
# GroupTemplate one-to-many to InterfaceTemplate
@declared_attr
def group_template_fk(cls):
- return cls.foreign_key('group_template', nullable=True)
+ return cls._create_foreign_key('group_template', nullable=True)
# RelationshipTemplate one-to-many to InterfaceTemplate
@declared_attr
def relationship_template_fk(cls):
- return cls.foreign_key('relationship_template', nullable=True)
+ return cls._create_foreign_key('relationship_template', nullable=True)
# endregion
@@ -1458,14 +1464,14 @@ class OperationTemplateBase(TemplateModelMixin):
"""
An operation in a :class:`InterfaceTemplate`.
- Operations are executed by an associated :class:`Plugin` via an executor.
+ Operations are executed by an associated :class:`PluginSpecification` via an executor.
:ivar name: Name (unique for the interface or service template)
:vartype name: basestring
:ivar description: Human-readable description
:vartype description: basestring
- :ivar plugin: Associated plugin
- :vartype plugin: :class:`Plugin`
+ :ivar plugin_specification: Associated plugin
+ :vartype plugin_specification: :class:`PluginSpecification`
:ivar implementation: Implementation string (interpreted by the plugin)
:vartype implementation: basestring
:ivar dependencies: Dependency strings (interpreted by the plugin)
@@ -1492,16 +1498,16 @@ class OperationTemplateBase(TemplateModelMixin):
description = Column(Text)
@declared_attr
- def plugin(cls):
- return cls.one_to_one_relationship('plugin')
+ def plugin_specification(cls):
+ return cls._create_one_to_one_relationship('plugin_specification')
implementation = Column(Text)
dependencies = Column(modeling_types.StrictList(item_cls=basestring))
@declared_attr
def inputs(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='inputs',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='inputs',
+ dict_key='name')
executor = Column(Text)
max_retries = Column(Integer)
@@ -1516,17 +1522,17 @@ class OperationTemplateBase(TemplateModelMixin):
# ServiceTemplate one-to-many to OperationTemplate
@declared_attr
def service_template_fk(cls):
- return cls.foreign_key('service_template', nullable=True)
+ return cls._create_foreign_key('service_template', nullable=True)
# InterfaceTemplate one-to-many to OperationTemplate
@declared_attr
def interface_template_fk(cls):
- return cls.foreign_key('interface_template', nullable=True)
+ return cls._create_foreign_key('interface_template', nullable=True)
- # OperationTemplate one-to-one to Plugin
+ # OperationTemplate one-to-one to PluginSpecification
@declared_attr
- def plugin_fk(cls):
- return cls.foreign_key('plugin', nullable=True)
+ def plugin_specification_fk(cls):
+ return cls._create_foreign_key('plugin_specification', nullable=True)
# endregion
@@ -1548,7 +1554,7 @@ class OperationTemplateBase(TemplateModelMixin):
description=utils.deepcopy_with_locators(self.description),
implementation=self.implementation,
dependencies=self.dependencies,
- plugin=self.plugin,
+ plugin_specification=self.plugin_specification,
executor=self.executor,
max_retries=self.max_retries,
retry_interval=self.retry_interval,
@@ -1614,7 +1620,7 @@ class ArtifactTemplateBase(TemplateModelMixin):
@declared_attr
def type(cls):
- return cls.many_to_one_relationship('type')
+ return cls._create_many_to_one_relationship('type')
description = Column(Text)
source_path = Column(Text)
@@ -1624,8 +1630,8 @@ class ArtifactTemplateBase(TemplateModelMixin):
@declared_attr
def properties(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='properties',
- dict_key='name')
+ return cls._create_many_to_many_relationship('parameter', table_prefix='properties',
+ dict_key='name')
# region foreign keys
@@ -1635,12 +1641,12 @@ class ArtifactTemplateBase(TemplateModelMixin):
# ArtifactTemplate many-to-one to Type
@declared_attr
def type_fk(cls):
- return cls.foreign_key('type')
+ return cls._create_foreign_key('type')
# NodeTemplate one-to-many to ArtifactTemplate
@declared_attr
def node_template_fk(cls):
- return cls.foreign_key('node_template')
+ return cls._create_foreign_key('node_template')
# endregion
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/aria/orchestrator/workflows/api/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task.py b/aria/orchestrator/workflows/api/task.py
index d434da8..744d1b4 100644
--- a/aria/orchestrator/workflows/api/task.py
+++ b/aria/orchestrator/workflows/api/task.py
@@ -59,10 +59,7 @@ class OperationTask(BaseTask):
Represents an operation task in the task_graph
"""
- SOURCE_OPERATION = 'source'
- TARGET_OPERATION = 'target'
-
- NAME_FORMAT = '{type}:{id}->{interface}/{operation}'
+ NAME_FORMAT = '{interface}:{operation}@{type}:{id}'
def __init__(self,
name,
@@ -73,8 +70,7 @@ class OperationTask(BaseTask):
ignore_failure=None,
inputs=None,
plugin=None,
- runs_on=None,
- dry=False):
+ runs_on=None):
"""
Creates an operation task using the name, details, node instance and any additional kwargs.
@@ -84,12 +80,9 @@ class OperationTask(BaseTask):
"""
assert isinstance(actor, (models.Node, models.Relationship))
+ assert (runs_on is None) or (runs_on in models.Task.RUNS_ON)
super(OperationTask, self).__init__()
- if dry:
- from ..dry import convert_to_dry
- plugin, implementation, inputs = convert_to_dry(plugin, implementation, inputs)
-
# Coerce inputs
if inputs is None:
inputs = {}
@@ -131,13 +124,21 @@ class OperationTask(BaseTask):
'Could not find operation "{0}" on interface "{1}" for node "{2}"'.format(
operation_name, interface_name, node.name))
+ plugin = None
+ if operation.plugin_specification:
+ plugin = cls._find_plugin(operation.plugin_specification, kwargs)
+ if plugin is None:
+ raise exceptions.TaskException(
+ 'Could not find plugin of operation "{0}" on interface "{1}" for node "{2}"'
+ .format(operation_name, interface_name, node.name))
+
return cls(
actor=node,
name=cls.NAME_FORMAT.format(type='node',
- id=node.id,
+ id=node.name,
interface=interface_name,
operation=operation_name),
- plugin=operation.plugin,
+ plugin=plugin,
implementation=operation.implementation,
inputs=cls._merge_inputs(operation.inputs, inputs),
runs_on=models.Task.RUNS_ON_NODE,
@@ -165,13 +166,21 @@ class OperationTask(BaseTask):
'Could not find operation "{0}" on interface "{1}" for relationship "{2}"'.format(
operation_name, interface_name, relationship.name))
+ plugin = None
+ if operation.plugin_specification:
+ plugin = cls._find_plugin(operation.plugin_specification, kwargs)
+ if plugin is None:
+ raise exceptions.TaskException(
+ 'Could not find plugin of operation "{0}" on interface "{1}" for relationship '
+ '"{2}"'.format(operation_name, interface_name, relationship.name))
+
return cls(
actor=relationship,
name=cls.NAME_FORMAT.format(type='relationship',
- id=relationship.id,
+ id=relationship.name,
interface=interface_name,
operation=operation_name),
- plugin=operation.plugin,
+ plugin=plugin,
implementation=operation.implementation,
inputs=cls._merge_inputs(operation.inputs, inputs),
runs_on=runs_on,
@@ -186,6 +195,13 @@ class OperationTask(BaseTask):
return None
@classmethod
+ def _find_plugin(cls, plugin_specification, kwargs):
+ workflow_context = kwargs.get('ctx') if kwargs else None
+ if workflow_context is None:
+ workflow_context = context.workflow.current.get()
+ return plugin_specification.find_plugin(workflow_context.model.plugin.list())
+
+ @classmethod
def _merge_inputs(cls, operation_inputs, override_inputs=None):
final_inputs = OrderedDict(operation_inputs)
if override_inputs:
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/aria/orchestrator/workflows/builtin/execute_operation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/execute_operation.py b/aria/orchestrator/workflows/builtin/execute_operation.py
index ed4ada3..348f47a 100644
--- a/aria/orchestrator/workflows/builtin/execute_operation.py
+++ b/aria/orchestrator/workflows/builtin/execute_operation.py
@@ -58,8 +58,7 @@ def execute_operation(
type_names=type_names))
if run_by_dependency_order:
- filtered_node_ids = set(node_instance.id
- for node_instance in filtered_nodes)
+ filtered_node_ids = set(node_instance.id for node_instance in filtered_nodes)
for node in ctx.nodes:
if node.id not in filtered_node_ids:
subgraphs[node.id] = ctx.task_graph(
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/aria/orchestrator/workflows/builtin/utils.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/utils.py b/aria/orchestrator/workflows/builtin/utils.py
index 045d47b..84d8293 100644
--- a/aria/orchestrator/workflows/builtin/utils.py
+++ b/aria/orchestrator/workflows/builtin/utils.py
@@ -17,7 +17,7 @@ from ..api.task import OperationTask
from .. import exceptions
-def create_node_task(interface_name, operation_name, node, dry=False):
+def create_node_task(interface_name, operation_name, node):
"""
Returns a new operation task if the operation exists in the node, otherwise returns None.
"""
@@ -25,14 +25,12 @@ def create_node_task(interface_name, operation_name, node, dry=False):
try:
return OperationTask.for_node(node=node,
interface_name=interface_name,
- operation_name=operation_name,
- dry=dry)
+ operation_name=operation_name)
except exceptions.TaskException:
- pass
- return None
+ return None
-def create_relationship_tasks(interface_name, operation_name, runs_on, node, dry=False):
+def create_relationship_tasks(interface_name, operation_name, runs_on, node):
"""
Returns a list of operation tasks for each outbound relationship of the node if the operation
exists there.
@@ -45,8 +43,7 @@ def create_relationship_tasks(interface_name, operation_name, runs_on, node, dry
OperationTask.for_relationship(relationship=relationship,
interface_name=interface_name,
operation_name=operation_name,
- runs_on=runs_on,
- dry=dry))
+ runs_on=runs_on))
except exceptions.TaskException:
pass
return sequence
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/aria/orchestrator/workflows/builtin/workflows.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/workflows.py b/aria/orchestrator/workflows/builtin/workflows.py
index f19c031..6065343 100644
--- a/aria/orchestrator/workflows/builtin/workflows.py
+++ b/aria/orchestrator/workflows/builtin/workflows.py
@@ -67,128 +67,108 @@ __all__ = (
@workflow(suffix_template='{node.name}')
def install_node(graph, node, **kwargs):
- dry = kwargs.get('dry', True)
-
sequence = []
# Create
sequence.append(
create_node_task(
NORMATIVE_STANDARD_INTERFACE, NORMATIVE_CREATE,
- node,
- dry))
+ node))
# Configure
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_PRE_CONFIGURE_SOURCE,
Task.RUNS_ON_SOURCE,
- node,
- dry)
+ node)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_PRE_CONFIGURE_TARGET,
Task.RUNS_ON_TARGET,
- node,
- dry)
+ node)
sequence.append(
create_node_task(
NORMATIVE_STANDARD_INTERFACE, NORMATIVE_CONFIGURE,
- node,
- dry))
+ node))
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_POST_CONFIGURE_SOURCE,
Task.RUNS_ON_SOURCE,
- node,
- dry)
+ node)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_POST_CONFIGURE_TARGET,
Task.RUNS_ON_TARGET,
- node,
- dry)
+ node)
# Start
- sequence += _create_start_tasks(node, dry)
+ sequence += _create_start_tasks(node)
graph.sequence(*sequence)
@workflow(suffix_template='{node.name}')
def uninstall_node(graph, node, **kwargs):
- dry = kwargs.get('dry', True)
-
# Stop
- sequence = _create_stop_tasks(node, dry)
+ sequence = _create_stop_tasks(node)
# Delete
sequence.append(
create_node_task(
NORMATIVE_STANDARD_INTERFACE, NORMATIVE_DELETE,
- node,
- dry))
+ node))
graph.sequence(*sequence)
@workflow(suffix_template='{node.name}')
def start_node(graph, node, **kwargs):
- dry = kwargs.get('dry', True)
- graph.sequence(*_create_start_tasks(node, dry))
+ graph.sequence(*_create_start_tasks(node))
@workflow(suffix_template='{node.name}')
def stop_node(graph, node, **kwargs):
- dry = kwargs.get('dry', True)
- graph.sequence(*_create_stop_tasks(node, dry))
+ graph.sequence(*_create_stop_tasks(node))
-def _create_start_tasks(node, dry):
+def _create_start_tasks(node):
sequence = []
sequence.append(
create_node_task(
NORMATIVE_STANDARD_INTERFACE, NORMATIVE_START,
- node,
- dry))
+ node))
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_ADD_SOURCE,
Task.RUNS_ON_SOURCE,
- node,
- dry)
+ node)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_ADD_TARGET,
Task.RUNS_ON_TARGET,
- node,
- dry)
+ node)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_TARGET_CHANGED,
Task.RUNS_ON_TARGET,
- node,
- dry)
+ node)
return sequence
-def _create_stop_tasks(node, dry):
+def _create_stop_tasks(node):
sequence = []
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_REMOVE_TARGET,
Task.RUNS_ON_TARGET,
- node,
- dry)
+ node)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_TARGET_CHANGED,
Task.RUNS_ON_TARGET,
- node,
- dry)
+ node)
sequence.append(
create_node_task(
NORMATIVE_STANDARD_INTERFACE, NORMATIVE_STOP,
- node,
- dry))
+ node))
return sequence
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/aria/orchestrator/workflows/core/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/task.py b/aria/orchestrator/workflows/core/task.py
index 7d8380c..64f2818 100644
--- a/aria/orchestrator/workflows/core/task.py
+++ b/aria/orchestrator/workflows/core/task.py
@@ -113,15 +113,15 @@ class OperationTask(BaseTask):
base_task_model = model_storage.task.model_cls
if isinstance(api_task.actor, models.Node):
context_cls = operation_context.NodeOperationContext
- task_model_cls = base_task_model.as_node_task
+ create_task_model = base_task_model.for_node
elif isinstance(api_task.actor, models.Relationship):
context_cls = operation_context.RelationshipOperationContext
- task_model_cls = base_task_model.as_relationship_task
+ create_task_model = base_task_model.for_relationship
else:
raise RuntimeError('No operation context could be created for {actor.model_cls}'
.format(actor=api_task.actor))
- operation_task = task_model_cls(
+ task_model = create_task_model(
name=api_task.name,
implementation=api_task.implementation,
instance=api_task.actor,
@@ -131,20 +131,19 @@ class OperationTask(BaseTask):
retry_interval=api_task.retry_interval,
ignore_failure=api_task.ignore_failure,
plugin=plugin,
- plugin_name=plugin.name if plugin is not None else 'execution',
execution=self._workflow_context.execution,
runs_on=api_task.runs_on
)
- self._workflow_context.model.task.put(operation_task)
+ self._workflow_context.model.task.put(task_model)
self._ctx = context_cls(name=api_task.name,
model_storage=self._workflow_context.model,
resource_storage=self._workflow_context.resource,
service_id=self._workflow_context._service_id,
- task_id=operation_task.id,
+ task_id=task_model.id,
actor_id=api_task.actor.id,
workdir=self._workflow_context._workdir)
- self._task_id = operation_task.id
+ self._task_id = task_model.id
self._update_fields = None
@contextmanager
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/aria/orchestrator/workflows/dry.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/dry.py b/aria/orchestrator/workflows/dry.py
deleted file mode 100644
index 766ea0c..0000000
--- a/aria/orchestrator/workflows/dry.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You 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 threading import RLock
-
-from ..decorators import operation
-from ...utils.collections import OrderedDict
-from ...utils.console import puts, Colored
-from ...utils.formatting import safe_repr
-
-
-_TERMINAL_LOCK = RLock()
-
-
-def convert_to_dry(plugin, implementation, inputs): # pylint: disable=unused-argument
- dry_implementation = '{0}.{1}'.format(__name__, 'dry_operation')
- dry_inputs = OrderedDict()
- dry_inputs['_implementation'] = implementation
- dry_inputs['_plugin'] = plugin.name if plugin is not None else None
- return None, dry_implementation, dry_inputs
-
-
-@operation
-def dry_operation(ctx, _plugin, _implementation, **kwargs):
- with _TERMINAL_LOCK:
- print ctx.name
- if hasattr(ctx, 'relationship'):
- puts('> Relationship: {0} -> {1}'.format(
- Colored.red(ctx.relationship.source_node.name),
- Colored.red(ctx.relationship.target_node.name)))
- else:
- puts('> Node: {0}'.format(Colored.red(ctx.node.name)))
- puts(' Operation: {0}'.format(Colored.green(ctx.name)))
- _dump_implementation(_plugin, _implementation)
-
-
-def _dump_implementation(plugin, implementation):
- if plugin:
- puts(' Plugin: {0}'.format(Colored.magenta(plugin, bold=True)))
- if implementation:
- puts(' Implementation: {0}'.format(Colored.magenta(safe_repr(implementation))))
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/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 0206e03..a7b2a11 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -27,7 +27,7 @@ from aria.modeling.models import (Type, ServiceTemplate, NodeTemplate,
RequirementTemplate, RelationshipTemplate, CapabilityTemplate,
GroupTemplate, PolicyTemplate, SubstitutionTemplate,
SubstitutionTemplateMapping, InterfaceTemplate, OperationTemplate,
- ArtifactTemplate, Metadata, Parameter, Plugin)
+ ArtifactTemplate, Metadata, Parameter, PluginSpecification)
from ..data_types import coerce_value
@@ -81,12 +81,13 @@ def create_service_template_model(context): # pylint: disable=too-many-locals,to
create_parameter_models_from_values(model.outputs,
topology_template._get_output_values(context))
- # Plugins
+ # Plugin specifications
policies = context.presentation.get('service_template', 'topology_template', 'policies')
if policies:
for policy in policies.itervalues():
if model.policy_types.get_descendant(policy.type).role == 'plugin':
- model.plugins.append(create_plugin_model(context, policy))
+ model.plugin_specifications.append(
+ create_plugin_specification_model(context, policy))
# Node templates
node_templates = context.presentation.get('service_template', 'topology_template',
@@ -349,7 +350,7 @@ def create_operation_template_model(context, service_template, operation): # pyl
implementation = operation.implementation
if (implementation is not None) and operation.implementation.primary:
- model.plugin, model.implementation = \
+ model.plugin_specification, model.implementation = \
parse_implementation_string(context, service_template, operation.implementation.primary)
dependencies = implementation.dependencies
@@ -427,7 +428,7 @@ def create_substitution_template_model(context, service_template, substitution_m
return model
-def create_plugin_model(context, policy):
+def create_plugin_specification_model(context, policy):
properties = policy.properties
def get(name):
@@ -436,18 +437,16 @@ def create_plugin_model(context, policy):
now = datetime.now()
- model = Plugin(name=policy._name,
- archive_name=get('archive_name') or '',
- distribution=get('distribution'),
- distribution_release=get('distribution_release'),
- distribution_version=get('distribution_version'),
- package_name=get('package_name') or '',
- package_source=get('package_source'),
- package_version=get('package_version'),
- supported_platform=get('supported_platform'),
- supported_py_versions=get('supported_py_versions'),
- uploaded_at=now,
- wheels=get('wheels') or [])
+ model = PluginSpecification(name=policy._name,
+ archive_name=get('archive_name') or '',
+ distribution=get('distribution'),
+ distribution_release=get('distribution_release'),
+ distribution_version=get('distribution_version'),
+ package_name=get('package_name') or '',
+ package_source=get('package_source'),
+ package_version=get('package_version'),
+ supported_platform=get('supported_platform'),
+ supported_py_versions=get('supported_py_versions'))
return model
@@ -665,15 +664,15 @@ def parse_implementation_string(context, service_template, implementation):
plugin_name = implementation[:index].strip()
if plugin_name == 'execution':
- plugin = None
+ plugin_specification = None
else:
- plugin = None
- for the_plugin in service_template.plugins:
- if the_plugin.name == plugin_name:
- plugin = the_plugin
+ plugin_specification = None
+ for a_plugin_specification in service_template.plugin_specifications:
+ if a_plugin_specification.name == plugin_name:
+ plugin_specification = a_plugin_specification
break
- if plugin is None:
+ if plugin_specification is None:
raise ValueError('unknown plugin: "{0}"'.format(plugin_name))
implementation = implementation[index+1:].strip()
- return plugin, implementation
+ return plugin_specification, implementation
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/end2end/test_orchestrator.py
----------------------------------------------------------------------
diff --git a/tests/end2end/test_orchestrator.py b/tests/end2end/test_orchestrator.py
index fac6207..f25134f 100644
--- a/tests/end2end/test_orchestrator.py
+++ b/tests/end2end/test_orchestrator.py
@@ -19,6 +19,7 @@ from aria.orchestrator.runner import Runner
from aria.orchestrator.workflows.builtin import BUILTIN_WORKFLOWS
from aria.utils.imports import import_fullname
from aria.utils.collections import OrderedDict
+from aria.cli.dry import convert_to_dry
from tests.parser.service_templates import consume_node_cellar
@@ -37,6 +38,8 @@ def test_custom():
def _workflow(workflow_name):
context, _ = consume_node_cellar()
+ convert_to_dry(context.modeling.instance)
+
# TODO: this logic will eventually stabilize and be part of the ARIA API,
# likely somewhere in aria.orchestrator.workflows
if workflow_name in BUILTIN_WORKFLOWS:
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/mock/models.py
----------------------------------------------------------------------
diff --git a/tests/mock/models.py b/tests/mock/models.py
index 716254e..483da7d 100644
--- a/tests/mock/models.py
+++ b/tests/mock/models.py
@@ -191,6 +191,7 @@ def create_execution(service):
def create_plugin(package_name='package', package_version='0.1'):
return models.Plugin(
+ name='test_plugin',
archive_name='archive_name',
distribution='distribution',
distribution_release='dist_release',
@@ -205,5 +206,20 @@ def create_plugin(package_name='package', package_version='0.1'):
)
+def create_plugin_specification(package_name='package', package_version='0.1'):
+ return models.PluginSpecification(
+ name='test_plugin',
+ archive_name='archive_name',
+ distribution='distribution',
+ distribution_release='dist_release',
+ distribution_version='dist_version',
+ package_name=package_name,
+ package_source='source',
+ package_version=package_version,
+ supported_platform='any',
+ supported_py_versions=['python27']
+ )
+
+
def _dictify(item):
return dict(((item.name, item),))
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/tests/modeling/__init__.py b/tests/modeling/__init__.py
new file mode 100644
index 0000000..072ef54
--- /dev/null
+++ b/tests/modeling/__init__.py
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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 sqlalchemy import (
+ Column,
+ Text,
+ Integer,
+)
+
+from aria.modeling import (
+ models,
+ types as modeling_types,
+ mixins
+)
+
+
+class MockModel(models.aria_declarative_base, mixins.ModelMixin): #pylint: disable=abstract-method
+ __tablename__ = 'mock_model'
+ model_dict = Column(modeling_types.Dict)
+ model_list = Column(modeling_types.List)
+ value = Column(Integer)
+ name = Column(Text)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/modeling/test_mixins.py
----------------------------------------------------------------------
diff --git a/tests/modeling/test_mixins.py b/tests/modeling/test_mixins.py
new file mode 100644
index 0000000..a60412f
--- /dev/null
+++ b/tests/modeling/test_mixins.py
@@ -0,0 +1,219 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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 pytest
+
+import sqlalchemy
+
+from aria.storage import (
+ ModelStorage,
+ sql_mapi,
+ exceptions
+)
+from aria import modeling
+
+from ..storage import (
+ release_sqlite_storage,
+ init_inmemory_model_storage
+)
+from . import MockModel
+from ..mock import (
+ models,
+ context as mock_context
+)
+
+
+@pytest.fixture
+def storage():
+ base_storage = ModelStorage(sql_mapi.SQLAlchemyModelAPI,
+ initiator=init_inmemory_model_storage)
+ base_storage.register(MockModel)
+ yield base_storage
+ release_sqlite_storage(base_storage)
+
+
+@pytest.fixture(scope='module', autouse=True)
+def module_cleanup():
+ modeling.models.aria_declarative_base.metadata.remove(MockModel.__table__) # pylint: disable=no-member
+
+
+@pytest.fixture
+def context(tmpdir):
+ ctx = mock_context.simple(str(tmpdir))
+ yield ctx
+ release_sqlite_storage(ctx.model)
+
+
+def test_inner_dict_update(storage):
+ inner_dict = {'inner_value': 1}
+
+ mock_model = MockModel(model_dict={'inner_dict': inner_dict, 'value': 0})
+ storage.mock_model.put(mock_model)
+
+ storage_mm = storage.mock_model.get(mock_model.id)
+ assert storage_mm == mock_model
+
+ storage_mm.model_dict['inner_dict']['inner_value'] = 2
+ storage_mm.model_dict['value'] = -1
+ storage.mock_model.update(storage_mm)
+ storage_mm = storage.mock_model.get(storage_mm.id)
+
+ assert storage_mm.model_dict['inner_dict']['inner_value'] == 2
+ assert storage_mm.model_dict['value'] == -1
+
+
+def test_inner_list_update(storage):
+ mock_model = MockModel(model_list=[0, [1]])
+ storage.mock_model.put(mock_model)
+
+ storage_mm = storage.mock_model.get(mock_model.id)
+ assert storage_mm == mock_model
+
+ storage_mm.model_list[1][0] = 'new_inner_value'
+ storage_mm.model_list[0] = 'new_value'
+ storage.mock_model.update(storage_mm)
+ storage_mm = storage.mock_model.get(storage_mm.id)
+
+ assert storage_mm.model_list[1][0] == 'new_inner_value'
+ assert storage_mm.model_list[0] == 'new_value'
+
+
+def test_model_to_dict(context):
+ service = context.service
+ service = service.to_dict()
+
+ expected_keys = [
+ 'description',
+ 'created_at',
+ 'permalink',
+ 'scaling_groups',
+ 'updated_at'
+ ]
+
+ for expected_key in expected_keys:
+ assert expected_key in service
+
+
+def test_relationship_model_ordering(context):
+ service = context.model.service.get_by_name(models.SERVICE_NAME)
+ source_node = context.model.node.get_by_name(models.DEPENDENT_NODE_NAME)
+ target_node = context.model.node.get_by_name(models.DEPENDENCY_NODE_NAME)
+
+ new_node_template = modeling.models.NodeTemplate(
+ name='new_node_template',
+ type=source_node.type,
+ default_instances=1,
+ min_instances=1,
+ max_instances=1,
+ service_template=service.service_template
+ )
+
+ new_node = modeling.models.Node(
+ name='new_node',
+ type=source_node.type,
+ runtime_properties={},
+ service=service,
+ version=None,
+ node_template=new_node_template,
+ state='',
+ scaling_groups=[]
+ )
+
+ source_node.outbound_relationships.append(modeling.models.Relationship(
+ source_node=source_node,
+ target_node=new_node,
+ ))
+
+ new_node.outbound_relationships.append(modeling.models.Relationship( # pylint: disable=no-member
+ source_node=new_node,
+ target_node=target_node,
+ ))
+
+ context.model.node_template.put(new_node_template)
+ context.model.node.put(new_node)
+ context.model.node.refresh(source_node)
+ context.model.node.refresh(target_node)
+
+ def flip_and_assert(node, direction):
+ """
+ Reversed the order of relationships and assert effects took place.
+ :param node: the node instance to operate on
+ :param direction: the type of relationships to flip (inbound/outbound)
+ :return:
+ """
+ assert direction in ('inbound', 'outbound')
+
+ relationships = getattr(node, direction + '_relationships')
+ assert len(relationships) == 2
+
+ reversed_relationship = list(reversed(relationships))
+ assert relationships != reversed_relationship
+
+ relationships[:] = reversed_relationship
+ context.model.node.update(node)
+ assert relationships == reversed_relationship
+
+ flip_and_assert(source_node, 'outbound')
+ flip_and_assert(target_node, 'inbound')
+
+
+class StrictClass(modeling.models.aria_declarative_base, modeling.mixins.ModelMixin):
+ __tablename__ = 'strict_class'
+
+ strict_dict = sqlalchemy.Column(modeling.types.StrictDict(basestring, basestring))
+ strict_list = sqlalchemy.Column(modeling.types.StrictList(basestring))
+
+
+def test_strict_dict():
+
+ strict_class = StrictClass()
+
+ def assert_strict(sc):
+ with pytest.raises(exceptions.StorageError):
+ sc.strict_dict = {'key': 1}
+
+ with pytest.raises(exceptions.StorageError):
+ sc.strict_dict = {1: 'value'}
+
+ with pytest.raises(exceptions.StorageError):
+ sc.strict_dict = {1: 1}
+
+ assert_strict(strict_class)
+ strict_class.strict_dict = {'key': 'value'}
+ assert strict_class.strict_dict == {'key': 'value'}
+
+ assert_strict(strict_class)
+ with pytest.raises(exceptions.StorageError):
+ strict_class.strict_dict['key'] = 1
+ with pytest.raises(exceptions.StorageError):
+ strict_class.strict_dict[1] = 'value'
+ with pytest.raises(exceptions.StorageError):
+ strict_class.strict_dict[1] = 1
+
+
+def test_strict_list():
+ strict_class = StrictClass()
+
+ def assert_strict(sc):
+ with pytest.raises(exceptions.StorageError):
+ sc.strict_list = [1]
+
+ assert_strict(strict_class)
+ strict_class.strict_list = ['item']
+ assert strict_class.strict_list == ['item']
+
+ assert_strict(strict_class)
+ with pytest.raises(exceptions.StorageError):
+ strict_class.strict_list[0] = 1
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/dd5bfa93/tests/modeling/test_model_storage.py
----------------------------------------------------------------------
diff --git a/tests/modeling/test_model_storage.py b/tests/modeling/test_model_storage.py
new file mode 100644
index 0000000..bb778d4
--- /dev/null
+++ b/tests/modeling/test_model_storage.py
@@ -0,0 +1,102 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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 pytest
+
+from aria.storage import (
+ ModelStorage,
+ exceptions,
+ sql_mapi
+)
+from aria import (application_model_storage, modeling)
+from ..storage import (release_sqlite_storage, init_inmemory_model_storage)
+
+from . import MockModel
+
+
+@pytest.fixture
+def storage():
+ base_storage = ModelStorage(sql_mapi.SQLAlchemyModelAPI,
+ initiator=init_inmemory_model_storage)
+ base_storage.register(MockModel)
+ yield base_storage
+ release_sqlite_storage(base_storage)
+
+
+@pytest.fixture(scope='module', autouse=True)
+def module_cleanup():
+ modeling.models.aria_declarative_base.metadata.remove(MockModel.__table__) #pylint: disable=no-member
+
+
+def test_storage_base(storage):
+ with pytest.raises(AttributeError):
+ storage.non_existent_attribute()
+
+
+def test_model_storage(storage):
+ mock_model = MockModel(value=0, name='model_name')
+ storage.mock_model.put(mock_model)
+
+ assert storage.mock_model.get_by_name('model_name') == mock_model
+
+ assert [mm_from_storage for mm_from_storage in storage.mock_model.iter()] == [mock_model]
+ assert [mm_from_storage for mm_from_storage in storage.mock_model] == [mock_model]
+
+ storage.mock_model.delete(mock_model)
+ with pytest.raises(exceptions.StorageError):
+ storage.mock_model.get(mock_model.id)
+
+
+def test_application_storage_factory():
+ storage = application_model_storage(sql_mapi.SQLAlchemyModelAPI,
+ initiator=init_inmemory_model_storage)
+
+ assert storage.service_template
+ assert storage.node_template
+ assert storage.group_template
+ assert storage.policy_template
+ assert storage.substitution_template
+ assert storage.substitution_template_mapping
+ assert storage.requirement_template
+ assert storage.relationship_template
+ assert storage.capability_template
+ assert storage.interface_template
+ assert storage.operation_template
+ assert storage.artifact_template
+
+ assert storage.service
+ assert storage.node
+ assert storage.group
+ assert storage.policy
+ assert storage.substitution
+ assert storage.substitution_mapping
+ assert storage.relationship
+ assert storage.capability
+ assert storage.interface
+ assert storage.operation
+ assert storage.artifact
+
+ assert storage.execution
+ assert storage.service_update
+ assert storage.service_update_step
+ assert storage.service_modification
+ assert storage.plugin
+ assert storage.task
+
+ assert storage.parameter
+ assert storage.type
+ assert storage.metadata
+
+ release_sqlite_storage(storage)