Class: Chef::Formatters::ErrorInspectors::CookbookResolveErrorInspector
- Inherits:
-
Object
- Object
- Chef::Formatters::ErrorInspectors::CookbookResolveErrorInspector
- Includes:
- APIErrorFormatting
- Defined in:
- lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb
Constant Summary
Constants included from APIErrorFormatting
APIErrorFormatting::NETWORK_ERROR_CLASSES
Instance Attribute Summary collapse
-
#exception ⇒ Object
readonly
Returns the value of attribute exception.
-
#expanded_run_list ⇒ Object
readonly
Returns the value of attribute expanded_run_list.
Instance Method Summary collapse
- #add_explanation(error_description) ⇒ Object
- #describe_412_error(error_description) ⇒ Object
- #expanded_run_list_ul ⇒ Object
-
#extract_412_error_message ⇒ Object
In my tests, the error from the server is double JSON encoded, but we should not rely on this not getting fixed.
- #humanize_http_exception(error_description) ⇒ Object
-
#initialize(expanded_run_list, exception) ⇒ CookbookResolveErrorInspector
constructor
A new instance of CookbookResolveErrorInspector.
Methods included from APIErrorFormatting
#api_key, #clock_skew?, #describe_400_error, #describe_401_error, #describe_406_error, #describe_500_error, #describe_503_error, #describe_eof_error, #describe_http_error, #describe_network_errors, #format_rest_error, #safe_format_rest_error, #server_url, #username
Constructor Details
#initialize(expanded_run_list, exception) ⇒ CookbookResolveErrorInspector
Returns a new instance of CookbookResolveErrorInspector.
31 32 33 34 |
# File 'lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb', line 31 def initialize(, exception) @expanded_run_list = @exception = exception end |
Instance Attribute Details
#exception ⇒ Object (readonly)
Returns the value of attribute exception.
26 27 28 |
# File 'lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb', line 26 def exception @exception end |
#expanded_run_list ⇒ Object (readonly)
Returns the value of attribute expanded_run_list.
27 28 29 |
# File 'lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb', line 27 def @expanded_run_list end |
Instance Method Details
#add_explanation(error_description) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb', line 36 def add_explanation(error_description) case exception when Net::HTTPClientException, Net::HTTPFatalError humanize_http_exception(error_description) when EOFError describe_eof_error(error_description) when *NETWORK_ERROR_CLASSES describe_network_errors(error_description) else error_description.section("Unexpected Error:", "#{exception.class.name}: #{exception.}") end end |
#describe_412_error(error_description) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb', line 84 def describe_412_error(error_description) explanation = "" error_reasons = # Prepare the error message if there is detailed information # about individual cookbooks. if !error_reasons.respond_to?(:key?) explanation << error_reasons.to_s else if error_reasons.key?("non_existent_cookbooks") && !Array(error_reasons["non_existent_cookbooks"]).empty? explanation << "The following cookbooks are required by the client but don't exist on the server:\n" Array(error_reasons["non_existent_cookbooks"]).each do |cookbook| explanation << "* #{cookbook}\n" end explanation << "\n" end if error_reasons.key?("cookbooks_with_no_versions") && !Array(error_reasons["cookbooks_with_no_versions"]).empty? explanation << "The following cookbooks exist on the server, but there is no version that meets\nthe version constraints in this environment:\n" Array(error_reasons["cookbooks_with_no_versions"]).each do |cookbook| explanation << "* #{cookbook}\n" end explanation << "\n" end end if !explanation.empty? error_description.section("Missing Cookbooks:", explanation) else # If we don't have any cookbook details print a more # generic error message. if error_reasons.respond_to?(:key?) && error_reasons["message"] explanation << "Error message: #{error_reasons["message"]}\n" end explanation << <<~EOM You might be able to resolve this issue with: 1-) Removing cookbook versions that depend on deleted cookbooks. 2-) Removing unused cookbook versions. 3-) Pinning exact cookbook versions using environments. EOM error_description.section("Cookbook dependency resolution error:", explanation) end error_description.section("Expanded Run List:", ) end |
#expanded_run_list_ul ⇒ Object
130 131 132 |
# File 'lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb', line 130 def @expanded_run_list.map { |i| "* #{i}" }.join("\n") end |
#extract_412_error_message ⇒ Object
In my tests, the error from the server is double JSON encoded, but we should not rely on this not getting fixed.
Return should be a Hash like this:
{ "non_existent_cookbooks" => ["nope"],
"cookbooks_with_no_versions" => [],
"message" => "Run list contains invalid items: no such cookbook nope."}
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb', line 141 def # Example: # "{\"error\":[\"{\\\"non_existent_cookbooks\\\":[\\\"nope\\\"],\\\"cookbooks_with_no_versions\\\":[],\\\"message\\\":\\\"Run list contains invalid items: no such cookbook nope.\\\"}\"]}" = attempt_json_parse(exception.response.body) unless .is_a?(Hash) && .key?("error") return .to_s end error_description = Array(["error"]).first if error_description.is_a?(Hash) return error_description end attempt_json_parse(error_description) end |
#humanize_http_exception(error_description) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb', line 49 def humanize_http_exception(error_description) response = exception.response case response when Net::HTTPUnauthorized # TODO: this is where you'd see conflicts b/c of username/clientname stuff describe_401_error(error_description) when Net::HTTPForbidden # TODO: we're rescuing errors from Node.find_or_create # * could be no write on nodes container # * could be no read on the node error_description.section("Authorization Error", <<~E) This client is not authorized to read some of the information required to access its cookbooks (HTTP 403). To access its cookbooks, a client needs to be able to read its environment and all of the cookbooks in its expanded run list. E error_description.section("Expanded Run List:", ) error_description.section("Server Response:", format_rest_error) when Net::HTTPPreconditionFailed describe_412_error(error_description) when Net::HTTPBadRequest describe_400_error(error_description) when Net::HTTPNotFound when Net::HTTPInternalServerError describe_500_error(error_description) when Net::HTTPBadGateway, Net::HTTPServiceUnavailable describe_503_error(error_description) when Net::HTTPNotAcceptable describe_406_error(error_description, response) else describe_http_error(error_description) end end |