diplomat 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|