creating custom facts - general usage

49 views
Skip to first unread message

Mike Reed

unread,
Aug 29, 2014, 6:05:01 PM8/29/14
to puppet...@googlegroups.com
Hello all,

To start, I would like to thank you in advance for your responses.

I'm attempting to create a custom fact that will determine the network location of a node, based on it's hostname.  Ideally this would be run on a node prior to the rest of the puppet modules because I will use the result as a top scope variable to assign certain values to nodes, based on their network location.  My node hostnames currently subscribe to this convention:

network-hostname/role-number (ie. home-elastic-01/work-mysql-02)

I've written a very simple fact to start with that looks like this (please excuse my code as I'm quite new to ruby):

# custom fact for determining network location of node
#
require 'facter'
Facter.add(:network_geo) do
  setcode do
    hostname          = Facter.value(:hostname)
    hostname_array = hostname.split('-')
    hostname_array
  end
end

This fact obviously doesn't get me what I want yet, but I'd like to test this on a node to ensure basic parsing of the hostname and this is where my confusion comes in.  I've created a puppet module called sys_ident and added the above code into a file called network_geo.rb, located within the /sys_ident/files/ directory. 

It's my understanding that I have to add the /sys_ident/files/ path into either the RUBYLIB or FACTERLIB environment path and I've done that (although I don't understand how that fits into my master/agent setup and if I need to add this into the path in the first place).  However, my expectation was that after the above, I could simply run 'facter | grep network_geo' and I would see the hostname of my machine split up but that is not the case.  Instead, have to run 'facter -p network_geo' and I get the desired output.

So my question is, do I want to or should I expect to use a custom fact by simply running 'facter network_geo' or will I have to run 'facter -p <custom fact>' to invoke my fact.  Also, if I run puppet and this module does run, can I identify this fact as a normal top scope variable in my manifests ?

If anybody has a good link that explains this, I would be most appreciative as I'm a bit confused.

Once again, thank you for your time in advance as it's most appreciated.

Cheers,

Mike


Felix Frank

unread,
Aug 31, 2014, 11:06:54 AM8/31/14
to puppet...@googlegroups.com
Hi,


On 08/30/2014 12:05 AM, Mike Reed wrote:
> network-hostname/role-number (ie. home-elastic-01/work-mysql-02)

are you sure that it's safe to include slashes in host names? Does that
not clash with some internet standard?

> I've written a very simple fact to start with that looks like this
> (please excuse my code as I'm quite new to ruby):

The code looks quite fine, actually. Good work.

> This fact obviously doesn't get me what I want yet, but I'd like to
> test this on a node to ensure basic parsing of the hostname and this
> is where my confusion comes in. I've created a puppet module called
> sys_ident and added the above code into a file called network_geo.rb,
> located within the /sys_ident/files/ directory.

That's the mistake right there. The Ruby file needs to be in
sys_ident/lib/facter/.

The Custom Fact documentation links you to
https://docs.puppetlabs.com/guides/plugins_in_modules.html#module-structure
where this is explained.

HTH,
Felix

jcbollinger

unread,
Sep 2, 2014, 9:42:11 AM9/2/14
to puppet...@googlegroups.com


On Friday, August 29, 2014 5:05:01 PM UTC-5, Mike Reed wrote:
Hello all,

To start, I would like to thank you in advance for your responses.

I'm attempting to create a custom fact that will determine the network location of a node, based on it's hostname.  Ideally this would be run on a node prior to the rest of the puppet modules because I will use the result as a top scope variable to assign certain values to nodes, based on their network location.  My node hostnames currently subscribe to this convention:

network-hostname/role-number (ie. home-elastic-01/work-mysql-02)


I would like to suggest that you not do this via a fact.  More generally, I consider it a principle of a good design to avoid creating any fact that is strictly derivative of other facts.

You can get a top scope variable with the same value in several other ways, principal among them:
  1. Compute it directly at top scope in your site manifest
  2. Compute it in a class that manages no resources, 'include' that class at top scope, and set the top-scope variable from the class variable
As a subset of (1), you could consider creating and using a custom function, which would be very clean as far as your manifests go.

Note, however, that for most purposes you don't actually need a top-scope variable; you could instead use a class variable directly.  Either way, you should be using a fully-qualified name everywhere you refer to the variable in your manifests, so the choice of namespace is mostly a personal preference in that context.  The only use I can think of where you actually need a top-scope variable is if you want to interpolate it into Hiera hierarchy definitions (which is indeed a perfectly reasonable thing to do).

Option 2 might look like this:

modules/site/manifests/hostname_info.pp:
----
class site::hostname_info {
  $hostname_parts = split($::hostname, '-')
  $network = $hostname_parts[0]
  $role = $hostname_parts[1]
  $number = $hostname_parts[2]
}


manifests/site.pp (or any other manifest where you need the info):
----
# ...
include 'site::hostname_info'
$host_network = $site::hostname_info::network
# ...


John

Mike Reed

unread,
Sep 2, 2014, 2:58:56 PM9/2/14
to puppet...@googlegroups.com

Hello Felix and John,

First, thank you both for your responses and information.

In regards to John's post, you make a very interesting point and I didn't realize that I could achieve my objective without using a custom fact.  My goal is to extract all site-specific data to Heira in the near future so this custom-fact exercise does seem worth while but thank you for pointing out these alternate ways to achieve my goal.

Thanks again to both of you for the informative posts.

Cheers,

Mike
Reply all
Reply to author
Forward
0 new messages