Skip to content

Commit

Permalink
(#12357) Add puppet_vardir custom fact
Browse files Browse the repository at this point in the history
Without this patch the PE modules don't have a way to identify a
filesystem path where it's OK to place variable data related to managing
the target node.  This is a problem when a module like pe_compliance
needs to write a wrapper script to the node's filesystem.

This patch addresses the problem by exposing the node's Puppet[:vardir]
setting as a Facter fact.

This fact value will be set to `nil` if Puppet is not loaded into
memory.  If Puppet is loaded, e.g. using `facter --puppet` or using
`puppet agent` or `puppet apply` then the fact will automatically set
the value to Puppet[:vardir]

The value of this setting is subject to Puppet's run_mode.

This patch implements a new utility method in the standard library
module named `Facter::Util::PuppetSettings.with_puppet`.  The method
accepts a block and will only invoke the block if the Puppet library is
loaded into the Ruby process.  If Puppet is not loaded, the method
always returns nil.  This makes it easy to define Facter facts that only
give values if Puppet is loaded in memory.
  • Loading branch information
Jeff McCune committed Mar 6, 2012
1 parent c0ac470 commit a452f6a
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 0 deletions.
35 changes: 35 additions & 0 deletions README_DEVELOPER.markdown
@@ -0,0 +1,35 @@
Puppet Specific Facts
=====================

Facter is meant to stand alone and apart from Puppet. However, Facter often
runs inside Puppet and all custom facts included in the stdlib module will
almost always be evaluated in the context of Puppet and Facter working
together.

Still, we don't want to write custom facts that blow up in the users face if
Puppet is not loaded in memory. This is often the case if the user run
`facter` without also supplying the `--puppet` flag.

Ah! But Jeff, the custom fact won't be in the `$LOAD_PATH` unless the user
supplies `--facter`! You might say...

Not (always) true I say! If the user happens to have a CWD of
`<modulepath>/stdlib/lib` then the facts will automatically be evaluated and
blow up.

In any event, it's pretty easy to write a fact that has no value if Puppet is
not loaded. Simply do it like this:

Facter.add(:node_vardir) do
setcode do
# This will be nil if Puppet is not available.
Facter::Util::PuppetSettings.with_puppet do
Puppet[:vardir]
end
end
end

The `Facter::Util::PuppetSettings.with_puppet` method accepts a block and
yields to it only if the Puppet library is loaded. If the Puppet library is
not loaded, then the method silently returns `nil` which Facter interprets as
an undefined fact value. The net effect is that the fact won't be set.
16 changes: 16 additions & 0 deletions lib/facter/puppet_vardir.rb
@@ -0,0 +1,16 @@
# This facter fact returns the value of the Puppet vardir setting for the node
# running puppet or puppet agent. The intent is to enable Puppet modules to
# automatically have insight into a place where they can place variable data,
# regardless of the node's platform.
#
# The value should be directly usable in a File resource path attribute.
require 'facter/util/puppet_settings'

Facter.add(:puppet_vardir) do
setcode do
# This will be nil if Puppet is not available.
Facter::Util::PuppetSettings.with_puppet do
Puppet[:vardir]
end
end
end
17 changes: 17 additions & 0 deletions lib/facter/util/puppet_settings.rb
@@ -0,0 +1,17 @@
module Facter
module Util
module PuppetSettings
class << self
def with_puppet
begin
Module.const_get("Puppet")
rescue NameError
nil
else
yield
end
end
end
end
end
end
35 changes: 35 additions & 0 deletions spec/unit/facter/util/puppet_settings_spec.rb
@@ -0,0 +1,35 @@
require 'spec_helper'
require 'facter/util/puppet_settings'

describe Facter::Util::PuppetSettings do

describe "#with_puppet" do
context "Without Puppet loaded" do
before(:each) do
Module.expects(:const_get).with("Puppet").raises(NameError)
end

it 'should be nil' do
subject.with_puppet { Puppet[:vardir] }.should be_nil
end
it 'should not yield to the block' do
Puppet.expects(:[]).never
subject.with_puppet { Puppet[:vardir] }.should be_nil
end
end
context "With Puppet loaded" do
module Puppet; end
let(:vardir) { "/var/lib/puppet" }

before :each do
Puppet.expects(:[]).with(:vardir).returns vardir
end
it 'should yield to the block' do
subject.with_puppet { Puppet[:vardir] }
end
it 'should return the nodes vardir' do
subject.with_puppet { Puppet[:vardir] }.should eq vardir
end
end
end
end

0 comments on commit a452f6a

Please sign in to comment.