vault 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8070f5204dc7fb565bfd50f5ba081fcd43b871ee
4
- data.tar.gz: ee1b072bdf2cf41a886b35fcb765337bdb18b260
3
+ metadata.gz: 85725acc286dd2dc1e346442a4e528d7e11ae42e
4
+ data.tar.gz: 6344245bd60e54203151708b45134c9ae2201a51
5
5
  SHA512:
6
- metadata.gz: a4ef3702182f75b6d33b48be4d93f3bb8c0ea66920bc9b63cbaa46be9983a934c2611728fef80260d591293d87b941a07904d5add95f65feebd9847efc8125d0
7
- data.tar.gz: dbb8386139effe9ba92a6803e7f20074a0a1ae92fe527d113113f9d6f95495465ac4ab190e13ae6ff944ffc09f480ff251904cf1e9edaa274bb715a3908746ca
6
+ metadata.gz: 6d573f396ec086b8103a3d29750c92aa79c0dd0567c5eb511c60a2d9912ad9fb47ef7d4a7a43b910e480ba3742e61e24cd2df9b3fe30e215dfa8d5d22993da88
7
+ data.tar.gz: 558a0c41ef94a57da06b5bb40bdd34fb07d0367a0ccdf7b51edae9d53fbb28940a81abccd5b9eccd78474493424d7f259459fcc8c522da515f3af37a0e8d5b2d
@@ -1,5 +1,16 @@
1
1
  # Vault Ruby Changelog
2
2
 
3
+ ## v0.2.0 (December 2, 2015)
4
+
5
+ IMPROVEMENTS
6
+
7
+ - Add support for retries (clients must opt-in) [GH-47]
8
+
9
+ BUG FIXES
10
+
11
+ - Fix redirection on POST/PUT [GH-40]
12
+ - Use `$HOME` instead of `~` for shell expansion
13
+
3
14
  ## v0.1.5 (September 1, 2015)
4
15
 
5
16
  IMPROVEMENTS
@@ -1,13 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- vault (0.1.5)
4
+ vault (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ addressable (2.3.8)
9
10
  coderay (1.1.0)
11
+ crack (0.4.2)
12
+ safe_yaml (~> 1.0.0)
10
13
  diff-lcs (1.2.5)
14
+ hashdiff (0.2.3)
11
15
  method_source (0.8.2)
12
16
  pry (0.10.1)
13
17
  coderay (~> 1.1.0)
@@ -27,7 +31,12 @@ GEM
27
31
  diff-lcs (>= 1.2.0, < 2.0)
28
32
  rspec-support (~> 3.2.0)
29
33
  rspec-support (3.2.2)
34
+ safe_yaml (1.0.4)
30
35
  slop (3.6.0)
36
+ webmock (1.22.3)
37
+ addressable (>= 2.3.6)
38
+ crack (>= 0.3.2)
39
+ hashdiff
31
40
 
32
41
  PLATFORMS
33
42
  ruby
@@ -38,6 +47,7 @@ DEPENDENCIES
38
47
  rake (~> 10.0)
39
48
  rspec (~> 3.2)
40
49
  vault!
50
+ webmock (~> 1.22)
41
51
 
42
52
  BUNDLED WITH
43
53
  1.10.6
data/README.md CHANGED
@@ -3,6 +3,8 @@ Vault Ruby Client [![Build Status](https://secure.travis-ci.org/hashicorp/vault-
3
3
 
4
4
  Vault is the official Ruby client for interacting with [Vault](https://vaultproject.io) by HashiCorp.
5
5
 
6
+ **The documentation in this README corresponds to the master branch of the Vault Ruby client. It may contain unreleased features or different APIs than the most recently released version. Please see the Git tag that corresponds to your version of the Vault Ruby client for the proper documentation.**
7
+
6
8
  Quick Start
7
9
  -----------
8
10
  Install Ruby 2.0+: [Guide](https://www.ruby-lang.org/en/documentation/installation/).
@@ -35,7 +37,7 @@ Usage
35
37
  The following configuration options are available:
36
38
 
37
39
  ```ruby
38
- Vault::Client.configure do |config|
40
+ Vault.configure do |config|
39
41
  # The address of the Vault server, also read as ENV["VAULT_ADDR"]
40
42
  config.address = "https://127.0.0.1:8200"
41
43
 
@@ -76,6 +78,61 @@ client_2 = Vault::Client.new(address: "https://other-vault.mycompany.com")
76
78
  ### Making requests
77
79
  All of the methods and API calls are heavily documented with examples inline using YARD. In order to keep the examples versioned with the code, the README only lists a few examples for using the Vault gem. Please see the inline documentation for the full API documentation. The tests in the 'spec' directory are an additional source of examples.
78
80
 
81
+ Idempotent requests can be wrapped with a `with_retries` clause to automatically retry on certain connection errors. For example, to retry on socket/network-level issues, you can do the following:
82
+
83
+ ```ruby
84
+ Vault.with_retries(Vault::HTTPConnectionError) do
85
+ Vault.logical.read("secret/on_bad_network")
86
+ end
87
+ ```
88
+
89
+ To rescue particular HTTP exceptions:
90
+
91
+ ```ruby
92
+ # Rescue 4xx errors
93
+ Vault.with_retries(Vault::HTTPClientError) {}
94
+
95
+ # Rescue 5xx errors
96
+ Vault.with_retries(Vault::HTTPServerError) {}
97
+
98
+ # Rescue all HTTP errors
99
+ Vault.with_retries(Vault::HTTPError) {}
100
+ ```
101
+
102
+ For advanced users, the first argument of the block is the attempt number and the second argument is the exception itself:
103
+
104
+ ```ruby
105
+ Vault.with_retries(Vault::HTTPConnectionError, Vault::HTTPError) do |attempt, e|
106
+ log "Received exception #{e} from Vault - attempt #{attempt}"
107
+ Vault.logical.read("secret/bacon")
108
+ end
109
+ ```
110
+
111
+ The following options are available:
112
+
113
+ ```ruby
114
+ # :attempts - The number of retries when communicating with the Vault server.
115
+ # The default value is 2.
116
+ #
117
+ # :base - The base interval for retry exponential backoff. The default value is
118
+ # 0.05s.
119
+ #
120
+ # :max_wait - The maximum amount of time for a single exponential backoff to
121
+ # sleep. The default value is 2.0s.
122
+
123
+ Vault.with_retries(Vault::HTTPError, attempts: 5) do
124
+ # ...
125
+ end
126
+ ```
127
+
128
+ After the number of retries have been exhausted, the original exception is raised.
129
+
130
+ ```ruby
131
+ Vault.with_retries(Exception) do
132
+ raise Exception
133
+ end #=> #<Exception>
134
+ ```
135
+
79
136
  #### Seal Status
80
137
  ```ruby
81
138
  Vault.sys.seal_status
@@ -16,6 +16,9 @@ module Vault
16
16
  # The name of the header used to hold the Vault token.
17
17
  TOKEN_HEADER = "X-Vault-Token".freeze
18
18
 
19
+ # The name of the header used for redirection.
20
+ LOCATION_HEADER = "location".freeze
21
+
19
22
  # The default headers that are sent with every request.
20
23
  DEFAULT_HEADERS = {
21
24
  "Content-Type" => "application/json",
@@ -214,8 +217,7 @@ module Vault
214
217
 
215
218
  case response
216
219
  when Net::HTTPRedirection
217
- redirect = URI.parse(response["location"])
218
- request(verb, redirect, data, headers)
220
+ request(verb, response[LOCATION_HEADER], data, headers)
219
221
  when Net::HTTPSuccess
220
222
  success(response)
221
223
  else
@@ -313,18 +315,65 @@ module Vault
313
315
  raise MissingTokenError
314
316
  end
315
317
 
318
+ # Use the correct exception class
319
+ case response
320
+ when Net::HTTPClientError
321
+ klass = HTTPClientError
322
+ when Net::HTTPServerError
323
+ klass = HTTPServerError
324
+ else
325
+ klass = HTTPError
326
+ end
327
+
316
328
  if (response.content_type || '').include?("json")
317
329
  # Attempt to parse the error as JSON
318
330
  begin
319
331
  json = JSON.parse(response.body, JSON_PARSE_OPTIONS)
320
332
 
321
333
  if json[:errors]
322
- raise HTTPError.new(address, response.code, json[:errors])
334
+ raise klass.new(address, response, json[:errors])
323
335
  end
324
336
  rescue JSON::ParserError; end
325
337
  end
326
338
 
327
- raise HTTPError.new(address, response.code, [response.body])
339
+ raise klass.new(address, response, [response.body])
340
+ end
341
+
342
+ # Execute the given block with retries and exponential backoff.
343
+ #
344
+ # @param [Array<Exception>] rescued
345
+ # the list of exceptions to rescue
346
+ def with_retries(*rescued, &block)
347
+ options = rescued.last.is_a?(Hash) ? rescued.pop : {}
348
+ exception = nil
349
+ retries = 0
350
+
351
+ max_attempts = options[:attempts] || Defaults::RETRY_ATTEMPTS
352
+ backoff_base = options[:base] || Defaults::RETRY_BASE
353
+ backoff_max = options[:max_wait] || Defaults::RETRY_MAX_WAIT
354
+
355
+ begin
356
+ return yield retries
357
+ rescue *rescued => e
358
+ exception = e
359
+
360
+ retries += 1
361
+ raise if retries > max_attempts
362
+
363
+ # Calculate the exponential backoff combined with an element of
364
+ # randomness.
365
+ backoff = [backoff_base * (2 ** (retries - 1)), backoff_max].min
366
+ backoff = backoff * (0.5 * (1 + Kernel.rand))
367
+
368
+ # Ensure we are sleeping at least the minimum interval.
369
+ backoff = [backoff_base, backoff].max
370
+
371
+ # Exponential backoff.
372
+ Kernel.sleep(backoff)
373
+
374
+ # Now retry
375
+ retry
376
+ end
328
377
  end
329
378
  end
330
379
  end
@@ -8,13 +8,24 @@ module Vault
8
8
 
9
9
  # The path to the vault token on disk.
10
10
  # @return [String]
11
- VAULT_DISK_TOKEN = Pathname.new("~/.vault-token").expand_path.freeze
11
+ VAULT_DISK_TOKEN = Pathname.new("#{ENV["HOME"]}/.vault-token").expand_path.freeze
12
12
 
13
13
  # The list of SSL ciphers to allow. You should not change this value unless
14
14
  # you absolutely know what you are doing!
15
15
  # @return [String]
16
16
  SSL_CIPHERS = "TLSv1.2:!aNULL:!eNULL".freeze
17
17
 
18
+ # The default number of attempts.
19
+ # @return [Fixnum]
20
+ RETRY_ATTEMPTS = 2
21
+
22
+ # The default backoff interval.
23
+ # @return [Fixnum]
24
+ RETRY_BASE = 0.05
25
+
26
+ # The maximum amount of time for a single exponential backoff to sleep.
27
+ RETRY_MAX_WAIT = 2.0
28
+
18
29
  class << self
19
30
  # The list of calculated options for this configurable.
20
31
  # @return [Hash]
@@ -42,13 +42,18 @@ shown below:
42
42
  Please refer to the documentation for more help.
43
43
  EOH
44
44
  end
45
+
46
+ def original_exception
47
+ @exception
48
+ end
45
49
  end
46
50
 
47
51
  class HTTPError < VaultError
48
- attr_reader :address, :code, :errors
52
+ attr_reader :address, :response, :code, :errors
49
53
 
50
- def initialize(address, code, errors = [])
51
- @address, @code, @errors = address, code.to_i, errors
54
+ def initialize(address, response, errors = [])
55
+ @address, @response, @errors = address, response, errors
56
+ @code = response.code.to_i
52
57
  errors = errors.map { |error| " * #{error}" }
53
58
 
54
59
  super <<-EOH
@@ -61,4 +66,7 @@ Please refer to the documentation for help.
61
66
  EOH
62
67
  end
63
68
  end
69
+
70
+ class HTTPClientError < HTTPError; end
71
+ class HTTPServerError < HTTPError; end
64
72
  end
@@ -1,3 +1,3 @@
1
1
  module Vault
2
- VERSION = "0.1.5"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "pry"
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_development_dependency "rspec", "~> 3.2"
26
+ spec.add_development_dependency "webmock", "~> 1.22"
26
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vault
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seth Vargo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-09-01 00:00:00.000000000 Z
11
+ date: 2015-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.22'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.22'
69
83
  description: Vault is a Ruby API client for interacting with a Vault server.
70
84
  email:
71
85
  - sethvargo@gmail.com