Interpolate Parameters after merging from storage

Following the merging of parameters, the storage base class now invokes
interpolate() on the Parameters instance (via the Entity) instance.

Signed-off-by: martin f. krafft <madduck@madduck.net>
diff --git a/README b/README
index 3bea51b..5aa0aca 100644
--- a/README
+++ b/README
@@ -237,6 +237,22 @@
 are extended, rather than replaced. There is currently no way to remove or
 overwrite an existing value.
 
+Finally, parameters may reference each other, including deep references, e.g.:
+
+  parameters:
+    location: Munich, Germany
+    motd:
+      header: This node sits in ${location}
+    for_demonstration: ${motd:header}
+    dict_reference: ${motd}
+
+After merging and interpolation, which happens automatically inside the
+storage modules, the 'for_demonstration' parameter will have a value of "This
+node sits in Munich, Germany".
+
+Types are preserved if the value contains nothing but a reference. Hence, the
+value of 'dict_reference' will actually be a dictionary.
+
 Version control
 ~~~~~~~~~~~~~~~
 I recommend you maintain your reclass inventory database in Git, right from
@@ -299,4 +315,4 @@
 Adapters may implement their own lookup logic, of course, so make sure to read
 their READMEs.
 
- -- martin f. krafft <madduck@madduck.net>  Thu, 04 Jul 2013 22:20:20 +0200
+ -- martin f. krafft <madduck@madduck.net>  Wed, 07 Aug 2013 16:21:04 +0200
diff --git a/README.Ansible b/README.Ansible
index 6fa013a..2b146f4 100644
--- a/README.Ansible
+++ b/README.Ansible
@@ -165,16 +165,39 @@
 
   - Parameters corresponding to a node become host_vars for that host.
 
-It is possible to include Jinja2-style variables like you would in Ansible,
-in parameter values. This is especially powerful in combination with the
-recursive merging, e.g.
+Ansible allows you to include Jinja2-style variables in parameter values:
 
   parameters:
     motd:
       greeting: Welcome to {{ ansible_fqdn }}!
       closing: This system is part of {{ realm }}
+    dict_reference: {{ motd }}
+
+However, in resolving this, Ansible casts everything to a string, so in this
+example, 'dict_reference' would be the string-representation of the dictionary
+under the 'motd' key.¹ To get at facts (such as 'ansible_fqdn'), you still
+have to use this approach, but for pure parameter references, I strongly
+suggest to use reclass interpolation instead, as it supports deep references,
+does not clobber type information, and is more efficient anyway:
+
+  parameters:
+    motd:
+      greeting: Welcome to {{ ansible_fqdn }}!
+      closing: This system is part of ${realm}
+    dict_reference: ${motd}
 
 Now you just need to specify realm somewhere. The reference can reside in
-a parent class, while the variable is defined e.g. in the node.
+a parent class, while the variable is defined e.g. in the node definition.
 
- -- martin f. krafft <madduck@madduck.net>  Thu, 04 Jul 2013 22:20:20 +0200
+And as expected, 'dict_reference' now points to a dictionary, not
+a string-representation thereof.
+
+Footnotes
+~~~~~~~~~
+¹) I pointed this out to Michael Dehaan, Ansible's chief developer, but he
+   denied this behaviour. When I tried to provide further insights, I found
+   myself banned from the mailing list, apparently because I dared to point
+   out flaws. If you care, you may look at
+   https://github.com/madduck/reclass/issues/6 for more information.
+
+ -- martin f. krafft <madduck@madduck.net>  Wed, 07 Aug 2013 16:21:04 +0200
diff --git a/README.Salt b/README.Salt
index 1b5abf1..4fe8e0f 100644
--- a/README.Salt
+++ b/README.Salt
@@ -141,22 +141,4 @@
 Unfortunately, this does not work yet, please stay tuned, and let me know
 if you figure out a way. Salt issue #5787 is also of relevance.
 
-It will also be possible to include Jinja2-style variables in parameter
-values. This is especially powerful in combination with the recursive merging,
-e.g.
-
-  parameters:
-    motd:
-      greeting: Welcome to {{ grains.fqdn }}!
-      closing: This system is part of {{ realm }}
-
-Now you just need to specify realm somewhere. The reference can reside in
-a parent class, while the variable is defined e.g. in the node.
-
-This is also not yet working. The main reason is that the expansion cannot
-happen at the YAML-file level, because that would cast most types to strings.
-Instead, the interpolation needs to happen at the data structure level inside
-reclass, or maybe at the adapter level, reusing the templating of Salt. This
-will require some more thought, but it's on the horizon…
-
- -- martin f. krafft <madduck@madduck.net>  Thu, 04 Jul 2013 22:20:20 +0200
+ -- martin f. krafft <madduck@madduck.net>  Wed, 07 Aug 2013 16:21:04 +0200
diff --git a/TODO b/TODO
index bb4845c..d90e9ac 100644
--- a/TODO
+++ b/TODO
@@ -5,7 +5,6 @@
 - Write unittest for everything but datatypes, the existing nosetests are
   pretty crap, incl. yaml_fs, outputters, CLI and adapters.
 - Configurable file extension (.yaml/.yml, or support both)
-- Variable interpolation
 - Verbosity options, debugging
 - Add a configuration option to allow a set of classes to be slapped onto
   nodes by default (#5).
diff --git a/reclass/datatypes/entity.py b/reclass/datatypes/entity.py
index f2ed10d..2606e9e 100644
--- a/reclass/datatypes/entity.py
+++ b/reclass/datatypes/entity.py
@@ -55,6 +55,9 @@
         self._parameters.merge(other._parameters)
         self._name = other.name
 
+    def interpolate(self):
+        self._parameters.interpolate()
+
     def __eq__(self, other):
         return self._applications == other._applications \
                 and self._classes == other._classes \
diff --git a/reclass/storage/__init__.py b/reclass/storage/__init__.py
index be9440a..ca49ac0 100644
--- a/reclass/storage/__init__.py
+++ b/reclass/storage/__init__.py
@@ -26,6 +26,7 @@
 
     def nodeinfo(self, node):
         entity, uri = self._read_nodeinfo(node, self.nodes_uri, {})
+        entity.interpolate()
         return {'__reclass__' : {'node': node, 'node_uri': uri,
                                  'timestamp': _get_timestamp()
                                 },