6

I have a Puppet class that sets up a number of services and configuration files. In most cases, there is a default server that can be used, but it is also possible to configure explicit per-service servers. I find myself doing this all the time:

class myclass (
  $default_server    = 'server.example.com',
  $server_for_thing1 = undef,
  $server_for_thing2 = undef,
  $server_for_thing3 = undef
) {

  if $server_for_thing1 {
    $real_server_for_thing1 = $server_for_thing1
  } else {
    $real_server_for_thing1 = $default_server
  }

  # ...and so forth...
}

As the number of possible services grows large, this syntax becomes unwieldy. Is there a better way of doing this? I really want something along the lines of:

$server_for_thing1 = $server_for_thing1 || $default_server

...but variables cannot be re-assigned in Puppet. Are there better ways of doing this?

2 Answers 2

2

While not exactly what you are asking for, have you considered using an External Node Classifier to set and override the default value for specific servers? I believe the ECN is the "puppet way" of doing things in a situation like yours.

EDIT: (based on the first comment)

Second idea: you can use a custom function to at least make the multi-line repeated logic a bit more readable. Something like this, which returns the first "defined" argument, though with puppet, I am never sure what "defined" is (in this case, "undef" gets passed as an empty string to the function, which is still good enough).

module Puppet::Parser::Functions
    newfunction(:get_default, :type => :rvalue) do |args|
        value = nil
        args.each { |x|
            if ! x.nil? and x.length > 0
                value = x
                break
            end
        }
        return value
    end
end

You can then call it as many times as you want:

$real_server_for_thing1 = get_default($server_for_thing1, $default_server)
$real_server_for_thing2 = get_default($server_for_thing2, $default_server)
$real_server_for_thing3 = get_default($server_for_thing3, $default_server)
3
  • An external node classifier isn't going to be the right solution here, because this is not typically something that varies from node to node. It is more typically something in a generally reusable module that would vary from site to site.
    – larsks
    May 27, 2012 at 0:55
  • Well, you could also set up a custom puppet function to shorten the three lines into one. Though I don't think that's what you are aiming for either. $real_server_for_thing1 = get_default($server_for_thing1, $default_server). get_default should return the second parameter if the first one is undefined (or empty, or null, because puppet's interpretation of "undef" is not always consistent).
    – chutz
    May 27, 2012 at 7:01
  • I was actually thinking about doing exactly that (creating a custom function). And yeah, I've run into puppet's inconsistent treatment of undef.
    – larsks
    May 27, 2012 at 11:40
0

Since I posted this question oh those many years ago, Puppet's stdlib module has learned about the pick function, which will return the first non-undef or non-empty value from a list of values. So one can write:

$real_server_for_thing1 = pick($server_for_thing1, $default_server)

There is also a pick_default function empty values are valid (you only want to ignore undef).

You must log in to answer this question.

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