Ask Your Question
0

Hiera with masterless Puppet - how to extract data from available facts?

asked 2016-06-22 05:15:46 -0500

I'd need to infer some information from available facts, e.g. given a hostname like dev-london1-server0, available as fact to hiera, I would like to extract the environment (dev), the datacenter (london1) and optionally the server name (server0), so that I can use them to instruct hiera how to navigate the hierarchy.

For example I'd like an hierarchy like this:

hieradata/dev/london1/common.yaml
hieradata/dev/london1/dev-london1-server0.yaml
hieradata/dev/london1/dev-london1-server1.yaml
hieradata/dev/london2/common.yaml
...

with a hiera.yaml like this:

---
:backends:
  - yaml
:yaml:
  :datadir: ./hieradata
:hierarchy:
  - "%{env}/%{datacenter}/%{::fqdn}"
  - "%{env}/%{datacenter}/common"
  - "virtual/%{::virtual}"
  - "osfamily/%{osfamily}"
  - common

My idea is to extract %{env} and %{datacenter} from the local ::hostname provided by facter (e.g. dev-london1-server0). Is there a way to do this?

What alternative solution could be applied? As mentioned, this is a masterless structure. Thanks.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2016-06-22 09:59:33 -0500

DarylW gravatar image

updated 2016-06-23 03:52:22 -0500

You would need to create a custom fact that would read the value from the :hostname fact, and parse it into the information you want. You would then add a fact for each piece of information that you wish to pull out.

Here's an example where you decompose it using a regex. You also could split on -, or something similar. If you are using a regex, you could make them more specific than .* matchgroups. You would add this to your module like any other custom fact, placing it in your module under something like modulename/lib/facter/parse_hostname.rb

require 'facter'

hostname = Facter.value(:hostname)
# This will create a variable for each named label in the capturegroup, http://ruby-doc.org/core-1.9.3/Regexp.html#top
/(?<env>.*)-(?<datacenter>.*)-(?<servername>.*)/ =~ hostname

# if the variable was defined, add a fact with the value from each capturegroup
if env
  Facter.add(:env) do
    setcode do
      env
    end
  end
end

if datacenter
  Facter.add(:datacenter) do
    setcode do
      datacenter
    end
  end
end

if servername
  Facter.add(:servername) do
    setcode do
      servername
    end
  end
end

You could also get a little bit more fancy with the capture group, and generate a facts based on the name specified... This does the same thing as above, but with less code

require 'facter'

hostname = Facter.value(:hostname)
match_data = /(?<env>.*)-(?<datacenter>.*)-(?<servername>.*)/.match(hostname)

match_data.names.each do |name|
  Facter.add(name.to_sym) do
    setcode do
      match_data[name]
    end
  end
end
edit flag offensive delete link more

Comments

1

Thank you - I've seen your answer and I'm testing/experimenting. Will report.

giavac gravatar imagegiavac ( 2016-06-22 12:15:32 -0500 )edit

Awesome.. If my answer solves your problem, please accept it (by selecting the green check under the voting arrows). That was a fun little fact to write.

DarylW gravatar imageDarylW ( 2016-06-23 00:38:50 -0500 )edit
1

Works like a charm! Thank you.

giavac gravatar imagegiavac ( 2016-06-23 03:50:31 -0500 )edit

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

Stats

Asked: 2016-06-22 05:15:46 -0500

Seen: 159 times

Last updated: Jun 23 '16