Correct approach for complex hierarchical data parsing

asked 2014-11-12 06:38:30 -0500

gin gravatar image

updated 2014-11-12 06:40:03 -0500


basically, this thread is a follow-up of my previous question:

My aim is to come up with an autorizedkeys manager script that reads configuration from Hiera and updates relevant authorizedkeys.

I use YAML to store access data (Hiera for access) [1].

The interesting bit is the Puppet script [2]. As you can see, I find a hard way to get around the language concept (no iterations, asynchronous). The workflow of my script to parse the data is:

  1. Collect the $nodes list with hiera_array
  2. Iterate through the list by defining resources with the $nodes[i] as a $name
  3. In each declared resource collect $roles of the specified $name
  4. Again, iterate throught the $roles list by declaring resources...
  5. I use the same principle until I get down to key generation.

Of course, if I have 2 hosts that share the same role <role1> (example [1]), I will get the error: "Duplicate declaration: Parse_users[<role1>] is already declared...". Thus array iteration cheat does not work out as well as expected.

So my question is: how would you deal with such data structures? What is the correct way to parse it?



[1] The data structure is as follows:

   #a list of nodes affected by my ssh access control
         - '<hostname1>'
         - '<hostname2>'

    #each node has allowed roles    
         - '<role1>'
         - '<role2>'

         - '<role1>'

    #each role has users
         - <user1>

    #NOT IMPLEMENTED: user's auth_keys can have other users keys. 
    #E.g. <user2> can ssh as <user1>.
    #   <user1>:users
    #    - <user2>

    #user info
         type: 'ssh-rsa'
         public_key: 'B3NzaC1yc2EAAAABJQA'

[2] My Puppet script. Bear in mind, it might have typos, thus might not work when pasted.

define parse_roles() {
  if $name {
    $roles = hiera_array("roles::${name}", "null")
    parse_users{"${roles}": }

define parse_users() {
  if $name != "null" {
    $users = hiera_array("users::${name}", "null")
     parse_key{$users: }

define parse_key() {
     $key = hiera_hash("key::${name}")
     create_key{$name: key => $key}

define create_key($key, $ensure=present) {
    ssh_authorized_key { "${name}-key-${ensure}-in-${owner}@${::hostname}":
       ensure => $ensure,
       key    => $key[public_key],
       type   => $key[type],
       user   => $name,

$nodes = hiera_array("nodes", undef)
edit retag flag offensive close merge delete