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/05 03:32:09 UTC

[1/2] incubator-ariatosca git commit: Add rich docs, fix many tests

Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-105-integrate-modeling 36eb2d24c -> 24ad8ba1e


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/tests/storage/test_instrumentation.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_instrumentation.py b/tests/storage/test_instrumentation.py
index 413b888..3ef74e4 100644
--- a/tests/storage/test_instrumentation.py
+++ b/tests/storage/test_instrumentation.py
@@ -18,11 +18,11 @@ from sqlalchemy import Column, Text, Integer, event
 
 from aria.modeling import (
     bases,
-    exceptions,
     types as modeling_types,
     models
 )
 from aria.storage import (
+    exceptions,
     ModelStorage,
     sql_mapi,
     instrumentation
@@ -281,8 +281,8 @@ class TestInstrumentation(object):
     def test_track_changes_to_strict_dict(self, storage):
         model_kwargs = dict(strict_dict={'key': 'value'},
                             strict_list=['item'])
-        mode_instance = StrictMockModel(**model_kwargs)
-        storage.strict_mock_model.put(mode_instance)
+        model_instance = StrictMockModel(**model_kwargs)
+        storage.strict_mock_model.put(model_instance)
 
         instrument = self._track_changes({
             StrictMockModel.strict_dict: dict,
@@ -291,7 +291,7 @@ class TestInstrumentation(object):
 
         assert not instrument.tracked_changes
 
-        storage_model_instance = storage.strict_mock_model.get(mode_instance.id)
+        storage_model_instance = storage.strict_mock_model.get(model_instance.id)
 
         with pytest.raises(exceptions.StorageError):
             storage_model_instance.strict_dict = {1: 1}
@@ -312,7 +312,7 @@ class TestInstrumentation(object):
 
         assert instrument.tracked_changes == {
             'strict_mock_model': {
-                mode_instance.id: {
+                model_instance.id: {
                     'strict_dict': Value(STUB, {'hello': 'world'}),
                     'strict_list': Value(STUB, ['hello']),
                 }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/tests/storage/test_model_storage.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_model_storage.py b/tests/storage/test_model_storage.py
index 416a0a8..bb778d4 100644
--- a/tests/storage/test_model_storage.py
+++ b/tests/storage/test_model_storage.py
@@ -63,40 +63,40 @@ def test_application_storage_factory():
     storage = application_model_storage(sql_mapi.SQLAlchemyModelAPI,
                                         initiator=init_inmemory_model_storage)
 
-    assert storage.parameter
-    assert storage.mapping_template
-    assert storage.substitution_template
     assert storage.service_template
     assert storage.node_template
     assert storage.group_template
-    assert storage.interface_template
-    assert storage.operation_template
-    assert storage.artifact_template
     assert storage.policy_template
-    assert storage.group_policy_template
-    assert storage.group_policy_trigger_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.mapping
-    assert storage.substitution
-    assert storage.service_instance
+    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.capability
     assert storage.artifact
-    assert storage.policy
-    assert storage.group_policy
-    assert storage.group_policy_trigger
-    assert storage.relationship
 
     assert storage.execution
-    assert storage.service_instance_update
-    assert storage.service_instance_update_step
-    assert storage.service_instance_modification
+    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)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/tests/storage/test_models.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_models.py b/tests/storage/test_models.py
index 45324dc..0088314 100644
--- a/tests/storage/test_models.py
+++ b/tests/storage/test_models.py
@@ -12,6 +12,7 @@
 # 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 datetime import datetime
 from contextlib import contextmanager
 
@@ -34,7 +35,8 @@ from aria.modeling.models import (
     Relationship,
     NodeTemplate,
     Node,
-    Parameter
+    Parameter,
+    Type
 )
 
 from tests import mock
@@ -59,55 +61,55 @@ def _empty_storage():
 
 def _service_template_storage():
     storage = _empty_storage()
-    service_template = mock.models.get_service_template()
+    service_template = mock.models.create_service_template()
     storage.service_template.put(service_template)
+    storage.type.put(Type(variant='node'))
     return storage
 
 
-def _service_instance_storage():
+def _service_storage():
     storage = _service_template_storage()
-    service_instance = mock.models.get_service(
+    service = mock.models.create_service(
         storage.service_template.get_by_name(mock.models.SERVICE_TEMPLATE_NAME))
-    storage.service_instance.put(service_instance)
+    storage.service.put(service)
     return storage
 
 
-def _service_instance_update_storage():
-    storage = _service_instance_storage()
-    service_instance_update = ServiceUpdate(
-        service_instance=storage.service_instance.list()[0],
+def _service_update_storage():
+    storage = _service_storage()
+    service_update = ServiceUpdate(
+        service=storage.service.list()[0],
         created_at=now,
-        service_instance_plan={},
+        service_plan={},
     )
-    storage.service_instance_update.put(service_instance_update)
+    storage.service_update.put(service_update)
     return storage
 
 
 def _node_template_storage():
-    storage = _service_instance_storage()
-    node_template = mock.models.get_dependency_node_template(storage.service_instance.list()[0])
+    storage = _service_storage()
+    service_template = storage.service_template.list()[0]
+    node_template = mock.models.create_dependency_node_template(service_template)
     storage.node_template.put(node_template)
     return storage
 
 
 def _nodes_storage():
-    storage = _nodes_storage()
-    service_instance = storage.service_instance.get_by_name(mock.models.SERVICE_NAME)
+    storage = _nodes_storage() # ???
+    service = storage.service.get_by_name(mock.models.SERVICE_NAME)
     dependent_node_template = storage.node_template.get_by_name(mock.models.DEPENDENT_NODE_NAME)
     dependency_node_template = storage.node_template.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
-    dependency_node = mock.models.get_dependency_node(dependency_node_template,
-                                                               service_instance)
-    dependent_node = mock.models.get_dependent_node(dependent_node_template,
-                                                             service_instance)
+    dependency_node = mock.models.create_dependency_node(dependency_node_template, service)
+    dependent_node = mock.models.create_dependent_node(dependent_node_template, service)
     storage.node.put(dependency_node)
     storage.node.put(dependent_node)
     return storage
 
 
 def _execution_storage():
-    storage = _service_instance_storage()
-    execution = mock.models.get_execution(storage.service_instance.list()[0])
-    plugin = mock.models.get_plugin()
+    storage = _service_storage()
+    execution = mock.models.create_execution(storage.service.list()[0])
+    plugin = mock.models.create_plugin()
     storage.execution.put(execution)
     storage.plugin.put(plugin)
     return storage
@@ -126,14 +128,14 @@ def service_template_storage():
 
 
 @pytest.fixture
-def service_instance_storage():
-    with sql_storage(_service_instance_storage) as storage:
+def service_storage():
+    with sql_storage(_service_storage) as storage:
         yield storage
 
 
 @pytest.fixture
-def service_instance_update_storage():
-    with sql_storage(_service_instance_update_storage) as storage:
+def service_update_storage():
+    with sql_storage(_service_update_storage) as storage:
         yield storage
 
 
@@ -174,7 +176,7 @@ class TestServiceTemplate(object):
     @pytest.mark.parametrize(
         'is_valid, description, created_at, updated_at, main_file_name',
         [
-            (False, 'description', now, now, '/path'),
+            (True, 'description', now, now, '/path'),
             (False, {}, now, now, '/path'),
             (False, 'description', 'error', now, '/path'),
             (False, 'description', now, 'error', '/path'),
@@ -183,8 +185,8 @@ class TestServiceTemplate(object):
         ]
     )
 
-    def test_blueprint_model_creation(self, empty_storage, is_valid, description, created_at,
-                                      updated_at, main_file_name):
+    def test_service_template_model_creation(self, empty_storage, is_valid, description, created_at,
+                                             updated_at, main_file_name):
         _test_model(is_valid=is_valid,
                     storage=empty_storage,
                     model_cls=ServiceTemplate,
@@ -199,58 +201,49 @@ class TestServiceTemplate(object):
 class TestService(object):
 
     @pytest.mark.parametrize(
-        'is_valid, name, created_at, description, inputs, permalink, policy_triggers, '
-        'policy_types, outputs, scaling_groups, updated_at, workflows',
+        'is_valid, name, created_at, description, inputs, permalink, '
+        'outputs, scaling_groups, updated_at',
         [
-            (False, m_cls, now, 'desc', [], 'perlnk', {}, {}, [], {}, now, {}),
-            (False, 'name', m_cls, 'desc', [], 'perlnk', {}, {}, [], {}, now, {}),
-            (False, 'name', now, m_cls, [], 'perlnk', {}, {}, [], {}, now, {}),
-            (False, 'name', now, 'desc', [], m_cls, {}, {}, [], {}, now, {}),
-            (False, 'name', now, 'desc', [], 'perlnk', m_cls, {}, [], {}, now, {}),
-            (False, 'name', now, 'desc', [], 'perlnk', {}, m_cls, [], {}, now, {}),
-            (False, 'name', now, 'desc', [], 'perlnk', {}, {}, m_cls, {}, now, {}),
-            (False, 'name', now, 'desc', [], 'perlnk', {}, {}, [], m_cls, now, {}),
-            (False, 'name', now, 'desc', [], 'perlnk', {}, {}, [], {}, m_cls, {}),
-            (False, 'name', now, 'desc', [], 'perlnk', {}, {}, [], {}, now, m_cls),
-
-            (True, 'name', now, 'desc', [], 'perlnk', {}, {}, [], {}, now, {}),
-            (True, None, now, 'desc', [], 'perlnk', {}, {}, [], {}, now, {}),
-            (True, 'name', now, 'desc', [], 'perlnk', {}, {}, [], {}, now, {}),
-            (True, 'name', now, None, [], 'perlnk', {}, {}, [], {}, now, {}),
-            (True, 'name', now, 'desc', [], 'perlnk', {}, {}, [], {}, now, {}),
-            (True, 'name', now, 'desc', [], None, {}, {}, [], {}, now, {}),
-            (True, 'name', now, 'desc', [], 'perlnk', None, {}, [], {}, now, {}),
-            (True, 'name', now, 'desc', [], 'perlnk', {}, None, [], {}, now, {}),
-            (True, 'name', now, 'desc', [], 'perlnk', {}, {}, [], None, now, {}),
-            (True, 'name', now, 'desc', [], 'perlnk', {}, {}, [], {}, None, {}),
-            (True, 'name', now, 'desc', [], 'perlnk', {}, {}, [], {}, now, None),
+            (False, m_cls, now, 'desc', {}, 'perlnk', {}, {}, now),
+            (False, 'name', m_cls, 'desc', {}, 'perlnk', {}, {}, now),
+            (False, 'name', now, m_cls, {}, 'perlnk', {}, {}, now),
+            (False, 'name', now, 'desc', {}, m_cls, {}, {}, now),
+            (False, 'name', now, 'desc', {}, 'perlnk', m_cls, {}, now),
+            (False, 'name', now, 'desc', {}, 'perlnk', {}, m_cls, now),
+            (False, 'name', now, 'desc', {}, 'perlnk', {}, {}, m_cls),
+
+            (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now),
+            (True, None, now, 'desc', {}, 'perlnk', {}, {}, now),
+            (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now),
+            (True, 'name', now, None, {}, 'perlnk', {}, {}, now),
+            (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now),
+            (True, 'name', now, 'desc', {}, None, {}, {}, now),
+            (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now),
+            (True, 'name', now, 'desc', {}, 'perlnk', {}, None, now),
+            (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, None),
+            (True, 'name', now, 'desc', {}, 'perlnk', {}, {}, now),
         ]
     )
-    def test_deployment_model_creation(self, service_instance_storage, is_valid, name, created_at,
-                                       description, inputs, permalink, policy_triggers,
-                                       policy_types, outputs, scaling_groups, updated_at,
-                                       workflows):
-        service_instance = _test_model(
+    def test_service_model_creation(self, service_storage, is_valid, name, created_at, description,
+                                    inputs, permalink, outputs, scaling_groups, updated_at):
+        service = _test_model(
             is_valid=is_valid,
-            storage=service_instance_storage,
+            storage=service_storage,
             model_cls=Service,
             model_kwargs=dict(
                 name=name,
-                service_template=service_instance_storage.service_template.list()[0],
+                service_template=service_storage.service_template.list()[0],
                 created_at=created_at,
                 description=description,
                 inputs=inputs,
                 permalink=permalink,
-                policy_triggers=policy_triggers,
-                policy_types=policy_types,
                 outputs=outputs,
                 scaling_groups=scaling_groups,
-                updated_at=updated_at,
-                workflows=workflows
+                updated_at=updated_at
             ))
         if is_valid:
-            assert service_instance.service_template == \
-                   service_instance_storage.service_template.list()[0]
+            assert service.service_template == \
+                   service_storage.service_template.list()[0]
 
 
 class TestExecution(object):
@@ -274,15 +267,15 @@ class TestExecution(object):
             (True, now, now, now, 'error', False, None, Execution.STARTED, 'wf_name'),
         ]
     )
-    def test_execution_model_creation(self, service_instance_storage, is_valid, created_at,
-                                      started_at, ended_at, error, is_system_workflow, parameters,
-                                      status, workflow_name):
+    def test_execution_model_creation(self, service_storage, is_valid, created_at, started_at,
+                                      ended_at, error, is_system_workflow, parameters, status,
+                                      workflow_name):
         execution = _test_model(
             is_valid=is_valid,
-            storage=service_instance_storage,
+            storage=service_storage,
             model_cls=Execution,
             model_kwargs=dict(
-                service_instance=service_instance_storage.service_instance.list()[0],
+                service=service_storage.service.list()[0],
                 created_at=created_at,
                 started_at=started_at,
                 ended_at=ended_at,
@@ -293,8 +286,8 @@ class TestExecution(object):
                 workflow_name=workflow_name,
             ))
         if is_valid:
-            assert execution.service_instance == service_instance_storage.service_instance.list()[0]
-            assert execution.service_template == service_instance_storage.service_template.list()[0]
+            assert execution.service == service_storage.service.list()[0]
+            assert execution.service_template == service_storage.service_template.list()[0]
 
     def test_execution_status_transition(self):
         def create_execution(status):
@@ -363,8 +356,8 @@ class TestExecution(object):
 
 class TestServiceUpdate(object):
     @pytest.mark.parametrize(
-        'is_valid, created_at, deployment_plan, service_instance_update_node_instances, '
-        'service_instance_update_service_instance, service_instance_update_nodes, '
+        'is_valid, created_at, service_plan, service_update_nodes, '
+        'service_update_service, service_update_node_templates, '
         'modified_entity_ids, state',
         [
             (False, m_cls, {}, {}, {}, [], {}, 'state'),
@@ -383,27 +376,27 @@ class TestServiceUpdate(object):
             (True, now, {}, {}, {}, [], {}, None),
         ]
     )
-    def test_service_instance_update_model_creation(
-            self, service_instance_storage, is_valid, created_at, deployment_plan,
-            service_instance_update_node_instances, service_instance_update_service_instance,
-            service_instance_update_nodes, modified_entity_ids, state):
-        service_instance_update = _test_model(
+    def test_service_update_model_creation(self, service_storage, is_valid, created_at,
+                                           service_plan, service_update_nodes,
+                                           service_update_service, service_update_node_templates,
+                                           modified_entity_ids, state):
+        service_update = _test_model(
             is_valid=is_valid,
-            storage=service_instance_storage,
+            storage=service_storage,
             model_cls=ServiceUpdate,
             model_kwargs=dict(
-                service_instance=service_instance_storage.service_instance.list()[0],
+                service=service_storage.service.list()[0],
                 created_at=created_at,
-                service_instance_plan=deployment_plan,
-                service_instance_update_node_instances=service_instance_update_node_instances,
-                service_instance_update_service_instance=service_instance_update_service_instance,
-                service_instance_update_nodes=service_instance_update_nodes,
+                service_plan=service_plan,
+                service_update_nodes=service_update_nodes,
+                service_update_service=service_update_service,
+                service_update_node_templates=service_update_node_templates,
                 modified_entity_ids=modified_entity_ids,
-                state=state,
+                state=state
             ))
         if is_valid:
-            assert service_instance_update.service_instance == \
-                   service_instance_storage.service_instance.list()[0]
+            assert service_update.service == \
+                   service_storage.service.list()[0]
 
 
 class TestServiceUpdateStep(object):
@@ -420,24 +413,24 @@ class TestServiceUpdateStep(object):
              ServiceUpdateStep.ENTITY_TYPES.NODE)
         ]
     )
-    def test_deployment_update_step_model_creation(self, service_instance_update_storage, is_valid,
-                                                   action, entity_id, entity_type):
-        service_instance_update_step = _test_model(
+    def test_service_update_step_model_creation(self, service_update_storage, is_valid, action,
+                                                entity_id, entity_type):
+        service_update_step = _test_model(
             is_valid=is_valid,
-            storage=service_instance_update_storage,
+            storage=service_update_storage,
             model_cls=ServiceUpdateStep,
             model_kwargs=dict(
-                service_instance_update=
-                service_instance_update_storage.service_instance_update.list()[0],
+                service_update=
+                service_update_storage.service_update.list()[0],
                 action=action,
                 entity_id=entity_id,
                 entity_type=entity_type
             ))
         if is_valid:
-            assert service_instance_update_step.service_instance_update == \
-                   service_instance_update_storage.service_instance_update.list()[0]
+            assert service_update_step.service_update == \
+                   service_update_storage.service_update.list()[0]
 
-    def test_deployment_update_step_order(self):
+    def test_service_update_step_order(self):
         add_node = ServiceUpdateStep(
             id='add_step',
             action='add',
@@ -478,7 +471,7 @@ class TestServiceUpdateStep(object):
         assert not add_node < None
 
 
-class TestDeploymentModification(object):
+class TestServiceModification(object):
     @pytest.mark.parametrize(
         'is_valid, context, created_at, ended_at, modified_node_templates, nodes, status',
         [
@@ -495,66 +488,60 @@ class TestDeploymentModification(object):
             (True, {}, now, now, {}, None, ServiceModification.STARTED),
         ]
     )
-    def test_deployment_modification_model_creation(
-            self, service_instance_storage, is_valid, context, created_at, ended_at,
-            modified_node_templates, nodes, status):
-        deployment_modification = _test_model(
+    def test_service_modification_model_creation(self, service_storage, is_valid, context,
+                                                 created_at, ended_at, modified_node_templates,
+                                                 nodes, status):
+        service_modification = _test_model(
             is_valid=is_valid,
-            storage=service_instance_storage,
+            storage=service_storage,
             model_cls=ServiceModification,
             model_kwargs=dict(
-                service_instance=service_instance_storage.service_instance.list()[0],
+                service=service_storage.service.list()[0],
                 context=context,
                 created_at=created_at,
                 ended_at=ended_at,
-                modified_nodes=modified_node_templates,
-                node_instances=nodes,
+                modified_node_templates=modified_node_templates,
+                nodes=nodes,
                 status=status,
             ))
         if is_valid:
-            assert deployment_modification.service_instance == \
-                   service_instance_storage.service_instance.list()[0]
+            assert service_modification.service == \
+                   service_storage.service.list()[0]
 
 
 class TestNodeTemplate(object):
     @pytest.mark.parametrize(
-        'is_valid, name, default_instances, max_instances, min_instances, plugins, properties, '
-        'type_name, type_hierarchy',
+        'is_valid, name, default_instances, max_instances, min_instances, plugins, properties',
         [
-            (False, m_cls, 1, 1, 1, [], [], 'type', []),
-            (False, 'name', m_cls, 1, 1, [], [], 'type', []),
-            (False, 'name', 1, m_cls, 1, [], [], 'type', []),
-            (False, 'name', 1, 1, m_cls, [], [], 'type', []),
-            (False, 'name', 1, 1, 1, m_cls, [], 'type', []),
-            (False, 'name', 1, 1, 1, [], [], m_cls, []),
-            (False, 'name', 1, 1, 1, [], [], 'type', m_cls),
-            #
-            (True, 'name', 1, 1, 1, [], [], 'type', []),
-            (True, 'name', 1, 1, 1, None, [], 'type', []),
-            (True, 'name', 1, 1, 1, [], [], 'type', None),
+            (False, m_cls, 1, 1, 1, [], {}),
+            (False, 'name', m_cls, 1, 1, [], {}),
+            (False, 'name', 1, m_cls, 1, [], {}),
+            (False, 'name', 1, 1, m_cls, [], {}),
+            (False, 'name', 1, 1, 1, m_cls, {}),
+            (False, 'name', 1, 1, 1, None, {}),
+
+            (True, 'name', 1, 1, 1, [], {}),
         ]
     )
-    def test_node_model_creation(self, service_instance_storage, is_valid, name,
-                                 default_instances, max_instances, min_instances, plugins,
-                                 properties, type_name, type_hierarchy):
+    def test_node_template_model_creation(self, service_storage, is_valid, name, default_instances,
+                                          max_instances, min_instances, plugins, properties):
         node_template = _test_model(
             is_valid=is_valid,
-            storage=service_instance_storage,
+            storage=service_storage,
             model_cls=NodeTemplate,
             model_kwargs=dict(
                 name=name,
+                type=service_storage.type.list()[0],
                 default_instances=default_instances,
                 max_instances=max_instances,
                 min_instances=min_instances,
                 plugins=plugins,
                 properties=properties,
-                type_name=type_name,
-                type_hierarchy=type_hierarchy,
-                service_template=service_instance_storage.service_template.list()[0]
+                service_template=service_storage.service_template.list()[0]
             ))
         if is_valid:
             assert node_template.service_template == \
-                   service_instance_storage.service_template.list()[0]
+                   service_storage.service_template.list()[0]
 
 
 class TestNode(object):
@@ -574,62 +561,63 @@ class TestNode(object):
             (True, 'name', {}, [], 'state', None),
         ]
     )
-    def test_node_instance_model_creation(self, node_template_storage, is_valid, name,
-                                          runtime_properties, scaling_groups, state, version):
-        node_instance = _test_model(
+    def test_node_model_creation(self, node_template_storage, is_valid, name, runtime_properties,
+                                 scaling_groups, state, version):
+        node = _test_model(
             is_valid=is_valid,
             storage=node_template_storage,
             model_cls=Node,
             model_kwargs=dict(
                 node_template=node_template_storage.node_template.list()[0],
+                type=node_template_storage.type.list()[0],
                 name=name,
                 runtime_properties=runtime_properties,
                 scaling_groups=scaling_groups,
                 state=state,
                 version=version,
-                service_instance=node_template_storage.service_instance.list()[0]
+                service=node_template_storage.service.list()[0]
             ))
         if is_valid:
-            assert node_instance.node_template == node_template_storage.node_template.list()[0]
-            assert node_instance.service_instance == \
-                   node_template_storage.service_instance.list()[0]
+            assert node.node_template == node_template_storage.node_template.list()[0]
+            assert node.service == \
+                   node_template_storage.service.list()[0]
 
 
 class TestNodeInstanceIP(object):
 
     ip = '1.1.1.1'
 
-    def test_ip_on_none_hosted_node_instance(self, service_instance_storage):
-        node_template = self._node_template(service_instance_storage, ip='not considered')
-        node = self._node(service_instance_storage,
+    def test_ip_on_none_hosted_node(self, service_storage):
+        node_template = self._node_template(service_storage, ip='not considered')
+        node = self._node(service_storage,
                           node_template,
                           is_host=False,
                           ip='not considered')
         assert node.ip is None
 
-    def test_property_ip_on_host_node_instance(self, service_instance_storage):
-        node_template = self._node_template(service_instance_storage, ip=self.ip)
-        node = self._node(service_instance_storage, node_template, is_host=True, ip=None)
+    def test_property_ip_on_host_node(self, service_storage):
+        node_template = self._node_template(service_storage, ip=self.ip)
+        node = self._node(service_storage, node_template, is_host=True, ip=None)
         assert node.ip == self.ip
 
-    def test_runtime_property_ip_on_host_node_instance(self, service_instance_storage):
-        node_template = self._node_template(service_instance_storage, ip='not considered')
-        node = self._node(service_instance_storage, node_template, is_host=True, ip=self.ip)
+    def test_runtime_property_ip_on_host_node(self, service_storage):
+        node_template = self._node_template(service_storage, ip='not considered')
+        node = self._node(service_storage, node_template, is_host=True, ip=self.ip)
         assert node.ip == self.ip
 
-    def test_no_ip_configured_on_host_node_instance(self, service_instance_storage):
-        node_template = self._node_template(service_instance_storage, ip=None)
-        node = self._node(service_instance_storage, node_template, is_host=True, ip=None)
+    def test_no_ip_configured_on_host_node(self, service_storage):
+        node_template = self._node_template(service_storage, ip=None)
+        node = self._node(service_storage, node_template, is_host=True, ip=None)
         assert node.ip is None
 
-    def test_runtime_property_on_hosted_node_instance(self, service_instance_storage):
-        host_node_template = self._node_template(service_instance_storage, ip=None)
-        host_node = self._node(service_instance_storage,
+    def test_runtime_property_on_hosted_node(self, service_storage):
+        host_node_template = self._node_template(service_storage, ip=None)
+        host_node = self._node(service_storage,
                                host_node_template,
                                is_host=True,
                                ip=self.ip)
-        node_template = self._node_template(service_instance_storage, ip=None)
-        node = self._node(service_instance_storage,
+        node_template = self._node_template(service_storage, ip=None)
+        node = self._node(service_storage,
                           node_template,
                           is_host=False,
                           ip=None,
@@ -639,14 +627,14 @@ class TestNodeInstanceIP(object):
     def _node_template(self, storage, ip):
         kwargs = dict(
             name='node_template',
+            type=storage.type.list()[0],
             default_instances=1,
             max_instances=1,
             min_instances=1,
-            type_name='',
             service_template=storage.service_template.list()[0]
         )
         if ip:
-            kwargs['properties'] = [Parameter(name='ip', type='str', str_value=str(ip))]
+            kwargs['properties'] = {'ip': Parameter(name='ip', type_name='string', value=ip)}
         node = NodeTemplate(**kwargs)
         storage.node_template.put(node)
         return node
@@ -655,9 +643,10 @@ class TestNodeInstanceIP(object):
         kwargs = dict(
             name='node',
             node_template=node,
+            type=storage.type.list()[0],
             runtime_properties={},
             state='',
-            service_instance=storage.service_instance.list()[0]
+            service=storage.service.list()[0]
         )
         if ip:
             kwargs['runtime_properties']['ip'] = ip
@@ -665,21 +654,21 @@ class TestNodeInstanceIP(object):
             kwargs['host_fk'] = 1
         elif host_fk:
             kwargs['host_fk'] = host_fk
-        node_instance = Node(**kwargs)
-        storage.node.put(node_instance)
-        return node_instance
+        node = Node(**kwargs)
+        storage.node.put(node)
+        return node
 
 
 @pytest.mark.skip('Should be reworked into relationship')
-class TestRelationshipInstance(object):
-    def test_relatiship_instance_model_creation(self, nodes_storage):
-        relationship = mock.models.get_relationship(
+class TestRelationship(object):
+    def test_relationship_model_creation(self, nodes_storage):
+        relationship = mock.models.create_relationship(
             target=nodes_storage.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
         )
         nodes_storage.relationship.put(relationship)
-        node_instances = nodes_storage.node
-        source_node_instance = node_instances.get_by_name(mock.models.DEPENDENT_NODE_INSTANCE_NAME)
-        target_node_instance = node_instances.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
+        nodes = nodes_storage.node
+        source_node = nodes.get_by_name(mock.models.DEPENDENT_NODE_NAME)
+        target_node = nodes.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
 
         relationship_instance = _test_model(
             is_valid=True,
@@ -687,12 +676,12 @@ class TestRelationshipInstance(object):
             model_cls=Relationship,
             model_kwargs=dict(
                 relationship=relationship,
-                source_node_instance=source_node_instance,
-                target_node_instance=target_node_instance
+                source_node=source_node,
+                target_node=target_node
             ))
         assert relationship_instance.relationship == relationship
-        assert relationship_instance.source_node_instance == source_node_instance
-        assert relationship_instance.target_node_instance == target_node_instance
+        assert relationship_instance.source_node == source_node
+        assert relationship_instance.target_node == target_node
 
 
 class TestPlugin(object):
@@ -747,9 +736,9 @@ class TestPlugin(object):
         ]
     )
     def test_plugin_model_creation(self, empty_storage, is_valid, archive_name, distribution,
-                                   distribution_release, distribution_version,
-                                   package_name, package_source, package_version,
-                                   supported_platform, supported_py_versions, uploaded_at, wheels):
+                                   distribution_release, distribution_version, package_name,
+                                   package_source, package_version, supported_platform,
+                                   supported_py_versions, uploaded_at, wheels):
         _test_model(is_valid=is_valid,
                     storage=empty_storage,
                     model_cls=Plugin,
@@ -785,6 +774,7 @@ class TestTask(object):
             (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', m_cls, {}, '1'),
             (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', m_cls, '1'),
             (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, m_cls),
+            (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', None, '1'),
 
             (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'),
             (True, Task.STARTED, None, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'),
@@ -795,7 +785,6 @@ class TestTask(object):
             (True, Task.STARTED, now, now, now, 1, 1, 1, None, 'name', 'map', {}, '1'),
             (True, Task.STARTED, now, now, now, 1, 1, 1, True, None, 'map', {}, '1'),
             (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', None, {}, '1'),
-            (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', None, '1'),
             (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, None),
         ]
     )

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/tests/storage/test_structures.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_structures.py b/tests/storage/test_structures.py
index 67510ad..ceaea11 100644
--- a/tests/storage/test_structures.py
+++ b/tests/storage/test_structures.py
@@ -92,73 +92,71 @@ def test_inner_list_update(storage):
 
 
 def test_model_to_dict(context):
-    service_instance = context.service_instance
-    service_instance = service_instance.to_dict()
+    service = context.service
+    service = service.to_dict()
 
     expected_keys = [
         'description',
-        '_metadata',
         'created_at',
         'permalink',
-        'policy_triggers',
-        'policy_types',
         'scaling_groups',
-        'updated_at',
-        'workflows',
+        'updated_at'
     ]
 
     for expected_key in expected_keys:
-        assert expected_key in service_instance
+        assert expected_key in service
 
 
 def test_relationship_model_ordering(context):
-    service_instance = context.model.service_instance.get_by_name(models.SERVICE_NAME)
-    source_node = context.model.node.get_by_name(models.DEPENDENT_NODE_INSTANCE_NAME)
-    target_node = context.model.node.get_by_name(models.DEPENDENCY_NODE_INSTANCE_NAME)
+    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',
-        type_name='test_node_type',
-        type_hierarchy=[],
+        name='new_node_template',
+        type=source_node.type,
         default_instances=1,
         min_instances=1,
         max_instances=1,
-        service_template=service_instance.service_template
+        service_template=service.service_template
     )
+
     new_node = modeling.models.Node(
-        name='new_node_instance',
+        name='new_node',
+        type=source_node.type,
         runtime_properties={},
-        service_instance=service_instance,
+        service=service,
         version=None,
         node_template=new_node_template,
         state='',
         scaling_groups=[]
     )
 
-    source_to_new_relationship = modeling.models.Relationship(
-        target_node=new_node,
+    source_node.outbound_relationships.append(modeling.models.Relationship(
         source_node=source_node,
-    )
+        target_node=new_node,
+    ))
 
-    new_to_target_relationship = modeling.models.Relationship(
+    new_node.outbound_relationships.append(modeling.models.Relationship(
         source_node=new_node,
         target_node=target_node,
-    )
+    ))
 
     context.model.node_template.put(new_node_template)
     context.model.node.put(new_node)
-    context.model.relationship.put(source_to_new_relationship)
-    context.model.relationship.put(new_to_target_relationship)
+    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 operatate on
-        :param direction: the type of relationships to flip (inbound/outbount)
+        :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').all()
+        relationships = getattr(node, direction + '_relationships')
         assert len(relationships) == 2
 
         reversed_relationship_instances = list(reversed(relationships))



[2/2] incubator-ariatosca git commit: Add rich docs, fix many tests

Posted by em...@apache.org.
Add rich docs, fix many tests


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

Branch: refs/heads/ARIA-105-integrate-modeling
Commit: 24ad8ba1e1a013a2348880459e81830fc270b16f
Parents: 36eb2d2
Author: Tal Liron <ta...@gmail.com>
Authored: Sat Mar 4 21:31:42 2017 -0600
Committer: Tal Liron <ta...@gmail.com>
Committed: Sat Mar 4 21:31:42 2017 -0600

----------------------------------------------------------------------
 aria/modeling/orchestration.py                  |  18 +-
 aria/modeling/service.py                        | 369 +++++++++++------
 aria/modeling/service_template.py               | 402 ++++++++++++-------
 aria/modeling/utils.py                          |  36 ++
 .../simple_v1_0/modeling/__init__.py            |  16 +-
 tests/mock/context.py                           |   4 +-
 tests/mock/models.py                            | 217 +++++-----
 tests/mock/topology.py                          |  90 ++---
 tests/orchestrator/context/test_operation.py    |  56 +--
 tests/orchestrator/test_runner.py               |   5 +-
 tests/storage/test_instrumentation.py           |  10 +-
 tests/storage/test_model_storage.py             |  38 +-
 tests/storage/test_models.py                    | 337 ++++++++--------
 tests/storage/test_structures.py                |  52 ++-
 14 files changed, 971 insertions(+), 679 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/aria/modeling/orchestration.py
----------------------------------------------------------------------
diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py
index 9cbb3cf..30879e9 100644
--- a/aria/modeling/orchestration.py
+++ b/aria/modeling/orchestration.py
@@ -154,13 +154,13 @@ class ServiceUpdateBase(ModelMixin):
 
     __tablename__ = 'service_update' 
 
-    _private_fields = ['execution_fk', 'deployment_fk']
+    _private_fields = ['execution_fk', 'service_fk']
 
     created_at = Column(DateTime, nullable=False, index=True)
     service_plan = Column(Dict, nullable=False)
-    service_update_node_instances = Column(Dict)
-    service_update_service_instance = Column(Dict)
-    service_update_nodes = Column(List)
+    service_update_nodes = Column(Dict)
+    service_update_service = Column(Dict)
+    service_update_node_templates = Column(List)
     modified_entity_ids = Column(Dict)
     state = Column(Text)
 
@@ -239,8 +239,8 @@ class ServiceUpdateStepBase(ModelMixin):
                                             backreference='steps')
 
     @declared_attr
-    def deployment_update_name(cls):
-        return association_proxy('deployment_update', cls.name_column_name())
+    def service_update_name(cls):
+        return association_proxy('service_update', cls.name_column_name())
 
     # region foreign keys
 
@@ -297,9 +297,9 @@ class ServiceModificationBase(ModelMixin):
     context = Column(Dict)
     created_at = Column(DateTime, nullable=False, index=True)
     ended_at = Column(DateTime, index=True)
-    modified_nodes = Column(Dict)
-    node_instances = Column(Dict)
-    status = Column(Enum(*STATES, name='deployment_modification_status'))
+    modified_node_templates = Column(Dict)
+    nodes = Column(Dict)
+    status = Column(Enum(*STATES, name='service_modification_status'))
 
     @declared_attr
     def service(cls):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/aria/modeling/service.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service.py b/aria/modeling/service.py
index e555b70..842d0fc 100644
--- a/aria/modeling/service.py
+++ b/aria/modeling/service.py
@@ -36,23 +36,47 @@ from . import (
 
 class ServiceBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
     """
-    A service instance is usually an instance of a :class:`ServiceTemplate`.
+    A service is usually an instance of a :class:`ServiceTemplate`.
 
-    You will usually not create it programmatically, but instead instantiate it from the template.
+    You will usually not create it programmatically, but instead instantiate it from a service
+    template.
 
+    :ivar name: Name (unique for this ARIA installation)
+    :vartype name: basestring
+    :ivar service_template: Template from which this service was instantiated (optional)
+    :vartype service_template: :class:`ServiceTemplate`
     :ivar description: Human-readable description
-    :ivar meta_data: Dict of :class:`Metadata`
-    :ivar nodes: Dict of :class:`Node`
-    :ivar groups: Dict of :class:`Group`
-    :ivar policies: Dict of :class:`Policy`
-    :ivar substitution: :class:`Substitution`
-    :ivar inputs: Dict of :class:`Parameter`
-    :ivar outputs: Dict of :class:`Parameter`
-    :ivar operations: Dict of :class:`Operation`
+    :vartype description: string
+    :ivar meta_data: Custom annotations
+    :vartype meta_data: {basestring: :class:`Metadata`}
+    :ivar node: Nodes
+    :vartype node: [:class:`Node`]
+    :ivar groups: Groups of nodes
+    :vartype groups: [:class:`Group`]
+    :ivar policies: Policies
+    :vartype policies: [:class:`Policy`]
+    :ivar substitution: The entire service can appear as a node
+    :vartype substitution: :class:`Substitution`
+    :ivar inputs: Externally provided parameters
+    :vartype inputs: {basestring: :class:`Parameter`}
+    :ivar outputs: These parameters are filled in after service installation
+    :vartype outputs: {basestring: :class:`Parameter`}
+    :ivar operations: Custom operations that can be performed on the service
+    :vartype operations: {basestring: :class:`Operation`}
+    :ivar plugins: Plugins required to be installed
+    :vartype plugins: {basestring: :class:`Plugin`}
+    :ivar created_at: Creation timestamp
+    :vartype created_at: :class:`datetime.datetime`
+    :ivar updated_at: Update timestamp
+    :vartype updated_at: :class:`datetime.datetime`
     """
 
     __tablename__ = 'service'
 
+    @declared_attr
+    def service_template(cls):
+        return cls.many_to_one_relationship('service_template')
+
     description = Column(Text)
 
     @declared_attr
@@ -91,20 +115,16 @@ class ServiceBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
         return cls.one_to_many_relationship('operation', dict_key='name')
 
     @declared_attr
-    def service_template(cls):
-        return cls.many_to_one_relationship('service_template')
-
-    # region orchestration
+    def plugins(cls):
+        return cls.many_to_many_relationship('plugin')
 
     created_at = Column(DateTime, nullable=False, index=True)
     updated_at = Column(DateTime)
+
+    # region orchestration
+
     permalink = Column(Text)
     scaling_groups = Column(modeling_types.Dict)
-    workflows = Column(modeling_types.Dict)
-
-    @declared_attr
-    def service_template_name(cls):
-        return association_proxy('service_template', 'name')
 
     # endregion
 
@@ -260,20 +280,44 @@ class NodeBase(InstanceModelMixin):
 
     Nodes may have zero or more :class:`Relationship` instances to other nodes.
 
-    :ivar name: Unique ID (often prefixed with the template name)
-    :ivar properties: Dict of :class:`Parameter`
-    :ivar interfaces: Dict of :class:`Interface`
-    :ivar artifacts: Dict of :class:`Artifact`
-    :ivar capabilities: Dict of :class:`CapabilityTemplate`
-    :ivar relationships: List of :class:`Relationship`
+    :ivar name: Name (unique for this service)
+    :vartype name: basestring
+    :ivar node_template: Template from which this node was instantiated (optional)
+    :vartype node_template: :class:`NodeTemplate`
+    :ivar type: Node type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: string
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
+    :ivar interfaces: Bundles of operations
+    :vartype interfaces: {basestring: :class:`Interface`}
+    :ivar artifacts: Associated files
+    :vartype artifacts: {basestring: :class:`Artifact`}
+    :ivar capabilities: Exposed capabilities
+    :vartype capabilities: {basestring: :class:`Capability`}
+    :ivar outbound_relationships: Relationships to other nodes
+    :vartype outbound_relationships: [:class:`Relationship`]
+    :ivar inbound_relationships: Relationships from other nodes
+    :vartype inbound_relationships: [:class:`Relationship`]
+    :ivar plugins: Plugins required to be installed on the node's host
+    :vartype plugins: {basestring: :class:`Plugin`}
+    :ivar host: Host node (can be self)
+    :vartype host: :class:`Node`
     """
 
     __tablename__ = 'node'
 
     @declared_attr
+    def node_template(cls):
+        return cls.many_to_one_relationship('node_template')
+
+    @declared_attr
     def type(cls):
         return cls.many_to_one_relationship('type')
 
+    description = Column(Text)
+
     @declared_attr
     def properties(cls):
         return cls.many_to_many_relationship('parameter', table_prefix='properties',
@@ -304,12 +348,12 @@ class NodeBase(InstanceModelMixin):
                                             backreference='target_node')
 
     @declared_attr
-    def host(cls):
-        return cls.relationship_to_self('host_fk')
+    def plugins(cls):
+        return cls.many_to_many_relationship('plugin')
 
     @declared_attr
-    def node_template(cls):
-        return cls.many_to_one_relationship('node_template')
+    def host(cls):
+        return cls.relationship_to_self('host_fk')
 
     # region orchestration
 
@@ -319,10 +363,6 @@ class NodeBase(InstanceModelMixin):
     version = Column(Integer, default=1)
 
     @declared_attr
-    def plugins(cls):
-        return association_proxy('node_template', 'plugins')
-
-    @declared_attr
     def service_name(cls):
         return association_proxy('service', 'name')
 
@@ -335,9 +375,9 @@ class NodeBase(InstanceModelMixin):
         if 'ip' in host_node.runtime_properties:  # pylint: disable=no-member
             return host_node.runtime_properties['ip']  # pylint: disable=no-member
         host_node = host_node.node_template  # pylint: disable=no-member
-        host_ip_property = [prop for prop in host_node.properties if prop.name == 'ip']
+        host_ip_property = host_node.properties.get('ip')
         if host_ip_property:
-            return host_ip_property[0].value
+            return host_ip_property.value
         return None
 
     # endregion
@@ -415,7 +455,7 @@ class NodeBase(InstanceModelMixin):
                     relationship = \
                         requirement_template.relationship_template.instantiate(context, self)
                 else:
-                    relationship = models.Relationship(capability=target_capability)
+                    relationship = models.Relationship(target_capability=target_capability)
                 relationship.name = requirement_template.name
                 relationship.requirement_template = requirement_template
                 relationship.target_node = target_node
@@ -504,17 +544,38 @@ class GroupBase(InstanceModelMixin):
     """
     Usually an instance of a :class:`GroupTemplate`.
 
-    :ivar name: Unique ID (often equal to the template name)
-    :ivar properties: Dict of :class:`Parameter`
-    :ivar interfaces: Dict of :class:`Interface`
+    :ivar name: Name (unique for this service)
+    :vartype name: basestring
+    :ivar group_template: Template from which this group was instantiated (optional)
+    :vartype group_template: :class:`GroupTemplate`
+    :ivar type: Group type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: string
+    :ivar nodes: Members of this group
+    :vartype nodes: [:class:`Node`]
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
+    :ivar interfaces: Bundles of operations
+    :vartype interfaces: {basestring: :class:`Interface`}
     """
 
     __tablename__ = 'group'
 
     @declared_attr
+    def group_template(cls):
+        return cls.many_to_one_relationship('group_template')
+
+    @declared_attr
     def type(cls):
         return cls.many_to_one_relationship('type')
 
+    description = Column(Text)
+
+    @declared_attr
+    def nodes(cls):
+        return cls.many_to_many_relationship('node')
+
     @declared_attr
     def properties(cls):
         return cls.many_to_many_relationship('parameter', table_prefix='properties',
@@ -524,14 +585,6 @@ class GroupBase(InstanceModelMixin):
     def interfaces(cls):
         return cls.one_to_many_relationship('interface', dict_key='name')
 
-    @declared_attr
-    def nodes(cls):
-        return cls.many_to_many_relationship('node')
-
-    @declared_attr
-    def group_template(cls):
-        return cls.many_to_one_relationship('group_template')
-
     # region foreign_keys
 
     __private_fields__ = ['type_fk',
@@ -587,16 +640,34 @@ class PolicyBase(InstanceModelMixin):
     """
     Usually an instance of a :class:`PolicyTemplate`.
 
-    :ivar name: Name
-    :ivar properties: Dict of :class:`Parameter`
+    :ivar name: Name (unique for this service)
+    :vartype name: basestring
+    :ivar policy_template: Template from which this policy was instantiated (optional)
+    :vartype policy_template: :class:`PolicyTemplate`
+    :ivar type: Policy type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: string
+    :ivar nodes: Policy will be enacted on all these nodes
+    :vartype nodes: [:class:`Node`]
+    :ivar groups: Policy will be enacted on all nodes in these groups
+    :vartype groups: [:class:`Group`]
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
     """
 
     __tablename__ = 'policy'
 
     @declared_attr
+    def policy_template(cls):
+        return cls.many_to_one_relationship('policy_template')
+
+    @declared_attr
     def type(cls):
         return cls.many_to_one_relationship('type')
 
+    description = Column(Text)
+
     @declared_attr
     def properties(cls):
         return cls.many_to_many_relationship('parameter', table_prefix='properties',
@@ -610,10 +681,6 @@ class PolicyBase(InstanceModelMixin):
     def groups(cls):
         return cls.many_to_many_relationship('group')
 
-    @declared_attr
-    def policy_template(cls):
-        return cls.many_to_one_relationship('policy_template')
-
     # region foreign_keys
 
     __private_fields__ = ['type_fk',
@@ -669,14 +736,25 @@ class PolicyBase(InstanceModelMixin):
 
 class SubstitutionBase(InstanceModelMixin):
     """
+    Used to substitute a single node for the entire deployment.
+
     Usually an instance of a :class:`SubstitutionTemplate`.
 
-    :ivar mappings: Dict of :class:` SubstitutionMapping`
+    :ivar substitution_template: Template from which this substitution was instantiated (optional)
+    :vartype substitution_template: :class:`SubstitutionTemplate`
+    :ivar node_type: Exposed node type
+    :vartype node_type: :class:`Type`
+    :ivar mappings: Requirement and capability mappings
+    :vartype mappings: {basestring: :class:`SubstitutionTemplate`}
     """
 
     __tablename__ = 'substitution'
 
     @declared_attr
+    def substitution_template(cls):
+        return cls.many_to_one_relationship('substitution_template')
+
+    @declared_attr
     def node_type(cls):
         return cls.many_to_one_relationship('type')
 
@@ -684,10 +762,6 @@ class SubstitutionBase(InstanceModelMixin):
     def mappings(cls):
         return cls.one_to_many_relationship('substitution_mapping', dict_key='name')
 
-    @declared_attr
-    def substitution_template(cls):
-        return cls.many_to_one_relationship('substitution_template')
-
     # region foreign_keys
 
     __private_fields__ = ['node_type_fk',
@@ -726,9 +800,20 @@ class SubstitutionBase(InstanceModelMixin):
 
 class SubstitutionMappingBase(InstanceModelMixin):
     """
-    An instance of a :class:`SubstitutionMappingTemplate`.
+    Used by :class:`Substitution` to map a capability or a requirement to a node.
+    
+    Only one of `capability_template` and `requirement_template` can be set.
+
+    Usually an instance of a :class:`SubstitutionTemplate`.
 
     :ivar name: Exposed capability or requirement name
+    :vartype name: basestring
+    :ivar node: Node
+    :vartype node: :class:`Node`
+    :ivar capability: Capability in the node
+    :vartype capability: :class:`Capability`
+    :ivar requirement_template: Requirement template in the node template
+    :vartype requirement_template: :class:`RequirementTemplate`
     """
 
     __tablename__ = 'substitution_mapping'
@@ -798,22 +883,43 @@ class SubstitutionMappingBase(InstanceModelMixin):
 
 class RelationshipBase(InstanceModelMixin):
     """
-    Connects :class:`Node` to another node.
+    Connects :class:`Node` to a capability in another node.
 
     Might be an instance of a :class:`RelationshipTemplate`.
 
     :ivar name: Name (usually the name of the requirement at the source node template)
-    :ivar properties: Dict of :class:`Parameter`
-    :ivar interfaces: Dict of :class:`Interface`
+    :vartype name: basestring
+    :ivar relationship_template: Template from which this relationship was instantiated (optional)
+    :vartype relationship_template: :class:`RelationshipTemplate`
+    :ivar type: Relationship type
+    :vartype type: :class:`Type`
+    :ivar source_node: Source node
+    :vartype source_node: :class:`Node`
+    :ivar target_node: Target node
+    :vartype target_node: :class:`Node`
+    :ivar target_capability: Capability at the target node (optional)
+    :vartype target_capability: :class:`Capability`
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
+    :ivar interface_templates: Bundles of operations
+    :vartype interface_templates: {basestring: :class:`InterfaceTemplate`}
     """
 
     __tablename__ = 'relationship'
 
     @declared_attr
+    def relationship_template(cls):
+        return cls.many_to_one_relationship('relationship_template')
+
+    @declared_attr
     def type(cls):
         return cls.many_to_one_relationship('type')
 
     @declared_attr
+    def target_capability(cls):
+        return cls.one_to_one_relationship('capability')
+
+    @declared_attr
     def properties(cls):
         return cls.many_to_many_relationship('parameter', table_prefix='properties',
                                              dict_key='name')
@@ -823,17 +929,9 @@ class RelationshipBase(InstanceModelMixin):
         return cls.one_to_many_relationship('interface', dict_key='name')
 
     @declared_attr
-    def capability(cls):
-        return cls.one_to_one_relationship('capability')
-
-    @declared_attr
     def requirement_template(cls):
         return cls.many_to_one_relationship('requirement_template')
 
-    @declared_attr
-    def relationship_template(cls):
-        return cls.many_to_one_relationship('relationship_template')
-
     # region orchestration
 
     source_position = Column(Integer) # ???
@@ -907,8 +1005,9 @@ class RelationshipBase(InstanceModelMixin):
             console.puts('->')
         with context.style.indent:
             console.puts('Node: {0}'.format(context.style.node(self.target_node.name)))
-            if self.capability:
-                console.puts('Capability: {0}'.format(context.style.node(self.capability.name)))
+            if self.target_capability:
+                console.puts('Capability: {0}'.format(context.style.node(
+                    self.target_capability.name)))
             if self.type is not None:
                 console.puts('Relationship type: {0}'.format(context.style.type(self.type.name)))
             if (self.relationship_template is not None) and self.relationship_template.name:
@@ -924,20 +1023,34 @@ class CapabilityBase(InstanceModelMixin):
 
     Usually an instance of a :class:`CapabilityTemplate`.
 
-    :ivar name: Name
+    :ivar name: Name (unique for the node)
+    :vartype name: basestring
+    :ivar capability_template: Template from which this capability was instantiated (optional)
+    :vartype capability_template: :class:`capabilityTemplate`
+    :ivar type: Capability type
+    :vartype type: :class:`Type`
     :ivar min_occurrences: Minimum number of requirement matches required
+    :vartype min_occurrences: int
     :ivar max_occurrences: Maximum number of requirement matches allowed
-    :ivar properties: Dict of :class:`Parameter`
+    :vartype min_occurrences: int
+    :ivar occurrences: Actual number of requirement matches
+    :vartype occurrences: int
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
     """
 
     __tablename__ = 'capability'
 
     @declared_attr
+    def capability_template(cls):
+        return cls.many_to_one_relationship('capability_template')
+
+    @declared_attr
     def type(cls):
         return cls.many_to_one_relationship('type')
 
-    min_occurrences = Column(Integer, default=None) # optional
-    max_occurrences = Column(Integer, default=None) # optional
+    min_occurrences = Column(Integer, default=None)
+    max_occurrences = Column(Integer, default=None)
     occurrences = Column(Integer, default=0)
 
     @declared_attr
@@ -945,10 +1058,6 @@ class CapabilityBase(InstanceModelMixin):
         return cls.many_to_many_relationship('parameter', table_prefix='properties',
                                              dict_key='name')
 
-    @declared_attr
-    def capability_template(cls):
-        return cls.many_to_one_relationship('capability_template')
-
     # region foreign_keys
 
     __private_fields__ = ['capability_fk',
@@ -1017,15 +1126,27 @@ class InterfaceBase(InstanceModelMixin):
     
     Usually an instance of :class:`InterfaceTemplate`.
 
-    :ivar name: Name
-    :ivar description: Description
-    :ivar inputs: Dict of :class:`Parameter`
-    :ivar operations: Dict of :class:`Operation`
+    :ivar name: Name (unique for the node, group, or relationship)
+    :vartype name: basestring
+    :ivar interface_template: Template from which this interface was instantiated (optional)
+    :vartype interface_template: :class:`InterfaceTemplate`
+    :ivar type: Interface type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: string
+    :ivar inputs: Parameters that can be used by all operations in the interface
+    :vartype inputs: {basestring: :class:`Parameter`}
+    :ivar operations: Operations
+    :vartype operations: {basestring: :class:`Operation`}
     """
 
     __tablename__ = 'interface'
 
     @declared_attr
+    def interface_template(cls):
+        return cls.many_to_one_relationship('interface_template')
+
+    @declared_attr
     def type(cls):
         return cls.many_to_one_relationship('type')
 
@@ -1040,10 +1161,6 @@ class InterfaceBase(InstanceModelMixin):
     def operations(cls):
         return cls.one_to_many_relationship('operation', dict_key='name')
 
-    @declared_attr
-    def interface_template(cls):
-        return cls.many_to_one_relationship('interface_template')
-
     # region foreign_keys
 
     __private_fields__ = ['type_fk',
@@ -1112,37 +1229,51 @@ class OperationBase(InstanceModelMixin):
     
     Might be an instance of :class:`OperationTemplate`.
 
-    :ivar name: Name
-    :ivar description: Description
-    :ivar implementation: Implementation string (interpreted by the orchestrator)
-    :ivar dependencies: List of strings (interpreted by the orchestrator)
-    :ivar executor: Executor string (interpreted by the orchestrator)
+    :ivar name: Name (unique for the interface or service)
+    :vartype name: basestring
+    :ivar operation_template: Template from which this operation was instantiated (optional)
+    :vartype operation_template: :class:`OperationTemplate`
+    :ivar description: Human-readable description
+    :vartype description: string
+    :ivar plugin: Associated plugin
+    :vartype plugin: :class:`Plugin`
+    :ivar implementation: Implementation string (interpreted by the plugin)
+    :vartype implementation: basestring
+    :ivar dependencies: Dependency strings (interpreted by the plugin)
+    :vartype dependencies: [basestring]
+    :ivar inputs: Parameters that can be used by this operation
+    :vartype inputs: {basestring: :class:`Parameter`}
+    :ivar executor: Executor name
+    :vartype executor: basestring
     :ivar max_retries: Maximum number of retries allowed in case of failure
-    :ivar retry_interval: Interval between retries
-    :ivar inputs: Dict of :class:`Parameter`
+    :vartype max_retries: int
+    :ivar retry_interval: Interval between retries (in seconds)
+    :vartype retry_interval: int
     """
 
     __tablename__ = 'operation'
 
+    @declared_attr
+    def operation_template(cls):
+        return cls.many_to_one_relationship('operation_template')
+
     description = Column(Text)
+
+    @declared_attr
+    def plugin(cls):
+        return cls.one_to_one_relationship('plugin')
+
     implementation = Column(Text)
     dependencies = Column(modeling_types.StrictList(item_cls=basestring))
-    executor = Column(Text)
-    max_retries = Column(Integer)
-    retry_interval = Column(Integer)
 
     @declared_attr
     def inputs(cls):
         return cls.many_to_many_relationship('parameter', table_prefix='inputs',
                                              dict_key='name')
 
-    @declared_attr
-    def plugin(cls):
-        return cls.one_to_one_relationship('plugin')
-
-    @declared_attr
-    def operation_template(cls):
-        return cls.many_to_one_relationship('operation_template')
+    executor = Column(Text)
+    max_retries = Column(Integer)
+    retry_interval = Column(Integer)
 
     # region foreign_keys
 
@@ -1220,23 +1351,37 @@ class ArtifactBase(InstanceModelMixin):
     
     Usually an instance of :class:`ArtifactTemplate`.
 
-    :ivar name: Name
-    :ivar description: Description
+    :ivar name: Name (unique for the node)
+    :vartype name: basestring
+    :ivar artifact_template: Template from which this artifact was instantiated (optional)
+    :vartype artifact_template: :class:`ArtifactTemplate`
+    :ivar type: Artifact type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: string
     :ivar source_path: Source path (CSAR or repository)
+    :vartype source_path: basestring
     :ivar target_path: Path at destination machine
+    :vartype target_path: basestring
     :ivar repository_url: Repository URL
-    :ivar repository_credential: Dict of string
-    :ivar properties: Dict of :class:`Parameter`
+    :vartype repository_path: basestring
+    :ivar repository_credential: Credentials for accessing the repository
+    :vartype repository_credential: {basestring: basestring}
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
     """
 
     __tablename__ = 'artifact'
 
     @declared_attr
+    def artifact_template(cls):
+        return cls.many_to_one_relationship('artifact_template')
+
+    @declared_attr
     def type(cls):
         return cls.many_to_one_relationship('type')
 
     description = Column(Text)
-    type_name = Column(Text)
     source_path = Column(Text)
     target_path = Column(Text)
     repository_url = Column(Text)
@@ -1247,10 +1392,6 @@ class ArtifactBase(InstanceModelMixin):
         return cls.many_to_many_relationship('parameter', table_prefix='properties',
                                              dict_key='name')
 
-    @declared_attr
-    def artifact_template(cls):
-        return cls.many_to_one_relationship('artifact_template')
-
     # region foreign_keys
 
     __private_fields__ = ['type_fk',

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index 1f2d1f3..aec7aa0 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -17,7 +17,6 @@
 
 from __future__ import absolute_import  # so we can import standard 'types'
 
-from copy import deepcopy
 from types import FunctionType
 from datetime import datetime
 
@@ -40,27 +39,61 @@ from . import (
 
 class ServiceTemplateBase(TemplateModelMixin):
     """
-    A service template is a normalized blueprint from which :class:`ServiceInstance` instances can
-    be created.
+    A service template is a source for creating :class:`Service` instances.
 
     It is usually created by various DSL parsers, such as ARIA's TOSCA extension. However, it can
     also be created programmatically.
 
+    :ivar name: Name (unique for this ARIA installation)
+    :vartype name: basestring
     :ivar description: Human-readable description
-    :vartype description: string
-    :ivar meta_data: Dict of :class:`Metadata`
-    :ivar node_templates: List of :class:`NodeTemplate`
-    :ivar group_templates: List of :class:`GroupTemplate`
-    :ivar policy_templates: List of :class:`PolicyTemplate`
-    :ivar substitution_template: :class:`SubstitutionTemplate`
-    :ivar inputs: Dict of :class:`Parameter`
-    :ivar outputs: Dict of :class:`Parameter`
-    :ivar operation_templates: Dict of :class:`OperationTemplate`
+    :vartype description: basestring
+    :ivar main_file_name: Filename of CSAR or YAML file from which this service template was parsed
+    :vartype main_file_name: basestring
+    :ivar meta_data: Custom annotations
+    :vartype meta_data: {basestring: :class:`Metadata`}
+    :ivar node_templates: Templates for creating nodes
+    :vartype node_templates: [:class:`NodeTemplate`]
+    :ivar group_templates: Templates for creating groups
+    :vartype group_templates: [:class:`GroupTemplate`]
+    :ivar policy_templates: Templates for creating policies
+    :vartype policy_templates: [:class:`PolicyTemplate`]
+    :ivar substitution_template: The entire service can appear as a node
+    :vartype substitution_template: :class:`SubstitutionTemplate`
+    :ivar inputs: Externally provided parameters
+    :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 node_types: Base for the node type hierarchy
+    :vartype node_types: :class:`Type`
+    :ivar group_types: Base for the group type hierarchy
+    :vartype group_types: :class:`Type`
+    :ivar policy_types: Base for the policy type hierarchy
+    :vartype policy_types: :class:`Type`
+    :ivar relationship_types: Base for the relationship type hierarchy
+    :vartype relationship_types: :class:`Type`
+    :ivar capability_types: Base for the capability type hierarchy
+    :vartype capability_types: :class:`Type`
+    :ivar interface_types: Base for the interface type hierarchy
+    :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 created_at: Creation timestamp
+    :vartype created_at: :class:`datetime.datetime`
+    :ivar updated_at: Update timestamp
+    :vartype updated_at: :class:`datetime.datetime`
     """
 
     __tablename__ = 'service_template'
 
     description = Column(Text)
+    main_file_name = Column(Text)
 
     @declared_attr
     def meta_data(cls):
@@ -98,6 +131,10 @@ class ServiceTemplateBase(TemplateModelMixin):
         return cls.one_to_many_relationship('operation_template', dict_key='name')
 
     @declared_attr
+    def plugins(cls):
+        return cls.one_to_many_relationship('plugin')
+
+    @declared_attr
     def node_types(cls):
         return cls.one_to_one_relationship('type', key='node_type_fk', backreference='')
 
@@ -106,40 +143,42 @@ class ServiceTemplateBase(TemplateModelMixin):
         return cls.one_to_one_relationship('type', key='group_type_fk', backreference='')
 
     @declared_attr
-    def capability_types(cls):
-        return cls.one_to_one_relationship('type', key='capability_type_fk', backreference='')
+    def policy_types(cls):
+        return cls.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='')
 
     @declared_attr
-    def policy_types(cls):
-        return cls.one_to_one_relationship('type', key='policy_type_fk', backreference='')
-
-    @declared_attr
-    def artifact_types(cls):
-        return cls.one_to_one_relationship('type', key='artifact_type_fk', backreference='')
+    def capability_types(cls):
+        return cls.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='')
 
+    @declared_attr
+    def artifact_types(cls):
+        return cls.one_to_one_relationship('type', key='artifact_type_fk', backreference='')
+
     # region orchestration
 
     created_at = Column(DateTime, nullable=False, index=True)
     updated_at = Column(DateTime)
-    main_file_name = Column(Text)
-
-    @declared_attr
-    def plugins(cls):
-        return cls.one_to_many_relationship('plugin', dict_key='name')
 
     # endregion
 
     # region foreign keys
 
-    __private_fields__ = ['substitution_template_fk']
+    __private_fields__ = ['substitution_template_fk',
+                          'node_type_fk',
+                          'group_type_fk',
+                          'policy_type_fk',
+                          'relationship_type_fk',
+                          'capability_type_fk',
+                          'interface_type_fk',
+                          'artifact_type_fk']
 
     # ServiceTemplate one-to-one to SubstitutionTemplate
     @declared_attr
@@ -158,7 +197,7 @@ class ServiceTemplateBase(TemplateModelMixin):
 
     # ServiceTemplate one-to-one to Type
     @declared_attr
-    def capability_type_fk(cls):
+    def policy_type_fk(cls):
         return cls.foreign_key('type', nullable=True)
 
     # ServiceTemplate one-to-one to Type
@@ -168,17 +207,17 @@ class ServiceTemplateBase(TemplateModelMixin):
 
     # ServiceTemplate one-to-one to Type
     @declared_attr
-    def policy_type_fk(cls):
+    def capability_type_fk(cls):
         return cls.foreign_key('type', nullable=True)
 
     # ServiceTemplate one-to-one to Type
     @declared_attr
-    def artifact_type_fk(cls):
+    def interface_type_fk(cls):
         return cls.foreign_key('type', nullable=True)
 
     # ServiceTemplate one-to-one to Type
     @declared_attr
-    def interface_type_fk(cls):
+    def artifact_type_fk(cls):
         return cls.foreign_key('type', nullable=True)
 
     # endregion
@@ -215,18 +254,18 @@ class ServiceTemplateBase(TemplateModelMixin):
         return collections.OrderedDict((
             ('node_types', formatting.as_raw(self.node_types)),
             ('group_types', formatting.as_raw(self.group_types)),
-            ('capability_types', formatting.as_raw(self.capability_types)),
-            ('relationship_types', formatting.as_raw(self.relationship_types)),
             ('policy_types', formatting.as_raw(self.policy_types)),
-            ('artifact_types', formatting.as_raw(self.artifact_types)),
-            ('interface_types', formatting.as_raw(self.interface_types))))
+            ('relationship_types', formatting.as_raw(self.relationship_types)),
+            ('capability_types', formatting.as_raw(self.capability_types)),
+            ('interface_types', formatting.as_raw(self.interface_types)),
+            ('artifact_types', formatting.as_raw(self.artifact_types))))
 
     def instantiate(self, context, container):
         from . import models
         now = datetime.now()
         service = models.Service(created_at=now,
                                  updated_at=now,
-                                 description=deepcopy_with_locators(self.description),
+                                 description=utils.deepcopy_with_locators(self.description),
                                  service_template=self)
         #service.name = '{0}_{1}'.format(self.name, service.id)
 
@@ -267,6 +306,20 @@ class ServiceTemplateBase(TemplateModelMixin):
         utils.validate_dict_values(context, self.inputs)
         utils.validate_dict_values(context, self.outputs)
         utils.validate_dict_values(context, self.operation_templates)
+        if self.node_types is not None:
+            self.node_types.validate(context)
+        if self.group_types is not None:
+            self.group_types.validate(context)
+        if self.policy_types is not None:
+            self.policy_types.validate(context)
+        if self.relationship_types is not None:
+            self.relationship_types.validate(context)
+        if self.capability_types is not None:
+            self.capability_types.validate(context)
+        if self.interface_types is not None:
+            self.interface_types.validate(context)
+        if self.artifact_types is not None:
+            self.artifact_types.validate(context)
 
     def coerce_values(self, context, container, report_issues):
         utils.coerce_dict_values(context, container, self.meta_data, report_issues)
@@ -283,7 +336,6 @@ class ServiceTemplateBase(TemplateModelMixin):
         if self.description is not None:
             console.puts(context.style.meta(self.description))
         utils.dump_dict_values(context, self.meta_data, 'Metadata')
-
         for node_template in self.node_templates:
             node_template.dump(context)
         for group_template in self.group_templates:
@@ -327,17 +379,33 @@ class NodeTemplateBase(TemplateModelMixin):
     """
     A template for creating zero or more :class:`Node` instances.
 
-    :ivar name: Name (will be used as a prefix for node IDs)
-    :ivar description: Description
-    :ivar default_instances: Default number nodes that will appear in the deployment plan
-    :ivar min_instances: Minimum number nodes that will appear in the deployment plan
-    :ivar max_instances: Maximum number nodes that will appear in the deployment plan
-    :ivar properties: Dict of :class:`Parameter`
-    :ivar interface_templates: Dict of :class:`InterfaceTemplate`
-    :ivar artifact_templates: Dict of :class:`ArtifactTemplate`
-    :ivar capability_templates: Dict of :class:`CapabilityTemplate`
-    :ivar requirement_templates: List of :class:`RequirementTemplate`
-    :ivar target_node_template_constraints: List of :class:`FunctionType`
+    :ivar name: Name (unique for this service template; will usually be used as a prefix for node
+                names)
+    :vartype name: basestring
+    :ivar type: Node type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: basestring
+    :ivar default_instances: Default number nodes that will appear in the service
+    :vartype default_instances: int
+    :ivar min_instances: Minimum number nodes that will appear in the service
+    :vartype min_instances: int
+    :ivar max_instances: Maximum number nodes that will appear in the service
+    :vartype max_instances: int
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
+    :ivar interface_templates: Bundles of operations
+    :vartype interface_templates: {basestring: :class:`InterfaceTemplate`}
+    :ivar artifact_templates: Associated files
+    :vartype artifact_templates: {basestring: :class:`ArtifactTemplate`}
+    :ivar capability_templates: Exposed capabilities
+    :vartype capability_templates: {basestring: :class:`CapabilityTemplate`}
+    :ivar requirement_templates: Potential relationships with other nodes
+    :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`}
     """
 
     __tablename__ = 'node_template'
@@ -350,7 +418,6 @@ class NodeTemplateBase(TemplateModelMixin):
     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))
 
     @declared_attr
     def properties(cls):
@@ -372,15 +439,14 @@ class NodeTemplateBase(TemplateModelMixin):
     @declared_attr
     def requirement_templates(cls):
         return cls.one_to_many_relationship('requirement_template',
-                                            foreign_key='node_template_fk')
+                                            foreign_key='node_template_fk',
+                                            backreference='node_template')
 
-    # region orchestration
+    target_node_template_constraints = Column(modeling_types.StrictList(FunctionType))
 
     @declared_attr
     def plugins(cls):
-        return cls.many_to_many_relationship('plugin', dict_key='name')
-
-    # endregion
+        return cls.many_to_many_relationship('plugin')
 
     # region foreign_keys
 
@@ -426,6 +492,7 @@ class NodeTemplateBase(TemplateModelMixin):
         name = context.modeling.generate_node_id(self.name)
         node = models.Node(name=name,
                            type=self.type,
+                           description=utils.deepcopy_with_locators(self.description),
                            state='',
                            node_template=self)
         utils.instantiate_dict(context, node, node.properties, self.properties)
@@ -469,15 +536,22 @@ class NodeTemplateBase(TemplateModelMixin):
 
 class GroupTemplateBase(TemplateModelMixin):
     """
-    A template for creating zero or more :class:`Group` instances.
+    A template for creating a :class:`Group` instance.
 
-    Groups are logical containers for zero or more nodes that allow applying zero or more
-    :class:`GroupPolicy` instances to the nodes together.
+    Groups are logical containers for zero or more nodes.
 
-    :ivar name: Name (will be used as a prefix for group IDs)
-    :ivar description: Description
-    :ivar properties: Dict of :class:`Parameter`
-    :ivar interface_templates: Dict of :class:`InterfaceTemplate`
+    :ivar name: Name (unique for this service template)
+    :vartype name: basestring
+    :ivar type: Group type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: basestring
+    :ivar node_templates: All nodes instantiated by these templates will be members of the group
+    :vartype node_templates: [:class:`NodeTemplate`]
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
+    :ivar interface_templates: Bundles of operations
+    :vartype interface_templates: {basestring: :class:`InterfaceTemplate`}
     """
 
     __tablename__ = 'group_template'
@@ -489,6 +563,10 @@ class GroupTemplateBase(TemplateModelMixin):
     description = Column(Text)
 
     @declared_attr
+    def node_templates(cls):
+        return cls.many_to_many_relationship('node_template')
+
+    @declared_attr
     def properties(cls):
         return cls.many_to_many_relationship('parameter', table_prefix='properties',
                                              dict_key='name')
@@ -497,10 +575,6 @@ class GroupTemplateBase(TemplateModelMixin):
     def interface_templates(cls):
         return cls.one_to_many_relationship('interface_template', dict_key='name')
 
-    @declared_attr
-    def node_templates(cls):
-        return cls.many_to_many_relationship('node_template')
-
     # region foreign keys
 
     __private_fields__ = ['type_fk',
@@ -531,6 +605,7 @@ class GroupTemplateBase(TemplateModelMixin):
         from . import models
         group = models.Group(name=self.name,
                              type=self.type,
+                             description=utils.deepcopy_with_locators(self.description),
                              group_template=self)
         utils.instantiate_dict(context, self, group.properties, self.properties)
         utils.instantiate_dict(context, self, group.interfaces, self.interface_templates)
@@ -565,9 +640,18 @@ class PolicyTemplateBase(TemplateModelMixin):
     Policies can be applied to zero or more :class:`NodeTemplate` or :class:`GroupTemplate`
     instances.
 
-    :ivar name: Name
-    :ivar description: Description
-    :ivar properties: Dict of :class:`Parameter`
+    :ivar name: Name (unique for this service template)
+    :vartype name: basestring
+    :ivar type: Policy type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: basestring
+    :ivar node_templates: Policy will be enacted on all nodes instantiated by these templates
+    :vartype node_templates: [:class:`NodeTemplate`]
+    :ivar group_templates: Policy will be enacted on all nodes in these groups
+    :vartype group_templates: [:class:`GroupTemplate`]
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
     """
 
     __tablename__ = 'policy_template'
@@ -579,11 +663,6 @@ class PolicyTemplateBase(TemplateModelMixin):
     description = Column(Text)
 
     @declared_attr
-    def properties(cls):
-        return cls.many_to_many_relationship('parameter', table_prefix='properties',
-                                             dict_key='name')
-
-    @declared_attr
     def node_templates(cls):
         return cls.many_to_many_relationship('node_template')
 
@@ -591,6 +670,11 @@ class PolicyTemplateBase(TemplateModelMixin):
     def group_templates(cls):
         return cls.many_to_many_relationship('group_template')
 
+    @declared_attr
+    def properties(cls):
+        return cls.many_to_many_relationship('parameter', table_prefix='properties',
+                                             dict_key='name')
+
     # region foreign keys
 
     __private_fields__ = ['type_fk',
@@ -620,6 +704,7 @@ class PolicyTemplateBase(TemplateModelMixin):
         from . import models
         policy = models.Policy(name=self.name,
                                type=self.type,
+                               description=utils.deepcopy_with_locators(self.description),
                                policy_template=self)
         utils.instantiate_dict(context, self, policy.properties, self.properties)
         if self.node_templates:
@@ -655,7 +740,10 @@ class SubstitutionTemplateBase(TemplateModelMixin):
     """
     Used to substitute a single node for the entire deployment.
 
-    :ivar mappings: Dict of :class:` SubstitutionTemplateMapping`
+    :ivar node_type: Exposed node type
+    :vartype node_type: :class:`Type`
+    :ivar mappings: Requirement and capability mappings
+    :vartype mappings: {basestring: :class:`SubstitutionTemplateMapping`}
     """
 
     __tablename__ = 'substitution_template'
@@ -708,8 +796,17 @@ class SubstitutionTemplateBase(TemplateModelMixin):
 class SubstitutionTemplateMappingBase(TemplateModelMixin):
     """
     Used by :class:`SubstitutionTemplate` to map a capability or a requirement to a node.
+    
+    Only one of `capability_template` and `requirement_template` can be set.
 
     :ivar name: Exposed capability or requirement name
+    :vartype name: basestring
+    :ivar node_template: Node template
+    :vartype node_template: :class:`NodeTemplate`
+    :ivar capability_template: Capability template in the node template
+    :vartype capability_template: :class:`CapabilityTemplate`
+    :ivar requirement_template: Requirement template in the node template
+    :vartype requirement_template: :class:`RequirementTemplate`
     """
 
     __tablename__ = 'substitution_template_mapping'
@@ -807,10 +904,20 @@ class RequirementTemplateBase(TemplateModelMixin):
     Requirements may optionally contain a :class:`RelationshipTemplate` that will be created between
     the nodes.
 
-    :ivar name: Name
-    :ivar target_node_template_constraints: List of :class:`FunctionType`
-    :ivar target_capability_name: Name of capability in target node
-    :ivar relationship_template: :class:`RelationshipTemplate`
+    :ivar name: Name (a node template can have multiple requirements with the same name)
+    :vartype name: basestring
+    :ivar target_node_type: Required node type (optional)
+    :vartype target_node_type: :class:`Type`
+    :ivar target_node_template: Required node template (optional)
+    :vartype target_node_template: :class:`NodeTemplate`
+    :ivar target_capability_type: Required capability type (optional)
+    :vartype target_capability_type: :class:`Type`
+    :ivar target_capability_name: Name of capability in target node (optional)
+    :vartype target_capability_name: basestring
+    :ivar target_node_template_constraints: Constraints for filtering relationship targets
+    :vartype target_node_template_constraints: [:class:`FunctionType`]
+    :ivar relationship_template: Template for relationships (optional)
+    :vartype relationship_template: :class:`RelationshipTemplate`
     """
 
     __tablename__ = 'requirement_template'
@@ -829,8 +936,8 @@ class RequirementTemplateBase(TemplateModelMixin):
         return cls.one_to_one_relationship('type', key='target_capability_type_fk',
                                            backreference='')
 
-    target_node_template_constraints = Column(modeling_types.StrictList(FunctionType))
     target_capability_name = Column(Text)
+    target_node_template_constraints = Column(modeling_types.StrictList(FunctionType))
 
     @declared_attr
     def relationship_template(cls):
@@ -972,10 +1079,21 @@ class RelationshipTemplateBase(TemplateModelMixin):
     """
     Optional addition to a :class:`RequirementTemplate` in :class:`NodeTemplate` that can be applied
     when the requirement is matched with a capability.
-
-    :ivar description: Description
-    :ivar properties: Dict of :class:`Parameter`
-    :ivar interface_templates: Dict of :class:`InterfaceTemplate`
+    
+    Note that a relationship template here is not equivalent to a relationship template entity in
+    TOSCA. For example, a TOSCA requirement specifying a relationship type instead of a template
+    would still be represented here as a relationship template.
+
+    :ivar name: Name (optional; if present is unique for this service template)
+    :vartype name: basestring
+    :ivar type: Relationship type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: basestring
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
+    :ivar interface_templates: Bundles of operations
+    :vartype interface_templates: {basestring: :class:`InterfaceTemplate`}
     """
 
     __tablename__ = 'relationship_template'
@@ -1052,11 +1170,18 @@ class CapabilityTemplateBase(TemplateModelMixin):
     A capability of a :class:`NodeTemplate`. Nodes expose zero or more capabilities that can be
     matched with :class:`Requirement` instances of other nodes.
 
-    :ivar name: Name
-    :ivar description: Description
+    :ivar name: Name (unique for the node template)
+    :vartype name: basestring
+    :ivar type: Capability type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: basestring
     :ivar min_occurrences: Minimum number of requirement matches required
+    :vartype min_occurrences: int
     :ivar max_occurrences: Maximum number of requirement matches allowed
-    :ivar properties: Dict of :class:`Parameter`
+    :vartype min_occurrences: int
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
     """
 
     __tablename__ = 'capability_template'
@@ -1170,10 +1295,16 @@ class InterfaceTemplateBase(TemplateModelMixin):
     """
     A typed set of :class:`OperationTemplate`.
 
-    :ivar name: Name
-    :ivar description: Description
-    :ivar inputs: Dict of :class:`Parameter`
-    :ivar operation_templates: Dict of :class:`OperationTemplate`
+    :ivar name: Name (unique for the node, group, or relationship template)
+    :vartype name: basestring
+    :ivar type: Interface type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: basestring
+    :ivar inputs: Parameters that can be used by all operations in the interface
+    :vartype inputs: {basestring: :class:`Parameter`}
+    :ivar operation_templates: Operations
+    :vartype operation_templates: {basestring: :class:`OperationTemplate`}
     """
 
     __tablename__ = 'interface_template'
@@ -1234,8 +1365,8 @@ class InterfaceTemplateBase(TemplateModelMixin):
     def instantiate(self, context, container):
         from . import models
         interface = models.Interface(name=self.name,
-                                     description=deepcopy_with_locators(self.description),
                                      type=self.type,
+                                     description=utils.deepcopy_with_locators(self.description),
                                      interface_template=self)
         utils.instantiate_dict(context, container, interface.inputs, self.inputs)
         utils.instantiate_dict(context, container, interface.operations, self.operation_templates)
@@ -1263,34 +1394,44 @@ class OperationTemplateBase(TemplateModelMixin):
     """
     An operation in a :class:`InterfaceTemplate`.
 
-    :ivar name: Name
-    :ivar description: Description
-    :ivar implementation: Implementation string (interpreted by the orchestrator)
-    :ivar dependencies: List of strings (interpreted by the orchestrator)
-    :ivar executor: Executor string (interpreted by the orchestrator)
+    Operations are executed by an associated :class:`Plugin` 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 implementation: Implementation string (interpreted by the plugin)
+    :vartype implementation: basestring
+    :ivar dependencies: Dependency strings (interpreted by the plugin)
+    :vartype dependencies: [basestring]
+    :ivar inputs: Parameters that can be used by this operation
+    :vartype inputs: {basestring: :class:`Parameter`}
+    :ivar executor: Executor name
+    :vartype executor: basestring
     :ivar max_retries: Maximum number of retries allowed in case of failure
-    :ivar retry_interval: Interval between retries
-    :ivar inputs: Dict of :class:`Parameter`
+    :vartype max_retries: int
+    :ivar retry_interval: Interval between retries (in seconds)
+    :vartype retry_interval: int
     """
 
     __tablename__ = 'operation_template'
 
     description = Column(Text)
+
+    @declared_attr
+    def plugin(cls):
+        return cls.one_to_one_relationship('plugin')
+
     implementation = Column(Text)
     dependencies = Column(modeling_types.StrictList(item_cls=basestring))
-    executor = Column(Text)
-    max_retries = Column(Integer)
-    retry_interval = Column(Integer)
 
     @declared_attr
     def inputs(cls):
         return cls.many_to_many_relationship('parameter', table_prefix='inputs',
                                              dict_key='name')
 
-    @declared_attr
-    def plugin(cls):
-        return cls.one_to_one_relationship('plugin')
-
     executor = Column(Text)
     max_retries = Column(Integer)
     retry_interval = Column(Integer)
@@ -1333,7 +1474,7 @@ class OperationTemplateBase(TemplateModelMixin):
     def instantiate(self, context, container):
         from . import models
         operation = models.Operation(name=self.name,
-                                     description=deepcopy_with_locators(self.description),
+                                     description=utils.deepcopy_with_locators(self.description),
                                      implementation=self.implementation,
                                      dependencies=self.dependencies,
                                      plugin=self.plugin,
@@ -1375,13 +1516,22 @@ class ArtifactTemplateBase(TemplateModelMixin):
     """
     A file associated with a :class:`NodeTemplate`.
 
-    :ivar name: Name
-    :ivar description: Description
+    :ivar name: Name (unique for the node template)
+    :vartype name: basestring
+    :ivar type: Artifact type
+    :vartype type: :class:`Type`
+    :ivar description: Human-readable description
+    :vartype description: basestring
     :ivar source_path: Source path (CSAR or repository)
+    :vartype source_path: basestring
     :ivar target_path: Path at destination machine
+    :vartype target_path: basestring
     :ivar repository_url: Repository URL
-    :ivar repository_credential: Dict of string
-    :ivar properties: Dict of :class:`Parameter`
+    :vartype repository_path: basestring
+    :ivar repository_credential: Credentials for accessing the repository
+    :vartype repository_credential: {basestring: basestring}
+    :ivar properties: Associated parameters
+    :vartype properties: {basestring: :class:`Parameter`}
     """
 
     __tablename__ = 'artifact_template'
@@ -1434,8 +1584,8 @@ class ArtifactTemplateBase(TemplateModelMixin):
         from . import models
         artifact = models.Artifact(name=self.name,
                                    type=self.type,
+                                   description=utils.deepcopy_with_locators(self.description),
                                    source_path=self.source_path,
-                                   description=deepcopy_with_locators(self.description),
                                    target_path=self.target_path,
                                    repository_url=self.repository_url,
                                    repository_credential=self.repository_credential,
@@ -1465,35 +1615,3 @@ class ArtifactTemplateBase(TemplateModelMixin):
                 console.puts('Repository credential: {0}'.format(
                     context.style.literal(self.repository_credential)))
             utils.dump_dict_values(context, self.properties, 'Properties')
-
-
-def deepcopy_with_locators(value):
-    """
-    Like :code:`deepcopy`, but also copies over locators.
-    """
-
-    res = deepcopy(value)
-    copy_locators(res, value)
-    return res
-
-
-def copy_locators(target, source):
-    """
-    Copies over :code:`_locator` for all elements, recursively.
-
-    Assumes that target and source have exactly the same list/dict structure.
-    """
-
-    locator = getattr(source, '_locator', None)
-    if locator is not None:
-        try:
-            setattr(target, '_locator', locator)
-        except AttributeError:
-            pass
-
-    if isinstance(target, list) and isinstance(source, list):
-        for i, _ in enumerate(target):
-            copy_locators(target[i], source[i])
-    elif isinstance(target, dict) and isinstance(source, dict):
-        for k, v in target.items():
-            copy_locators(v, source[k])

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/aria/modeling/utils.py
----------------------------------------------------------------------
diff --git a/aria/modeling/utils.py b/aria/modeling/utils.py
index a2f0bfc..a071d69 100644
--- a/aria/modeling/utils.py
+++ b/aria/modeling/utils.py
@@ -13,6 +13,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from copy import deepcopy
+
 from ..parser.exceptions import InvalidValueError
 from ..parser.presentation import Value
 from ..utils.collections import OrderedDict
@@ -109,6 +111,40 @@ def dump_interfaces(context, interfaces, name='Interfaces'):
             interface.dump(context)
 
 
+
+
+def deepcopy_with_locators(value):
+    """
+    Like :code:`deepcopy`, but also copies over locators.
+    """
+
+    res = deepcopy(value)
+    copy_locators(res, value)
+    return res
+
+
+def copy_locators(target, source):
+    """
+    Copies over :code:`_locator` for all elements, recursively.
+
+    Assumes that target and source have exactly the same list/dict structure.
+    """
+
+    locator = getattr(source, '_locator', None)
+    if locator is not None:
+        try:
+            setattr(target, '_locator', locator)
+        except AttributeError:
+            pass
+
+    if isinstance(target, list) and isinstance(source, list):
+        for i, _ in enumerate(target):
+            copy_locators(target[i], source[i])
+    elif isinstance(target, dict) and isinstance(source, dict):
+        for k, v in target.items():
+            copy_locators(v, source[k])
+
+
 class classproperty(object):                                                                        # pylint: disable=invalid-name
     def __init__(self, f):
         self._func = f

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/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 959f3c4..0206e03 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -64,14 +64,14 @@ def create_service_template_model(context): # pylint: disable=too-many-locals,to
     create_types(context,
                  model.capability_types,
                  context.presentation.get('service_template', 'capability_types'))
-    model.artifact_types = Type(variant='artifact')
-    create_types(context,
-                 model.artifact_types,
-                 context.presentation.get('service_template', 'artifact_types'))
     model.interface_types = Type(variant='interface')
     create_types(context,
                  model.interface_types,
                  context.presentation.get('service_template', 'interface_types'))
+    model.artifact_types = Type(variant='artifact')
+    create_types(context,
+                 model.artifact_types,
+                 context.presentation.get('service_template', 'artifact_types'))
 
     # Topology template
     topology_template = context.presentation.get('service_template', 'topology_template')
@@ -86,7 +86,7 @@ def create_service_template_model(context): # pylint: disable=too-many-locals,to
     if policies:
         for policy in policies.itervalues():
             if model.policy_types.get_descendant(policy.type).role == 'plugin':
-                model.plugins[policy._name] = create_plugin_model(context, policy)
+                model.plugins.append(create_plugin_model(context, policy))
 
     # Node templates
     node_templates = context.presentation.get('service_template', 'topology_template',
@@ -667,7 +667,11 @@ def parse_implementation_string(context, service_template, implementation):
     if plugin_name == 'execution':
         plugin = None
     else:
-        plugin = service_template.plugins.get(plugin_name)
+        plugin = None
+        for the_plugin in service_template.plugins:
+            if the_plugin.name == plugin_name:
+                plugin = the_plugin
+                break
         if plugin is None:
             raise ValueError('unknown plugin: "{0}"'.format(plugin_name))
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/tests/mock/context.py
----------------------------------------------------------------------
diff --git a/tests/mock/context.py b/tests/mock/context.py
index cf1a32d..3de3133 100644
--- a/tests/mock/context.py
+++ b/tests/mock/context.py
@@ -38,13 +38,13 @@ def simple(tmpdir, inmemory=False, context_kwargs=None):
         api_kwargs=dict(directory=os.path.join(tmpdir, 'resources'))
     )
 
-    service_instance_id = create_simple_topology_two_nodes(model_storage)
+    service_id = create_simple_topology_two_nodes(model_storage)
 
     final_kwargs = dict(
         name='simple_context',
         model_storage=model_storage,
         resource_storage=resource_storage,
-        service_instance_id=service_instance_id,
+        service_id=service_id,
         workflow_name=models.WORKFLOW_NAME,
         task_max_attempts=models.TASK_MAX_ATTEMPTS,
         task_retry_interval=models.TASK_RETRY_INTERVAL

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/tests/mock/models.py
----------------------------------------------------------------------
diff --git a/tests/mock/models.py b/tests/mock/models.py
index 522cc78..3ccd97e 100644
--- a/tests/mock/models.py
+++ b/tests/mock/models.py
@@ -18,107 +18,161 @@ from datetime import datetime
 from aria.modeling import models
 from . import operations
 
-SERVICE_NAME = 'test_service_id'
-SERVICE_TEMPLATE_NAME = 'test_service_template_id'
-WORKFLOW_NAME = 'test_workflow_id'
-EXECUTION_NAME = 'test_execution_id'
+SERVICE_NAME = 'test_service_name'
+SERVICE_TEMPLATE_NAME = 'test_service_template_name'
+WORKFLOW_NAME = 'test_workflow_name'
+EXECUTION_NAME = 'test_execution_name'
 TASK_RETRY_INTERVAL = 1
 TASK_MAX_ATTEMPTS = 1
 
-DEPENDENCY_NODE_NAME = 'dependency_node_template'
-DEPENDENCY_NODE_INSTANCE_NAME = 'dependency_node'
-DEPENDENT_NODE_NAME = 'dependent_node_template'
-DEPENDENT_NODE_INSTANCE_NAME = 'dependent_node'
+DEPENDENCY_NODE_TEMPLATE_NAME = 'dependency_node_template'
+DEPENDENCY_NODE_NAME = 'dependency_node'
+DEPENDENT_NODE_TEMPLATE_NAME = 'dependent_node_template'
+DEPENDENT_NODE_NAME = 'dependent_node'
 
 
-def create_dependency_node_template(service):
-    return models.NodeTemplate(
-        name=DEPENDENCY_NODE_NAME,
-        type=service.service_template.node_types.get_descendant('test_node_type'),
-        default_instances=1,
-        min_instances=1,
-        max_instances=1,
-        service_template_fk=service.service_template.id,
+def create_service_template():
+    now = datetime.now()
+    return models.ServiceTemplate(
+        name=SERVICE_TEMPLATE_NAME,
+        description=None,
+        created_at=now,
+        updated_at=now,
+        main_file_name='main_file_name',
+        node_types=models.Type(variant='node', name='test_node_type'),
+        group_types=models.Type(variant='group', name='test_group_type'),
+        policy_types=models.Type(variant='policy', name='test_policy_type'),
+        relationship_types=models.Type(variant='relationship', name='test_relationship_type'),
+        capability_types=models.Type(variant='capability', name='test_capability_type'),
+        artifact_types=models.Type(variant='artifact', name='test_artifact_type'),
+        interface_types=models.Type(variant='interface', name='test_interface_type')
     )
 
 
-def create_dependency_node(dependency_node_template, service):
-    return models.Node(
-        name=DEPENDENCY_NODE_INSTANCE_NAME,
-        type=dependency_node_template.type,
-        service=service,
-        runtime_properties={'ip': '1.1.1.1'},
-        version=None,
-        node_template=dependency_node_template,
-        state='',
-        scaling_groups=[]
+def create_service(service_template):
+    now = datetime.utcnow()
+    return models.Service(
+        name=SERVICE_NAME,
+        service_template=service_template,
+        description='',
+        created_at=now,
+        updated_at=now,
+        permalink='',
+        scaling_groups={},
     )
 
 
-def create_requirement(source):
-    requirement_template = models.RequirementTemplate(node_template=source)
+def create_dependency_node_template(service_template):
+    the_type = service_template.node_types.get_descendant('test_node_type')
+    
     capability_template = models.CapabilityTemplate(
-        node_template=source,
-        type=source.service_template.capability_types.get_descendant('test_capability_type'))
-    return requirement_template, capability_template
-
-
-def create_relationship(source_instance, target_instance):
-    return models.Relationship(
-        target_node=target_instance,
-        source_node=source_instance,
+        name='capability',
+        type=service_template.capability_types.get_descendant('test_capability_type')
     )
+    
+    node_template = models.NodeTemplate(
+        name=DEPENDENCY_NODE_TEMPLATE_NAME,
+        type=the_type,
+        capability_templates=_dictify(capability_template),
+        default_instances=1,
+        min_instances=1,
+        max_instances=1,
+        service_template=service_template
+    )
+    service_template.node_templates.append(node_template)
+    return node_template
+
 
+def create_dependent_node_template(service_template, dependency_node_template):
+    the_type = service_template.node_types.get_descendant('test_node_type')
 
-def create_dependent_node_template(service, requirement_template, capability_template):
     operation_templates = dict((op, models.OperationTemplate(
         name=op,
         implementation='test'))
                                 for op in operations.NODE_OPERATIONS)
     interface_template = models.InterfaceTemplate(
-        type=service.service_template.interface_types.get_descendant('test_interface_type'),
+        type=service_template.interface_types.get_descendant('test_interface_type'),
         operation_templates=operation_templates)
 
-    return models.NodeTemplate(
-        name=DEPENDENT_NODE_NAME,
-        type=service.service_template.node_types.get_descendant('test_node_type'),
+    requirement_template = models.RequirementTemplate(
+        name='requirement',
+        target_node_template=dependency_node_template
+    )
+
+    node_template = models.NodeTemplate(
+        name=DEPENDENT_NODE_TEMPLATE_NAME,
+        type=the_type,
         default_instances=1,
         min_instances=1,
         max_instances=1,
-        service_template=service.service_template,
         interface_templates=_dictify(interface_template),
         requirement_templates=[requirement_template],
-        capability_templates=_dictify(capability_template),
+        service_template=service_template
+    )
+    service_template.node_templates.append(node_template)
+    return node_template
+
+
+def create_dependency_node(dependency_node_template, service):
+    node = models.Node(
+        name=DEPENDENCY_NODE_NAME,
+        type=dependency_node_template.type,
+        runtime_properties={'ip': '1.1.1.1'},
+        version=None,
+        node_template=dependency_node_template,
+        state='',
+        scaling_groups=[]
     )
+    service.nodes.append(node)
+    return node
 
 
 def create_dependent_node(dependent_node_template, service):
-    return models.Node(
-        name=DEPENDENT_NODE_INSTANCE_NAME,
-        service=service,
+    node = models.Node(
+        name=DEPENDENT_NODE_NAME,
+        type=dependent_node_template.type,
         runtime_properties={},
         version=None,
         node_template=dependent_node_template,
         state='',
         scaling_groups=[],
     )
+    service.nodes.append(node)
+    return node
 
 
-def create_service_template():
-    now = datetime.now()
-    return models.ServiceTemplate(
-        name=SERVICE_TEMPLATE_NAME,
-        description=None,
-        created_at=now,
-        updated_at=now,
-        main_file_name='main_file_name',
-        node_types=models.Type(variant='node', name='test_node_type'),
-        group_types=models.Type(variant='group', name='test_group_type'),
-        policy_types=models.Type(variant='policy', name='test_policy_type'),
-        relationship_types=models.Type(variant='relationship', name='test_relationship_type'),
-        capability_types=models.Type(variant='capability', name='test_capability_type'),
-        artifact_types=models.Type(variant='artifact', name='test_artifact_type'),
-        interface_types=models.Type(variant='interface', name='test_interface_type')
+def create_relationship(source, target):
+    return models.Relationship(
+        source_node=source,
+        target_node=target
+    )
+
+
+def create_interface_template(service_template, operation_name, operation_kwargs=None,
+                              interface_kwargs=None):
+    the_type = service_template.interface_types.get_descendant('test_interface_type')
+    interface_name, operation_name = operation_name.rsplit('.', 1)
+    operation_template = models.OperationTemplate(
+        name=operation_name,
+        **(operation_kwargs or {})
+    )
+    return models.InterfaceTemplate(
+        type=the_type,
+        operation_templates=_dictify(operation_template),
+        name=interface_name,
+        **(interface_kwargs or {})
+    )
+
+
+def create_interface(service, operation_name, operation_kwargs=None, interface_kwargs=None):
+    the_type = service.service_template.interface_types.get_descendant('test_interface_type')
+    interface_name, operation_name = operation_name.rsplit('.', 1)
+    operation = models.Operation(name=operation_name, **(operation_kwargs or {}))
+    return models.Interface(
+        type=the_type,
+        operations=_dictify(operation),
+        name=interface_name,
+        **(interface_kwargs or {})
     )
 
 
@@ -132,20 +186,6 @@ def create_execution(service):
     )
 
 
-def create_service(service_template):
-    now = datetime.utcnow()
-    return models.Service(
-        name=SERVICE_NAME,
-        service_template=service_template,
-        description='',
-        created_at=now,
-        updated_at=now,
-        workflows={},
-        permalink='',
-        scaling_groups={},
-    )
-
-
 def create_plugin(package_name='package', package_version='0.1'):
     return models.Plugin(
         archive_name='archive_name',
@@ -162,30 +202,5 @@ def create_plugin(package_name='package', package_version='0.1'):
     )
 
 
-def create_interface_template(operation_name, operation_kwargs=None, interface_kwargs=None):
-    operation_template = models.OperationTemplate(
-        name=operation_name,
-        **(operation_kwargs or {})
-
-    )
-    return models.InterfaceTemplate(
-        operation_templates=_dictify(operation_template),
-        name=operation_name.rsplit('.', 1)[0],
-        **(interface_kwargs or {})
-    )
-
-
-def create_interface(operation_name,
-                     operation_kwargs=None,
-                     interface_kwargs=None,
-                     edge=None):
-    operation = models.Operation(name=operation_name, **(operation_kwargs or {}))
-    interface_name = operation_name.rsplit('.', 1)[0]
-    return models.Interface(operations=_dictify(operation),
-                            name=interface_name,
-                            edge=edge,
-                            **(interface_kwargs or {}))
-
-
 def _dictify(item):
     return dict(((item.name, item),))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/tests/mock/topology.py
----------------------------------------------------------------------
diff --git a/tests/mock/topology.py b/tests/mock/topology.py
index b511ee3..b702783 100644
--- a/tests/mock/topology.py
+++ b/tests/mock/topology.py
@@ -20,67 +20,55 @@ from . import models
 
 def create_simple_topology_single_node(model_storage, create_operation):
     service_template = models.create_service_template()
-    model_storage.service_template.put(service_template)
 
     service = models.create_service(service_template)
-    model_storage.service.put(service)
 
-    node_template = models.create_dependency_node_template(service)
-    node_template.interface_templates = [models.create_interface_template(
-        'tosca.interfaces.node.lifecycle.Standard.create',
+    node_template = models.create_dependency_node_template(service_template)
+    interface_template = models.create_interface_template(
+        service_template,
+        'Standard.create',
         operation_kwargs=dict(
             implementation=create_operation,
-            inputs=[aria_models.Parameter(name='key', value='create', type_name='string'),
-                    aria_models.Parameter(name='value', value=True, type_name='boolean')]
-        )
-    )]
-    model_storage.node_template.put(node_template)
+            inputs={'key': aria_models.Parameter(name='key', value='create', type_name='string'),
+                    'value': aria_models.Parameter(name='value', value=True, type_name='boolean')})
+    )
+    node_template.interface_templates[interface_template.name] = interface_template
 
     node = models.create_dependency_node(node_template, service)
-    node.interfaces = [models.create_interface(
-        'tosca.interfaces.node.lifecycle.Standard.create',
+    interface = models.create_interface(
+        service,
+        'Standard.create',
         operation_kwargs=dict(
             implementation=create_operation,
-            inputs=[aria_models.Parameter(name='key', value='create', type_name='string'),
-                    aria_models.Parameter(name='value', value=True, type_name='boolean')])
-    )]
-    model_storage.node.put(node)
+            inputs={'key': aria_models.Parameter(name='key', value='create', type_name='string'),
+                    'value': aria_models.Parameter(name='value', value=True, type_name='boolean')})
+    )
+    node.interfaces[interface.name] = interface
+
+    model_storage.service_template.put(service_template)
+    model_storage.service.put(service)
 
 
 def create_simple_topology_two_nodes(model_storage):
-    blueprint = models.create_service_template()
-    model_storage.service_template.put(blueprint)
-    deployment = models.create_service(blueprint)
-    model_storage.service.put(deployment)
-
-    #################################################################################
-    # Creating a simple deployment with node -> node as a graph
-
-    dependency_node = models.create_dependency_node_template(deployment)
-    model_storage.node_template.put(dependency_node)
-    storage_dependency_node = model_storage.node_template.get(dependency_node.id)
-
-    dependency_node_instance = models.create_dependency_node(storage_dependency_node,
-                                                                   deployment)
-    model_storage.node.put(dependency_node_instance)
-    storage_dependency_node_instance = model_storage.node.get(dependency_node_instance.id)
-
-    req_template, cap_template = models.create_requirement(storage_dependency_node)
-    model_storage.requirement_template.put(req_template)
-    model_storage.capability_template.put(cap_template)
-
-    dependent_node = models.create_dependent_node_template(deployment, req_template, cap_template)
-    model_storage.node_template.put(dependent_node)
-    storage_dependent_node = model_storage.node_template.get(dependent_node.id)
-
-    dependent_node_instance = models.create_dependent_node(storage_dependent_node, deployment)
-    model_storage.node.put(dependent_node_instance)
-    storage_dependent_node_instance = model_storage.node.get(dependent_node_instance.id)
-
-    relationship_instance = models.create_relationship(
-        target_instance=storage_dependency_node_instance,
-        source_instance=storage_dependent_node_instance
-    )
-    model_storage.relationship.put(relationship_instance)
+    service_template = models.create_service_template()
+
+    service = models.create_service(service_template)
+
+    # Creating a simple service with node -> node as a graph
+
+    dependency_node_template = models.create_dependency_node_template(service_template)
+    dependent_node_template = models.create_dependent_node_template(service_template,
+                                                                    dependency_node_template)
+
+    dependency_node = models.create_dependency_node(dependency_node_template, service)
+    dependent_node = models.create_dependent_node(dependent_node_template, service)
+
+    dependent_node.outbound_relationships.append(models.create_relationship(
+        source=dependent_node,
+        target=dependency_node
+    ))
+
+    model_storage.service_template.put(service_template)
+    model_storage.service.put(service)
 
-    return deployment.id
+    return service.id

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py b/tests/orchestrator/context/test_operation.py
index 3f39979..b460b9f 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -58,21 +58,23 @@ def executor():
 def test_node_operation_task_execution(ctx, executor):
     operation_name = 'aria.interfaces.lifecycle.create'
 
-    node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
-    interface = mock.models.get_interface(
+    node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
+    interface = mock.models.create_interface(
+        node.service,
         operation_name,
         operation_kwargs=dict(implementation=op_path(my_operation, module_path=__name__))
     )
-    node.interfaces = [interface]
+    node.interfaces[interface.name] = interface
     ctx.model.node.update(node)
     inputs = {'putput': True}
 
     @workflow
     def basic_workflow(graph, **_):
         graph.add_tasks(
-            api.task.OperationTask.node(
-                name=operation_name,
-                instance=node,
+            api.task.OperationTask.for_node(
+                interface_name='aria.interfaces.lifecycle',
+                operation_name='create',
+                node=node,
                 inputs=inputs
             )
         )
@@ -100,24 +102,24 @@ def test_relationship_operation_task_execution(ctx, executor):
     operation_name = 'aria.interfaces.relationship_lifecycle.post_configure'
     relationship = ctx.model.relationship.list()[0]
 
-    interface = mock.models.get_interface(
+    interface = mock.models.create_interface(
+        relationship.source_node.service,
         operation_name=operation_name,
         operation_kwargs=dict(implementation=op_path(my_operation, module_path=__name__)),
-        edge='source'
     )
 
-    relationship.interfaces = [interface]
+    relationship.interfaces[interface.name] = interface
     ctx.model.relationship.update(relationship)
     inputs = {'putput': True}
 
     @workflow
     def basic_workflow(graph, **_):
         graph.add_tasks(
-            api.task.OperationTask.relationship(
-                instance=relationship,
-                name=operation_name,
-                inputs=inputs,
-                edge='source'
+            api.task.OperationTask.for_relationship(
+                relationship=relationship,
+                interface_name='aria.interfaces.relationship_lifecycle',
+                operation_name='post_configure',
+                inputs=inputs
             )
         )
 
@@ -137,9 +139,9 @@ def test_relationship_operation_task_execution(ctx, executor):
 
     # Context based attributes (sugaring)
     dependency_node_template = ctx.model.node_template.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
-    dependency_node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
+    dependency_node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
     dependent_node_template = ctx.model.node_template.get_by_name(mock.models.DEPENDENT_NODE_NAME)
-    dependent_node = ctx.model.node.get_by_name(mock.models.DEPENDENT_NODE_INSTANCE_NAME)
+    dependent_node = ctx.model.node.get_by_name(mock.models.DEPENDENT_NODE_NAME)
 
     assert operation_context.target_node_template == dependency_node_template
     assert operation_context.target_node == dependency_node
@@ -161,9 +163,9 @@ def test_invalid_task_operation_id(ctx, executor):
     assert other_node.id == 1
     assert node.id == 2
 
-    interface = mock.models.get_interface(
+    interface = mock.models.create_interface(
         operation_name=operation_name,
-        operation_kwargs=dict(implementation=op_path(get_node_instance_id, module_path=__name__))
+        operation_kwargs=dict(implementation=op_path(get_node_id, module_path=__name__))
     )
     node.interfaces = [interface]
     ctx.model.node.update(node)
@@ -171,21 +173,21 @@ def test_invalid_task_operation_id(ctx, executor):
     @workflow
     def basic_workflow(graph, **_):
         graph.add_tasks(
-            api.task.OperationTask.node(name=operation_name, instance=node)
+            api.task.OperationTask.for_node(name=operation_name, node=node)
         )
 
     execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
 
-    op_node_instance_id = global_test_holder[op_name(node, operation_name)]
-    assert op_node_instance_id == node.id
-    assert op_node_instance_id != other_node.id
+    op_node_id = global_test_holder[op_name(node, operation_name)]
+    assert op_node_id == node.id
+    assert op_node_id != other_node.id
 
 
 def test_plugin_workdir(ctx, executor, tmpdir):
     op = 'test.op'
     plugin_name = 'mock_plugin'
-    node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
-    node.interfaces = [mock.models.get_interface(
+    node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
+    node.interfaces = [mock.models.create_interface(
         op,
         operation_kwargs=dict(
             implementation='{0}.{1}'.format(__name__, _test_plugin_workdir.__name__),
@@ -200,8 +202,8 @@ def test_plugin_workdir(ctx, executor, tmpdir):
 
     @workflow
     def basic_workflow(graph, **_):
-        graph.add_tasks(api.task.OperationTask.node(
-            name=op, instance=node, inputs=inputs))
+        graph.add_tasks(api.task.OperationTask.for_node(
+            name=op, node=node, inputs=inputs))
 
     execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
     expected_file = tmpdir.join('workdir', 'plugins', str(ctx.service_instance.id),
@@ -216,7 +218,7 @@ def my_operation(ctx, **_):
 
 
 @operation
-def get_node_instance_id(ctx, **_):
+def get_node_id(ctx, **_):
     global_test_holder[ctx.name] = ctx.node.id
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/24ad8ba1/tests/orchestrator/test_runner.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/test_runner.py b/tests/orchestrator/test_runner.py
index 2e509b5..74e98ad 100644
--- a/tests/orchestrator/test_runner.py
+++ b/tests/orchestrator/test_runner.py
@@ -50,7 +50,8 @@ def test_runner_tasks():
         for node in ctx.model.node:
             graph.add_tasks(
                 OperationTask.for_node(node=node,
-                                       name='tosca.interfaces.node.lifecycle.Standard.create'))
+                                       interface_name='Standard',
+                                       operation_name='create'))
 
     _test_runner(workflow_fn)
 
@@ -69,5 +70,5 @@ def _test_runner(workflow_fn):
                     workflow_fn=workflow_fn,
                     inputs={},
                     initialize_model_storage_fn=_initialize_model_storage_fn,
-                    service_instance_id=1)
+                    service_id_fn=lambda: 1)
     runner.run()