Bug #4717

Global variables are no longer fully global

Added by Dan Urist almost 3 years ago. Updated 6 months ago.

Status:Needs More InformationStart date:09/03/2010
Priority:NormalDue date:
Assignee:-% Done:

0%

Category:-
Target version:-
Affected Puppet version:0.25.5 Branch:
Keywords:global variable scope

Description

A variable defined in global scope is no longer visible in the global scope of other files. For example:

site.pp:

$testvar = “TESTVAR_VALUE”

nodes.pp:

notice(“testvar outside node is: ${testvar}”) node ‘test.puppet.cms.ucar.edu’ {

 notice("testvar inside node is: ${testvar}")

}

The log contains this after a puppet run:

puppet-master[3758]: (Scope(Class[main])) testvar outside node is: puppet-master[3758]: (Scope(Node[test.puppet.cms.ucar.edu])) testvar inside node is: TESTVAR_VALUE

If I move the node definition to site.pp, so it is in the same file as the variable definition, then it’s defined both outside and inside the node definition.

I haven’t tested whether the same issue exists for classes as well as nodes. Note that the behavior in 0.25 was that the global variable was defined everywhere, which is what I would expect (and is the behavior some of my modules rely on).

History

#1 Updated by Cody Herriges almost 3 years ago

  • Status changed from Unreviewed to Needs More Information

I was unable to reproduce this in 2.6.1rc4. Could you please try out the latest release candidate?

#2 Updated by Nan Liu almost 3 years ago

Simple test case:

site.pp:

testvar = 'foo'
import a.pp
include a
import b.pp

a.pp:

class a {
  notice ("In class a, testvar is ${testvar})
}

b.pp:

notice ("In b, testvar is ${testvar})

Result

In class a, testvar is foo
In b, testvar is

This is the same behavior on 0.25.5 and 2.6.1rc4, so please provide more information.

#3 Updated by Dan Urist almost 3 years ago

I’ve tried it with 2.6.1rc4, and I’m still seeing the same behavior. I don’t have time to reinstall 0.25, but this definitely worked in 0.25; I used global variables to set some paths in at least half a dozen manifests. Again, here is my trivial test case:

/tmp/puppettest/site.pp:

$testvar = 'TESTVAR_VALUE'
import '/tmp/puppettest/nodes.pp'

/tmp/puppettest/nodes.pp:

notice("testvar outside node is: ${testvar}")
node 'test.puppet.cms.ucar.edu' {
    notice("testvar inside node is: ${testvar}")
}

And here are the log entries:

Sep 13 08:53:08 npuppet puppet-master[23724]: (Scope(Class[main])) testvar outside node is: 
Sep 13 08:53:08 npuppet puppet-master[23724]: (Scope(Node[test.puppet.cms.ucar.edu])) testvar inside node is: TESTVAR_VALUE

To reiterate, the variable WAS set in 0.25.

FWIW, I don’t need this functionality anymore (I’m now using sub-modules, which are a cleaner solution for what I was trying to do), but I think it’s a significant change that should at least be documented, and frankly it doesn’t make sense to me that the global variable isn’t set in global scope!

#4 Updated by Dan Urist almost 3 years ago

One more thing… if I add a notice statement to site.pp like this:

$testvar = 'TESTVAR_VALUE'
notice("testvar in site.pp is: ${testvar}")
import '/tmp/puppettest/nodes.pp'

Then I get the following log entries:

Sep 13 09:05:51 npuppet puppet-master[23720]: (Scope(Class[main])) testvar outside node is: 
Sep 13 09:05:51 npuppet puppet-master[23720]: (Scope(Class[main])) testvar in site.pp is: TESTVAR_VALUE
Sep 13 09:05:51 npuppet puppet-master[23720]: (Scope(Node[test.puppet.cms.ucar.edu])) testvar inside node is: TESTVAR_VALUE

So clearly the variable is set in Scope(Class[main]) in site.pp, but not in Scope(Class[main]) in nodes.pp? I’m guessing for some reason nodes.pp is evaluated first? This certainly seems buggy to me…

#5 Updated by Paul Berry over 2 years ago

  • Target version set to 2.7.x
  • Affected Puppet version changed from 2.6.1rc2 to 0.25.5

I spent some time debugging this and it is not what it seemed at first.

The problem is a combination of these factors:

  • variable definitions, function calls, and resources that appear at toplevel are treated as though they appear in an invisible class called :main.

  • the contents of identically-named classes that appear in separate files are merged together in the order that those files finished processing.

  • variable evaluation is order-dependent—a variable’s value can’t be seen until it is set.

Considering Dan’s example from comments 3 and 4: Puppet interprets it as declaring three entities: a node and two :main classes:

class :main from /tmp/puppettest/site.pp:

$testvar = 'TESTVAR_VALUE'
notice("testvar in site.pp is: ${testvar}")

class :main from /tmp/puppettest/nodes.pp:

notice("testvar outside node is: ${testvar}")

node test.puppet.cms.ucar.edu from /tmp/puppettest/nodes.pp:

notice("testvar inside node is: ${testvar}")

Since Puppet pauses the parsing of site.pp to import nodes.pp, it finishes parsing nodes.pp first, so when the :main classes are merged together, nodes.pp’s :main goes first:

Merged :main class:

notice("testvar inside node is: ${testvar}")
$testvar = 'TESTVAR_VALUE'
notice("testvar in site.pp is: ${testvar}")

So the problem is not that global variables aren’t global. It’s that variables are only accessible after they’re declared, and the order relationships between different files is counterintuitive.

Note: AFAIK all these problems also exist in 0.25.x.

#6 Updated by Andrew Parker 6 months ago

  • Target version deleted (2.7.x)

Also available in: Atom PDF