puppethieraaugeas

Using hiera_hash for augeas changes in hiera puppet


I've created yaml files for each environment type dev, qa, integration. However there are multiple dev environments and i want to override some changes via host specific yaml files.

Hiera
|--host
|  |-dev1.internet.com
|  |-dev2.intranet.com
|--servertype
|  |-dev
|  |-qa

dev.yaml
augeas_xml:
  - 'set /root/node/servername/#text 'dev'
  - 'set /root/node/serverlocation/#text 'London'
  - 'set /root/node/ntp/#text '123.123.123.123'

dev1.internet.com.yaml
augeas_xml:
  - 'set /root/node/serverlocation/#text 'New York'
  - 'set /root/node/ntp/#text '123.123.123.125'

dev2.intranet.com.yaml
augeas_xml:
  - 'set /root/node/serverlocation/#text 'Accrington'

I need a way to get the config of dev1.internet.com.yaml to have the following

augeas_xml:
  - 'set /root/node/servername/#text 'dev'
  - 'set /root/node/serverlocation/#text 'New York'
  - 'set /root/node/ntp/#text '123.123.123.125'

hiera_array is not giving me the desired result and hiera_hash is giving me the following error: Hiera type mismatch for key 'augeas_xml': expected Hash and got Array

The host specific settings are not taking priority over the environment specific settings. The example i gave is for a small set of servers. I'm using puppet to manage hundreds of servers. I could use hiera and create a yaml file for every single host. However, I want to have a default.yaml and be able to override the changes in the host.yaml

---
:hierarchy:
  - "host/%{::fqdn}"
  - "server_type/%{server_type}"
  - default
:backends:
  - yaml
:yaml:
  :datadir: "/puppet/hieradata/%{::environment}"
:merge_behavior: deeper

The latter is producing

    dev1.internet.com.yaml
    augeas_xml:
      - 'set /root/node/serverlocation/#text 'New York'
      - 'set /root/node/ntp/#text '123.123.123.125'
      - 'set /root/node/servername/#text 'dev'
      - 'set /root/node/serverlocation/#text 'London'
      - 'set /root/node/ntp/#text '123.123.123.123'

but I want it to do

    dev1.internet.com.yaml
    augeas_xml:
      - 'set /root/node/servername/#text 'dev'
      - 'set /root/node/serverlocation/#text 'London'
      - 'set /root/node/ntp/#text '123.123.123.123'
      - 'set /root/node/serverlocation/#text 'New York'
      - 'set /root/node/ntp/#text '123.123.123.125'

Solution

  • It'd be much simpler to keep the Augeas commands and paths out of your data files and only put the important bits of data - the name, location, and server address - in the data files. The Augeas commands are most definitely implementation-specific, not data.

    For example:

    dev.yaml

    servername: 'dev'
    serverlocation: 'London'
    ntp: '123.123.123.123'
    

    dev1.internet.com.yaml

    serverlocation: 'New York'
    ntp: '123.123.123.125'
    

    dev2.intranet.com.yaml

    serverlocation: 'Accrington'
    

    Then in your manifest, you have something like this:

    $servername = hiera('servername')
    $serverlocation = hiera('serverlocation')
    $ntp = hiera('ntp')
    
    augeas { 'node':
      context => '/files/root/node',
      changes => [
        "set servername/#text '$servername'",
        "set serverlocation/#text '$serverlocation'",
        "set ntp/#text '$ntp'",
      ],
    }
    

    (note the other Augeas resource properties are missing and should be replaced by your own)