diff --git a/lib/puppet/indirector/facts/facter.rb b/lib/puppet/indirector/facts/facter.rb index 7f65e3488..df71b5677 100644 --- a/lib/puppet/indirector/facts/facter.rb +++ b/lib/puppet/indirector/facts/facter.rb @@ -1,78 +1,82 @@ require 'puppet/node/facts' require 'puppet/indirector/code' class Puppet::Node::Facts::Facter < Puppet::Indirector::Code desc "Retrieve facts from Facter. This provides a somewhat abstract interface between Puppet and Facter. It's only `somewhat` abstract because it always returns the local host's facts, regardless of what you attempt to find." + def allow_remote_requests? + false + end + def destroy(facts) raise Puppet::DevError, 'You cannot destroy facts in the code store; it is only used for getting facts from Facter' end def save(facts) raise Puppet::DevError, 'You cannot save facts to the code store; it is only used for getting facts from Facter' end # Lookup a host's facts up in Facter. def find(request) Facter.reset self.class.setup_external_search_paths(request) if Puppet.features.external_facts? self.class.setup_search_paths(request) result = Puppet::Node::Facts.new(request.key, Facter.to_hash) result.add_local_facts Puppet[:stringify_facts] ? result.stringify : result.sanitize result end private def self.setup_search_paths(request) # Add any per-module fact directories to facter's search path dirs = request.environment.modulepath.collect do |dir| ['lib', 'plugins'].map do |subdirectory| Dir.glob("#{dir}/*/#{subdirectory}/facter") end end.flatten + Puppet[:factpath].split(File::PATH_SEPARATOR) dirs = dirs.select do |dir| next false unless FileTest.directory?(dir) # Even through we no longer directly load facts in the terminus, # print out each .rb in the facts directory as module # developers may find that information useful for debugging purposes if Puppet::Util::Log.sendlevel?(:info) Puppet.info "Loading facts" Dir.glob("#{dir}/*.rb").each do |file| Puppet.debug "Loading facts from #{file}" end end true end Facter.search *dirs end def self.setup_external_search_paths(request) # Add any per-module external fact directories to facter's external search path dirs = [] request.environment.modules.each do |m| if m.has_external_facts? dir = m.plugin_fact_directory Puppet.debug "Loading external facts from #{dir}" dirs << dir end end # Add system external fact directory if it exists if FileTest.directory?(Puppet[:pluginfactdest]) dir = Puppet[:pluginfactdest] Puppet.debug "Loading external facts from #{dir}" dirs << dir end Facter.search_external dirs end end diff --git a/lib/puppet/indirector/facts/network_device.rb b/lib/puppet/indirector/facts/network_device.rb index 2c8da947f..5e3ad4b16 100644 --- a/lib/puppet/indirector/facts/network_device.rb +++ b/lib/puppet/indirector/facts/network_device.rb @@ -1,24 +1,28 @@ require 'puppet/node/facts' require 'puppet/indirector/code' class Puppet::Node::Facts::NetworkDevice < Puppet::Indirector::Code desc "Retrieve facts from a network device." + def allow_remote_requests? + false + end + # Look a device's facts up through the current device. def find(request) result = Puppet::Node::Facts.new(request.key, Puppet::Util::NetworkDevice.current.facts) result.add_local_facts Puppet[:stringify_facts] ? result.stringify : result.sanitize result end def destroy(facts) raise Puppet::DevError, "You cannot destroy facts in the code store; it is only used for getting facts from a remote device" end def save(facts) raise Puppet::DevError, "You cannot save facts to the code store; it is only used for getting facts from a remote device" end end diff --git a/lib/puppet/indirector/facts/store_configs.rb b/lib/puppet/indirector/facts/store_configs.rb index 247898f0b..1bc631689 100644 --- a/lib/puppet/indirector/facts/store_configs.rb +++ b/lib/puppet/indirector/facts/store_configs.rb @@ -1,8 +1,11 @@ require 'puppet/node/facts' require 'puppet/indirector/store_configs' class Puppet::Node::Facts::StoreConfigs < Puppet::Indirector::StoreConfigs desc %q{Part of the "storeconfigs" feature. Should not be directly set by end users.} + def allow_remote_requests? + false + end end diff --git a/lib/puppet/indirector/facts/yaml.rb b/lib/puppet/indirector/facts/yaml.rb index 65bd78354..94efe3103 100644 --- a/lib/puppet/indirector/facts/yaml.rb +++ b/lib/puppet/indirector/facts/yaml.rb @@ -1,82 +1,86 @@ require 'puppet/node/facts' require 'puppet/indirector/yaml' class Puppet::Node::Facts::Yaml < Puppet::Indirector::Yaml desc "Store client facts as flat files, serialized using YAML, or return deserialized facts from disk." + def allow_remote_requests? + false + end + def search(request) node_names = [] Dir.glob(yaml_dir_path).each do |file| facts = YAML.load_file(file) node_names << facts.name if node_matches?(facts, request.options) end node_names end private # Return the path to a given node's file. def yaml_dir_path base = Puppet.run_mode.master? ? Puppet[:yamldir] : Puppet[:clientyamldir] File.join(base, 'facts', '*.yaml') end def node_matches?(facts, options) options.each do |key, value| type, name, operator = key.to_s.split(".") operator ||= 'eq' return false unless node_matches_option?(type, name, operator, value, facts) end return true end def node_matches_option?(type, name, operator, value, facts) case type when "meta" case name when "timestamp" compare_timestamp(operator, facts.timestamp, Time.parse(value)) end when "facts" compare_facts(operator, facts.values[name], value) end end def compare_facts(operator, value1, value2) return false unless value1 case operator when "eq" value1.to_s == value2.to_s when "le" value1.to_f <= value2.to_f when "ge" value1.to_f >= value2.to_f when "lt" value1.to_f < value2.to_f when "gt" value1.to_f > value2.to_f when "ne" value1.to_s != value2.to_s end end def compare_timestamp(operator, value1, value2) case operator when "eq" value1 == value2 when "le" value1 <= value2 when "ge" value1 >= value2 when "lt" value1 < value2 when "gt" value1 > value2 when "ne" value1 != value2 end end end