Site module with Puppet Enterprise

598 views
Skip to first unread message

Rufus McDufus

unread,
May 16, 2012, 9:11:35 AM5/16/12
to Puppet Users
In the Puppet Enterprise docs below, they mention using a 'Site
Module'

http://docs.puppetlabs.com/pe/2.5/quick_writing.html#using-a-site-module

However I can't find any examples of people using such a method. I'm
interested in this because I'd prefer to use generic modules (e.g from
puppet forge etc) as 'libraries' without modifying the modules, but
call the modules elsewhere & perform the site-specific logic outside
of the generic modules.
How would a site module differ from a manifest and what would be the
advantage of a site module instead of doing it in manifests?

Thanks,

Jeff McCune

unread,
May 16, 2012, 1:29:32 PM5/16/12
to puppet...@googlegroups.com
Site modules are usually private to an organization which is why there
might not be many published examples of them.

Writing a module that support the "site module" pattern is a bit
trickier but here's the most common use case I've found. A module
that is generally re-usable should use it's own template for the
general case but allow the module user to pass in a different template
from a different module. This "different module" is the site module.

So, how do I change the behavior of a module without modifying the
module itself? If it allows you to pass in the data you need then you
can store that data in a site module and pass it using the template
function:

# motd module:
class motd($motd_content='UNSET') {
$motd_content_real = $motd_content ? {
UNSET => template("motd/motd.erb"),
default => $motd_content,
}

# Manage the message of the day
file { "/etc/motd":
content => $motd_content_real,
}
}

Now there are two ways to use this module. If I don't want to change
the behavior I can just use it "as is"

node default { include motd }

However, if I want to change the message of the day I can pass in the
full contents from my own module rather than modifying the motd module
itself:

node default {
class { motd: motd_content => template('site/motd.erb') }
}

This will cause the motd module to use a template from my site module
rather than using it's own erb template. The key difference is
template("motd/motd.erb") inside the motd module versus
template("site/motd.erb") "outside" the motd module.

Hope this helps,
-Jeff

Rufus McDufus

unread,
May 16, 2012, 2:00:08 PM5/16/12
to puppet...@googlegroups.com
Ah, thanks Jeff - that's a nifty way of doing it! I've been setting templatedir which appears to override the templatedir of each module which seems to work, but I can't figure a way of doing this with files - I tried an entry [modules] in fileserver.conf as a test and this seems to just be ignored in favour of the local module files/ dir.  Also use of templatedir appears to be discouraged in the docs nowadays, probably with good reason.

So the 'site module' in your case would be a method of overriding generic module settings on a per-module basis. So the idea would be that your single site module provides practically all the puppet logic for your site, right? And effectively use the generic modules as libraries (as seems to make sense to me) ?

With Puppet Enterprise I'm looking to avoid individual node definitions altogether (and have super-simple manifests come to that, perhaps just a site.pp)  and define the nodes in PE, but use the 'groups' feature of PE to map classes to classes in the site module.  I *think* this is a similar thing to what they're getting at in the PE docs but it's all very briefly mentioned so I may be getting the wrong end of the stick completely.

Rufus McDufus

unread,
May 17, 2012, 2:30:29 PM5/17/12
to puppet...@googlegroups.com
I had a bit of a play with this today and couldn't get anything working... (I am something of as puppet newbie as you can tell so go easy on me!).
In Jeff's example above:

---

# motd module:
class motd($motd_content='UNSET') {
  $motd_content_real = $motd_content ? {
    UNSET => template("motd/motd.erb"),
    default => $motd_content,
  }

  # Manage the message of the day
  file { "/etc/motd":
    content => $motd_content_real,
  }
}
---

Are you actually trying to overload the real motd module? Would this not require a module path set with the site module in front of the real one?
I figured not as I'm not so sure this is intended to work in puppet (?), so I was trying things with inheritance along the lines of:

# site::motd module:
class site::motd($motd_content='UNSET') inherits motd {
  $motd_content_real = $motd_content ? {
    UNSET => template("motd/motd.erb"),
    default => $motd_content,
  }

  ...
}

But couldn't get it to work. Have I got the wrong end of the stick completely?

Jeff McCune

unread,
May 17, 2012, 5:01:24 PM5/17/12
to puppet...@googlegroups.com
On Thu, May 17, 2012 at 11:30 AM, Rufus McDufus <r...@bamalam.com> wrote:
> I had a bit of a play with this today and couldn't get anything working...

Hrm, I'm sure we'll be able to sort it out.

> Are you actually trying to overload the real motd module?

No, the module named site and the module named motd can exist in the
same directory along the modulepath.

I also notice you have "inherits" in there, which isn't necessary and
can complicate things. This pattern is really just providing a string
to the motd class in the motd module. That's really it. If the
string isn't provided (It's unset), then the motd module itself will
use it's own string from it's own template.

So for example your manifests might be laid out like this:

/etc/puppet/modules/site/manifests/init.pp # <= class site { ... }
/etc/puppet/modules/motd/manifests/init.pp # <= class
motd($motd_content) { ... }
/etc/puppet/modules/motd/manifests/motd.pp # <= class site::motd { ... }

In that third manifest for class site::motd you could do this:

class site::motd {
# Declare the motd class from the motd module, but tell it to use
# a template from the site module, not it's own template.
class { motd: motd_content => template("site/motd.erb") }
}

You could just as easily pass a string directly rather than use the
template function:

class site::motd {
class { motd: motd_content => "Hello World!\n" }
}

Hope this helps.

I think avoiding "inherits" will help clear up the issue you're facing.

-Jeff

Rufus McDufus

unread,
May 18, 2012, 2:32:38 AM5/18/12
to puppet...@googlegroups.com
Ah, thanks Jeff! I think my problem is that I'm assuming the target module won't necessarily allow you to pass an alternate source content path, so I'm basically trying to write a wrapper module which provides an extra parameter of that content source.

Nathan Valentine

unread,
Mar 6, 2013, 11:21:24 PM3/6/13
to puppet...@googlegroups.com
Paleoposting FTW!

I've been doing enough work with site modules as of late that I decided to make a git repo with a basic site module set up for following Craig Dunn's "Roles and Profiles" pattern. Or at least something very similar (no inheritance):


Nothing groundbreaking but an easy 'git clone' as opposed to putting together the scaffolding every time. 
Reply all
Reply to author
Forward
0 new messages