Class: Puppet::Node::Facts::DiffPuppetdb
- Inherits:
-
Indirector::REST
- Object
- Indirector::REST
- Puppet::Node::Facts::DiffPuppetdb
- Includes:
- Util::Puppetdb, Util::Puppetdb::CommandNames
- Defined in:
- lib/puppet/indirector/facts/diff_puppetdb.rb
Overview
A copy of the 2.x PuppetDB Facts terminus that performs find requests using the v4 API so that non-stringified and structured facts are returned. This is done because many comparisons executed by the future parser are type-sensitive. Without fully-typed facts, a variable containing a stringified fact (such as $::processorcount) will raise a fatal error when compared against an integer.
TODO: Remove once Puppet 4.0 or PuppetDB 3.0 are standard and backwards compatibility with PE 3.x isn’t required.
Instance Method Summary collapse
- #find(request) ⇒ Object
- #get_trusted_info(node) ⇒ Object
- #headers ⇒ Object
- #save(request) ⇒ Object
-
#search(request) ⇒ Object
Search for nodes matching a set of fact constraints.
Instance Method Details
#find(request) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/puppet/indirector/facts/diff_puppetdb.rb', line 53 def find(request) profile('facts#find', [:puppetdb, :facts, :find, request.key]) do begin url = Puppet::Util::Puppetdb.url_path("/v4/nodes/#{CGI.escape(request.key)}/facts") response = profile("Query for nodes facts: #{url}", [:puppetdb, :facts, :find, :query_nodes, request.key]) do http_get(request, url, headers) end log_x_deprecation_header(response) if response.is_a? Net::HTTPSuccess profile("Parse fact query response (size: #{response.body.size})", [:puppetdb, :facts, :find, :parse_response, request.key]) do result = JSON.parse(response.body) # Note: the Inventory Service API appears to expect us to return nil here # if the node isn't found. However, PuppetDB returns an empty array in # this case; for now we will just look for that condition and assume that # it means that the node wasn't found, so we will return nil. In the # future we may want to improve the logic such that we can distinguish # between the "node not found" and the "no facts for this node" cases. if result.empty? return nil end facts = result.inject({}) do |a,h| a.merge(h['name'] => h['value']) end Puppet::Node::Facts.new(request.key, facts) end else # Newline characters cause an HTTP error, so strip them raise "[#{response.code} #{response.}] #{response.body.gsub(/[\r\n]/, '')}" end rescue => e raise Puppet::Error, "Failed to find facts from PuppetDB at #{self.class.server}:#{self.class.port}: #{e}" end end end |
#get_trusted_info(node) ⇒ Object
21 22 23 24 25 26 |
# File 'lib/puppet/indirector/facts/diff_puppetdb.rb', line 21 def get_trusted_info(node) trusted = Puppet.lookup(:trusted_information) do Puppet::Context::TrustedInformation.local(node) end trusted.to_h end |
#headers ⇒ Object
149 150 151 152 153 154 |
# File 'lib/puppet/indirector/facts/diff_puppetdb.rb', line 149 def headers { 'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8', } end |
#save(request) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/puppet/indirector/facts/diff_puppetdb.rb', line 28 def save(request) profile('facts#save', [:puppetdb, :facts, :save, request.key]) do payload = profile('Encode facts command submission payload', [:puppetdb, :facts, :encode]) do facts = request.instance.dup facts.values = facts.strip_internal.dup if ! Puppet::Util::Puppetdb.puppet3compat? || Puppet[:trusted_node_data] facts.values[:trusted] = get_trusted_info(request.node) end { 'name' => facts.name, 'values' => facts.values, # PDB-453: we call to_s to avoid a 'stack level too deep' error # when we attempt to use ActiveSupport 2.3.16 on RHEL 5 with # legacy storeconfigs. 'environment' => request.[:environment] || request.environment.to_s, 'producer-timestamp' => request.[:producer_timestamp] || Time.now.iso8601, } end submit_command(request.key, payload, CommandReplaceFacts, 3) end end |
#search(request) ⇒ Object
Search for nodes matching a set of fact constraints. The constraints are specified as a hash of the form:
‘=> value`
The only accepted ‘type` is ’facts’.
‘name` must be the fact name to query against.
‘operator` may be one of {eq, ne, lt, gt, le, ge, and will default to ’eq’ if unspecified.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/puppet/indirector/facts/diff_puppetdb.rb', line 102 def search(request) profile('facts#search', [:puppetdb, :facts, :search, request.key]) do return [] unless request. operator_map = { 'eq' => '=', 'gt' => '>', 'lt' => '<', 'ge' => '>=', 'le' => '<=', } filters = request..sort.map do |key,value| type, name, operator = key.to_s.split('.') operator ||= 'eq' raise Puppet::Error, "Fact search against keys of type '#{type}' is unsupported" unless type == 'facts' if operator == 'ne' ['not', ['=', ['fact', name], value]] else [operator_map[operator], ['fact', name], value] end end query = ['and'] + filters query_param = CGI.escape(query.to_json) begin url = Puppet::Util::Puppetdb.url_path("/v3/nodes?query=#{query_param}") response = profile("Fact query request: #{URI.unescape(url)}", [:puppetdb, :facts, :search, :query_request, request.key]) do http_get(request, url, headers) end log_x_deprecation_header(response) if response.is_a? Net::HTTPSuccess profile("Parse fact query response (size: #{response.body.size})", [:puppetdb, :facts, :search, :parse_query_response, request.key,]) do JSON.parse(response.body).collect {|s| s['name']} end else # Newline characters cause an HTTP error, so strip them raise "[#{response.code} #{response.}] #{response.body.gsub(/[\r\n]/, '')}" end rescue => e raise Puppet::Error, "Could not perform inventory search from PuppetDB at #{self.class.server}:#{self.class.port}: #{e}" end end end |