2

Is it possible to declare variable in node and than propage it way down to the erb template?

Example:

node basenode {
  $myvar = "bar" # default
  include myclass
}

node mynode extends basenode {
  $myvar = "foo"
}

class myclass {
  file { "/root/myfile":
    content => template("myclass/mytemplate.erb")
    ensure  => present,
  }
}

Source of mytemplate.erb:

myvar has value: <%= myvar %>

I know that my example might be complicated. But I'm trying to propagate file on (almost) all my nodes and I want its content to be altered depending on the node which requests the file. The $myvar = "bar" statement should be default when node does not override its value.

Is there a solution to my problem? I'm using puppet 0.24.5

Edit: The problem here is probably variable inheritance order. This $myvar variable won't have foo value in mynode node. The solution here would be to include myclass directly in mynode. But I really don't want to do that. Is there an option to override class variable value after the class has been included?

3

3 Answers 3

3

Puppet node inheritance is not the same as inheritance in most other programming languages . Included classes are evaluated immediatelly when the child is evaluated. And the parent node is evaluated after that. Therefore my example will never work. If you want to know recommended solution for this, read puppet - common misconceptions. I did it this way and it works.

Although I have to admit that I'm pretty disappointed right now, because complex puppet syntax might be confusing for starters.

2
  • I'm being pedantic, but declarative languages like Puppet's DSL are programming languages every bit as much as procedural programming languages (which is what you probably meant) like C. Jan 20, 2011 at 3:42
  • Changed my statement so it does not sound like I don't accept puppet language as programming langugage :) Jan 22, 2011 at 12:14
2

Other answers have already pointed out the scoping problem. What you probably want to do is use the base node only for variable definitions, and separate out the actual logic (including your base class definitions) into a separate class that's included by all of your nodes. This preserves the scoping the way that you want, and only adds a single extra line to all of your node definitions.

node basenode {
  $myvar = "bar" # default
}

node mynode extends basenode {
  $myvar = "foo"
  include baseclass
}

class baseclass {
  include myclass
}

class myclass {
  file { "/root/myfile":
    content => template("myclass/mytemplate.erb"),
    ensure  => present
  }
}
0
0

Instead of declaring the default value within basenode, I would declare the default within the template itself. Since ERB is largely based on ruby, you can get away with some fairly extensive logic. Here is an example from the template I use for managing the snort config file.

var DNS_SERVERS <% if has_variable?("dns_servers") then %>[<%= dns_servers.flatten.join(',') %>]<% else %>$HOME_NET<% end %>

In this case I am using an array that, if it exists, gets turned into a comma separated list for inclusion. Otherwise the default $HOME_NET gets used. If we simplify it to your example we could use:

myvar has value <% if has_variable?("myvar") %><% then %><%= myvar %><% else %>bar<% end %>

Again, if the variable myvar has been set then that will be expanded, otherwise the string "bar" will be printed. This way the variable myvar can be set, or not, in your node definitions with impunity.

2
  • This is probably a good point. But my main point here is that I'm not able to use variables from node definition within erb templates (which are used inside classes). Is there something bad in my example? My real situation is much more complicated than this, but I think that main point is here. Are there any limits of the scope in which the variable will be propagated? Jan 10, 2011 at 20:42
  • Ah, sorry, I didn't realize you meant that you tried it, but didn't work. I am doing exactly what you are, and it works fine. It could be that your ERB syntax is wonky, or you've run into an ordering problem. I'll have to do some more testing.
    – Scott Pack
    Jan 10, 2011 at 21:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .