Search code examples
puppet

Puppet: manifest: optional parameter within class declaration


I have a puppet manifest to apply, however, depending on the target, the puppet module defined class does not support certain parameters, whereas it will on other target.

e.g. on targetA init.pp: 
   class myclass (
       $foo = undef,
       $bar = undef)
On targetB init.pp:
      class myclass(
           $foo = undef)

Is there a method to variably change the parameters in the declaration without modifying the module already installed on target?

i.e. on targetA, (running puppet version 5.x):

                file {‘extra.conf’:
                       ensure => present}
                 ->
                 class {‘::myclass’:
                       foo => ‘myfoo’
                      }

while on target B, (running puppet version 4.x):

                file {‘extra.conf’:
                       ensure => present|
                 -> 
                 class {‘::myclass’:
                      foo => ‘myfoo’,
                      bar => ‘mybar’
                  }

However, if declare the class in this way on target A, an error would occur due to the extra ‘bar’ parameter. Is there a way to keep the modules (both named 'myclass') while making the manifest portable?


Solution

  • Is there a way to keep the modules (both named 'myclass') while making the manifest portable?

    Yes.

    Option 1 - automatic data binding

    Put the class parameters in hiera data, use include-like class declarations instead of resource-like class declarations, and rely on automatic data binding. You can put the same data on each node, as automatic data binding looks only for values for classes' defined parameters -- it will ignore keys, no matter the form, that don't correspond to class parameters.

    Option 2 - conditional statements

    Puppet DSL has a fairly rich suite of conditional statements that you can use to select a declaration appropriate to the actual target node. The real trick here is what condition to use to distinguish, because there is no easy way to directly test whether the class supports a specific parameter. You could certainly distinguish by $hostname or $certname, but if there are more than two machines then you might want something more generic, such as $server_facts['serverversion'].

    For example,

      case $server_facts['serverversion'] {
        # Puppet version 4
        /^4[.]/: { class { '::myclass': foo => 'myfoo' } }
    
        # Anything else
        default: { class { '::myclass': foo => 'myfoo', bar => 'mybar' } }
      }
    
      file { 'extra.conf':
        ensure => 'present',
        before => Class['::myclass'],
      }