class Chef::ResourceReporter
Constants
- PROTOCOL_VERSION
- ResourceReport
Attributes
error_descriptions[R]
exception[R]
status[R]
updated_resources[R]
Public Class Methods
new(rest_client)
click to toggle source
# File lib/chef/resource_reporter.rb, line 101 def initialize(rest_client) if Chef::Config[:enable_reporting] && !Chef::Config[:why_run] @reporting_enabled = true else @reporting_enabled = false end @updated_resources = [] @total_res_count = 0 @pending_update = nil @status = "success" @exception = nil @rest_client = rest_client @error_descriptions = {} @expanded_run_list = {} end
Public Instance Methods
cookbook_resolution_failed(expanded_run_list, exception)
click to toggle source
# File lib/chef/resource_reporter.rb, line 306 def cookbook_resolution_failed(expanded_run_list, exception) description = Formatters::ErrorMapper.cookbook_resolution_failed(expanded_run_list, exception) @error_descriptions = description.for_json end
cookbook_sync_failed(cookbooks, exception)
click to toggle source
# File lib/chef/resource_reporter.rb, line 311 def cookbook_sync_failed(cookbooks, exception) description = Formatters::ErrorMapper.cookbook_sync_failed(cookbooks, exception) @error_descriptions = description.for_json end
end_time()
click to toggle source
# File lib/chef/resource_reporter.rb, line 272 def end_time @run_status.end_time end
handle_error_starting_run(e, url)
click to toggle source
# File lib/chef/resource_reporter.rb, line 131 def handle_error_starting_run(e, url) message = "Reporting error starting run. URL: #{url} " code = if e.response.code e.response.code.to_s else "Exception Code Empty" end if !e.response || (code != "404" && code != "406") exception = "Exception: #{code} " if Chef::Config[:enable_reporting_url_fatals] reporting_status = "Reporting fatals enabled. Aborting run. " Chef::Log.error(message + exception + reporting_status) raise else reporting_status = "Disabling reporting for run." Chef::Log.info(message + exception + reporting_status) end else reason = "Received #{code}. " if code == "406" reporting_status = "Client version not supported. Please update the client. Disabling reporting for run." Chef::Log.info(message + reason + reporting_status) else reporting_status = "Disabling reporting for run." Chef::Log.trace(message + reason + reporting_status) end end @reporting_enabled = false end
headers(additional_headers = {})
click to toggle source
# File lib/chef/resource_reporter.rb, line 259 def headers(additional_headers = {}) options = { "X-Ops-Reporting-Protocol-Version" => PROTOCOL_VERSION } options.merge(additional_headers) end
node_name()
click to toggle source
# File lib/chef/resource_reporter.rb, line 264 def node_name @run_status.node.name end
post_reporting_data()
click to toggle source
# File lib/chef/resource_reporter.rb, line 235 def post_reporting_data if reporting_enabled? run_data = prepare_run_data resource_history_url = "reports/nodes/#{node_name}/runs/#{run_id}" Chef::Log.info("Sending resource update report (run-id: #{run_id})") Chef::Log.trace run_data.inspect compressed_data = encode_gzip(Chef::JSONCompat.to_json(run_data)) Chef::Log.trace("Sending compressed run data...") # Since we're posting compressed data we can not directly call post which expects JSON begin @rest_client.raw_request(:POST, resource_history_url, headers({ "Content-Encoding" => "gzip" }), compressed_data) rescue StandardError => e if e.respond_to? :response Chef::FileCache.store("failed-reporting-data.json", Chef::JSONCompat.to_json_pretty(run_data), 0640) Chef::Log.error("Failed to post reporting data to server (HTTP #{e.response.code}), saving to #{Chef::FileCache.load("failed-reporting-data.json", false)}") else Chef::Log.error("Failed to post reporting data to server (#{e})") end end else Chef::Log.trace("Server doesn't support resource history, skipping resource report.") end end
prepare_run_data()
click to toggle source
# File lib/chef/resource_reporter.rb, line 276 def prepare_run_data run_data = {} run_data["action"] = "end" run_data["resources"] = updated_resources.map do |resource_record| resource_record.for_json end run_data["status"] = @status run_data["run_list"] = Chef::JSONCompat.to_json(@run_status.node.run_list) run_data["total_res_count"] = @total_res_count.to_s run_data["data"] = {} run_data["start_time"] = start_time.to_s run_data["end_time"] = end_time.to_s run_data["expanded_run_list"] = Chef::JSONCompat.to_json(@expanded_run_list) if exception exception_data = {} exception_data["class"] = exception.inspect exception_data["message"] = exception.message exception_data["backtrace"] = Chef::JSONCompat.to_json(exception.backtrace) exception_data["description"] = @error_descriptions run_data["data"]["exception"] = exception_data end run_data end
reporting_enabled?()
click to toggle source
# File lib/chef/resource_reporter.rb, line 316 def reporting_enabled? @reporting_enabled end
resource_completed(new_resource)
click to toggle source
# File lib/chef/resource_reporter.rb, line 197 def resource_completed(new_resource) if @pending_update && !nested_resource?(new_resource) @pending_update.finish # Verify if the resource has sensitive data # and create a new blank resource with only # the name so we can report it back without # sensitive data if @pending_update.new_resource.sensitive klass = @pending_update.new_resource.class resource_name = @pending_update.new_resource.name @pending_update.new_resource = klass.new(resource_name) end @updated_resources << @pending_update @pending_update = nil end end
resource_current_state_loaded(new_resource, action, current_resource)
click to toggle source
# File lib/chef/resource_reporter.rb, line 167 def resource_current_state_loaded(new_resource, action, current_resource) unless nested_resource?(new_resource) @pending_update = ResourceReport.new_with_current_state(new_resource, action, current_resource) end end
resource_failed(new_resource, action, exception)
click to toggle source
# File lib/chef/resource_reporter.rb, line 187 def resource_failed(new_resource, action, exception) @total_res_count += 1 unless nested_resource?(new_resource) @pending_update ||= ResourceReport.new_for_exception(new_resource, action) @pending_update.exception = exception end description = Formatters::ErrorMapper.resource_failed(new_resource, action, exception) @error_descriptions = description.for_json end
resource_skipped(resource, action, conditional)
click to toggle source
# File lib/chef/resource_reporter.rb, line 178 def resource_skipped(resource, action, conditional) @total_res_count += 1 @pending_update = nil unless nested_resource?(resource) end
resource_up_to_date(new_resource, action)
click to toggle source
# File lib/chef/resource_reporter.rb, line 173 def resource_up_to_date(new_resource, action) @total_res_count += 1 @pending_update = nil unless nested_resource?(new_resource) end
resource_updated(new_resource, action)
click to toggle source
# File lib/chef/resource_reporter.rb, line 183 def resource_updated(new_resource, action) @total_res_count += 1 end
run_completed(node)
click to toggle source
# File lib/chef/resource_reporter.rb, line 216 def run_completed(node) @status = "success" post_reporting_data end
run_failed(exception)
click to toggle source
# File lib/chef/resource_reporter.rb, line 221 def run_failed(exception) @exception = exception @status = "failure" # If we failed before we received the run_started callback, there's not much we can do # in terms of reporting if @run_status post_reporting_data end end
run_id()
click to toggle source
# File lib/chef/resource_reporter.rb, line 163 def run_id @run_status.run_id end
run_list_expand_failed(node, exception)
click to toggle source
# File lib/chef/resource_reporter.rb, line 301 def run_list_expand_failed(node, exception) description = Formatters::ErrorMapper.run_list_expand_failed(node, exception) @error_descriptions = description.for_json end
run_list_expanded(run_list_expansion)
click to toggle source
# File lib/chef/resource_reporter.rb, line 231 def run_list_expanded(run_list_expansion) @expanded_run_list = run_list_expansion end
run_started(run_status)
click to toggle source
# File lib/chef/resource_reporter.rb, line 117 def run_started(run_status) @run_status = run_status if reporting_enabled? begin resource_history_url = "reports/nodes/#{node_name}/runs" server_response = @rest_client.post(resource_history_url, { :action => :start, :run_id => run_id, :start_time => start_time.to_s }, headers) rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e handle_error_starting_run(e, resource_history_url) end end end
start_time()
click to toggle source
# File lib/chef/resource_reporter.rb, line 268 def start_time @run_status.start_time end
Private Instance Methods
encode_gzip(data)
click to toggle source
# File lib/chef/resource_reporter.rb, line 330 def encode_gzip(data) "".tap do |out| Zlib::GzipWriter.wrap(StringIO.new(out)) { |gz| gz << data } end end
nested_resource?(new_resource)
click to toggle source
If we are getting messages about a resource while we are in the middle of another resource's update, we assume that the nested resource is just the implementation of a provider, and we want to hide it from the reporting output.
# File lib/chef/resource_reporter.rb, line 326 def nested_resource?(new_resource) @pending_update && @pending_update.new_resource != new_resource end