variablesif-statementpuppetfacter

In Puppet, how to use defined node variables in an if clause


In a puppet class how should I test if a variable has been set in a node? I use a VM name (like server1) and a domain name (like example.org) where users can reach the page. "example.org" won't be conveyed via a fact, so I need to pass it via a class parameter. I came up with this way to define the variable in a node block and use it in my test class for my settings.

node "VM1" {
  class { 'test':
    domainname => "example.org",
  }

[...]

class test ($domainname) {
  ini_setting {
    'set_property':
      ensure  => present,
      path    => '/tmp/test.ini',
      section => 'main',
      setting => 'url',
      value   => "https://$domainname";
  }

[...]

But now I want to add a condition that if $domainname isn't set then the $hostname fact should be used in its place.

ini_setting {
    'set_property':
    ensure  => present,
    path    => '/tmp/test.ini',
    section => 'main',
    setting => 'url',
    if $domainname !~ $hostname {
      value   => "https://$domainname";
    } else {
      value   => "https://$hostname";
    }

But now I get an error like this every time:

Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Syntax error at 'domainname'

What should I do instead?


Solution

  • The error message is explaining to you that if statements cannot appear inside resource declarations. There is, however, a different conditional form, called a "selector" that can appear inside resource declarations. It is Puppet's analog of the ternary ?: operator that appears in several languages.

    Stylistically, though, it is usually better form to keep resource declarations as simple as possible. To that end, you should probably set a variable, conditionally, outside the resource declaration, and then use its value inside. Using your own conditional, that might look like this:

      if $domainname !~ $hostname {
        $url_value = "https://$domainname";
      } else {
        $url_value = "https://$hostname";
      }
    
      ini_setting {
        'set_property':
          ensure  => present,
          path    => '/tmp/test.ini',
          section => 'main',
          setting => 'url',
          value   => $url_value;
      }
    

    Additionally, however, I note that your particular condition, repeated above, is highly suspect. In recent Puppet (version 4 and above), you should be using Puppet data types to both declare your class parameters and check them. In particular, if it is permissible to declare class test without providing a $domainname parameter, then you would declare that class like so:

    # Using the Puppet v4+ type system
    class test(
      Optional[String] $domainname = undef
    ) {
      # ...
    

    , and would test whether a value was provided for $domainname like so:

      if $domainname =~ Undef {
        # ...
      }
    

    You cannot use the type system in earlier Puppet, but there you can rely on undefined variables to expand to nothing when you interpolate them:

    # Using the Puppet v3- behavior
    class test(
      $domainname = undef
    ) {
      # ...
    
      if "$domainname" == "" {
        # ...
      }
    
      # ...
    }