We are working on Puppet 4.x :

[root@puppetserver ~]# puppet --version
4.7.0

Read hashes and arrays from a YAML file

Create a simple YAML file :

[root@puppetserver ~]# mkdir -p /examples && cd /examples
[root@puppetserver examples]# cat hashes_and_arrays.yaml
# Here a small example of shashes and arrays in YAML format :
---

array_of_hashes:
  - key0: 'value 0'
  - key1: 'value 1'
  - key2: 'value 2'

Create a class to read this file :

[root@puppetserver examples]# cat read_hashes_and_arrays.pp
# class definition :
class read_hashes_and_arrays {

  $file_name = '/examples/hashes_and_arrays.yaml'
  $file_read = loadyaml($file_name)
  notify { "we have read from \"${file_name}\" : \"${file_read}\"": }

}

# execute this class immediatly :
class { '::read_hashes_and_arrays': }

We execute this class :

[root@puppetserver examples]# puppet apply read_hashes_and_arrays.pp
Notice: Compiled catalog for puppetserver.argonay.wou in environment production in 0.16 seconds
Notice: we have read from "/examples/hashes_and_arrays.yaml" : "{array_of_hashes => [{key0 => value 0}, {key1 => value 1}, {key2 => value 2}]}"
Notice: /Stage[main]/Read_hashes_and_arrays/Notify[we have read from "/examples/hashes_and_arrays.yaml" : "{array_of_hashes => [{key0 => value 0}, {key1 => value 1}, {key2 => value 2}]}"]/message: defined 'message' as 'we have read from "/examples/hashes_and_arrays.yaml" : "{array_of_hashes => [{key0 => value 0}, {key1 => value 1}, {key2 => value 2}]}"'
Notice: Applied catalog in 0.08 seconds

So, we have a hash wich contains an array of hashes …

We modify this class to test if we have a hash , an array :

[root@puppetserver examples]# cat read_hashes_and_arrays.pp
# class definition :
class read_hashes_and_arrays {

  $file_name = '/examples/hashes_and_arrays.yaml'
  $file_read = loadyaml($file_name)

  if $file_read =~ Hash {
    notify { "\"${file_read}\" is a hash !": }
  }

  if $file_read['array_of_hashes'] =~ Array {
    notify { "\"${file_read['array_of_hashes']}\" is an array !": }
  }

}

# execute this class immediatly :
class { '::read_hashes_and_arrays': }

Let’s execute this class :

[root@puppetserver examples]# puppet apply read_hashes_and_arrays.pp
Notice: Compiled catalog for puppetserver.argonay.wou in environment production in 0.16 seconds
Notice: "{array_of_hashes => [{key0 => value 0}, {key1 => value 1}, {key2 => value 2}]}" is a hash !
Notice: /Stage[main]/Read_hashes_and_arrays/Notify["{array_of_hashes => [{key0 => value 0}, {key1 => value 1}, {key2 => value 2}]}" is a hash !]/message: defined 'message' as '"{array_of_hashes => [{key0 => value 0}, {key1 => value 1}, {key2 => value 2}]}" is a hash !'
Notice: "[{key0 => value 0}, {key1 => value 1}, {key2 => value 2}]" is an array !
Notice: /Stage[main]/Read_hashes_and_arrays/Notify["[{key0 => value 0}, {key1 => value 1}, {key2 => value 2}]" is an array !]/message: defined 'message' as '"[{key0 => value 0}, {key1 => value 1}, {key2 => value 2}]" is an array !'
Notice: Applied catalog in 0.08 seconds

“.each” method can be applied on both hashes an arrays

First and formost, we want Puppet to fail if we got a unexpected data type.

Don’t use deprecated “stdlib” functions “validate_hash” and validate_array” anymore !

# class definition :
class read_hashes_and_arrays {

  $file_name = '/examples/hashes_and_arrays.yaml'
  $file_read = loadyaml($file_name)

## "stdlib" "validate_hash" is now deprecated, don't use it anymore !
  if $file_read =~ Hash {
## "stdlib" "validate_hash" is now deprecated, don't use it anymore !
    if $file_read['array_of_hashes'] =~ Array {
      notify {"OK, let's go on !": }
    }
    else {
      fail ('we are expected an array !')
    }
  }
  else {
    fail ('we are expecting a hash !')
  }
}

# execute this class immediatly :
class { '::read_hashes_and_arrays': }

We execute this class :

[root@puppetserver examples]# puppet apply read_hashes_and_arrays.pp
Notice: Compiled catalog for puppetserver.argonay.wou in environment production in 0.15 seconds
Notice: OK, let's go on !
Notice: /Stage[main]/Read_hashes_and_arrays/Notify[OK, let's go on !]/message: defined 'message' as 'OK, let's go on !'
Notice: Applied catalog in 0.08 seconds

Iterate the array :

  • Class :
[root@puppetserver examples]# cat read_hashes_and_arrays.pp
# class definition :
class read_hashes_and_arrays {

  $file_name = '/examples/hashes_and_arrays.yaml'
  $file_read = loadyaml($file_name)

## "stdlib" "validate_hash" is now deprecated, don't use it anymore !
  if $file_read =~ Hash {
## "stdlib" "validate_hash" is now deprecated, don't use it anymore !
    if $file_read['array_of_hashes'] =~ Array {
## iterate each each array element :
      $file_read['array_of_hashes'].each |$my_array| {
        notify {"array element : \"${my_array}\"": }
      }
    }
    else {
      fail ('we are expected an array !')
    }
  }
  else {
    fail ('we are expecting a hash !')
  }
}

# execute this class immediatly :
class { '::read_hashes_and_arrays': }
  • Execution :
[root@puppetserver examples]# puppet apply read_hashes_and_arrays.pp
Notice: Compiled catalog for puppetserver.argonay.wou in environment production in 0.17 seconds
Notice: array element : "{key0 => value 0}"
Notice: /Stage[main]/Read_hashes_and_arrays/Notify[array element : "{key0 => value 0}"]/message: defined 'message' as 'array element : "{key0 => value 0}"'
Notice: array element : "{key1 => value 1}"
Notice: /Stage[main]/Read_hashes_and_arrays/Notify[array element : "{key1 => value 1}"]/message: defined 'message' as 'array element : "{key1 => value 1}"'
Notice: array element : "{key2 => value 2}"
Notice: /Stage[main]/Read_hashes_and_arrays/Notify[array element : "{key2 => value 2}"]/message: defined 'message' as 'array element : "{key2 => value 2}"'
Notice: Applied catalog in 0.13 seconds

Now, iterate the enclosed hash to retrieve both key and value :

  • Class :
[root@puppetserver examples]# cat read_hashes_and_arrays.pp
# class definition :
class read_hashes_and_arrays {

  $file_name = '/examples/hashes_and_arrays.yaml'
  $file_read = loadyaml($file_name)

## "stdlib" "validate_hash" is now deprecated, don't use it anymore !
  if $file_read =~ Hash {
## "stdlib" "validate_hash" is now deprecated, don't use it anymore !
    if $file_read['array_of_hashes'] =~ Array {
## iterate each each array element :
      $file_read['array_of_hashes'].each |$my_array| {
## this element must be a hash :
        if $my_array =~ Hash {
## extract key and value using ".each" iteration :
          $my_array.each |$my_key, $my_value| {
            notify { "key : \"${my_key}\", value : \"${my_value}\"": }
          }
        }
      }
    }
    else {
      fail ('we are expected an array !')
    }
  }
  else {
    fail ('we are expecting a hash !')
  }
}

# execute this class immediatly :
class { '::read_hashes_and_arrays': }
  • Execution :
[root@puppetserver examples]# puppet apply read_hashes_and_arrays.pp
Notice: Compiled catalog for puppetserver.argonay.wou in environment production in 0.17 seconds
Notice: key : "key0", value : "value 0"
Notice: /Stage[main]/Read_hashes_and_arrays/Notify[key : "key0", value : "value 0"]/message: defined 'message' as 'key : "key0", value : "value 0"'
Notice: key : "key1", value : "value 1"
Notice: /Stage[main]/Read_hashes_and_arrays/Notify[key : "key1", value : "value 1"]/message: defined 'message' as 'key : "key1", value : "value 1"'
Notice: key : "key2", value : "value 2"
Notice: /Stage[main]/Read_hashes_and_arrays/Notify[key : "key2", value : "value 2"]/message: defined 'message' as 'key : "key2", value : "value 2"'
Notice: Applied catalog in 0.11 seconds

Important remark

It’s not possible to this “notify” inside a loop:

[root@puppetserver examples]# cat read_hashes_and_arrays.pp
# class definition :
class read_hashes_and_arrays {

  $file_name = '/examples/hashes_and_arrays.yaml'
  $file_read = loadyaml($file_name)

## "stdlib" "validate_hash" is now deprecated, don't use it anymore !
  if $file_read =~ Hash {
## "stdlib" "validate_hash" is now deprecated, don't use it anymore !
    if $file_read['array_of_hashes'] =~ Array {
## iterate each each array element :
      $file_read['array_of_hashes'].each |$my_array| {
## this element must be a hash :
        if $my_array =~ Hash {
## extract key and value using ".each" iteration :
          $my_array.each |$my_key, $my_value| {
# this notify works well #            notify { "key : \"${my_key}\", value : \"${my_value}\"": }
            notify { 'we are trying to notify the same message': }
          }
        }
      }
    }
    else {
      fail ('we are expected an array !')
    }
  }
  else {
    fail ('we are expecting a hash !')
  }
}

# execute this class immediatly :
class { '::read_hashes_and_arrays': }

And we got an error during execution :

[root@puppetserver examples]# puppet apply read_hashes_and_arrays.pp
Error: Evaluation Error: Error while evaluating a Resource Statement, Duplicate declaration: Notify[we are trying to notify the same message] is already declared in file /examples/read_hashes_and_arrays.pp:18; cannot redeclare at /examples/read_hashes_and_arrays.pp:18 at /examples/read_hashes_and_arrays.pp:18:13 on node puppetserver.argonay.wou

Read hashes and arrays from hiera

hiera file

Here is my hiera configuration (default file) :

[root@puppetserver ~]# cat $(puppet config print hiera_config)
---
:backends:
  - yaml
:hierarchy:
  - "nodes/%{::trusted.certname}"
  - common

:yaml:
# datadir is empty here, so hiera uses its defaults:
# - /etc/puppetlabs/code/environments/%{environment}/hieradata on *nix
# - %CommonAppData%\PuppetLabs\code\environments\%{environment}\hieradata on Windows
# When specifying a datadir, make sure the directory exists.
  :datadir:

Create this directory :

[root@puppetserver ~]# mkdir -p /etc/puppetlabs/code/environments/production/hieradata/nodes

And create this YAML file :

[root@puppetserver ~]# cat /etc/puppetlabs/code/environments/production/hieradata/nodes/$(hostname -f).yaml
# classes to execute :
classes :
  - 'no_module::read_hashes_and_arrays'

# hiera values :
array_of_hashes:
  - key0: 'value 0'
  - key1: 'value 1'
  - key2: 'value 2'

Remark : we already have a class to launch “classes” defined in hiera :

[root@puppetserver ~]# grep hiera_include $(puppet config print manifest)/*
/etc/puppetlabs/code/environments/production/manifests/use_hiera.pp: hiera_include('classes')

Manifest

Where to put the manifest ?

We dont’ want to create a complete module, a simple manifest will be fine.

[root@puppetserver ~]# puppet module list | grep /etc/puppetlabs/code/modules
/etc/puppetlabs/code/modules (no modules installed)

Create, for example, this directory :

[root@puppetserver ~]# mkdir -p /etc/puppetlabs/code/modules/no_module/manifests

The manifest differs from the previous one :

  • the class name
  • we retrieve directly the array of hashes
  • this class will be executed by Puppet server
[root@puppetserver ~]# cat /etc/puppetlabs/code/modules/no_module/manifests/read_hashes_and_arrays.pp
class no_module::read_hashes_and_arrays {
  $read_from_hiera = hiera(array_of_hashes,undef)
## "stdlib" "validate_hash" is now deprecated, don't use it anymore !
  if $read_from_hiera=~ Array {
## iterate each each array element :
    $read_from_hiera.each |$my_array| {
## this element must be a hash :
      if $my_array =~ Hash {
## extract key and value using ".each" iteration :
        $my_array.each |$my_key, $my_value| {
          notify { "key : \"${my_key}\", value : \"${my_value}\"": }
        }
      }
    }
  }
  else {
    fail ('we are expected an array !')
  }
}

Let’s Puppet server execute this class :

[root@puppetserver ~]# puppet agent -tv
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for puppetserver.argonay.wou
Info: Applying configuration version '1479034511'
Notice: key : "key0", value : "value 0"
Notice: /Stage[main]/No_module::Read_hashes_and_arrays/Notify[key : "key0", value : "value 0"]/message: defined 'message' as 'key : "key0", value : "value 0"'
Notice: key : "key1", value : "value 1"
Notice: /Stage[main]/No_module::Read_hashes_and_arrays/Notify[key : "key1", value : "value 1"]/message: defined 'message' as 'key : "key1", value : "value 1"'
Notice: key : "key2", value : "value 2"
Notice: /Stage[main]/No_module::Read_hashes_and_arrays/Notify[key : "key2", value : "value 2"]/message: defined 'message' as 'key : "key2", value : "value 2"'
defined 'message' as 'we are executing "easy::my_manifest" class'
Notice: Applied catalog in 0.08 seconds

 

en.pdf24.org    Send article as PDF   

Leave a Reply

Your email address will not be published. Required fields are marked *


*