2

I'd like to write a puppet manifest to install and configure an application on target servers.

Parts of this manifest shall be re-usable. Thus I used define for defining my re-usable functionality. Doing so, I've always the problem that there are parts of the definition which are not re-usable.

A simple example is a bunch of configuration files to be created. These file must be placed in the same directory. This directory must be created only once.

Example:

nodes.pp

node 'myNode.in.a.domain' { mymodule::addconfig {'configfile1.xml': param => 'somevalue', } mymodule::addconfig {'configfile2.xml': param => 'someothervalue', } } 

mymodule.pp

define mymodule::addconfig ($param) { $config_dir = "/the/directory/" #ensure that directory exits: file { $config_dir: ensure => directory, } #create the configuration file: file { $name: path => "${config_dir}/${name}" content => template('a_template.erb'), require => File[$config_dir], } } 

This example will fail, because now the resource file {$config_dir: is defined twice.

As far as I understood, it is required to extract these parts into a class. Then it looks like this:

nodes.pp

node 'myNode.in.a.domain' { class { 'mymodule::createConfigurationDirectory': } mymodule::addconfig {'configfile1.xml': param => 'somevalue', require => Class ['mymodule::createConfigurationDirectory'], } mymodule::addconfig {'configfile2.xml': param => 'someothervalue', require => Class ['mymodule::createConfigurationDirectory'], } } 

But this makes my interface hard use. Every user of my module has to know, that there is a class which is additionally required. For this simple use case the additional class might be acceptable. But with growing module complexity (lots of definitions) I'm a bit afraid of confusing the modules user.

So I'd like to know is there a better way to handle this dependencies. Ideally, classes like createConfigurationDirectory are hidden from the user of the modules api.

Or are there some other "Best Practices"/Patterns handling such dependencies?

2 Answers 2

2

Break all the functionality into separate files within the module, each file containing one class or defined type. Use resource ordering to manage resources in the correct order.

In your node definition:

class {'mymodule': conffile => 'file_name', } 

In your module manifest directory:

init.pp:

# This class does basic setup, # and optionally allows you to define a config file class mymodule ( $conffile = undef ) { include mymodule::confdir if $conffile { mymodule::conffile { $conffile: } } } 

params.pp:

# This class defines variables class mymodule::params { $confdir = '/path/to/dir' } 

confdir.pp:

# This class creates a conf dir class mymodule::confdir { include mymodule::params file { $mymodule::params::confdir: ensure = directory, } } 

conffile.pp:

# This define creates a config file define mymodule::conffile($file=$title) { include mymodule::params file { "${mymodule::params::confdir}/${file}": ensure => present, require => Class['mymodule::confdir'], } } 
1

Is best if you can take out the config directory from the define. This is an example

class def($config_dir) { file { $config_dir: ensure => directory } } define def::template($file_location) { file { $file_location: path => "${def::config_dir}/${file_location}", content => 'hi', require => Class['def'], } } if $fqdn == 'my_host' { class { 'def': config_dir => '/tmp/d1' } def::template { 'f1.txt': file_location => "f1.txt" } def::template { 'f2.txt': file_location => "f2.txt" } } ls /tmp/d1/ f1.txt f2.txt 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.