# class Chef::ResourceReporter

### Constants

PROTOCOL_VERSION

### Attributes

error_descriptions[R]
exception[R]
run_id[R]
status[R]
updated_resources[R]

### Public Class Methods

new(rest_client) click to toggle source

    # File lib/chef/resource_reporter.rb, line 99
    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 = {}
    end

### Public Instance Methods

cookbook_resolution_failed(expanded_run_list, exception) click to toggle source

    # File lib/chef/resource_reporter.rb, line 288
    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 293
    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 255
    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 128
    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.debug(message + reason + reporting_status)
        end
      end

      @reporting_enabled = false
    end

headers(additional_headers = {}) click to toggle source

    # File lib/chef/resource_reporter.rb, line 242
    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 247
    def node_name
      @run_status.node.name
    end

post_reporting_data() click to toggle source

    # File lib/chef/resource_reporter.rb, line 217
    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.debug run_data.inspect
        compressed_data = encode_gzip(run_data.to_json)
        begin
          Chef::Log.debug("Sending compressed run data...")
          # Since we're posting compressed data we can not directly call post_rest which expects JSON
          reporting_url = @rest_client.create_url(resource_history_url)
          @rest_client.raw_http_request(:POST, reporting_url, headers({'Content-Encoding' => 'gzip'}), compressed_data)
        rescue Net::HTTPServerException => e
          if e.response.code.to_s == "400"
            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 400), saving to #{Chef::FileCache.load("failed-reporting-data.json", false)}")
          else
            Chef::Log.error("Failed to post reporting data to server (HTTP #{e.response.code.to_s})")
          end
        end
      else
        Chef::Log.debug("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 259
    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"] = @run_status.node.run_list.to_json
      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

      if exception
        exception_data = {}
        exception_data["class"] = exception.inspect
        exception_data["message"] = exception.message
        exception_data["backtrace"] = exception.backtrace.to_json
        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 298
    def reporting_enabled?
      @reporting_enabled
    end

resource_completed(new_resource) click to toggle source

    # File lib/chef/resource_reporter.rb, line 194
    def resource_completed(new_resource)
      if @pending_update && !nested_resource?(new_resource)
        @pending_update.finish
        @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 164
    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 184
    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 175
    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 170
    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 180
    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 202
    def run_completed(node)
      @status = "success"
      post_reporting_data
    end

run_failed(exception) click to toggle source

    # File lib/chef/resource_reporter.rb, line 207
    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_list_expand_failed(node, exception) click to toggle source

    # File lib/chef/resource_reporter.rb, line 283
    def run_list_expand_failed(node, exception)
      description = Formatters::ErrorMapper.run_list_expand_failed(node, exception)
      @error_descriptions = description.for_json
    end

run_started(run_status) click to toggle source

    # File lib/chef/resource_reporter.rb, line 114
    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_rest(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 251
    def start_time
      @run_status.start_time
    end