markround/tiller

Tiller support for pre-defined hierarchies similar to hiera

Opened this issue · 0 comments

pll commented

Hiera allows the end-user to define a particular customized hierarchy for where to search for KV pairs in a hiera.yaml file like this:

...
:hierarchy:
  - "%{::stack}/nodes/%{::hostname}"
  - "%{::stack}"
  - "%{::stack}/%{::stack}_%{::system_type}"
  - "system_types/%{::system_type}"
  - global

This example hierarchy states that hiera should look in the following locations, in the specified order for the values to the requested key. For example, given the key FOO, hiera will look for a KV pair of foo = some_value in the above paths in order. In hiera, those paths are .yaml or .json files with file names matching the last variable. In consul, they could be paths with the folder being denoted by that path. e.g. given a hostname of prod-nginx-1 where each hyphen-delimited token represents stack-system_type-sytem_number, hiera would look for a file, or consul path named:

  1. /prod/nodes/prod-nginx-1
  2. /prod
  3. /prod/prod_nginx
  4. /system_types/nginx

(for hiera, each of those paths would be file names ending in either .yaml or .json)

The advantage of this hierarchy is the ability to define variables in a most-to-least-specific manner. In other words, if I have:

  • a host-specific setting which should be different only on a single host for some reason, I set the KV in a host-specific location.
  • an environment-wide setting, I set the KV in the environment-specific file (i.e. /prod, /stage, /qa, etc.)
  • an environment-wide setting to a specific host-type, I set it based on /env/type
  • a system-type specific setting that is essentially a global only for that host type, I set it in /system_types/type.
  • and lastly, KVs which are common or global to all systems are set in /global.

Hiera is mostly used directly from puppet, which has a variety of functions with which to search for a KV pair. From https://docs.puppet.com/hiera/3.1/puppet.html#hiera-lookup-functions:

  • hiera() — Standard priority lookup. Gets the most specific value for a given key. This can retrieve values of any data type (strings, arrays, hashes) from Hiera.
  • hiera_array() — Uses an array merge lookup. Gets all of the string or array values in the hierarchy for a given key, then flattens them into a single array of unique values.
  • hiera_hash() — Uses a hash merge lookup. Expects every value in the hierarchy for a given key to be a hash, and merges the top-level keys in each hash into a single hash. Note that this does not do a deep merge in the case of nested structures unless you’ve installed the deep merge gem and configured deep merging.

(I'm not entirely sure hiera_array() or hiera_hash() are immediately useful, or a priority. Just providing the ability to find the first occurrence of KEY in a specified hierarchy similar to hiera() would be fantastic!)

Given this ability, in my puppet code, I can do:

  $foo = hiera('key')

Then when I evaluate an ERB template where the variable $foo is within scope, I can simply specify <%= foo %> and hiera will go search that hierarchy for me and replace it the first value it finds for key.

Since hiera is written in ruby, and ERB allows embedded calls to ruby functions, it is also possible to do something like this:

<%= scope.function_hiera(["key"]) -%>

So, it's possible we might just be able to include the hiera libs in tiller, and this will "just work" :)