scope for templates that is called from a class that includes the class that calls the template.

957 views
Skip to first unread message

Daniel Jung

unread,
Jul 2, 2013, 12:07:51 AM7/2/13
to puppet...@googlegroups.com
hi,

trying to understand the scope for templates -- after reading http://docs.puppetlabs.com/guides/templating.html, got a question about the following,


class test::foo {

     file {
       <snip>


       content => template ("footemplate.erb"),
     }

}


class test::foo2 {
      $var = blah,
      class {'test::foo' :
      }
}

so the question is if footemplate.erb uses variable $var as @var, is there a need for me to pass it as a argument within class {'test::foo': var => $var ?   My interpretation of templating.html is that all the variables that are in scope of the called class would be passed/available in the template hence i would need to pass it as an argument.

Can anyone shed some lights on this?

Thanks

Wolf Noble

unread,
Jul 2, 2013, 2:04:14 AM7/2/13
to puppet...@googlegroups.com
Hi Daniel,


What I've done in the past is:

Foo.erb
<% foobar = scope.lookupvar('::somefact')
  othervar   = scope.lookupvar('class::variable')
lastvar = scope.lookupvar('myclass::myvar')
fqdn = scope.lookupvar('::fqdn')
-%>
#this file generated automatically by puppet for <%=fqdn%>
#manual changes will be reverted


<% if foobar -%>
Foo = <%=foobar%>
<%end-%>
... <stuff and things here > ...


Not sure if there's a better way, but I'm inter the impression (correct me if I'm wrong here?) that scope.lookupvar will do the right thing as often as is possible.

HtH!

Wolf
MobileMail
--
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 post to this group, send email to puppet...@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-users.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Daniel Jung

unread,
Jul 2, 2013, 2:17:11 AM7/2/13
to puppet...@googlegroups.com
Hi Wolf,

I guess you can use the lookupvar and specifically call the variable from the class where it belongs to. That would be one method of doing it and probably works with Puppet 3.* as well.
I just want to get my head around the scope while calling templates from a manifest.

Thanks for the reply though!

jcbollinger

unread,
Jul 8, 2013, 3:25:07 PM7/8/13
to puppet...@googlegroups.com


On Monday, July 1, 2013 9:17:11 PM UTC-5, Daniel Jung wrote:
Hi Wolf,

I guess you can use the lookupvar and specifically call the variable from the class where it belongs to. That would be one method of doing it and probably works with Puppet 3.* as well.
I just want to get my head around the scope while calling templates from a manifest.


Yes, you can use scope.lookupvar() to retrieve the value of a variable of any class by passing the qualified name of the variable.  And that is what your templates should do if they need to query variables from outside the local scope where they are evaluated.  This works in Puppet 2 and Puppet 3.

Before dynamic scoping was removed (i.e. before Puppet 3), a template might, under some circumstances, be able to directly access variables belonging to other scopes, such as in your example code.  That was never a good idea, however, for exactly the same reasons that dynamic scoping in general was not a good idea.

The potential gotcha with looking up variables of other classes is that you must make sure that a declaration of the host class has already been parsed before the template is evaluated.  That's not necessarily a big problem, but you can expect to be bitten in the behind if you forget to do it.


John


John

David Portabella

unread,
Nov 27, 2013, 1:40:41 PM11/27/13
to puppet...@googlegroups.com
about dynamic lookup from an included puppet file:
puppet 2.7 warns about it, and puppet 3.2 stops working, as expected.

however,
about dynamic lookup from a template called on an included puppet file:
both puppet 2.7 and puppet 3.2 it works, without even a warning. (see in red the below example)

Why is that?
And so, does this mean that dynamic lookup is bad from a puppet file, but not from a template file?


See below a specific example:

test.pp
class c1 {
  $var = 'hello'
  notify {"var from c1: $var": }
  include c2
}

class c2 {
  notify {"var from c2: $var": }
  
  file { '/tmp/file.txt':
    content => template('file.txt.erb'),
  }
}

class { c1: }

file.txt.erb
var from file.txt.erb: <%= @var %>


----
running with puppet 2.7.19:
$ puppet apply --templatedir templates/ test.pp
warning: Dynamic lookup of $var at /vagrant/t1/test.pp:8 is deprecated. For more information, see http://docs.puppetlabs.com/guides/scope_and_puppet.html. To see the change in behavior, use the --debug flag.
notice: var from c1: hello
notice: /Stage[main]/C1/Notify[var from c1: hello]/message: defined 'message' as 'var from c1: hello'
notice: /Stage[main]/C2/File[/tmp/file.txt]/ensure: defined content as '{md5}ea0d73f3957b0893f63e03cb9d8c9d98'
notice: var from c2: hello
notice: /Stage[main]/C2/Notify[var from c2: hello]/message: defined 'message' as 'var from c2: hello'
notice: Finished catalog run in 0.05 seconds

$ cat /tmp/file.txt 
var from file.txt.erb: hello


running with puppet 3.3.2:
$ puppet apply --templatedir templates/ test.pp
Notice: Compiled catalog for mac4c.local in environment production in 0.16 seconds
Notice: var from c1: hello
Notice: /Stage[main]/C1/Notify[var from c1: hello]/message: defined 'message' as 'var from c1: hello'
Notice: var from c2: 
Notice: /Stage[main]/C2/Notify[var from c2: ]/message: defined 'message' as 'var from c2: '
Notice: /Stage[main]/C2/File[/tmp/file.txt]/ensure: defined content as '{md5}ea0d73f3957b0893f63e03cb9d8c9d98'

$ cat /tmp/file.txt 
var from file.txt.erb: hello

David Portabella

unread,
Nov 27, 2013, 1:50:53 PM11/27/13
to puppet...@googlegroups.com
All of the variables visible in the current scope are available as Ruby instance variables
but out of the scope variables should be accessed by scope.lookupvar.

so, why does the previous example works? why does file.txt get the 'hello' value?
var from file.txt.erb: hello

Felix Frank

unread,
Nov 28, 2013, 8:32:00 AM11/28/13
to puppet...@googlegroups.com
Hi,

that's interesting indeed. You may have stumbled upon a bug. You could
try and search http://projects.puppetlabs.com/issues/ for similar
reports. If there is none, feel free to open a new bug and supply your
example code.

If time allows, I'll look into it over the weekend.

Cheers,
Felix

On 11/27/2013 02:50 PM, David Portabella wrote:
> and according to http://docs.puppetlabs.com/guides/templating.html
> /All of the variables visible in the current scope are available as Ruby
> instance variables/
> but out of the scope variables should be accessed by scope.lookupvar.
>
> so, why does the previous example works? why does file.txt get the
> 'hello' value?
> *var from file.txt.erb: hello*

David Portabella

unread,
Nov 28, 2013, 8:55:35 AM11/28/13
to puppet...@googlegroups.com
you are right, someone filled a bug ticket one month ago:
http://projects.puppetlabs.com/issues/22800

Felix Frank

unread,
Dec 1, 2013, 10:07:26 AM12/1/13
to puppet...@googlegroups.com
Hi,

I've taken a look into the issue and it would appear that your root
problem is wrong template syntax. The below is not strictly valid:

On 11/27/2013 02:40 PM, David Portabella wrote:
> file.txt.erb
> var from file.txt.erb: <%= @var %>

What works as expected:

> var from file.txt.erb: <%= var %>

or

> var from file.txt.erb: <%= scope.lookupvar("var") %>

The fact that the member variable syntax @var works at all is confusing,
and may be considered a bug. Will update Redmine accordingly. I believe
that the support for such templates should be deprecated if possible.

Thanks,
Felix

David Portabella

unread,
Dec 1, 2013, 10:21:34 AM12/1/13
to puppet...@googlegroups.com
Hi,


> What works as expected:
>> var from file.txt.erb: <%= var %>

using var instead of @var produces this warning on puppet 3:
Warning: Variable access via 'var' is deprecated. Use '@var' instead. 

and it's explained here: http://docs.puppetlabs.com/guides/templating.html
Historically, all of the variables visible in the current scope were also available as Ruby methods — that is, fqdn, memoryfree, operatingsystem, etc., without the prepended @ sign. This style of reference caused problems when variable names collided with Ruby method names; its use emits deprecation warnings as of Puppet 3 and will be removed in Puppet 4. Please update any existing code which uses it and start any new code out with the @fqdn instance-variable syntax.


> var from file.txt.erb: <%= scope.lookupvar("var") %>
yes, we need to use this function if we need to access someothermodule::var, or a hiera variable.
however, using this function for all variables in the current scope would be ugly.


> The fact that the member variable syntax @var works at all is confusing,
> and may be considered a bug.

yes. that's what we are saying.

dynamic lookup in templates should show a warning in puppet 2.7, and stop working on puppet 3.


Regards,
David

Felix Frank

unread,
Dec 1, 2013, 10:24:30 AM12/1/13
to puppet...@googlegroups.com
Absolutely! Sorry I had missed the deprecation warning earlier.

Full agreement on all points.

Debugging away... :-)

On 12/01/2013 11:21 AM, David Portabella wrote:
> Hi,
>
>> What works as expected:
>>> var from file.txt.erb: <%= var %>
>
> using var instead of @var produces this warning on puppet 3:
> /Warning: Variable access via 'var' is deprecated. Use '@var' instead. /
> /Historically, all of the variables visible in the current scope were
> also available as Ruby methods � that is, fqdn, memoryfree,
> operatingsystem, etc., without the prepended @ sign. This style of
> reference caused problems when variable names collided with Ruby method
> names; its use emits deprecation warnings as of Puppet 3 and will be
> removed in Puppet 4. Please update any existing code which uses it and
> start any new code out with the @fqdn instance-variable syntax.
> /

Felix Frank

unread,
Dec 3, 2013, 1:14:35 PM12/3/13
to puppet...@googlegroups.com
In case someone's keeping score - a patch has been posted to github and
linked from the Redmine issue. I've had feedback from Puppetlabs' Andy
Parker and it looks like this cannot be fixed before Puppet 4.x.

In the meantime, please be wary of relying on scoping effects concerning
variables used in templates with 3.x, because those will suddenly stop
working. For technical reasons, there can be no deprecation warning for
this scenario.
Reply all
Reply to author
Forward
0 new messages