Grouping configurations in hiera based off a type of host

Before I begin, let me preface this by saying I am running under Puppet 5 these days, which means this may or may not work for you, so as always, please test before committing.

Lets say you have three print servers and they all have exactly the same configuration.  In terms of roles, profiles, and modules, this is fairly easy to work with, you can create a print server role and apply it to all three nodes.  However, hiera doesn’t have an “include” function.

In the past, we would create hosttype.yaml files and symlink all three hostname.yaml files to that:

hosttypes/printserver.yaml

nodes/printserver1.example.ncsu.edu -> hosttypes/printserver.yaml

nodes/printserver2.example.ncsu.edu -> hosttypes/printserver.yaml

nodes/printserver3.example.ncsu.edu -> hosttypes/printserver.yaml

This worked … ok.  However dealing with git-handled symlinks in Windows is a pain, which my main development environment.  On top of that, there was no way to do some one off exceptions.  For example what if I have testprintserver.example.ncsu.edu and want to test overriding only one setting.

 

So that’s fine and all, but what can we do about it?  I came across a handy trick (i wish i could link the article, but I’ve long lost it) to work around this — basically your hiera hierarchy can actually utilize puppet variables just like it can facts, and you can use that to look up a practical include set IN hiera, to look up other hiera settings.  Admittedly, it has a bit of a spaghetti feel to it, but whatever, it works.   So do to this, first I put something in my control_repo/manifests/00_all_nodes.pp file like so:

$hosttype = lookup('hosttype', String, 'first', 'default')
Then in my hiera hierarchy I add:
{
'name' => 'Host Type (defined by hiera variable type at node level)',
'path' => 'hosttypes/%{::hosttype}.yaml',
},
Note, this is in hiera 5 format, but should be fairly obvious to translate into an earlier format.
At this point, I can now replace all of those symlinks with standalone .yaml files that contain:
---
hosttype: 'printserver'
I can add whatever extra node-level hiera settings that I need that will win over the hosttype based one (because of where I put it in my hiera hierarchy), continue to have a shared hiera config between multiple hosts, and my Windows symlink woes are gone.
A couple of additional misc comments:
  • Sadly, no, you can’t have multiple hosttypes for one machine — but then I treat hosttype as a companion to a role, so there should be only one
  • This solution should work great with both puppet apply and just about any puppet master implementation out there that is new enough to support this behavior (unfortunately I can’t tell you how far back this works as I simply do not know)
  • Other departments have come up with a nice solution utilizing host groups in foreman, thereby relying on foreman to handle the categorization — a very excellent solution as well and hopefully they will write up their own article about their solution <hint hint>