Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I've read the documentation on scope, but I'm still having trouble working this out. I've got two environments that are very similar - so I've got:

modules/django-env/manifests/init.pp

class django-env {
    package { "python26":
        ensure => installed
    }
    # etc ...
}
import "er.pp"

modules/django-env/manifests/er.pp

$venvname = "er"
$venvpath = "/home/django/virtualenvs"

class er {
    file { "$venvpath/$venvname" :
        ensure => directory
    }
    # etc ...
}
class er-dev {
    include er
}
class er-bce-dev {
    $venvname = "er-bce"
    include er
}

manifests/modules.pp

import "django-env"

manifests/nodes.pp

node default {
    # etc ...
}
node 'centos-dev' imports default {
    include django-env
    include er-bce-dev
    include er-dev
}

The result here is that the "inheritance" works - but only the first "er-" item under the 'centos-dev' node is acted upon, I either get er-bce-dev or er-dev, but not both. There must be some basic thing I'm misunderstanding here.

Is it the difference between import and include ? (not sure I understand that)

share|improve this question
    
IIRC the FAQ of puppet contained an item that stated that node inheritance has problems and shouldn't be used. But now the FAQ has moved and lost this piece of information along the way. –  ptman Jan 16 '11 at 11:24

1 Answer 1

up vote 11 down vote accepted

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!

share|improve this answer
    
Thanks for this! –  EMiller Jan 19 '11 at 5:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.