ariatosca-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From emblempar...@apache.org
Subject incubator-ariatosca git commit: Relationships now have only one "interfaces" property; update task API accordingly
Date Mon, 06 Feb 2017 23:38:26 GMT
Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-44-Merge-parser-and-storage-models 5230ae6e4 -> c5fb0abad


Relationships now have only one "interfaces" property; update task API accordingly


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

Branch: refs/heads/ARIA-44-Merge-parser-and-storage-models
Commit: c5fb0abad9e3e6970f70498eab288482eb8346ac
Parents: 5230ae6
Author: Tal Liron <tal.liron@gmail.com>
Authored: Mon Feb 6 17:37:48 2017 -0600
Committer: Tal Liron <tal.liron@gmail.com>
Committed: Mon Feb 6 17:37:48 2017 -0600

----------------------------------------------------------------------
 aria/orchestrator/workflows/api/task.py        | 61 +++++++++++++--------
 aria/orchestrator/workflows/builtin/utils.py   | 15 +++--
 aria/parser/modeling/storage.py                | 24 ++++----
 aria/storage/modeling/instance_elements.py     | 23 ++------
 tests/mock/models.py                           |  8 ++-
 tests/orchestrator/context/test_operation.py   | 10 ++--
 tests/orchestrator/context/test_toolbelt.py    | 11 ++--
 tests/orchestrator/workflows/api/test_task.py  | 16 ++++--
 tests/orchestrator/workflows/core/test_task.py | 14 +++--
 9 files changed, 97 insertions(+), 85 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c5fb0aba/aria/orchestrator/workflows/api/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task.py b/aria/orchestrator/workflows/api/task.py
index 50fe6a9..64cd7f3 100644
--- a/aria/orchestrator/workflows/api/task.py
+++ b/aria/orchestrator/workflows/api/task.py
@@ -111,21 +111,23 @@ class OperationTask(BaseTask):
         interfaces = instance.interfaces.filter_by(name=interface_name)
         if interfaces.count() > 1:
             raise exceptions.TaskException(
-                "More than one interface with the same name {0} were found".format(name))
+                "More than one interface with the same name `{0}` found".format(name)
+            )
         elif interfaces.count() == 0:
             raise exceptions.TaskException(
-                "No Interface with the name `{interface_name}` was found".format(
+                "No Interface with the name `{interface_name}` found".format(
                     interface_name=interface_name)
             )
 
         operation_templates = interfaces[0].operations.filter_by(name=name)
         if operation_templates.count() > 1:
             raise exceptions.TaskException(
-                "More than one operation with the same name {0} were found".format(name))
+                "More than one operation with the same name `{0}` were found".format(name)
+            )
 
         elif operation_templates.count() == 0:
             raise exceptions.TaskException(
-                "No Interface with the name `{operation_name}` was found".format(
+                "No interface with the name `{operation_name}` found".format(
                     operation_name=name)
             )
 
@@ -140,44 +142,57 @@ class OperationTask(BaseTask):
             **kwargs)
 
     @classmethod
-    def relationship_instance(cls, instance, name, inputs=None, *args, **kwargs):
+    def relationship_instance(cls, instance, name, edge, runs_on=None, inputs=None, *args,
+                              **kwargs):
         """
         Represents a relationship based operation
 
         :param instance: the relationship of which this operation belongs to.
         :param name: the name of the operation.
+        :param edge: the edge of the interface ("source" or "target").
+        :param runs_on: where to run the operation ("source" or "target"); if None defaults
to the
+                        interface edge.
         :param inputs any additional inputs to the operation
         """
         assert isinstance(instance, model.Relationship)
-        operation_name, operation_end = name.rsplit('_', 1)
-        interface_name = _get_interface_name(operation_name)
-        interfaces = getattr(instance, operation_end + '_interfaces').filter_by(name=interface_name)
-        if interfaces.count() > 1:
+        interface_name = _get_interface_name(name)
+        interfaces = instance.interfaces.filter_by(name=interface_name, edge=edge)
+        count = interfaces.count()
+        if count > 1:
             raise exceptions.TaskException(
-                "More than one interface with the same name {0} found".format(interface_name))
-        elif interfaces.count() == 0:
+                "More than one interface with the same name `{interface_name}` found at `{edge}`"
+                + " edge".format(
+                    interface_name=interface_name, edge=edge)
+            )
+        elif count == 0:
             raise exceptions.TaskException(
-                "No Interface with the name `{interface_name}` was found".format(
-                    interface_name=interface_name)
+                "No interface with the name `{interface_name}` found at `{edge}` edge".format(
+                    interface_name=interface_name, edge=edge)
             )
 
-        operations = interfaces.all()[0].operations.filter_by(name=operation_name)
-        if operations.count() > 1:
+        operations = interfaces.all()[0].operations.filter_by(name=name)
+        count = operations.count()
+        if count > 1:
             raise exceptions.TaskException(
-                "More than one operation with the same name {0} found".format(name))
-        elif operations.count() == 0:
+                "More than one operation with the same name `{0}` found".format(name)
+            )
+        elif count == 0:
             raise exceptions.TaskException(
-                "No Operation with the name `{operation_name}` was found".format(
-                    operation_name=operation_name)
+                "No operation with the name `{operation_name}` found".format(
+                    operation_name=name)
             )
 
-        if operation_end == cls.SOURCE_OPERATION:
-            plugins = instance.source_node.plugins
-            runs_on = model.Task.RUNS_ON_SOURCE
+        if not runs_on:
+            if edge == cls.SOURCE_OPERATION:
+                runs_on = model.Task.RUNS_ON_SOURCE
+            else:
+                runs_on = model.Task.RUNS_ON_TARGET
 
+        if runs_on == model.Task.RUNS_ON_SOURCE:
+            plugins = instance.source_node.plugins
         else:
             plugins = instance.target_node.plugins
-            runs_on = model.Task.RUNS_ON_TARGET
+
         return cls._instance(instance=instance,
                              name=name,
                              operation_template=operations[0],

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c5fb0aba/aria/orchestrator/workflows/builtin/utils.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/utils.py b/aria/orchestrator/workflows/builtin/utils.py
index 855f911..bf85153 100644
--- a/aria/orchestrator/workflows/builtin/utils.py
+++ b/aria/orchestrator/workflows/builtin/utils.py
@@ -27,20 +27,20 @@ def create_node_task(operation_name, node):
     return None
 
 
-def create_relationship_tasks(operation_name, edge, node):
+def create_relationship_tasks(operation_name, runs_on, node):
     """
     Returns a list of operation tasks for each outbound relationship of the node if the operation
     exists there.
     """
 
-    edge = 'source' # TODO: support target?
-
     sequence = []
     for relationship in node.outbound_relationships:
-        if _has_operation(getattr(relationship, edge + '_interfaces'), operation_name):
+        if _has_operation(relationship.interfaces, operation_name):
             sequence.append(
                 OperationTask.relationship_instance(instance=relationship,
-                                                    name=operation_name + '_' + edge))
+                                                    name=operation_name,
+                                                    edge='source',
+                                                    runs_on=runs_on))
     return sequence
 
 
@@ -71,7 +71,6 @@ def create_node_task_dependencies(graph, tasks_and_nodes, reverse=False):
 
 def _has_operation(interfaces, operation_name):
     for interface in interfaces:
-        for operation in interface.operations:
-            if operation.name == operation_name:
-                return True
+        if interface.operations.filter_by(name=operation_name).count() == 1:
+            return True
     return False

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c5fb0aba/aria/parser/modeling/storage.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/storage.py b/aria/parser/modeling/storage.py
index e6b0a80..108ccb4 100644
--- a/aria/parser/modeling/storage.py
+++ b/aria/parser/modeling/storage.py
@@ -34,7 +34,7 @@ def initialize_storage(context, model_storage, service_instance_id):
     s_service_instance = create_service_instance(context, s_service_template, service_instance_id)
     model_storage.service_instance.put(s_service_instance)
 
-    # Create nodes templates and nodes
+    # Create node templates and nodes
     for node_template in context.modeling.model.node_templates.itervalues():
         s_node_template = create_node_template(s_service_template, node_template)
         model_storage.node_template.put(s_node_template)
@@ -42,7 +42,8 @@ def initialize_storage(context, model_storage, service_instance_id):
         for node in context.modeling.instance.find_nodes(node_template.name):
             s_node = create_node(s_service_instance, s_node_template, node)
             model_storage.node.put(s_node)
-            create_interfaces(context, model_storage, node.interfaces, s_node, 'node', '_dry_node')
+            create_interfaces(context, model_storage, node.interfaces,
+                              s_node, 'node', None, '_dry_node')
 
     # Create relationships between nodes
     for source_node in context.modeling.instance.nodes.itervalues():
@@ -51,8 +52,9 @@ def initialize_storage(context, model_storage, service_instance_id):
             s_target_node = model_storage.node.get_by_name(relationship.target_node_id)
             s_relationship = create_relationship(s_source_node, s_target_node)
             model_storage.relationship.put(s_relationship)
+            # TOSCA always uses the "source" edge
             create_interfaces(context, model_storage, relationship.source_interfaces,
-                              s_relationship, 'relationship', '_dry_relationship')
+                              s_relationship, 'relationship', 'source', '_dry_relationship')
 
 
 def create_service_template(context):
@@ -73,7 +75,7 @@ def create_service_template(context):
 def create_service_instance(context, service_template, service_instance_id):
     now = datetime.utcnow()
     return model.ServiceInstance(
-        name='%s_%s' % (service_template.name, service_instance_id),
+        name='{0}_{1}'.format(service_template.name, service_instance_id),
         service_template=service_template,
         description=context.modeling.instance.description or '',
         created_at=now,
@@ -104,16 +106,13 @@ def create_relationship(source_node, target_node):
         target_node=target_node)
 
 
-def create_interfaces(context, model_storage, interfaces, obj, attr_name, fn_name):
+def create_interfaces(context, model_storage, interfaces, node_or_relationship, type_name,
edge,
+                      fn_name):
     for interface_name, interface in interfaces.iteritems():
         s_interface = model.Interface(name=interface_name,
-                                      type_name=interface.type_name)
-        setattr(s_interface, attr_name, obj)
-        try:
-            obj.source_interfaces.append(s_interface)
-        except AttributeError:
-            # is a node
-            pass
+                                      type_name=interface.type_name,
+                                      edge=edge)
+        setattr(s_interface, type_name, node_or_relationship)
         model_storage.interface.put(s_interface)
         for operation_name, oper in interface.operations.iteritems():
             operation_name = '{0}.{1}'.format(interface_name, operation_name)
@@ -121,6 +120,7 @@ def create_interfaces(context, model_storage, interfaces, obj, attr_name,
fn_nam
                                           implementation='{0}.{1}'.format(__name__, fn_name),
                                           interface=s_interface)
             plugin, implementation = _parse_implementation(context, oper.implementation)
+            # TODO: operation's user inputs
             s_operation.inputs.append(model.Parameter(name='_plugin', # pylint: disable=no-member
                                                       value=plugin,
                                                       type='str'))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c5fb0aba/aria/storage/modeling/instance_elements.py
----------------------------------------------------------------------
diff --git a/aria/storage/modeling/instance_elements.py b/aria/storage/modeling/instance_elements.py
index 7273ff0..faa4c48 100644
--- a/aria/storage/modeling/instance_elements.py
+++ b/aria/storage/modeling/instance_elements.py
@@ -264,17 +264,14 @@ class InterfaceBase(structure.ModelMixin):
         return cls.foreign_key('node', nullable=True)
 
     @declared_attr
-    def relationship_source_fk(cls):
-        return cls.foreign_key('relationship', nullable=True)
-
-    @declared_attr
-    def relationship_target_fk(cls):
+    def relationship_fk(cls):
         return cls.foreign_key('relationship', nullable=True)
 
     # endregion
 
     description = Column(Text)
     type_name = Column(Text)
+    edge = Column(Text)
 
     # region many-to-one relationships
 
@@ -282,21 +279,9 @@ class InterfaceBase(structure.ModelMixin):
     def node(cls):
         return cls.many_to_one_relationship('node')
 
-    @property
-    def relationship(self):
-        return self.relationship_source or self.relationship_target
-
-    @declared_attr
-    def relationship_source(cls):
-        return cls.many_to_one_relationship('relationship',
-                                            foreign_key_column='relationship_source_fk',
-                                            backreference='source_interfaces')
-
     @declared_attr
-    def relationship_target(cls):
-        return cls.many_to_one_relationship('relationship',
-                                            foreign_key_column='relationship_target_fk',
-                                            backreference='target_interfaces')
+    def relationship(cls):
+        return cls.many_to_one_relationship('relationship')
 
     @declared_attr
     def group(cls):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c5fb0aba/tests/mock/models.py
----------------------------------------------------------------------
diff --git a/tests/mock/models.py b/tests/mock/models.py
index e735230..047526a 100644
--- a/tests/mock/models.py
+++ b/tests/mock/models.py
@@ -172,7 +172,11 @@ def get_interface_template(operation_name, operation_kwargs=None, interface_kwar
 
 def get_interface(operation_name,
                   operation_kwargs=None,
-                  interface_kwargs=None):
+                  interface_kwargs=None,
+                  edge=None):
     operation = model.Operation(name=operation_name, **(operation_kwargs or {}))
     interface_name = operation_name.rsplit('.', 1)[0]
-    return model.Interface(operations=[operation], name=interface_name, **(interface_kwargs
or {}))
+    return model.Interface(operations=[operation],
+                           name=interface_name,
+                           edge=edge,
+                           **(interface_kwargs or {}))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c5fb0aba/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py b/tests/orchestrator/context/test_operation.py
index 7706db3..35db048 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -100,9 +100,10 @@ def test_relationship_operation_task_execution(ctx, executor):
     interface = mock.models.get_interface(
         operation_name=operation_name,
         operation_kwargs=dict(implementation=op_path(my_operation, module_path=__name__)),
+        edge='source'
     )
 
-    relationship.source_interfaces = [interface]
+    relationship.interfaces = [interface]
     ctx.model.relationship.update(relationship)
     inputs = {'putput': True}
 
@@ -111,15 +112,16 @@ def test_relationship_operation_task_execution(ctx, executor):
         graph.add_tasks(
             api.task.OperationTask.relationship_instance(
                 instance=relationship,
-                name='{0}_source'.format(operation_name),
-                inputs=inputs
+                name=operation_name,
+                inputs=inputs,
+                edge='source'
             )
         )
 
     execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
 
     operation_context = global_test_holder[op_name(relationship,
-                                                   '{0}_source'.format(operation_name))]
+                                                   operation_name)]
 
     assert isinstance(operation_context, context.operation.RelationshipOperationContext)
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c5fb0aba/tests/orchestrator/context/test_toolbelt.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_toolbelt.py b/tests/orchestrator/context/test_toolbelt.py
index 35306a6..5805293 100644
--- a/tests/orchestrator/context/test_toolbelt.py
+++ b/tests/orchestrator/context/test_toolbelt.py
@@ -101,11 +101,12 @@ def test_host_ip(workflow_context, executor):
 def test_relationship_tool_belt(workflow_context, executor):
     operation_name = 'aria.interfaces.relationship_lifecycle.post_configure'
     _, _, _, _, relationship = _get_elements(workflow_context)
-    relationship.source_interfaces = [
+    relationship.interfaces = [
         mock.models.get_interface(
             operation_name,
             operation_kwargs=dict(
-                implementation=op_path(relationship_operation, module_path=__name__)))
+                implementation=op_path(relationship_operation, module_path=__name__)),
+            edge='source')
     ]
     workflow_context.model.relationship.update(relationship)
 
@@ -116,15 +117,15 @@ def test_relationship_tool_belt(workflow_context, executor):
         graph.add_tasks(
             api.task.OperationTask.relationship_instance(
                 instance=relationship,
-                name='{0}_source'.format(operation_name),
+                name=operation_name,
+                edge='source',
                 inputs=inputs
             )
         )
 
     execute(workflow_func=basic_workflow, workflow_context=workflow_context, executor=executor)
 
-    assert isinstance(global_test_holder.get(op_name(relationship,
-                                                     '{0}_source'.format(operation_name))),
+    assert isinstance(global_test_holder.get(op_name(relationship, operation_name)),
                       RelationshipToolBelt)
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c5fb0aba/tests/orchestrator/workflows/api/test_task.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/api/test_task.py b/tests/orchestrator/workflows/api/test_task.py
index cddacfe..92d0917 100644
--- a/tests/orchestrator/workflows/api/test_task.py
+++ b/tests/orchestrator/workflows/api/test_task.py
@@ -81,10 +81,11 @@ class TestOperationTask(object):
         interface = mock.models.get_interface(
             operation_name,
             operation_kwargs=dict(implementation='op_path', plugin='plugin'),
+            edge='source'
         )
 
         relationship = ctx.model.relationship.list()[0]
-        relationship.source_interfaces = [interface]
+        relationship.interfaces = [interface]
         relationship.source_node.plugins = [{'name': 'plugin',
                                              'package_name': 'package',
                                              'package_version': '0.1'}]
@@ -94,13 +95,14 @@ class TestOperationTask(object):
 
         with context.workflow.current.push(ctx):
             api_task = api.task.OperationTask.relationship_instance(
-                name='{0}_source'.format(operation_name),
+                name=operation_name,
                 instance=relationship,
+                edge='source',
                 inputs=inputs,
                 max_attempts=max_attempts,
                 retry_interval=retry_interval)
 
-        assert api_task.name == '{0}_source.{1}'.format(operation_name, relationship.id)
+        assert api_task.name == '{0}.{1}'.format(operation_name, relationship.id)
         assert api_task.implementation == 'op_path'
         assert api_task.actor == relationship
         assert api_task.inputs == inputs
@@ -116,10 +118,11 @@ class TestOperationTask(object):
         interface = mock.models.get_interface(
             operation_name,
             operation_kwargs=dict(implementation='op_path', plugin='plugin'),
+            edge='target'
         )
 
         relationship = ctx.model.relationship.list()[0]
-        relationship.target_interfaces = [interface]
+        relationship.interfaces = [interface]
         relationship.target_node.plugins = [{'name': 'plugin',
                                              'package_name': 'package',
                                              'package_version': '0.1'}]
@@ -129,13 +132,14 @@ class TestOperationTask(object):
 
         with context.workflow.current.push(ctx):
             api_task = api.task.OperationTask.relationship_instance(
-                name='{0}_target'.format(operation_name),
+                name=operation_name,
                 instance=relationship,
+                edge='target',
                 inputs=inputs,
                 max_attempts=max_attempts,
                 retry_interval=retry_interval)
 
-        assert api_task.name == '{0}_target.{1}'.format(operation_name, relationship.id)
+        assert api_task.name == '{0}.{1}'.format(operation_name, relationship.id)
         assert api_task.implementation == 'op_path'
         assert api_task.actor == relationship
         assert api_task.inputs == inputs

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c5fb0aba/tests/orchestrator/workflows/core/test_task.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/core/test_task.py b/tests/orchestrator/workflows/core/test_task.py
index 8d07b09..ca2731e 100644
--- a/tests/orchestrator/workflows/core/test_task.py
+++ b/tests/orchestrator/workflows/core/test_task.py
@@ -37,8 +37,10 @@ def ctx(tmpdir):
     context = mock.context.simple(storage.get_sqlite_api_kwargs(str(tmpdir)))
 
     relationship = context.model.relationship.list()[0]
-    relationship.source_interfaces = [mock.models.get_interface(RELATIONSHIP_OP_NAME)]
-    relationship.target_interfaces = [mock.models.get_interface(RELATIONSHIP_OP_NAME)]
+    relationship.interfaces = [
+        mock.models.get_interface(RELATIONSHIP_OP_NAME, edge='source'),
+        mock.models.get_interface(RELATIONSHIP_OP_NAME, edge='target')
+    ]
     context.model.relationship.update(relationship)
 
     dependent_node = context.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
@@ -59,10 +61,10 @@ class TestOperationTask(object):
             core_task = core.task.OperationTask(api_task=api_task)
         return api_task, core_task
 
-    def _create_relationship_operation_task(self, ctx, relationship, operation_name):
+    def _create_relationship_operation_task(self, ctx, relationship, operation_name, edge):
         with workflow_context.current.push(ctx):
             api_task = api.task.OperationTask.relationship_instance(
-                instance=relationship, name=operation_name)
+                instance=relationship, name=operation_name, edge=edge)
             core_task = core.task.OperationTask(api_task=api_task)
         return api_task, core_task
 
@@ -99,13 +101,13 @@ class TestOperationTask(object):
         relationship = ctx.model.relationship.list()[0]
         ctx.model.relationship.update(relationship)
         _, core_task = self._create_relationship_operation_task(
-            ctx, relationship, '{0}_source'.format(RELATIONSHIP_OP_NAME))
+            ctx, relationship, RELATIONSHIP_OP_NAME, 'source')
         assert core_task.model_task.runs_on == relationship.source_node
 
     def test_target_relationship_operation_task_creation(self, ctx):
         relationship = ctx.model.relationship.list()[0]
         _, core_task = self._create_relationship_operation_task(
-            ctx, relationship, '{0}_target'.format(RELATIONSHIP_OP_NAME))
+            ctx, relationship, RELATIONSHIP_OP_NAME, 'target')
         assert core_task.model_task.runs_on == relationship.target_node
 
     def test_operation_task_edit_locked_attribute(self, ctx):


Mime
View raw message