diplomat 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/features/step_definitions/setup_diplomat.rb +8 -6
- data/features/step_definitions/test_key_value.rb +2 -2
- data/lib/diplomat.rb +19 -9
- data/lib/diplomat/acl.rb +31 -33
- data/lib/diplomat/api_options.rb +4 -3
- data/lib/diplomat/check.rb +26 -44
- data/lib/diplomat/configuration.rb +2 -3
- data/lib/diplomat/datacenter.rb +10 -15
- data/lib/diplomat/error.rb +2 -0
- data/lib/diplomat/event.rb +67 -69
- data/lib/diplomat/health.rb +48 -53
- data/lib/diplomat/kv.rb +41 -47
- data/lib/diplomat/lock.rb +14 -12
- data/lib/diplomat/maintenance.rb +17 -20
- data/lib/diplomat/members.rb +4 -6
- data/lib/diplomat/node.rb +20 -28
- data/lib/diplomat/nodes.rb +15 -17
- data/lib/diplomat/query.rb +124 -0
- data/lib/diplomat/rest_client.rb +47 -51
- data/lib/diplomat/service.rb +29 -27
- data/lib/diplomat/session.rb +70 -23
- data/lib/diplomat/version.rb +1 -1
- metadata +25 -8
data/lib/diplomat/health.rb
CHANGED
@@ -1,106 +1,101 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'faraday'
|
3
|
-
|
4
1
|
module Diplomat
|
2
|
+
# Methods for interacting with the Consul health API endpoint
|
5
3
|
class Health < Diplomat::RestClient
|
6
|
-
@access_methods = [
|
7
|
-
|
4
|
+
@access_methods = [:node, :checks, :service, :state,
|
5
|
+
:any, :passing, :warning, :critical]
|
8
6
|
|
9
7
|
# Get node health
|
10
8
|
# @param n [String] the node
|
11
9
|
# @param options [Hash] :dc string for dc specific query
|
12
10
|
# @return [OpenStruct] all data associated with the node
|
13
|
-
def node
|
11
|
+
def node(n, options = nil)
|
14
12
|
url = ["/v1/health/node/#{n}"]
|
15
|
-
url << use_named_parameter('dc', options[:dc]) if options
|
13
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
16
14
|
|
17
15
|
# If the request fails, it's probably due to a bad path
|
18
16
|
# so return a PathNotFound error.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
return JSON.parse(ret.body)
|
17
|
+
ret = @conn.get concat_url url
|
18
|
+
JSON.parse(ret.body).map { |node| OpenStruct.new node }
|
19
|
+
rescue Faraday::ClientError
|
20
|
+
raise Diplomat::PathNotFound
|
25
21
|
end
|
26
22
|
|
27
23
|
# Get service checks
|
28
24
|
# @param s [String] the service
|
29
25
|
# @param options [Hash] :dc string for dc specific query
|
30
26
|
# @return [OpenStruct] all data associated with the node
|
31
|
-
def checks
|
27
|
+
def checks(s, options = nil)
|
32
28
|
url = ["/v1/health/checks/#{s}"]
|
33
|
-
url << use_named_parameter('dc', options[:dc]) if options
|
34
|
-
|
29
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
30
|
+
|
35
31
|
# If the request fails, it's probably due to a bad path
|
36
32
|
# so return a PathNotFound error.
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
return JSON.parse(ret.body)
|
33
|
+
ret = @conn.get concat_url url
|
34
|
+
JSON.parse(ret.body).map { |check| OpenStruct.new check }
|
35
|
+
rescue Faraday::ClientError
|
36
|
+
raise Diplomat::PathNotFound
|
43
37
|
end
|
44
38
|
|
45
39
|
# Get service health
|
46
40
|
# @param s [String] the service
|
47
41
|
# @param options [Hash] :dc string for dc specific query
|
48
|
-
# @param options [Hash] :
|
42
|
+
# @param options [Hash] :passing boolean to return only checks in passing state
|
49
43
|
# @param options [Hash] :tag string for specific tag
|
50
44
|
# @return [OpenStruct] all data associated with the node
|
51
|
-
|
45
|
+
# rubocop:disable PerceivedComplexity, CyclomaticComplexity, AbcSize
|
46
|
+
def service(s, options = nil)
|
52
47
|
url = ["/v1/health/service/#{s}"]
|
53
|
-
url << use_named_parameter('dc', options[:dc]) if options
|
54
|
-
url <<
|
55
|
-
url << use_named_parameter('tag', options[:tag]) if options
|
48
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
49
|
+
url << 'passing' if options && options[:passing]
|
50
|
+
url << use_named_parameter('tag', options[:tag]) if options && options[:tag]
|
51
|
+
url << use_named_parameter('near', options[:near]) if options && options[:near]
|
56
52
|
|
57
53
|
# If the request fails, it's probably due to a bad path
|
58
|
-
# so return a PathNotFound error.
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
-
return JSON.parse(ret.body)
|
54
|
+
# so return a PathNotFound error.
|
55
|
+
ret = @conn.get concat_url url
|
56
|
+
JSON.parse(ret.body).map { |service| OpenStruct.new service }
|
57
|
+
rescue Faraday::ClientError
|
58
|
+
raise Diplomat::PathNotFound
|
65
59
|
end
|
60
|
+
# rubocop:enable PerceivedComplexity, CyclomaticComplexity, AbcSize
|
66
61
|
|
67
62
|
# Get service health
|
68
|
-
# @param s [String] the state ("
|
63
|
+
# @param s [String] the state ("any", "passing", "warning", or "critical")
|
69
64
|
# @param options [Hash] :dc string for dc specific query
|
70
65
|
# @return [OpenStruct] all data associated with the node
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
# so return a PathNotFound error.
|
77
|
-
begin
|
78
|
-
ret = @conn.get concat_url url
|
79
|
-
rescue Faraday::ClientError
|
80
|
-
raise Diplomat::PathNotFound
|
81
|
-
end
|
82
|
-
return JSON.parse(ret.body)
|
66
|
+
# rubocop:disable AbcSize
|
67
|
+
def state(s, options = nil)
|
68
|
+
url = ["/v1/health/state/#{s}"]
|
69
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
70
|
+
url << use_named_parameter('near', options[:near]) if options && options[:near]
|
83
71
|
|
72
|
+
# If the request fails, it's probably due to a bad path
|
73
|
+
# so return a PathNotFound error.
|
74
|
+
ret = @conn.get concat_url url
|
75
|
+
JSON.parse(ret.body).map { |status| OpenStruct.new status }
|
76
|
+
rescue Faraday::ClientError
|
77
|
+
raise Diplomat::PathNotFound
|
84
78
|
end
|
79
|
+
# rubocop:enable AbcSize
|
85
80
|
|
86
|
-
# Convenience method to get services in
|
87
|
-
def
|
88
|
-
state(
|
81
|
+
# Convenience method to get services in any state
|
82
|
+
def any
|
83
|
+
state('any')
|
89
84
|
end
|
90
85
|
|
91
86
|
# Convenience method to get services in passing state
|
92
87
|
def passing
|
93
|
-
state(
|
88
|
+
state('passing')
|
94
89
|
end
|
95
90
|
|
96
91
|
# Convenience method to get services in warning state
|
97
92
|
def warning
|
98
|
-
state(
|
93
|
+
state('warning')
|
99
94
|
end
|
100
95
|
|
101
96
|
# Convenience method to get services in critical state
|
102
97
|
def critical
|
103
|
-
state(
|
98
|
+
state('critical')
|
104
99
|
end
|
105
100
|
end
|
106
101
|
end
|
data/lib/diplomat/kv.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'faraday'
|
3
|
-
|
4
1
|
module Diplomat
|
2
|
+
# Methods for interacting with the Consul KV API endpoint
|
5
3
|
class Kv < Diplomat::RestClient
|
6
|
-
|
7
4
|
include ApiOptions
|
8
5
|
|
9
|
-
@access_methods = [
|
6
|
+
@access_methods = [:get, :put, :delete]
|
10
7
|
attr_reader :key, :value, :raw
|
11
8
|
|
12
9
|
# Get a value by its key, potentially blocking for the first or next value
|
@@ -18,7 +15,8 @@ module Diplomat
|
|
18
15
|
# @option options [Boolean] :keys Only return key names.
|
19
16
|
# @option options [Boolean] :modify_index Only return ModifyIndex value.
|
20
17
|
# @option options [Boolean] :decode_values Return consul response with decoded values.
|
21
|
-
# @option options [String] :separator List only up to a given separator.
|
18
|
+
# @option options [String] :separator List only up to a given separator.
|
19
|
+
# Only applies when combined with :keys option.
|
22
20
|
# @option options [Boolean] :nil_values If to return keys/dirs with nil values
|
23
21
|
# @option options [Boolean] :convert_to_hash Take the data returned from consul and build a hash
|
24
22
|
# @option options [Callable] :transformation funnction to invoke on keys values
|
@@ -43,7 +41,8 @@ module Diplomat
|
|
43
41
|
# - W R - get the first or current value; always return something, but
|
44
42
|
# block only when necessary
|
45
43
|
# - W W - get the first or next value; wait until there is an update
|
46
|
-
|
44
|
+
# rubocop:disable PerceivedComplexity, MethodLength, CyclomaticComplexity, AbcSize, LineLength
|
45
|
+
def get(key, options = nil, not_found = :reject, found = :return)
|
47
46
|
@key = key
|
48
47
|
@options = options
|
49
48
|
|
@@ -55,53 +54,48 @@ module Diplomat
|
|
55
54
|
url += keys(@options)
|
56
55
|
url += separator(@options)
|
57
56
|
|
58
|
-
return_nil_values =
|
59
|
-
transformation =
|
57
|
+
return_nil_values = @options && @options[:nil_values]
|
58
|
+
transformation = @options && @options[:transformation] && @options[:transformation].methods.find_index(:call) ? @options[:transformation] : nil
|
60
59
|
|
61
60
|
# 404s OK using this connection
|
62
61
|
raw = @conn_no_err.get concat_url url
|
63
62
|
if raw.status == 404
|
64
63
|
case not_found
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
64
|
+
when :reject
|
65
|
+
raise Diplomat::KeyNotFound, key
|
66
|
+
when :return
|
67
|
+
return @value = ''
|
68
|
+
when :wait
|
69
|
+
index = raw.headers['x-consul-index']
|
71
70
|
end
|
72
71
|
elsif raw.status == 200
|
73
72
|
case found
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
if @options and @options[:convert_to_hash]
|
86
|
-
return convert_to_hash(return_value(return_nil_values, transformation))
|
87
|
-
end
|
88
|
-
return return_value(return_nil_values, transformation)
|
89
|
-
when :wait
|
90
|
-
index = raw.headers["x-consul-index"]
|
73
|
+
when :reject
|
74
|
+
raise Diplomat::KeyAlreadyExists, key
|
75
|
+
when :return
|
76
|
+
@raw = raw
|
77
|
+
@raw = parse_body
|
78
|
+
return @raw.first['ModifyIndex'] if @options && @options[:modify_index]
|
79
|
+
return decode_values if @options && @options[:decode_values]
|
80
|
+
return convert_to_hash(return_value(return_nil_values, transformation)) if @options && @options[:convert_to_hash]
|
81
|
+
return return_value(return_nil_values, transformation)
|
82
|
+
when :wait
|
83
|
+
index = raw.headers['x-consul-index']
|
91
84
|
end
|
92
85
|
else
|
93
|
-
raise Diplomat::UnknownStatus, "status #{raw.status}"
|
86
|
+
raise Diplomat::UnknownStatus, "status #{raw.status}: #{raw.body}"
|
94
87
|
end
|
95
88
|
|
96
89
|
# Wait for first/next value
|
97
|
-
url += use_named_parameter(
|
90
|
+
url += use_named_parameter('index', index)
|
98
91
|
@raw = @conn.get do |req|
|
99
92
|
req.url concat_url url
|
100
|
-
req.options.timeout =
|
93
|
+
req.options.timeout = 86_400
|
101
94
|
end
|
102
|
-
parse_body
|
95
|
+
@raw = parse_body
|
103
96
|
return_value(return_nil_values, transformation)
|
104
97
|
end
|
98
|
+
# rubocop:enable PerceivedComplexity, MethodLength, CyclomaticComplexity, AbcSize, LineLength
|
105
99
|
|
106
100
|
# Associate a value with a key
|
107
101
|
# @param key [String] the key
|
@@ -110,7 +104,8 @@ module Diplomat
|
|
110
104
|
# @option options [Integer] :cas The modify index
|
111
105
|
# @option options [String] :dc Target datacenter
|
112
106
|
# @return [Bool] Success or failure of the write (can fail in c-a-s mode)
|
113
|
-
|
107
|
+
# rubocop:disable MethodLength, AbcSize
|
108
|
+
def put(key, value, options = nil)
|
114
109
|
@options = options
|
115
110
|
@raw = @conn.put do |req|
|
116
111
|
url = ["/v1/kv/#{key}"]
|
@@ -120,12 +115,11 @@ module Diplomat
|
|
120
115
|
req.url concat_url url
|
121
116
|
req.body = value
|
122
117
|
end
|
123
|
-
if @raw.body ==
|
124
|
-
|
125
|
-
|
126
|
-
end
|
127
|
-
@raw.body == "true"
|
118
|
+
@key = key if @raw.body == 'true'
|
119
|
+
@value = value if @raw.body == 'true'
|
120
|
+
@raw.body == 'true'
|
128
121
|
end
|
122
|
+
# rubocop:enable MethodLength, AbcSize
|
129
123
|
|
130
124
|
# Delete a value by its key
|
131
125
|
# @param key [String] the key
|
@@ -133,7 +127,7 @@ module Diplomat
|
|
133
127
|
# @option options [String] :dc Target datacenter
|
134
128
|
# @option options [Boolean] :recurse If to make recursive get or not
|
135
129
|
# @return [OpenStruct]
|
136
|
-
def delete
|
130
|
+
def delete(key, options = nil)
|
137
131
|
@key = key
|
138
132
|
@options = options
|
139
133
|
url = ["/v1/kv/#{@key}"]
|
@@ -146,19 +140,19 @@ module Diplomat
|
|
146
140
|
private
|
147
141
|
|
148
142
|
def recurse_get(options)
|
149
|
-
|
143
|
+
options && options[:recurse] ? ['recurse'] : []
|
150
144
|
end
|
151
145
|
|
152
146
|
def dc(options)
|
153
|
-
|
147
|
+
options && options[:dc] ? use_named_parameter('dc', options[:dc]) : []
|
154
148
|
end
|
155
149
|
|
156
150
|
def keys(options)
|
157
|
-
|
151
|
+
options && options[:keys] ? ['keys'] : []
|
158
152
|
end
|
159
153
|
|
160
154
|
def separator(options)
|
161
|
-
|
155
|
+
options && options[:separator] ? use_named_parameter('separator', options[:separator]) : []
|
162
156
|
end
|
163
157
|
end
|
164
158
|
end
|
data/lib/diplomat/lock.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
|
3
1
|
module Diplomat
|
2
|
+
# Methods for interacting with the Consul lock API endpoint
|
4
3
|
class Lock < Diplomat::RestClient
|
5
|
-
|
6
4
|
include ApiOptions
|
7
5
|
|
8
|
-
@access_methods = [
|
6
|
+
@access_methods = [:acquire, :wait_to_acquire, :release]
|
9
7
|
|
10
8
|
# Acquire a lock
|
11
9
|
# @param key [String] the key
|
12
10
|
# @param session [String] the session, generated from Diplomat::Session.create
|
13
11
|
# @param value [String] the value for the key
|
12
|
+
# @param options [Hash] :dc string for dc specific query
|
14
13
|
# @return [Boolean] If the lock was acquired
|
15
|
-
def acquire
|
14
|
+
def acquire(key, session, value = nil, options = nil)
|
16
15
|
raw = @conn.put do |req|
|
17
16
|
url = ["/v1/kv/#{key}"]
|
18
17
|
url += use_named_parameter('acquire', session)
|
19
18
|
url += check_acl_token
|
19
|
+
url += use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
20
20
|
|
21
21
|
req.url concat_url url
|
22
22
|
req.body = value unless value.nil?
|
@@ -29,30 +29,32 @@ module Diplomat
|
|
29
29
|
# @param session [String] the session, generated from Diplomat::Session.create
|
30
30
|
# @param value [String] the value for the key
|
31
31
|
# @param check_interval [Integer] number of seconds to wait between retries
|
32
|
+
# @param options [Hash] :dc string for dc specific query
|
32
33
|
# @return [Boolean] If the lock was acquired
|
33
|
-
def wait_to_acquire
|
34
|
+
def wait_to_acquire(key, session, value = nil, check_interval = 10, options = nil)
|
34
35
|
acquired = false
|
35
|
-
|
36
|
-
acquired =
|
37
|
-
sleep(check_interval)
|
36
|
+
until acquired
|
37
|
+
acquired = acquire(key, session, value, options)
|
38
|
+
sleep(check_interval) unless acquired
|
38
39
|
return true if acquired
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
42
|
-
|
43
43
|
# Release a lock
|
44
44
|
# @param key [String] the key
|
45
45
|
# @param session [String] the session, generated from Diplomat::Session.create
|
46
|
+
# @param options [Hash] :dc string for dc specific query
|
46
47
|
# @return [nil]
|
47
|
-
def release
|
48
|
+
def release(key, session, options = nil)
|
48
49
|
raw = @conn.put do |req|
|
49
50
|
url = ["/v1/kv/#{key}"]
|
50
51
|
url += use_named_parameter('release', session)
|
51
52
|
url += check_acl_token
|
53
|
+
url += use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
52
54
|
|
53
55
|
req.url concat_url url
|
54
56
|
end
|
55
|
-
|
57
|
+
raw.body
|
56
58
|
end
|
57
59
|
end
|
58
60
|
end
|
data/lib/diplomat/maintenance.rb
CHANGED
@@ -1,23 +1,21 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'faraday'
|
3
|
-
|
4
1
|
module Diplomat
|
2
|
+
# Methods to interact with the Consul maintenance API endpoint
|
5
3
|
class Maintenance < Diplomat::RestClient
|
6
|
-
@access_methods = [
|
4
|
+
@access_methods = [:enabled, :enable]
|
7
5
|
|
8
6
|
# Get the maintenance state of a host
|
9
7
|
# @param n [String] the node
|
10
8
|
# @param options [Hash] :dc string for dc specific query
|
11
9
|
# @return [Hash] { :enabled => true, :reason => 'foo' }
|
12
|
-
def enabled
|
10
|
+
def enabled(n, options = nil)
|
13
11
|
health = Diplomat::Health.new(@conn)
|
14
|
-
result = health.node(n, options)
|
15
|
-
|
12
|
+
result = health.node(n, options)
|
13
|
+
.select { |check| check['CheckID'] == '_node_maintenance' }
|
16
14
|
|
17
|
-
if result.
|
18
|
-
{ :
|
15
|
+
if result.empty?
|
16
|
+
{ enabled: false, reason: nil }
|
19
17
|
else
|
20
|
-
{ :
|
18
|
+
{ enabled: true, reason: result.first['Notes'] }
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
@@ -27,21 +25,20 @@ module Diplomat
|
|
27
25
|
# @param reason [String] the reason for enabling maintenance mode
|
28
26
|
# @param options [Hash] :dc string for dc specific query
|
29
27
|
# @return true if call is successful
|
30
|
-
|
28
|
+
# rubocop:disable AbcSize
|
29
|
+
def enable(enable = true, reason = nil, options = nil)
|
31
30
|
raw = @conn.put do |req|
|
32
|
-
url = [
|
31
|
+
url = ['/v1/agent/maintenance']
|
33
32
|
url << use_named_parameter('enable', enable.to_s)
|
34
|
-
url << use_named_parameter('reason', reason)
|
35
|
-
url << use_named_parameter('dc', options[:dc]) if options
|
33
|
+
url << use_named_parameter('reason', reason) if reason
|
34
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
36
35
|
req.url concat_url url
|
37
36
|
end
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
else
|
43
|
-
raise Diplomat::UnknownStatus, "status #{raw.status}"
|
44
|
-
end
|
38
|
+
return_status = raw.status == 200
|
39
|
+
raise Diplomat::UnknownStatus, "status #{raw.status}: #{raw.body}" unless return_status
|
40
|
+
return_status
|
45
41
|
end
|
42
|
+
# rubocop:enable AbcSize
|
46
43
|
end
|
47
44
|
end
|