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()
},