From f9d2c0b518bfd3b635afd28aa4b0abdfb86e58ab Mon Sep 17 00:00:00 2001 From: Andreas Ntaflos Date: Tue, 12 Mar 2019 17:43:16 +0100 Subject: [PATCH] Avoid processing fact yaml files with empty 'values' hash 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. --- files/external_node_v2.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/files/external_node_v2.rb b/files/external_node_v2.rb index 87fa02b17..7af418728 100644 --- a/files/external_node_v2.rb +++ b/files/external_node_v2.rb @@ -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 @@ -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]