user2800773
user2800773

Reputation: 67

Construct mutable string from hash iteration

I'm stuck on the following puppet code from days, can you please give me an hand?

In hiera I have the following structure:

my_list::servers:
  server1.subnet.env.com:
    id: 0
  server2.subnet.env.com:
    id: 1
  server3.subnet.env.com:
    id: 2
  server4.subnet.env.com:
    id: 3

Where the various server1..n (n=>2) are the FQDN of the servers in the specific environment. The ID is always in order, but starting from 0.

I need to create a string that contains a comma separated list of string as broker-${id}-check, where id is different from the FQDN of the server where I'm running puppet, so for example if I'm running the script on server2.subnet.env.com the string should be broker-0-check,broker-2-check,broker-3-check. If I'm running on server1.subnet.env.com it will be broker-1-check,broker-2-check,broker-3-check, etc..

My last tentative is:

$servers_list = hiera('my_list::servers',  {"${::fqdn}" => {'id' => 0 } })
$list_broker=''
$servers_list.each |$key, $value| {
  if $key != $::fqdn {
    $list_broker="${list_broker},broker-${value['id']}-check"
  }
}
notify {"******* ${list_broker}": }

but list_broker is still empty and then I will have to fix the leading comma.

Is there a better way to do that?

I'm using Puppet 4.

Upvotes: 2

Views: 833

Answers (1)

Alex Harvey
Alex Harvey

Reputation: 15472

The problem is that although Puppet has an iteration feature, it doesn't allow the reassignment of variables (ref).

For this reason, Puppet has a lot of functional programming features that allow you to solve problems like this without needing to reassign variables.

This works (Puppet < 5.5), where join() comes from stdlib:

$list_broker = join(
  $servers_list
    .filter |$key, $value| { $key != $::fqdn }
    .map    |$key, $value| { "broker-${value['id']}-check" },
  ','
)

Or in Puppet >= 5.5 (as suggested in comments), where the join command is built-in, the join can be chained too:

$list_broker = $servers_list
  .filter |$key, $value| { $key != $::fqdn }
  .map    |$key, $value| { "broker-${value['id']}-check" }
  .join(',')

If you'd prefer it in more steps:

$filtered = $servers_list.filter |$key, $value| { $key != $::fqdn } 
$mapped = $filtered.map |$key, $value| { "broker-${value['id']}-check" }
$list_broker = join($mapped, ',')

Explanation:

  • The filter function selects elements from an Array or Hash on the basis of some criteria.
  • The map function performs a transformation on all elements of an Array or Hash and returns an Array of transformed data.
  • The join function (which prior to Puppet 5.5 comes from stdlib) joins an array of strings.

Upvotes: 3

Related Questions