Puppet class inheritance confusion

Puppet does not support this kind of configuration, but the restriction can be easily bypassed. The reason is in two basic puppet "rules":

  1. A class can be included only once (subsequent include -statements will do nothing)
  2. The order of execution is not strictly defined and can even be random

er-dev and er-bce-dev both include the class er. But the class cannot be included two times, so er class is executed only with the default $venvname = "er", or with overridden $venvname = "er-dev", but not both.

The solution: Change er class to a definition (see "Definitions" from Puppet Language Tutorial (http://docs.puppetlabs.com/guides/language_tutorial.html)):

modules/django-env/manifests/er.pp

# Create new er resource definition
define django-env::er($vpath="/home/django/virtualenvs", $vname="er") {
    file { "$vpath/$vname" :
        ensure => directory
    }
    # etc ...
}

We do not need the $venvname and $venvpath variables, they are specified as default values in the definition. The name django-env::er adds the definition into django-env namespace and allows automatic import (see below).

Import and Include

The difference between import and include statemens is:

  • import works with files, and does not execute classes
  • include executes classes
  • files must be imported before the classes can be included

Note: there is a very strong exception to the last rule: Puppet module lookup. include statement does automatic imports in many situations. Here are some of them:

  • include foo tries to import the file module_dir/foo/manifests/init.pp
  • include foo::bar imports module_dir/foo/manifests/bar.pp

With these automatic imports and the resource definition, you can define multiple virtual environments very easily. Change node 'centos-dev':

node 'centos-dev' imports default {
    include django-env
    # The er resource with default values:
    django-env::er { 'er-bce': }
    # Another er resource with different environment name:
    django-env::er { 'er-bce-dev': vname => 'bce-dev'}
}

And you can remove basically all import statements considering django-env module.

Happy Puppeting!

Tags:

Puppet