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/members.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'faraday'
|
3
|
-
|
4
1
|
module Diplomat
|
2
|
+
# Methods for interacting with the Consul members API endpoint
|
5
3
|
class Members < Diplomat::RestClient
|
6
|
-
@access_methods = [
|
4
|
+
@access_methods = [:get]
|
7
5
|
|
8
6
|
# Get all members
|
9
7
|
# @return [OpenStruct] all data associated with the service
|
10
8
|
def get
|
11
|
-
ret = @conn.get
|
12
|
-
|
9
|
+
ret = @conn.get '/v1/agent/members'
|
10
|
+
JSON.parse(ret.body)
|
13
11
|
end
|
14
12
|
end
|
15
13
|
end
|
data/lib/diplomat/node.rb
CHANGED
@@ -1,64 +1,56 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'faraday'
|
3
|
-
|
4
1
|
module Diplomat
|
2
|
+
# Methods for interacting with the Consul node API endpoint
|
5
3
|
class Node < Diplomat::RestClient
|
6
|
-
|
7
4
|
include ApiOptions
|
8
5
|
|
9
|
-
@access_methods = [
|
6
|
+
@access_methods = [:get, :get_all, :register, :deregister]
|
10
7
|
|
11
8
|
# Get a node by it's key
|
12
9
|
# @param key [String] the key
|
13
10
|
# @param options [Hash] :dc string for dc specific query
|
14
11
|
# @return [OpenStruct] all data associated with the node
|
15
|
-
def get
|
16
|
-
|
12
|
+
def get(key, options = nil)
|
17
13
|
url = ["/v1/catalog/node/#{key}"]
|
18
14
|
url += check_acl_token
|
19
|
-
url << use_named_parameter('dc', options[:dc]) if options
|
15
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
20
16
|
|
21
17
|
# If the request fails, it's probably due to a bad path
|
22
18
|
# so return a PathNotFound error.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
return OpenStruct.new JSON.parse(ret.body)
|
19
|
+
ret = @conn.get concat_url url
|
20
|
+
OpenStruct.new JSON.parse(ret.body)
|
21
|
+
rescue Faraday::ClientError
|
22
|
+
raise Diplomat::PathNotFound
|
29
23
|
end
|
30
24
|
|
31
25
|
# Get all the nodes
|
32
26
|
# @param options [Hash] :dc string for dc specific query
|
33
27
|
# @return [OpenStruct] the list of all nodes
|
34
|
-
def get_all
|
35
|
-
url = [
|
36
|
-
url << use_named_parameter('dc', options[:dc]) if options
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
return JSON.parse(ret.body).map { |service| OpenStruct.new service }
|
28
|
+
def get_all(options = nil)
|
29
|
+
url = ['/v1/catalog/nodes']
|
30
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
31
|
+
|
32
|
+
ret = @conn.get concat_url url
|
33
|
+
JSON.parse(ret.body).map { |service| OpenStruct.new service }
|
34
|
+
rescue Faraday::ClientError
|
35
|
+
raise Diplomat::PathNotFound
|
44
36
|
end
|
45
37
|
|
46
38
|
# Register a node
|
47
39
|
# @param definition [Hash] Hash containing definition of a node to register
|
48
40
|
# @return [Boolean]
|
49
|
-
def register(definition, path='/v1/catalog/register')
|
41
|
+
def register(definition, path = '/v1/catalog/register')
|
50
42
|
register = @conn.put path, JSON.dump(definition)
|
51
43
|
|
52
|
-
|
44
|
+
register.status == 200
|
53
45
|
end
|
54
46
|
|
55
47
|
# De-register a node (and all associated services and checks)
|
56
48
|
# @param definition [Hash] Hash containing definition of a node to de-register
|
57
49
|
# @return [Boolean]
|
58
|
-
def deregister(definition, path=
|
50
|
+
def deregister(definition, path = '/v1/catalog/deregister')
|
59
51
|
deregister = @conn.put path, JSON.dump(definition)
|
60
52
|
|
61
|
-
|
53
|
+
deregister.status == 200
|
62
54
|
end
|
63
55
|
end
|
64
56
|
end
|
data/lib/diplomat/nodes.rb
CHANGED
@@ -1,27 +1,25 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'faraday'
|
3
|
-
|
4
1
|
module Diplomat
|
2
|
+
# @depreciated
|
3
|
+
# Methods for interacting with the Consul nodes API endpoint
|
5
4
|
class Nodes < Diplomat::RestClient
|
6
|
-
@access_methods = [
|
5
|
+
@access_methods = [:get, :get_all]
|
7
6
|
|
8
7
|
# Get all nodes
|
9
8
|
# @deprecated Please use Diplomat::Node instead.
|
10
9
|
# @return [OpenStruct] all data associated with the nodes in catalog
|
11
10
|
def get
|
12
|
-
ret = @conn.get
|
13
|
-
|
11
|
+
ret = @conn.get '/v1/catalog/nodes'
|
12
|
+
JSON.parse(ret.body)
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_all(options = nil)
|
16
|
+
url = ['/v1/catalog/nodes']
|
17
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
18
|
+
|
19
|
+
ret = @conn.get concat_url url
|
20
|
+
JSON.parse(ret.body).map { |service| OpenStruct.new service }
|
21
|
+
rescue Faraday::ClientError
|
22
|
+
raise Diplomat::PathNotFound
|
14
23
|
end
|
15
|
-
|
16
|
-
def get_all options=nil
|
17
|
-
url = ["/v1/catalog/nodes"]
|
18
|
-
url << use_named_parameter('dc', options[:dc]) if options and options[:dc]
|
19
|
-
begin
|
20
|
-
ret = @conn.get concat_url url
|
21
|
-
rescue Faraday::ClientError
|
22
|
-
raise Diplomat::PathNotFound
|
23
|
-
end
|
24
|
-
return JSON.parse(ret.body).map { |service| OpenStruct.new service }
|
25
|
-
end
|
26
24
|
end
|
27
25
|
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Diplomat
|
2
|
+
# Methods for interacting with the Consul query API endpoint
|
3
|
+
class Query < Diplomat::RestClient
|
4
|
+
include ApiOptions
|
5
|
+
|
6
|
+
@access_methods = [:get, :get_all, :create, :delete, :update, :execute, :explain]
|
7
|
+
|
8
|
+
# Get a prepared query by it's key
|
9
|
+
# @param key [String] the prepared query ID
|
10
|
+
# @param options [Hash] :dc string for dc specific query
|
11
|
+
# @return [OpenStruct] all data associated with the prepared query
|
12
|
+
def get(key, options = nil)
|
13
|
+
url = ["/v1/query/#{key}"]
|
14
|
+
url += check_acl_token
|
15
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
16
|
+
|
17
|
+
ret = @conn.get concat_url url
|
18
|
+
JSON.parse(ret.body).map { |query| OpenStruct.new query }
|
19
|
+
rescue Faraday::ClientError
|
20
|
+
raise Diplomat::QueryNotFound
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get all prepared queries
|
24
|
+
# @param options [Hash] :dc Consul datacenter to query
|
25
|
+
# @return [OpenStruct] the list of all prepared queries
|
26
|
+
def get_all(options = nil)
|
27
|
+
url = ['/v1/query']
|
28
|
+
url += check_acl_token
|
29
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
30
|
+
|
31
|
+
ret = @conn.get concat_url url
|
32
|
+
JSON.parse(ret.body).map { |query| OpenStruct.new query }
|
33
|
+
rescue Faraday::ClientError
|
34
|
+
raise Diplomat::PathNotFound
|
35
|
+
end
|
36
|
+
|
37
|
+
# Create a prepared query or prepared query template
|
38
|
+
# @param definition [Hash] Hash containing definition of prepared query
|
39
|
+
# @param options [Hash] :dc Consul datacenter to query
|
40
|
+
# @return [String] the ID of the prepared query created
|
41
|
+
def create(definition, options = nil)
|
42
|
+
url = ['/v1/query']
|
43
|
+
url += check_acl_token
|
44
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
45
|
+
@raw = @conn.post do |req|
|
46
|
+
req.url concat_url url
|
47
|
+
req.body = JSON.dump(definition)
|
48
|
+
end
|
49
|
+
|
50
|
+
parse_body
|
51
|
+
rescue Faraday::ClientError
|
52
|
+
raise Diplomat::QueryAlreadyExists
|
53
|
+
end
|
54
|
+
|
55
|
+
# Delete a prepared query or prepared query template
|
56
|
+
# @param key [String] the prepared query ID
|
57
|
+
# @param options [Hash] :dc Consul datacenter to query
|
58
|
+
# @return [Boolean]
|
59
|
+
def delete(key, options = nil)
|
60
|
+
url = ["/v1/query/#{key}"]
|
61
|
+
url += check_acl_token
|
62
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
63
|
+
ret = @conn.delete concat_url url
|
64
|
+
|
65
|
+
ret.status == 200
|
66
|
+
end
|
67
|
+
|
68
|
+
# Update a prepared query or prepared query template
|
69
|
+
# @param key [String] the prepared query ID
|
70
|
+
# @param definition [Hash] Hash containing updated definition of prepared query
|
71
|
+
# @param options [Hash] :dc Consul datacenter to query
|
72
|
+
# @return [Boolean]
|
73
|
+
def update(key, definition, options = nil)
|
74
|
+
url = ["/v1/query/#{key}"]
|
75
|
+
url += check_acl_token
|
76
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
77
|
+
json_definition = JSON.dump(definition)
|
78
|
+
ret = @conn.put do |req|
|
79
|
+
req.url concat_url url
|
80
|
+
req.body = json_definition
|
81
|
+
end
|
82
|
+
|
83
|
+
ret.status == 200
|
84
|
+
end
|
85
|
+
|
86
|
+
# Execute a prepared query or prepared query template
|
87
|
+
# @param key [String] the prepared query ID or name
|
88
|
+
# @param options [Hash] prepared query execution options
|
89
|
+
# @option dc [String] :dc Consul datacenter to query
|
90
|
+
# @option near [String] node name to sort the resulting list in ascending order based on the
|
91
|
+
# estimated round trip time from that node
|
92
|
+
# @option limit [Integer] to limit the size of the return list to the given number of results
|
93
|
+
# @return [OpenStruct] the list of results from the prepared query or prepared query template
|
94
|
+
# rubocop:disable PerceivedComplexity, CyclomaticComplexity, AbcSize
|
95
|
+
def execute(key, options = nil)
|
96
|
+
url = ["/v1/query/#{key}/execute"]
|
97
|
+
url += check_acl_token
|
98
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
99
|
+
url << use_named_parameter('near', options[:near]) if options && options[:near]
|
100
|
+
url << use_named_parameter('limit', options[:limit]) if options && options[:limit]
|
101
|
+
|
102
|
+
ret = @conn.get concat_url url
|
103
|
+
OpenStruct.new JSON.parse(ret.body)
|
104
|
+
rescue Faraday::ClientError
|
105
|
+
raise Diplomat::QueryNotFound
|
106
|
+
end
|
107
|
+
# rubocop:enable PerceivedComplexity, CyclomaticComplexity, AbcSize
|
108
|
+
|
109
|
+
# Get the fully rendered query template
|
110
|
+
# @param key [String] the prepared query ID or name
|
111
|
+
# @param options [Hash] :dc Consul datacenter to query
|
112
|
+
# @return [OpenStruct] the list of results from the prepared query or prepared query template
|
113
|
+
def explain(key, options = nil)
|
114
|
+
url = ["/v1/query/#{key}/explain"]
|
115
|
+
url += check_acl_token
|
116
|
+
url << use_named_parameter('dc', options[:dc]) if options && options[:dc]
|
117
|
+
|
118
|
+
ret = @conn.get concat_url url
|
119
|
+
OpenStruct.new JSON.parse(ret.body)
|
120
|
+
rescue Faraday::ClientError
|
121
|
+
raise Diplomat::QueryNotFound
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/diplomat/rest_client.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
require 'json'
|
3
|
-
|
4
1
|
module Diplomat
|
2
|
+
# Base class for interacting with the Consul RESTful API
|
5
3
|
class RestClient
|
6
|
-
|
7
4
|
@access_methods = []
|
8
5
|
|
9
6
|
# Initialize the fadaray connection
|
10
7
|
# @param api_connection [Faraday::Connection,nil] supply mock API Connection
|
11
|
-
def initialize
|
8
|
+
def initialize(api_connection = nil)
|
12
9
|
start_connection api_connection
|
13
10
|
end
|
14
11
|
|
@@ -17,14 +14,14 @@ module Diplomat
|
|
17
14
|
# @param value [String] the value of the parameter
|
18
15
|
# @return [Array] the resultant parameter string inside an array.
|
19
16
|
def use_named_parameter(name, value)
|
20
|
-
|
17
|
+
value ? ["#{name}=#{value}"] : []
|
21
18
|
end
|
22
19
|
|
23
20
|
# Assemble a url from an array of parts.
|
24
21
|
# @param parts [Array] the url chunks to be assembled
|
25
22
|
# @return [String] the resultant url string
|
26
|
-
def concat_url
|
27
|
-
if parts.length > 1
|
23
|
+
def concat_url(parts)
|
24
|
+
if parts.length > 1
|
28
25
|
parts.first + '?' + parts.drop(1).join('&')
|
29
26
|
else
|
30
27
|
parts.first
|
@@ -32,8 +29,7 @@ module Diplomat
|
|
32
29
|
end
|
33
30
|
|
34
31
|
class << self
|
35
|
-
|
36
|
-
def access_method? meth_id
|
32
|
+
def access_method?(meth_id)
|
37
33
|
@access_methods.include? meth_id
|
38
34
|
end
|
39
35
|
|
@@ -78,13 +74,13 @@ module Diplomat
|
|
78
74
|
|
79
75
|
# Build the API Client
|
80
76
|
# @param api_connection [Faraday::Connection,nil] supply mock API Connection
|
81
|
-
def start_connection
|
77
|
+
def start_connection(api_connection = nil)
|
82
78
|
@conn = build_connection(api_connection)
|
83
79
|
@conn_no_err = build_connection(api_connection, true)
|
84
80
|
end
|
85
81
|
|
86
|
-
def build_connection(api_connection, raise_error=false)
|
87
|
-
|
82
|
+
def build_connection(api_connection, raise_error = false)
|
83
|
+
api_connection || Faraday.new(Diplomat.configuration.url, Diplomat.configuration.options) do |faraday|
|
88
84
|
faraday.adapter Faraday.default_adapter
|
89
85
|
faraday.request :url_encoded
|
90
86
|
faraday.response :raise_error unless raise_error
|
@@ -95,85 +91,85 @@ module Diplomat
|
|
95
91
|
end
|
96
92
|
end
|
97
93
|
|
98
|
-
#Converts k/v data into ruby hash
|
94
|
+
# Converts k/v data into ruby hash
|
95
|
+
# rubocop:disable MethodLength, AbcSize
|
99
96
|
def convert_to_hash(data)
|
100
97
|
collection = []
|
101
98
|
master = {}
|
102
99
|
data.each do |item|
|
103
|
-
split_up = item[:key].split
|
100
|
+
split_up = item[:key].split('/')
|
104
101
|
sub_hash = {}
|
105
102
|
temp = nil
|
106
103
|
real_size = split_up.size - 1
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
104
|
+
(0..real_size).each do |i|
|
105
|
+
if i.zero?
|
106
|
+
temp = {}
|
107
|
+
sub_hash[split_up[i]] = temp
|
108
|
+
next
|
109
|
+
end
|
110
|
+
if i == real_size
|
111
|
+
temp[split_up[i]] = item[:value]
|
112
|
+
else
|
113
|
+
new_h = {}
|
114
|
+
temp[split_up[i]] = new_h
|
115
|
+
temp = new_h
|
116
|
+
end
|
117
|
+
end
|
118
|
+
collection << sub_hash
|
122
119
|
end
|
123
120
|
|
124
121
|
collection.each do |h|
|
125
|
-
|
126
|
-
master = n
|
122
|
+
master = deep_merge(master, h)
|
127
123
|
end
|
128
124
|
master
|
129
125
|
end
|
126
|
+
# rubocop:enable MethodLength, AbcSize
|
130
127
|
|
131
128
|
def deep_merge(first, second)
|
132
|
-
|
133
|
-
|
129
|
+
merger = proc { |_key, v1, v2| v1.is_a?(Hash) && v2.is_a?(Hash) ? v1.merge(v2, &merger) : v2 }
|
130
|
+
first.merge(second, &merger)
|
134
131
|
end
|
135
132
|
|
136
133
|
# Parse the body, apply it to the raw attribute
|
137
134
|
def parse_body
|
138
135
|
return JSON.parse(@raw.body) if @raw.status == 200
|
139
|
-
raise Diplomat::UnknownStatus, "status #{@raw.status}"
|
136
|
+
raise Diplomat::UnknownStatus, "status #{@raw.status}: #{@raw.body}"
|
140
137
|
end
|
141
138
|
|
142
139
|
# Return @raw with Value fields decoded
|
143
140
|
def decode_values
|
144
141
|
return @raw if @raw.first.is_a? String
|
145
|
-
@raw.
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
acc
|
142
|
+
@raw.each_with_object([]) do |acc, el|
|
143
|
+
acc['Value'] = Base64.decode64(acc['Value']) rescue nil # rubocop:disable RescueModifier
|
144
|
+
el << acc
|
145
|
+
el
|
150
146
|
end
|
151
147
|
end
|
152
148
|
|
153
149
|
# Get the key/value(s) from the raw output
|
154
|
-
|
150
|
+
# rubocop:disable PerceivedComplexity, MethodLength, CyclomaticComplexity, AbcSize
|
151
|
+
def return_value(nil_values = false, transformation = nil)
|
155
152
|
@value = decode_values
|
156
|
-
if @value.first.is_a? String
|
157
|
-
|
158
|
-
|
159
|
-
@value = @value.
|
160
|
-
@value = transformation.call(@value) if transformation and not @value.nil?
|
153
|
+
return @value if @value.first.is_a? String
|
154
|
+
if @value.count == 1
|
155
|
+
@value = @value.first['Value']
|
156
|
+
@value = transformation.call(@value) if transformation && !@value.nil?
|
161
157
|
return @value
|
162
158
|
else
|
163
159
|
@value = @value.map do |el|
|
164
|
-
el[
|
165
|
-
{ :
|
160
|
+
el['Value'] = transformation.call(el['Value']) if transformation && !el['Value'].nil?
|
161
|
+
{ key: el['Key'], value: el['Value'] } if el['Value'] || nil_values
|
166
162
|
end.compact
|
167
163
|
end
|
168
164
|
end
|
165
|
+
# rubocop:enable PerceivedComplexity, MethodLength, CyclomaticComplexity, AbcSize
|
169
166
|
|
170
167
|
# Get the name and payload(s) from the raw output
|
171
168
|
def return_payload
|
172
169
|
@value = @raw.map do |e|
|
173
|
-
{ :
|
174
|
-
:
|
170
|
+
{ name: e['Name'],
|
171
|
+
payload: (Base64.decode64(e['Payload']) unless e['Payload'].nil?) }
|
175
172
|
end
|
176
173
|
end
|
177
|
-
|
178
174
|
end
|
179
175
|
end
|