Puppet: System Administration Automated

Support

Common Misconceptions


Language

Node Inheritance and Variable Scope

It is generally assumed that the following will result in the /tmp/puppet-test.variable file containing the string 'my_node':

class test_class {
    file { "/tmp/puppet-test.variable":
       content => "$testname",
       ensure => present,
    }
}

node base_node {
    include test_class
}

node my_node inherits base_node {
    $testname = 'my_node'
}

Contrary to expectations, /tmp/puppet-test.variable is created with no contents. This is because the inherited test_class remains in the scope of base_node, where $testname is undefined.

Node inheritance is currently only really useful for inheriting static or self-contained classes, and is as a result of quite limited value. It is planned that Kinial, the new node classification tool, will remove this limitation.

A workaround is to define classes for your node types - essentially include classes rather than inheriting them. For example:

class test_class {
    file { "/tmp/puppet-test.variable":
       content => "$testname",
       ensure => present,
    }
}

class base_node_class {
    include test_class
}

node my_node {
    $testname = 'my_node'
    include base_node_class
}

/tmp/puppet-test.variable will now contain 'my_node' as desired.

Class Inheritance and Variable Scope

The following would also not work as generally expected:

class base_class {
    $myvar = 'bob'
    file {"/tmp/testvar":
         content => "$myvar",
         ensure => present,
    }
}

class child_class inherits base_class {
    $myvar = 'fred'
}

The /tmp/testvar file would be created with the content 'bob', as this is the value of $myvar where the type is defined.

A workaround would be to 'include' the base_class, rather than inheriting it, and also to strip the $myvar out of the included class itself (otherwise it will cause a variable scope conflict - $myvar would be set twice in the same child_class scope):

$myvar = 'bob'

class base_class {
    file {"/tmp/testvar":
         content => "$myvar",
         ensure => present,
    }
}

class child_class {
    $myvar = 'fred'
    include base_class
}

Whilst not directly solving the problem also useful are qualified variables that allow you to refer to and assign variables from other classes. Qualified variables might provoke alternate methods of solving this issue. You can use qualified methods like:

class foo {
    $foovariable = "foobar"
}

class bar {
    $barvariable = $foo::foovariable
}

In this example the value of the of the $barvariable variable in the bar class will be set to foobar the value of the $foovariable variable which was set in the foo class.