You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by mx...@apache.org on 2017/07/23 14:02:54 UTC

incubator-ariatosca git commit: basic template to instance framework is up [Forced Update!]

Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-174-Refactor-instantiation-phase 35b9ba713 -> 0bc7993f8 (forced update)


basic template to instance framework is up


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

Branch: refs/heads/ARIA-174-Refactor-instantiation-phase
Commit: 0bc7993f856798188b81bee53d6acea824be4c58
Parents: 609d305
Author: max-orlov <ma...@gigaspaces.com>
Authored: Sun Jul 23 16:59:56 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Sun Jul 23 17:02:49 2017 +0300

----------------------------------------------------------------------
 aria/core.py                           |   4 +-
 aria/modeling/service_instance.py      |   9 +-
 aria/modeling/service_template.py      |  19 -
 aria/orchestrator/topology/__init__.py |   2 +-
 aria/orchestrator/topology/topology.py | 609 ++++++++++++++++++----------
 aria/orchestrator/topology/utils.py    |  19 +
 aria/parser/consumption/modeling.py    |   2 +-
 7 files changed, 424 insertions(+), 240 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/0bc7993f/aria/core.py
----------------------------------------------------------------------
diff --git a/aria/core.py b/aria/core.py
index c3fe96f..9ae45b5 100644
--- a/aria/core.py
+++ b/aria/core.py
@@ -74,8 +74,8 @@ class Core(object):
         # setting no autoflush for the duration of instantiation - this helps avoid dependency
         # constraints as they're being set up
         with storage_session.no_autoflush:
-            with topology.initiator.push_model_storage(self._model_storage) as initiator:
-                service = initiator.instantiate_service(service_template, inputs=inputs)
+            service = topology.Handler(self.model_storage).instantiate(
+                service_template, inputs=inputs)
 
         storage_session.flush()  # flushing so service.id would auto-populate
         service.name = service_name or '{0}_{1}'.format(service_template.name, service.id)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/0bc7993f/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index 2eaead2..58734b2 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -660,7 +660,8 @@ class NodeBase(InstanceModelMixin):
             if target_node is not None:
                 if requirement_template.relationship_template is not None:
                     from aria.orchestrator import topology
-                    relationship_model = topology.initiator.instantiate(requirement_template.relationship_template)
+                    relationship_model = topology.handler.instantiate(
+                        requirement_template.relationship_template)
                 else:
                     relationship_model = models.Relationship()
                 relationship_model.name = requirement_template.name
@@ -1958,19 +1959,19 @@ class OperationBase(InstanceModelMixin):
             # can validate the configuration and otherwise create specially derived arguments. For
             # now, we just send all configuration parameters as arguments without validation.
             for key, conf in self.configurations.items():
-                self.arguments[key] = topology.initiator.instantiate(conf.as_argument())
+                self.arguments[key] = topology.handler.instantiate(conf.as_argument())
 
         if self.interface is not None:
             # Send all interface inputs as extra arguments
             # ("interface" is None for workflow operations)
             # Note that they will override existing arguments of the same names
             for key, input in self.interface.inputs.items():
-                self.arguments[key] = topology.initiator.instantiate(input.as_argument())
+                self.arguments[key] = topology.handler.instantiate(input.as_argument())
 
         # Send all inputs as extra arguments
         # Note that they will override existing arguments of the same names
         for key, input in self.inputs.items():
-            self.arguments[key] = topology.initiator.instantiate(input.as_argument())
+            self.arguments[key] = topology.handler.instantiate(input.as_argument())
 
         # Check for reserved arguments
         from ..orchestrator.decorators import OPERATION_DECORATOR_RESERVED_ARGUMENTS

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/0bc7993f/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index 0cbfdb6..719a221 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -34,7 +34,6 @@ from sqlalchemy.ext.declarative import declared_attr
 from ..parser import validation
 from ..parser.consumption import ConsumptionContext
 from ..utils import (collections, formatting, console)
-from ..utils.versions import VersionString
 from .mixins import TemplateModelMixin
 from . import (
     relationship,
@@ -2198,21 +2197,3 @@ class PluginSpecificationBase(TemplateModelMixin):
 
     def coerce_values(self, report_issues):
         pass
-
-    def resolve(self, model_storage):
-        # TODO: we are planning a separate "instantiation" module where this will be called or
-        # moved to.
-        plugins = model_storage.plugin.list()
-        matching_plugins = []
-        if plugins:
-            for plugin in plugins:
-                if (plugin.name == self.name) and \
-                    ((self.version is None) or \
-                     (VersionString(plugin.package_version) >= self.version)):
-                    matching_plugins.append(plugin)
-        self.plugin = None
-        if matching_plugins:
-            # Return highest version of plugin
-            key = lambda plugin: VersionString(plugin.package_version).key
-            self.plugin = sorted(matching_plugins, key=key)[-1]
-        return self.plugin is not None

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/0bc7993f/aria/orchestrator/topology/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/__init__.py b/aria/orchestrator/topology/__init__.py
index ae9c900..c90f465 100644
--- a/aria/orchestrator/topology/__init__.py
+++ b/aria/orchestrator/topology/__init__.py
@@ -13,4 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from .topology import Instantiation, initiator
+from .topology import Handler, handler

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/0bc7993f/aria/orchestrator/topology/topology.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/topology.py b/aria/orchestrator/topology/topology.py
index abe8cd6..c79c445 100644
--- a/aria/orchestrator/topology/topology.py
+++ b/aria/orchestrator/topology/topology.py
@@ -13,281 +13,464 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 from datetime import datetime
-from functools import partial
-from contextlib import contextmanager
 
 
 from ...modeling import (
     utils as modeling_utils,
     models
 )
-from ...parser import validation, consumption
 from . import utils
 
 
-class Instantiation(object):
-
-    def __init__(self, context):
-        self._context = context or consumption.ConsumptionContext()
-        self._initiators = {
-            'meta_data': self._instantiate_metadata,
-            'node_template': self._instantiate_node,
-            'substitution_template': self._instantiate_substitution,
-            'workflow_templates': self._instantiate_operation,
-            'operation_templates': self._instantiate_operation,
-            'interface_templates': self._instantiate_interface,
-            'artifact_templates': self._instantiate_artifact,
-            'capability_templates': self._instantiate_capability,
-            'group_templates': self._instantiate_group,
-            'policy_templates': self._instantiate_policy,
-            'relationship_template': self._instantiate_relationship,
-
-            # Parameter-Based instantiations
-            'argument': partial(self._instantiate_parameter, model_cls=models.Argument),
-
-            'inputs': partial(self._instantiate_parameter, model_cls=models.Input),
-            'outputs': partial(self._instantiate_parameter, model_cls=models.Output),
-            'properties': partial(self._instantiate_parameter, model_cls=models.Property),
-            'attributes': partial(self._instantiate_parameter, model_cls=models.Attribute),
-            'configurations': partial(self._instantiate_parameter, model_cls=models.Configuration),
+class _Entity(object):
+    
+    def __init__(self, topology_initiator, template, _instance_cls):
+        self._topology = topology_initiator
+        self._template = template
+        self._instance_cls = _instance_cls
+    
+    def instantiate(self, **kwargs):
+        raise NotImplementedError
+    
+    def coerce(self):
+        raise NotImplementedError
+    
+    def validate(self):
+        raise NotImplementedError
+    
+    def dump(self):
+        raise NotImplementedError
+
+
+class Handler(object):
+    def __init__(self, model_storage=None):
+        # TODO: model storage is required only for the list of plugins, can we get it
+        # somewhere else?
+        self._model_storage = model_storage
+        self._handlers = {
+            models.ServiceTemplate: ServiceInstance,
+            models.ArtifactTemplate: Artifact,
+            models.CapabilityTemplate: Capability,
+            models.GroupTemplate: Group,
+            models.InterfaceTemplate: Interface,
+            models.NodeTemplate: Node,
+            models.PolicyTemplate: Policy,
+            models.SubstitutionTemplate: Substitution,
+            models.SubstitutionMapping: SubstitutionMapping,
+            models.RelationshipTemplate: Relationship,
+            models.OperationTemplate: Operation,
+            models.Metadata: Metadata,
+
+            models.Attribute: Parameter,
+            models.Property: Parameter,
+            models.Input: Parameter,
+            models.Output: Parameter,
+            models.Configuration: Parameter,
+            models.Argument: Parameter,
 
         }
-        self._model_storage = None
 
-    @property
-    def _has_model_storage(self):
-        return self._model_storage is not None
+    def instantiate(self, template, **kwargs):
+        if isinstance(template, dict):
+            return dict((name, self.instantiate(value, **kwargs))
+                        for name, value in template.iteritems())
+        elif isinstance(template, list):
+            return list(self.instantiate(value, **kwargs) for value in template)
+        else:
+            handler = self._handlers[template.__class__]
+            return handler(self, template).instantiate(**kwargs)
 
-    @contextmanager
-    def push_model_storage(self, model_storage):
-        original_model_storage = self._model_storage
-        self._model_storage = model_storage
-        yield self
-        self._model_storage = original_model_storage
 
-    def instantiate_service(self, service_template, inputs=None):
+class ServiceInstance(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(ServiceInstance, self).__init__(*args, _instance_cls=models.Service, **kwargs)
+
+    def dump(self):
+        pass
 
+    def coerce(self):
+        pass
+
+    def instantiate(self, inputs=None):
         now = datetime.now()
-        service = models.Service(
+        service = self._instance_cls(
             created_at=now,
             updated_at=now,
-            description=utils.deepcopy_with_locators(service_template.description),
-            service_template=service_template
+            description=utils.deepcopy_with_locators(self._template.description),
+            service_template=self._template,
+            inputs=modeling_utils.merge_parameter_values(inputs, self._template.inputs)
         )
 
-        self._context.modeling.instance = service
-
-        service.inputs = modeling_utils.merge_parameter_values(inputs, service_template.inputs)
-        # TODO: now that we have inputs, we should scan properties and inputs and evaluate functions
-
-        for plugin_specification in service_template.plugin_specifications.itervalues():
-            if plugin_specification.enabled:
-                if plugin_specification.resolve(self._model_storage):
+        for plugin_specification in self._template.plugin_specifications.itervalues():
+            if plugin_specification.enabled and self._topology._model_storage:
+                if utils.resolve_plugin_specification(plugin_specification,
+                                                      self._topology.model_storage.plugin.list()):
                     plugin = plugin_specification.plugin
                     service.plugins[plugin.name] = plugin
                 else:
-                    self._context.validation.report('specified plugin not found: {0}'.format(
-                        plugin_specification.name), level=validation.Issue.EXTERNAL)
-
-        service.meta_data = self.instantiate(service_template.meta_data)
+                    # TODO: fix the context report usage
+                    pass
+                    # self._context.validation.report('specified plugin not found: {0}'.format(
+                    #     plugin_specification.name), level=validation.Issue.EXTERNAL)
+        service.meta_data = self._topology.instantiate(self._template.meta_data)
 
-        for node_template in service_template.node_templates.itervalues():
+        for node_template in self._template.node_templates.itervalues():
             for _ in range(node_template.scaling['default_instances']):
-                node = self.instantiate(node_template)
+                node = self._topology.instantiate(node_template)
                 service.nodes[node.name] = node
 
-        service.groups = self.instantiate(service_template.group_templates)
-        service.policies = self.instantiate(service_template.policy_templates)
-        service.workflows = self.instantiate(service_template.workflow_templates)
+        service.groups = self._topology.instantiate(self._template.group_templates)
+        service.policies = self._topology.instantiate(self._template.policy_templates)
+        service.workflows = self._topology.instantiate(self._template.workflow_templates)
 
-        if service_template.substitution_template is not None:
-            service.substitution = self.instantiate(service_template.substitution_template)
-            service.outputs = self.instantiate(service_template.outputs)
+        if self._template.substitution_template is not None:
+            service.substitution = self._topology.instantiate(self._template.substitution_template)
+            service.outputs = self._topology.instantiate(self._template.outputs)
 
         return service
 
-    def instantiate(self, source_template):
-        if isinstance(source_template, (dict, list)):
-            initiator = self._initiators[source_template._sa_adapter.attr.key]
-            if isinstance(source_template, dict):
-                dict_ = {}
-                for name, value in source_template.iteritems():
-                    value = initiator(value)
-                    if value is not None:
-                        dict_[name] = value
-                return dict_
-            elif isinstance(source_template, list):
-                list_ = []
-                for value in source_template:
-                    value = initiator(value)
-                    if value is not None:
-                        list_.append(value)
-                return list_
-        else:
-            return self._initiators[source_template.__tablename__](source_template)
-
-    @staticmethod
-    def _instantiate_artifact(artifact_template):
-        artifact = models.Artifact(
-            name=artifact_template.name,
-            type=artifact_template.type,
-            description=utils.deepcopy_with_locators(artifact_template.description),
-            source_path=artifact_template.source_path,
-            target_path=artifact_template.target_path,
-            repository_url=artifact_template.repository_url,
-            repository_credential=artifact_template.repository_credential,
-            artifact_template=artifact_template)
-        return artifact
-
-    @staticmethod
-    def _instantiate_capability(capability_template):
-        capability = models.Capability(name=capability_template.name,
-                                       type=capability_template.type,
-                                       min_occurrences=capability_template.min_occurrences,
-                                       max_occurrences=capability_template.max_occurrences,
-                                       occurrences=0,
-                                       capability_template=capability_template)
-        return capability
-
-    def _instantiate_group(self, group_template):
-        group = models.Group(name=group_template.name,
-                             type=group_template.type,
-                             description=utils.deepcopy_with_locators(group_template.description),
-                             group_template=group_template)
-        group.properties = self.instantiate(group_template.properties)
-        group.interfaces = self.instantiate(group_template.interface_templates)
-        if group_template.node_templates:
-            for node_template in group_template.node_templates:
+    def validate(self):
+        pass
+    
+    
+class Artifact(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(Artifact, self).__init__(*args, _instance_cls=models.Artifact, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        return self._instance_cls(
+            name=self._template.name,
+            type=self._template.type,
+            description=utils.deepcopy_with_locators(self._template.description),
+            source_path=self._template.source_path,
+            target_path=self._template.target_path,
+            repository_url=self._template.repository_url,
+            repository_credential=self._template.repository_credential,
+            artifact_template=self._template)
+
+    def validate(self):
+        pass
+    
+    
+class Capability(_Entity):
+    def __init__(self, *args, **kwargs):
+        super(Capability, self).__init__(*args, _instance_cls=models.Capability, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        return self._instance_cls(name=self._template.name,
+                                  type=self._template.type,
+                                  min_occurrences=self._template.min_occurrences,
+                                  max_occurrences=self._template.max_occurrences,
+                                  occurrences=0,
+                                  capability_template=self._template)
+
+    def validate(self):
+        pass
+    
+
+class Group(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(Group, self).__init__(*args, _instance_cls=models.Group, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        group = self._instance_cls(
+            name=self._template.name,
+            type=self._template.type,
+            description=utils.deepcopy_with_locators(self._template.description),
+            group_template=self._template)
+        group.properties = self._topology.instantiate(self._template.properties)
+        group.interfaces = self._topology.instantiate(self._template.interface_templates)
+        if self._template.node_templates:
+            for node_template in self._template.node_templates:
                 group.nodes += node_template.nodes
         return group
 
-    def _instantiate_interface(self, interface_template):
-        interface = models.Interface(
-            name=interface_template.name,
-            type=interface_template.type,
-            description=utils.deepcopy_with_locators(interface_template.description),
-            interface_template=interface_template)
-        interface.inputs = self.instantiate(interface_template.inputs)
-        interface.operations = self.instantiate(interface_template.operation_templates)
+    def validate(self):
+        pass
+    
+    
+class Interface(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(Interface, self).__init__(*args, _instance_cls=models.Interface, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        interface = self._instance_cls(
+            name=self._template.name,
+            type=self._template.type,
+            description=utils.deepcopy_with_locators(self._template.description),
+            interface_template=self._template)
+        interface.inputs = self._topology.instantiate(self._template.inputs)
+        interface.operations = self._topology.instantiate(self._template.operation_templates)
         return interface
 
-    def _instantiate_node(self, node_template):
-        node = models.Node(
-            name=node_template._next_name,
-            type=node_template.type,
-            description=utils.deepcopy_with_locators(node_template.description),
+    def validate(self):
+        pass
+
+
+class Node(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(Node, self).__init__(*args, _instance_cls=models.Node, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        node = self._instance_cls(
+            name=self._template._next_name,
+            type=self._template.type,
+            description=utils.deepcopy_with_locators(self._template.description),
             state=models.Node.INITIAL,
-            node_template=node_template
+            node_template=self._template
         )
-        node.properties = self.instantiate(node_template.properties)
-        node.attributes = self.instantiate(node_template.attributes)
-        node.interfaces = self.instantiate(node_template.interface_templates)
-        node.artifacts = self.instantiate(node_template.artifact_templates)
-        node.capabilities = self.instantiate(node_template.capability_templates)
+
+        node.properties = self._topology.instantiate(self._template.properties)
+        node.attributes = self._topology.instantiate(self._template.attributes)
+        node.interfaces = self._topology.instantiate(self._template.interface_templates)
+        node.artifacts = self._topology.instantiate(self._template.artifact_templates)
+        node.capabilities = self._topology.instantiate(self._template.capability_templates)
 
         # Default attributes
         if ('tosca_name' in node.attributes) \
-            and (node.attributes['tosca_name'].type_name == 'string'):
-            node.attributes['tosca_name'].value = node_template.name
+                and (node.attributes['tosca_name'].type_name == 'string'):
+            node.attributes['tosca_name'].value = self._template.name
         if 'tosca_id' in node.attributes \
-            and (node.attributes['tosca_id'].type_name == 'string'):
+                and (node.attributes['tosca_id'].type_name == 'string'):
             node.attributes['tosca_id'].value = node.name
 
         return node
 
-    def _instantiate_policy(self, policy_template):
-        policy = models.Policy(
-            name=policy_template.name,
-            type=policy_template.type,
-            description=utils.deepcopy_with_locators(policy_template.description),
-            policy_template=policy_template)
-        policy.properties = self.instantiate(policy_template.properties)
-        if policy_template.node_templates:
-            for node_template in policy_template.node_templates:
+    def validate(self):
+        pass
+
+
+class Policy(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(Policy, self).__init__(*args, _instance_cls=models.Policy, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        policy = self._instance_cls(
+            name=self._template.name,
+            type=self._template.type,
+            description=utils.deepcopy_with_locators(self._template.description),
+            policy_template=self._template)
+
+        policy.properties = self._topology.instantiate(self._template.properties)
+        if self._template.node_templates:
+            for node_template in self._template.node_templates:
                 policy.nodes += node_template.nodes
-        if policy_template.group_templates:
-            for group_template in policy_template.group_templates:
+        if self._template.group_templates:
+            for group_template in self._template.group_templates:
                 policy.groups += group_template.groups
         return policy
 
-    @staticmethod
-    def _instantiate_parameter(parameter_template, model_cls):
-        return model_cls(
-            name=parameter_template.name,  # pylint: disable=unexpected-keyword-arg
-            type_name=parameter_template.type_name,
-            _value=parameter_template._value,
-            description=parameter_template.description
+    def validate(self):
+        pass
+
+
+class Parameter(_Entity):
+    def __init__(self, topology_initiator, template, *args, **kwargs):
+        super(Parameter, self).__init__(
+            topology_initiator, template, *args, _instance_cls=template.__class__, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        return self._instance_cls(
+            name=self._template.name,  # pylint: disable=unexpected-keyword-arg
+            type_name=self._template.type_name,
+            _value=self._template._value,
+            description=self._template.description
         )
 
-    @staticmethod
-    def _instantiate_substitution(substitution_template):
-        substitution = models.Substitution(node_type=substitution_template.node_type,
-                                           substitution_template=substitution_template)
-        return substitution
+    def validate(self):
+        pass
+
+
+class Substitution(_Entity):
+    def __init__(self, *args, **kwargs):
+        super(Substitution, self).__init__(_instance_cls=models.Substitution, *args, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        return self._instance_cls(node_type=self._template.node_type,
+                                  substitution_template=self._template)
 
-    @staticmethod
-    def _instantiate_metadata(metadata_template):
-        return models.Metadata(name=metadata_template.name, value=metadata_template.value)
+    def validate(self):
+        pass
 
-    def _instantiate_substitution_mapping(self, substitution_mapping):
-        if substitution_mapping.capability_template is not None:
-            node_template = substitution_mapping.capability_template.node_template
+
+class SubstitutionMapping(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(SubstitutionMapping, self).__init__(
+            _instance_cls=models.SubstitutionMapping, *args, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        substitution_mapping = self._instance_cls(
+            name=self._template.name,
+            requirement_template=self._template.requirement_template)
+
+        if self._template.capability_template is not None:
+            node_template = self._template.capability_template.node_template
         else:
-            node_template = substitution_mapping.requirement_template.node_template
+            node_template = self._template.requirement_template.node_template
         nodes = node_template.nodes
         if len(nodes) == 0:
-            self._context.validation.report(
-                'mapping "{0}" refers to node template "{1}" but there are no node instances'.
-                    format(substitution_mapping.mapped_name,
-                           substitution_mapping.node_template.name),
-                level=validation.Issue.BETWEEN_INSTANCES)
+            # TODO: manage the context report
+            # self._context.validation.report(
+            #     'mapping "{0}" refers to node template "{1}" but there are no node instances'.
+            #         format(self._template.mapped_name,
+            #                self._template.node_template.name),
+            #     level=validation.Issue.BETWEEN_INSTANCES)
             return None
         # The TOSCA spec does not provide a way to choose the node,
         # so we will just pick the first one
-        node = nodes[0]
-        capability = None
-        if substitution_mapping.capability_template:
-            for a_capability in node.capabilities.itervalues():
+        substitution_mapping.node = nodes[0]
+        if self._template.capability_template:
+            for a_capability in substitution_mapping.node.capabilities.itervalues():
                 if a_capability.capability_template.name == \
-                        substitution_mapping.capability_template.name:
-                    capability = a_capability
-        return models.SubstitutionMapping(
-            name=substitution_mapping.name,
-            capability=capability,
-            requirement_template=substitution_mapping.requirement_template,
-            node=node)
-
-    def _instantiate_relationship(self, relationship_template):
-        relationship_model = models.Relationship(name=relationship_template.name,
-                                                 type=relationship_template.type,
-                                                 relationship_template=relationship_template)
-        relationship_model.properties = self.instantiate(relationship_template.properties)
-        relationship_model.interfaces = self.instantiate(relationship_template.interface_templates)
-        return relationship_model
-
-    def _instantiate_operation(self, operation_template):
-        plugin = None
-        if (operation_template.plugin_specification is not None and
-            operation_template.plugin_specification.enabled):
-            plugin = operation_template.plugin_specification.plugin
-
-        operation = models.Operation(
-            name=operation_template.name,
-            description=utils.deepcopy_with_locators(operation_template.description),
-            relationship_edge=operation_template.relationship_edge,
-            implementation=operation_template.implementation,
-            dependencies=operation_template.dependencies,
-            executor=operation_template.executor,
-            plugin=plugin,
-            function=operation_template.function,
-            max_attempts=operation_template.max_attempts,
-            retry_interval=operation_template.retry_interval,
-            operation_template=operation_template)
-
-        operation.inputs = self.instantiate(operation_template.inputs)
-        operation.configurations = self.instantiate(operation_template.configurations)
+                        self._template.capability_template.name:
+                    substitution_mapping.capability = a_capability
+
+        return substitution_mapping
+
+    def validate(self):
+        pass
+
+
+class Relationship(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(Relationship, self).__init__(_instance_cls=models.Relationship, *args, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        relationship = self._instance_cls(
+            name=self._template.name,
+            type=self._template.type,
+            relationship_template=self._template)
+
+        relationship.properties = self._topology.instantiate(self._template.properties)
+        relationship.interfaces = self._topology.instantiate(self._template.interface_templates)
+        return relationship
+
+    def validate(self):
+        pass
+
+
+class Operation(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(Operation, self).__init__(_instance_cls=models.Operation, *args, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        operation = self._instance_cls(
+            name=self._template.name,
+            description=utils.deepcopy_with_locators(self._template.description),
+            relationship_edge=self._template.relationship_edge,
+            implementation=self._template.implementation,
+            dependencies=self._template.dependencies,
+            executor=self._template.executor,
+            function=self._template.function,
+            max_attempts=self._template.max_attempts,
+            retry_interval=self._template.retry_interval,
+            operation_template=self._template)
+
+
+        if (self._template.plugin_specification is not None and
+            self._template.plugin_specification.enabled):
+            operation.plugin = self._template.plugin_specification.plugin
+
+        operation.inputs = self._topology.instantiate(self._template.inputs)
+        operation.configurations = self._topology.instantiate(self._template.configurations)
 
         return operation
 
+    def validate(self):
+        pass
+
+
+class Metadata(_Entity):
+
+    def __init__(self, *args, **kwargs):
+        super(Metadata, self).__init__(_instance_cls=models.Metadata, *args, **kwargs)
+
+    def dump(self):
+        pass
+
+    def coerce(self):
+        pass
+
+    def instantiate(self):
+        return self._instance_cls(name=self._template.name, value=self._template.value)
+
+    def validate(self):
+        pass
+
 
-initiator = Instantiation(consumption.ConsumptionContext.get_thread_local())
+handler = Handler()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/0bc7993f/aria/orchestrator/topology/utils.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/utils.py b/aria/orchestrator/topology/utils.py
index ec74391..ce81f30 100644
--- a/aria/orchestrator/topology/utils.py
+++ b/aria/orchestrator/topology/utils.py
@@ -15,6 +15,8 @@
 
 from copy import deepcopy
 
+from ...utils.versions import VersionString
+
 
 def deepcopy_with_locators(value):
     """
@@ -46,3 +48,20 @@ def copy_locators(target, source):
     elif isinstance(target, dict) and isinstance(source, dict):
         for k, v in target.items():
             copy_locators(v, source[k])
+
+
+def resolve_plugin_specification(plugin_specification, plugins):
+    matching_plugins = []
+    if plugins:
+        for plugin in plugins:
+            if all([plugin.name == plugin_specification.name,
+                    any([plugin_specification.version is None,
+                         VersionString(plugin.package_version) >= plugin_specification.version])
+                    ]):
+                matching_plugins.append(plugin)
+    plugin_specification.plugin = None
+    if matching_plugins:
+        # Return highest version of plugin
+        plugin_specification.plugin = \
+            max(matching_plugins, key=lambda plugin: VersionString(plugin.package_version).key)
+    return plugin_specification.plugin is not None

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/0bc7993f/aria/parser/consumption/modeling.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/modeling.py b/aria/parser/consumption/modeling.py
index e142327..34204ca 100644
--- a/aria/parser/consumption/modeling.py
+++ b/aria/parser/consumption/modeling.py
@@ -108,7 +108,7 @@ class InstantiateServiceInstance(Consumer):
             return
         from aria.orchestrator import topology
 
-        self.context.modeling.instance = topology.Instantiation(self.context).instantiate_service(
+        self.context.modeling.instance = topology.handler.instantiate(
             self.context.modeling.template,
             inputs=dict(self.context.modeling.inputs)
         )