Ask Your Question

Using Variables in a Hiera Hierachy

asked 2014-06-25 16:27:38 -0500

kemra102 gravatar image

updated 2014-06-25 16:30:05 -0500

I am looking for a way to assign roles to a group of servers easily. These values are arbitrary and facter cannot determine them. This is my current hiera.yaml:

        - yaml 

      :datadir: /etc/puppet/hieradata

        - "servers/%{::fqdn}"
        - "roles/%{::role}"
        - common

:logger: console

:merge_behavior: deeper

The idea I had was to use something like site.pp to create these roles like so:

node '' {
  $role = "puppetmaster"

However this does not seem to work as expected. Is there anyway to approximate something similar?

edit retag flag offensive close merge delete

4 Answers

Sort by ยป oldest newest most voted

answered 2014-06-26 06:20:43 -0500

daff gravatar image

You should not rely on node-level variables at all. I am not sure where I read or heard this but support for such variables might go away in future Puppet releases. This only leaves top-scope variables and proper facts, which is what you should be using.

Why not simply create a custom, external fact named role, making use of Facter's support for external facts? Something like this:

# mkdir -p /etc/facter/facts.d
# echo "role=puppetmaster" > /etc/facter/facts.d/role.txt

Then facter -p role will return "puppetmaster" on that node.

Of course this is impractical to do manually on multiple nodes so you either need to find a way to set up such facts at provisioning time, or with Puppet and a file resource, or "out of band", possibly using MCollective, Capistrano, or even parallel SSH.

That said, you seem to be making life for yourself more difficult by trying it this way.

We assign roles to nodes this way:

Our /etc/puppet/environments/production/manifests/site.pp only contains this:

node default {
  $role = hiera('role')
  include $role

Then in the data file for a node like

$ cat /etc/puppet/hieradata/production/nodes/
role: '::role::postgresql_server'

Or for our Puppet masters:

$ cat /etc/puppet/hieradata/production/nodes/
role: '::role::puppet_master_worker'

Or a default role for nodes that don't have their own data file:

$ cat /etc/puppet/hieradata/production/common.yaml
role: '::role::standard_server'

This makes assigning roles to nodes very easy and it can all be done from Hiera by editing Yaml files.

The role classes are set up pretty much exactly like documented and explained in any of the following resources:

edit flag offensive delete link more


I ended up being able to write a custom fact to define the role as a colleague decided to inform me our host names in the new environment would be predictable. Your info certainly helped me out though - thanks.

kemra102 gravatar imagekemra102 ( 2014-06-26 09:25:39 -0500 )edit

answered 2015-04-08 21:54:04 -0500

TommyTheKid gravatar image

If you want to use "role" or other "runtime" defined variables in hiera, you can define them in the ENC. We use both "role" and "app_tier" in our hiera.yaml, both defined in "TheForeman" for the hostgroup, but I am sure that PE would work the same.

edit flag offensive delete link more

answered 2015-04-09 09:37:05 -0500

rnelson0 gravatar image

A slight variant on daff's solution would be to add this to your site manifest:

hiera_include('classes', [])

This saves the step of assigning the hiera lookup to a variable and then include $role. The empty array ensures that hiera_include does not fail when no hiera response is found, and also that pre-commit checks don't flag your site manifest as invalid (because pre-commit checks usually have no valid hiera source).

edit flag offensive delete link more

answered 2015-04-10 12:20:27 -0500

dbowling gravatar image

I tried Daff's solution for a while, but eventually ran into problems with hierarchy flexibility. Writing a fact based on hostname ended up being the solution that PuppetLabs support had me do and it has worked wonderfully.

Here's my code for {module_name}\lib\facter\application_tier.rb:

require 'facter'

Facter.add(:application_tier) do
  setcode do
    location = case Facter.value(:hostname)
               when /dev(\d|)$/ then 'development'
               when /test(\d|)$/ then 'test'
               else 'production'

You can place the fact in any module, and it will be applied via pluginsync. If you're using Vagrant without a Puppet Master, like I am, then you'll need to define FACTERLIB too. I use a shell provisioner with the following line in it:

echo 'export FACTERLIB="/vagrant/modules/roles/lib/facter"' > /etc/profile.d/

One tip is to be sure to use the hostname, and not the FQDN. The FQDN fact takes forever to run, while hostname is very fast.

My hiera.yaml file then looks like this:

  - "vagrant"
  - "node/%{::hostname}"
  - "tier/%{::application_tier}"
  - "secrets"
  - "common"
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2014-06-25 16:27:38 -0500

Seen: 4,217 times

Last updated: Apr 10 '15