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/27 14:15:31 UTC

[1/2] incubator-ariatosca git commit: removed the old style class from consumption, removed any unnecessary and local imports [Forced Update!]

Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-174-Refactor-instantiation-phase d1db39926 -> ec7b9c970 (forced update)


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/orchestrator/topology/template.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/template.py b/aria/orchestrator/topology/template.py
deleted file mode 100644
index 51be788..0000000
--- a/aria/orchestrator/topology/template.py
+++ /dev/null
@@ -1,583 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from datetime import datetime
-
-from ...utils import formatting
-from ...modeling import utils as modeling_utils
-from . import utils, common
-
-
-class ServiceTemplate(common._TemplateHandlerMixin):
-    def dump(self, console):
-        if self._model.description is not None:
-            console.write(console.meta(self._model.description))
-        self._topology.dump(self._model.meta_data, console, 'Metadata')
-        self._topology.dump(self._model.node_templates, console)
-        self._topology.dump(self._model.group_templates, console)
-        self._topology.dump(self._model.policy_templates, console)
-        self._topology.dump(self._model.substitution_template, console)
-        self._topology.dump(self._model.inputs, console, 'Inputs')
-        self._topology.dump(self._model.outputs, console, 'Outputs')
-        self._topology.dump(self._model.workflow_templates, console, 'Workflow templates')
-
-    def coerce(self, **kwargs):
-        self._coerce(self._model.meta_data,
-                     self._model.node_templates,
-                     self._model.group_templates,
-                     self._model.policy_templates,
-                     self._model.substitution_template,
-                     self._model.inputs,
-                     self._model.outputs,
-                     self._model.workflow_templates,
-                     **kwargs)
-
-    def instantiate(self, instance_cls, inputs=None):                                               # pylint: disable=arguments-differ
-        now = datetime.now()
-        service = instance_cls(
-            created_at=now,
-            updated_at=now,
-            description=utils.deepcopy_with_locators(self._model.description),
-            service_template=self._model,
-            inputs=modeling_utils.merge_parameter_values(inputs, self._model.inputs)
-        )
-
-        for plugin_specification in self._model.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._topology.report('specified plugin not found: {0}'.format(
-                        plugin_specification.name), level=self._topology.Issue.EXTERNAL)
-        service.meta_data = self._topology.instantiate(self._model.meta_data)
-
-        for node_template in self._model.node_templates.itervalues():
-            for _ in range(self._scaling(node_template)['default_instances']):
-                node = self._topology.instantiate(node_template)
-                service.nodes[node.name] = node
-
-        service.groups = self._topology.instantiate(self._model.group_templates)
-        service.policies = self._topology.instantiate(self._model.policy_templates)
-        service.workflows = self._topology.instantiate(self._model.workflow_templates)
-        service.substitution = self._topology.instantiate(self._model.substitution_template)
-        service.outputs = self._topology.instantiate(self._model.outputs)
-
-        return service
-
-    def _scaling(self, node_template):
-        scaling = {}
-
-        def extract_property(properties, name):
-            if name in scaling:
-                return
-            prop = properties.get(name)
-            if (prop is not None) and (prop.type_name == 'integer') and (prop.value is not None):
-                scaling[name] = prop.value
-
-        def extract_properties(properties):
-            extract_property(properties, 'min_instances')
-            extract_property(properties, 'max_instances')
-            extract_property(properties, 'default_instances')
-
-        # From our scaling capabilities
-        for capability_template in node_template.capability_templates.itervalues():
-            if capability_template.type.role == 'scaling':
-                extract_properties(capability_template.properties)
-
-        # From service scaling policies
-        for policy_template in node_template.service_template.policy_templates.itervalues():
-            if policy_template.type.role == 'scaling':
-                if policy_template.is_for_node_template(node_template.name):
-                    extract_properties(policy_template.properties)
-
-        # Defaults
-        scaling.setdefault('min_instances', 0)
-        scaling.setdefault('max_instances', 1)
-        scaling.setdefault('default_instances', 1)
-
-        # Validate
-        # pylint: disable=too-many-boolean-expressions
-        if (scaling['min_instances'] < 0 or
-                scaling['max_instances'] < 0 or
-                scaling['default_instances'] < 0 or
-                scaling['max_instances'] < scaling['min_instances'] or
-                scaling['default_instances'] < scaling['min_instances'] or
-                scaling['default_instances'] > scaling['max_instances']):
-            self._topology.report(
-                'invalid scaling parameters for node template "{0}": min={min_instances}, max='
-                '{max_instances}, default={default_instances}'.format(self._model.name, **scaling),
-                level=self._topology.Issue.BETWEEN_TYPES)
-
-        return scaling
-
-    def validate(self):
-        self._topology.validate(self._model.meta_data)
-        self._topology.validate(self._model.node_templates)
-        self._topology.validate(self._model.group_templates)
-        self._topology.validate(self._model.policy_templates)
-        self._topology.validate(self._model.substitution_template)
-        self._topology.validate(self._model.inputs)
-        self._topology.validate(self._model.outputs)
-        self._topology.validate(self._model.workflow_templates)
-        self._topology.validate(self._model.node_types)
-        self._topology.validate(self._model.group_types)
-        self._topology.validate(self._model.policy_types)
-        self._topology.validate(self._model.relationship_types)
-        self._topology.validate(self._model.capability_types)
-        self._topology.validate(self._model.interface_types)
-        self._topology.validate(self._model.artifact_types)
-
-
-class ArtifactTemplate(common._TemplateHandlerMixin):
-    def dump(self, console):
-        console.write(console.node(self._model.name))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            console.write('Artifact type: {0}'.format(console.type(self._model.type.name)))
-            console.write('Source path: {0}'.format(console.literal(self._model.source_path)))
-            if self._model.target_path is not None:
-                console.write('Target path: {0}'.format(console.literal(self._model.target_path)))
-            if self._model.repository_url is not None:
-                console.write('Repository URL: {0}'.format(
-                    console.literal(self._model.repository_url)))
-            if self._model.repository_credential:
-                console.write('Repository credential: {0}'.format(
-                    console.literal(self._model.repository_credential)))
-            self._topology.dump(self._model.properties, console, 'Properties')
-
-    def coerce(self, **kwargs):
-        self._topology.coerce(self._model.properties, **kwargs)
-
-    def instantiate(self, instance_cls):
-        return instance_cls(
-            name=self._model.name,
-            type=self._model.type,
-            description=utils.deepcopy_with_locators(self._model.description),
-            source_path=self._model.source_path,
-            target_path=self._model.target_path,
-            repository_url=self._model.repository_url,
-            repository_credential=self._model.repository_credential,
-            artifact_template=self._model)
-
-    def validate(self):
-        self._topology.validate(self._model.properties)
-
-
-class CapabilityTemplate(common._TemplateHandlerMixin):
-    def dump(self, console):
-        console.write(console.node(self._model.name))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            console.write('Type: {0}'.format(console.type(self._model.type.name)))
-            console.write(
-                'Occurrences: {0:d}{1}'.format(
-                    self._model.min_occurrences or 0,
-                    ' to {0:d}'.format(self._model.max_occurrences)
-                    if self._model.max_occurrences is not None
-                    else ' or more'))
-            if self._model.valid_source_node_types:
-                console.write('Valid source node types: {0}'.format(
-                    ', '.join((str(console.type(v.name))
-                               for v in self._model.valid_source_node_types))))
-            self._topology.dump(self._model.properties, console, 'Properties')
-
-    def coerce(self):
-        self._topology.coerce(self._model.properties)
-
-    def instantiate(self, instance_cls):
-        return instance_cls(name=self._model.name,
-                            type=self._model.type,
-                            min_occurrences=self._model.min_occurrences,
-                            max_occurrences=self._model.max_occurrences,
-                            occurrences=0,
-                            capability_template=self._model)
-
-    def validate(self):
-        self._topology.validate(self._model.properties)
-
-
-class RequirementTemplate(common._TemplateHandlerMixin):
-    def dump(self, console):
-        if self._model.name:
-            console.write(console.node(self._model.name))
-        else:
-            console.write('Requirement:')
-        with console.indent:
-            if self._model.target_node_type is not None:
-                console.write('Target node type: {0}'.format(
-                    console.type(self._model.target_node_type.name)))
-            elif self._model.target_node_template is not None:
-                console.write('Target node template: {0}'.format(
-                    console.node(self._model.target_node_template.name)))
-            if self._model.target_capability_type is not None:
-                console.write('Target capability type: {0}'.format(
-                    console.type(self._model.target_capability_type.name)))
-            elif self._model.target_capability_name is not None:
-                console.write('Target capability name: {0}'.format(
-                    console.node(self._model.target_capability_name)))
-            if self._model.target_node_template_constraints:
-                console.write('Target node template constraints:')
-                with console.indent:
-                    for constraint in self._model.target_node_template_constraints:
-                        console.write(console.literal(constraint))
-            if self._model.relationship_template:
-                console.write('Relationship:')
-                with console.indent:
-                    self._topology.dump(self._model.relationship_template, console)
-
-    def coerce(self, **kwargs):
-        self._topology.coerce(self._model.relationship_template, **kwargs)
-
-    def instantiate(self, instance_cls):
-        return instance_cls(name=self._model.name,
-                            type=self._model.type,
-                            min_occurrences=self._model.min_occurrences,
-                            max_occurrences=self._model.max_occurrences,
-                            occurrences=0,
-                            capability_template=self._model)
-
-    def validate(self):
-        self._topology.validate(self._model.relationship_template)
-
-
-class GroupTemplate(common._TemplateHandlerMixin):
-    def dump(self, console):
-        console.write('Group template: {0}'.format(console.node(self._model.name)))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            console.write('Type: {0}'.format(console.type(self._model.type.name)))
-            self._topology.dump(self._model.properties, console, 'Properties')
-            self._topology.dump(self._model.interface_templates, console, 'Interface Templates')
-            if self._model.node_templates:
-                console.write('Member node templates: {0}'.format(', '.join(
-                    (str(console.node(v.name)) for v in self._model.node_templates))))
-
-    def coerce(self, **kwargs):
-        self._coerce(self._model.properties,
-                     self._model.interface_templates,
-                     **kwargs)
-
-    def instantiate(self, instance_cls):
-        group = instance_cls(
-            name=self._model.name,
-            type=self._model.type,
-            description=utils.deepcopy_with_locators(self._model.description),
-            group_template=self._model)
-        group.properties = self._topology.instantiate(self._model.properties)
-        group.interfaces = self._topology.instantiate(self._model.interface_templates)
-        if self._model.node_templates:
-            for node_template in self._model.node_templates:
-                group.nodes += node_template.nodes
-        return group
-
-    def validate(self):
-        self._validate(self._model.properties,
-                       self._model.interface_templates)
-
-
-class InterfaceTemplate(common._TemplateHandlerMixin):
-    def dump(self, console):
-        console.write(console.node(self._model.name))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            console.write('Interface type: {0}'.format(console.type(self._model.type.name)))
-            self._topology.dump(self._model.inputs, console, 'Inputs')
-            self._topology.dump(self._model.operation_templates, console, 'Operation templates')
-
-    def coerce(self, **kwargs):
-        self._coerce(self._model.inputs,
-                     self._model.operation_templates,
-                     **kwargs)
-
-    def instantiate(self, instance_cls):
-        interface = instance_cls(
-            name=self._model.name,
-            type=self._model.type,
-            description=utils.deepcopy_with_locators(self._model.description),
-            interface_template=self._model)
-        interface.inputs = self._topology.instantiate(self._model.inputs)
-        interface.operations = self._topology.instantiate(self._model.operation_templates)
-        return interface
-
-    def validate(self):
-        self._validate(self._model.inputs,
-                       self._model.operation_templates)
-
-
-class NodeTemplate(common._TemplateHandlerMixin):
-    def dump(self, console):
-        console.write('Node template: {0}'.format(console.node(self._model.name)))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        console.write('Type: {0}'.format(console.type(self._model.type.name)))
-        self._topology.dump(self._model.properties, console, 'Properties')
-        self._topology.dump(self._model.attributes, console, 'Attributes')
-        self._topology.dump(self._model.interface_templates, console, 'Interface Templates')
-        self._topology.dump(self._model.artifact_templates, console, 'Artifact Templates')
-        self._topology.dump(self._model.capability_templates, console, 'Capability Templates')
-        self._topology.dump(self._model.requirement_templates, console, 'Requirement Templates')
-
-    def coerce(self, **kwargs):
-        self._coerce(self._model.properties,
-                     self._model.attributes,
-                     self._model.interface_templates,
-                     self._model.artifact_templates,
-                     self._model.capability_templates,
-                     self._model.requirement_templates,
-                     **kwargs)
-
-    def instantiate(self, instance_cls):
-        node = instance_cls(
-            name=self._model._next_name,
-            type=self._model.type,
-            description=utils.deepcopy_with_locators(self._model.description),
-            node_template=self._model
-        )
-
-        node.properties = self._topology.instantiate(self._model.properties)
-        node.attributes = self._topology.instantiate(self._model.attributes)
-        node.interfaces = self._topology.instantiate(self._model.interface_templates)
-        node.artifacts = self._topology.instantiate(self._model.artifact_templates)
-        node.capabilities = self._topology.instantiate(self._model.capability_templates)
-
-        # Default attributes
-        if 'tosca_name' in node.attributes and node.attributes['tosca_name'].type_name == 'string':
-            node.attributes['tosca_name'].value = self._model.name
-        if 'tosca_id' in node.attributes and node.attributes['tosca_id'].type_name == 'string':
-            node.attributes['tosca_id'].value = node.name
-
-        return node
-
-    def validate(self):
-        self._validate(self._model.properties,
-                       self._model.attributes,
-                       self._model.interface_templates,
-                       self._model.artifact_templates,
-                       self._model.capability_templates,
-                       self._model.requirement_templates)
-
-
-class PolicyTemplate(common._TemplateHandlerMixin):
-    def dump(self, console):
-        console.write('Policy template: {0}'.format(console.node(self._model.name)))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            console.write('Type: {0}'.format(console.type(self._model.type.name)))
-            self._topology.dump(self._model.properties, console, 'Properties')
-            if self._model.node_templates:
-                console.write('Target node templates: {0}'.format(', '.join(
-                    (str(console.node(v.name)) for v in self._model.node_templates))))
-            if self._model.group_templates:
-                console.write('Target group templates: {0}'.format(', '.join(
-                    (str(console.node(v.name)) for v in self._model.group_templates))))
-
-    def coerce(self, **kwargs):
-        self._topology.coerce(self._model.properties, **kwargs)
-
-    def instantiate(self, instance_cls):
-        policy = instance_cls(
-            name=self._model.name,
-            type=self._model.type,
-            description=utils.deepcopy_with_locators(self._model.description),
-            policy_template=self._model)
-
-        policy.properties = self._topology.instantiate(self._model.properties)
-        if self._model.node_templates:
-            for node_template in self._model.node_templates:
-                policy.nodes += node_template.nodes
-        if self._model.group_templates:
-            for group_template in self._model.group_templates:
-                policy.groups += group_template.groups
-        return policy
-
-    def validate(self):
-        self._topology.validate(self._model.properties)
-
-
-class SubstitutionTemplate(common._TemplateHandlerMixin):
-
-    def dump(self, console):
-        console.write('Substitution template:')
-        with console.indent:
-            console.write('Node type: {0}'.format(console.type(self._model.node_type.name)))
-            self._topology.dump(self._model.mappings, console, 'Mappings')
-
-    def coerce(self, **kwargs):
-        self._topology.coerce(self._model.mappings, **kwargs)
-
-    def instantiate(self, instance_cls):
-        return instance_cls(node_type=self._model.node_type,
-                            substitution_template=self._model)
-
-    def validate(self):
-        self._topology.validate(self._model.mappings)
-
-
-class SubstitutionTemplateMapping(common._TemplateHandlerMixin):
-
-    def dump(self, console):
-        if self._topology.capability_template is not None:
-            node_template = self._topology.capability_template.node_template
-        else:
-            node_template = self._topology.requirement_template.node_template
-        console.write('{0} -> {1}.{2}'.format(
-            console.node(self._topology.name),
-            console.node(node_template.name),
-            console.node(self._topology.capability_template.name
-                         if self._topology.capability_template
-                         else self._topology.requirement_template.name)))
-
-    def coerce(self):
-        pass
-
-    def instantiate(self, instance_cls):
-        substitution_mapping = instance_cls(
-            name=self._model.name,
-            requirement_template=self._model.requirement_template)
-
-        if self._model.capability_template is not None:
-            node_template = self._model.capability_template.node_template
-        else:
-            node_template = self._model.requirement_template.node_template
-        nodes = node_template.nodes
-        if len(nodes) == 0:
-            self._topology.report(
-                'mapping "{0}" refers to node template "{1}" but there are no node instances'.
-                format(self._model.mapped_name, self._model.node_template.name),
-                level=self._topology.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
-        substitution_mapping.node = nodes[0]
-        if self._model.capability_template:
-            for a_capability in substitution_mapping.node.capabilities.itervalues():
-                if a_capability.capability_template.name == \
-                        self._model.capability_template.name:
-                    substitution_mapping.capability = a_capability
-
-        return substitution_mapping
-
-    def validate(self):
-        if self._model.capability_template is None and self._model.requirement_template is None:
-            self._topology.report(
-                'mapping "{0}" refers to neither capability nor a requirement '
-                'in node template: {1}'.format(
-                    self._model.name, formatting.safe_repr(self._model.node_template.name)),
-                level=self._topology.Issue.BETWEEN_TYPES)
-
-
-class RelationshipTemplate(common._TemplateHandlerMixin):
-    def dump(self, console):
-        if self._model.type is not None:
-            console.write('Relationship type: {0}'.format(console.type(self._model.type.name)))
-        else:
-            console.write('Relationship template: {0}'.format(
-                console.node(self._model.name)))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            self._topology.dump(self._model.properties, console, 'Properties')
-            self._topology.dump(self._model.interface_templates, console, 'Interface Templates')
-
-    def coerce(self, **kwargs):
-        self._coerce(self._model.properties, self._model.interface_templates, **kwargs)
-
-    def instantiate(self, instance_cls):
-        relationship = instance_cls(
-            name=self._model.name,
-            type=self._model.type,
-            relationship_template=self._model)
-
-        relationship.properties = self._topology.instantiate(self._model.properties)
-        relationship.interfaces = self._topology.instantiate(self._model.interface_templates)
-        return relationship
-
-    def validate(self):
-        self._validate(self._model.properties, self._model.interface_templates)
-
-
-class OperationTemplate(common._TemplateHandlerMixin):
-
-    def dump(self, console):
-        console.write(console.node(self._model.name))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            if self._model.implementation is not None:
-                console.write('Implementation: {0}'.format(
-                    console.literal(self._model.implementation)))
-            if self._model.dependencies:
-                console.write('Dependencies: {0}'.format(
-                    ', '.join((str(console.literal(v)) for v in self._model.dependencies))))
-            self._topology.dump(self._model.inputs, console, 'Inputs')
-            if self._model.executor is not None:
-                console.write('Executor: {0}'.format(console.literal(self._model.executor)))
-            if self._model.max_attempts is not None:
-                console.write('Max attempts: {0}'.format(console.literal(self._model.max_attempts)))
-            if self._model.retry_interval is not None:
-                console.write('Retry interval: {0}'.format(
-                    console.literal(self._model.retry_interval)))
-            if self._model.plugin_specification is not None:
-                console.write('Plugin specification: {0}'.format(
-                    console.literal(self._model.plugin_specification.name)))
-            self._topology.dump(self._model.configurations, console, 'Configuration')
-            if self._model.function is not None:
-                console.write('Function: {0}'.format(console.literal(self._model.function)))
-
-    def coerce(self, **kwargs):
-        self._coerce(self._model.inputs,
-                     self._model.configurations,
-                     **kwargs)
-
-    def instantiate(self, instance_cls):
-        operation = instance_cls(
-            name=self._model.name,
-            description=utils.deepcopy_with_locators(self._model.description),
-            relationship_edge=self._model.relationship_edge,
-            implementation=self._model.implementation,
-            dependencies=self._model.dependencies,
-            executor=self._model.executor,
-            function=self._model.function,
-            max_attempts=self._model.max_attempts,
-            retry_interval=self._model.retry_interval,
-            operation_template=self._model)
-
-        if (self._model.plugin_specification is not None and
-                self._model.plugin_specification.enabled):
-            operation.plugin = self._model.plugin_specification.plugin
-
-        operation.inputs = self._topology.instantiate(self._model.inputs)
-        operation.configurations = self._topology.instantiate(self._model.configurations)
-
-        return operation
-
-    def validate(self):
-        self._validate(self._model.inputs,
-                       self._model.configurations)
-
-
-class PluginSpecification(common._TemplateHandlerMixin):
-    def instantiate(self, **kwargs):
-        pass
-
-    def dump(self, console):
-        pass

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/orchestrator/topology/template_handler.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/template_handler.py b/aria/orchestrator/topology/template_handler.py
new file mode 100644
index 0000000..51be788
--- /dev/null
+++ b/aria/orchestrator/topology/template_handler.py
@@ -0,0 +1,583 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from datetime import datetime
+
+from ...utils import formatting
+from ...modeling import utils as modeling_utils
+from . import utils, common
+
+
+class ServiceTemplate(common._TemplateHandlerMixin):
+    def dump(self, console):
+        if self._model.description is not None:
+            console.write(console.meta(self._model.description))
+        self._topology.dump(self._model.meta_data, console, 'Metadata')
+        self._topology.dump(self._model.node_templates, console)
+        self._topology.dump(self._model.group_templates, console)
+        self._topology.dump(self._model.policy_templates, console)
+        self._topology.dump(self._model.substitution_template, console)
+        self._topology.dump(self._model.inputs, console, 'Inputs')
+        self._topology.dump(self._model.outputs, console, 'Outputs')
+        self._topology.dump(self._model.workflow_templates, console, 'Workflow templates')
+
+    def coerce(self, **kwargs):
+        self._coerce(self._model.meta_data,
+                     self._model.node_templates,
+                     self._model.group_templates,
+                     self._model.policy_templates,
+                     self._model.substitution_template,
+                     self._model.inputs,
+                     self._model.outputs,
+                     self._model.workflow_templates,
+                     **kwargs)
+
+    def instantiate(self, instance_cls, inputs=None):                                               # pylint: disable=arguments-differ
+        now = datetime.now()
+        service = instance_cls(
+            created_at=now,
+            updated_at=now,
+            description=utils.deepcopy_with_locators(self._model.description),
+            service_template=self._model,
+            inputs=modeling_utils.merge_parameter_values(inputs, self._model.inputs)
+        )
+
+        for plugin_specification in self._model.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._topology.report('specified plugin not found: {0}'.format(
+                        plugin_specification.name), level=self._topology.Issue.EXTERNAL)
+        service.meta_data = self._topology.instantiate(self._model.meta_data)
+
+        for node_template in self._model.node_templates.itervalues():
+            for _ in range(self._scaling(node_template)['default_instances']):
+                node = self._topology.instantiate(node_template)
+                service.nodes[node.name] = node
+
+        service.groups = self._topology.instantiate(self._model.group_templates)
+        service.policies = self._topology.instantiate(self._model.policy_templates)
+        service.workflows = self._topology.instantiate(self._model.workflow_templates)
+        service.substitution = self._topology.instantiate(self._model.substitution_template)
+        service.outputs = self._topology.instantiate(self._model.outputs)
+
+        return service
+
+    def _scaling(self, node_template):
+        scaling = {}
+
+        def extract_property(properties, name):
+            if name in scaling:
+                return
+            prop = properties.get(name)
+            if (prop is not None) and (prop.type_name == 'integer') and (prop.value is not None):
+                scaling[name] = prop.value
+
+        def extract_properties(properties):
+            extract_property(properties, 'min_instances')
+            extract_property(properties, 'max_instances')
+            extract_property(properties, 'default_instances')
+
+        # From our scaling capabilities
+        for capability_template in node_template.capability_templates.itervalues():
+            if capability_template.type.role == 'scaling':
+                extract_properties(capability_template.properties)
+
+        # From service scaling policies
+        for policy_template in node_template.service_template.policy_templates.itervalues():
+            if policy_template.type.role == 'scaling':
+                if policy_template.is_for_node_template(node_template.name):
+                    extract_properties(policy_template.properties)
+
+        # Defaults
+        scaling.setdefault('min_instances', 0)
+        scaling.setdefault('max_instances', 1)
+        scaling.setdefault('default_instances', 1)
+
+        # Validate
+        # pylint: disable=too-many-boolean-expressions
+        if (scaling['min_instances'] < 0 or
+                scaling['max_instances'] < 0 or
+                scaling['default_instances'] < 0 or
+                scaling['max_instances'] < scaling['min_instances'] or
+                scaling['default_instances'] < scaling['min_instances'] or
+                scaling['default_instances'] > scaling['max_instances']):
+            self._topology.report(
+                'invalid scaling parameters for node template "{0}": min={min_instances}, max='
+                '{max_instances}, default={default_instances}'.format(self._model.name, **scaling),
+                level=self._topology.Issue.BETWEEN_TYPES)
+
+        return scaling
+
+    def validate(self):
+        self._topology.validate(self._model.meta_data)
+        self._topology.validate(self._model.node_templates)
+        self._topology.validate(self._model.group_templates)
+        self._topology.validate(self._model.policy_templates)
+        self._topology.validate(self._model.substitution_template)
+        self._topology.validate(self._model.inputs)
+        self._topology.validate(self._model.outputs)
+        self._topology.validate(self._model.workflow_templates)
+        self._topology.validate(self._model.node_types)
+        self._topology.validate(self._model.group_types)
+        self._topology.validate(self._model.policy_types)
+        self._topology.validate(self._model.relationship_types)
+        self._topology.validate(self._model.capability_types)
+        self._topology.validate(self._model.interface_types)
+        self._topology.validate(self._model.artifact_types)
+
+
+class ArtifactTemplate(common._TemplateHandlerMixin):
+    def dump(self, console):
+        console.write(console.node(self._model.name))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            console.write('Artifact type: {0}'.format(console.type(self._model.type.name)))
+            console.write('Source path: {0}'.format(console.literal(self._model.source_path)))
+            if self._model.target_path is not None:
+                console.write('Target path: {0}'.format(console.literal(self._model.target_path)))
+            if self._model.repository_url is not None:
+                console.write('Repository URL: {0}'.format(
+                    console.literal(self._model.repository_url)))
+            if self._model.repository_credential:
+                console.write('Repository credential: {0}'.format(
+                    console.literal(self._model.repository_credential)))
+            self._topology.dump(self._model.properties, console, 'Properties')
+
+    def coerce(self, **kwargs):
+        self._topology.coerce(self._model.properties, **kwargs)
+
+    def instantiate(self, instance_cls):
+        return instance_cls(
+            name=self._model.name,
+            type=self._model.type,
+            description=utils.deepcopy_with_locators(self._model.description),
+            source_path=self._model.source_path,
+            target_path=self._model.target_path,
+            repository_url=self._model.repository_url,
+            repository_credential=self._model.repository_credential,
+            artifact_template=self._model)
+
+    def validate(self):
+        self._topology.validate(self._model.properties)
+
+
+class CapabilityTemplate(common._TemplateHandlerMixin):
+    def dump(self, console):
+        console.write(console.node(self._model.name))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            console.write('Type: {0}'.format(console.type(self._model.type.name)))
+            console.write(
+                'Occurrences: {0:d}{1}'.format(
+                    self._model.min_occurrences or 0,
+                    ' to {0:d}'.format(self._model.max_occurrences)
+                    if self._model.max_occurrences is not None
+                    else ' or more'))
+            if self._model.valid_source_node_types:
+                console.write('Valid source node types: {0}'.format(
+                    ', '.join((str(console.type(v.name))
+                               for v in self._model.valid_source_node_types))))
+            self._topology.dump(self._model.properties, console, 'Properties')
+
+    def coerce(self):
+        self._topology.coerce(self._model.properties)
+
+    def instantiate(self, instance_cls):
+        return instance_cls(name=self._model.name,
+                            type=self._model.type,
+                            min_occurrences=self._model.min_occurrences,
+                            max_occurrences=self._model.max_occurrences,
+                            occurrences=0,
+                            capability_template=self._model)
+
+    def validate(self):
+        self._topology.validate(self._model.properties)
+
+
+class RequirementTemplate(common._TemplateHandlerMixin):
+    def dump(self, console):
+        if self._model.name:
+            console.write(console.node(self._model.name))
+        else:
+            console.write('Requirement:')
+        with console.indent:
+            if self._model.target_node_type is not None:
+                console.write('Target node type: {0}'.format(
+                    console.type(self._model.target_node_type.name)))
+            elif self._model.target_node_template is not None:
+                console.write('Target node template: {0}'.format(
+                    console.node(self._model.target_node_template.name)))
+            if self._model.target_capability_type is not None:
+                console.write('Target capability type: {0}'.format(
+                    console.type(self._model.target_capability_type.name)))
+            elif self._model.target_capability_name is not None:
+                console.write('Target capability name: {0}'.format(
+                    console.node(self._model.target_capability_name)))
+            if self._model.target_node_template_constraints:
+                console.write('Target node template constraints:')
+                with console.indent:
+                    for constraint in self._model.target_node_template_constraints:
+                        console.write(console.literal(constraint))
+            if self._model.relationship_template:
+                console.write('Relationship:')
+                with console.indent:
+                    self._topology.dump(self._model.relationship_template, console)
+
+    def coerce(self, **kwargs):
+        self._topology.coerce(self._model.relationship_template, **kwargs)
+
+    def instantiate(self, instance_cls):
+        return instance_cls(name=self._model.name,
+                            type=self._model.type,
+                            min_occurrences=self._model.min_occurrences,
+                            max_occurrences=self._model.max_occurrences,
+                            occurrences=0,
+                            capability_template=self._model)
+
+    def validate(self):
+        self._topology.validate(self._model.relationship_template)
+
+
+class GroupTemplate(common._TemplateHandlerMixin):
+    def dump(self, console):
+        console.write('Group template: {0}'.format(console.node(self._model.name)))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            console.write('Type: {0}'.format(console.type(self._model.type.name)))
+            self._topology.dump(self._model.properties, console, 'Properties')
+            self._topology.dump(self._model.interface_templates, console, 'Interface Templates')
+            if self._model.node_templates:
+                console.write('Member node templates: {0}'.format(', '.join(
+                    (str(console.node(v.name)) for v in self._model.node_templates))))
+
+    def coerce(self, **kwargs):
+        self._coerce(self._model.properties,
+                     self._model.interface_templates,
+                     **kwargs)
+
+    def instantiate(self, instance_cls):
+        group = instance_cls(
+            name=self._model.name,
+            type=self._model.type,
+            description=utils.deepcopy_with_locators(self._model.description),
+            group_template=self._model)
+        group.properties = self._topology.instantiate(self._model.properties)
+        group.interfaces = self._topology.instantiate(self._model.interface_templates)
+        if self._model.node_templates:
+            for node_template in self._model.node_templates:
+                group.nodes += node_template.nodes
+        return group
+
+    def validate(self):
+        self._validate(self._model.properties,
+                       self._model.interface_templates)
+
+
+class InterfaceTemplate(common._TemplateHandlerMixin):
+    def dump(self, console):
+        console.write(console.node(self._model.name))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            console.write('Interface type: {0}'.format(console.type(self._model.type.name)))
+            self._topology.dump(self._model.inputs, console, 'Inputs')
+            self._topology.dump(self._model.operation_templates, console, 'Operation templates')
+
+    def coerce(self, **kwargs):
+        self._coerce(self._model.inputs,
+                     self._model.operation_templates,
+                     **kwargs)
+
+    def instantiate(self, instance_cls):
+        interface = instance_cls(
+            name=self._model.name,
+            type=self._model.type,
+            description=utils.deepcopy_with_locators(self._model.description),
+            interface_template=self._model)
+        interface.inputs = self._topology.instantiate(self._model.inputs)
+        interface.operations = self._topology.instantiate(self._model.operation_templates)
+        return interface
+
+    def validate(self):
+        self._validate(self._model.inputs,
+                       self._model.operation_templates)
+
+
+class NodeTemplate(common._TemplateHandlerMixin):
+    def dump(self, console):
+        console.write('Node template: {0}'.format(console.node(self._model.name)))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        console.write('Type: {0}'.format(console.type(self._model.type.name)))
+        self._topology.dump(self._model.properties, console, 'Properties')
+        self._topology.dump(self._model.attributes, console, 'Attributes')
+        self._topology.dump(self._model.interface_templates, console, 'Interface Templates')
+        self._topology.dump(self._model.artifact_templates, console, 'Artifact Templates')
+        self._topology.dump(self._model.capability_templates, console, 'Capability Templates')
+        self._topology.dump(self._model.requirement_templates, console, 'Requirement Templates')
+
+    def coerce(self, **kwargs):
+        self._coerce(self._model.properties,
+                     self._model.attributes,
+                     self._model.interface_templates,
+                     self._model.artifact_templates,
+                     self._model.capability_templates,
+                     self._model.requirement_templates,
+                     **kwargs)
+
+    def instantiate(self, instance_cls):
+        node = instance_cls(
+            name=self._model._next_name,
+            type=self._model.type,
+            description=utils.deepcopy_with_locators(self._model.description),
+            node_template=self._model
+        )
+
+        node.properties = self._topology.instantiate(self._model.properties)
+        node.attributes = self._topology.instantiate(self._model.attributes)
+        node.interfaces = self._topology.instantiate(self._model.interface_templates)
+        node.artifacts = self._topology.instantiate(self._model.artifact_templates)
+        node.capabilities = self._topology.instantiate(self._model.capability_templates)
+
+        # Default attributes
+        if 'tosca_name' in node.attributes and node.attributes['tosca_name'].type_name == 'string':
+            node.attributes['tosca_name'].value = self._model.name
+        if 'tosca_id' in node.attributes and node.attributes['tosca_id'].type_name == 'string':
+            node.attributes['tosca_id'].value = node.name
+
+        return node
+
+    def validate(self):
+        self._validate(self._model.properties,
+                       self._model.attributes,
+                       self._model.interface_templates,
+                       self._model.artifact_templates,
+                       self._model.capability_templates,
+                       self._model.requirement_templates)
+
+
+class PolicyTemplate(common._TemplateHandlerMixin):
+    def dump(self, console):
+        console.write('Policy template: {0}'.format(console.node(self._model.name)))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            console.write('Type: {0}'.format(console.type(self._model.type.name)))
+            self._topology.dump(self._model.properties, console, 'Properties')
+            if self._model.node_templates:
+                console.write('Target node templates: {0}'.format(', '.join(
+                    (str(console.node(v.name)) for v in self._model.node_templates))))
+            if self._model.group_templates:
+                console.write('Target group templates: {0}'.format(', '.join(
+                    (str(console.node(v.name)) for v in self._model.group_templates))))
+
+    def coerce(self, **kwargs):
+        self._topology.coerce(self._model.properties, **kwargs)
+
+    def instantiate(self, instance_cls):
+        policy = instance_cls(
+            name=self._model.name,
+            type=self._model.type,
+            description=utils.deepcopy_with_locators(self._model.description),
+            policy_template=self._model)
+
+        policy.properties = self._topology.instantiate(self._model.properties)
+        if self._model.node_templates:
+            for node_template in self._model.node_templates:
+                policy.nodes += node_template.nodes
+        if self._model.group_templates:
+            for group_template in self._model.group_templates:
+                policy.groups += group_template.groups
+        return policy
+
+    def validate(self):
+        self._topology.validate(self._model.properties)
+
+
+class SubstitutionTemplate(common._TemplateHandlerMixin):
+
+    def dump(self, console):
+        console.write('Substitution template:')
+        with console.indent:
+            console.write('Node type: {0}'.format(console.type(self._model.node_type.name)))
+            self._topology.dump(self._model.mappings, console, 'Mappings')
+
+    def coerce(self, **kwargs):
+        self._topology.coerce(self._model.mappings, **kwargs)
+
+    def instantiate(self, instance_cls):
+        return instance_cls(node_type=self._model.node_type,
+                            substitution_template=self._model)
+
+    def validate(self):
+        self._topology.validate(self._model.mappings)
+
+
+class SubstitutionTemplateMapping(common._TemplateHandlerMixin):
+
+    def dump(self, console):
+        if self._topology.capability_template is not None:
+            node_template = self._topology.capability_template.node_template
+        else:
+            node_template = self._topology.requirement_template.node_template
+        console.write('{0} -> {1}.{2}'.format(
+            console.node(self._topology.name),
+            console.node(node_template.name),
+            console.node(self._topology.capability_template.name
+                         if self._topology.capability_template
+                         else self._topology.requirement_template.name)))
+
+    def coerce(self):
+        pass
+
+    def instantiate(self, instance_cls):
+        substitution_mapping = instance_cls(
+            name=self._model.name,
+            requirement_template=self._model.requirement_template)
+
+        if self._model.capability_template is not None:
+            node_template = self._model.capability_template.node_template
+        else:
+            node_template = self._model.requirement_template.node_template
+        nodes = node_template.nodes
+        if len(nodes) == 0:
+            self._topology.report(
+                'mapping "{0}" refers to node template "{1}" but there are no node instances'.
+                format(self._model.mapped_name, self._model.node_template.name),
+                level=self._topology.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
+        substitution_mapping.node = nodes[0]
+        if self._model.capability_template:
+            for a_capability in substitution_mapping.node.capabilities.itervalues():
+                if a_capability.capability_template.name == \
+                        self._model.capability_template.name:
+                    substitution_mapping.capability = a_capability
+
+        return substitution_mapping
+
+    def validate(self):
+        if self._model.capability_template is None and self._model.requirement_template is None:
+            self._topology.report(
+                'mapping "{0}" refers to neither capability nor a requirement '
+                'in node template: {1}'.format(
+                    self._model.name, formatting.safe_repr(self._model.node_template.name)),
+                level=self._topology.Issue.BETWEEN_TYPES)
+
+
+class RelationshipTemplate(common._TemplateHandlerMixin):
+    def dump(self, console):
+        if self._model.type is not None:
+            console.write('Relationship type: {0}'.format(console.type(self._model.type.name)))
+        else:
+            console.write('Relationship template: {0}'.format(
+                console.node(self._model.name)))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            self._topology.dump(self._model.properties, console, 'Properties')
+            self._topology.dump(self._model.interface_templates, console, 'Interface Templates')
+
+    def coerce(self, **kwargs):
+        self._coerce(self._model.properties, self._model.interface_templates, **kwargs)
+
+    def instantiate(self, instance_cls):
+        relationship = instance_cls(
+            name=self._model.name,
+            type=self._model.type,
+            relationship_template=self._model)
+
+        relationship.properties = self._topology.instantiate(self._model.properties)
+        relationship.interfaces = self._topology.instantiate(self._model.interface_templates)
+        return relationship
+
+    def validate(self):
+        self._validate(self._model.properties, self._model.interface_templates)
+
+
+class OperationTemplate(common._TemplateHandlerMixin):
+
+    def dump(self, console):
+        console.write(console.node(self._model.name))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            if self._model.implementation is not None:
+                console.write('Implementation: {0}'.format(
+                    console.literal(self._model.implementation)))
+            if self._model.dependencies:
+                console.write('Dependencies: {0}'.format(
+                    ', '.join((str(console.literal(v)) for v in self._model.dependencies))))
+            self._topology.dump(self._model.inputs, console, 'Inputs')
+            if self._model.executor is not None:
+                console.write('Executor: {0}'.format(console.literal(self._model.executor)))
+            if self._model.max_attempts is not None:
+                console.write('Max attempts: {0}'.format(console.literal(self._model.max_attempts)))
+            if self._model.retry_interval is not None:
+                console.write('Retry interval: {0}'.format(
+                    console.literal(self._model.retry_interval)))
+            if self._model.plugin_specification is not None:
+                console.write('Plugin specification: {0}'.format(
+                    console.literal(self._model.plugin_specification.name)))
+            self._topology.dump(self._model.configurations, console, 'Configuration')
+            if self._model.function is not None:
+                console.write('Function: {0}'.format(console.literal(self._model.function)))
+
+    def coerce(self, **kwargs):
+        self._coerce(self._model.inputs,
+                     self._model.configurations,
+                     **kwargs)
+
+    def instantiate(self, instance_cls):
+        operation = instance_cls(
+            name=self._model.name,
+            description=utils.deepcopy_with_locators(self._model.description),
+            relationship_edge=self._model.relationship_edge,
+            implementation=self._model.implementation,
+            dependencies=self._model.dependencies,
+            executor=self._model.executor,
+            function=self._model.function,
+            max_attempts=self._model.max_attempts,
+            retry_interval=self._model.retry_interval,
+            operation_template=self._model)
+
+        if (self._model.plugin_specification is not None and
+                self._model.plugin_specification.enabled):
+            operation.plugin = self._model.plugin_specification.plugin
+
+        operation.inputs = self._topology.instantiate(self._model.inputs)
+        operation.configurations = self._topology.instantiate(self._model.configurations)
+
+        return operation
+
+    def validate(self):
+        self._validate(self._model.inputs,
+                       self._model.configurations)
+
+
+class PluginSpecification(common._TemplateHandlerMixin):
+    def instantiate(self, **kwargs):
+        pass
+
+    def dump(self, console):
+        pass

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/orchestrator/topology/topology.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/topology.py b/aria/orchestrator/topology/topology.py
new file mode 100644
index 0000000..c66749d
--- /dev/null
+++ b/aria/orchestrator/topology/topology.py
@@ -0,0 +1,256 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from StringIO import StringIO
+
+from ...parser.validation import issue
+from ...modeling import models
+from ...utils import (
+    console as console_utils,
+    formatting
+)
+from . import (
+    template_handler,
+    instance_handler,
+    common
+)
+
+
+class Topology(issue.Reporter):
+
+    _init_map = {
+        models.ServiceTemplate: models.Service,
+        models.ArtifactTemplate: models.Artifact,
+        models.CapabilityTemplate: models.Capability,
+        models.GroupTemplate: models.Group,
+        models.InterfaceTemplate: models.Interface,
+        models.NodeTemplate: models.Node,
+        models.PolicyTemplate: models.Policy,
+        models.SubstitutionTemplate: models.Substitution,
+        models.RelationshipTemplate: models.Relationship,
+        models.OperationTemplate: models.Operation,
+        models.RequirementTemplate: None,
+        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
+
+        # Common
+        models.Metadata: models.Metadata,
+        models.Attribute: models.Attribute,
+        models.Property: models.Property,
+        models.Input: models.Input,
+        models.Output: models.Output,
+        models.Configuration: models.Configuration,
+        models.Argument: models.Argument,
+        models.Type: models.Type
+    }
+
+    class Stylizer(object):
+
+        def __init__(self, indentation=2):
+            self._str = StringIO()
+            self.indentation = indentation
+
+        def write(self, str_):
+            console_utils.puts(str_, stream=self._str)
+
+        @property
+        def indent(self):
+            return console_utils.indent(self.indentation)
+
+        @staticmethod
+        def section(value):
+            return console_utils.Colored.cyan(value, bold=True)
+
+        @staticmethod
+        def type(value):
+            return console_utils.Colored.blue(value, bold=True)
+
+        @staticmethod
+        def node(value):
+            return console_utils.Colored.red(value, bold=True)
+
+        @staticmethod
+        def property(value):
+            return console_utils.Colored.magenta(value, bold=True)
+
+        @staticmethod
+        def literal(value):
+            return console_utils.Colored.magenta(formatting.safe_repr(value))
+
+        @staticmethod
+        def meta(value):
+            return console_utils.Colored.green(value)
+
+        def __repr__(self):
+            return self._str.getvalue()
+
+        def __str__(self):
+            return repr(self)
+
+    def __init__(self, model_storage=None, *args, **kwargs):
+        # TODO: model storage is required only for the list of plugins, can we get it
+        # somewhere else?
+        super(Topology, self).__init__(*args, **kwargs)
+        self._model_storage = model_storage
+        self._handlers = dict(self._init_handlers(instance_handler),
+                              **self._init_handlers(template_handler))
+
+    @staticmethod
+    def _init_handlers(module_):
+        handlers = {}
+        for attribute_name in dir(module_):
+            if attribute_name.startswith('_'):
+                continue
+            attribute = getattr(module_, attribute_name)
+            if isinstance(attribute, type) and issubclass(attribute, common._Handler):
+                handlers[getattr(models, attribute_name)] = attribute
+        return handlers
+
+    def instantiate(self, model, **kwargs):
+        """
+        all handlers used by instantiate should hold a tuple as value (handler, instnace_cls)
+        :param model:
+        :param kwargs:
+        :return:
+        """
+        if isinstance(model, dict):
+            return dict((name, self.instantiate(value, **kwargs))
+                        for name, value in model.iteritems())
+        elif isinstance(model, list):
+            return list(self.instantiate(value, **kwargs) for value in model)
+        elif model is not None:
+            _handler = self._handlers.get(model.__class__)
+            instance_cls = self._init_map.get(model.__class__)
+            return _handler(self, model).instantiate(instance_cls, **kwargs)
+
+    def validate(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.validate(model.values())
+        elif isinstance(model, list):
+            return all(self.validate(value) for value in model)
+        elif model is not None:
+            _handler = self._handlers.get(model.__class__)
+            return _handler(self, model).validate(**kwargs)
+
+    def dump(self, model, console=None, section_name=None, **kwargs):
+        console = console or self.Stylizer()
+
+        # if model is empty, no need to print out the section name
+        if model and section_name:
+            console.write('{0}:'.format(section_name))
+
+        if isinstance(model, dict):
+            return self.dump(model.values(), console=console, **kwargs)
+        elif isinstance(model, list):
+            with console.indent:
+                for value in model:
+                    self.dump(value, console=console, **kwargs)
+        elif model is not None:
+            _handler = self._handlers.get(model.__class__)
+            _handler(self, model).dump(console=console, **kwargs)
+        return str(console)
+
+    def dump_graph(self, service, **kwargs):
+        console = self.Stylizer()
+        for node in service.nodes.itervalues():
+            if not node.inbound_relationships:
+                self._dump_graph_node(console, node)
+
+    def _dump_graph_node(self, console, node, capability=None):
+        console.write(console.style.node(node.name))
+        if capability is not None:
+            console.write('{0} ({1})'.format(console.style.property(capability.name),
+                                             console.style.type(capability.type.name)))
+        if node.outbound_relationships:
+            with console.style.indent:
+                for relationship_model in node.outbound_relationships:
+                    relationship_name = console.style.property(relationship_model.name)
+                    if relationship_model.type is not None:
+                        console.write('-> {0} ({1})'.format(
+                            relationship_name, console.style.type(relationship_model.type.name)))
+                    else:
+                        console.write('-> {0}'.format(relationship_name))
+                    with console.indent(3):
+                        self._dump_graph_node(relationship_model.target_node,
+                                              relationship_model.target_capability)
+
+    def coerce(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.validate(model.values())
+        elif isinstance(model, list):
+            return all(self.validate(value) for value in model)
+        elif model is not None:
+            _handler = self._handlers.get(model.__class__)
+            return _handler(self, model).coerce(**kwargs)
+
+    def dump_types(self, service_template, console=None):
+        console = console or self.Stylizer()
+        console.write(self.dump(service_template.node_types, console))
+        console.write(self.dump(service_template.group_types, console))
+        console.write(self.dump(service_template.capability_types, console))
+        console.write(self.dump(service_template.relationship_types, console))
+        console.write(self.dump(service_template.policy_types, console))
+        console.write(self.dump(service_template.artifact_types, console))
+        console.write(self.dump(service_template.interface_types, console))
+
+        return str(console)
+
+    def satisfy_requirements(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.satisfy_requirements(model.values())
+        elif isinstance(model, list):
+            return all(self.satisfy_requirements(value) for value in model)
+        elif model is not None:
+            _handler = self._handlers.get(model.__class__)
+            return _handler(self, model).satisfy_requirements(**kwargs)
+
+    def validate_capabilities(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.validate_capabilities(model.values())
+        elif isinstance(model, list):
+            return all(self.validate_capabilities(value) for value in model)
+        elif model is not None:
+            _handler = self._handlers.get(model.__class__)
+            return _handler(self, model).validate_capabilities(**kwargs)
+
+    def _find_host(self, node):
+        if node.type.role == 'host':
+            return node
+
+        has_role = lambda rel, role: \
+            rel.target_capability is not None and rel.target_capability.type.role == role
+
+        for relationship in node.outbound_relationships:
+            if has_role(relationship, 'host'):
+                host = self._find_host(relationship.target_node)
+                if host is not None:
+                    return host
+        for relationship in node.inbound_relationships:
+            if has_role(relationship, 'feature'):
+                host = self._find_host(relationship.source_node)
+                if host is not None:
+                    return host
+        return None
+
+    def find_hosts(self, service):
+        for node in service.nodes.values():
+            node.host = self._find_host(node)
+
+    def configure_operations(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.configure_operations(model.values())
+        elif isinstance(model, list):
+            return all(self.configure_operations(value) for value in model)
+        elif model is not None:
+            _handler = self._handlers.get(model.__class__)
+            return _handler(self, model).configure_operations(**kwargs)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/parser/consumption/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/__init__.py b/aria/parser/consumption/__init__.py
index bd4b29c..f9caf5f 100644
--- a/aria/parser/consumption/__init__.py
+++ b/aria/parser/consumption/__init__.py
@@ -20,7 +20,6 @@ Consumption package.
    :nosignatures:
 
    aria.parser.consumption.ConsumptionContext
-   aria.parser.consumption.Style
 
 Consumers
 ---------
@@ -47,7 +46,6 @@ Consumers
 
 from .exceptions import ConsumerException
 from .context import ConsumptionContext
-from .style import Style
 from .consumer import (
     Consumer,
     ConsumerChain
@@ -70,7 +68,6 @@ from .inputs import Inputs
 __all__ = (
     'ConsumerException',
     'ConsumptionContext',
-    'Style',
     'Consumer',
     'ConsumerChain',
     'Read',

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/parser/consumption/consumer.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/consumer.py b/aria/parser/consumption/consumer.py
index ea63643..fb60d66 100644
--- a/aria/parser/consumption/consumer.py
+++ b/aria/parser/consumption/consumer.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 
 
+from ...orchestrator import topology
 from ...exceptions import AriaException
 from ...utils.exceptions import print_exception
 from ..validation import Issue
@@ -27,9 +28,7 @@ class Consumer(object):
     """
 
     def __init__(self, context):
-        from aria.orchestrator import topology
-
-        self.handler = topology.Handler()
+        self.topology = topology.Topology()
         self.context = context
 
     def consume(self):
@@ -77,8 +76,8 @@ class ConsumerChain(Consumer):
                 else:
                     raise e
 
-            if consumer.handler.has_issues:
-                self.context.validation.extend_issues(consumer.handler.issues)
+            if consumer.topology.has_issues:
+                self.context.validation.extend_issues(consumer.topology.issues)
 
             if self.context.validation.has_issues:
                 break

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/parser/consumption/context.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/context.py b/aria/parser/consumption/context.py
index 6fa61f4..5b2f31b 100644
--- a/aria/parser/consumption/context.py
+++ b/aria/parser/consumption/context.py
@@ -21,7 +21,6 @@ from ..loading import LoadingContext
 from ..reading import ReadingContext
 from ..presentation import PresentationContext
 from ..modeling import ModelingContext
-from .style import Style
 
 
 _thread_locals = threading.local()
@@ -58,7 +57,6 @@ class ConsumptionContext(object):
     def __init__(self, set_thread_local=True):
         self.args = []
         self.out = sys.stdout
-        self.style = Style()
         self.validation = ValidationContext()
         self.loading = LoadingContext()
         self.reading = ReadingContext()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/parser/consumption/modeling.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/modeling.py b/aria/parser/consumption/modeling.py
index 1338c03..0afd555 100644
--- a/aria/parser/consumption/modeling.py
+++ b/aria/parser/consumption/modeling.py
@@ -43,7 +43,7 @@ class CoerceServiceTemplateValues(Consumer):
     """
 
     def consume(self):
-        self.handler.coerce(self.context.modeling.template, report_issues=True)
+        self.topology.coerce(self.context.modeling.template, report_issues=True)
 
 
 class ValidateServiceTemplate(Consumer):
@@ -52,7 +52,7 @@ class ValidateServiceTemplate(Consumer):
     """
 
     def consume(self):
-        self.handler.validate(self.context.modeling.template)
+        self.topology.validate(self.context.modeling.template)
 
 
 class ServiceTemplate(ConsumerChain):
@@ -75,7 +75,7 @@ class ServiceTemplate(ConsumerChain):
             raw = self.context.modeling.template_as_raw
             self.context.write(json_dumps(raw, indent=indent))
         else:
-            self.handler.dump(self.context.modeling.template)
+            self.topology.dump(self.context.modeling.template)
 
 
 class Types(Consumer):
@@ -93,7 +93,7 @@ class Types(Consumer):
             raw = self.context.modeling.types_as_raw
             self.context.write(json_dumps(raw, indent=indent))
         else:
-            self.handler.dump_types(self.context, self.context.modeling.template)
+            self.topology.dump_types(self.context, self.context.modeling.template)
 
 
 class InstantiateServiceInstance(Consumer):
@@ -106,7 +106,7 @@ class InstantiateServiceInstance(Consumer):
             self.context.validation.report('InstantiateServiceInstance consumer: missing service '
                                            'template')
             return
-        self.context.modeling.instance = self.handler.instantiate(
+        self.context.modeling.instance = self.topology.instantiate(
             self.context.modeling.template,
             inputs=dict(self.context.modeling.inputs)
         )
@@ -134,7 +134,7 @@ class CoerceServiceInstanceValues(Consumer):
     """
 
     def consume(self):
-        self.handler.coerce(self.context.modeling.instance, report_issues=True)
+        self.topology.coerce(self.context.modeling.instance, report_issues=True)
 
 
 class ValidateServiceInstance(Consumer):
@@ -143,7 +143,7 @@ class ValidateServiceInstance(Consumer):
     """
 
     def consume(self):
-        self.handler.validate(self.context.modeling.instance)
+        self.topology.validate(self.context.modeling.instance)
 
 
 class SatisfyRequirements(Consumer):
@@ -152,7 +152,7 @@ class SatisfyRequirements(Consumer):
     """
 
     def consume(self):
-        self.handler.satisfy_requirements(self.context.modeling.instance)
+        self.topology.satisfy_requirements(self.context.modeling.instance)
 
 
 class ValidateCapabilities(Consumer):
@@ -161,7 +161,7 @@ class ValidateCapabilities(Consumer):
     """
 
     def consume(self):
-        self.handler.validate_capabilities(self.context.modeling.instance)
+        self.topology.validate_capabilities(self.context.modeling.instance)
 
 
 class FindHosts(Consumer):
@@ -170,7 +170,7 @@ class FindHosts(Consumer):
     """
 
     def consume(self):
-        self.handler.find_hosts(self.context.modeling.instance)
+        self.topology.find_hosts(self.context.modeling.instance)
 
 
 class ConfigureOperations(Consumer):
@@ -179,7 +179,7 @@ class ConfigureOperations(Consumer):
     """
 
     def consume(self):
-        self.handler.configure_operations(self.context.modeling.instance)
+        self.topology.configure_operations(self.context.modeling.instance)
 
 
 class ServiceInstance(ConsumerChain):
@@ -211,5 +211,5 @@ class ServiceInstance(ConsumerChain):
             raw = self.context.modeling.instance_as_raw
             self.context.write(json_dumps(raw, indent=indent))
         else:
-            str_rep = self.handler.dump(self.context.modeling.instance)
+            str_rep = self.topology.dump(self.context.modeling.instance)
             self.context.write(str_rep)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/parser/consumption/style.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/style.py b/aria/parser/consumption/style.py
deleted file mode 100644
index 72892b9..0000000
--- a/aria/parser/consumption/style.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from ...utils.console import Colored, indent
-from ...utils.formatting import safe_repr
-
-
-class Style(object):
-    def __init__(self, indentation=2):
-        self.indentation = indentation
-
-    @property
-    def indent(self):
-        return indent(self.indentation)
-
-    @staticmethod
-    def section(value):
-        return Colored.cyan(value, bold=True)
-
-    @staticmethod
-    def type(value):
-        return Colored.blue(value, bold=True)
-
-    @staticmethod
-    def node(value):
-        return Colored.red(value, bold=True)
-
-    @staticmethod
-    def property(value):
-        return Colored.magenta(value, bold=True)
-
-    @staticmethod
-    def literal(value):
-        return Colored.magenta(safe_repr(value))
-
-    @staticmethod
-    def meta(value):
-        return Colored.green(value)


[2/2] incubator-ariatosca git commit: removed the old style class from consumption, removed any unnecessary and local imports

Posted by mx...@apache.org.
removed the old style class from consumption, removed any unnecessary and local imports


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

Branch: refs/heads/ARIA-174-Refactor-instantiation-phase
Commit: ec7b9c9702509f6619d4ae20508d06134ee10f26
Parents: bb67dbb
Author: max-orlov <ma...@gigaspaces.com>
Authored: Thu Jul 27 16:45:03 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Thu Jul 27 17:15:25 2017 +0300

----------------------------------------------------------------------
 aria/cli/commands/service_templates.py         |   6 +-
 aria/cli/commands/services.py                  |   6 +-
 aria/core.py                                   |  24 +-
 aria/orchestrator/topology/__init__.py         | 216 +------
 aria/orchestrator/topology/instance.py         | 633 --------------------
 aria/orchestrator/topology/instance_handler.py | 633 ++++++++++++++++++++
 aria/orchestrator/topology/template.py         | 583 ------------------
 aria/orchestrator/topology/template_handler.py | 583 ++++++++++++++++++
 aria/orchestrator/topology/topology.py         | 256 ++++++++
 aria/parser/consumption/__init__.py            |   3 -
 aria/parser/consumption/consumer.py            |   9 +-
 aria/parser/consumption/context.py             |   2 -
 aria/parser/consumption/modeling.py            |  24 +-
 aria/parser/consumption/style.py               |  50 --
 14 files changed, 1507 insertions(+), 1521 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/cli/commands/service_templates.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/service_templates.py b/aria/cli/commands/service_templates.py
index 6eef97a..482170b 100644
--- a/aria/cli/commands/service_templates.py
+++ b/aria/cli/commands/service_templates.py
@@ -28,7 +28,7 @@ from ...core import Core
 from ...storage import exceptions as storage_exceptions
 from ...parser import consumption
 from ...utils import (formatting, collections, console)
-from ... orchestrator import topology
+from ... orchestrator.topology import Topology
 
 DESCRIPTION_FIELD_LENGTH_LIMIT = 20
 SERVICE_TEMPLATE_COLUMNS = \
@@ -73,9 +73,9 @@ def show(service_template_name, model_storage, mode_full, mode_types, format_jso
         elif format_yaml:
             console.puts(formatting.yaml_dumps(collections.prune(service_template.as_raw)))
         else:
-            logger.info(topology.Handler().dump(service_template))
+            logger.info(Topology().dump(service_template))
     elif mode_types:
-        logger.info(topology.Handler().dump_types(service_template=service_template))
+        logger.info(Topology().dump_types(service_template=service_template))
     else:
         logger.info('Showing service template {0}...'.format(service_template_name))
         service_template_dict = service_template.to_dict()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/cli/commands/services.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/services.py b/aria/cli/commands/services.py
index 93bea7f..3b07866 100644
--- a/aria/cli/commands/services.py
+++ b/aria/cli/commands/services.py
@@ -20,7 +20,7 @@ CLI ``services`` sub-commands.
 import os
 from StringIO import StringIO
 
-from aria.orchestrator import topology
+from aria.orchestrator.topology import Topology
 from . import service_templates
 from .. import helptexts
 from .. import table
@@ -74,9 +74,9 @@ def show(service_name, model_storage, mode_full, mode_graph, format_json, format
         elif format_yaml:
             console.puts(formatting.yaml_dumps(collections.prune(service.as_raw)))
         else:
-            logger.info(topology.Handler().dump(service))
+            logger.info(Topology().dump(service))
     elif mode_graph:
-        logger.info(topology.Handler().dump_graph(service))
+        logger.info(Topology().dump_graph(service))
     else:
         logger.info('Showing service {0}...'.format(service_name))
         service_dict = service.to_dict()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/core.py
----------------------------------------------------------------------
diff --git a/aria/core.py b/aria/core.py
index 444bcb9..e726be7 100644
--- a/aria/core.py
+++ b/aria/core.py
@@ -17,10 +17,10 @@
 ARIA core module.
 """
 
-from aria.orchestrator import topology
 from . import exceptions
 from .parser import consumption
 from .parser.loading.location import UriLocation
+from .orchestrator.topology import Topology
 
 
 class Core(object):
@@ -74,20 +74,20 @@ 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:
-            handler = topology.Handler(self.model_storage)
-            service = handler.instantiate(service_template, inputs=inputs)
-            handler.coerce(service)
+            topology = Topology(self.model_storage)
+            service = topology.instantiate(service_template, inputs=inputs)
+            topology.coerce(service)
 
-            handler.validate(service)
-            handler.satisfy_requirements(service)
-            handler.coerce(service)
+            topology.validate(service)
+            topology.satisfy_requirements(service)
+            topology.coerce(service)
 
-            handler.validate_capabilities(service)
-            handler.find_hosts(service)
-            handler.configure_operations(service)
-            handler.coerce(service)
+            topology.validate_capabilities(service)
+            topology.find_hosts(service)
+            topology.configure_operations(service)
+            topology.coerce(service)
 
-            if handler.dump_issues():
+            if topology.dump_issues():
                 raise exceptions.InstantiationError('Failed to instantiate service template `{0}`'
                                                     .format(service_template.name))
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/orchestrator/topology/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/__init__.py b/aria/orchestrator/topology/__init__.py
index 1ba12aa..099a950 100644
--- a/aria/orchestrator/topology/__init__.py
+++ b/aria/orchestrator/topology/__init__.py
@@ -12,219 +12,5 @@
 # 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 StringIO import StringIO
 
-from ...parser.validation import issue
-from ...parser.consumption.style import Style
-from ...modeling import models
-from ...utils import console as console_utils
-from . import (
-    template,
-    instance,
-    common
-)
-
-
-class Handler(issue.Reporter):
-
-    _init_map = {
-        models.ServiceTemplate: models.Service,
-        models.ArtifactTemplate: models.Artifact,
-        models.CapabilityTemplate: models.Capability,
-        models.GroupTemplate: models.Group,
-        models.InterfaceTemplate: models.Interface,
-        models.NodeTemplate: models.Node,
-        models.PolicyTemplate: models.Policy,
-        models.SubstitutionTemplate: models.Substitution,
-        models.RelationshipTemplate: models.Relationship,
-        models.OperationTemplate: models.Operation,
-        models.RequirementTemplate: None,
-        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
-
-        # Common
-        models.Metadata: models.Metadata,
-        models.Attribute: models.Attribute,
-        models.Property: models.Property,
-        models.Input: models.Input,
-        models.Output: models.Output,
-        models.Configuration: models.Configuration,
-        models.Argument: models.Argument,
-        models.Type: models.Type
-    }
-
-    class TopologyStylizer(object):
-        def __init__(self):
-            self._style = Style()
-            self._str = StringIO()
-
-        def write(self, str_):
-            console_utils.puts(str_, stream=self._str)
-
-        def __repr__(self):
-            return self._str.getvalue()
-
-        def __str__(self):
-            return repr(self)
-
-        def __getattr__(self, item):
-            try:
-                return getattr(self._style, item)
-            except AttributeError:
-                return super(Handler.TopologyStylizer, self).__getattribute__(item)
-
-    def __init__(self, model_storage=None, *args, **kwargs):
-        # TODO: model storage is required only for the list of plugins, can we get it
-        # somewhere else?
-        super(Handler, self).__init__(*args, **kwargs)
-        self._model_storage = model_storage
-        self._handlers = dict(self._init_handlers(instance), **self._init_handlers(template))
-
-    @staticmethod
-    def _init_handlers(module_):
-        handlers = {}
-        for attribute_name in dir(module_):
-            if attribute_name.startswith('_'):
-                continue
-            attribute = getattr(module_, attribute_name)
-            if isinstance(attribute, type) and issubclass(attribute, common._Handler):
-                handlers[getattr(models, attribute_name)] = attribute
-        return handlers
-
-    def instantiate(self, model, **kwargs):
-        """
-        all handlers used by instantiate should hold a tuple as value (handler, instnace_cls)
-        :param model:
-        :param kwargs:
-        :return:
-        """
-        if isinstance(model, dict):
-            return dict((name, self.instantiate(value, **kwargs))
-                        for name, value in model.iteritems())
-        elif isinstance(model, list):
-            return list(self.instantiate(value, **kwargs) for value in model)
-        elif model is not None:
-            _handler = self._handlers.get(model.__class__)
-            instance_cls = self._init_map.get(model.__class__)
-            return _handler(self, model).instantiate(instance_cls, **kwargs)
-
-    def validate(self, model, **kwargs):
-        if isinstance(model, dict):
-            return self.validate(model.values())
-        elif isinstance(model, list):
-            return all(self.validate(value) for value in model)
-        elif model is not None:
-            _handler = self._handlers.get(model.__class__)
-            return _handler(self, model).validate(**kwargs)
-
-    def dump(self, model, console=None, section_name=None, **kwargs):
-        console = console or self.TopologyStylizer()
-
-        # if model is empty, no need to print out the section name
-        if model and section_name:
-            console.write('{0}:'.format(section_name))
-
-        if isinstance(model, dict):
-            return self.dump(model.values(), console=console, **kwargs)
-        elif isinstance(model, list):
-            with console.indent:
-                for value in model:
-                    self.dump(value, console=console, **kwargs)
-        elif model is not None:
-            _handler = self._handlers.get(model.__class__)
-            _handler(self, model).dump(console=console, **kwargs)
-        return str(console)
-
-    def dump_graph(self, service, **kwargs):
-        console = self.TopologyStylizer()
-        for node in service.nodes.itervalues():
-            if not node.inbound_relationships:
-                self._dump_graph_node(console, node)
-
-    def _dump_graph_node(self, console, node, capability=None):
-        console.write(console.style.node(node.name))
-        if capability is not None:
-            console.write('{0} ({1})'.format(console.style.property(capability.name),
-                                             console.style.type(capability.type.name)))
-        if node.outbound_relationships:
-            with console.style.indent:
-                for relationship_model in node.outbound_relationships:
-                    relationship_name = console.style.property(relationship_model.name)
-                    if relationship_model.type is not None:
-                        console.write('-> {0} ({1})'.format(
-                            relationship_name, console.style.type(relationship_model.type.name)))
-                    else:
-                        console.write('-> {0}'.format(relationship_name))
-                    with console.indent(3):
-                        self._dump_graph_node(relationship_model.target_node,
-                                              relationship_model.target_capability)
-
-    def coerce(self, model, **kwargs):
-        if isinstance(model, dict):
-            return self.validate(model.values())
-        elif isinstance(model, list):
-            return all(self.validate(value) for value in model)
-        elif model is not None:
-            _handler = self._handlers.get(model.__class__)
-            return _handler(self, model).coerce(**kwargs)
-
-    def dump_types(self, service_template, console=None):
-        console = console or self.TopologyStylizer()
-        console.write(self.dump(service_template.node_types, console))
-        console.write(self.dump(service_template.group_types, console))
-        console.write(self.dump(service_template.capability_types, console))
-        console.write(self.dump(service_template.relationship_types, console))
-        console.write(self.dump(service_template.policy_types, console))
-        console.write(self.dump(service_template.artifact_types, console))
-        console.write(self.dump(service_template.interface_types, console))
-
-        return str(console)
-
-    def satisfy_requirements(self, model, **kwargs):
-        if isinstance(model, dict):
-            return self.satisfy_requirements(model.values())
-        elif isinstance(model, list):
-            return all(self.satisfy_requirements(value) for value in model)
-        elif model is not None:
-            _handler = self._handlers.get(model.__class__)
-            return _handler(self, model).satisfy_requirements(**kwargs)
-
-    def validate_capabilities(self, model, **kwargs):
-        if isinstance(model, dict):
-            return self.validate_capabilities(model.values())
-        elif isinstance(model, list):
-            return all(self.validate_capabilities(value) for value in model)
-        elif model is not None:
-            _handler = self._handlers.get(model.__class__)
-            return _handler(self, model).validate_capabilities(**kwargs)
-
-    def _find_host(self, node):
-        if node.type.role == 'host':
-            return node
-
-        has_role = lambda rel, role: \
-            rel.target_capability is not None and rel.target_capability.type.role == role
-
-        for relationship in node.outbound_relationships:
-            if has_role(relationship, 'host'):
-                host = self._find_host(relationship.target_node)
-                if host is not None:
-                    return host
-        for relationship in node.inbound_relationships:
-            if has_role(relationship, 'feature'):
-                host = self._find_host(relationship.source_node)
-                if host is not None:
-                    return host
-        return None
-
-    def find_hosts(self, service):
-        for node in service.nodes.values():
-            node.host = self._find_host(node)
-
-    def configure_operations(self, model, **kwargs):
-        if isinstance(model, dict):
-            return self.configure_operations(model.values())
-        elif isinstance(model, list):
-            return all(self.configure_operations(value) for value in model)
-        elif model is not None:
-            _handler = self._handlers.get(model.__class__)
-            return _handler(self, model).configure_operations(**kwargs)
+from .topology import Topology

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/orchestrator/topology/instance.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/instance.py b/aria/orchestrator/topology/instance.py
deleted file mode 100644
index dc204fe..0000000
--- a/aria/orchestrator/topology/instance.py
+++ /dev/null
@@ -1,633 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from ... parser.modeling import context
-from ... modeling import models
-from ... utils import formatting
-from .. import execution_plugin
-from .. import decorators
-from . import common
-
-
-class Artifact(common._InstanceHandlerMixin):
-
-    def coerce(self, **kwargs):
-        self._topology.coerce(self._model.properties, **kwargs)
-
-    def validate(self, **kwargs):
-        self._topology.validate(self._model.properties)
-
-    def dump(self, console):
-        console.write(console.node(self._model.name))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            console.write('Artifact type: {0}'.format(console.type(self._model.type.name)))
-            console.write('Source path: {0}'.format(
-                console.literal(self._model.source_path)))
-            if self._model.target_path is not None:
-                console.write('Target path: {0}'.format(
-                    console.literal(self._model.target_path)))
-            if self._model.repository_url is not None:
-                console.write('Repository URL: {0}'.format(
-                    console.literal(self._model.repository_url)))
-            if self._model.repository_credential:
-                console.write('Repository credential: {0}'.format(
-                    console.literal(self._model.repository_credential)))
-            self._topology.dump(self._model.properties, console, 'Properties')
-
-
-class Capability(common._InstanceHandlerMixin):
-    def coerce(self, **kwargs):
-        self._topology.coerce(self._model.properties, **kwargs)
-
-    def validate(self, **kwargs):
-        self._topology.validate(self._model.properties)
-
-    def dump(self, console):
-        console.write(console.node(self._model.name))
-        with console.indent:
-            console.write('Type: {0}'.format(console.type(self._model.type.name)))
-            console.write('Occurrences: {0:d} ({1:d}{2})'.format(
-                self._model.occurrences,
-                self._model.min_occurrences or 0,
-                ' to {0:d}'.format(self._model.max_occurrences)
-                if self._model.max_occurrences is not None
-                else ' or more'))
-            self._topology.dump(self._model.properties, console, 'Properties')
-
-
-class Group(common._OperatorHolderHandlerMixin):
-
-    def coerce(self, **kwargs):
-        self._coerce(self._model.properties, self._model.interfaces, **kwargs)
-
-    def validate(self, **kwargs):
-        self._validate(self._model.properties,
-                       self._model.interfaces)
-
-    def dump(self, console):
-        console.write('Group: {0}'.format(console.node(self._model.name)))
-        with console.indent:
-            console.write('Type: {0}'.format(console.type(self._model.type.name)))
-            self._topology.dump(self._model.properties, console, 'Properties')
-            self._topology.dump(self._model.interfaces, console, 'Interfaces')
-            if self._model.nodes:
-                console.write('Member nodes:')
-                with console.indent:
-                    for node in self._model.nodes:
-                        console.write(console.node(node.name))
-
-    def configure_operations(self):
-        for interface in self._model.interfaces.values():
-            self._topology.configure_operations(interface)
-
-
-class Interface(common._OperatorHolderHandlerMixin):
-    def coerce(self, **kwargs):
-        self._coerce(self._model.inputs, self._model.operations, **kwargs)
-
-    def validate(self, **kwargs):
-        self._validate(self._model.inputs,
-                       self._model.operations)
-
-    def dump(self, console):
-        console.write(console.node(self._model.name))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            console.write('Interface type: {0}'.format(console.type(self._model.type.name)))
-            self._topology.dump(self._model.inputs, console, 'Inputs')
-            self._topology.dump(self._model.operations, console, 'Operations')
-
-    def configure_operations(self):
-        for operation in self._model.operations.values():
-            self._topology.configure_operations(operation)
-
-
-class Node(common._OperatorHolderHandlerMixin):
-    def coerce(self, **kwargs):
-        self._coerce(self._model.properties,
-                     self._model.attributes,
-                     self._model.interfaces,
-                     self._model.artifacts,
-                     self._model.capabilities,
-                     self._model.outbound_relationships,
-                     **kwargs)
-
-    def validate(self, **kwargs):
-        if len(self._model.name) > context.ID_MAX_LENGTH:
-            self._topology.report(
-                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
-                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
-                level=self._topology.Issue.BETWEEN_INSTANCES)
-
-        self._validate(self._model.properties,
-                       self._model.attributes,
-                       self._model.interfaces,
-                       self._model.artifacts,
-                       self._model.capabilities,
-                       self._model.outbound_relationships)
-
-    def dump(self, console):
-        console.write('Node: {0}'.format(console.node(self._model.name)))
-        with console.indent:
-            console.write('Type: {0}'.format(console.type(self._model.type.name)))
-            console.write('Template: {0}'.format(console.node(self._model.node_template.name)))
-            self._topology.dump(self._model.properties, console, 'Properties')
-            self._topology.dump(self._model.attributes, console, 'Attributes')
-            self._topology.dump(self._model.interfaces, console, 'Interfaces')
-            self._topology.dump(self._model.artifacts, console, 'Artifacts')
-            self._topology.dump(self._model.capabilities, console, 'Capabilities')
-            self._topology.dump(self._model.outbound_relationships, console, 'Relationships')
-
-    def configure_operations(self):
-        for interface in self._model.interfaces.values():
-            self._topology.configure_operations(interface)
-        for relationship in self._model.outbound_relationships:
-            self._topology.configure_operations(relationship)
-
-    def validate_capabilities(self):
-        satisfied = False
-        for capability in self._model.capabilities.itervalues():
-            if not capability.has_enough_relationships:
-                self._topology.report(
-                    'capability "{0}" of node "{1}" requires at least {2:d} '
-                    'relationships but has {3:d}'.format(capability.name,
-                                                         self._model.name,
-                                                         capability.min_occurrences,
-                                                         capability.occurrences),
-                    level=self._topology.Issue.BETWEEN_INSTANCES)
-                satisfied = False
-        return satisfied
-
-    def satisfy_requirements(self):
-        satisfied = True
-        for requirement_template in self._model.node_template.requirement_templates:
-
-            # Since we try and satisfy requirements, which are node template bound, and use that
-            # information in the creation of the relationship, Some requirements may have been
-            # satisfied by a previous run on that node template.
-            # The entire mechanism of satisfying requirements needs to be refactored.
-            if any(r.requirement_template == requirement_template
-                   for r in self._model.outbound_relationships):
-                return satisfied
-
-            # Find target template
-            target_node_template, target_node_capability = self._find_target(requirement_template)
-            if target_node_template is not None:
-                satisfied = self._satisfy_capability(
-                    target_node_capability, target_node_template, requirement_template)
-            else:
-                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
-                                      format(requirement_template.name, self._model.name),
-                                      level=self._topology.Issue.BETWEEN_INSTANCES)
-                satisfied = False
-        return satisfied
-
-    def _satisfy_capability(self, target_node_capability, target_node_template,
-                            requirement_template):
-        # Find target nodes
-        target_nodes = target_node_template.nodes
-        if target_nodes:
-            target_node = None
-            target_capability = None
-
-            if target_node_capability is not None:
-                # Relate to the first target node that has capacity
-                for node in target_nodes:
-                    a_target_capability = node.capabilities.get(target_node_capability.name)
-                    if a_target_capability.relate():
-                        target_node = node
-                        target_capability = a_target_capability
-                        break
-            else:
-                # Use first target node
-                target_node = target_nodes[0]
-
-            if target_node is not None:
-                if requirement_template.relationship_template is not None:
-                    relationship_model = self._topology.instantiate(
-                        requirement_template.relationship_template)
-                else:
-                    relationship_model = models.Relationship()
-                relationship_model.name = requirement_template.name
-                relationship_model.requirement_template = requirement_template
-                relationship_model.target_node = target_node
-                relationship_model.target_capability = target_capability
-                self._model.outbound_relationships.append(relationship_model)
-                return True
-            else:
-                self._topology.report(
-                    'requirement "{0}" of node "{1}" targets node '
-                    'template "{2}" but its instantiated nodes do not '
-                    'have enough capacity'.format(
-                        requirement_template.name, self._model.name, target_node_template.name),
-                    level=self._topology.Issue.BETWEEN_INSTANCES)
-                return False
-        else:
-            self._topology.report(
-                'requirement "{0}" of node "{1}" targets node template '
-                '"{2}" but it has no instantiated nodes'.format(
-                    requirement_template.name, self._model.name, target_node_template.name),
-                level=self._topology.Issue.BETWEEN_INSTANCES)
-            return False
-
-    def _find_target(self, requirement_template):
-        # We might already have a specific node template, so we'll just verify it
-        if requirement_template.target_node_template is not None:
-            if not self._model.node_template.is_target_node_template_valid(
-                    requirement_template.target_node_template):
-                self._topology.report(
-                    'requirement "{0}" of node template "{1}" is for node '
-                    'template "{2}" but it does not match constraints'.format(
-                        requirement_template.name,
-                        requirement_template.target_node_template.name,
-                        self._model.node_template.name),
-                    level=self._topology.Issue.BETWEEN_TYPES)
-            if (requirement_template.target_capability_type is not None or
-                    requirement_template.target_capability_name is not None):
-                target_node_capability = self._get_capability(requirement_template)
-                if target_node_capability is None:
-                    return None, None
-            else:
-                target_node_capability = None
-
-            return requirement_template.target_node_template, target_node_capability
-
-        # Find first node that matches the type
-        elif requirement_template.target_node_type is not None:
-            for target_node_template in \
-                    self._model.node_template.service_template.node_templates.itervalues():
-                if requirement_template.target_node_type.get_descendant(
-                        target_node_template.type.name) is None:
-                    continue
-
-                if not self._model.node_template.is_target_node_template_valid(
-                        target_node_template):
-                    continue
-
-                target_node_capability = self._get_capability(requirement_template,
-                                                              target_node_template)
-
-                if target_node_capability is None:
-                    continue
-
-                return target_node_template, target_node_capability
-
-        return None, None
-
-    def _get_capability(self, requirement_template, target_node_template=None):
-        target_node_template = target_node_template or requirement_template.target_node_template
-
-        for capability_template in target_node_template.capability_templates.values():
-            if self._satisfies_requirement(
-                    capability_template, requirement_template, target_node_template):
-                return capability_template
-
-        return None
-
-    def _satisfies_requirement(
-            self, capability_template, requirement_template, target_node_template):
-        # Do we match the required capability type?
-        if (requirement_template.target_capability_type and
-                requirement_template.target_capability_type.get_descendant(
-                    capability_template.type.name) is None):
-            return False
-
-        # Are we in valid_source_node_types?
-        if capability_template.valid_source_node_types:
-            for valid_source_node_type in capability_template.valid_source_node_types:
-                if valid_source_node_type.get_descendant(
-                        self._model.node_template.type.name) is None:
-                    return False
-
-        # Apply requirement constraints
-        if requirement_template.target_node_template_constraints:
-            for node_template_constraint in requirement_template.target_node_template_constraints:
-                if not node_template_constraint.matches(
-                        self._model.node_template, target_node_template):
-                    return False
-
-        return True
-
-
-class Operation(common._OperatorHolderHandlerMixin):
-    def coerce(self, **kwargs):
-        self._coerce(self._model.inputs,
-                     self._model.configurations,
-                     self._model.arguments,
-                     **kwargs)
-
-    def validate(self, **kwargs):
-        self._validate(self._model.inputs,
-                       self._model.configurations,
-                       self._model.arguments)
-
-    def dump(self, console):
-        console.write(console.node(self._model.name))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-        with console.indent:
-            if self._model.implementation is not None:
-                console.write('Implementation: {0}'.format(
-                    console.literal(self._model.implementation)))
-            if self._model.dependencies:
-                console.write(
-                    'Dependencies: {0}'.format(
-                        ', '.join((str(console.literal(v)) for v in self._model.dependencies))))
-            self._topology.dump(self._model.inputs, console, 'Inputs')
-            if self._model.executor is not None:
-                console.write('Executor: {0}'.format(console.literal(self._model.executor)))
-            if self._model.max_attempts is not None:
-                console.write('Max attempts: {0}'.format(console.literal(self._model.max_attempts)))
-            if self._model.retry_interval is not None:
-                console.write('Retry interval: {0}'.format(
-                    console.literal(self._model.retry_interval)))
-            if self._model.plugin is not None:
-                console.write('Plugin: {0}'.format(
-                    console.literal(self._model.plugin.name)))
-            self._topology.dump(self._model.configurations, console, 'Configuration')
-            if self._model.function is not None:
-                console.write('Function: {0}'.format(console.literal(self._model.function)))
-            self._topology.dump(self._model.arguments, console, 'Arguments')
-
-    def configure_operations(self):
-        if self._model.implementation is None and self._model.function is None:
-            return
-
-        if (self._model.interface is not None and
-                self._model.plugin is None and
-                self._model.function is None):
-            # ("interface" is None for workflow operations, which do not currently use "plugin")
-            # The default (None) plugin is the execution plugin
-            execution_plugin.instantiation.configure_operation(self._model)
-        else:
-            # In the future plugins may be able to add their own "configure_operation" hook that
-            # 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._model.configurations.items():
-                self._model.arguments[key] = self._topology.instantiate(conf.as_argument())
-
-        if self._model.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._model.interface.inputs.items():
-                self._model.arguments[key] = self._topology.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._model.inputs.items():
-            self._model.arguments[key] = self._topology.instantiate(input.as_argument())
-
-        # Check for reserved arguments
-        used_reserved_names = set(decorators.OPERATION_DECORATOR_RESERVED_ARGUMENTS).intersection(
-            self._model.arguments.keys())
-        if used_reserved_names:
-            self._topology.report(
-                'using reserved arguments in operation "{0}": {1}'.format(
-                    self._model.name, formatting.string_list_as_string(used_reserved_names)),
-                level=self._topology.Issue.EXTERNAL)
-
-
-class Policy(common._InstanceHandlerMixin):
-    def coerce(self, **kwargs):
-        self._topology.coerce(self._model.properties, **kwargs)
-
-    def validate(self, **kwargs):
-        self._topology.validate(self._model.properties)
-
-    def dump(self, console):
-        console.write('Policy: {0}'.format(console.node(self._model.name)))
-        with console.indent:
-            console.write('Type: {0}'.format(console.type(self._model.type.name)))
-            self._topology.dump(self._model.properties, console, 'Properties')
-            if self._model.nodes:
-                console.write('Target nodes:')
-                with console.indent:
-                    for node in self._model.nodes:
-                        console.write(console.node(node.name))
-            if self._model.groups:
-                console.write('Target groups:')
-                with console.indent:
-                    for group in self._model.groups:
-                        console.write(console.node(group.name))
-
-
-class Relationship(common._OperatorHolderHandlerMixin):
-    def coerce(self, **kwargs):
-        self._coerce(self._model.properties,
-                     self._model.interfaces,
-                     **kwargs)
-
-    def validate(self, **kwargs):
-        self._validate(self._model.properties,
-                       self._model.interfaces)
-
-    def dump(self, console):
-        if self._model.name:
-            console.write('{0} ->'.format(console.node(self._model.name)))
-        else:
-            console.write('->')
-        with console.indent:
-            console.write('Node: {0}'.format(console.node(self._model.target_node.name)))
-            if self._model.target_capability:
-                console.write('Capability: {0}'.format(console.node(
-                    self._model.target_capability.name)))
-            if self._model.type is not None:
-                console.write('Relationship type: {0}'.format(
-                    console.type(self._model.type.name)))
-            if (self._model.relationship_template is not None and
-                    self._model.relationship_template.name):
-                console.write('Relationship template: {0}'.format(
-                    console.node(self._model.relationship_template.name)))
-            self._topology.dump(self._model.properties, console, 'Properties')
-            self._topology.dump(self._model.interfaces, console, 'Interfaces')
-
-    def configure_operations(self):
-        for interface in self._model.interfaces.values():
-            self._topology.configure_operations(interface)
-
-
-class Service(common._OperatorHolderHandlerMixin):
-    def coerce(self, **kwargs):
-        self._coerce(self._model.meta_data,
-                     self._model.nodes,
-                     self._model.groups,
-                     self._model.policies,
-                     self._model.substitution,
-                     self._model.inputs,
-                     self._model.outputs,
-                     self._model.workflows,
-                     **kwargs)
-
-    def validate(self, **kwargs):
-        self._validate(self._model.meta_data,
-                       self._model.nodes,
-                       self._model.groups,
-                       self._model.policies,
-                       self._model.substitution,
-                       self._model.inputs,
-                       self._model.outputs,
-                       self._model.workflows)
-
-    def dump(self, console):
-        if self._model.description is not None:
-            console.write(console.meta(self._model.description))
-        self._topology.dump(self._model.meta_data, console, 'Metadata')
-        self._topology.dump(self._model.nodes, console)
-        self._topology.dump(self._model.groups, console)
-        self._topology.dump(self._model.policies, console)
-        self._topology.dump(self._model.substitution, console)
-        self._topology.dump(self._model.inputs, console, 'Inputs')
-        self._topology.dump(self._model.outputs, console, 'Outputs')
-        self._topology.dump(self._model.workflows, console, 'Workflows')
-
-    def configure_operations(self):
-        for node in self._model.nodes.itervalues():
-            self._topology.configure_operations(node)
-        for group in self._model.groups.itervalues():
-            self._topology.configure_operations(group)
-        for operation in self._model.workflows.itervalues():
-            self._topology.configure_operations(operation)
-
-    def validate_capabilities(self):
-        satisfied = True
-        for node in self._model.nodes.values():
-            if not self._topology.validate_capabilities(node):
-                satisfied = False
-        return satisfied
-
-    def satisfy_requirements(self):
-        return all(self._topology.satisfy_requirements(node)
-                   for node in self._model.nodes.values())
-
-
-class Substitution(common._InstanceHandlerMixin):
-    def coerce(self, **kwargs):
-        self._topology.coerce(self._model.mappings, **kwargs)
-
-    def validate(self, **kwargs):
-        self._topology.validate(self._model.mappings)
-
-    def dump(self, console):
-        console.write('Substitution:')
-        with console.indent:
-            console.write('Node type: {0}'.format(console.type(self._model.node_type.name)))
-            self._topology.dump(self._model.mappings, console, 'Mappings')
-
-
-class SubstitutionMapping(common._InstanceHandlerMixin):
-
-    def validate(self, **kwargs):
-        if (self._model.capability is None) and (self._model.requirement_template is None):
-            self._topology.report(
-                'mapping "{0}" refers to neither capability nor a requirement'
-                ' in node: {1}'.format(
-                    self._model.name, formatting.safe_repr(self._model.node.name)),
-                level=self._topology.Issue.BETWEEN_TYPES)
-
-    def dump(self, console):
-        if self._model.capability is not None:
-            console.write('{0} -> {1}.{2}'.format(
-                console.node(self._model.name),
-                console.node(self._model.capability.node.name),
-                console.node(self._model.capability.name)))
-        else:
-            console.write('{0} -> {1}.{2}'.format(
-                console.node(self._model.name),
-                console.node(self._model.node.name),
-                console.node(self._model.requirement_template.name)))
-
-
-class Metadata(common._InstanceHandlerMixin):
-
-    def dump(self, console):
-        console.write('{0}: {1}'.format(
-            console.property(self._topology.name),
-            console.literal(self._topology.value)))
-
-    def coerce(self):
-        pass
-
-    def instantiate(self, instance_cls, **kwargs):
-        return instance_cls(name=self._model.name, value=self._model.value)
-
-    def validate(self):
-        pass
-
-
-class _Parameter(common._InstanceHandlerMixin):
-
-    def dump(self, console):
-        if self._model.type_name is not None:
-            console.write('{0}: {1} ({2})'.format(
-                console.property(self._model.name),
-                console.literal(formatting.as_raw(self._model.value)),
-                console.type(self._model.type_name)))
-        else:
-            console.write('{0}: {1}'.format(
-                console.property(self._model.name),
-                console.literal(formatting.as_raw(self._model.value))))
-        if self._model.description:
-            console.write(console.meta(self._model.description))
-
-    def instantiate(self, instance_cls, **kwargs):
-        return instance_cls(
-            name=self._model.name,  # pylint: disable=unexpected-keyword-arg
-            type_name=self._model.type_name,
-            _value=self._model._value,
-            description=self._model.description
-        )
-
-    def validate(self):
-        pass
-
-
-class Attribute(_Parameter):
-    pass
-
-
-class Input(_Parameter):
-    pass
-
-
-class Output(_Parameter):
-    pass
-
-
-class Argument(_Parameter):
-    pass
-
-
-class Property(_Parameter):
-    pass
-
-
-class Configuration(_Parameter):
-    pass
-
-
-class Type(common._InstanceHandlerMixin):
-    def coerce(self):
-        pass
-
-    def dump(self, console):
-        if self._model.name:
-            console.write(console.type(self._model.name))
-        with console.indent:
-            for child in self._model.children:
-                self._topology.dump(child, console)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ec7b9c97/aria/orchestrator/topology/instance_handler.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/instance_handler.py b/aria/orchestrator/topology/instance_handler.py
new file mode 100644
index 0000000..dc204fe
--- /dev/null
+++ b/aria/orchestrator/topology/instance_handler.py
@@ -0,0 +1,633 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ... parser.modeling import context
+from ... modeling import models
+from ... utils import formatting
+from .. import execution_plugin
+from .. import decorators
+from . import common
+
+
+class Artifact(common._InstanceHandlerMixin):
+
+    def coerce(self, **kwargs):
+        self._topology.coerce(self._model.properties, **kwargs)
+
+    def validate(self, **kwargs):
+        self._topology.validate(self._model.properties)
+
+    def dump(self, console):
+        console.write(console.node(self._model.name))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            console.write('Artifact type: {0}'.format(console.type(self._model.type.name)))
+            console.write('Source path: {0}'.format(
+                console.literal(self._model.source_path)))
+            if self._model.target_path is not None:
+                console.write('Target path: {0}'.format(
+                    console.literal(self._model.target_path)))
+            if self._model.repository_url is not None:
+                console.write('Repository URL: {0}'.format(
+                    console.literal(self._model.repository_url)))
+            if self._model.repository_credential:
+                console.write('Repository credential: {0}'.format(
+                    console.literal(self._model.repository_credential)))
+            self._topology.dump(self._model.properties, console, 'Properties')
+
+
+class Capability(common._InstanceHandlerMixin):
+    def coerce(self, **kwargs):
+        self._topology.coerce(self._model.properties, **kwargs)
+
+    def validate(self, **kwargs):
+        self._topology.validate(self._model.properties)
+
+    def dump(self, console):
+        console.write(console.node(self._model.name))
+        with console.indent:
+            console.write('Type: {0}'.format(console.type(self._model.type.name)))
+            console.write('Occurrences: {0:d} ({1:d}{2})'.format(
+                self._model.occurrences,
+                self._model.min_occurrences or 0,
+                ' to {0:d}'.format(self._model.max_occurrences)
+                if self._model.max_occurrences is not None
+                else ' or more'))
+            self._topology.dump(self._model.properties, console, 'Properties')
+
+
+class Group(common._OperatorHolderHandlerMixin):
+
+    def coerce(self, **kwargs):
+        self._coerce(self._model.properties, self._model.interfaces, **kwargs)
+
+    def validate(self, **kwargs):
+        self._validate(self._model.properties,
+                       self._model.interfaces)
+
+    def dump(self, console):
+        console.write('Group: {0}'.format(console.node(self._model.name)))
+        with console.indent:
+            console.write('Type: {0}'.format(console.type(self._model.type.name)))
+            self._topology.dump(self._model.properties, console, 'Properties')
+            self._topology.dump(self._model.interfaces, console, 'Interfaces')
+            if self._model.nodes:
+                console.write('Member nodes:')
+                with console.indent:
+                    for node in self._model.nodes:
+                        console.write(console.node(node.name))
+
+    def configure_operations(self):
+        for interface in self._model.interfaces.values():
+            self._topology.configure_operations(interface)
+
+
+class Interface(common._OperatorHolderHandlerMixin):
+    def coerce(self, **kwargs):
+        self._coerce(self._model.inputs, self._model.operations, **kwargs)
+
+    def validate(self, **kwargs):
+        self._validate(self._model.inputs,
+                       self._model.operations)
+
+    def dump(self, console):
+        console.write(console.node(self._model.name))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            console.write('Interface type: {0}'.format(console.type(self._model.type.name)))
+            self._topology.dump(self._model.inputs, console, 'Inputs')
+            self._topology.dump(self._model.operations, console, 'Operations')
+
+    def configure_operations(self):
+        for operation in self._model.operations.values():
+            self._topology.configure_operations(operation)
+
+
+class Node(common._OperatorHolderHandlerMixin):
+    def coerce(self, **kwargs):
+        self._coerce(self._model.properties,
+                     self._model.attributes,
+                     self._model.interfaces,
+                     self._model.artifacts,
+                     self._model.capabilities,
+                     self._model.outbound_relationships,
+                     **kwargs)
+
+    def validate(self, **kwargs):
+        if len(self._model.name) > context.ID_MAX_LENGTH:
+            self._topology.report(
+                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
+                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
+                level=self._topology.Issue.BETWEEN_INSTANCES)
+
+        self._validate(self._model.properties,
+                       self._model.attributes,
+                       self._model.interfaces,
+                       self._model.artifacts,
+                       self._model.capabilities,
+                       self._model.outbound_relationships)
+
+    def dump(self, console):
+        console.write('Node: {0}'.format(console.node(self._model.name)))
+        with console.indent:
+            console.write('Type: {0}'.format(console.type(self._model.type.name)))
+            console.write('Template: {0}'.format(console.node(self._model.node_template.name)))
+            self._topology.dump(self._model.properties, console, 'Properties')
+            self._topology.dump(self._model.attributes, console, 'Attributes')
+            self._topology.dump(self._model.interfaces, console, 'Interfaces')
+            self._topology.dump(self._model.artifacts, console, 'Artifacts')
+            self._topology.dump(self._model.capabilities, console, 'Capabilities')
+            self._topology.dump(self._model.outbound_relationships, console, 'Relationships')
+
+    def configure_operations(self):
+        for interface in self._model.interfaces.values():
+            self._topology.configure_operations(interface)
+        for relationship in self._model.outbound_relationships:
+            self._topology.configure_operations(relationship)
+
+    def validate_capabilities(self):
+        satisfied = False
+        for capability in self._model.capabilities.itervalues():
+            if not capability.has_enough_relationships:
+                self._topology.report(
+                    'capability "{0}" of node "{1}" requires at least {2:d} '
+                    'relationships but has {3:d}'.format(capability.name,
+                                                         self._model.name,
+                                                         capability.min_occurrences,
+                                                         capability.occurrences),
+                    level=self._topology.Issue.BETWEEN_INSTANCES)
+                satisfied = False
+        return satisfied
+
+    def satisfy_requirements(self):
+        satisfied = True
+        for requirement_template in self._model.node_template.requirement_templates:
+
+            # Since we try and satisfy requirements, which are node template bound, and use that
+            # information in the creation of the relationship, Some requirements may have been
+            # satisfied by a previous run on that node template.
+            # The entire mechanism of satisfying requirements needs to be refactored.
+            if any(r.requirement_template == requirement_template
+                   for r in self._model.outbound_relationships):
+                return satisfied
+
+            # Find target template
+            target_node_template, target_node_capability = self._find_target(requirement_template)
+            if target_node_template is not None:
+                satisfied = self._satisfy_capability(
+                    target_node_capability, target_node_template, requirement_template)
+            else:
+                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
+                                      format(requirement_template.name, self._model.name),
+                                      level=self._topology.Issue.BETWEEN_INSTANCES)
+                satisfied = False
+        return satisfied
+
+    def _satisfy_capability(self, target_node_capability, target_node_template,
+                            requirement_template):
+        # Find target nodes
+        target_nodes = target_node_template.nodes
+        if target_nodes:
+            target_node = None
+            target_capability = None
+
+            if target_node_capability is not None:
+                # Relate to the first target node that has capacity
+                for node in target_nodes:
+                    a_target_capability = node.capabilities.get(target_node_capability.name)
+                    if a_target_capability.relate():
+                        target_node = node
+                        target_capability = a_target_capability
+                        break
+            else:
+                # Use first target node
+                target_node = target_nodes[0]
+
+            if target_node is not None:
+                if requirement_template.relationship_template is not None:
+                    relationship_model = self._topology.instantiate(
+                        requirement_template.relationship_template)
+                else:
+                    relationship_model = models.Relationship()
+                relationship_model.name = requirement_template.name
+                relationship_model.requirement_template = requirement_template
+                relationship_model.target_node = target_node
+                relationship_model.target_capability = target_capability
+                self._model.outbound_relationships.append(relationship_model)
+                return True
+            else:
+                self._topology.report(
+                    'requirement "{0}" of node "{1}" targets node '
+                    'template "{2}" but its instantiated nodes do not '
+                    'have enough capacity'.format(
+                        requirement_template.name, self._model.name, target_node_template.name),
+                    level=self._topology.Issue.BETWEEN_INSTANCES)
+                return False
+        else:
+            self._topology.report(
+                'requirement "{0}" of node "{1}" targets node template '
+                '"{2}" but it has no instantiated nodes'.format(
+                    requirement_template.name, self._model.name, target_node_template.name),
+                level=self._topology.Issue.BETWEEN_INSTANCES)
+            return False
+
+    def _find_target(self, requirement_template):
+        # We might already have a specific node template, so we'll just verify it
+        if requirement_template.target_node_template is not None:
+            if not self._model.node_template.is_target_node_template_valid(
+                    requirement_template.target_node_template):
+                self._topology.report(
+                    'requirement "{0}" of node template "{1}" is for node '
+                    'template "{2}" but it does not match constraints'.format(
+                        requirement_template.name,
+                        requirement_template.target_node_template.name,
+                        self._model.node_template.name),
+                    level=self._topology.Issue.BETWEEN_TYPES)
+            if (requirement_template.target_capability_type is not None or
+                    requirement_template.target_capability_name is not None):
+                target_node_capability = self._get_capability(requirement_template)
+                if target_node_capability is None:
+                    return None, None
+            else:
+                target_node_capability = None
+
+            return requirement_template.target_node_template, target_node_capability
+
+        # Find first node that matches the type
+        elif requirement_template.target_node_type is not None:
+            for target_node_template in \
+                    self._model.node_template.service_template.node_templates.itervalues():
+                if requirement_template.target_node_type.get_descendant(
+                        target_node_template.type.name) is None:
+                    continue
+
+                if not self._model.node_template.is_target_node_template_valid(
+                        target_node_template):
+                    continue
+
+                target_node_capability = self._get_capability(requirement_template,
+                                                              target_node_template)
+
+                if target_node_capability is None:
+                    continue
+
+                return target_node_template, target_node_capability
+
+        return None, None
+
+    def _get_capability(self, requirement_template, target_node_template=None):
+        target_node_template = target_node_template or requirement_template.target_node_template
+
+        for capability_template in target_node_template.capability_templates.values():
+            if self._satisfies_requirement(
+                    capability_template, requirement_template, target_node_template):
+                return capability_template
+
+        return None
+
+    def _satisfies_requirement(
+            self, capability_template, requirement_template, target_node_template):
+        # Do we match the required capability type?
+        if (requirement_template.target_capability_type and
+                requirement_template.target_capability_type.get_descendant(
+                    capability_template.type.name) is None):
+            return False
+
+        # Are we in valid_source_node_types?
+        if capability_template.valid_source_node_types:
+            for valid_source_node_type in capability_template.valid_source_node_types:
+                if valid_source_node_type.get_descendant(
+                        self._model.node_template.type.name) is None:
+                    return False
+
+        # Apply requirement constraints
+        if requirement_template.target_node_template_constraints:
+            for node_template_constraint in requirement_template.target_node_template_constraints:
+                if not node_template_constraint.matches(
+                        self._model.node_template, target_node_template):
+                    return False
+
+        return True
+
+
+class Operation(common._OperatorHolderHandlerMixin):
+    def coerce(self, **kwargs):
+        self._coerce(self._model.inputs,
+                     self._model.configurations,
+                     self._model.arguments,
+                     **kwargs)
+
+    def validate(self, **kwargs):
+        self._validate(self._model.inputs,
+                       self._model.configurations,
+                       self._model.arguments)
+
+    def dump(self, console):
+        console.write(console.node(self._model.name))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+        with console.indent:
+            if self._model.implementation is not None:
+                console.write('Implementation: {0}'.format(
+                    console.literal(self._model.implementation)))
+            if self._model.dependencies:
+                console.write(
+                    'Dependencies: {0}'.format(
+                        ', '.join((str(console.literal(v)) for v in self._model.dependencies))))
+            self._topology.dump(self._model.inputs, console, 'Inputs')
+            if self._model.executor is not None:
+                console.write('Executor: {0}'.format(console.literal(self._model.executor)))
+            if self._model.max_attempts is not None:
+                console.write('Max attempts: {0}'.format(console.literal(self._model.max_attempts)))
+            if self._model.retry_interval is not None:
+                console.write('Retry interval: {0}'.format(
+                    console.literal(self._model.retry_interval)))
+            if self._model.plugin is not None:
+                console.write('Plugin: {0}'.format(
+                    console.literal(self._model.plugin.name)))
+            self._topology.dump(self._model.configurations, console, 'Configuration')
+            if self._model.function is not None:
+                console.write('Function: {0}'.format(console.literal(self._model.function)))
+            self._topology.dump(self._model.arguments, console, 'Arguments')
+
+    def configure_operations(self):
+        if self._model.implementation is None and self._model.function is None:
+            return
+
+        if (self._model.interface is not None and
+                self._model.plugin is None and
+                self._model.function is None):
+            # ("interface" is None for workflow operations, which do not currently use "plugin")
+            # The default (None) plugin is the execution plugin
+            execution_plugin.instantiation.configure_operation(self._model)
+        else:
+            # In the future plugins may be able to add their own "configure_operation" hook that
+            # 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._model.configurations.items():
+                self._model.arguments[key] = self._topology.instantiate(conf.as_argument())
+
+        if self._model.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._model.interface.inputs.items():
+                self._model.arguments[key] = self._topology.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._model.inputs.items():
+            self._model.arguments[key] = self._topology.instantiate(input.as_argument())
+
+        # Check for reserved arguments
+        used_reserved_names = set(decorators.OPERATION_DECORATOR_RESERVED_ARGUMENTS).intersection(
+            self._model.arguments.keys())
+        if used_reserved_names:
+            self._topology.report(
+                'using reserved arguments in operation "{0}": {1}'.format(
+                    self._model.name, formatting.string_list_as_string(used_reserved_names)),
+                level=self._topology.Issue.EXTERNAL)
+
+
+class Policy(common._InstanceHandlerMixin):
+    def coerce(self, **kwargs):
+        self._topology.coerce(self._model.properties, **kwargs)
+
+    def validate(self, **kwargs):
+        self._topology.validate(self._model.properties)
+
+    def dump(self, console):
+        console.write('Policy: {0}'.format(console.node(self._model.name)))
+        with console.indent:
+            console.write('Type: {0}'.format(console.type(self._model.type.name)))
+            self._topology.dump(self._model.properties, console, 'Properties')
+            if self._model.nodes:
+                console.write('Target nodes:')
+                with console.indent:
+                    for node in self._model.nodes:
+                        console.write(console.node(node.name))
+            if self._model.groups:
+                console.write('Target groups:')
+                with console.indent:
+                    for group in self._model.groups:
+                        console.write(console.node(group.name))
+
+
+class Relationship(common._OperatorHolderHandlerMixin):
+    def coerce(self, **kwargs):
+        self._coerce(self._model.properties,
+                     self._model.interfaces,
+                     **kwargs)
+
+    def validate(self, **kwargs):
+        self._validate(self._model.properties,
+                       self._model.interfaces)
+
+    def dump(self, console):
+        if self._model.name:
+            console.write('{0} ->'.format(console.node(self._model.name)))
+        else:
+            console.write('->')
+        with console.indent:
+            console.write('Node: {0}'.format(console.node(self._model.target_node.name)))
+            if self._model.target_capability:
+                console.write('Capability: {0}'.format(console.node(
+                    self._model.target_capability.name)))
+            if self._model.type is not None:
+                console.write('Relationship type: {0}'.format(
+                    console.type(self._model.type.name)))
+            if (self._model.relationship_template is not None and
+                    self._model.relationship_template.name):
+                console.write('Relationship template: {0}'.format(
+                    console.node(self._model.relationship_template.name)))
+            self._topology.dump(self._model.properties, console, 'Properties')
+            self._topology.dump(self._model.interfaces, console, 'Interfaces')
+
+    def configure_operations(self):
+        for interface in self._model.interfaces.values():
+            self._topology.configure_operations(interface)
+
+
+class Service(common._OperatorHolderHandlerMixin):
+    def coerce(self, **kwargs):
+        self._coerce(self._model.meta_data,
+                     self._model.nodes,
+                     self._model.groups,
+                     self._model.policies,
+                     self._model.substitution,
+                     self._model.inputs,
+                     self._model.outputs,
+                     self._model.workflows,
+                     **kwargs)
+
+    def validate(self, **kwargs):
+        self._validate(self._model.meta_data,
+                       self._model.nodes,
+                       self._model.groups,
+                       self._model.policies,
+                       self._model.substitution,
+                       self._model.inputs,
+                       self._model.outputs,
+                       self._model.workflows)
+
+    def dump(self, console):
+        if self._model.description is not None:
+            console.write(console.meta(self._model.description))
+        self._topology.dump(self._model.meta_data, console, 'Metadata')
+        self._topology.dump(self._model.nodes, console)
+        self._topology.dump(self._model.groups, console)
+        self._topology.dump(self._model.policies, console)
+        self._topology.dump(self._model.substitution, console)
+        self._topology.dump(self._model.inputs, console, 'Inputs')
+        self._topology.dump(self._model.outputs, console, 'Outputs')
+        self._topology.dump(self._model.workflows, console, 'Workflows')
+
+    def configure_operations(self):
+        for node in self._model.nodes.itervalues():
+            self._topology.configure_operations(node)
+        for group in self._model.groups.itervalues():
+            self._topology.configure_operations(group)
+        for operation in self._model.workflows.itervalues():
+            self._topology.configure_operations(operation)
+
+    def validate_capabilities(self):
+        satisfied = True
+        for node in self._model.nodes.values():
+            if not self._topology.validate_capabilities(node):
+                satisfied = False
+        return satisfied
+
+    def satisfy_requirements(self):
+        return all(self._topology.satisfy_requirements(node)
+                   for node in self._model.nodes.values())
+
+
+class Substitution(common._InstanceHandlerMixin):
+    def coerce(self, **kwargs):
+        self._topology.coerce(self._model.mappings, **kwargs)
+
+    def validate(self, **kwargs):
+        self._topology.validate(self._model.mappings)
+
+    def dump(self, console):
+        console.write('Substitution:')
+        with console.indent:
+            console.write('Node type: {0}'.format(console.type(self._model.node_type.name)))
+            self._topology.dump(self._model.mappings, console, 'Mappings')
+
+
+class SubstitutionMapping(common._InstanceHandlerMixin):
+
+    def validate(self, **kwargs):
+        if (self._model.capability is None) and (self._model.requirement_template is None):
+            self._topology.report(
+                'mapping "{0}" refers to neither capability nor a requirement'
+                ' in node: {1}'.format(
+                    self._model.name, formatting.safe_repr(self._model.node.name)),
+                level=self._topology.Issue.BETWEEN_TYPES)
+
+    def dump(self, console):
+        if self._model.capability is not None:
+            console.write('{0} -> {1}.{2}'.format(
+                console.node(self._model.name),
+                console.node(self._model.capability.node.name),
+                console.node(self._model.capability.name)))
+        else:
+            console.write('{0} -> {1}.{2}'.format(
+                console.node(self._model.name),
+                console.node(self._model.node.name),
+                console.node(self._model.requirement_template.name)))
+
+
+class Metadata(common._InstanceHandlerMixin):
+
+    def dump(self, console):
+        console.write('{0}: {1}'.format(
+            console.property(self._topology.name),
+            console.literal(self._topology.value)))
+
+    def coerce(self):
+        pass
+
+    def instantiate(self, instance_cls, **kwargs):
+        return instance_cls(name=self._model.name, value=self._model.value)
+
+    def validate(self):
+        pass
+
+
+class _Parameter(common._InstanceHandlerMixin):
+
+    def dump(self, console):
+        if self._model.type_name is not None:
+            console.write('{0}: {1} ({2})'.format(
+                console.property(self._model.name),
+                console.literal(formatting.as_raw(self._model.value)),
+                console.type(self._model.type_name)))
+        else:
+            console.write('{0}: {1}'.format(
+                console.property(self._model.name),
+                console.literal(formatting.as_raw(self._model.value))))
+        if self._model.description:
+            console.write(console.meta(self._model.description))
+
+    def instantiate(self, instance_cls, **kwargs):
+        return instance_cls(
+            name=self._model.name,  # pylint: disable=unexpected-keyword-arg
+            type_name=self._model.type_name,
+            _value=self._model._value,
+            description=self._model.description
+        )
+
+    def validate(self):
+        pass
+
+
+class Attribute(_Parameter):
+    pass
+
+
+class Input(_Parameter):
+    pass
+
+
+class Output(_Parameter):
+    pass
+
+
+class Argument(_Parameter):
+    pass
+
+
+class Property(_Parameter):
+    pass
+
+
+class Configuration(_Parameter):
+    pass
+
+
+class Type(common._InstanceHandlerMixin):
+    def coerce(self):
+        pass
+
+    def dump(self, console):
+        if self._model.name:
+            console.write(console.type(self._model.name))
+        with console.indent:
+            for child in self._model.children:
+                self._topology.dump(child, console)