Ask Your Question

Cannot set a flag inside a .each iteration and use it outside of it

asked 2017-05-09 13:48:23 -0500

besleg gravatar image

Hi. This might be a dumb question, but i`m going to ask it anyway :)

So.. i have a hashes array . I need to iterate trough all the hashes in the array, and if a certain key in any hash matches a desired value, i need to set a flag e.g "$flag = true". Outside of the loop, i need to execute some tasks if the $flag is NOT true. I am not a puppet advanced user.. yet. Puppet scoping does not allow me to use the $flag outside of the .each loop in which it was defined. Does anyone have a solution or a workaround for this scenario ?

Puppet version 4.4.

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted

answered 2017-05-09 23:01:13 -0500

smarlow gravatar image

Technically the code block passed to each is a lambda and so has its own scope. You can access outside variables inside of the code block, but variables declared inside cannot be reached outside.

In your particular scenario one way to work around this would be through the reduce function (link). This function iterates over a data structure like each, but it also carries over a 'memo' value which gets returned at the end. The value of the memo parameter in each iteration is set to the value of the last statement in the previous iteration.

For example:

$data = [{'k' => 'a' },
         {'k' => 'b' },
         {'k' => 'c'}]

# Initialize $memo to false, set $flag to the final value of $memo
$flag = $data.reduce(false) |$memo, $v| {
  if $v['k'] == 'b' {
    # If we find the value we're looking for, set $memo to true
    $f = true
  } else {
    # Otherwise carry over the existing value
    $f = $memo
  $f # $memo gets set to the value of the final statement; ensure that it is $f

A more compact (but less readable) way to express this is:

# If $memo is true that value will carry over;
# otherwise, if $v['k'] == 'b' the statement will evaluate as true
# and $memo will be set for the next iteration.
$flag = $data.reduce(false) |$memo, $v| {
  $memo or $v['k'] == 'b'

Which version is preferable depends on how familiar people are in your organization with programming/idiomatic Ruby.

Additionally there may be useful functions in the function reference or the stdlib, but nothing jumped out at me for this case.

edit flag offensive delete link more


i found a more naive solution in the meantime, used .erb $flag = inline_template('<% @hash_array.flatten.each do |hash| %><% if hash[\'title\'] == "desired_value" %>true<% break %><% end %><% end %>') unfortunately, i end up with the $flag as a string, but that is not a blocker for me. Thank you !

besleg gravatar imagebesleg ( 2017-05-10 03:35:48 -0500 )edit

answered 2017-05-09 18:52:51 -0500

ross.murray gravatar image

updated 2017-05-09 18:54:37 -0500

Do you need to iterate over the entire array?

$my_hash = {'key_name' => 'desired_value'}
if ($my_hash[key_name] == 'desired_value') {
  $flag = true
} else {
  $flag = false

If that doesn't suit your particular needs, a conditional statement combined with the has_key function from the puppetlabs/stdlib module should get you there.

edit flag offensive delete link more


that was my first attempt, but unfortunately, scoping does not allow me to use $flag outside of the .each iteration (keep in mind that i have an array of hashes, not just one hash)

besleg gravatar imagebesleg ( 2017-05-10 03:31:34 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools


Asked: 2017-05-09 13:43:20 -0500

Seen: 39 times

Last updated: May 09