class Chef::Formatters::ErrorInspectors::CompileErrorInspector
CompileErrorInspector
¶ ↑
Wraps exceptions that occur during the compile phase of a Chef
run and tries to find the code responsible for the error.
Attributes
exception[R]
path[R]
Public Class Methods
new(path, exception)
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 31 def initialize(path, exception) @path, @exception = path, exception @backtrace_lines_in_cookbooks = nil @file_lines = nil @culprit_backtrace_entry = nil @culprit_line = nil end
Public Instance Methods
add_explanation(error_description)
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 39 def add_explanation(error_description) error_description.section(exception.class.name, exception.message) if found_error_in_cookbooks? traceback = filtered_bt.map { |line| " #{line}" }.join("\n") error_description.section("Cookbook Trace: (most recent call first)", traceback) error_description.section("Relevant File Content:", context) end if exception_message_modifying_frozen? msg = <<-MESSAGE Ruby objects are often frozen to prevent further modifications when they would negatively impact the process (e.g. values inside Ruby's ENV class) or to prevent polluting other objects when default values are passed by reference to many instances of an object (e.g. the empty Array as a Chef resource default, passed by reference to every instance of the resource). Chef uses Object#freeze to ensure the default values of properties inside Chef resources are not modified, so that when a new instance of a Chef resource is created, and Object#dup copies values by reference, the new resource is not receiving a default value that has been by a previous instance of that resource. Instead of modifying an object that contains a default value for all instances of a Chef resource, create a new object and assign it to the resource's parameter, e.g.: fruit_basket = resource(:fruit_basket, 'default') # BAD: modifies 'contents' object for all new fruit_basket instances fruit_basket.contents << 'apple' # GOOD: allocates new array only owned by this fruit_basket instance fruit_basket.contents %w(apple) MESSAGE error_description.section("Additional information:", msg.gsub(/^ {6}/, "")) end end
backtrace_lines_in_cookbooks()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 136 def backtrace_lines_in_cookbooks @backtrace_lines_in_cookbooks ||= begin filters = Array(Chef::Config.cookbook_path).map { |p| /^#{Regexp.escape(p)}/i } r = exception.backtrace.select { |line| filters.any? { |filter| line =~ filter } } Chef::Log.trace("Filtered backtrace of compile error: #{r.join(",")}") r end end
context()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 81 def context context_lines = [] context_lines << "#{culprit_file}:\n\n" Range.new(display_lower_bound, display_upper_bound).each do |i| line_nr = (i + 1).to_s.rjust(3) indicator = (i + 1) == culprit_line ? ">> " : ": " context_lines << "#{line_nr}#{indicator}#{file_lines[i]}" end context_lines.join("") end
culprit_backtrace_entry()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 108 def culprit_backtrace_entry @culprit_backtrace_entry ||= begin bt_entry = filtered_bt.first Chef::Log.trace("Backtrace entry for compile error: '#{bt_entry}'") bt_entry end end
culprit_file()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 124 def culprit_file @culprit_file ||= culprit_backtrace_entry[/^((?:.\:)?[^:]+):(\d+)/, 1] end
culprit_line()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 116 def culprit_line @culprit_line ||= begin line_number = culprit_backtrace_entry[/^(?:.\:)?[^:]+:(\d+)/, 1].to_i Chef::Log.trace("Line number of compile error: '#{line_number}'") line_number end end
display_lower_bound()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 92 def display_lower_bound lower = (culprit_line - 8) lower = 0 if lower < 0 lower end
display_upper_bound()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 98 def display_upper_bound upper = (culprit_line + 8) upper = file_lines.size if upper > file_lines.size upper end
exception_message_modifying_frozen?()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 146 def exception_message_modifying_frozen? exception.message.include?("can't modify frozen") end
file_lines()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 104 def file_lines @file_lines ||= IO.readlines(culprit_file) end
filtered_bt()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 128 def filtered_bt backtrace_lines_in_cookbooks.count > 0 ? backtrace_lines_in_cookbooks : exception.backtrace end
found_error_in_cookbooks?()
click to toggle source
# File lib/chef/formatters/error_inspectors/compile_error_inspector.rb, line 132 def found_error_in_cookbooks? !backtrace_lines_in_cookbooks.empty? end