Bug #4717
Global variables are no longer fully global
| Status: | Needs More Information | Start date: | 09/03/2010 | |
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | - | % Done: | 0% |
|
| Category: | - | |||
| Target version: | 2.7.x | |||
| Affected Puppet version: | 0.25.5 | Branch: | ||
| Keywords: | global variable scope | |||
| Votes: | 0 |
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
Updated by Cody Herriges over 1 year 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?
Updated by Nan Liu over 1 year 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.
Updated by Dan Urist over 1 year 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!
Updated by Dan Urist over 1 year 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…
Updated by Paul Berry over 1 year 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.