Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-132-Models-cascading-deletion-raises-constraint-errors 
6fb690006 -> d35a11959 (forced update)


ARIA-132-Models-cascading-deletion-raises-constraint-errors


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/d35a1195
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/d35a1195
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/d35a1195

Branch: refs/heads/ARIA-132-Models-cascading-deletion-raises-constraint-errors
Commit: d35a11959662c4759678377d4e197cb12743510a
Parents: 07cbfcd
Author: max-orlov <[email protected]>
Authored: Sun Mar 26 14:13:47 2017 +0300
Committer: max-orlov <[email protected]>
Committed: Tue Mar 28 13:02:01 2017 +0300

----------------------------------------------------------------------
 aria/.pylintrc                                  |   2 +-
 aria/modeling/orchestration.py                  |  16 +
 aria/modeling/relationship.py                   | 220 +++--
 aria/modeling/service_changes.py                |  86 +-
 aria/modeling/service_common.py                 |   4 +
 aria/modeling/service_instance.py               | 795 ++++++++++++------
 aria/modeling/service_template.py               | 803 +++++++++++++------
 tests/orchestrator/context/test_operation.py    |   4 +-
 .../node-cellar/node-cellar.yaml                |   1 -
 9 files changed, 1287 insertions(+), 644 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35a1195/aria/.pylintrc
----------------------------------------------------------------------
diff --git a/aria/.pylintrc b/aria/.pylintrc
index 589402f..7222605 100644
--- a/aria/.pylintrc
+++ b/aria/.pylintrc
@@ -375,7 +375,7 @@ max-attributes=20
 min-public-methods=0
 
 # Maximum number of public methods for a class (see R0904).
-max-public-methods=20
+max-public-methods=50
 
 # Maximum number of boolean expressions in a if statement
 max-bool-expr=5

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35a1195/aria/modeling/orchestration.py
----------------------------------------------------------------------
diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py
index 2d58671..a13ae87 100644
--- a/aria/modeling/orchestration.py
+++ b/aria/modeling/orchestration.py
@@ -103,9 +103,17 @@ class ExecutionBase(ModelMixin):
     workflow_name = Column(Text)
 
     @declared_attr
+    def logs(cls):
+        return relationship.one_to_many(cls, 'log')
+
+    @declared_attr
     def service(cls):
         return relationship.many_to_one(cls, 'service')
 
+    @declared_attr
+    def tasks(cls):
+        return relationship.one_to_many(cls, 'task')
+
     # region foreign keys
 
     @declared_attr
@@ -185,6 +193,10 @@ class PluginBase(ModelMixin):
 
     __tablename__ = 'plugin'
 
+    @declared_attr
+    def tasks(cls):
+        return relationship.one_to_many(cls, 'task')
+
     archive_name = Column(Text, nullable=False, index=True)
     distribution = Column(Text)
     distribution_release = Column(Text)
@@ -239,6 +251,10 @@ class TaskBase(ModelMixin):
     INFINITE_RETRIES = -1
 
     @declared_attr
+    def logs(cls):
+        return relationship.one_to_many(cls, 'log')
+
+    @declared_attr
     def node(cls):
         return relationship.many_to_one(cls, 'node')
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35a1195/aria/modeling/relationship.py
----------------------------------------------------------------------
diff --git a/aria/modeling/relationship.py b/aria/modeling/relationship.py
index 70691b3..1121dc0 100644
--- a/aria/modeling/relationship.py
+++ b/aria/modeling/relationship.py
@@ -27,8 +27,7 @@ from sqlalchemy import (
 from ..utils import formatting
 
 
-def foreign_key(other_table,
-                nullable=False):
+def foreign_key(other_table, nullable=False):
     """
     Declare a foreign key property, which will also create a foreign key 
column in the table with
     the name of the property. By convention the property name should end in 
"_fk".
@@ -54,9 +53,7 @@ def foreign_key(other_table,
                   nullable=nullable)
 
 
-def one_to_one_self(model_class,
-                    fk,
-                    relationship_kwargs=None):
+def one_to_one_self(model_class, fk):
     """
     Declare a one-to-one relationship property. The property value would be an 
instance of the same
     model.
@@ -69,12 +66,8 @@ def one_to_one_self(model_class,
     :type model_class: type
     :param fk: Foreign key name
     :type fk: basestring
-    :param relationship_kwargs: Extra kwargs for SQLAlchemy ``relationship``
-    :type relationship_kwargs: {}
     """
 
-    relationship_kwargs = relationship_kwargs or {}
-
     remote_side = '{model_class}.{remote_column}'.format(
         model_class=model_class.__name__,
         remote_column=model_class.id_column_name()
@@ -85,20 +78,18 @@ def one_to_one_self(model_class,
         model_class=model_class.__name__,
         column=fk
     )
-
-    return relationship(
-        _get_class_for_table(model_class, model_class.__tablename__).__name__,
-        primaryjoin=primaryjoin,
-        remote_side=remote_side,
-        post_update=True,
-        **relationship_kwargs
+    return _relationship(
+        model_class,
+        model_class.__tablename__,
+        relationship_kwargs={
+            'primaryjoin': primaryjoin,
+            'remote_side': remote_side,
+            'post_update': True
+        }
     )
 
 
-def one_to_many_self(model_class,
-                     fk,
-                     dict_key=None,
-                     relationship_kwargs=None):
+def one_to_many_self(model_class, fk, dict_key=None):
     """
     Declare a one-to-many relationship property. The property value would be a 
list or dict of
     instances of the same model.
@@ -114,28 +105,24 @@ def one_to_many_self(model_class,
     :param dict_key: If set the value will be a dict with this key as the dict 
key; otherwise will
                      be a list
     :type dict_key: basestring
-    :param relationship_kwargs: Extra kwargs for SQLAlchemy ``relationship``
-    :type relationship_kwargs: {}
     """
-
-    relationship_kwargs = relationship_kwargs or {}
-
-    relationship_kwargs.setdefault('remote_side', 
'{model_class}.{remote_column}'.format(
-        model_class=model_class.__name__,
-        remote_column=fk
-    ))
-
-    return _relationship(model_class, model_class.__tablename__, None, 
relationship_kwargs,
-                         other_property=False, dict_key=dict_key)
+    return _relationship(
+        model_class,
+        model_class.__tablename__,
+        relationship_kwargs={
+            'remote_side': '{model_class}.{remote_column}'.format(
+                model_class=model_class.__name__, remote_column=fk)
+        },
+        back_populates=False,
+        dict_key=dict_key
+    )
 
 
 def one_to_one(model_class,
                other_table,
                fk=None,
                other_fk=None,
-               other_property=None,
-               relationship_kwargs=None,
-               backref_kwargs=None):
+               back_populates=None):
     """
     Declare a one-to-one relationship property. The property value would be an 
instance of the other
     table's model.
@@ -154,26 +141,25 @@ def one_to_one(model_class,
     :type fk: basestring
     :param other_fk: Foreign key name at the other table (no need specify if 
there's no ambiguity)
     :type other_fk: basestring
-    :param relationship_kwargs: Extra kwargs for SQLAlchemy ``relationship``
-    :type relationship_kwargs: {}
-    :param backref_kwargs: Extra kwargs for SQLAlchemy ``backref``
-    :type backref_kwargs: {}
+    :param back_populates: Override name of matching many-to-many property at 
other table; set to
+                       false to disable
+    :type back_populates: basestring|bool
     """
+    if back_populates is None:
+        back_populates = model_class.__tablename__
 
-    backref_kwargs = backref_kwargs or {}
-    backref_kwargs.setdefault('uselist', False)
-
-    return _relationship(model_class, other_table, backref_kwargs, 
relationship_kwargs,
-                         other_property, fk=fk, other_fk=other_fk)
+    return _relationship(model_class,
+                         other_table,
+                         fk=fk,
+                         back_populates=back_populates,
+                         other_fk=other_fk)
 
 
 def one_to_many(model_class,
                 child_table,
                 child_fk=None,
                 dict_key=None,
-                child_property=None,
-                relationship_kwargs=None,
-                backref_kwargs=None):
+                back_populates=None):
     """
     Declare a one-to-many relationship property. The property value would be a 
list or dict of
     instances of the child table's model.
@@ -194,29 +180,25 @@ def one_to_many(model_class,
     :param dict_key: If set the value will be a dict with this key as the dict 
key; otherwise will
                      be a list
     :type dict_key: basestring
-    :param child_property: Override name of matching many-to-one property at 
child table; set to
+    :param back_populates: Override name of matching many-to-one property at 
child table; set to
                            false to disable
-    :type child_property: basestring|bool
-    :param relationship_kwargs: Extra kwargs for SQLAlchemy ``relationship``
-    :type relationship_kwargs: {}
-    :param backref_kwargs: Extra kwargs for SQLAlchemy ``backref``
-    :type backref_kwargs: {}
+    :type back_populates: basestring|bool
     """
-
-    backref_kwargs = backref_kwargs or {}
-    backref_kwargs.setdefault('uselist', False)
-
-    return _relationship(model_class, child_table, backref_kwargs, 
relationship_kwargs,
-                         child_property, other_fk=child_fk, dict_key=dict_key)
+    if back_populates is None:
+        back_populates = model_class.__tablename__
+    return _relationship(
+        model_class,
+        child_table,
+        back_populates=back_populates,
+        other_fk=child_fk,
+        dict_key=dict_key)
 
 
 def many_to_one(model_class,
                 parent_table,
                 fk=None,
                 parent_fk=None,
-                parent_property=None,
-                relationship_kwargs=None,
-                backref_kwargs=None):
+                back_populates=None):
     """
     Declare a many-to-one relationship property. The property value would be 
an instance of the
     parent table's model.
@@ -236,34 +218,25 @@ def many_to_one(model_class,
     :type parent_table: basestring
     :param fk: Foreign key name at our table (no need specify if there's no 
ambiguity)
     :type fk: basestring
-    :param parent_property: Override name of matching one-to-many property at 
parent table; set to
+    :param back_populates: Override name of matching one-to-many property at 
parent table; set to
                             false to disable
-    :type parent_property: basestring|bool
-    :param relationship_kwargs: Extra kwargs for SQLAlchemy ``relationship``
-    :type relationship_kwargs: {}
-    :param backref_kwargs: Extra kwargs for SQLAlchemy ``backref``
-    :type backref_kwargs: {}
+    :type back_populates: basestring|bool
     """
+    if back_populates is None:
+        back_populates = formatting.pluralize(model_class.__tablename__)
 
-    if parent_property is None:
-        parent_property = formatting.pluralize(model_class.__tablename__)
-
-    backref_kwargs = backref_kwargs or {}
-    backref_kwargs.setdefault('uselist', True)
-    backref_kwargs.setdefault('lazy', 'dynamic')
-    backref_kwargs.setdefault('cascade', 'all') # delete children when parent 
is deleted
-
-    return _relationship(model_class, parent_table, backref_kwargs, 
relationship_kwargs,
-                         parent_property, fk=fk, other_fk=parent_fk)
+    return _relationship(model_class,
+                         parent_table,
+                         back_populates=back_populates,
+                         fk=fk,
+                         other_fk=parent_fk)
 
 
 def many_to_many(model_class,
                  other_table,
                  prefix=None,
                  dict_key=None,
-                 other_property=None,
-                 relationship_kwargs=None,
-                 backref_kwargs=None):
+                 other_property=None):
     """
     Declare a many-to-many relationship property. The property value would be 
a list or dict of
     instances of the other table's model.
@@ -280,8 +253,8 @@ def many_to_many(model_class,
 
     :param model_class: The class in which this relationship will be declared
     :type model_class: type
-    :param parent_table: Parent table name
-    :type parent_table: basestring
+    :param other_table: Parent table name
+    :type other_table: basestring
     :param prefix: Optional prefix for extra table name as well as for 
``other_property``
     :type prefix: basestring
     :param dict_key: If set the value will be a dict with this key as the dict 
key; otherwise will
@@ -290,10 +263,6 @@ def many_to_many(model_class,
     :param other_property: Override name of matching many-to-many property at 
other table; set to
                            false to disable
     :type other_property: basestring|bool
-    :param relationship_kwargs: Extra kwargs for SQLAlchemy ``relationship``
-    :type relationship_kwargs: {}
-    :param backref_kwargs: Extra kwargs for SQLAlchemy ``backref``
-    :type backref_kwargs: {}
     """
 
     this_table = model_class.__tablename__
@@ -303,69 +272,68 @@ def many_to_many(model_class,
     other_column_name = '{0}_id'.format(other_table)
     other_foreign_key = '{0}.id'.format(other_table)
 
-    secondary_table = '{0}_{1}'.format(this_table, other_table)
+    secondary_table_name = '{0}_{1}'.format(this_table, other_table)
 
     if prefix is not None:
-        secondary_table = '{0}_{1}'.format(prefix, secondary_table)
+        secondary_table_name = '{0}_{1}'.format(prefix, secondary_table_name)
         if other_property is None:
             other_property = '{0}_{1}'.format(prefix, 
formatting.pluralize(this_table))
 
-    backref_kwargs = backref_kwargs or {}
-    backref_kwargs.setdefault('uselist', True)
-
-    relationship_kwargs = relationship_kwargs or {}
-    relationship_kwargs.setdefault('secondary', _get_secondary_table(
+    secondary_table = _get_secondary_table(
         model_class.metadata,
-        secondary_table,
+        secondary_table_name,
         this_column_name,
         other_column_name,
         this_foreign_key,
         other_foreign_key
-    ))
+    )
 
-    return _relationship(model_class, other_table, backref_kwargs, 
relationship_kwargs,
-                         other_property, dict_key=dict_key)
+    return _relationship(
+        model_class,
+        other_table,
+        relationship_kwargs={'secondary': secondary_table},
+        backref_kwargs={'name': other_property, 'uselist': True} if 
other_property else None,
+        dict_key=dict_key
+    )
 
 
-def _relationship(model_class, other_table, backref_kwargs, 
relationship_kwargs, other_property,
-                  fk=None, other_fk=None, dict_key=None):
+def _relationship(model_class,
+                  other_table_name,
+                  back_populates=None,
+                  backref_kwargs=None,
+                  relationship_kwargs=None,
+                  fk=None,
+                  other_fk=None,
+                  dict_key=None):
     relationship_kwargs = relationship_kwargs or {}
 
     if fk:
-        relationship_kwargs.setdefault('foreign_keys',
-                                       lambda: getattr(
-                                           _get_class_for_table(
-                                               model_class,
-                                               model_class.__tablename__),
-                                           fk))
+        relationship_kwargs.setdefault(
+            'foreign_keys',
+            lambda: getattr(_get_class_for_table(model_class, 
model_class.__tablename__), fk)
+        )
 
     elif other_fk:
-        relationship_kwargs.setdefault('foreign_keys',
-                                       lambda: getattr(
-                                           _get_class_for_table(
-                                               model_class,
-                                               other_table),
-                                           other_fk))
+        relationship_kwargs.setdefault(
+            'foreign_keys',
+            lambda: getattr(_get_class_for_table(model_class, 
other_table_name), other_fk)
+        )
 
     if dict_key:
         relationship_kwargs.setdefault('collection_class',
                                        attribute_mapped_collection(dict_key))
 
-    if other_property is False:
-        # No backref
-        return relationship(
-            lambda: _get_class_for_table(model_class, other_table),
-            **relationship_kwargs
-        )
+    if backref_kwargs:
+        assert back_populates is None
+        return relationship(lambda: _get_class_for_table(model_class, 
other_table_name),
+                            backref=backref(**backref_kwargs),
+                            **relationship_kwargs
+                           )
     else:
-        if other_property is None:
-            other_property = model_class.__tablename__
-        backref_kwargs = backref_kwargs or {}
-        return relationship(
-            lambda: _get_class_for_table(model_class, other_table),
-            backref=backref(other_property, **backref_kwargs),
-            **relationship_kwargs
-        )
+        if back_populates:
+            relationship_kwargs['back_populates'] = back_populates
+        return relationship(lambda: _get_class_for_table(model_class, 
other_table_name),
+                            **relationship_kwargs)
 
 
 def _get_class_for_table(model_class, tablename):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35a1195/aria/modeling/service_changes.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_changes.py b/aria/modeling/service_changes.py
index a33e6ae..6c13b0f 100644
--- a/aria/modeling/service_changes.py
+++ b/aria/modeling/service_changes.py
@@ -42,9 +42,6 @@ class ServiceUpdateBase(ModelMixin):
     """
     Deployment update model representation.
     """
-
-    steps = None
-
     __tablename__ = 'service_update'
 
     __private_fields__ = ['service_fk',
@@ -60,14 +57,6 @@ class ServiceUpdateBase(ModelMixin):
     modified_entity_ids = Column(Dict)
     state = Column(Text)
 
-    @declared_attr
-    def execution(cls):
-        return relationship.many_to_one(cls, 'execution')
-
-    @declared_attr
-    def service(cls):
-        return relationship.many_to_one(cls, 'service', 
parent_property='updates')
-
     # region foreign keys
 
     @declared_attr
@@ -94,6 +83,34 @@ class ServiceUpdateBase(ModelMixin):
 
     # endregion
 
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def steps(cls):
+        return relationship.one_to_many(cls, 'service_update_step')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def execution(cls):
+        return relationship.one_to_one(cls, 'execution', back_populates=False)
+
+    @declared_attr
+    def service(cls):
+        return relationship.many_to_one(cls, 'service', 
back_populates='updates')
+
+    # endregion
+
+    # region many_to_many relationships
+
+    # endregion
+
     def to_dict(self, suppress_error=False, **kwargs):
         dep_update_dict = super(ServiceUpdateBase, 
self).to_dict(suppress_error)     #pylint: disable=no-member
         # Taking care of the fact the DeploymentSteps are _BaseModels
@@ -133,10 +150,6 @@ class ServiceUpdateStepBase(ModelMixin):
     entity_id = Column(Text, nullable=False)
     entity_type = Column(Enum(*ENTITY_TYPES, name='entity_type'), 
nullable=False)
 
-    @declared_attr
-    def service_update(cls):
-        return relationship.many_to_one(cls, 'service_update', 
parent_property='steps')
-
     # region foreign keys
 
     @declared_attr
@@ -154,6 +167,26 @@ class ServiceUpdateStepBase(ModelMixin):
 
     # endregion
 
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def service_update(cls):
+        return relationship.many_to_one(cls, 'service_update', 
back_populates='steps')
+
+    # endregion
+
+    # region many_to_many relationships
+
+    # endregion
+
     def __hash__(self):
         return hash((getattr(self, self.id_column_name()), self.entity_id))
 
@@ -206,10 +239,6 @@ class ServiceModificationBase(ModelMixin):
     nodes = Column(Dict)
     status = Column(Enum(*STATES, name='service_modification_status'))
 
-    @declared_attr
-    def service(cls):
-        return relationship.many_to_one(cls, 'service', 
parent_property='modifications')
-
     # region foreign keys
 
     @declared_attr
@@ -226,3 +255,22 @@ class ServiceModificationBase(ModelMixin):
         return association_proxy('service', cls.name_column_name())
 
     # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    # endregion
+
+    # region many_to_one relationships
+    @declared_attr
+    def service(cls):
+        return relationship.many_to_one(cls, 'service', 
back_populates='modifications')
+
+    # endregion
+
+    # region many_to_many relationships
+
+    # endregion

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35a1195/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index d6b1f33..48c3170 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -275,6 +275,10 @@ class PluginSpecificationBase(TemplateModelMixin):
 
     # endregion
 
+    @declared_attr
+    def service_template(cls):
+        return relationship.many_to_one(cls, 'service_template')
+
     @property
     def as_raw(self):
         return collections.OrderedDict((

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35a1195/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py 
b/aria/modeling/service_instance.py
index 1e18db0..327affc 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -91,16 +91,53 @@ class ServiceBase(InstanceModelMixin): # pylint: 
disable=too-many-public-methods
                           'service_template_fk',
                           'service_template_name']
 
+    # region foreign keys
+
     @declared_attr
-    def service_template(cls):
-        return relationship.many_to_one(cls, 'service_template')
+    def substitution_fk(cls):
+        """Service one-to-one to Substitution"""
+        return relationship.foreign_key('substitution', nullable=True)
 
-    description = Column(Text)
+    @declared_attr
+    def service_template_fk(cls):
+        """For Service many-to-one to ServiceTemplate"""
+        return relationship.foreign_key('service_template', nullable=True)
+
+    # endregion
+
+    # region association proxies
 
     @declared_attr
-    def meta_data(cls):
-        # Warning! We cannot use the attr name "metadata" because it's used by 
SQLAlchemy!
-        return relationship.many_to_many(cls, 'metadata', dict_key='name')
+    def service_template_name(cls):
+        """Required for use by SQLAlchemy queries"""
+        return association_proxy('service_template', 'name')
+
+    # endregion
+
+    # region one_to_one relationships
+
+    @declared_attr
+    def substitution(cls):
+        return relationship.one_to_one(cls, 'substitution', 
back_populates=False)
+
+    # endregion
+
+    # region one_to_many relationships
+    @declared_attr
+    def updates(cls):
+        return relationship.one_to_many(cls, 'service_update')
+
+    @declared_attr
+    def modifications(cls):
+        return relationship.one_to_many(cls, 'service_modification')
+
+    @declared_attr
+    def executions(cls):
+        return relationship.one_to_many(cls, 'execution')
+
+    @declared_attr
+    def operations(cls):
+        return relationship.one_to_many(cls, 'operation')
 
     @declared_attr
     def nodes(cls):
@@ -115,8 +152,24 @@ class ServiceBase(InstanceModelMixin): # pylint: 
disable=too-many-public-methods
         return relationship.one_to_many(cls, 'policy', dict_key='name')
 
     @declared_attr
-    def substitution(cls):
-        return relationship.one_to_one(cls, 'substitution')
+    def workflows(cls):
+        return relationship.one_to_many(cls, 'operation', dict_key='name')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def service_template(cls):
+        return relationship.many_to_one(cls, 'service_template')
+
+    # endregion
+
+    # region many_to_many relationships
+    @declared_attr
+    def meta_data(cls):
+        # Warning! We cannot use the attr name "metadata" because it's used by 
SQLAlchemy!
+        return relationship.many_to_many(cls, 'metadata', dict_key='name')
 
     @declared_attr
     def inputs(cls):
@@ -127,13 +180,13 @@ class ServiceBase(InstanceModelMixin): # pylint: 
disable=too-many-public-methods
         return relationship.many_to_many(cls, 'parameter', prefix='outputs', 
dict_key='name')
 
     @declared_attr
-    def workflows(cls):
-        return relationship.one_to_many(cls, 'operation', dict_key='name')
-
-    @declared_attr
     def plugin_specifications(cls):
         return relationship.many_to_many(cls, 'plugin_specification', 
dict_key='name')
 
+    # endregion
+
+    description = Column(Text)
+
     created_at = Column(DateTime, nullable=False, index=True)
     updated_at = Column(DateTime)
 
@@ -144,29 +197,6 @@ class ServiceBase(InstanceModelMixin): # pylint: 
disable=too-many-public-methods
 
     # endregion
 
-    # region foreign keys
-
-    @declared_attr
-    def substitution_fk(cls):
-        """Service one-to-one to Substitution"""
-        return relationship.foreign_key('substitution', nullable=True)
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For Service many-to-one to ServiceTemplate"""
-        return relationship.foreign_key('service_template', nullable=True)
-
-    # endregion
-
-    # region association proxies
-
-    @declared_attr
-    def service_template_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service_template', 'name')
-
-    # endregion
-
     def satisfy_requirements(self):
         satisfied = True
         for node in self.nodes.itervalues():
@@ -391,19 +421,52 @@ class NodeBase(InstanceModelMixin): # pylint: 
disable=too-many-public-methods
         except KeyError:
             return None
 
+    # region foreign_keys
+
     @declared_attr
-    def node_template(cls):
-        return relationship.many_to_one(cls, 'node_template')
+    def type_fk(cls):
+        """For Node many-to-one to Type"""
+        return relationship.foreign_key('type')
 
     @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
+    def host_fk(cls):
+        """For Node one-to-one to Node"""
+        return relationship.foreign_key('node', nullable=True)
 
-    description = Column(Text)
+    @declared_attr
+    def service_fk(cls):
+        """For Service one-to-many to Node"""
+        return relationship.foreign_key('service')
 
     @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+    def node_template_fk(cls):
+        """For Node many-to-one to NodeTemplate"""
+        return relationship.foreign_key('node_template')
+
+    # endregion
+
+    # region association proxies
+
+    @declared_attr
+    def service_name(cls):
+        """Required for use by SQLAlchemy queries"""
+        return association_proxy('service', 'name')
+
+    # endregion
+
+    # region one_to_one relationships
+
+    @declared_attr
+    def host(cls):
+        return relationship.one_to_one_self(cls, 'host_fk')
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def tasks(cls):
+        return relationship.one_to_many(cls, 'task')
 
     @declared_attr
     def interfaces(cls):
@@ -419,20 +482,40 @@ class NodeBase(InstanceModelMixin): # pylint: 
disable=too-many-public-methods
 
     @declared_attr
     def outbound_relationships(cls):
-        return relationship.one_to_many(cls, 'relationship', 
child_fk='source_node_fk',
-                                        child_property='source_node')
+        return relationship.one_to_many(
+            cls, 'relationship', child_fk='source_node_fk', 
back_populates='source_node')
 
     @declared_attr
     def inbound_relationships(cls):
-        return relationship.one_to_many(cls, 'relationship', 
child_fk='target_node_fk',
-                                        child_property='target_node')
+        return relationship.one_to_many(
+            cls, 'relationship', child_fk='target_node_fk', 
back_populates='target_node')
+
+    # endregion
+
+    # region many_to_one relationships
 
     @declared_attr
-    def host(cls):
-        return relationship.one_to_one_self(cls, 'host_fk')
+    def service(cls):
+        return relationship.many_to_one(cls, 'service')
 
-    # region orchestration
+    @declared_attr
+    def node_template(cls):
+        return relationship.many_to_one(cls, 'node_template')
+
+    @declared_attr
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
+    @declared_attr
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+
+    # endregion
 
+    description = Column(Text)
     runtime_properties = Column(modeling_types.Dict)
     scaling_groups = Column(modeling_types.List)
     state = Column(Enum(*STATES, name='node_state'), nullable=False, 
default=INITIAL)
@@ -454,41 +537,6 @@ class NodeBase(InstanceModelMixin): # pylint: 
disable=too-many-public-methods
             return host_ip_property.value
         return None
 
-    # endregion
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For Node many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def host_fk(cls):
-        """For Node one-to-one to Node"""
-        return relationship.foreign_key('node', nullable=True)
-
-    @declared_attr
-    def service_fk(cls):
-        """For Service one-to-many to Node"""
-        return relationship.foreign_key('service')
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For Node many-to-one to NodeTemplate"""
-        return relationship.foreign_key('node_template', nullable=True)
-
-    # endregion
-
-    # region association proxies
-
-    @declared_attr
-    def service_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service', 'name')
-
-    # endregion
-
     def satisfy_requirements(self):
         node_template = self.node_template
         satisfied = True
@@ -513,7 +561,7 @@ class NodeBase(InstanceModelMixin): # pylint: 
disable=too-many-public-methods
         from . import models
         context = ConsumptionContext.get_thread_local()
         # Find target nodes
-        target_nodes = target_node_template.nodes.all()
+        target_nodes = target_node_template.nodes
         if target_nodes:
             target_node = None
             target_capability = None
@@ -621,6 +669,7 @@ class NodeBase(InstanceModelMixin): # pylint: 
disable=too-many-public-methods
             utils.dump_dict_values(self.capabilities, 'Capabilities')
             utils.dump_list_values(self.outbound_relationships, 
'Relationships')
 
+
 class GroupBase(InstanceModelMixin):
     """
     Usually an instance of a :class:`GroupTemplate`.
@@ -648,51 +697,73 @@ class GroupBase(InstanceModelMixin):
 
     __tablename__ = 'group'
 
-    __private_fields__ = ['type_fk',
-                          'service_fk',
-                          'group_template_fk']
+    __private_fields__ = ['type_fk', 'service_fk', 'group_template_fk']
 
-    @declared_attr
-    def group_template(cls):
-        return relationship.many_to_one(cls, 'group_template')
+    # region foreign_keys
 
     @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
-
-    description = Column(Text)
+    def type_fk(cls):
+        """For Group many-to-one to Type"""
+        return relationship.foreign_key('type')
 
     @declared_attr
-    def nodes(cls):
-        return relationship.many_to_many(cls, 'node')
+    def service_fk(cls):
+        """For Service one-to-many to Group"""
+        return relationship.foreign_key('service')
 
     @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+    def group_template_fk(cls):
+        """For Group many-to-one to GroupTemplate"""
+        return relationship.foreign_key('group_template', nullable=True)
+
+    # endregion
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
 
     @declared_attr
     def interfaces(cls):
         return relationship.one_to_many(cls, 'interface', dict_key='name')
 
-    # region foreign_keys
+    # endregion
+
+    # region many_to_one relationships
 
     @declared_attr
-    def type_fk(cls):
-        """For Group many-to-one to Type"""
-        return relationship.foreign_key('type')
+    def service(cls):
+        return relationship.many_to_one(cls, 'service')
 
     @declared_attr
-    def service_fk(cls):
-        """For Service one-to-many to Group"""
-        return relationship.foreign_key('service')
+    def group_template(cls):
+        return relationship.many_to_one(cls, 'group_template')
 
     @declared_attr
-    def group_template_fk(cls):
-        """For Group many-to-one to GroupTemplate"""
-        return relationship.foreign_key('group_template', nullable=True)
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def nodes(cls):
+        return relationship.many_to_many(cls, 'node')
+
+    @declared_attr
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
 
     # endregion
 
+    description = Column(Text)
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -747,51 +818,73 @@ class PolicyBase(InstanceModelMixin):
 
     __tablename__ = 'policy'
 
-    __private_fields__ = ['type_fk',
-                          'service_fk',
-                          'policy_template_fk']
+    __private_fields__ = ['type_fk', 'service_fk', 'policy_template_fk']
 
-    @declared_attr
-    def policy_template(cls):
-        return relationship.many_to_one(cls, 'policy_template')
+    # region foreign_keys
 
     @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
-
-    description = Column(Text)
+    def type_fk(cls):
+        """For Policy many-to-one to Type"""
+        return relationship.foreign_key('type')
 
     @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+    def service_fk(cls):
+        """For Service one-to-many to Policy"""
+        return relationship.foreign_key('service')
 
     @declared_attr
-    def nodes(cls):
-        return relationship.many_to_many(cls, 'node')
+    def policy_template_fk(cls):
+        """For Policy many-to-one to PolicyTemplate"""
+        return relationship.foreign_key('policy_template', nullable=True)
+
+    # endregion
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    # endregion
+
+    # region many_to_one relationships
 
     @declared_attr
-    def groups(cls):
-        return relationship.many_to_many(cls, 'group')
+    def service(cls):
+        return relationship.many_to_one(cls, 'service')
 
-    # region foreign_keys
+    @declared_attr
+    def policy_template(cls):
+        return relationship.many_to_one(cls, 'policy_template')
 
     @declared_attr
-    def type_fk(cls):
-        """For Policy many-to-one to Type"""
-        return relationship.foreign_key('type')
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
 
     @declared_attr
-    def service_fk(cls):
-        """For Service one-to-many to Policy"""
-        return relationship.foreign_key('service')
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
 
     @declared_attr
-    def policy_template_fk(cls):
-        """For Policy many-to-one to PolicyTemplate"""
-        return relationship.foreign_key('policy_template', nullable=True)
+    def nodes(cls):
+        return relationship.many_to_many(cls, 'node')
+
+    @declared_attr
+    def groups(cls):
+        return relationship.many_to_many(cls, 'group')
 
     # endregion
 
+    description = Column(Text)
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -845,29 +938,53 @@ class SubstitutionBase(InstanceModelMixin):
     __private_fields__ = ['node_type_fk',
                           'substitution_template_fk']
 
+    # region foreign_keys
+
     @declared_attr
-    def substitution_template(cls):
-        return relationship.many_to_one(cls, 'substitution_template')
+    def node_type_fk(cls):
+        """For Substitution many-to-one to Type"""
+        return relationship.foreign_key('type')
 
     @declared_attr
-    def node_type(cls):
-        return relationship.many_to_one(cls, 'type')
+    def substitution_template_fk(cls):
+        """For Substitution many-to-one to SubstitutionTemplate"""
+        return relationship.foreign_key('substitution_template', nullable=True)
+
+    # endregion
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
 
     @declared_attr
     def mappings(cls):
         return relationship.one_to_many(cls, 'substitution_mapping', 
dict_key='name')
 
-    # region foreign_keys
+    # endregion
+
+    # region many_to_one relationships
 
     @declared_attr
-    def node_type_fk(cls):
-        """For Substitution many-to-one to Type"""
-        return relationship.foreign_key('type')
+    def service(cls):
+        return relationship.one_to_one(cls, 'service', back_populates=False)
 
     @declared_attr
-    def substitution_template_fk(cls):
-        """For Substitution many-to-one to SubstitutionTemplate"""
-        return relationship.foreign_key('substitution_template', nullable=True)
+    def substitution_template(cls):
+        return relationship.many_to_one(cls, 'substitution_template')
+
+    @declared_attr
+    def node_type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
 
     # endregion
 
@@ -919,18 +1036,6 @@ class SubstitutionMappingBase(InstanceModelMixin):
                           'capability_fk',
                           'requirement_template_fk']
 
-    @declared_attr
-    def node(cls):
-        return relationship.one_to_one(cls, 'node')
-
-    @declared_attr
-    def capability(cls):
-        return relationship.one_to_one(cls, 'capability')
-
-    @declared_attr
-    def requirement_template(cls):
-        return relationship.one_to_one(cls, 'requirement_template')
-
     # region foreign keys
 
     @declared_attr
@@ -955,6 +1060,42 @@ class SubstitutionMappingBase(InstanceModelMixin):
 
     # endregion
 
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    @declared_attr
+    def substitution(cls):
+        return relationship.many_to_one(cls, 'substitution', 
back_populates='mappings')
+
+    @declared_attr
+    def node(cls):
+        return relationship.one_to_one(cls, 'node', back_populates=False)
+
+    @declared_attr
+    def capability(cls):
+        return relationship.one_to_one(cls, 'capability', back_populates=False)
+
+    @declared_attr
+    def requirement_template(cls):
+        return relationship.one_to_one(cls, 'requirement_template', 
back_populates=False)
+
+    # endregion
+
+    # region one_to_many relationships
+
+    # endregion
+
+    # region many_to_one relationships
+
+    # endregion
+
+    # region many_to_many relationships
+
+    # endregion
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1027,37 +1168,6 @@ class RelationshipBase(InstanceModelMixin):
                           'source_node_name',
                           'target_node_name']
 
-    @declared_attr
-    def relationship_template(cls):
-        return relationship.many_to_one(cls, 'relationship_template')
-
-    @declared_attr
-    def requirement_template(cls):
-        return relationship.many_to_one(cls, 'requirement_template')
-
-    @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
-
-    @declared_attr
-    def target_capability(cls):
-        return relationship.one_to_one(cls, 'capability')
-
-    @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
-
-    @declared_attr
-    def interfaces(cls):
-        return relationship.one_to_many(cls, 'interface', dict_key='name')
-
-    # region orchestration
-
-    source_position = Column(Integer) # ???
-    target_position = Column(Integer) # ???
-
-    # endregion
-
     # region foreign keys
 
     @declared_attr
@@ -1106,6 +1216,63 @@ class RelationshipBase(InstanceModelMixin):
 
     # endregion
 
+    # region one_to_one relationships
+
+    @declared_attr
+    def target_capability(cls):
+        return relationship.one_to_one(cls, 'capability', back_populates=False)
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def tasks(cls):
+        return relationship.one_to_many(cls, 'task')
+
+    @declared_attr
+    def interfaces(cls):
+        return relationship.one_to_many(cls, 'interface', dict_key='name')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def source_node(cls):
+        return relationship.many_to_one(
+            cls, 'node', fk='source_node_fk', 
back_populates='outbound_relationships')
+
+    @declared_attr
+    def target_node(cls):
+        return relationship.many_to_one(
+            cls, 'node', fk='target_node_fk', 
back_populates='inbound_relationships')
+
+    @declared_attr
+    def relationship_template(cls):
+        return relationship.many_to_one(cls, 'relationship_template')
+
+    @declared_attr
+    def requirement_template(cls):
+        return relationship.many_to_one(cls, 'requirement_template')
+
+    @declared_attr
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+
+    # endregion
+
+    source_position = Column(Integer) # ???
+    target_position = Column(Integer) # ???
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1181,22 +1348,6 @@ class CapabilityBase(InstanceModelMixin):
                           'node_fk',
                           'capability_template_fk']
 
-    @declared_attr
-    def capability_template(cls):
-        return relationship.many_to_one(cls, 'capability_template')
-
-    @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
-
-    min_occurrences = Column(Integer, default=None)
-    max_occurrences = Column(Integer, default=None)
-    occurrences = Column(Integer, default=0)
-
-    @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
-
     # region foreign_keys
 
     @declared_attr
@@ -1216,6 +1367,46 @@ class CapabilityBase(InstanceModelMixin):
 
     # endregion
 
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def node(cls):
+        return relationship.many_to_one(cls, 'node')
+
+    @declared_attr
+    def capability_template(cls):
+        return relationship.many_to_one(cls, 'capability_template')
+
+    @declared_attr
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+
+    # endregion
+
+    min_occurrences = Column(Integer, default=None)
+    max_occurrences = Column(Integer, default=None)
+    occurrences = Column(Integer, default=0)
+
     @property
     def has_enough_relationships(self):
         if self.min_occurrences is not None:
@@ -1291,24 +1482,6 @@ class InterfaceBase(InstanceModelMixin):
                           'relationship_fk',
                           'interface_template_fk']
 
-    @declared_attr
-    def interface_template(cls):
-        return relationship.many_to_one(cls, 'interface_template')
-
-    @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
-
-    description = Column(Text)
-
-    @declared_attr
-    def inputs(cls):
-        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
-
-    @declared_attr
-    def operations(cls):
-        return relationship.one_to_many(cls, 'operation', dict_key='name')
-
     # region foreign_keys
 
     @declared_attr
@@ -1338,6 +1511,56 @@ class InterfaceBase(InstanceModelMixin):
 
     # endregion
 
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def operations(cls):
+        return relationship.one_to_many(cls, 'operation', dict_key='name')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def node(cls):
+        return relationship.many_to_one(cls, 'node')
+
+    @declared_attr
+    def relationship(cls):
+        return relationship.many_to_one(cls, 'relationship')
+
+    @declared_attr
+    def group(cls):
+        return relationship.many_to_one(cls, 'group')
+
+    @declared_attr
+    def interface_template(cls):
+        return relationship.many_to_one(cls, 'interface_template')
+
+    @declared_attr
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def inputs(cls):
+        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
+
+    # endregion
+
+    description = Column(Text)
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1406,27 +1629,6 @@ class OperationBase(InstanceModelMixin):
                           'plugin_fk',
                           'operation_template_fk']
 
-    @declared_attr
-    def operation_template(cls):
-        return relationship.many_to_one(cls, 'operation_template')
-
-    description = Column(Text)
-
-    @declared_attr
-    def plugin_specification(cls):
-        return relationship.one_to_one(cls, 'plugin_specification')
-
-    implementation = Column(Text)
-    dependencies = Column(modeling_types.StrictList(item_cls=basestring))
-
-    @declared_attr
-    def inputs(cls):
-        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
-
-    executor = Column(Text)
-    max_retries = Column(Integer)
-    retry_interval = Column(Integer)
-
     # region foreign_keys
 
     @declared_attr
@@ -1451,6 +1653,55 @@ class OperationBase(InstanceModelMixin):
 
     # endregion
 
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    @declared_attr
+    def plugin_specification(cls):
+        return relationship.one_to_one(cls, 'plugin_specification', 
back_populates=False)
+
+    # endregion
+
+    # region one_to_many relationships
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def service(cls):
+        return relationship.many_to_one(cls, 'service')
+
+    @declared_attr
+    def interface(cls):
+        return relationship.many_to_one(cls, 'interface')
+
+    @declared_attr
+    def operation_template(cls):
+        return relationship.many_to_one(cls, 'operation_template')
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def inputs(cls):
+        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
+
+    # endregion
+
+    description = Column(Text)
+    implementation = Column(Text)
+    dependencies = Column(modeling_types.StrictList(item_cls=basestring))
+    executor = Column(Text)
+    max_retries = Column(Integer)
+    retry_interval = Column(Integer)
+
+
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1528,24 +1779,6 @@ class ArtifactBase(InstanceModelMixin):
                           'node_fk',
                           'artifact_template_fk']
 
-    @declared_attr
-    def artifact_template(cls):
-        return relationship.many_to_one(cls, 'artifact_template')
-
-    @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
-
-    description = Column(Text)
-    source_path = Column(Text)
-    target_path = Column(Text)
-    repository_url = Column(Text)
-    repository_credential = Column(modeling_types.StrictDict(basestring, 
basestring))
-
-    @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
-
     # region foreign_keys
 
     @declared_attr
@@ -1565,6 +1798,44 @@ class ArtifactBase(InstanceModelMixin):
 
     # endregion
 
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    # endregion
+
+    # region many_to_one relationships
+    @declared_attr
+    def node(cls):
+        return relationship.many_to_one(cls, 'node')
+
+    @declared_attr
+    def artifact_template(cls):
+        return relationship.many_to_one(cls, 'artifact_template')
+
+    @declared_attr
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+    # endregion
+
+    # region many_to_many relationships
+    @declared_attr
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+    # endregion
+
+    description = Column(Text)
+    source_path = Column(Text)
+    target_path = Column(Text)
+    repository_url = Column(Text)
+    repository_credential = Column(modeling_types.StrictDict(basestring, 
basestring))
+
     @property
     def as_raw(self):
         return collections.OrderedDict((

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35a1195/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py 
b/aria/modeling/service_template.py
index 8b619bf..0cbbe24 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -108,124 +108,148 @@ class ServiceTemplateBase(TemplateModelMixin): # 
pylint: disable=too-many-public
 
     description = Column(Text)
     main_file_name = Column(Text)
+    created_at = Column(DateTime, nullable=False, index=True)
+    updated_at = Column(DateTime)
+
+    # region foreign keys
 
     @declared_attr
-    def meta_data(cls):
-        # Warning! We cannot use the attr name "metadata" because it's used by 
SQLAlchemy!
-        return relationship.many_to_many(cls, 'metadata', dict_key='name')
+    def substitution_template_fk(cls):
+        """For ServiceTemplate one-to-one to SubstitutionTemplate"""
+        return relationship.foreign_key('substitution_template', nullable=True)
 
     @declared_attr
-    def node_templates(cls):
-        return relationship.one_to_many(cls, 'node_template', dict_key='name')
+    def node_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
 
     @declared_attr
-    def group_templates(cls):
-        return relationship.one_to_many(cls, 'group_template', dict_key='name')
+    def group_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
 
     @declared_attr
-    def policy_templates(cls):
-        return relationship.one_to_many(cls, 'policy_template', 
dict_key='name')
+    def policy_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
 
     @declared_attr
-    def substitution_template(cls):
-        return relationship.one_to_one(cls, 'substitution_template')
+    def relationship_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
 
     @declared_attr
-    def inputs(cls):
-        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
+    def capability_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
 
     @declared_attr
-    def outputs(cls):
-        return relationship.many_to_many(cls, 'parameter', prefix='outputs', 
dict_key='name')
+    def interface_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
 
     @declared_attr
-    def workflow_templates(cls):
-        return relationship.one_to_many(cls, 'operation_template', 
dict_key='name')
+    def artifact_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    # endregion
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
 
     @declared_attr
-    def plugin_specifications(cls):
-        return relationship.one_to_many(cls, 'plugin_specification', 
dict_key='name')
+    def substitution_template(cls):
+        return relationship.one_to_one(cls, 'substitution_template', 
back_populates=False)
 
     @declared_attr
     def node_types(cls):
-        return relationship.one_to_one(cls, 'type', fk='node_type_fk', 
other_property=False)
+        return relationship.one_to_one(cls, 'type', fk='node_type_fk', 
back_populates=False)
 
     @declared_attr
     def group_types(cls):
-        return relationship.one_to_one(cls, 'type', fk='group_type_fk', 
other_property=False)
+        return relationship.one_to_one(cls, 'type', fk='group_type_fk', 
back_populates=False)
 
     @declared_attr
     def policy_types(cls):
-        return relationship.one_to_one(cls, 'type', fk='policy_type_fk', 
other_property=False)
+        return relationship.one_to_one(cls, 'type', fk='policy_type_fk', 
back_populates=False)
 
     @declared_attr
     def relationship_types(cls):
-        return relationship.one_to_one(cls, 'type', fk='relationship_type_fk',
-                                       other_property=False)
+        return relationship.one_to_one(cls, 'type', fk='relationship_type_fk', 
back_populates=False)
 
     @declared_attr
     def capability_types(cls):
-        return relationship.one_to_one(cls, 'type', fk='capability_type_fk', 
other_property=False)
+        return relationship.one_to_one(cls, 'type', fk='capability_type_fk', 
back_populates=False)
 
     @declared_attr
     def interface_types(cls):
-        return relationship.one_to_one(cls, 'type', fk='interface_type_fk', 
other_property=False)
+        return relationship.one_to_one(cls, 'type', fk='interface_type_fk', 
back_populates=False)
 
     @declared_attr
     def artifact_types(cls):
-        return relationship.one_to_one(cls, 'type', fk='artifact_type_fk', 
other_property=False)
+        return relationship.one_to_one(cls, 'type', fk='artifact_type_fk', 
back_populates=False)
 
-    # region orchestration
+    # endregion
 
-    created_at = Column(DateTime, nullable=False, index=True)
-    updated_at = Column(DateTime)
+    # region one_to_many relationships
 
-    # endregion
+    @declared_attr
+    def services(cls):
+        return relationship.one_to_many(cls, 'service')
 
-    # region foreign keys
+    @declared_attr
+    def operation_templates(cls):
+        return relationship.one_to_many(cls, 'operation_template')
 
     @declared_attr
-    def substitution_template_fk(cls):
-        """For ServiceTemplate one-to-one to SubstitutionTemplate"""
-        return relationship.foreign_key('substitution_template', nullable=True)
+    def node_templates(cls):
+        return relationship.one_to_many(cls, 'node_template', dict_key='name')
 
     @declared_attr
-    def node_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    def group_templates(cls):
+        return relationship.one_to_many(cls, 'group_template', dict_key='name')
 
     @declared_attr
-    def group_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    def policy_templates(cls):
+        return relationship.one_to_many(cls, 'policy_template', 
dict_key='name')
 
     @declared_attr
-    def policy_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    def workflow_templates(cls):
+        return relationship.one_to_many(cls, 'operation_template', 
dict_key='name')
 
     @declared_attr
-    def relationship_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    def plugin_specifications(cls):
+        return relationship.one_to_many(cls, 'plugin_specification', 
dict_key='name')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    # endregion
+
+    # region many_to_many relationships
 
     @declared_attr
-    def capability_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    def meta_data(cls):
+        # Warning! We cannot use the attr name "metadata" because it's used by 
SQLAlchemy!
+        return relationship.many_to_many(cls, 'metadata', dict_key='name')
 
     @declared_attr
-    def interface_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    def inputs(cls):
+        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
 
     @declared_attr
-    def artifact_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    def outputs(cls):
+        return relationship.many_to_many(cls, 'parameter', prefix='outputs', 
dict_key='name')
 
     # endregion
 
+
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -413,14 +437,54 @@ class NodeTemplateBase(TemplateModelMixin):
                           'service_template_fk',
                           'service_template_name']
 
+    # region foreign_keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For NodeTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def service_template_fk(cls):
+        """For ServiceTemplate one-to-many to NodeTemplate"""
+        return relationship.foreign_key('service_template')
+
+    # endregion
+
+    # region association proxies
+
+    @declared_attr
+    def service_template_name(cls):
+        """Required for use by SQLAlchemy queries"""
+        return association_proxy('service_template', 'name')
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def nodes(cls):
+        return relationship.one_to_many(cls, 'node')
+
+    # endregion
+
+    # region many_to_one relationships
+
     @declared_attr
     def type(cls):
-        return relationship.many_to_one(cls, 'type')
+        return relationship.many_to_one(cls, 'type', back_populates=False)
 
-    description = Column(Text)
-    default_instances = Column(Integer, default=1)
-    min_instances = Column(Integer, default=0)
-    max_instances = Column(Integer, default=None)
+    @declared_attr
+    def service_template(cls):
+        return relationship.many_to_one(cls, 'service_template')
+
+    # endregion
+
+    # region many_to_many relationships
 
     @declared_attr
     def properties(cls):
@@ -440,33 +504,15 @@ class NodeTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def requirement_templates(cls):
-        return relationship.one_to_many(cls, 'requirement_template', 
child_fk='node_template_fk',
-                                        child_property='node_template')
-
-    target_node_template_constraints = 
Column(modeling_types.StrictList(FunctionType))
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For NodeTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to NodeTemplate"""
-        return relationship.foreign_key('service_template')
+        return relationship.one_to_many(cls, 'requirement_template', 
child_fk='node_template_fk')
 
     # endregion
 
-    # region association proxies
-
-    @declared_attr
-    def service_template_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service_template', 'name')
-
-    # endregion
+    description = Column(Text)
+    default_instances = Column(Integer, default=1)
+    min_instances = Column(Integer, default=0)
+    max_instances = Column(Integer, default=None)
+    target_node_template_constraints = 
Column(modeling_types.StrictList(FunctionType))
 
     def is_target_node_valid(self, target_node_template):
         if self.target_node_template_constraints:
@@ -571,38 +617,66 @@ class GroupTemplateBase(TemplateModelMixin):
     __private_fields__ = ['type_fk',
                           'service_template_fk']
 
-    @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
+    # region foreign keys
 
-    description = Column(Text)
+    @declared_attr
+    def type_fk(cls):
+        """For GroupTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
 
     @declared_attr
-    def node_templates(cls):
-        return relationship.many_to_many(cls, 'node_template')
+    def service_template_fk(cls):
+        """For ServiceTemplate one-to-many to GroupTemplate"""
+        return relationship.foreign_key('service_template')
+
+    # endregion
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
 
     @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+    def groups(cls):
+        return relationship.one_to_many(cls, 'group')
 
     @declared_attr
     def interface_templates(cls):
         return relationship.one_to_many(cls, 'interface_template', 
dict_key='name')
 
-    # region foreign keys
+    # endregion
+
+    # region many_to_one relationships
 
     @declared_attr
-    def type_fk(cls):
-        """For GroupTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
+    def service_template(cls):
+        return relationship.many_to_one(cls, 'service_template')
 
     @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to GroupTemplate"""
-        return relationship.foreign_key('service_template')
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
 
     # endregion
 
+    # region many_to_many relationships
+
+    @declared_attr
+    def node_templates(cls):
+        return relationship.many_to_many(cls, 'node_template')
+
+    @declared_attr
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+
+    # endregion
+
+    description = Column(Text)
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -622,7 +696,7 @@ class GroupTemplateBase(TemplateModelMixin):
         utils.instantiate_dict(self, group.interfaces, 
self.interface_templates)
         if self.node_templates:
             for node_template in self.node_templates:
-                group.nodes += node_template.nodes.all()
+                group.nodes += node_template.nodes
         return group
 
     def validate(self):
@@ -673,14 +747,51 @@ class PolicyTemplateBase(TemplateModelMixin):
 
     __tablename__ = 'policy_template'
 
-    __private_fields__ = ['type_fk',
-                          'service_template_fk']
+    __private_fields__ = ['type_fk', 'service_template_fk']
+
+    # region foreign keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For PolicyTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def service_template_fk(cls):
+        """For ServiceTemplate one-to-many to PolicyTemplate"""
+        return relationship.foreign_key('service_template')
+
+    # endregion
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def policies(cls):
+        return relationship.one_to_many(cls, 'policy')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def service_template(cls):
+        return relationship.many_to_one(cls, 'service_template')
 
     @declared_attr
     def type(cls):
-        return relationship.many_to_one(cls, 'type')
+        return relationship.many_to_one(cls, 'type', back_populates=False)
 
-    description = Column(Text)
+    # endregion
+
+    # region many_to_many relationships
 
     @declared_attr
     def node_templates(cls):
@@ -694,20 +805,10 @@ class PolicyTemplateBase(TemplateModelMixin):
     def properties(cls):
         return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
 
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For PolicyTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to PolicyTemplate"""
-        return relationship.foreign_key('service_template')
-
     # endregion
 
+    description = Column(Text)
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -725,10 +826,10 @@ class PolicyTemplateBase(TemplateModelMixin):
         utils.instantiate_dict(self, policy.properties, self.properties)
         if self.node_templates:
             for node_template in self.node_templates:
-                policy.nodes += node_template.nodes.all()
+                policy.nodes += node_template.nodes
         if self.group_templates:
             for group_template in self.group_templates:
-                policy.groups += group_template.groups.all()
+                policy.groups += group_template.groups
         return policy
 
     def validate(self):
@@ -772,20 +873,44 @@ class SubstitutionTemplateBase(TemplateModelMixin):
 
     __private_fields__ = ['node_type_fk']
 
+    # region foreign keys
+
     @declared_attr
-    def node_type(cls):
-        return relationship.many_to_one(cls, 'type')
+    def node_type_fk(cls):
+        """For SubstitutionTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    # endregion
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def substitutions(cls):
+        return relationship.one_to_many(cls, 'substitution')
 
     @declared_attr
     def mappings(cls):
         return relationship.one_to_many(cls, 'substitution_template_mapping', 
dict_key='name')
 
-    # region foreign keys
+    # endregion
+
+    # region many_to_one relationships
 
     @declared_attr
-    def node_type_fk(cls):
-        """For SubstitutionTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
+    def node_type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
 
     # endregion
 
@@ -842,18 +967,6 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
                           'capability_template_fk',
                           'requirement_template_fk']
 
-    @declared_attr
-    def node_template(cls):
-        return relationship.one_to_one(cls, 'node_template')
-
-    @declared_attr
-    def capability_template(cls):
-        return relationship.one_to_one(cls, 'capability_template')
-
-    @declared_attr
-    def requirement_template(cls):
-        return relationship.one_to_one(cls, 'requirement_template')
-
     # region foreign keys
 
     @declared_attr
@@ -878,6 +991,48 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
 
     # endregion
 
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    @declared_attr
+    def node_template(cls):
+        return relationship.one_to_one(cls, 'node_template', 
back_populates=False)
+
+    @declared_attr
+    def capability_template(cls):
+        return relationship.one_to_one(cls, 'capability_template', 
back_populates=False)
+
+    @declared_attr
+    def requirement_template(cls):
+        return relationship.one_to_one(cls, 'requirement_template', 
back_populates=False)
+
+    # endregion
+
+    # region one_to_many relationships
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def substitution_template(cls):
+        return relationship.many_to_one(cls, 'substitution_template', 
back_populates='mappings')
+
+    # endregion
+
+    # region many_to_many relationships
+
+    # endregion
+
+
+
+
+
+
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -889,7 +1044,7 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
     def instantiate(self, container):
         from . import models
         context = ConsumptionContext.get_thread_local()
-        nodes = self.node_template.nodes.all()
+        nodes = self.node_template.nodes
         if len(nodes) == 0:
             context.validation.report(
                 'mapping "{0}" refers to node template "{1}" but there are no '
@@ -967,28 +1122,6 @@ class RequirementTemplateBase(TemplateModelMixin):
                           'node_template_fk',
                           'relationship_template_fk']
 
-    @declared_attr
-    def target_node_type(cls):
-        return relationship.many_to_one(cls, 'type', fk='target_node_type_fk',
-                                        parent_property=False)
-
-    @declared_attr
-    def target_node_template(cls):
-        return relationship.one_to_one(cls, 'node_template', 
fk='target_node_template_fk',
-                                       other_property=False)
-
-    @declared_attr
-    def target_capability_type(cls):
-        return relationship.one_to_one(cls, 'type', 
fk='target_capability_type_fk',
-                                       other_property=False)
-
-    target_capability_name = Column(Text)
-    target_node_template_constraints = 
Column(modeling_types.StrictList(FunctionType))
-
-    @declared_attr
-    def relationship_template(cls):
-        return relationship.one_to_one(cls, 'relationship_template')
-
     # region foreign keys
 
     @declared_attr
@@ -1007,17 +1140,67 @@ class RequirementTemplateBase(TemplateModelMixin):
         return relationship.foreign_key('type', nullable=True)
 
     @declared_attr
-    def node_template_fk(cls):
-        """For NodeTemplate one-to-many to RequirementTemplate"""
-        return relationship.foreign_key('node_template')
+    def node_template_fk(cls):
+        """For NodeTemplate one-to-many to RequirementTemplate"""
+        return relationship.foreign_key('node_template')
+
+    @declared_attr
+    def relationship_template_fk(cls):
+        """For RequirementTemplate one-to-one to RelationshipTemplate"""
+        return relationship.foreign_key('relationship_template', nullable=True)
+
+    # endregion
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    @declared_attr
+    def target_node_template(cls):
+        return relationship.one_to_one(
+            cls, 'node_template', fk='target_node_template_fk', 
back_populates=False)
+
+    @declared_attr
+    def target_capability_type(cls):
+        return relationship.one_to_one(cls, 'type', 
fk='target_capability_type_fk',
+                                       back_populates=False)
+
+    @declared_attr
+    def relationship_template(cls):
+        return relationship.one_to_one(cls, 'relationship_template', 
back_populates=False)
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def relationships(cls):
+        return relationship.one_to_many(cls, 'relationship')
+
+    @declared_attr
+    def target_node_type(cls):
+        return relationship.many_to_one(
+            cls, 'type', fk='target_node_type_fk', back_populates=False)
+
+    # endregion
+
+    # region many_to_one relationships
 
     @declared_attr
-    def relationship_template_fk(cls):
-        """For RequirementTemplate one-to-one to RelationshipTemplate"""
-        return relationship.foreign_key('relationship_template', nullable=True)
+    def node_template(cls):
+        return relationship.many_to_one(cls, 'node_template', 
fk='node_template_fk')
 
     # endregion
 
+    # region many_to_many relationships
+
+    # endregion
+
+    target_capability_name = Column(Text)
+    target_node_template_constraints = 
Column(modeling_types.StrictList(FunctionType))
+
     def find_target(self, source_node_template):
         context = ConsumptionContext.get_thread_local()
 
@@ -1148,29 +1331,53 @@ class RelationshipTemplateBase(TemplateModelMixin):
 
     __private_fields__ = ['type_fk']
 
+    # region foreign keys
+
     @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
+    def type_fk(cls):
+        """For RelationshipTemplate many-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
 
-    description = Column(Text)
+    # endregion
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
 
     @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+    def relationships(cls):
+        return relationship.one_to_many(cls, 'relationship')
 
     @declared_attr
     def interface_templates(cls):
         return relationship.one_to_many(cls, 'interface_template', 
dict_key='name')
 
-    # region foreign keys
+    # endregion
+
+    # region many_to_one relationships
 
     @declared_attr
-    def type_fk(cls):
-        """For RelationshipTemplate many-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
 
     # endregion
 
+    description = Column(Text)
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1245,22 +1452,6 @@ class CapabilityTemplateBase(TemplateModelMixin):
     __private_fields__ = ['type_fk',
                           'node_template_fk']
 
-    @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
-
-    description = Column(Text)
-    min_occurrences = Column(Integer, default=None)  # optional
-    max_occurrences = Column(Integer, default=None)  # optional
-
-    @declared_attr
-    def valid_source_node_types(cls):
-        return relationship.many_to_many(cls, 'type', prefix='valid_sources')
-
-    @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
-
     # region foreign keys
 
     @declared_attr
@@ -1275,6 +1466,51 @@ class CapabilityTemplateBase(TemplateModelMixin):
 
     # endregion
 
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def capabilities(cls):
+        return relationship.one_to_many(cls, 'capability')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def node_template(cls):
+        return relationship.many_to_one(cls, 'node_template')
+
+    @declared_attr
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def valid_source_node_types(cls):
+        return relationship.many_to_many(cls, 'type', prefix='valid_sources')
+
+    @declared_attr
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+
+    # endregion
+
+    description = Column(Text)
+    min_occurrences = Column(Integer, default=None)  # optional
+    max_occurrences = Column(Integer, default=None)  # optional
+
     def satisfies_requirement(self,
                               source_node_template,
                               requirement,
@@ -1378,19 +1614,6 @@ class InterfaceTemplateBase(TemplateModelMixin):
                           'group_template_fk',
                           'relationship_template_fk']
 
-    @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
-
-    description = Column(Text)
-
-    @declared_attr
-    def inputs(cls):
-        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
-
-    @declared_attr
-    def operation_templates(cls):
-        return relationship.one_to_many(cls, 'operation_template', 
dict_key='name')
 
     # region foreign keys
 
@@ -1416,6 +1639,57 @@ class InterfaceTemplateBase(TemplateModelMixin):
 
     # endregion
 
+
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def interfaces(cls):
+        return relationship.one_to_many(cls, 'interface')
+
+    @declared_attr
+    def operation_templates(cls):
+        return relationship.one_to_many(cls, 'operation_template', 
dict_key='name')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def relationship_template(cls):
+        return relationship.many_to_one(cls, 'relationship_template')
+
+    @declared_attr
+    def group_template(cls):
+        return relationship.many_to_one(cls, 'group_template')
+
+    @declared_attr
+    def node_template(cls):
+        return relationship.many_to_one(cls, 'node_template')
+
+    @declared_attr
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def inputs(cls):
+        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
+
+    # endregion
+
+    description = Column(Text)
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1496,21 +1770,6 @@ class OperationTemplateBase(TemplateModelMixin):
 
     description = Column(Text)
 
-    @declared_attr
-    def plugin_specification(cls):
-        return relationship.one_to_one(cls, 'plugin_specification')
-
-    implementation = Column(Text)
-    dependencies = Column(modeling_types.StrictList(item_cls=basestring))
-
-    @declared_attr
-    def inputs(cls):
-        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
-
-    executor = Column(Text)
-    max_retries = Column(Integer)
-    retry_interval = Column(Integer)
-
     # region foreign keys
 
     @declared_attr
@@ -1530,6 +1789,52 @@ class OperationTemplateBase(TemplateModelMixin):
 
     # endregion
 
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    @declared_attr
+    def plugin_specification(cls):
+        return relationship.one_to_one(cls, 'plugin_specification', 
back_populates=False)
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def operations(cls):
+        return relationship.one_to_many(cls, 'operation')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def service_template(cls):
+        return relationship.many_to_one(cls, 'service_template')
+
+    @declared_attr
+    def interface_template(cls):
+        return relationship.many_to_one(cls, 'interface_template')
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def inputs(cls):
+        return relationship.many_to_many(cls, 'parameter', prefix='inputs', 
dict_key='name')
+
+    # endregion
+
+    implementation = Column(Text)
+    dependencies = Column(modeling_types.StrictList(item_cls=basestring))
+    executor = Column(Text)
+    max_retries = Column(Integer)
+    retry_interval = Column(Integer)
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1616,20 +1921,6 @@ class ArtifactTemplateBase(TemplateModelMixin):
     __private_fields__ = ['type_fk',
                           'node_template_fk']
 
-    @declared_attr
-    def type(cls):
-        return relationship.many_to_one(cls, 'type')
-
-    description = Column(Text)
-    source_path = Column(Text)
-    target_path = Column(Text)
-    repository_url = Column(Text)
-    repository_credential = Column(modeling_types.StrictDict(basestring, 
basestring))
-
-    @declared_attr
-    def properties(cls):
-        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
-
     # region foreign keys
 
     @declared_attr
@@ -1644,6 +1935,52 @@ class ArtifactTemplateBase(TemplateModelMixin):
 
     # endregion
 
+    # region association proxies
+
+    # endregion
+
+    # region one_to_one relationships
+
+    # endregion
+
+    # region one_to_many relationships
+
+    @declared_attr
+    def artifacts(cls):
+        return relationship.one_to_many(cls, 'artifact')
+
+    # endregion
+
+    # region many_to_one relationships
+
+    @declared_attr
+    def node_template(cls):
+        return relationship.many_to_one(cls, 'node_template')
+
+    @declared_attr
+    def type(cls):
+        return relationship.many_to_one(cls, 'type', back_populates=False)
+
+    # endregion
+
+    # region many_to_many relationships
+
+    @declared_attr
+    def properties(cls):
+        return relationship.many_to_many(cls, 'parameter', 
prefix='properties', dict_key='name')
+
+    # endregion
+
+    description = Column(Text)
+    source_path = Column(Text)
+    target_path = Column(Text)
+    repository_url = Column(Text)
+    repository_credential = Column(modeling_types.StrictDict(basestring, 
basestring))
+
+
+
+
+
     @property
     def as_raw(self):
         return collections.OrderedDict((

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35a1195/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py 
b/tests/orchestrator/context/test_operation.py
index 6721b29..f55b83e 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -353,10 +353,10 @@ def _assert_loggins(ctx, inputs):
     tasks = ctx.model.task.list()
     assert len(tasks) == 1
     task = tasks[0]
-    assert task.logs.count() == 4
+    assert len(task.logs) == 4
 
     logs = ctx.model.log.list()
-    assert len(logs) == execution.logs.count() == 6
+    assert len(logs) == len(execution.logs) == 6
     assert set(logs) == set(execution.logs)
 
     assert all(l.execution == execution for l in logs)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35a1195/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
----------------------------------------------------------------------
diff --git 
a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
 
b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
index b950fa4..3b4f371 100644
--- 
a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
+++ 
b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
@@ -33,7 +33,6 @@ imports:
   - types/mongodb.yaml
   - types/nginx.yaml
   - aria-1.0
-
 dsl_definitions:
 
   default_openstack_credential: &DEFAULT_OPENSTACK_CREDENTIAL

Reply via email to