Puppet printing undef string instead of nil

Viewed 25

I'm currently in the process of updating some legacy Puppet files to a newer version of puppet and am running into the following problem:

The hieradata for one of our server has variables that can be left undefined and still work when we generate an env.yml for our RoR application from an erb file.

Previously, this worked correctly with our env.yml generating those values like:

read_only_mode:

With our update to Puppet v5, the values now generate as:

read_only_mode: undef

In the erb template:

read_only_mode: <%= @data['read_only_mode'] %>

I'm currently trying to write a test in the Puppet file that generates the env.yml with the thought that the following logic should work:

for ($key, value in $hieradata) {
  if ($hierdata[$key] == undef) {
    $hieradata[$key] = '' // Empty string
  }
}

As implemented:

$envdata.each |String $key, String $value| {
  if $envdata[$key] == undef {
    $envdata[$key] = ''
  }
}

However, this isn't working and the undef string is still being printed.

Does anyone have ideas as to a solution to this issue?

2 Answers

This

read_only_mode: undef

is going to be interpreted as a string and it's going to be passed into the template as a string, remembering that an ERB is Embedded RuBy we have to pass in something that Ruby is going to recognise as a null value and you can do this as follows.

read_only_mode: null
read_only_mode: Null
read_only_mode: NULL
read_only_mode: ~
read_only_mode:

So I'm not sure why you needed to change from

read_only_mode:

to

read_only_mode: undef

unless there is something else going on in your code, I couldn't really tell as your problem statement seemed to be missing a few bits. Once I had my values set in hiera as above I'd then wrap the template code in an if;

# erb template
<% if @data != nil -%>
value2 <%= @data %>
<% end -%>

The class

# pp class file
$data = lookup(read_only_mode)

  file { '/tmp/test':
    ensure  => file,
    content => template('module2/test.erb'),
  }

If you're refactoring your template for Puppet 5 you might want to go the whole hogg and convert it to epp which is much easier to use and you get access to regular Puppet language functions such as each.

We ended up changing the Hash values using the following code:

$data_tuples = $data.keys.map |$key, $value| {
  if type($value) == Undef {
    [$key, '']
  } else {
    [$key, $value]
  }
}

$data_filtered = Hash($data_tuples)
Related