Class: VagrantPlugins::Skytap::API::Client
- Defined in:
- lib/vagrant-skytap/api/client.rb
Constant Summary collapse
- DEFAULT_TIMEOUT =
120
- MAX_RATE_LIMIT_RETRIES =
3
- DEFAULT_RETRY_AFTER_SECONDS =
5
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#http ⇒ Object
readonly
Returns the value of attribute http.
Instance Method Summary collapse
- #delete(path, options = {}) ⇒ Object
- #error_string_from_body(resp) ⇒ Object
- #get(path, options = {}) ⇒ Object
-
#initialize(config) ⇒ Client
constructor
A new instance of Client.
- #post(path, body = nil, options = {}) ⇒ Object
- #put(path, body = nil, options = {}) ⇒ Object
-
#req(method, path, body, options = {}) ⇒ Object
path
may optionally include query and fragment parts.
Constructor Details
#initialize(config) ⇒ Client
Returns a new instance of Client.
37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/vagrant-skytap/api/client.rb', line 37 def initialize(config) @logger = Log4r::Logger.new("vagrant_skytap::api_client") @config = config uri = URI.parse(config.base_url) @http = Net::HTTP.new(uri.host, uri.port) @http.verify_mode = OpenSSL::SSL::VERIFY_NONE @http.use_ssl = uri.port == 443 || uri.scheme == 'https' end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
31 32 33 |
# File 'lib/vagrant-skytap/api/client.rb', line 31 def config @config end |
#http ⇒ Object (readonly)
Returns the value of attribute http.
31 32 33 |
# File 'lib/vagrant-skytap/api/client.rb', line 31 def http @http end |
Instance Method Details
#delete(path, options = {}) ⇒ Object
61 62 63 |
# File 'lib/vagrant-skytap/api/client.rb', line 61 def delete(path, ={}) req('DELETE', path, nil, ) end |
#error_string_from_body(resp) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/vagrant-skytap/api/client.rb', line 132 def error_string_from_body(resp) resp = resp.body if resp.respond_to?(:body) begin resp = JSON.load(resp) errors = resp['error'] || resp['errors'] errors = errors.join('; ') if errors.respond_to? :join rescue # treat non-JSON string as error text errors = resp end errors if errors.present? end |
#get(path, options = {}) ⇒ Object
49 50 51 |
# File 'lib/vagrant-skytap/api/client.rb', line 49 def get(path, ={}) req('GET', path, nil, ) end |
#post(path, body = nil, options = {}) ⇒ Object
53 54 55 |
# File 'lib/vagrant-skytap/api/client.rb', line 53 def post(path, body=nil, ={}) req('POST', path, body, ) end |
#put(path, body = nil, options = {}) ⇒ Object
57 58 59 |
# File 'lib/vagrant-skytap/api/client.rb', line 57 def put(path, body=nil, ={}) req('PUT', path, body, ) end |
#req(method, path, body, options = {}) ⇒ Object
path
may optionally include query and fragment parts
options
are:
query: A string or hash of the query string
extra_headers: A hash of extra headers
70 71 72 73 74 75 76 77 78 79 80 81 82 83 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 129 130 |
# File 'lib/vagrant-skytap/api/client.rb', line 70 def req(method, path, body, ={}) @logger.info("REST API call: #{method} #{path} #{'body: ' + body if body.present?}") uri = URI.parse(path) if qq = [:query] if qq.is_a?(Hash) extra_query = qq.collect{|k,v| [k,v].join('=')}.join('&') else extra_query = qq.to_s end end if (query = [uri.query, extra_query].compact.join('&')).present? path = [uri.path, query].join('?') end headers = default_headers.merge([:extra_headers] || {}) retry_after = DEFAULT_RETRY_AFTER_SECONDS most_recent_exception = nil begin Timeout.timeout([:timeout] || DEFAULT_TIMEOUT) do begin http.send_request(method, URI.encode(path), body, headers).tap do |ret| @logger.debug("REST API response: #{ret.body}") unless ret.code =~ /^2\d\d/ raise Errors::DoesNotExist, object_name: "Object '#{path}'" if ret.code == '404' error_class = case ret.code when '403' Errors::Unauthorized when '422' Errors::UnprocessableEntity when '423' Errors::ResourceBusy when '429' retry_after = ret['Retry-After'] || DEFAULT_RETRY_AFTER_SECONDS Errors::RateLimited else Errors::OperationFailed end raise error_class, err: error_string_from_body(ret) end end rescue Errors::RateLimited => ex most_recent_exception = ex @logger.info("Rate limited, wil retry in #{retry_after} seconds") sleep retry_after.to_f + 0.1 retry rescue Errors::ResourceBusy => ex most_recent_exception = ex @logger.debug("Resource busy, retrying") sleep DEFAULT_RETRY_AFTER_SECONDS retry end end rescue Timeout::Error => ex raise most_recent_exception if most_recent_exception raise Errors::OperationFailed, err: "Timeout exceeded" end end |