looping over an hashmap in an .pp file

963 views
Skip to first unread message

Simon Hönscheid

unread,
Aug 9, 2013, 11:47:27 AM8/9/13
to puppet...@googlegroups.com
I have an interesting problem an I found no solution yet:

I want puppet to repeat an exec for every hast element I have:

$database_users = [ {  user                  => 'jira',
                                 passwort            => 'supersecure',
                                 userpermissions => 'LOGIN CREATEDB NOSUPERUSER NOCREATEROLE'
                              },     
                              {  user                  => 'test',
                                 passwort           => 'test',
                                 userpermissions => 'CREATEDB NOSUPERUSER NOCREATEROLE'
                              },
                            ]    

now i want to do something in config.pp with it, for every element. is there a solution?

  exec { "echo \"CREATE ROLE ${database_user[user]}  WITH ${database_user[userpermissions]} PASSWORD '${database_user[password]}';\"| psql":
  onlyif => "test `echo \"\\dg\" | psql| grep ${database_user[user]}|wc -l` -eq 0"
}

thanks simon

Sergey Arlashin

unread,
Aug 9, 2013, 12:10:42 PM8/9/13
to puppet...@googlegroups.com
Hi Simon,

--
Best regards,
Sergey


--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To post to this group, send email to puppet...@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-users.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Sergey Arlashin

unread,
Aug 9, 2013, 12:14:55 PM8/9/13
to puppet...@googlegroups.com
also you can use the following way to iterate over a hash:

  $foo = [
            { "addr" => "bar",
              "port" => "1" },
            { "addr" => "bat",
              "port" => "2" }
         ]
  testmod::bar {$foo:}

  define testmod::bar () {
     $var1 = $name["addr"]
     $var2 = $name["port"]
     notify {"${var1}_${var2}": }
  }


--
Best regards,
Sergey Arlashin

On Aug 9, 2013, at 7:47 PM, Simon Hönscheid <simon.hoens...@gmail.com> wrote:

Simon Hönscheid

unread,
Aug 9, 2013, 12:16:58 PM8/9/13
to puppet...@googlegroups.com
thanks, that looks great!
does that work with 2.7.x with storedconfigs but without hiera backend?

Sergey Arlashin

unread,
Aug 9, 2013, 12:21:21 PM8/9/13
to puppet...@googlegroups.com
I'm using 3.2 without hiera backend and have never tried to iterate over a hash in 2.7. So you can try and report the result :) 

--
Best regards,
Sergey Arlashin

jcbollinger

unread,
Aug 12, 2013, 9:39:34 AM8/12/13
to puppet...@googlegroups.com


If you actually did have a hashmap (the local terminology being simply "hash") then your options would be different, but what you show is actually an array of hashes.  Puppet DSL does not have a general foreach feature, and neither of Sergey's suggestions is viable: passing the array as a resource title will cause the elements (the hashes) to be flattened to strings, and the data structure is not quite correct for create_resources().

From a data perspective, the problem is that your individual hashes are anonymous.  That they carry identifying data internally is irrelevant -- it's meaningful to you, but not to Puppet generally.  Would it be feasible to structure your data along these lines instead?

$database_users = { 'jira' => {
                                 password            => 'supersecure',
                                 userpermissions => 'LOGIN CREATEDB NOSUPERUSER NOCREATEROLE'
                              },
                              'test' => {
                                 password           => 'test',
                                 userpermissions => 'CREATEDB NOSUPERUSER NOCREATEROLE'
                              },
                            }

That is the general form you would want to use with create_resources() and a definition along these lines:

define database::user ( $password, $userpermissions ) {
  exec { "db_user_${title}":
    command => "echo \"CREATE ROLE ${title}  WITH ${userpermissions} PASSWORD '${password}';\"| psql",
    unless => "echo '\\dg' | psql | grep -q ${title}"
  }
}

Alternatively, there are sometimes reasons to prefer explicit resource declarations over create_resources().  With the same (revised) form of the data, you could also do this:

  $db_usernames = keys($database_users)
  database::user2 { $db_usernames:
    userdata => $database_users
  }

with a slightly different definition:

define database::user2 ( $all_data ) {
  $data = $all_data[$title]
  exec { "db_user_${title}":
    command => "echo \"CREATE ROLE ${title}  WITH ${data['userpermissions']} PASSWORD '${data['password']}';\"| psql",
    unless => "echo '\\dg' | psql | grep -q ${title}"
  }
}

Alternatively, if the top user data hash is in a class variable somewhere, then you can consider skipping passing it as a parameter, and let the definition instead access it directly.


John

Dick Davies

unread,
Aug 12, 2013, 10:43:38 AM8/12/13
to puppet...@googlegroups.com
+1 for create_resources. I use it on 2.7 without storeconfigs, and it doesn't
involve hiera at all. I just declare $modulename::data = [ {.....}]
and feed that into
a resource with:

create_resources(resourcename, $modulename::data)

One gotcha: this is a function (essentially a macro that expands into
a load of resource definitions
before they get sent down to the node) - so if you make any typos etc.
it won't be obvious on
the puppet reports. the master should log errors that'll help you
debug it, though.


On 9 August 2013 17:16, Simon Hönscheid
Reply all
Reply to author
Forward
0 new messages