# Hiera Hierachy Advice

Hi,

I have a Hiera hiearchy similar to:

:hierarchy:
- "%{::environment}/node/%{fqdn}"
- "%{::environment}/role/%{role}"
- "%{::environment}/location/%{location}"
- "%{::environment}/env/%{::environment}"
- "%{::environment}/common"
- global/common


My 'role' hierarchy contains data that is common across several machines (ie, DNS servers). I define data in role/dns_server_internal.yaml like:

bind9::config::bind_recursion: no
bind9::config::also_notify:
- 172.31.200.60
bind9::config::acl_xfer:
- 172.31.200.60


This works well until I need to have common role data that differs from environment to environment (ie, from QA to PROD). In QA I may need one value for bind9::config::also_notify, but I need another value for it in PROD.

I would rather not have to use the 'node' hierarchy to define data per node. Furthermore, I cannot place the data in the "environment" hierarchy because I have several different DNS server roles (ie, dns_server_internal, dns_server_external) that require different data as well.

How are others dealing with situations like this? I do maintain separate sets of hiera data for dev/qa/production, but they are just separate git branches in the same git repo. Therefore, my workflow currently is "do the work in dev, merge to qa, and then merge to production." Because my workflow looks like this, it doesn't allow me to maintain separate sets of data per environment.

Any suggestions would be greatly appreciated.

edit retag close merge delete

Sort by » oldest newest most voted

You may be interested in my presentation from puppetconf 2013. It addresses the hierarchy and how to handle your exact situation. Our strategy is much likes ramindk's above but if done right you don't need the node level in the hierarchy. It also clarifies why you want levels like "env/%{environment}/%{role}" which essentially de-conflict a collision between the environment and role.

more

I watched your talk again last night. It doesn't get linked often enough.

( 2014-07-25 11:53:19 -0600 )edit

I have my setup like so. I create a datacenter fact that is based on a combo of ip/hostname. I also have a "environment" fact based on the hostname. This env fact has nothing to do with the puppet environments though. So basically I can't control things at the datacenter level and then control at a finer grained level where I might have multiple dev/qa environments in a single datacenter. My datacenter fact is probably similar to your location fact. Now since my customenvfact is a fact that is read from a file, I can actually control that fact data with hiera node level data to give me the ability to override the hostname. Sometimes I need a to place a node in a specific environment when new hostnames don't meet our standard naming convention. Although this has a side affect of having to run puppet twice to get the fact and classified correctly.

---
:hierarchy:
- "node/%{fqdn}"
- "datacenter/%{datacenter}"
- "env/%{custom_env_fact}"
- common

:yaml:

more

You might try something like following. I dropped env/common which env/$environment does anyway and added a combined env/role level. I also dropped the$env from the front and make it part of the datadir, but that's just the way I like to do it.

---
:hierarchy:
- "node/%{fqdn}"
- "env/%{environment}/%{role}"
- "role/%{role}"
- "location/%{location}"
- "env/%{environment}"
- common

:yaml:


You might be tempted to try something like the following. In my experience using three facts just makes is too complicated to keep in your head. If you need that sort of granularity, a custom ENC with your own rich business logic layer is probably a better solution. For small to medium sized systems it's almost always easier to set defaults in %{location} and not attempt to override at a different level.

    - "env/%{environment}/%{location}/%{role}"

more