File: //proc/thread-self/root/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/mcollective/facts/base.rb
module MCollective
module Facts
# A base class for fact providers, to make a new fully functional fact provider
# inherit from this and simply provide a self.get_facts method that returns a
# hash like:
#
# {"foo" => "bar",
# "bar" => "baz"}
class Base
def initialize
@mutex = Mutex.new
@facts = {}
@last_good_facts = {}
@last_facts_load = 0
end
# Registers new fact sources into the plugin manager
def self.inherited(klass)
PluginManager << {:type => "facts_plugin", :class => klass.to_s}
end
# Returns the value of a single fact
def get_fact(fact=nil)
config = Config.instance
cache_time = config.fact_cache_time || 300
@mutex.synchronize do
begin
if (Time.now.to_i - @last_facts_load > cache_time.to_i ) || force_reload?
Log.debug("Resetting facter cache, now: #{Time.now.to_i} last-known-good: #{@last_facts_load}")
tfacts = load_facts_from_source
# Force reset to last known good state on empty facts
raise "Got empty facts" if tfacts.empty?
@facts = normalize_facts(tfacts)
@last_good_facts = @facts.clone
@last_facts_load = Time.now.to_i
else
Log.debug("Using cached facts now: #{Time.now.to_i} last-known-good: #{@last_facts_load}")
end
rescue Exception => e
Log.error("Failed to load facts: #{e.class}: #{e}")
# Avoid loops where failing fact loads cause huge CPU
# loops, this way it only retries once every cache_time
# seconds
@last_facts_load = Time.now.to_i
# Revert to last known good state
@facts = @last_good_facts.clone
end
end
# If you do not supply a specific fact all facts will be returned
if fact.nil?
return @facts
else
@facts.include?(fact) ? @facts[fact] : nil
end
end
# Returns all facts
def get_facts
get_fact(nil)
end
# Returns true if we know about a specific fact, false otherwise
def has_fact?(fact)
get_fact(nil).include?(fact)
end
# Plugins can override this to provide forced fact invalidation
def force_reload?
false
end
private
def normalize_facts(value)
case value
when Array
return value.map { |v| normalize_facts(v) }
when Hash
new_hash = {}
value.each do |k,v|
new_hash[k.to_s] = normalize_facts(v)
end
return new_hash
else
return value.to_s
end
end
end
end
end