Skip to content

Commit

Permalink
Avoid processing fact yaml files with empty 'values' hash
Browse files Browse the repository at this point in the history
Under certain conditions it can happen that Puppet Server creates a fact
yaml file for a node that contains an empty `values` hash, for example
when multiple Puppet Servers are accessed through a load balancer like
HAProxy where Puppet agent requests are distributed equally and randomly.

When trying to process such a facts file with an empty `values` hash
Foreman will reject the HTTP request with an error message like this:

    During the fact upload the server responded with: 422 Unprocessable Entity. Error is ignored and the execution continues.
    {"message":"ERF42-3829 [Foreman::Exception]: invalid facts, missing operating system value"}

This change adds a simple method that loads the fact yaml file and
returns true if the `values` hash is empty. Such fact yaml files are
then skipped when processing host facts and a warning is written to
STDOUT. The Puppet administrator can then examine and delete any invalid
fact yaml files.
  • Loading branch information
antaflos committed Mar 12, 2019
1 parent a32fa64 commit 72aea85
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions files/external_node_v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,21 @@ class FactUploadError < StandardError; end
end
end

def empty_values_hash?(facts_file)
facts = File.read(facts_file)
puppet_facts = YAML::load(facts.gsub(/\!ruby\/object.*$/,''))

puppet_facts['values'].empty?
end

def process_host_facts(certname)
f = "#{puppetdir}/yaml/facts/#{certname}.yaml"
if File.size(f) != 0
if empty_values_hash?(f)
puts "Empty values hash in fact file #{f}, not uploading"
return 0
end

req = generate_fact_request(certname, f)
begin
upload_facts(certname, req) if req
Expand All @@ -115,6 +127,10 @@ def process_all_facts(http_requests)
certname = File.basename(f, ".yaml")
# Skip empty host fact yaml files
if File.size(f) != 0
if empty_values_hash?(f)
puts "Empty values hash in fact file #{f}, not uploading"
next
end
req = generate_fact_request(certname, f)
if http_requests
http_requests << [certname, req]
Expand Down

0 comments on commit 72aea85

Please sign in to comment.