Skip to content
Advertisement

Changing class variable in node declaration in Puppet

I am trying to create a “template” for all my servers. I have 2 configurations. An NTP client (which is taken care of in the baseclass class. I want to create an override specific for the NTP servers by declaring something specific in the node declaration. Something like “baseclass::ntp:restrict => true,”. Or alternatively, how would I change one of the already declared variable from baseclass::ntp?

Does anyone have any ideas host to do this?

This is what I have so far:

templates.pp

class baseclass {
    include defaultusers
    include sudoers
    include issue

    class { ntp:
            ensure => running,
            servers => ['ntpserver1.host.com',
                        'ntpserver2.host.com',],
            autoupdate => false,
    }
}

nodes.pp

node default {
    include baseclass
}

node "ntpserver1.host.com" inherits default {
    <some code here to declare new variable in baseclass::ntp>
    <some code here to change existing variable, such as "ensure">
}

Advertisement

Answer

You have run smack into the problem with parameterized classes: they don’t support overrides. They should, but due to various problems with the order in which things are initialized in Puppet, you can’t override parameters to classes. Once you set them, you’re done. This is different from defines, where overriding parameters works as you expect. There’s an open bug about this that a bunch of us have voted up and are watching, but there appears to be little progress.

Given that, my recommendation would be to recast your parameterized ntp class as a define instead, because a define will work exactly as you want. Change the class to something like:

define ntp($servers, $autoupdate = false, $ensure = 'running') {
  # ... put code from class here ...
}

and then change baseclass to:

ntp { $fqdn:
  servers => [ 'ntpserver1.host.com',
               'ntpserver2.host.com',],
}

You will have to change the class structure to add a new class, since you can’t inherit from a class in a node, so change your node to:

node "ntpserver1.host.com" inherits default {
  include hosts::ntpserver1
}

or however you want to name your per-host configuration classes. Then, in that class, you can do exactly what you expect to be able to do:

class hosts::ntpserver1 inherits baseclass {
  Ntp["$fqdn"] { ensure => 'stopped' }
}

I know this seems like a huge runaround, particularly if you’re used to doing a bunch of stuff inside nodes (which don’t participate in the class inheritance tree). But without being able to override parameters to classes, there doesn’t seem to be a good alternative. (We manage 500+ nodes and about 100 completely separate service definitions, with hundreds of modules and a huge amount of variety between hosts, including per-host overrides, using this method and it works extremely well.)

TL,DR summary: You can’t override class parameters. Once you’ve passed a parameter to a class in Puppet, you’re done. You can override define parameters. Therefore, anything you want to override is better written as a define than a class. However, remember that override hierarchies means that you have to put the core of your node definition in a class, since only classes can inherit from and override another class. Therefore, if you use overrides heavily, get into the habit of having your node definitions be trivial (just including a class that does all the work) so that your classes can inherit from base classes and override the parameters to defines.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement