class Proxy::Reports::AnsibleProcessor

Constants

KEYS_TO_COPY

Public Class Methods

new(data, json_body: true) click to toggle source
Calls superclass method
# File lib/smart_proxy_reports/ansible_processor.rb, line 9
def initialize(data, json_body: true)
  super(data, json_body: json_body)
  measure :parse do
    @data = JSON.parse(data)
  end
  @body = {}
  @failure = 0
  @change = 0
  @nochange = 0
  logger.debug "Processing report #{report_id}"
  debug_payload("Input", @data)
end

Public Instance Methods

build_facts() click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 120
def build_facts
  facts = find_facts_task
  return nil unless facts
  {
    "name" => hostname_from_config || @data["host"],
    "facts" => {
      "ansible_facts" => facts,
      "_type" => "ansible",
      "_timestamp" => @data["reported_at"],
    },
  }
end
build_report() click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 73
def build_report
  process
  if debug_payload?
    logger.debug { JSON.pretty_generate(@body) }
  end
  build_report_root(
    format: "ansible",
    version: 1,
    host: @body["host"],
    proxy: @body["proxy"],
    change: @body["summary"]["foreman"]["change"],
    nochange: @body["summary"]["foreman"]["nochange"],
    failure: @body["summary"]["foreman"]["failure"],
    keywords: @body["keywords"],
    body: @body,
  )
end
count_summary(result) click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 26
def count_summary(result)
  if result["result"]["changed"]
    @change += 1
  else
    @nochange += 1
  end
  if result["failed"]
    @failure += 1
  end
end
find_facts_task() click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 111
def find_facts_task
  @data["results"]&.each do |result|
    if result["result"] && result["result"]["ansible_facts"]
      return result["result"]["ansible_facts"]
    end
  end
  false
end
process() click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 53
def process
  @body["format"] = "ansible"
  @body["id"] = report_id
  @body["host"] = hostname_from_config || @data["host"]
  @body["proxy"] = Proxy::Reports::Plugin.settings.reported_proxy_hostname
  @body["reported_at"] = @data["reported_at"]
  @body["reported_at_proxy"] = now_utc
  measure :process_results do
    @body["results"] = process_results
  end
  @body["summary"] = build_summary
  process_root_keywords
  @body["keywords"] = keywords
  @body["telemetry"] = telemetry
  @body["errors"] = errors if errors?
  KEYS_TO_COPY.each do |key|
    @body[key] = @data[key]
  end
end
process_results() click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 37
def process_results
  @data["results"]&.each do |result|
    raise("Report do not contain required 'results/result' element") unless result["result"]
    raise("Report do not contain required 'results/task' element") unless result["task"]
    process_level(result)
    friendly_message = FriendlyMessage.new(result)
    result["friendly_message"] = friendly_message.generate_message
    process_keywords(result)
    count_summary(result)
  end
  @data["results"]
rescue StandardError => e
  log_error("Unable to parse results", e)
  @data["results"]
end
report_id() click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 22
def report_id
  @data["uuid"] || generated_report_id
end
spool_report() click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 91
def spool_report
  facts_hash = measure :build_facts do
    build_facts
  end
  if facts_hash
    debug_payload("Facts output", facts_hash)
    payload = measure :format_facts do
      facts_hash.to_json
    end
    SpooledHttpClient.instance.spool(:ansible_facts, payload)
  end

  report_hash = build_report
  debug_payload("Output", report_hash)
  payload = measure :format do
    report_hash.to_json
  end
  SpooledHttpClient.instance.spool(:report, payload)
end

Private Instance Methods

build_summary() click to toggle source

foreman-ansible-modules 3.0 does not contain summary field, convert it here github.com/theforeman/foreman-ansible-modules/pull/1325/files

# File lib/smart_proxy_reports/ansible_processor.rb, line 137
def build_summary
  if @data["summary"]
    native = @data["summary"]
  elsif (status = @data["status"])
    native = {
      "changed" => status["applied"] || 0,
      "failures" => status["failed"] || 0,
      "ignored" => 0,
      "ok" => 0,
      "rescued" => 0,
      "skipped" => status["skipped"] || 0,
      "unreachable" => 0,
    }
  else
    native = {}
  end
  {
    "foreman" => {
      "change" => @change, "nochange" => @nochange, "failure" => @failure,
    },
    "native" => native,
  }
rescue StandardError => e
  log_error("Unable to build summary", e)
  {
    "foreman" => {
      "change" => @change, "nochange" => @nochange, "failure" => @failure,
    },
    "native" => {},
  }
end
process_keywords(result) click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 189
def process_keywords(result)
  if result["failed"]
    add_keywords("AnsibleFailure", "AnsibleFailure:#{result["task"]["action"]}")
  elsif result["result"]["changed"]
    add_keywords("AnsibleChanged")
  end
rescue StandardError => e
  log_error("Unable to parse keywords", e)
end
process_level(result) click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 199
def process_level(result)
  if result["failed"]
    result["level"] = "err"
  elsif result["result"]["changed"]
    result["level"] = "notice"
  else
    result["level"] = "info"
  end
rescue StandardError => e
  log_error("Unable to parse log level", e)
  result["level"] = "info"
end
process_root_keywords() click to toggle source
# File lib/smart_proxy_reports/ansible_processor.rb, line 169
def process_root_keywords
  if (summary = @body["summary"])
    if summary["changed"] && summary["changed"] > 0
      add_keywords("AnsibleChanged")
    elsif summary["failures"] && summary["failures"] > 0
      add_keywords("AnsibleFailures")
    elsif summary["unreachable"] && summary["unreachable"] > 0
      add_keywords("AnsibleUnreachable")
    elsif summary["rescued"] && summary["rescued"] > 0
      add_keywords("AnsibleRescued")
    elsif summary["ignored"] && summary["ignored"] > 0
      add_keywords("AnsibleIgnored")
    elsif summary["skipped"] && summary["skipped"] > 0
      add_keywords("AnsibleSkipped")
    end
  end
rescue StandardError => e
  log_error("Unable to parse root summary keywords", e)
end