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/24 15:04:34 UTC

[2/2] incubator-ariatosca git commit: removed any remaining consumptioncontext reporting for now, added dynamic model handler resolving and only coerce remains

removed any remaining consumptioncontext reporting for now, added dynamic model handler resolving and only coerce remains


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

Branch: refs/heads/ARIA-174-Refactor-instantiation-phase
Commit: 5c92ccad652a1bd2706363768d13f0509fc9d58f
Parents: 8e5fe10
Author: max-orlov <ma...@gigaspaces.com>
Authored: Mon Jul 24 18:04:29 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Mon Jul 24 18:04:29 2017 +0300

----------------------------------------------------------------------
 aria/modeling/functions.py                      |   7 +-
 aria/modeling/mixins.py                         |  23 +-
 aria/modeling/service_common.py                 |  16 --
 aria/modeling/service_instance.py               | 241 +++-------------
 aria/modeling/service_template.py               | 232 ++-------------
 aria/modeling/utils.py                          |  59 ----
 .../execution_plugin/instantiation.py           |  61 ++--
 aria/orchestrator/topology/__init__.py          | 113 +++++---
 aria/orchestrator/topology/common.py            |  16 +-
 aria/orchestrator/topology/instance.py          | 285 +++++++++++++++----
 aria/orchestrator/topology/template.py          | 224 ++++++++++++---
 aria/parser/consumption/consumer.py             |   3 +
 aria/parser/consumption/modeling.py             |  11 +-
 13 files changed, 603 insertions(+), 688 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/modeling/functions.py
----------------------------------------------------------------------
diff --git a/aria/modeling/functions.py b/aria/modeling/functions.py
index 6544adf..425b69b 100644
--- a/aria/modeling/functions.py
+++ b/aria/modeling/functions.py
@@ -17,7 +17,6 @@
 Mechanism for evaluating intrinsic functions.
 """
 
-from ..parser.consumption import ConsumptionContext
 from ..parser.exceptions import InvalidValueError
 from ..utils.collections import OrderedDict
 from . import exceptions
@@ -105,8 +104,10 @@ def evaluate(value, container_holder, report_issues=False): # pylint: disable=to
             pass
         except InvalidValueError as e:
             if report_issues:
-                context = ConsumptionContext.get_thread_local()
-                context.validation.report(e.issue)
+                # TODO: do not use the context for "reporting"
+                pass
+                # context = ConsumptionContext.get_thread_local()
+                # context.validation.report(e.issue)
 
     elif isinstance(value, list):
         evaluated_list = []

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/modeling/mixins.py
----------------------------------------------------------------------
diff --git a/aria/modeling/mixins.py b/aria/modeling/mixins.py
index 91fc5e3..fd31e3e 100644
--- a/aria/modeling/mixins.py
+++ b/aria/modeling/mixins.py
@@ -25,8 +25,7 @@ from sqlalchemy import (
     PickleType
 )
 
-from ..parser.consumption import ConsumptionContext
-from ..utils import console, collections, caching, formatting
+from ..utils import collections, caching
 from ..utils.type import canonical_type_name, full_type_name
 from . import utils, functions
 
@@ -132,15 +131,9 @@ class InstanceModelMixin(ModelMixin):
     def as_raw(self):
         raise NotImplementedError
 
-    def validate(self):
-        pass
-
     def coerce_values(self, report_issues):
         pass
 
-    def dump(self):
-        pass
-
 
 class TemplateModelMixin(InstanceModelMixin):
     """
@@ -313,20 +306,6 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
                 # A final evaluation can safely replace the existing value
                 self._value = evaluation.value
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.type_name is not None:
-            console.puts('{0}: {1} ({2})'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value)),
-                context.style.type(self.type_name)))
-        else:
-            console.puts('{0}: {1}'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value))))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-
     @property
     def unwrapped(self):
         return self.name, self.value

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index f735c6b..60c7330 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -25,11 +25,9 @@ from sqlalchemy import (
 )
 from sqlalchemy.ext.declarative import declared_attr
 
-from ..parser.consumption import ConsumptionContext
 from ..utils import (
     collections,
     formatting,
-    console,
 )
 from .mixins import InstanceModelMixin, TemplateModelMixin, ParameterMixin
 from . import relationship
@@ -553,14 +551,6 @@ class TypeBase(InstanceModelMixin):
     def coerce_values(self, report_issues):
         pass
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.name:
-            console.puts(context.style.type(self.name))
-        with context.style.indent:
-            for child in self.children:
-                child.dump()
-
     def _append_raw_children(self, types):
         for child in self.children:
             raw_child = formatting.as_raw(child)
@@ -602,9 +592,3 @@ class MetadataBase(TemplateModelMixin):
 
     def coerce_values(self, report_issues):
         pass
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('{0}: {1}'.format(
-            context.style.property(self.name),
-            context.style.literal(self.value)))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index 93d610b..03f8632 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -38,7 +38,6 @@ from . import (
 from .mixins import InstanceModelMixin
 from ..orchestrator import execution_plugin
 from ..parser import validation
-from ..parser.consumption import ConsumptionContext
 from ..utils import (
     collections,
     formatting,
@@ -300,29 +299,14 @@ class ServiceBase(InstanceModelMixin):
         utils.coerce_dict_values(self.outputs, report_issues)
         utils.coerce_dict_values(self.workflows, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.description is not None:
-            console.puts(context.style.meta(self.description))
-        utils.dump_dict_values(self.meta_data, 'Metadata')
-        for node in self.nodes.itervalues():
-            node.dump()
-        for group in self.groups.itervalues():
-            group.dump()
-        for policy in self.policies.itervalues():
-            policy.dump()
-        if self.substitution is not None:
-            self.substitution.dump()
-        utils.dump_dict_values(self.inputs, 'Inputs')
-        utils.dump_dict_values(self.outputs, 'Outputs')
-        utils.dump_dict_values(self.workflows, 'Workflows')
-
     def dump_graph(self):
         for node in self.nodes.itervalues():
             if not self.is_node_a_target(node):
                 self._dump_graph_node(node)
 
     def _dump_graph_node(self, node, capability=None):
+        from ..parser.consumption import ConsumptionContext
+
         context = ConsumptionContext.get_thread_local()
         console.puts(context.style.node(node.name))
         if capability is not None:
@@ -617,17 +601,20 @@ class NodeBase(InstanceModelMixin):
                                                      target_node_template,
                                                      requirement_template)
             else:
-                context = ConsumptionContext.get_thread_local()
-                context.validation.report('requirement "{0}" of node "{1}" has no target node '
-                                          'template'.format(requirement_template.name, self.name),
-                                          level=validation.Issue.BETWEEN_INSTANCES)
+                # TODO: fix
+
+                # context = ConsumptionContext.get_thread_local()
+                # context.validation.report('requirement "{0}" of node "{1}" has no target node '
+                #                           'template'.format(requirement_template.name, self.name),
+                #                           level=validation.Issue.BETWEEN_INSTANCES)
                 satisfied = False
         return satisfied
 
     def _satisfy_capability(self, target_node_capability, target_node_template,
                             requirement_template):
         from . import models
-        context = ConsumptionContext.get_thread_local()
+        # TODO: fix reporting
+        # context = ConsumptionContext.get_thread_local()
         # Find target nodes
         target_nodes = target_node_template.nodes
         if target_nodes:
@@ -660,35 +647,36 @@ class NodeBase(InstanceModelMixin):
                 self.outbound_relationships.append(relationship_model)
                 return True
             else:
-                context.validation.report('requirement "{0}" of node "{1}" targets node '
-                                          'template "{2}" but its instantiated nodes do not '
-                                          'have enough capacity'.format(
-                                              requirement_template.name,
-                                              self.name,
-                                              target_node_template.name),
-                                          level=validation.Issue.BETWEEN_INSTANCES)
+                # context.validation.report('requirement "{0}" of node "{1}" targets node '
+                #                           'template "{2}" but its instantiated nodes do not '
+                #                           'have enough capacity'.format(
+                #                               requirement_template.name,
+                #                               self.name,
+                #                               target_node_template.name),
+                #                           level=validation.Issue.BETWEEN_INSTANCES)
                 return False
         else:
-            context.validation.report('requirement "{0}" of node "{1}" targets node template '
-                                      '"{2}" but it has no instantiated nodes'.format(
-                                          requirement_template.name,
-                                          self.name,
-                                          target_node_template.name),
-                                      level=validation.Issue.BETWEEN_INSTANCES)
+            # context.validation.report('requirement "{0}" of node "{1}" targets node template '
+            #                           '"{2}" but it has no instantiated nodes'.format(
+            #                               requirement_template.name,
+            #                               self.name,
+            #                               target_node_template.name),
+            #                           level=validation.Issue.BETWEEN_INSTANCES)
             return False
 
     def validate_capabilities(self):
-        context = ConsumptionContext.get_thread_local()
+        # TODO: fix
+        # context = ConsumptionContext.get_thread_local()
         satisfied = False
         for capability in self.capabilities.itervalues():
             if not capability.has_enough_relationships:
-                context.validation.report('capability "{0}" of node "{1}" requires at least {2:d} '
-                                          'relationships but has {3:d}'.format(
-                                              capability.name,
-                                              self.name,
-                                              capability.min_occurrences,
-                                              capability.occurrences),
-                                          level=validation.Issue.BETWEEN_INSTANCES)
+                # context.validation.report('capability "{0}" of node "{1}" requires at least {2:d} '
+                #                           'relationships but has {3:d}'.format(
+                #                               capability.name,
+                #                               self.name,
+                #                               capability.min_occurrences,
+                #                               capability.occurrences),
+                #                           level=validation.Issue.BETWEEN_INSTANCES)
                 satisfied = False
         return satisfied
 
@@ -738,19 +726,6 @@ class NodeBase(InstanceModelMixin):
         utils.coerce_dict_values(self.capabilities, report_issues)
         utils.coerce_list_values(self.outbound_relationships, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Node: {0}'.format(context.style.node(self.name)))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            console.puts('Template: {0}'.format(context.style.node(self.node_template.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_dict_values(self.attributes, 'Attributes')
-            utils.dump_interfaces(self.interfaces)
-            utils.dump_dict_values(self.artifacts, 'Artifacts')
-            utils.dump_dict_values(self.capabilities, 'Capabilities')
-            utils.dump_list_values(self.outbound_relationships, 'Relationships')
-
 
 class GroupBase(InstanceModelMixin):
     """
@@ -871,19 +846,6 @@ class GroupBase(InstanceModelMixin):
         utils.coerce_dict_values(self.properties, report_issues)
         utils.coerce_dict_values(self.interfaces, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Group: {0}'.format(context.style.node(self.name)))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interfaces)
-            if self.nodes:
-                console.puts('Member nodes:')
-                with context.style.indent:
-                    for node in self.nodes:
-                        console.puts(context.style.node(node.name))
-
 
 class PolicyBase(InstanceModelMixin):
     """
@@ -1000,23 +962,6 @@ class PolicyBase(InstanceModelMixin):
     def coerce_values(self, report_issues):
         utils.coerce_dict_values(self.properties, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Policy: {0}'.format(context.style.node(self.name)))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            if self.nodes:
-                console.puts('Target nodes:')
-                with context.style.indent:
-                    for node in self.nodes:
-                        console.puts(context.style.node(node.name))
-            if self.groups:
-                console.puts('Target groups:')
-                with context.style.indent:
-                    for group in self.groups:
-                        console.puts(context.style.node(group.name))
-
 
 class SubstitutionBase(InstanceModelMixin):
     """
@@ -1097,13 +1042,6 @@ class SubstitutionBase(InstanceModelMixin):
     def coerce_values(self, report_issues):
         utils.coerce_dict_values(self.mappings, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Substitution:')
-        with context.style.indent:
-            console.puts('Node type: {0}'.format(context.style.type(self.node_type.name)))
-            utils.dump_dict_values(self.mappings, 'Mappings')
-
 
 class SubstitutionMappingBase(InstanceModelMixin):
     """
@@ -1202,19 +1140,6 @@ class SubstitutionMappingBase(InstanceModelMixin):
     def coerce_values(self, report_issues):
         pass
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.capability is not None:
-            console.puts('{0} -> {1}.{2}'.format(
-                context.style.node(self.name),
-                context.style.node(self.capability.node.name),
-                context.style.node(self.capability.name)))
-        else:
-            console.puts('{0} -> {1}.{2}'.format(
-                context.style.node(self.name),
-                context.style.node(self.node.name),
-                context.style.node(self.requirement_template.name)))
-
 
 class RelationshipBase(InstanceModelMixin):
     """
@@ -1408,25 +1333,6 @@ class RelationshipBase(InstanceModelMixin):
         utils.coerce_dict_values(self.properties, report_issues)
         utils.coerce_dict_values(self.interfaces, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.name:
-            console.puts('{0} ->'.format(context.style.node(self.name)))
-        else:
-            console.puts('->')
-        with context.style.indent:
-            console.puts('Node: {0}'.format(context.style.node(self.target_node.name)))
-            if self.target_capability:
-                console.puts('Capability: {0}'.format(context.style.node(
-                    self.target_capability.name)))
-            if self.type is not None:
-                console.puts('Relationship type: {0}'.format(context.style.type(self.type.name)))
-            if (self.relationship_template is not None) and self.relationship_template.name:
-                console.puts('Relationship template: {0}'.format(
-                    context.style.node(self.relationship_template.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interfaces, 'Interfaces')
-
 
 class CapabilityBase(InstanceModelMixin):
     """
@@ -1546,19 +1452,6 @@ class CapabilityBase(InstanceModelMixin):
     def coerce_values(self, report_issues):
         utils.coerce_dict_values(self.properties, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            console.puts('Occurrences: {0:d} ({1:d}{2})'.format(
-                self.occurrences,
-                self.min_occurrences or 0,
-                ' to {0:d}'.format(self.max_occurrences)
-                if self.max_occurrences is not None
-                else ' or more'))
-            utils.dump_dict_values(self.properties, 'Properties')
-
 
 class InterfaceBase(InstanceModelMixin):
     """
@@ -1700,16 +1593,6 @@ class InterfaceBase(InstanceModelMixin):
         utils.coerce_dict_values(self.inputs, report_issues)
         utils.coerce_dict_values(self.operations, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Interface type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            utils.dump_dict_values(self.operations, 'Operations')
-
 
 class OperationBase(InstanceModelMixin):
     """
@@ -1917,13 +1800,13 @@ class OperationBase(InstanceModelMixin):
         from ..orchestrator.decorators import OPERATION_DECORATOR_RESERVED_ARGUMENTS
         used_reserved_names = \
             OPERATION_DECORATOR_RESERVED_ARGUMENTS.intersection(self.arguments.keys())
-        if used_reserved_names:
-            context = ConsumptionContext.get_thread_local()
-            context.validation.report('using reserved arguments in operation "{0}": {1}'
-                                      .format(
-                                          self.name,
-                                          formatting.string_list_as_string(used_reserved_names)),
-                                      level=validation.Issue.EXTERNAL)
+        # if used_reserved_names:
+        #     # context = ConsumptionContext.get_thread_local()
+        #     context.validation.report('using reserved arguments in operation "{0}": {1}'
+        #                               .format(
+        #                                   self.name,
+        #                                   formatting.string_list_as_string(used_reserved_names)),
+        #                               level=validation.Issue.EXTERNAL)
 
 
     @property
@@ -1940,35 +1823,6 @@ class OperationBase(InstanceModelMixin):
         utils.coerce_dict_values(self.configurations, report_issues)
         utils.coerce_dict_values(self.arguments, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            if self.implementation is not None:
-                console.puts('Implementation: {0}'.format(
-                    context.style.literal(self.implementation)))
-            if self.dependencies:
-                console.puts(
-                    'Dependencies: {0}'.format(
-                        ', '.join((str(context.style.literal(v)) for v in self.dependencies))))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            if self.executor is not None:
-                console.puts('Executor: {0}'.format(context.style.literal(self.executor)))
-            if self.max_attempts is not None:
-                console.puts('Max attempts: {0}'.format(context.style.literal(self.max_attempts)))
-            if self.retry_interval is not None:
-                console.puts('Retry interval: {0}'.format(
-                    context.style.literal(self.retry_interval)))
-            if self.plugin is not None:
-                console.puts('Plugin: {0}'.format(
-                    context.style.literal(self.plugin.name)))
-            utils.dump_dict_values(self.configurations, 'Configuration')
-            if self.function is not None:
-                console.puts('Function: {0}'.format(context.style.literal(self.function)))
-            utils.dump_dict_values(self.arguments, 'Arguments')
-
 
 class ArtifactBase(InstanceModelMixin):
     """
@@ -2091,20 +1945,3 @@ class ArtifactBase(InstanceModelMixin):
     def coerce_values(self, report_issues):
         utils.coerce_dict_values(self.properties, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Artifact type: {0}'.format(context.style.type(self.type.name)))
-            console.puts('Source path: {0}'.format(context.style.literal(self.source_path)))
-            if self.target_path is not None:
-                console.puts('Target path: {0}'.format(context.style.literal(self.target_path)))
-            if self.repository_url is not None:
-                console.puts('Repository URL: {0}'.format(
-                    context.style.literal(self.repository_url)))
-            if self.repository_credential:
-                console.puts('Repository credential: {0}'.format(
-                    context.style.literal(self.repository_credential)))
-            utils.dump_dict_values(self.properties, 'Properties')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index b505a06..665a4f1 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -31,8 +31,6 @@ from sqlalchemy import (
 )
 from sqlalchemy.ext.declarative import declared_attr
 
-from ..parser import validation
-from ..parser.consumption import ConsumptionContext
 from ..utils import (collections, formatting, console)
 from .mixins import TemplateModelMixin
 from . import (
@@ -338,23 +336,6 @@ class ServiceTemplateBase(TemplateModelMixin):
         utils.coerce_dict_values(self.outputs, report_issues)
         utils.coerce_dict_values(self.workflow_templates, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.description is not None:
-            console.puts(context.style.meta(self.description))
-        utils.dump_dict_values(self.meta_data, 'Metadata')
-        for node_template in self.node_templates.itervalues():
-            node_template.dump()
-        for group_template in self.group_templates.itervalues():
-            group_template.dump()
-        for policy_template in self.policy_templates.itervalues():
-            policy_template.dump()
-        if self.substitution_template is not None:
-            self.substitution_template.dump()
-        utils.dump_dict_values(self.inputs, 'Inputs')
-        utils.dump_dict_values(self.outputs, 'Outputs')
-        utils.dump_dict_values(self.workflow_templates, 'Workflow templates')
-
     def dump_types(self):
         if self.node_types.children:
             console.puts('Node types:')
@@ -556,20 +537,6 @@ class NodeTemplateBase(TemplateModelMixin):
         utils.coerce_dict_values(self.capability_templates, report_issues)
         utils.coerce_list_values(self.requirement_templates, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Node template: {0}'.format(context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_dict_values(self.attributes, 'Attributes')
-            utils.dump_interfaces(self.interface_templates)
-            utils.dump_dict_values(self.artifact_templates, 'Artifact templates')
-            utils.dump_dict_values(self.capability_templates, 'Capability templates')
-            utils.dump_list_values(self.requirement_templates, 'Requirement templates')
-
     @property
     def scaling(self):
         scaling = {}
@@ -614,14 +581,16 @@ class NodeTemplateBase(TemplateModelMixin):
                 (scaling['max_instances'] < scaling['min_instances']) or
                 (scaling['default_instances'] < scaling['min_instances']) or
                 (scaling['default_instances'] > scaling['max_instances'])):
-            context = ConsumptionContext.get_thread_local()
-            context.validation.report('invalid scaling parameters for node template "{0}": '
-                                      'min={1}, max={2}, default={3}'.format(
-                                          self.name,
-                                          scaling['min_instances'],
-                                          scaling['max_instances'],
-                                          scaling['default_instances']),
-                                      level=validation.Issue.BETWEEN_TYPES)
+            pass
+            # TODO: fix this
+            # context = ConsumptionContext.get_thread_local()
+            # context.validation.report('invalid scaling parameters for node template "{0}": '
+                                      # 'min={1}, max={2}, default={3}'.format(
+                                      #     self.name,
+                                      #     scaling['min_instances'],
+                                      #     scaling['max_instances'],
+                                      #     scaling['default_instances']),
+                                      # level=validation.Issue.BETWEEN_TYPES)
 
         return scaling
 
@@ -772,19 +741,6 @@ class GroupTemplateBase(TemplateModelMixin):
         utils.coerce_dict_values(self.properties, report_issues)
         utils.coerce_dict_values(self.interface_templates, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Group template: {0}'.format(context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interface_templates)
-            if self.node_templates:
-                console.puts('Member node templates: {0}'.format(', '.join(
-                    (str(context.style.node(v.name)) for v in self.node_templates))))
-
     def contains_node_template(self, name):
         for node_template in self.node_templates:
             if node_template.name == name:
@@ -900,21 +856,6 @@ class PolicyTemplateBase(TemplateModelMixin):
     def coerce_values(self, report_issues):
         utils.coerce_dict_values(self.properties, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Policy template: {0}'.format(context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            if self.node_templates:
-                console.puts('Target node templates: {0}'.format(', '.join(
-                    (str(context.style.node(v.name)) for v in self.node_templates))))
-            if self.group_templates:
-                console.puts('Target group templates: {0}'.format(', '.join(
-                    (str(context.style.node(v.name)) for v in self.group_templates))))
-
     def is_for_node_template(self, name):
         for node_template in self.node_templates:
             if node_template.name == name:
@@ -994,13 +935,6 @@ class SubstitutionTemplateBase(TemplateModelMixin):
     def coerce_values(self, report_issues):
         utils.coerce_dict_values(self.mappings, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Substitution template:')
-        with context.style.indent:
-            console.puts('Node type: {0}'.format(context.style.type(self.node_type.name)))
-            utils.dump_dict_values(self.mappings, 'Mappings')
-
 
 class SubstitutionTemplateMappingBase(TemplateModelMixin):
     """
@@ -1083,19 +1017,6 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
     def coerce_values(self, report_issues):
         pass
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.capability_template is not None:
-            node_template = self.capability_template.node_template
-        else:
-            node_template = self.requirement_template.node_template
-        console.puts('{0} -> {1}.{2}'.format(
-            context.style.node(self.name),
-            context.style.node(node_template.name),
-            context.style.node(self.capability_template.name
-                               if self.capability_template
-                               else self.requirement_template.name)))
-
 
 class RequirementTemplateBase(TemplateModelMixin):
     """
@@ -1235,17 +1156,19 @@ class RequirementTemplateBase(TemplateModelMixin):
     """)
 
     def find_target(self, source_node_template):
-        context = ConsumptionContext.get_thread_local()
+        # context = ConsumptionContext.get_thread_local()
 
         # We might already have a specific node template, so we'll just verify it
         if self.target_node_template is not None:
             if not source_node_template.is_target_node_template_valid(self.target_node_template):
-                context.validation.report('requirement "{0}" of node template "{1}" is for node '
-                                          'template "{2}" but it does not match constraints'.format(
-                                              self.name,
-                                              self.target_node_template.name,
-                                              source_node_template.name),
-                                          level=validation.Issue.BETWEEN_TYPES)
+                # TODO: fix
+                pass
+                # context.validation.report('requirement "{0}" of node template "{1}" is for node '
+                                          # 'template "{2}" but it does not match constraints'.format(
+                                          #     self.name,
+                                          #     self.target_node_template.name,
+                                          #     source_node_template.name),
+                                          # level=validation.Issue.BETWEEN_TYPES)
             if (self.target_capability_type is not None) \
                 or (self.target_capability_name is not None):
                 target_node_capability = self.find_target_capability(source_node_template,
@@ -1301,35 +1224,6 @@ class RequirementTemplateBase(TemplateModelMixin):
         if self.relationship_template is not None:
             self.relationship_template.coerce_values(report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.name:
-            console.puts(context.style.node(self.name))
-        else:
-            console.puts('Requirement:')
-        with context.style.indent:
-            if self.target_node_type is not None:
-                console.puts('Target node type: {0}'.format(
-                    context.style.type(self.target_node_type.name)))
-            elif self.target_node_template is not None:
-                console.puts('Target node template: {0}'.format(
-                    context.style.node(self.target_node_template.name)))
-            if self.target_capability_type is not None:
-                console.puts('Target capability type: {0}'.format(
-                    context.style.type(self.target_capability_type.name)))
-            elif self.target_capability_name is not None:
-                console.puts('Target capability name: {0}'.format(
-                    context.style.node(self.target_capability_name)))
-            if self.target_node_template_constraints:
-                console.puts('Target node template constraints:')
-                with context.style.indent:
-                    for constraint in self.target_node_template_constraints:
-                        console.puts(context.style.literal(constraint))
-            if self.relationship_template:
-                console.puts('Relationship:')
-                with context.style.indent:
-                    self.relationship_template.dump()
-
 
 class RelationshipTemplateBase(TemplateModelMixin):
     """
@@ -1416,19 +1310,6 @@ class RelationshipTemplateBase(TemplateModelMixin):
         utils.coerce_dict_values(self.properties, report_issues)
         utils.coerce_dict_values(self.interface_templates, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.type is not None:
-            console.puts('Relationship type: {0}'.format(context.style.type(self.type.name)))
-        else:
-            console.puts('Relationship template: {0}'.format(
-                context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interface_templates, 'Interface templates')
-
 
 class CapabilityTemplateBase(TemplateModelMixin):
     """
@@ -1568,25 +1449,6 @@ class CapabilityTemplateBase(TemplateModelMixin):
     def coerce_values(self, report_issues):
         utils.coerce_dict_values(self.properties, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            console.puts(
-                'Occurrences: {0:d}{1}'.format(
-                    self.min_occurrences or 0,
-                    ' to {0:d}'.format(self.max_occurrences)
-                    if self.max_occurrences is not None
-                    else ' or more'))
-            if self.valid_source_node_types:
-                console.puts('Valid source node types: {0}'.format(
-                    ', '.join((str(context.style.type(v.name))
-                               for v in self.valid_source_node_types))))
-            utils.dump_dict_values(self.properties, 'Properties')
-
 
 class InterfaceTemplateBase(TemplateModelMixin):
     """
@@ -1720,16 +1582,6 @@ class InterfaceTemplateBase(TemplateModelMixin):
         utils.coerce_dict_values(self.inputs, report_issues)
         utils.coerce_dict_values(self.operation_templates, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Interface type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            utils.dump_dict_values(self.operation_templates, 'Operation templates')
-
 
 class OperationTemplateBase(TemplateModelMixin):
     """
@@ -1892,33 +1744,6 @@ class OperationTemplateBase(TemplateModelMixin):
         utils.coerce_dict_values(self.inputs, report_issues)
         utils.coerce_dict_values(self.configurations, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            if self.implementation is not None:
-                console.puts('Implementation: {0}'.format(
-                    context.style.literal(self.implementation)))
-            if self.dependencies:
-                console.puts('Dependencies: {0}'.format(
-                    ', '.join((str(context.style.literal(v)) for v in self.dependencies))))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            if self.executor is not None:
-                console.puts('Executor: {0}'.format(context.style.literal(self.executor)))
-            if self.max_attempts is not None:
-                console.puts('Max attempts: {0}'.format(context.style.literal(self.max_attempts)))
-            if self.retry_interval is not None:
-                console.puts('Retry interval: {0}'.format(
-                    context.style.literal(self.retry_interval)))
-            if self.plugin_specification is not None:
-                console.puts('Plugin specification: {0}'.format(
-                    context.style.literal(self.plugin_specification.name)))
-            utils.dump_dict_values(self.configurations, 'Configuration')
-            if self.function is not None:
-                console.puts('Function: {0}'.format(context.style.literal(self.function)))
-
 
 class ArtifactTemplateBase(TemplateModelMixin):
     """
@@ -2034,25 +1859,6 @@ class ArtifactTemplateBase(TemplateModelMixin):
     def coerce_values(self, report_issues):
         utils.coerce_dict_values(self.properties, report_issues)
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Artifact type: {0}'.format(context.style.type(self.type.name)))
-            console.puts('Source path: {0}'.format(context.style.literal(self.source_path)))
-            if self.target_path is not None:
-                console.puts('Target path: {0}'.format(context.style.literal(self.target_path)))
-            if self.repository_url is not None:
-                console.puts('Repository URL: {0}'.format(
-                    context.style.literal(self.repository_url)))
-            if self.repository_credential:
-                console.puts('Repository credential: {0}'.format(
-                    context.style.literal(self.repository_credential)))
-            utils.dump_dict_values(self.properties, 'Properties')
-
-
 class PluginSpecificationBase(TemplateModelMixin):
     """
     Requirement for a :class:`Plugin`.

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/modeling/utils.py
----------------------------------------------------------------------
diff --git a/aria/modeling/utils.py b/aria/modeling/utils.py
index e50fb2f..1002d5a 100644
--- a/aria/modeling/utils.py
+++ b/aria/modeling/utils.py
@@ -22,8 +22,6 @@ from json import JSONEncoder
 from StringIO import StringIO
 
 from . import exceptions
-from ..parser.consumption import ConsumptionContext
-from ..utils.console import puts
 from ..utils.type import validate_value_type
 from ..utils.collections import OrderedDict
 from ..utils.formatting import string_list_as_string
@@ -155,63 +153,6 @@ def coerce_list_values(the_list, report_issues=False):
         value.coerce_values(report_issues)
 
 
-def validate_dict_values(the_dict):
-    if not the_dict:
-        return
-    validate_list_values(the_dict.itervalues())
-
-
-def validate_list_values(the_list):
-    if not the_list:
-        return
-    for value in the_list:
-        value.validate()
-
-
-def instantiate_dict(container, the_dict, from_dict):
-    if not from_dict:
-        return
-    for name, value in from_dict.iteritems():
-        value = value.instantiate(container)
-        if value is not None:
-            the_dict[name] = value
-
-
-def instantiate_list(container, the_list, from_list):
-    if not from_list:
-        return
-    for value in from_list:
-        value = value.instantiate(container)
-        if value is not None:
-            the_list.append(value)
-
-
-def dump_list_values(the_list, name):
-    if not the_list:
-        return
-    puts('%s:' % name)
-    context = ConsumptionContext.get_thread_local()
-    with context.style.indent:
-        for value in the_list:
-            value.dump()
-
-
-def dump_dict_values(the_dict, name):
-    if not the_dict:
-        return
-    dump_list_values(the_dict.itervalues(), name)
-
-
-def dump_interfaces(interfaces, name='Interfaces'):
-    if not interfaces:
-        return
-    puts('%s:' % name)
-    context = ConsumptionContext.get_thread_local()
-    with context.style.indent:
-        for interface in interfaces.itervalues():
-            interface.dump()
-
-
 def parameters_as_values(the_dict):
     return dict((k, v.value) for k, v in the_dict.iteritems())
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/orchestrator/execution_plugin/instantiation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/instantiation.py b/aria/orchestrator/execution_plugin/instantiation.py
index f55aa50..4390252 100644
--- a/aria/orchestrator/execution_plugin/instantiation.py
+++ b/aria/orchestrator/execution_plugin/instantiation.py
@@ -23,7 +23,6 @@ from ...utils.type import full_type_name
 from ...utils.formatting import safe_repr
 from ...utils.collections import OrderedDict
 from ...parser import validation
-from ...parser.consumption import ConsumptionContext
 from ...modeling.functions import Function
 
 
@@ -110,20 +109,24 @@ def _configure_remote(operation):
 
     # Make sure we have a user
     if fabric_env.get('user') is None:
-        context = ConsumptionContext.get_thread_local()
-        context.validation.report('must configure "ssh.user" for "{0}"'
-                                  .format(operation.implementation),
-                                  level=validation.Issue.BETWEEN_TYPES)
+        # TODO: fix
+        pass
+        # context = ConsumptionContext.get_thread_local()
+        # context.validation.report('must configure "ssh.user" for "{0}"'
+        #                           .format(operation.implementation),
+        #                           level=validation.Issue.BETWEEN_TYPES)
 
     # Make sure we have an authentication value
     if (fabric_env.get('password') is None) and \
         (fabric_env.get('key') is None) and \
         (fabric_env.get('key_filename') is None):
-        context = ConsumptionContext.get_thread_local()
-        context.validation.report('must configure "ssh.password", "ssh.key", or "ssh.key_filename" '
-                                  'for "{0}"'
-                                  .format(operation.implementation),
-                                  level=validation.Issue.BETWEEN_TYPES)
+        # TODO: fix
+        pass
+        # context = ConsumptionContext.get_thread_local()
+        # context.validation.report('must configure "ssh.password", "ssh.key", or "ssh.key_filename" '
+        #                           'for "{0}"'
+        #                           .format(operation.implementation),
+        #                           level=validation.Issue.BETWEEN_TYPES)
 
     operation.arguments['fabric_env'] = Argument.wrap('fabric_env', fabric_env,
                                                       'Fabric configuration.')
@@ -152,10 +155,12 @@ def _get_process(operation):
         elif k == 'env':
             _validate_type(v, dict, 'process.env')
         else:
-            context = ConsumptionContext.get_thread_local()
-            context.validation.report('unsupported configuration parameter: "process.{0}"'
-                                      .format(k),
-                                      level=validation.Issue.BETWEEN_TYPES)
+            # TODO: fix
+            pass
+            # context = ConsumptionContext.get_thread_local()
+            # context.validation.report('unsupported configuration parameter: "process.{0}"'
+            #                           .format(k),
+            #                           level=validation.Issue.BETWEEN_TYPES)
     return value
 
 
@@ -185,9 +190,11 @@ def _get_ssh(operation):
         elif k == 'address':
             _validate_type(v, basestring, 'ssh.address')
         else:
-            context = ConsumptionContext.get_thread_local()
-            context.validation.report('unsupported configuration parameter: "ssh.{0}"'.format(k),
-                                      level=validation.Issue.BETWEEN_TYPES)
+            # TODO: fix
+            pass
+            # context = ConsumptionContext.get_thread_local()
+            # context.validation.report('unsupported configuration parameter: "ssh.{0}"'.format(k),
+            #                           level=validation.Issue.BETWEEN_TYPES)
     return value
 
 
@@ -195,10 +202,12 @@ def _validate_type(value, the_type, name):
     if isinstance(value, Function):
         return
     if not isinstance(value, the_type):
-        context = ConsumptionContext.get_thread_local()
-        context.validation.report('"{0}" configuration is not a {1}: {2}'
-                                  .format(name, full_type_name(the_type), safe_repr(value)),
-                                  level=validation.Issue.BETWEEN_TYPES)
+        # TODO: fix
+        pass
+        # context = ConsumptionContext.get_thread_local()
+        # context.validation.report('"{0}" configuration is not a {1}: {2}'
+        #                           .format(name, full_type_name(the_type), safe_repr(value)),
+        #                           level=validation.Issue.BETWEEN_TYPES)
 
 
 def _coerce_bool(value, name):
@@ -212,10 +221,12 @@ def _coerce_bool(value, name):
     elif value == 'false':
         return False
     else:
-        context = ConsumptionContext.get_thread_local()
-        context.validation.report('"{0}" configuration is not "true" or "false": {1}'
-                                  .format(name, safe_repr(value)),
-                                  level=validation.Issue.BETWEEN_TYPES)
+        # TODO: fix
+        pass
+        # context = ConsumptionContext.get_thread_local()
+        # context.validation.report('"{0}" configuration is not "true" or "false": {1}'
+        #                           .format(name, safe_repr(value)),
+        #                           level=validation.Issue.BETWEEN_TYPES)
 
 
 def _dict_to_list_of_strings(the_dict, name):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/orchestrator/topology/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/__init__.py b/aria/orchestrator/topology/__init__.py
index 4109af6..4737ac1 100644
--- a/aria/orchestrator/topology/__init__.py
+++ b/aria/orchestrator/topology/__init__.py
@@ -13,54 +13,19 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from StringIO import StringIO
+
 from ...modeling import models
 from . import (
     template,
-    instance
+    instance,
+    common
 )
 
-class Handler(object):
-
-    _handlers = {
-        # Templates
-        models.ServiceTemplate: template.ServiceTemplate,
-        models.ArtifactTemplate: template.ArtifactTemplate,
-        models.CapabilityTemplate: template.CapabilityTemplate,
-        models.GroupTemplate: template.GroupTemplate,
-        models.InterfaceTemplate: template.InterfaceTemplate,
-        models.NodeTemplate: template.NodeTemplate,
-        models.PolicyTemplate: template.PolicyTemplate,
-        models.SubstitutionTemplate: template.SubstitutionTemplate,
-        models.SubstitutionTemplateMapping: template.SubstitutionMapping,
-        models.RelationshipTemplate: template.RelationshipTemplate,
-        models.OperationTemplate: template.OperationTemplate,
-        models.RequirementTemplate: template.RequirementTemplate,
-
-        # Instances
-        models.Artifact: instance.Artifact,
-        models.Capability: instance.Capability,
-        models.Group: instance.Group,
-        models.Interface: instance.Interface,
-        models.Node: instance.Node,
-        models.Operation: instance.Operation,
-        models.Policy: instance.Policy,
-        models.Relationship: instance.Relationship,
-        models.Service: instance.Service,
-        models.Substitution: instance.Substitution,
-        models.SubstitutionMapping: instance.SubstitutionMapping,
-        models.Metadata: instance.Metadata,
 
-        # Common
-        models.Attribute: instance.Parameter,
-        models.Property: instance.Parameter,
-        models.Input: instance.Parameter,
-        models.Output: instance.Parameter,
-        models.Configuration: instance.Parameter,
-        models.Argument: instance.Parameter,
-    }
+class Handler(object):
 
-    _instance_mapping = {
-        # Templates
+    _init_map = {
         models.ServiceTemplate: models.Service,
         models.ArtifactTemplate: models.Artifact,
         models.CapabilityTemplate: models.Capability,
@@ -69,25 +34,67 @@ class Handler(object):
         models.NodeTemplate: models.Node,
         models.PolicyTemplate: models.Policy,
         models.SubstitutionTemplate: models.Substitution,
-        models.SubstitutionMapping: models.SubstitutionMapping,
         models.RelationshipTemplate: models.Relationship,
         models.OperationTemplate: models.Operation,
-        models.Metadata: models.Metadata,
+        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, context):
+            self._context = context
+            self._str = StringIO()
+
+        def write(self, str_):
+            self._str.write(str_)
+
+        def __repr__(self):
+            return self._str.getvalue()
+
+        def __str__(self):
+            return repr(self)
+
+        def __getattr__(self, item):
+            try:
+                return getattr(self._context, item)
+            except AttributeError:
+                return super(Handler.TopologyStylizer, self).__getattribute__(item)
+
     def __init__(self, model_storage=None):
         # TODO: model storage is required only for the list of plugins, can we get it
         # somewhere else?
         self._model_storage = model_storage
+        self._handlers = 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._TemplateHandler,
+                                                                      common._InstanceHandler)):
+                handlers[getattr(models, attribute_name)] = attribute
+        return handlers
 
     def instantiate(self, template, **kwargs):
+        """
+        all handlers used by instantiate should hold a tuple as value (handler, instnace_cls)
+        :param template:
+        :param kwargs:
+        :return:
+        """
         if isinstance(template, dict):
             return dict((name, self.instantiate(value, **kwargs))
                         for name, value in template.iteritems())
@@ -95,7 +102,7 @@ class Handler(object):
             return list(self.instantiate(value, **kwargs) for value in template)
         elif template is not None:
             handler = self._handlers.get(template.__class__)
-            instance_cls = self._instance_mapping[template.__class__]
+            instance_cls = self._init_map.get(template.__class__)
             return handler(self, template).instantiate(instance_cls, **kwargs)
 
     def validate(self, template, **kwargs):
@@ -107,5 +114,23 @@ class Handler(object):
             handler = self._handlers.get(template.__class__)
             return handler(self, template).validate(**kwargs)
 
+    def dump(self, template, context, **kwargs):
+        if not isinstance(context, self.TopologyStylizer):
+            # Wrap the context to contain a stringIO object
+            context = self.TopologyStylizer(context)
+
+        if isinstance(template, dict):
+            return self.dump(template.values(), context, **kwargs)
+        elif isinstance(template, list):
+            context.write('%s:' % template)
+            with context.style.indent:
+                for value in template:
+                    self.dump(value, context, **kwargs)
+        elif template is not None:
+            handler = self._handlers.get(template.__class__)
+            handler(self, template).dump(context, **kwargs)
+
+        return str(context)
+
 
 handler = Handler()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/orchestrator/topology/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/common.py b/aria/orchestrator/topology/common.py
index fb5cf50..48e3c07 100644
--- a/aria/orchestrator/topology/common.py
+++ b/aria/orchestrator/topology/common.py
@@ -14,14 +14,11 @@
 # limitations under the License.
 
 
-class _TemplateEntity(object):
+class _Handler(object):
     def __init__(self, topology, template):
         self._topology = topology
         self._template = template
 
-    def instantiate(self, **kwargs):
-        pass
-
     def coerce(self):
         raise NotImplementedError
 
@@ -32,10 +29,15 @@ class _TemplateEntity(object):
         for template in templates:
             self._topology.validate(template)
 
-    def dump(self):
+    def dump(self, context):
         raise NotImplementedError
 
 
-class _InstanceEntity(_TemplateEntity):
+class _TemplateHandler(_Handler):
+
     def instantiate(self, **kwargs):
-        pass
+        raise NotImplementedError
+
+
+class _InstanceHandler(_Handler):
+    pass

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/orchestrator/topology/instance.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/instance.py b/aria/orchestrator/topology/instance.py
index 337c9d5..7fb8c23 100644
--- a/aria/orchestrator/topology/instance.py
+++ b/aria/orchestrator/topology/instance.py
@@ -15,30 +15,58 @@
 
 from . import common
 
+# TODO: this should this be here?
+from aria.utils import formatting
 
-class Artifact(common._InstanceEntity):
+
+class Artifact(common._InstanceHandler):
     def coerce(self):
         pass
 
     def validate(self, **kwargs):
         self._topology.validate(self._template.properties)
 
-    def dump(self):
-        pass
-
-
-class Capability(common._InstanceEntity):
+    def dump(self, context):
+        context.write(context.style.node(self._template.name))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            context.write('Artifact type: {0}'.format(context.style.type(self._template.type.name)))
+            context.write('Source path: {0}'.format(
+                context.style.literal(self._template.source_path)))
+            if self._template.target_path is not None:
+                context.write('Target path: {0}'.format(
+                    context.style.literal(self._template.target_path)))
+            if self._template.repository_url is not None:
+                context.write('Repository URL: {0}'.format(
+                    context.style.literal(self._template.repository_url)))
+            if self._template.repository_credential:
+                context.write('Repository credential: {0}'.format(
+                    context.style.literal(self._template.repository_credential)))
+            self._topology.dump(self._template.properties, context, 'Properties')
+            
+
+class Capability(common._InstanceHandler):
     def coerce(self):
         pass
 
     def validate(self, **kwargs):
         self._topology.validate(self._template.properties)
 
-    def dump(self):
-        pass
+    def dump(self, context):
+        context.write(context.style.node(self._template.name))
+        with context.style.indent:
+            context.write('Type: {0}'.format(context.style.type(self._template.type.name)))
+            context.write('Occurrences: {0:d} ({1:d}{2})'.format(
+                self._template.occurrences,
+                self._template.min_occurrences or 0,
+                ' to {0:d}'.format(self._template.max_occurrences)
+                if self._template.max_occurrences is not None
+                else ' or more'))
+            self._topology.dump(self._template.properties, context, 'Properties')
 
 
-class Group(common._InstanceEntity):
+class Group(common._InstanceHandler):
     def coerce(self):
         pass
 
@@ -46,11 +74,20 @@ class Group(common._InstanceEntity):
         self._validate(self._template.properties,
                        self._template.interfaces)
 
-    def dump(self):
-        pass
+    def dump(self, context):
+        context.write('Group: {0}'.format(context.style.node(self._template.name)))
+        with context.style.indent:
+            context.write('Type: {0}'.format(context.style.type(self._template.type.name)))
+            self._topology.dump(self._template.properties, context, 'Properties')
+            self._topology.dump(self._template.interfaces, context, 'Interfaces')
+            if self._template.nodes:
+                context.write('Member nodes:')
+                with context.style.indent:
+                    for node in self._template.nodes:
+                        context.write(context.style.node(node.name))
 
 
-class Interface(common._InstanceEntity):
+class Interface(common._InstanceHandler):
     def coerce(self):
         pass
 
@@ -58,11 +95,17 @@ class Interface(common._InstanceEntity):
         self._validate(self._template.inputs,
                        self._template.operations)
 
-    def dump(self):
-        pass
+    def dump(self, context):
+        context.write(context.style.node(self._template.name))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            context.write('Interface type: {0}'.format(context.style.type(self._template.type.name)))
+            self._topology.dump(self._template.inputs, context, 'Inputs')
+            self._topology.dump(self._template.operations, context, 'Operations')
 
 
-class Node(common._InstanceEntity):
+class Node(common._InstanceHandler):
     def coerce(self):
         pass
 
@@ -85,11 +128,20 @@ class Node(common._InstanceEntity):
                        self._template.capabilities,
                        self._template.outbound_relationships)
 
-    def dump(self):
-        pass
+    def dump(self, context):
+        context.write('Node: {0}'.format(context.style.node(self._template.name)))
+        with context.style.indent:
+            context.write('Type: {0}'.format(context.style.type(self._template.type.name)))
+            context.write('Template: {0}'.format(context.style.node(self._template.node_template.name)))
+            self._topology.dump(self._template.properties, context, 'Properties')
+            self._topology.dump(self._template.attributes, context, 'Attributes')
+            self._topology.dump(self._template.interfaces, context, 'Interfaces')
+            self._topology.dump(self._template.artifacts, context, 'Artifacts')
+            self._topology.dump(self._template.capabilities, context, 'Capabilities')
+            self._topology.dump(self._template.outbound_relationships, context, 'Relationships')
 
 
-class Operation(common._InstanceEntity):
+class Operation(common._InstanceHandler):
     def coerce(self):
         pass
 
@@ -98,22 +150,60 @@ class Operation(common._InstanceEntity):
                        self._template.configurations,
                        self._template.arguments)
 
-    def dump(self):
-        pass
-
-
-class Policy(common._InstanceEntity):
+    def dump(self, context):
+        context.write(context.style.node(self._template.name))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            if self._template.implementation is not None:
+                context.write('Implementation: {0}'.format(
+                    context.style.literal(self._template.implementation)))
+            if self._template.dependencies:
+                context.write(
+                    'Dependencies: {0}'.format(
+                        ', '.join((str(context.style.literal(v)) for v in self._template.dependencies))))
+            self._topology.dump(self._template.inputs, context, 'Inputs')
+            if self._template.executor is not None:
+                context.write('Executor: {0}'.format(context.style.literal(self._template.executor)))
+            if self._template.max_attempts is not None:
+                context.write('Max attempts: {0}'.format(context.style.literal(self._template.max_attempts)))
+            if self._template.retry_interval is not None:
+                context.write('Retry interval: {0}'.format(
+                    context.style.literal(self._template.retry_interval)))
+            if self._template.plugin is not None:
+                context.write('Plugin: {0}'.format(
+                    context.style.literal(self._template.plugin.name)))
+            self._topology.dump(self._template.configurations, context, 'Configuration')
+            if self._template.function is not None:
+                context.write('Function: {0}'.format(context.style.literal(self._template.function)))
+            self._topology.dump(self._template.arguments, context, 'Arguments')
+
+
+class Policy(common._InstanceHandler):
     def coerce(self):
         pass
 
     def validate(self, **kwargs):
         self._topology.validate(self._template.properties)
 
-    def dump(self):
-        pass
-
-
-class Relationship(common._InstanceEntity):
+    def dump(self, context):
+        context.write('Policy: {0}'.format(context.style.node(self._template.name)))
+        with context.style.indent:
+            context.write('Type: {0}'.format(context.style.type(self._template.type.name)))
+            self._topology.dump(self._template.properties, context, 'Properties')
+            if self._template.nodes:
+                context.write('Target nodes:')
+                with context.style.indent:
+                    for node in self._template.nodes:
+                        context.write(context.style.node(node.name))
+            if self._template.groups:
+                context.write('Target groups:')
+                with context.style.indent:
+                    for group in self._template.groups:
+                        context.write(context.style.node(group.name))
+
+
+class Relationship(common._InstanceHandler):
     def coerce(self):
         pass
 
@@ -121,11 +211,28 @@ class Relationship(common._InstanceEntity):
         self._validate(self._template.properties,
                        self._template.interfaces)
 
-    def dump(self):
-        pass
-
-
-class Service(common._InstanceEntity):
+    def dump(self, context):
+        if self._template.name:
+            context.write('{0} ->'.format(context.style.node(self._template.name)))
+        else:
+            context.write('->')
+        with context.style.indent:
+            context.write('Node: {0}'.format(context.style.node(self._template.target_node.name)))
+            if self._template.target_capability:
+                context.write('Capability: {0}'.format(context.style.node(
+                    self._template.target_capability.name)))
+            if self._template.type is not None:
+                context.write('Relationship type: {0}'.format(
+                    context.style.type(self._template.type.name)))
+            if (self._template.relationship_template is not None and
+                self._template.relationship_template.name):
+                context.write('Relationship template: {0}'.format(
+                    context.style.node(self._template.relationship_template.name)))
+            self._topology.dump(self._template.properties, context, 'Properties')
+            self._topology.dump(self._template.interfaces, context, 'Interfaces')
+
+
+class Service(common._InstanceHandler):
     def coerce(self):
         pass
 
@@ -134,27 +241,43 @@ class Service(common._InstanceEntity):
                        self._template.nodes,
                        self._template.groups,
                        self._template.policies,
-                       self._template.substituion,
+                       self._template.substitution,
                        self._template.inputs,
                        self._template.outputs,
                        self._template.workflows)
 
-    def dump(self):
-        pass
-
-
-class Substitution(common._InstanceEntity):
+    def dump(self, context):
+        if self._template.description is not None:
+            context.write(context.style.meta(self._template.description))
+        self._topology.dump(self._template.meta_data, context, 'Metadata')
+        for node in self._template.nodes.itervalues():
+            node.dump()
+        for group in self._template.groups.itervalues():
+            group.dump()
+        for policy in self._template.policies.itervalues():
+            policy.dump()
+        if self._template.substitution is not None:
+            self._template.substitution.dump()
+        self._topology.dump(self._template.inputs, context, 'Inputs')
+        self._topology.dump(self._template.outputs, context, 'Outputs')
+        self._topology.dump(self._template.workflows, context, 'Workflows')
+
+
+class Substitution(common._InstanceHandler):
     def coerce(self):
         pass
 
     def validate(self, **kwargs):
         self._topology.validate(self._template.mappings)
 
-    def dump(self):
-        pass
+    def dump(self, context):
+        context.write('Substitution:')
+        with context.style.indent:
+            context.write('Node type: {0}'.format(context.style.type(self._template.node_type.name)))
+            self._topology.dump(self._template.mappings, context, 'Mappings')
 
 
-class SubstitutionMapping(common._InstanceEntity):
+class SubstitutionMapping(common._InstanceHandler):
     def coerce(self):
         pass
 
@@ -169,14 +292,24 @@ class SubstitutionMapping(common._InstanceEntity):
             #                               formatting.safe_repr(self.node.name)),
             #                           level=validation.Issue.BETWEEN_TYPES)
 
-    def dump(self):
-        pass
-
-
-class Metadata(common._InstanceEntity):
-
-    def dump(self):
-        pass
+    def dump(self, context):
+        if self._template.capability is not None:
+            context.write('{0} -> {1}.{2}'.format(
+                context.style.node(self._template.name),
+                context.style.node(self._template.capability.node.name),
+                context.style.node(self._template.capability.name)))
+        else:
+            context.write('{0} -> {1}.{2}'.format(
+                context.style.node(self._template.name),
+                context.style.node(self._template.node.name),
+                context.style.node(self._template.requirement_template.name)))
+
+class Metadata(common._InstanceHandler):
+
+    def dump(self, context):
+        context.write('{0}: {1}'.format(
+            context.style.property(self._topology.name),
+            context.style.literal(self._topology.value)))
 
     def coerce(self):
         pass
@@ -188,10 +321,20 @@ class Metadata(common._InstanceEntity):
         pass
 
 
-class Parameter(common._InstanceEntity):
+class _Parameter(common._InstanceHandler):
 
-    def dump(self):
-        pass
+    def dump(self, context):
+        if self._template.type_name is not None:
+            context.write('{0}: {1} ({2})'.format(
+                context.style.property(self._template.name),
+                context.style.literal(formatting.as_raw(self._template.value)),
+                context.style.type(self._template.type_name)))
+        else:
+            context.write('{0}: {1}'.format(
+                context.style.property(self._template.name),
+                context.style.literal(formatting.as_raw(self._template.value))))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
 
     def coerce(self):
         pass
@@ -206,3 +349,39 @@ class Parameter(common._InstanceEntity):
 
     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._InstanceHandler):
+    def coerce(self):
+        pass
+
+    def dump(self, context):
+        if self._template.name:
+            context.write(context.style.type(self._template.name))
+        with context.style.indent:
+            for child in self._template.children:
+                self._topology.dump(context, child)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5c92ccad/aria/orchestrator/topology/template.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/template.py b/aria/orchestrator/topology/template.py
index 12fc23e..5826a20 100644
--- a/aria/orchestrator/topology/template.py
+++ b/aria/orchestrator/topology/template.py
@@ -15,14 +15,26 @@
 
 from datetime import datetime
 
-
 from ...modeling import utils as modeling_utils
 from . import utils, common
 
 
-class ServiceTemplate(common._TemplateEntity):
-    def dump(self):
-        pass
+class ServiceTemplate(common._TemplateHandler):
+    def dump(self, context):
+        if self._template.description is not None:
+            context.write(context.style.meta(self._template.description))
+        self._topology.dump(self._template.meta_data, context, 'Metadata')
+        for node_template in self._template.node_templates.itervalues():
+            node_template.dump()
+        for group_template in self._template.group_templates.itervalues():
+            group_template.dump()
+        for policy_template in self._template.policy_templates.itervalues():
+            policy_template.dump()
+        if self._template.substitution_template is not None:
+            self._template.substitution_template.dump()
+        self._topology.dump(self._template.inputs, context, 'Inputs')
+        self._topology.dump(self._template.outputs, context, 'Outputs')
+        self._topology.dump(self._template.workflow_templates, context, 'Workflow templates')
 
     def coerce(self):
         pass
@@ -83,9 +95,23 @@ class ServiceTemplate(common._TemplateEntity):
         self._topology.validate(self._template.artifact_types)
 
 
-class ArtifactTemplate(common._TemplateEntity):
-    def dump(self):
-        pass
+class ArtifactTemplate(common._TemplateHandler):
+    def dump(self, context):
+        context.write(context.style.node(self._template.name))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            context.write('Artifact type: {0}'.format(context.style.type(self._template.type.name)))
+            context.write('Source path: {0}'.format(context.style.literal(self._template.source_path)))
+            if self._template.target_path is not None:
+                context.write('Target path: {0}'.format(context.style.literal(self._template.target_path)))
+            if self._template.repository_url is not None:
+                context.write('Repository URL: {0}'.format(
+                    context.style.literal(self._template.repository_url)))
+            if self._template.repository_credential:
+                context.write('Repository credential: {0}'.format(
+                    context.style.literal(self._template.repository_credential)))
+            self._topology.dump(self._template.properties, context, 'Properties')
 
     def coerce(self):
         pass
@@ -105,9 +131,25 @@ class ArtifactTemplate(common._TemplateEntity):
         self._topology.validate(self._template.properties)
 
 
-class CapabilityTemplate(common._TemplateEntity):
-    def dump(self):
-        pass
+class CapabilityTemplate(common._TemplateHandler):
+    def dump(self, context):
+        context.write(context.style.node(self._template.name))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            context.write('Type: {0}'.format(context.style.type(self._template.type.name)))
+            context.write(
+                'Occurrences: {0:d}{1}'.format(
+                    self._template.min_occurrences or 0,
+                    ' to {0:d}'.format(self._template.max_occurrences)
+                    if self._template.max_occurrences is not None
+                    else ' or more'))
+            if self._template.valid_source_node_types:
+                context.write('Valid source node types: {0}'.format(
+                    ', '.join((str(context.style.type(v.name))
+                               for v in self._template.valid_source_node_types))))
+            self._topology.dump(self._template.properties, contet, 'Properties')
+
 
     def coerce(self):
         pass
@@ -124,9 +166,34 @@ class CapabilityTemplate(common._TemplateEntity):
         self._topology.validate(self._template.properties)
 
 
-class RequirementTemplate(common._TemplateEntity):
-    def dump(self):
-        pass
+class RequirementTemplate(common._TemplateHandler):
+    def dump(self, context):
+        if self._template.name:
+            context.write(context.style.node(self._template.name))
+        else:
+            context.write('Requirement:')
+        with context.style.indent:
+            if self._template.target_node_type is not None:
+                context.write('Target node type: {0}'.format(
+                    context.style.type(self._template.target_node_type.name)))
+            elif self._template.target_node_template is not None:
+                context.write('Target node template: {0}'.format(
+                    context.style.node(self._template.target_node_template.name)))
+            if self._template.target_capability_type is not None:
+                context.write('Target capability type: {0}'.format(
+                    context.style.type(self._template.target_capability_type.name)))
+            elif self._template.target_capability_name is not None:
+                context.write('Target capability name: {0}'.format(
+                    context.style.node(self._template.target_capability_name)))
+            if self._template.target_node_template_constraints:
+                context.write('Target node template constraints:')
+                with context.style.indent:
+                    for constraint in self._template.target_node_template_constraints:
+                        context.write(context.style.literal(constraint))
+            if self._template.relationship_template:
+                context.write('Relationship:')
+                with context.style.indent:
+                    self._template.relationship_template.dump()
 
     def coerce(self):
         pass
@@ -143,9 +210,18 @@ class RequirementTemplate(common._TemplateEntity):
         self._topology.validate(self._template.relationship_template)
 
 
-class GroupTemplate(common._TemplateEntity):
-    def dump(self):
-        pass
+class GroupTemplate(common._TemplateHandler):
+    def dump(self, context):
+        context.write('Group template: {0}'.format(context.style.node(self._template.name)))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            context.write('Type: {0}'.format(context.style.type(self._template.type.name)))
+            self._topology.dump(self._template.properties, context, 'Properties')
+            self._topology.dump(self._template.interface_templates, context, 'Interface Templates')
+            if self._template.node_templates:
+                context.write('Member node templates: {0}'.format(', '.join(
+                    (str(context.style.node(v.name)) for v in self._template.node_templates))))
 
     def coerce(self):
         pass
@@ -168,9 +244,15 @@ class GroupTemplate(common._TemplateEntity):
                        self._template.interface_templates)
 
 
-class InterfaceTemplate(common._TemplateEntity):
-    def dump(self):
-        pass
+class InterfaceTemplate(common._TemplateHandler):
+    def dump(self, context):
+        context.write(context.style.node(self._template.name))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            context.write('Interface type: {0}'.format(context.style.type(self._template.type.name)))
+            self._topology.dump(self._template.inputs, context, 'Inputs')
+            self._topology.dump(self._template.operation_templates, context, 'Operation templates')
 
     def coerce(self):
         pass
@@ -190,9 +272,19 @@ class InterfaceTemplate(common._TemplateEntity):
                        self._template.operation_templates)
 
 
-class NodeTemplate(common._TemplateEntity):
-    def dump(self):
-        pass
+class NodeTemplate(common._TemplateHandler):
+    def dump(self, context):
+        context.write('Node template: {0}'.format(context.style.node(self._template.name)))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            context.write('Type: {0}'.format(context.style.type(self._template.type.name)))
+            self._topology.dump(self._template.properties, context, 'Properties')
+            self._topology.dump(self._template.attributes, context, 'Attributes')
+            self._topology.dump(self._template.interface_templates, context, 'Interface Templates')
+            self._topology.dump(self._template.artifact_templates, context, 'Artifact templates')
+            self._topology.dump(self._template.capability_templates, context, 'Capability templates')
+            self._topology.dump(self._template.requirement_templates, context, 'Requirement templates')
 
     def coerce(self):
         pass
@@ -230,10 +322,20 @@ class NodeTemplate(common._TemplateEntity):
                        self._template.requirement_templates)
 
 
-class PolicyTemplate(common._TemplateEntity):
-    def dump(self):
-        pass
-
+class PolicyTemplate(common._TemplateHandler):
+    def dump(self, context):
+        context.write('Policy template: {0}'.format(context.style.node(self._template.name)))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            context.write('Type: {0}'.format(context.style.type(self._template.type.name)))
+            self._topology.dump(self._template.properties, context, 'Properties')
+            if self._template.node_templates:
+                context.write('Target node templates: {0}'.format(', '.join(
+                    (str(context.style.node(v.name)) for v in self._template.node_templates))))
+            if self._template.group_templates:
+                context.write('Target group templates: {0}'.format(', '.join(
+                    (str(context.style.node(v.name)) for v in self._template.group_templates))))
     def coerce(self):
         pass
 
@@ -257,10 +359,13 @@ class PolicyTemplate(common._TemplateEntity):
         self._topology.validate(self._template.properties)
 
 
-class SubstitutionTemplate(common._TemplateEntity):
+class SubstitutionTemplate(common._TemplateHandler):
 
-    def dump(self):
-        pass
+    def dump(self, context):
+        context.write('Substitution template:')
+        with context.style.indent:
+            context.write('Node type: {0}'.format(context.style.type(self._template.node_type.name)))
+            self._topology.dump(self._template.mappings, context, 'Mappings')
 
     def coerce(self):
         pass
@@ -273,10 +378,19 @@ class SubstitutionTemplate(common._TemplateEntity):
         self._topology.validate(self._template.mappings)
 
 
-class SubstitutionMapping(common._TemplateEntity):
+class SubstitutionTemplateMapping(common._TemplateHandler):
 
-    def dump(self):
-        pass
+    def dump(self, context):
+        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
+        context.write('{0} -> {1}.{2}'.format(
+            context.style.node(self._topology.name),
+            context.style.node(node_template.name),
+            context.style.node(self._topology.capability_template.name
+                               if self._topology.capability_template
+                               else self._topology.requirement_template.name)))
 
     def coerce(self):
         pass
@@ -325,9 +439,18 @@ class SubstitutionMapping(common._TemplateEntity):
             #                           level=validation.Issue.BETWEEN_TYPES)
 
 
-class RelationshipTemplate(common._TemplateEntity):
-    def dump(self):
-        pass
+class RelationshipTemplate(common._TemplateHandler):
+    def dump(self, context):
+        if self._template.type is not None:
+            context.write('Relationship type: {0}'.format(context.style.type(self._template.type.name)))
+        else:
+            context.write('Relationship template: {0}'.format(
+                context.style.node(self._template.name)))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            self._topology.dump(self._template.properties, context, 'Properties')
+            self._topology.dump(self._template.interface_templates, context, 'Interface Templates')
 
     def coerce(self):
         pass
@@ -348,10 +471,33 @@ class RelationshipTemplate(common._TemplateEntity):
                        self._template.interface_templates)
 
 
-class OperationTemplate(common._TemplateEntity):
-
-    def dump(self):
-        pass
+class OperationTemplate(common._TemplateHandler):
+
+    def dump(self, context):
+        context.write(context.style.node(self._template.name))
+        if self._template.description:
+            context.write(context.style.meta(self._template.description))
+        with context.style.indent:
+            if self._template.implementation is not None:
+                context.write('Implementation: {0}'.format(
+                    context.style.literal(self._template.implementation)))
+            if self._template.dependencies:
+                context.write('Dependencies: {0}'.format(
+                    ', '.join((str(context.style.literal(v)) for v in self._template.dependencies))))
+            self._topology.dump(self._template.inputs, context, 'Inputs')
+            if self._template.executor is not None:
+                context.write('Executor: {0}'.format(context.style.literal(self._template.executor)))
+            if self._template.max_attempts is not None:
+                context.write('Max attempts: {0}'.format(context.style.literal(self._template.max_attempts)))
+            if self._template.retry_interval is not None:
+                context.write('Retry interval: {0}'.format(
+                    context.style.literal(self._template.retry_interval)))
+            if self._template.plugin_specification is not None:
+                context.write('Plugin specification: {0}'.format(
+                    context.style.literal(self._template.plugin_specification.name)))
+            self._topology.dump(self._template.configurations, context, 'Configuration')
+            if self._template.function is not None:
+                context.write('Function: {0}'.format(context.style.literal(self._template.function)))
 
     def coerce(self):
         pass