diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/http.rb | 39 | ||||
-rw-r--r-- | lib/chef/http/api_versions.rb | 3 | ||||
-rw-r--r-- | lib/chef/http/authenticator.rb | 21 | ||||
-rw-r--r-- | lib/chef/mixin/versioned_api.rb | 4 |
4 files changed, 61 insertions, 6 deletions
diff --git a/lib/chef/http.rb b/lib/chef/http.rb index 12acae953c..c741dcca97 100644 --- a/lib/chef/http.rb +++ b/lib/chef/http.rb @@ -142,13 +142,26 @@ class Chef # Makes an HTTP request to +path+ with the given +method+, +headers+, and # +data+ (if applicable). def request(method, path, headers = {}, data = false) + http_attempts ||= 0 url = create_url(path) method, url, headers, data = apply_request_middleware(method, url, headers, data) response, rest_request, return_value = send_http_request(method, url, headers, data) response, rest_request, return_value = apply_response_middleware(response, rest_request, return_value) + response.error! unless success_response?(response) return_value + + rescue Net::HTTPServerException => e + http_attempts += 1 + response = e.response + if response.kind_of?(Net::HTTPNotAcceptable) && version_retries - http_attempts > 0 + Chef::Log.debug("Negotiating protocol version with #{url}, retry #{http_attempts}/#{version_retries}") + sleep(http_retry_delay) + retry + else + raise + end rescue Exception => exception log_failed_request(response, return_value) unless response.nil? @@ -159,6 +172,7 @@ class Chef end def streaming_request_with_progress(path, headers = {}, &progress_block) + http_attempts ||= 0 url = create_url(path) response, rest_request, return_value = nil, nil, nil tempfile = nil @@ -177,6 +191,16 @@ class Chef response.error! end tempfile + rescue Net::HTTPServerException => e + http_attempts += 1 + response = e.response + if response.kind_of?(Net::HTTPNotAcceptable) && version_retries - http_attempts > 0 + Chef::Log.debug("Negotiating protocol version with #{url}, retry #{http_attempts}/#{version_retries}") + sleep(http_retry_delay) + retry + else + raise + end rescue Exception => e log_failed_request(response, return_value) unless response.nil? if e.respond_to?(:chef_rest_request=) @@ -195,6 +219,7 @@ class Chef # @yield [tempfile] block to process the tempfile # @yieldparams [tempfile<Tempfile>] tempfile def streaming_request(path, headers = {}) + http_attempts ||= 0 url = create_url(path) response, rest_request, return_value = nil, nil, nil tempfile = nil @@ -222,6 +247,16 @@ class Chef end end tempfile + rescue Net::HTTPServerException => e + http_attempts += 1 + response = e.response + if response.kind_of?(Net::HTTPNotAcceptable) && version_retries - http_attempts > 0 + Chef::Log.debug("Negotiating protocol version with #{url}, retry #{http_attempts}/#{version_retries}") + sleep(http_retry_delay) + retry + else + raise + end rescue Exception => e log_failed_request(response, return_value) unless response.nil? if e.respond_to?(:chef_rest_request=) @@ -413,6 +448,10 @@ class Chef end end + def version_retries + @version_retries ||= options[:version_class].possible_requests + end + # @api private def http_retry_delay config[:http_retry_delay] diff --git a/lib/chef/http/api_versions.rb b/lib/chef/http/api_versions.rb index 696c7072bf..674d8f85a7 100644 --- a/lib/chef/http/api_versions.rb +++ b/lib/chef/http/api_versions.rb @@ -32,6 +32,9 @@ class Chef end def handle_response(http_response, rest_request, return_value) + if http_response.code == "406" + ServerAPIVersions.instance.reset! + end if http_response.key?("x-ops-server-api-version") ServerAPIVersions.instance.set_versions(JSONCompat.parse(http_response["x-ops-server-api-version"])) end diff --git a/lib/chef/http/authenticator.rb b/lib/chef/http/authenticator.rb index 84065bf816..65367af107 100644 --- a/lib/chef/http/authenticator.rb +++ b/lib/chef/http/authenticator.rb @@ -30,6 +30,8 @@ class Chef attr_reader :raw_key attr_reader :attr_names attr_reader :auth_credentials + attr_reader :version_class + attr_reader :api_version attr_accessor :sign_request @@ -39,15 +41,12 @@ class Chef @signing_key_filename = opts[:signing_key_filename] @key = load_signing_key(opts[:signing_key_filename], opts[:raw_key]) @auth_credentials = AuthCredentials.new(opts[:client_name], @key) - if opts[:api_version] - @api_version = opts[:api_version] - else - @api_version = DEFAULT_SERVER_API_VERSION - end + @version_class = opts[:version_class] + @api_version = opts[:api_version] end def handle_request(method, url, headers = {}, data = false) - headers["X-Ops-Server-API-Version"] = @api_version + headers["X-Ops-Server-API-Version"] = request_version headers.merge!(authentication_headers(method, url, data, headers)) if sign_requests? [method, url, headers, data] end @@ -64,6 +63,16 @@ class Chef [http_response, rest_request, return_value] end + def request_version + if version_class + version_class.best_request_version + elsif api_version + api_version + else + DEFAULT_SERVER_API_VERSION + end + end + def sign_requests? auth_credentials.sign_requests? && @sign_request end diff --git a/lib/chef/mixin/versioned_api.rb b/lib/chef/mixin/versioned_api.rb index 3015345d44..17c9838d29 100644 --- a/lib/chef/mixin/versioned_api.rb +++ b/lib/chef/mixin/versioned_api.rb @@ -70,6 +70,10 @@ class Chef klass.minimum_api_version.to_s end + def possible_requests + versioned_interfaces.length + end + def new(*args) object = versioned_api_class.allocate object.send(:initialize, *args) |