variable scoping and templates

166 views
Skip to first unread message

drs

unread,
Apr 30, 2014, 2:31:03 PM4/30/14
to puppet...@googlegroups.com
I am new to puppet and am trying to figure out variable scoping. I have a test module that I am using for this and it looks like this:

manifiests/init.pp:

class test {
  include test::params

  file { 'testfile' :
    path   => "/tmp/testfile",
    content => template("test/testfile.erb"),
  }
}

manifests/params.pp:

class test::params {
  $p1 = hiera('param1')
  $p2 = hiera('param2')
}

templates/testfile.erb:

this is the first parameter:  <%= @p1 %>
this is the second parameter:  <%= @p2 %>

global.yaml:

---
  param1: "this is the first one"
  param2: "this is the second one"

Based on what I am seeing in the ProPuppet book (the discussion of the puppet module in Chap. 2, pp69-70), this should work. However, the values are not being inserted in the template. In order to get them in, I have to add something like this to the init.pp manifest:

  $a = $::test::params::p1
  $b = $::test::params::p2

and reference @a and @b in the template.

So the question is: Am I missing something or is there an error in the ProPuppet example?

If I need to add the $a = …. and $b=… lines to the init.pp, what, if any is the advantage to having a params.pp manifest. I could just put the hiera() calls in init.pp.

thanks for your patience.

Matthew Burgess

unread,
Apr 30, 2014, 3:43:07 PM4/30/14
to puppet...@googlegroups.com

We just ran into this too recently. From my investigation it looks like the syntax you quote above is for referencing Hiera values in Puppet manifests. For erb templates we ended up using scope.function_hiera () although I wonder now whether a scope.lookupvar () call would a) be better and b) be better as it's more generic?

Matt

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/abcf9bb6-b3a2-483d-8655-3b6a6eed8196%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alex Scoble

unread,
Apr 30, 2014, 3:55:29 PM4/30/14
to puppet...@googlegroups.com
As far as I know, the only reason you would use params.pp is if you have sane defaults you want to pass to variables. When you do, you use:

class test inherits test::params {
}

for your init.pp. You don't use an include statement as far as I know.

However, because you aren't defining sane defaults, you don't need the params.pp.

Instead just make your test/manifests/init.pp look like:

class test {

  $p1 = hiera('param1')
  $p2 = hiera('param2')

  file { 'testfile' :
    path   => "/tmp/testfile",
    content => template("test/testfile.erb"),
  }

}

Hope that helps.

--Alex

Alex Scoble

unread,
Apr 30, 2014, 4:02:14 PM4/30/14
to puppet...@googlegroups.com
By the way, if you are using Puppet 3.0.0 or newer you shouldn't need the hiera() function at all.

Just call out your variables like so:

class test (
  $a,
  $b,
) {

  file { 'testfile' :
    path   => "/tmp/testfile",
    content => template("test/testfile.erb"),
  }

}

In your hiera yaml it would look like (assuming you've set up your site.pp to allow for calling classes within hiera):

---
classes:
  - test
test::a:        'foo'
test::b:        'bar'

Hope this helps,

Alex

jcbollinger

unread,
Apr 30, 2014, 5:55:03 PM4/30/14
to puppet...@googlegroups.com


On Wednesday, April 30, 2014 1:31:03 PM UTC-5, drs wrote:
I am new to puppet and am trying to figure out variable scoping. I have a test module that I am using for this and it looks like this:

manifiests/init.pp:

class test {
  include test::params

  file { 'testfile' :
    path   => "/tmp/testfile",
    content => template("test/testfile.erb"),
  }
}

manifests/params.pp:

class test::params {
  $p1 = hiera('param1')
  $p2 = hiera('param2')
}

templates/testfile.erb:

this is the first parameter:  <%= @p1 %>
this is the second parameter:  <%= @p2 %>

global.yaml:

---
  param1: "this is the first one"
  param2: "this is the second one"

Based on what I am seeing in the ProPuppet book (the discussion of the puppet module in Chap. 2, pp69-70), this should work. However, the values are not being inserted in the template. In order to get them in, I have to add something like this to the init.pp manifest:

  $a = $::test::params::p1
  $b = $::test::params::p2

and reference @a and @b in the template.

So the question is: Am I missing something or is there an error in the ProPuppet example?


I am not looking at Pro Puppet, but probably you are missing something: templates can refer directly to only global variables and the local variables of the class where the template is evaluated.  When one class declares another, such as via 'include', the other class's variables do not become local to the including class (see also below).  For a template to reference variables of some other class than the one currently evaluating it, it must use scope.lookupvar('qualified::name::of::desired::variable').

Note 1: Although declaring another class does not make its variables local, inheriting from another class does effectively do so.  But use class inheritance for that purpose.

Note 2: Do not misunderstand the 'include' function.  It "includes" the named class in the target node's catalog.  It does not include or interpolate the class or any part of it into the class where the 'include' statement appears.

 

If I need to add the $a = …. and $b=… lines to the init.pp, what, if any is the advantage to having a params.pp manifest. I could just put the hiera() calls in init.pp.



The common understanding of the purpose of ::params class is to serve as a data repository, typically of hard-coded, module-specific data.  Such data most often serve as default values for class variables, including class parameters, and sometimes serve as general well-known values of the module's domain.  (To safely use a ::params class for parameter defaults, the parameterized class must inherit from the ::params class.) There has also been a growing tendency to put default data computations into such a class, though there is some doubt about the wisdom of that approach.

And you can indeed just put hiera() calls into one of your module's other classes instead, or allow puppet to make such calls automatically to select class parameter values.  For data ultimately coming from hiera, that's precisely what I would do.


John

jcbollinger

unread,
Apr 30, 2014, 5:57:16 PM4/30/14
to puppet...@googlegroups.com


On Wednesday, April 30, 2014 4:55:03 PM UTC-5, jcbollinger wrote:

Note 1: Although declaring another class does not make its variables local, inheriting from another class does effectively do so.  But use class inheritance for that purpose.


Critical correction: But DO NOT use class inheritance for that purpose.


John

jcbollinger

unread,
Apr 30, 2014, 6:04:33 PM4/30/14
to puppet...@googlegroups.com


On Wednesday, April 30, 2014 2:43:07 PM UTC-5, Matthew Burgess wrote:

We just ran into this too recently. From my investigation it looks like the syntax you quote above is for referencing Hiera values in Puppet manifests.


Nope, absolutely not.  Templates have visibility into hiera only via the hiera() Puppet function and its kin.

 

For erb templates we ended up using scope.function_hiera () although I wonder now whether a scope.lookupvar () call would a) be better and b) be better as it's more generic?


scope.lookupvar() doesn't do the same thing that scope.function_hiera() does.  The former looks up a qualified or unqualified Puppet variable (e.g. a class variable).  The latter invokes Puppet's hiera() function to query hiera for data associated with the specified key.  Under some circumstances they will return the same value for the same input; under those circumstances, scope.lookupvar() is better because it is cheaper.  If you cannot rely on the template being evaluated under those circumstances, however, then you should choose whichever function does the job you actually want.


John

jcbollinger

unread,
Apr 30, 2014, 6:12:21 PM4/30/14
to puppet...@googlegroups.com


On Wednesday, April 30, 2014 3:02:14 PM UTC-5, Alex Scoble wrote:
By the way, if you are using Puppet 3.0.0 or newer you shouldn't need the hiera() function at all.


Not so fast.  Automatic data binding does remove any need for writing explicit hiera() calls (provided you are willing to structure your hiera keys in a suitable way), but the implication that you in fact shouldn't use explicit hiera() calls is not nearly so well established.  Also, if you want the special hierarchy-transcending behavior of hiera_hash() or hiera_array() (which, admittedly, are not hiera() itself) then you can only get it via the appropriate function calls.


John

Alex Scoble

unread,
Apr 30, 2014, 10:36:06 PM4/30/14
to puppet...@googlegroups.com
Heh, John,

I said shouldn't need, not shouldn't use.

Thanks,

Alex


--
You received this message because you are subscribed to a topic in the Google Groups "Puppet Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/puppet-users/jZGsQ97oljs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/caf5ac4a-23c2-4ad1-9b94-17d9bb30c0e4%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages