diff options
| author | Micah Anderson <micah@riseup.net> | 2016-11-04 10:54:28 -0400 | 
|---|---|---|
| committer | Micah Anderson <micah@riseup.net> | 2016-11-04 10:54:28 -0400 | 
| commit | 34a381efa8f6295080c843f86bfa07d4e41056af (patch) | |
| tree | 9282cf5d4c876688602705a7fa0002bc4a810bde /puppet/modules/stdlib/lib/facter | |
| parent | 0a72bc6fd292bf9367b314fcb0347c4d35042f16 (diff) | |
| parent | 5821964ff7e16ca7aa9141bd09a77d355db492a9 (diff) | |
Merge branch 'develop'
Diffstat (limited to 'puppet/modules/stdlib/lib/facter')
| m--------- | puppet/modules/stdlib | 0 | ||||
| -rw-r--r-- | puppet/modules/stdlib/lib/facter/facter_dot_d.rb | 202 | ||||
| -rw-r--r-- | puppet/modules/stdlib/lib/facter/netmask_cidr_interface.rb | 22 | ||||
| -rw-r--r-- | puppet/modules/stdlib/lib/facter/pe_version.rb | 53 | ||||
| -rw-r--r-- | puppet/modules/stdlib/lib/facter/puppet_vardir.rb | 26 | ||||
| -rw-r--r-- | puppet/modules/stdlib/lib/facter/root_home.rb | 32 | ||||
| -rw-r--r-- | puppet/modules/stdlib/lib/facter/util/puppet_settings.rb | 21 | 
7 files changed, 356 insertions, 0 deletions
| diff --git a/puppet/modules/stdlib b/puppet/modules/stdlib deleted file mode 160000 -Subproject 71123634744b9fe2ec7d6a3e38e9789fd84801e diff --git a/puppet/modules/stdlib/lib/facter/facter_dot_d.rb b/puppet/modules/stdlib/lib/facter/facter_dot_d.rb new file mode 100644 index 00000000..b0584370 --- /dev/null +++ b/puppet/modules/stdlib/lib/facter/facter_dot_d.rb @@ -0,0 +1,202 @@ +# A Facter plugin that loads facts from /etc/facter/facts.d +# and /etc/puppetlabs/facter/facts.d. +# +# Facts can be in the form of JSON, YAML or Text files +# and any executable that returns key=value pairs. +# +# In the case of scripts you can also create a file that +# contains a cache TTL.  For foo.sh store the ttl as just +# a number in foo.sh.ttl +# +# The cache is stored in /tmp/facts_cache.yaml as a mode +# 600 file and will have the end result of not calling your +# fact scripts more often than is needed + +class Facter::Util::DotD +  require 'yaml' + +  def initialize(dir="/etc/facts.d", cache_file=File.join(Puppet[:libdir], "facts_dot_d.cache")) +    @dir = dir +    @cache_file = cache_file +    @cache = nil +    @types = {".txt" => :txt, ".json" => :json, ".yaml" => :yaml} +  end + +  def entries +    Dir.entries(@dir).reject { |f| f =~ /^\.|\.ttl$/ }.sort.map { |f| File.join(@dir, f) } +  rescue +    [] +  end + +  def fact_type(file) +    extension = File.extname(file) + +    type = @types[extension] || :unknown + +    type = :script if type == :unknown && File.executable?(file) + +    return type +  end + +  def txt_parser(file) +    File.readlines(file).each do |line| +      if line =~ /^([^=]+)=(.+)$/ +        var = $1; val = $2 + +        Facter.add(var) do +          setcode { val } +        end +      end +    end +  rescue Exception => e +    Facter.warn("Failed to handle #{file} as text facts: #{e.class}: #{e}") +  end + +  def json_parser(file) +    begin +      require 'json' +    rescue LoadError +      retry if require 'rubygems' +      raise +    end + +    JSON.load(File.read(file)).each_pair do |f, v| +      Facter.add(f) do +        setcode { v } +      end +    end +  rescue Exception => e +    Facter.warn("Failed to handle #{file} as json facts: #{e.class}: #{e}") +  end + +  def yaml_parser(file) +    require 'yaml' + +    YAML.load_file(file).each_pair do |f, v| +      Facter.add(f) do +        setcode { v } +      end +    end +  rescue Exception => e +    Facter.warn("Failed to handle #{file} as yaml facts: #{e.class}: #{e}") +  end + +  def script_parser(file) +    result = cache_lookup(file) +    ttl = cache_time(file) + +    unless result +      result = Facter::Util::Resolution.exec(file) + +      if ttl > 0 +        Facter.debug("Updating cache for #{file}") +        cache_store(file, result) +        cache_save! +      end +    else +      Facter.debug("Using cached data for #{file}") +    end + +    result.split("\n").each do |line| +      if line =~ /^(.+)=(.+)$/ +        var = $1; val = $2 + +        Facter.add(var) do +          setcode { val } +        end +      end +    end +  rescue Exception => e +    Facter.warn("Failed to handle #{file} as script facts: #{e.class}: #{e}") +    Facter.debug(e.backtrace.join("\n\t")) +  end + +  def cache_save! +    cache = load_cache +    File.open(@cache_file, "w", 0600) { |f| f.write(YAML.dump(cache)) } +  rescue +  end + +  def cache_store(file, data) +    load_cache + +    @cache[file] = {:data => data, :stored => Time.now.to_i} +  rescue +  end + +  def cache_lookup(file) +    cache = load_cache + +    return nil if cache.empty? + +    ttl = cache_time(file) + +    if cache[file] +      now = Time.now.to_i + +      return cache[file][:data] if ttl == -1 +      return cache[file][:data] if (now - cache[file][:stored]) <= ttl +      return nil +    else +      return nil +    end +  rescue +    return nil +  end + +  def cache_time(file) +    meta = file + ".ttl" + +    return File.read(meta).chomp.to_i +  rescue +    return 0 +  end + +  def load_cache +    unless @cache +      if File.exist?(@cache_file) +        @cache = YAML.load_file(@cache_file) +      else +        @cache = {} +      end +    end + +    return @cache +  rescue +    @cache = {} +    return @cache +  end + +  def create +    entries.each do |fact| +      type = fact_type(fact) +      parser = "#{type}_parser" + +      if respond_to?("#{type}_parser") +        Facter.debug("Parsing #{fact} using #{parser}") + +        send(parser, fact) +      end +    end +  end +end + + +mdata = Facter.version.match(/(\d+)\.(\d+)\.(\d+)/) +if mdata +  (major, minor, patch) = mdata.captures.map { |v| v.to_i } +  if major < 2 +    # Facter 1.7 introduced external facts support directly +    unless major == 1 and minor > 6 +      Facter::Util::DotD.new("/etc/facter/facts.d").create +      Facter::Util::DotD.new("/etc/puppetlabs/facter/facts.d").create + +      # Windows has a different configuration directory that defaults to a vendor +      # specific sub directory of the %COMMON_APPDATA% directory. +      if Dir.const_defined? 'COMMON_APPDATA' then +        windows_facts_dot_d = File.join(Dir::COMMON_APPDATA, 'PuppetLabs', 'facter', 'facts.d') +        Facter::Util::DotD.new(windows_facts_dot_d).create +      end +    end +  end +end diff --git a/puppet/modules/stdlib/lib/facter/netmask_cidr_interface.rb b/puppet/modules/stdlib/lib/facter/netmask_cidr_interface.rb new file mode 100644 index 00000000..d628d08c --- /dev/null +++ b/puppet/modules/stdlib/lib/facter/netmask_cidr_interface.rb @@ -0,0 +1,22 @@ +# adds netmask facts for each interface in cidr notation +# i.e.: +# ... +# netmask_cidr_eth2 => 24 +# netmask_cidr_lo => 8 +# netmask_cidr_tun0 => 32 +# netmask_cidr_virbr0 => 24 +# ... + +require 'facter/util/ip' + +Facter::Util::IP.get_interfaces.each do |interface| +  netmask = Facter.value("netmask_#{interface}") +  if netmask != nil +    Facter.add("netmask_cidr_" + interface ) do +      setcode do +        cidr_netmask=IPAddr.new(netmask).to_i.to_s(2).count("1") +        cidr_netmask +      end +    end +  end +end diff --git a/puppet/modules/stdlib/lib/facter/pe_version.rb b/puppet/modules/stdlib/lib/facter/pe_version.rb new file mode 100644 index 00000000..0cc0f64e --- /dev/null +++ b/puppet/modules/stdlib/lib/facter/pe_version.rb @@ -0,0 +1,53 @@ +# Fact: is_pe, pe_version, pe_major_version, pe_minor_version, pe_patch_version +# +# Purpose: Return various facts about the PE state of the system +# +# Resolution: Uses a regex match against puppetversion to determine whether the +#   machine has Puppet Enterprise installed, and what version (overall, major, +#   minor, patch) is installed. +# +# Caveats: +# +Facter.add("pe_version") do +  setcode do +    pe_ver = Facter.value("puppetversion").match(/Puppet Enterprise (\d+\.\d+\.\d+)/) +    pe_ver[1] if pe_ver +  end +end + +Facter.add("is_pe") do +  setcode do +    if Facter.value(:pe_version).to_s.empty? then +      false +    else +      true +    end +  end +end + +Facter.add("pe_major_version") do +  confine :is_pe => true +  setcode do +    if pe_version = Facter.value(:pe_version) +      pe_version.to_s.split('.')[0] +    end +  end +end + +Facter.add("pe_minor_version") do +  confine :is_pe => true +  setcode do +    if pe_version = Facter.value(:pe_version) +      pe_version.to_s.split('.')[1] +    end +  end +end + +Facter.add("pe_patch_version") do +  confine :is_pe => true +  setcode do +    if pe_version = Facter.value(:pe_version) +      pe_version.to_s.split('.')[2] +    end +  end +end diff --git a/puppet/modules/stdlib/lib/facter/puppet_vardir.rb b/puppet/modules/stdlib/lib/facter/puppet_vardir.rb new file mode 100644 index 00000000..0e6af40e --- /dev/null +++ b/puppet/modules/stdlib/lib/facter/puppet_vardir.rb @@ -0,0 +1,26 @@ +# 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. + + +begin +  require 'facter/util/puppet_settings' +rescue LoadError => e +  # puppet apply does not add module lib directories to the $LOAD_PATH (See +  # #4248). It should (in the future) but for the time being we need to be +  # defensive which is what this rescue block is doing. +  rb_file = File.join(File.dirname(__FILE__), 'util', 'puppet_settings.rb') +  load rb_file if File.exists?(rb_file) or raise e +end + +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 diff --git a/puppet/modules/stdlib/lib/facter/root_home.rb b/puppet/modules/stdlib/lib/facter/root_home.rb new file mode 100644 index 00000000..b4f87ff2 --- /dev/null +++ b/puppet/modules/stdlib/lib/facter/root_home.rb @@ -0,0 +1,32 @@ +# A facter fact to determine the root home directory. +# This varies on PE supported platforms and may be +# reconfigured by the end user. + +module Facter::Util::RootHome +  class << self +  def get_root_home +    root_ent = Facter::Util::Resolution.exec("getent passwd root") +    # The home directory is the sixth element in the passwd entry +    # If the platform doesn't have getent, root_ent will be nil and we should +    # return it straight away. +    root_ent && root_ent.split(":")[5] +  end +  end +end + +Facter.add(:root_home) do +  setcode { Facter::Util::RootHome.get_root_home } +end + +Facter.add(:root_home) do +  confine :kernel => :darwin +  setcode do +    str = Facter::Util::Resolution.exec("dscacheutil -q user -a name root") +    hash = {} +    str.split("\n").each do |pair| +      key,value = pair.split(/:/) +      hash[key] = value +    end +    hash['dir'].strip +  end +end diff --git a/puppet/modules/stdlib/lib/facter/util/puppet_settings.rb b/puppet/modules/stdlib/lib/facter/util/puppet_settings.rb new file mode 100644 index 00000000..1ad94521 --- /dev/null +++ b/puppet/modules/stdlib/lib/facter/util/puppet_settings.rb @@ -0,0 +1,21 @@ +module Facter +  module Util +    module PuppetSettings +      # This method is intended to provide a convenient way to evaluate a +      # Facter code block only if Puppet is loaded.  This is to account for the +      # situation where the fact happens to be in the load path, but Puppet is +      # not loaded for whatever reason.  Perhaps the user is simply running +      # facter without the --puppet flag and they happen to be working in a lib +      # directory of a module. +      def self.with_puppet +        begin +          Module.const_get("Puppet") +        rescue NameError +          nil +        else +          yield +        end +      end +    end +  end +end | 
