2

I have about 200 more or less identical Linux VMs. There is a class for all common configuration:

class my_packages {

    class { "::ntp":
        servers     => [ "de.pool.ntp.org" ],
    }
    ....
}

which I include in each node in site.pp.

Now I want to run my own local time server, which is trivial using the puppetlabs/ntp package. I simply have to replace the servers entry in my_packages with the ip address of the new time server VM, and that VM now has the same ntp class entry that was previously used in my_packages.

node 'mytime' {

#    include my_packages

    class { '::ntp':
        servers => [
            'de.pool.ntp.org',
            'ptbtime1.ptb.de',
            'ptbtime2.ptb.de',
            'ptbtime3.ptb.de',
        ],
    }
    ...
}

However since the class "::ntp" entry is now defined in the node, I can't include my_packages in the node entry for my new time server VM, because I get a "Duplicate declaration" error in this case.

A similar problem has occurred when using a local name server. Each VM has an /etc/resolv.conf file pointing to the local name server, so there is a file resource for that in my_packages. But the local name server itself must have a different /etc/resolv.conf file - it can't point to itself until its installation is complete, which is not the case during installation.

What is the best practise for using a common set of resources, but allowing for occasional exceptions?

1
  • use hiera, you can have independ parameter for every node
    – c4f4t0r
    May 20, 2015 at 6:21

1 Answer 1

2

If you are using Puppet 3 or later, the best way to approach this would be to use hiera to perform automatic parameter lookup. In brief, it allows you to declare classes using the include syntax rather than the resource-style syntax, meaning that you can have multiple declarations for the class. Note that you cannot mix include and resource-style declarations for a class.

Normally if you were to use the include syntax to declare a class it would fail if it had any required parameters. When you use automatic parameter lookup, puppet will attempt to look up the values for parameters through hiera.

Hiera is so named because it will attempt to look up values through a hierarchy of data sources. You can specify this hierarchy in hiera.yaml, and it can match against various facts (hostname, custom facts, etc) or check hard-coded files.

Here's a brief example that might work in your case:

Class definition:

class my_packages {
  include ::ntp
  ...
}

mytime.yaml:

----
ntp::servers:
  - 'de.pool.ntp.org'
  - 'ptbtime1.ptb.de'
  - 'ptbtime2.ptb.de'
  - 'ptbtime3.ptb.de'

common.yaml:

---
ntp::servers: ['de.pool.ntp.org']

hiera.yaml:

...
:hierarchy:
 - "${::fqdn}"
 - common
...

In this case hiera would try to look up a value for the servers param in the ntp class, using the key ntp::servers. It would first look for that key in any yaml files that match the hostname, and after that it would look in common.yaml.

In most cases it would use the key in common.yaml, but in the case of the mytime node it would find a value higher up in the hierarchy and stop looking there.

Here's a link to a complete example, which incidentally covers the ntp module.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .