Module: Kitchen::Driver::Azure::Http
- Defined in:
- lib/kitchen/driver/azure/http.rb
Overview
A very small JSON-over-HTTP helper built on the standard library.
The driver makes a handful of straightforward requests, so this replaces Faraday and its middleware chain rather than depending on them.
Defined Under Namespace
Classes: Response
Constant Summary collapse
- TRANSIENT_ERRORS =
Network-level failures worth retrying rather than surfacing.
[ Net::OpenTimeout, Net::ReadTimeout, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::EPIPE, EOFError, SocketError, OpenSSL::SSL::SSLError, ].freeze
- LINK_LOCAL =
The link-local range, which holds Azure's instance metadata service.
IPAddr.new("169.254.0.0/16").freeze
- OPEN_TIMEOUT =
Seconds to wait for a connection and for a response.
30- READ_TIMEOUT =
120
Class Method Summary collapse
-
.link_local?(host) ⇒ Boolean
private
Whether the host is a link-local address.
-
.perform(uri, request) ⇒ Net::HTTPResponse
private
Sends a request, honouring the proxy environment variables.
-
.proxy_for(uri) ⇒ URI?
private
The proxy to reach a URL through, if any.
-
.request(method:, url:, headers: {}, body: nil) ⇒ Response
Performs a request.
-
.request_class(method) ⇒ Class
private
The matching
Net::HTTPrequest class.
Class Method Details
.link_local?(host) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns whether the host is a link-local address.
133 134 135 136 137 138 |
# File 'lib/kitchen/driver/azure/http.rb', line 133 def self.link_local?(host) LINK_LOCAL.include?(IPAddr.new(host.to_s)) rescue IPAddr::Error # Not an IP address at all, so not the metadata service. false end |
.perform(uri, request) ⇒ Net::HTTPResponse
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Sends a request, honouring the proxy environment variables.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/kitchen/driver/azure/http.rb', line 95 def self.perform(uri, request) proxy = proxy_for(uri) http = if proxy Net::HTTP.new(uri.host, uri.port, proxy.host, proxy.port, proxy.user, proxy.password) else # Explicitly nil rather than Net::HTTP's default of :ENV, # which would send it back to the environment to pick a # proxy we have just decided against. Net::HTTP.new(uri.host, uri.port, nil) end http.use_ssl = uri.scheme == "https" http.open_timeout = OPEN_TIMEOUT http.read_timeout = READ_TIMEOUT http.start { |connection| connection.request(request) } end |
.proxy_for(uri) ⇒ URI?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The proxy to reach a URL through, if any.
Azure's instance metadata service answers on a link-local address, which exists only on the local link and which no proxy can route to. Sending it through one breaks managed identity authentication outright: the connection hangs until the open timeout, surfaces as a TransientError, and is then retried. Every Azure SDK carves the same exception out.
124 125 126 127 128 |
# File 'lib/kitchen/driver/azure/http.rb', line 124 def self.proxy_for(uri) return nil if link_local?(uri.host) uri.find_proxy end |
.request(method:, url:, headers: {}, body: nil) ⇒ Response
Performs a request.
77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/kitchen/driver/azure/http.rb', line 77 def self.request(method:, url:, headers: {}, body: nil) uri = URI.parse(url) request = request_class(method).new(uri) headers.each { |name, value| request[name] = value } request.body = body if body response = perform(uri, request) Response.new(response.code.to_i, response.body.to_s) rescue *TRANSIENT_ERRORS => e raise TransientError, "#{e.class}: #{e.}" end |
.request_class(method) ⇒ Class
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the matching Net::HTTP request class.
144 145 146 147 148 149 150 151 152 153 |
# File 'lib/kitchen/driver/azure/http.rb', line 144 def self.request_class(method) case method when :get then Net::HTTP::Get when :head then Net::HTTP::Head when :put then Net::HTTP::Put when :post then Net::HTTP::Post when :delete then Net::HTTP::Delete else raise ArgumentError, "Unsupported HTTP method: #{method}" end end |