[Puppet Users] Resolving variables when using templates

89 views
Skip to first unread message

Bernd Adamowicz

unread,
Apr 26, 2010, 7:24:22 AM4/26/10
to puppet...@googlegroups.com
Hi all,

given these two classes inside the file '/etc/puppet/modules/templates_eval/manifests/init.pp':

53 class templates_eval::providevars {
54
55 $hibernate_connection_dialect="org.hibernate.dialect.Oracle10gDialect"
56 }
57
58 class templates_eval::testvars {
59
60 include templates_eval::providevars
61
62 file {
63 "/tmp/tmplteval.properties":
64 ensure => "present",
65 mode => 644,
66 content => template("templates_eval/global.properties.erb"),
67 }
68 }

The file '/etc/puppet/manifests/site.pp' includes class 'templates_eval::testvars':

13 node "myhostname.net" {
...
17 include templates_eval::testvars
18 }

This is the content of template '/etc/puppet/modules/templates_eval/templates/global.properties.erb':

12
13 domain.suffix=<%= fqdn %>
14
15 hibernate.connection.dialect=<%= hibernate_connection_dialect %>

However, when running Puppet on a Puppet node, obviously the variable '$hibernate_connection_dialect' cannot be resolved:

[root@myhostname puppet]# puppetd -v -d --test
...
err: Could not retrieve catalog from remote server: Error 400 on SERVER: Failed to parse template templates_eval/global.properties.erb: Could not find value for 'hibernate_connection_dialect' at /etc/puppet/modules/templates_eval/manifests/init.pp:64 on node myhostname.net
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
[root@myhostname puppet]#

Obviously the 'include templates_eval::providevars' inside class 'templates_eval::testvars' has no impact. I tried several other approaches (importing manifests, etc.), too. But none of them worked. So the basic question is: How can I have a set of variables defined in scope X (where X might be a manifest, a class, or a define) and include it into scope Y (where Y will most likely be a class or maybe a node).

Thanks in advance for any help!
Bernd

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.

Dan Bode

unread,
Apr 26, 2010, 9:54:41 AM4/26/10
to puppet...@googlegroups.com
On Mon, Apr 26, 2010 at 4:24 AM, Bernd Adamowicz <Bernd.A...@esailors.de> wrote:
Hi all,

given these two classes inside the file '/etc/puppet/modules/templates_eval/manifests/init.pp':

    53 class templates_eval::providevars {
    54
    55     $hibernate_connection_dialect="org.hibernate.dialect.Oracle10gDialect"
    56 }
    57

It should work if you just explicitly assign the variable in the scope where you execute the template function.
 
    58 class templates_eval::testvars {
    59
    60     include templates_eval::providevars
    61
      
        61.5 hibernate_connection_dialect=templates_eval::providevars::hibernate_connection_dialect
 

Mike Pountney

unread,
Apr 26, 2010, 10:07:15 AM4/26/10
to puppet...@googlegroups.com
On 26 Apr 2010, at 12:24, Bernd Adamowicz wrote:

Hi all,

given these two classes inside the file '/etc/puppet/modules/templates_eval/manifests/init.pp':

    53 class templates_eval::providevars {
    54
    55     $hibernate_connection_dialect="org.hibernate.dialect.Oracle10gDialect"
    56 }
    57
    58 class templates_eval::testvars {
    59
    60     include templates_eval::providevars
    61
    62     file {
    63         "/tmp/tmplteval.properties":
    64             ensure => "present",
    65             mode => 644,
    66             content => template("templates_eval/global.properties.erb"),
    67     }
    68 }

This will not work as you expect, as the include templates_eval:;providevars creates a lower scope.

You would need either have the $hiber... variable defined in the templates_eval::testvars class directly, or inherit the providevars class like:

class templates_eval::testvars inherits templates_eval::providevars {
  ...
}


Obviously the 'include templates_eval::providevars' inside class 'templates_eval::testvars' has no impact. I tried several other approaches (importing manifests, etc.), too. But none of them worked. So the basic question is: How can I have a set of variables defined in scope X (where X might be a manifest, a class, or a define) and include it into scope Y (where Y will most likely be a class or maybe a node).


Importing a file works at the parsing stage rather than the compilation stage (where variables are interpreted), so this would also not work as you expect. I like to thing of the parser/import phase as puppet merging all the *.pp files into one big PP file, which is then compiled based on the node in question (and the facts provided by that node). I'm pretty sure something more clever actually happens, but it's not a bad place to start for thinking about how the scope works - import is more like #include in a C preprocessor.





Bernd Adamowicz

unread,
Apr 26, 2010, 11:51:32 AM4/26/10
to puppet...@googlegroups.com
OK. Actually it worked when I added:

$hibernate_connection_dialect=$templates_eval::providevars::hibernate_connection_dialect

This solves the base problem but at the same time creates another one: I do not have to include variables from only one class but depending one some environment settings from different classes. Maybe I've just picked a completely wrong approach, so I'd just like to show what I mean with some (none-Puppet) pseudo code:

If (environment == "envX")
Then
$hibernate_connection_dialect=$envX::hibernate_connection_dialect
Else if (environment == "envY")
Then
$hibernate_connection_dialect=$envY::hibernate_connection_dialect
End

But actually I don't want is to have code like this - the redefinition of every variable depending on the environment. I was thinking about some kind of associative array which would allow to iterate over values 'envX', 'envY', etc. But again this would lead to a redefinition and I think Puppet does not have the feature of assoc. array. (Right?)

Inheritance, as mentioned by Mike, is also not possible since I would then need some kind of 'dynamic' inheritance like this (pseudo code again):

If (environment == "envX")
Then
class env inhertit $envX::class {

}
End

Seems this is not possible in Puppet, too. So maybe there's a completely different approach in Puppet for accomplishing this problem (?)

Thanks Bernd


>> It should work if you just explicitly assign the variable in the scope where you execute the template function.

>    58 class templates_eval::testvars {
>    59
>    60     include templates_eval::providevars
>    61
>      
>>        61.5 hibernate_connection_dialect=templates_eval::providevars::hibernate_connection_dialect

>    62     file {
>    63         "/tmp/tmplteval.properties":
>    64             ensure => "present",
>    65             mode => 644,
>    66             content => template("templates_eval/global.properties.erb"),
>    67     }
>    68 }


Dan Bode

unread,
Apr 26, 2010, 1:50:49 PM4/26/10
to puppet...@googlegroups.com
On Mon, Apr 26, 2010 at 8:51 AM, Bernd Adamowicz <Bernd.A...@esailors.de> wrote:
OK. Actually it worked when I added:

$hibernate_connection_dialect=$templates_eval::providevars::hibernate_connection_dialect

This solves the base problem but at the same time creates another one: I do not have to include variables from only one class but depending one some environment settings from different classes. Maybe I've just picked a completely wrong approach, so I'd just like to show what I mean with some (none-Puppet) pseudo code:

If (environment == "envX")
Then
       $hibernate_connection_dialect=$envX::hibernate_connection_dialect
Else if (environment == "envY")
Then
       $hibernate_connection_dialect=$envY::hibernate_connection_dialect
End


this type of conditional logic looks like its better suited to be set in an external node classifier. This allows you to specify an external script that classfies nodes (sets top scope params and classes) based on external information about that node. This is best implemented using some kind of inheritance structure that supports overriding of parameters. Variables set at top scope will be available by their non fully qualified names in all scopes (unless they are overridden by a local scope).  The puppet dashboard is an implementation of the inheritence driven parameterization of nodes (called groups).

I actually like the approach of having a MODULE::params class for parmeterizations that can be handled internally. But for things that need to be specified by some external categorization of machines, its best to use an external node classifier to support a more data driven parameterization of classes.

 
But actually I don't want is to have code like this - the redefinition of every variable depending on the environment. I was thinking about some kind of associative array which would allow to iterate over values 'envX', 'envY', etc. But again this would lead to a redefinition and I think Puppet does not have the feature of assoc. array. (Right?)

not yet, this will be supported in Rwolf, but I dont think that would be the best way to solve you problem.

Bernd Adamowicz

unread,
Apr 27, 2010, 4:33:37 AM4/27/10
to puppet...@googlegroups.com
Dan, I think what you suggested seems to be the right way. I had a deeper look at external node classifiers as well as on working with different environments inside Puppet. I have not been aware of these concepts but will start now to create a proof of concept for our systems.

Thanks all for helping!

Bernd



> this type of conditional logic looks like its better suited to be set in an external node classifier. This allows you to specify an external script > > that classfies nodes (sets top scope params and classes) based on external information about that node. This is best implemented using some kind of > > inheritance structure that supports overriding of parameters. Variables set at top scope will be available by their non fully qualified names in all > > scopes (unless they are overridden by a local scope).  The puppet dashboard is an implementation of the inheritence driven parameterization of nodes > > (called groups).
>
> I actually like the approach of having a MODULE::params class for parmeterizations that can be handled internally. But for things that need to be > > > specified by some external categorization of machines, its best to use an external node classifier to support a more data driven parameterization of > > classes.
Reply all
Reply to author
Forward
0 new messages