Search code examples
automationyamlpuppetpuppet-enterprisehiera

Assess hashes value in puppet manifest from hiera


I'm having difficulty in calling the hashes value in my puppet manifest, my code as below,

hiera .yaml file:

---
users:
  app1:
    ensure: 'present'
    home: '/home/app1'
    password: '!!'
    password_max_age: '99999'
    password_min_age: '0'
  app2:
    ensure: 'present'
    home: '/home/app2'
    password: '!!'
    password_max_age: '99999'
    password_min_age: '0'

My puppet manifest:

class profile::sec::sec_model {
hiera_hash('users').each |String $user, Hash $user_hash| {
    $user_hash.each |String $attr, String $value| {
        user { "$user":
            "${attr}" => "${value}"
       }
    }
}
}

My goal is to create user app1 and app2, if using normal manifest as below, i able to create it, as example below,

user { 'app1':
        ensure            => "present",
        home              => "/home/app1",
        password          => '!!',
        password_max_age  => '99999',
        password_min_age  => '0',
        shell             => '/bin/bash',
    }
}

However, when using hiera, i received an error as below from the test puppet client server,

Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Syntax error at '' (file: /etc/puppetlabs/code/environments/xxxxx/site/profile/manifests/xxx/sec_model.pp, line: 11, column: 13) on node xxxx.xxx.com

When I look into my manifest everything is good, but cannot identify which side of code for calling the hash value is wrong.


Solution

  • Yes, that's not valid syntax.

    So, you should refactor your YAML as:

    ---
    profile::sec::sec_model::users:
      app1:
        ensure: present
        home: /home/app1
        password: '!!'
        password_max_age: 99999
        password_min_age: 0
      app2:
        ensure: present
        home: /home/app2
        password: '!!'
        password_max_age: 99999
        password_min_age: 0
    

    And then for your manifest, use either:

    class profile::sec::sec_model(Hash[String,Hash] $users) {
      $users.each |$user,$user_hash| {
        user { $user: * => $user_hash }
      }
    }
    

    Or, simply:

    class profile::sec::sec_model(Hash[String,Hash] $users) {
      create_resources(user, $users)
    }
    

    Noting that not everyone in the Puppet community likes using create_resources.

    Further explanation:

    • This question is quite similar to this earlier question. See there for further information on the "whys" and for further references.

    • Note also that I removed superfluous punctuation in the YAML. I personally consider it a best practice to include only punctuation in YAML files that is actually required, because it is cleaner, and it also forces you to learn when and why punctuation in YAML is required.