ridley 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +1 -1
- data/lib/ridley/connection.rb +30 -6
- data/lib/ridley/errors.rb +15 -12
- data/lib/ridley/middleware.rb +7 -3
- data/lib/ridley/middleware/retry.rb +60 -0
- data/lib/ridley/version.rb +1 -1
- data/ridley.gemspec +1 -0
- data/spec/unit/ridley/chef/digester_spec.rb +22 -0
- data/spec/unit/ridley/connection_spec.rb +27 -0
- metadata +22 -3
data/Gemfile
CHANGED
data/lib/ridley/connection.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'open-uri'
|
2
|
+
require 'retryable'
|
2
3
|
require 'tempfile'
|
3
4
|
|
4
5
|
module Ridley
|
@@ -17,6 +18,12 @@ module Ridley
|
|
17
18
|
attr_reader :organization
|
18
19
|
attr_reader :client_key
|
19
20
|
attr_reader :client_name
|
21
|
+
# @return [Integer]
|
22
|
+
# how many retries to attempt on HTTP requests
|
23
|
+
attr_reader :retries
|
24
|
+
# @return [Float]
|
25
|
+
# time to wait between retries
|
26
|
+
attr_reader :retry_interval
|
20
27
|
|
21
28
|
# @param [String] server_url
|
22
29
|
# @param [String] client_name
|
@@ -26,6 +33,10 @@ module Ridley
|
|
26
33
|
# URI query unencoded key/value pairs
|
27
34
|
# @option options [Hash] :headers
|
28
35
|
# unencoded HTTP header key/value pairs
|
36
|
+
# @option options [Integer] :retries (5)
|
37
|
+
# retry requests on 5XX failures
|
38
|
+
# @option options [Float] :retry_interval (0.5)
|
39
|
+
# how often we should pause between retries
|
29
40
|
# @option options [Hash] :request
|
30
41
|
# request options
|
31
42
|
# @option options [Hash] :ssl
|
@@ -33,14 +44,25 @@ module Ridley
|
|
33
44
|
# @option options [URI, String, Hash] :proxy
|
34
45
|
# URI, String, or Hash of HTTP proxy options
|
35
46
|
def initialize(server_url, client_name, client_key, options = {})
|
36
|
-
|
37
|
-
@
|
47
|
+
options = options.reverse_merge(retries: 5, retry_interval: 0.5)
|
48
|
+
@client_name = client_name
|
49
|
+
@client_key = client_key
|
50
|
+
@retries = options[:retries]
|
51
|
+
@retry_interval = options[:retry_interval]
|
38
52
|
|
39
53
|
options = options.reverse_merge(
|
40
54
|
builder: Faraday::Builder.new { |b|
|
41
|
-
b.request :chef_auth, client_name, client_key
|
42
|
-
b.response :chef_response
|
43
55
|
b.response :json
|
56
|
+
b.request :retry,
|
57
|
+
max: @retries,
|
58
|
+
interval: @retry_interval,
|
59
|
+
exceptions: [
|
60
|
+
Ridley::Errors::HTTP5XXError,
|
61
|
+
Errno::ETIMEDOUT,
|
62
|
+
Faraday::Error::TimeoutError
|
63
|
+
]
|
64
|
+
b.response :chef_response
|
65
|
+
b.request :chef_auth, client_name, client_key
|
44
66
|
|
45
67
|
b.adapter :net_http_persistent
|
46
68
|
}
|
@@ -117,8 +139,10 @@ module Ridley
|
|
117
139
|
local = Tempfile.new('ridley-stream')
|
118
140
|
local.binmode
|
119
141
|
|
120
|
-
|
121
|
-
|
142
|
+
retryable(tries: retries, on: OpenURI::HTTPError, sleep: retry_interval) do
|
143
|
+
open(target, 'rb', headers) do |remote|
|
144
|
+
local.write(remote.read)
|
145
|
+
end
|
122
146
|
end
|
123
147
|
|
124
148
|
local.flush
|
data/lib/ridley/errors.rb
CHANGED
@@ -87,18 +87,21 @@ module Ridley
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
class
|
91
|
-
class
|
92
|
-
|
93
|
-
class
|
94
|
-
class
|
95
|
-
class
|
96
|
-
class
|
90
|
+
class HTTP4XXError < HTTPError; end
|
91
|
+
class HTTP5XXError < HTTPError; end
|
92
|
+
|
93
|
+
class HTTPBadRequest < HTTP4XXError; register_error(400); end
|
94
|
+
class HTTPUnauthorized < HTTP4XXError; register_error(401); end
|
95
|
+
class HTTPForbidden < HTTP4XXError; register_error(403); end
|
96
|
+
class HTTPNotFound < HTTP4XXError; register_error(404); end
|
97
|
+
class HTTPMethodNotAllowed < HTTP4XXError; register_error(405); end
|
98
|
+
class HTTPRequestTimeout < HTTP4XXError; register_error(408); end
|
99
|
+
class HTTPConflict < HTTP4XXError; register_error(409); end
|
97
100
|
|
98
|
-
class HTTPInternalServerError <
|
99
|
-
class HTTPNotImplemented <
|
100
|
-
class HTTPBadGateway <
|
101
|
-
class HTTPServiceUnavailable <
|
102
|
-
class HTTPGatewayTimeout <
|
101
|
+
class HTTPInternalServerError < HTTP5XXError; register_error(500); end
|
102
|
+
class HTTPNotImplemented < HTTP5XXError; register_error(501); end
|
103
|
+
class HTTPBadGateway < HTTP5XXError; register_error(502); end
|
104
|
+
class HTTPServiceUnavailable < HTTP5XXError; register_error(503); end
|
105
|
+
class HTTPGatewayTimeout < HTTP5XXError; register_error(504); end
|
103
106
|
end
|
104
107
|
end
|
data/lib/ridley/middleware.rb
CHANGED
@@ -6,14 +6,18 @@ module Ridley
|
|
6
6
|
require 'ridley/middleware/parse_json'
|
7
7
|
require 'ridley/middleware/chef_response'
|
8
8
|
require 'ridley/middleware/chef_auth'
|
9
|
+
require 'ridley/middleware/retry'
|
9
10
|
|
10
11
|
Faraday.register_middleware :request,
|
11
|
-
chef_auth: -> { ChefAuth }
|
12
|
+
chef_auth: -> { Ridley::Middleware::ChefAuth }
|
13
|
+
|
14
|
+
Faraday.register_middleware :request,
|
15
|
+
retry: -> { Ridley::Middleware::Retry }
|
12
16
|
|
13
17
|
Faraday.register_middleware :response,
|
14
|
-
json: -> { ParseJson }
|
18
|
+
json: -> { Ridley::Middleware::ParseJson }
|
15
19
|
|
16
20
|
Faraday.register_middleware :response,
|
17
|
-
chef_response: -> { ChefResponse }
|
21
|
+
chef_response: -> { Ridley::Middleware::ChefResponse }
|
18
22
|
end
|
19
23
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Ridley
|
2
|
+
# @author Jamie Winsor <jamie@vialstudios.com>
|
3
|
+
#
|
4
|
+
# Catches exceptions and retries each request a limited number of times.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
#
|
8
|
+
# Faraday.new do |conn|
|
9
|
+
# conn.request :retry, max: 2, interval: 0.05, exceptions: [CustomException, Faraday::Timeout::Error]
|
10
|
+
# conn.adapter ...
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @note Borrowed and modified from: {https://github.com/lostisland/faraday/blob/master/lib/faraday/request/retry.rb}
|
14
|
+
# use the Faraday official middleware after the release of 0.9.x
|
15
|
+
class Middleware::Retry < Faraday::Middleware
|
16
|
+
# @option options [Integer] :max
|
17
|
+
# maximum number of retries
|
18
|
+
# @option options [Float] :interval
|
19
|
+
# pause in seconds between retries
|
20
|
+
# @option options [Array] :exceptions
|
21
|
+
# the list of exceptions to handle
|
22
|
+
def initialize(app, options = {})
|
23
|
+
super(app)
|
24
|
+
@options = options.slice(:max, :interval, :exceptions)
|
25
|
+
@errmatch = build_exception_matcher(@options[:exceptions])
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(env)
|
29
|
+
retries = @options[:max]
|
30
|
+
begin
|
31
|
+
@app.call(env)
|
32
|
+
rescue @errmatch
|
33
|
+
if retries > 0
|
34
|
+
retries -= 1
|
35
|
+
sleep @options[:interval] if @options[:interval] > 0
|
36
|
+
retry
|
37
|
+
end
|
38
|
+
raise
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# construct an exception matcher object.
|
43
|
+
#
|
44
|
+
# An exception matcher for the rescue clause can usually be any object that
|
45
|
+
# responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
|
46
|
+
def build_exception_matcher(exceptions)
|
47
|
+
matcher = Module.new
|
48
|
+
(class << matcher; self; end).class_eval do
|
49
|
+
define_method(:===) do |error|
|
50
|
+
exceptions.any? do |ex|
|
51
|
+
if ex.is_a? Module then error.is_a? ex
|
52
|
+
else error.class.to_s == ex.to_s
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
matcher
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/ridley/version.rb
CHANGED
data/ridley.gemspec
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Borrowed and modified from: {https://github.com/opscode/chef/blob/11.4.0/spec/unit/digester_spec.rb}
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Ridley::Chef::Digester do
|
6
|
+
before(:each) do
|
7
|
+
@cache = described_class.instance
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "when computing checksums of cookbook files and templates" do
|
11
|
+
it "proxies the class method checksum_for_file to the instance" do
|
12
|
+
@cache.should_receive(:checksum_for_file).with("a_file_or_a_fail")
|
13
|
+
described_class.checksum_for_file("a_file_or_a_fail")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "generates a checksum from a non-file IO object" do
|
17
|
+
io = StringIO.new("riseofthemachines\nriseofthechefs\n")
|
18
|
+
expected_md5 = '0e157ac1e2dd73191b76067fb6b4bceb'
|
19
|
+
@cache.generate_md5_checksum(io).should == expected_md5
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -9,6 +9,33 @@ describe Ridley::Connection do
|
|
9
9
|
described_class.new(server_url, client_name, client_key)
|
10
10
|
end
|
11
11
|
|
12
|
+
describe "configurable retries" do
|
13
|
+
before(:each) do
|
14
|
+
stub_request(:get, "https://api.opscode.com/organizations/vialstudios").to_return(status: 500, body: "")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "attempts five (5) retries by default" do
|
18
|
+
expect {
|
19
|
+
subject.get('organizations/vialstudios')
|
20
|
+
}.to raise_error
|
21
|
+
a_request(:get, "https://api.opscode.com/organizations/vialstudios").should have_been_made.times(6)
|
22
|
+
end
|
23
|
+
|
24
|
+
context "given a configured count of two (2) retries" do
|
25
|
+
subject do
|
26
|
+
described_class.new(server_url, client_name, client_key, retries: 2)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "attempts two (2) retries" do
|
30
|
+
expect {
|
31
|
+
subject.get('organizations/vialstudios')
|
32
|
+
}.to raise_error
|
33
|
+
|
34
|
+
a_request(:get, "https://api.opscode.com/organizations/vialstudios").should have_been_made.times(3)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
12
39
|
describe "#api_type" do
|
13
40
|
it "returns :foss if the organization is not set" do
|
14
41
|
subject.stub(:organization).and_return(nil)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ridley
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
@@ -251,6 +251,22 @@ dependencies:
|
|
251
251
|
- - ! '>='
|
252
252
|
- !ruby/object:Gem::Version
|
253
253
|
version: '2.8'
|
254
|
+
- !ruby/object:Gem::Dependency
|
255
|
+
name: retryable
|
256
|
+
requirement: !ruby/object:Gem::Requirement
|
257
|
+
none: false
|
258
|
+
requirements:
|
259
|
+
- - ! '>='
|
260
|
+
- !ruby/object:Gem::Version
|
261
|
+
version: '0'
|
262
|
+
type: :runtime
|
263
|
+
prerelease: false
|
264
|
+
version_requirements: !ruby/object:Gem::Requirement
|
265
|
+
none: false
|
266
|
+
requirements:
|
267
|
+
- - ! '>='
|
268
|
+
- !ruby/object:Gem::Version
|
269
|
+
version: '0'
|
254
270
|
description: A reliable Chef API client with a clean syntax
|
255
271
|
email:
|
256
272
|
- jamie@vialstudios.com
|
@@ -285,6 +301,7 @@ files:
|
|
285
301
|
- lib/ridley/middleware/chef_auth.rb
|
286
302
|
- lib/ridley/middleware/chef_response.rb
|
287
303
|
- lib/ridley/middleware/parse_json.rb
|
304
|
+
- lib/ridley/middleware/retry.rb
|
288
305
|
- lib/ridley/mixin.rb
|
289
306
|
- lib/ridley/mixin/checksum.rb
|
290
307
|
- lib/ridley/mixin/shell_out.rb
|
@@ -340,6 +357,7 @@ files:
|
|
340
357
|
- spec/unit/ridley/bootstrapper/context_spec.rb
|
341
358
|
- spec/unit/ridley/bootstrapper_spec.rb
|
342
359
|
- spec/unit/ridley/chef/cookbook_spec.rb
|
360
|
+
- spec/unit/ridley/chef/digester_spec.rb
|
343
361
|
- spec/unit/ridley/client_spec.rb
|
344
362
|
- spec/unit/ridley/connection_spec.rb
|
345
363
|
- spec/unit/ridley/errors_spec.rb
|
@@ -382,7 +400,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
382
400
|
version: '0'
|
383
401
|
segments:
|
384
402
|
- 0
|
385
|
-
hash:
|
403
|
+
hash: -1703790355388058426
|
386
404
|
requirements: []
|
387
405
|
rubyforge_project:
|
388
406
|
rubygems_version: 1.8.24
|
@@ -423,6 +441,7 @@ test_files:
|
|
423
441
|
- spec/unit/ridley/bootstrapper/context_spec.rb
|
424
442
|
- spec/unit/ridley/bootstrapper_spec.rb
|
425
443
|
- spec/unit/ridley/chef/cookbook_spec.rb
|
444
|
+
- spec/unit/ridley/chef/digester_spec.rb
|
426
445
|
- spec/unit/ridley/client_spec.rb
|
427
446
|
- spec/unit/ridley/connection_spec.rb
|
428
447
|
- spec/unit/ridley/errors_spec.rb
|