diplomat 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.
- checksums.yaml +4 -4
- data/README.md +38 -0
- data/lib/diplomat.rb +1 -1
- data/lib/diplomat/error.rb +2 -0
- data/lib/diplomat/event.rb +163 -0
- data/lib/diplomat/kv.rb +10 -38
- data/lib/diplomat/rest_client.rb +37 -5
- data/lib/diplomat/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c4fdef4cc41c9b67236ee64307e8f156ffcc790
|
4
|
+
data.tar.gz: 3506d1b24c567796d5fa397ae3055da5efbac41f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 837c53a701c4a1d3d1c2d8972bde7895530319dd056dcb9d5d1d9567c0c59ea130e3dca260df277f3f145bec30d18891987a9519e74551e21682090e95fc237d
|
7
|
+
data.tar.gz: 8a0d0aab7c784b5af4bb39a6d7aeb24b717d9c49134293542dc5ba5aa19a53f373bf067502ff0b30a8b7dff40951a49deb39c6cb935e56a1fedf33e4af380a84
|
data/README.md
CHANGED
@@ -118,6 +118,39 @@ Release a lock:
|
|
118
118
|
Diplomat::Lock.release("/key/to/lock", sessionid )
|
119
119
|
```
|
120
120
|
|
121
|
+
### Events
|
122
|
+
|
123
|
+
Fire an event:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
Diplomat::Event.fire('do_something', 'payload')
|
127
|
+
```
|
128
|
+
|
129
|
+
List all events with a certain name received by the local agent:
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
Diplomat::Event.get_all('do_something')
|
133
|
+
```
|
134
|
+
|
135
|
+
Get the latest event with a certain name received by the local agent:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
Diplomat::Event.get('do_something')
|
139
|
+
```
|
140
|
+
|
141
|
+
Iterate through the events with a certain name received by the local agent:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
events = Enumerator.new do |y|
|
145
|
+
ret = {token: :first}
|
146
|
+
while ret = begin Diplomat::Event.get('do_something', ret[:token], :reject) rescue nil end
|
147
|
+
y.yield(ret[:value])
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
events.each{ |e| puts e }
|
152
|
+
```
|
153
|
+
|
121
154
|
### Custom configuration
|
122
155
|
|
123
156
|
You can create a custom configuration using the following syntax:
|
@@ -136,13 +169,18 @@ This is traditionally kept inside the `config/initializers` directory if you're
|
|
136
169
|
### Todo
|
137
170
|
|
138
171
|
- [ ] Updating Docs with latest changes
|
172
|
+
- [ ] Using custom objects for response objects (instead of openStruct)
|
139
173
|
- [ ] PUTing and DELETEing services
|
174
|
+
- [ ] Custom SSL Cert Middleware for faraday
|
140
175
|
- [x] Allowing the custom configuration of the consul url to connect to
|
141
176
|
- [x] Deleting Keys
|
142
177
|
- [x] Listing available services
|
143
178
|
- [x] Health
|
144
179
|
- [x] Members
|
145
180
|
- [x] Status
|
181
|
+
- [x] Datacenter support for services
|
182
|
+
- [x] Ruby 1.8 support
|
183
|
+
- [x] Events
|
146
184
|
|
147
185
|
|
148
186
|
## Enjoy!
|
data/lib/diplomat.rb
CHANGED
@@ -20,7 +20,7 @@ module Diplomat
|
|
20
20
|
self.root_path = File.expand_path "..", __FILE__
|
21
21
|
self.lib_path = File.expand_path "../diplomat", __FILE__
|
22
22
|
|
23
|
-
require_libs "configuration", "rest_client", "kv", "service", "members", "check", "health", "session", "lock", "error"
|
23
|
+
require_libs "configuration", "rest_client", "kv", "service", "members", "check", "health", "session", "lock", "error", "event"
|
24
24
|
self.configuration ||= Diplomat::Configuration.new
|
25
25
|
|
26
26
|
class << self
|
data/lib/diplomat/error.rb
CHANGED
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Diplomat
|
4
|
+
class Event < Diplomat::RestClient
|
5
|
+
|
6
|
+
# Send an event
|
7
|
+
# @param name [String] the event name
|
8
|
+
# @param value [String] the payload of the event
|
9
|
+
# @param service [String] the target service name
|
10
|
+
# @param node [String] the target node name
|
11
|
+
# @param tag [String] the target tag name, must only be used with service
|
12
|
+
# @return [nil]
|
13
|
+
def fire name, value=nil, service=nil, node=nil, tag=nil
|
14
|
+
raw = @conn.put do |req|
|
15
|
+
url = [ "/v1/event/fire/#{name}" ]
|
16
|
+
url += use_named_parameter("service", service)
|
17
|
+
url += use_named_parameter("node", node)
|
18
|
+
url += use_named_parameter("tag", tag) if service
|
19
|
+
req.url concat_url url
|
20
|
+
req.body = value unless value.nil?
|
21
|
+
end
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get the list of events matching name
|
26
|
+
# @param name [String] the name of the event (regex)
|
27
|
+
# @param not_found [Symbol] behaviour if there are no events matching name;
|
28
|
+
# :reject with exception, or :wait for a non-empty list
|
29
|
+
# @param found [Symbol] behaviour if there are already events matching name;
|
30
|
+
# :reject with exception, :return its current value, or :wait for its next value
|
31
|
+
# @return [Array[hash]] The list of { :name, :payload } hashes
|
32
|
+
# @note
|
33
|
+
# Events are sent via the gossip protocol; there is no guarantee of delivery
|
34
|
+
# success or order, but the local agent will store up to 256 events that do
|
35
|
+
# arrive. This method lists those events.
|
36
|
+
# It has the same semantics as Kv::get, except the value returned is a list
|
37
|
+
# i.e. the current value is all events up until now, the next value is the
|
38
|
+
# current list plus the next event to arrive.
|
39
|
+
# To get a specific event in the sequence, @see #get
|
40
|
+
# When trying to get a list of events matching a name, there are two possibilities:
|
41
|
+
# - The list doesn't (yet) exist / is empty
|
42
|
+
# - The list exists / is non-empty
|
43
|
+
# The combination of not_found and found behaviour gives maximum possible
|
44
|
+
# flexibility. For X: reject, R: return, W: wait
|
45
|
+
# - X X - meaningless; never return a value
|
46
|
+
# - X R - "normal" non-blocking get operation. Default
|
47
|
+
# - X W - get the next value only (must have a current value)
|
48
|
+
# - W X - get the first value only (must not have a current value)
|
49
|
+
# - W R - get the first or current value; always return something, but
|
50
|
+
# block only when necessary
|
51
|
+
# - W W - get the first or next value; wait until there is an update
|
52
|
+
def get_all name=nil, not_found=:reject, found=:return
|
53
|
+
url = ["/v1/event/list"]
|
54
|
+
url += use_named_parameter("name", name)
|
55
|
+
|
56
|
+
# Event list never returns 404 or blocks, but may return an empty list
|
57
|
+
@raw = @conn.get concat_url url
|
58
|
+
if JSON.parse(@raw.body).count == 0
|
59
|
+
case not_found
|
60
|
+
when :reject
|
61
|
+
raise Diplomat::EventNotFound, name
|
62
|
+
when :wait
|
63
|
+
index = @raw.headers["x-consul-index"]
|
64
|
+
end
|
65
|
+
else
|
66
|
+
case found
|
67
|
+
when :reject
|
68
|
+
raise Diplomat::EventAlreadyExists, name
|
69
|
+
when :return
|
70
|
+
parse_body
|
71
|
+
return return_payload
|
72
|
+
when :wait
|
73
|
+
index = @raw.headers["x-consul-index"]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Wait for first/next event
|
78
|
+
url += use_named_parameter("index", index)
|
79
|
+
@raw = @conn.get do |req|
|
80
|
+
req.url concat_url url
|
81
|
+
req.options.timeout = 86400
|
82
|
+
end
|
83
|
+
parse_body
|
84
|
+
return_payload
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get a specific event in the sequence matching name
|
88
|
+
# @param name [String] the name of the event (regex)
|
89
|
+
# @param token [String|Symbol] the ordinate of the event in the sequence;
|
90
|
+
# String are tokens returned by previous calls to this function
|
91
|
+
# Symbols are the special tokens :first, :last, and :next
|
92
|
+
# @param not_found [Symbol] behaviour if there is no matching event;
|
93
|
+
# :reject with exception, or :wait for event
|
94
|
+
# @param found [Symbol] behaviour if there is a matching event;
|
95
|
+
# :reject with exception, or :return its current value
|
96
|
+
# @return [hash] A hash with keys :value and :token;
|
97
|
+
# :value is a further hash of the :name and :payload of the event,
|
98
|
+
# :token is the event's ordinate in the sequence and can be passed to future calls to get the subsequent event
|
99
|
+
# @note
|
100
|
+
# Whereas the consul API for events returns all past events that match
|
101
|
+
# name, this method allows retrieval of individual events from that
|
102
|
+
# sequence. However, because consul's API isn't conducive to this, we can
|
103
|
+
# offer first, last, next (last + 1) events, or arbitrary events in the
|
104
|
+
# middle, though these can only be identified relative to the preceding
|
105
|
+
# event. However, this is ideal for iterating through the sequence of
|
106
|
+
# events (while being sure that none are missed).
|
107
|
+
def get name=nil, token=:last, not_found=:wait, found=:return
|
108
|
+
url = ["/v1/event/list"]
|
109
|
+
url += use_named_parameter("name", name)
|
110
|
+
@raw = @conn.get concat_url url
|
111
|
+
body = JSON.parse(@raw.body)
|
112
|
+
# TODO: deal with unknown symbols, invalid indices (find_index will return nil)
|
113
|
+
idx = case token
|
114
|
+
when :first then 0
|
115
|
+
when :last then body.length - 1
|
116
|
+
when :next then body.length
|
117
|
+
else body.find_index { |e| e["ID"] == token } + 1
|
118
|
+
end
|
119
|
+
if idx == body.length then
|
120
|
+
case not_found
|
121
|
+
when :reject
|
122
|
+
raise Diplomat::EventNotFound, name
|
123
|
+
when :wait
|
124
|
+
# Wait for next event
|
125
|
+
index = @raw.headers["x-consul-index"]
|
126
|
+
url += use_named_parameter("index", index)
|
127
|
+
@raw = @conn.get do |req|
|
128
|
+
req.url concat_url url
|
129
|
+
req.options.timeout = 86400
|
130
|
+
end
|
131
|
+
body = JSON.parse(@raw.body)
|
132
|
+
event = body.last # If it's possible for two events to arrive at once, this needs to #find again
|
133
|
+
end
|
134
|
+
else
|
135
|
+
case found
|
136
|
+
when :reject
|
137
|
+
raise Diplomat::EventAlreadyExits, name
|
138
|
+
when :return
|
139
|
+
event = body[idx]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
{ :value => { :name => event["Name"], :payload => Base64.decode64(event["Payload"]) },
|
144
|
+
:token => event["ID"] }
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
# @note This is sugar, see (#fire)
|
149
|
+
def self.fire *args
|
150
|
+
Diplomat::Event.new.fire *args
|
151
|
+
end
|
152
|
+
|
153
|
+
# @note This is sugar, see (#get_all)
|
154
|
+
def self.get_all *args
|
155
|
+
Diplomat::Event.new.get_all *args
|
156
|
+
end
|
157
|
+
|
158
|
+
# @note This is sugar, see (#get)
|
159
|
+
def self.get *args
|
160
|
+
Diplomat::Event.new.get *args
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
data/lib/diplomat/kv.rb
CHANGED
@@ -13,7 +13,7 @@ module Diplomat
|
|
13
13
|
# @param not_found [Symbol] behaviour if the key doesn't exist;
|
14
14
|
# :reject with exception, or :wait for it to appear
|
15
15
|
# @param found [Symbol] behaviour if the key does exist;
|
16
|
-
# :reject with exception, :
|
16
|
+
# :reject with exception, :return its current value, or :wait for its next value
|
17
17
|
# @return [String] The base64-decoded value associated with the key
|
18
18
|
# @note
|
19
19
|
# When trying to access a key, there are two possibilites:
|
@@ -33,8 +33,8 @@ module Diplomat
|
|
33
33
|
@options = options
|
34
34
|
|
35
35
|
url = ["/v1/kv/#{@key}"]
|
36
|
-
url += check_acl_token
|
37
|
-
url += use_consistency(@options)
|
36
|
+
url += check_acl_token
|
37
|
+
url += use_consistency(@options)
|
38
38
|
|
39
39
|
# 404s OK using this connection
|
40
40
|
raw = @conn_no_err.get concat_url url
|
@@ -61,10 +61,7 @@ module Diplomat
|
|
61
61
|
end
|
62
62
|
|
63
63
|
# Wait for first/next value
|
64
|
-
url
|
65
|
-
url += check_acl_token unless check_acl_token.nil?
|
66
|
-
url += use_consistency(@options) unless use_consistency(@options).nil?
|
67
|
-
url += ["index=#{index}"]
|
64
|
+
url += use_named_parameter("index", index)
|
68
65
|
@raw = @conn.get do |req|
|
69
66
|
req.url concat_url url
|
70
67
|
req.options.timeout = 86400
|
@@ -83,8 +80,8 @@ module Diplomat
|
|
83
80
|
@options = options
|
84
81
|
@raw = @conn.put do |req|
|
85
82
|
url = ["/v1/kv/#{key}"]
|
86
|
-
url += check_acl_token
|
87
|
-
url += use_cas(@options)
|
83
|
+
url += check_acl_token
|
84
|
+
url += use_cas(@options)
|
88
85
|
req.url concat_url url
|
89
86
|
req.body = value
|
90
87
|
end
|
@@ -101,7 +98,7 @@ module Diplomat
|
|
101
98
|
def delete key
|
102
99
|
@key = key
|
103
100
|
url = ["/v1/kv/#{@key}"]
|
104
|
-
url += check_acl_token
|
101
|
+
url += check_acl_token
|
105
102
|
@raw = @conn.delete concat_url url
|
106
103
|
end
|
107
104
|
|
@@ -122,41 +119,16 @@ module Diplomat
|
|
122
119
|
|
123
120
|
private
|
124
121
|
|
125
|
-
# Parse the body, apply it to the raw attribute
|
126
|
-
def parse_body
|
127
|
-
@raw = JSON.parse(@raw.body)
|
128
|
-
end
|
129
|
-
|
130
|
-
# Get the key from the raw output
|
131
|
-
def return_key
|
132
|
-
@key = @raw["Key"]
|
133
|
-
end
|
134
|
-
|
135
|
-
# Get the value from the raw output
|
136
|
-
def return_value
|
137
|
-
if @raw.count == 1
|
138
|
-
@value = @raw.first["Value"]
|
139
|
-
@value = Base64.decode64(@value) unless @value.nil?
|
140
|
-
else
|
141
|
-
@value = @raw.map do |e|
|
142
|
-
{
|
143
|
-
:key => e["Key"],
|
144
|
-
:value => e["Value"].nil? ? e["Value"] : Base64.decode64(e["Value"])
|
145
|
-
}
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
122
|
def check_acl_token
|
151
|
-
|
123
|
+
use_named_parameter("token", Diplomat.configuration.acl_token)
|
152
124
|
end
|
153
125
|
|
154
126
|
def use_cas(options)
|
155
|
-
|
127
|
+
if options then use_named_parameter("cas", options[:cas]) else [] end
|
156
128
|
end
|
157
129
|
|
158
130
|
def use_consistency(options)
|
159
|
-
["#{options[:consistency]}"]
|
131
|
+
if options && options[:consistency] then ["#{options[:consistency]}"] else [] end
|
160
132
|
end
|
161
133
|
end
|
162
134
|
end
|
data/lib/diplomat/rest_client.rb
CHANGED
@@ -8,12 +8,16 @@ module Diplomat
|
|
8
8
|
start_connection api_connection
|
9
9
|
end
|
10
10
|
|
11
|
+
def use_named_parameter(name, value)
|
12
|
+
if value then ["#{name}=#{value}"] else [] end
|
13
|
+
end
|
14
|
+
|
11
15
|
def concat_url parts
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
if parts.length > 1 then
|
17
|
+
parts.first + '?' + parts.drop(1).join('&')
|
18
|
+
else
|
19
|
+
parts.first
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
23
|
private
|
@@ -41,5 +45,33 @@ module Diplomat
|
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
48
|
+
# Parse the body, apply it to the raw attribute
|
49
|
+
def parse_body
|
50
|
+
@raw = JSON.parse(@raw.body)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Get the key/value(s) from the raw output
|
54
|
+
def return_value
|
55
|
+
if @raw.count == 1
|
56
|
+
@value = @raw.first["Value"]
|
57
|
+
@value = Base64.decode64(@value) unless @value.nil?
|
58
|
+
else
|
59
|
+
@value = @raw.map do |e|
|
60
|
+
{
|
61
|
+
:key => e["Key"],
|
62
|
+
:value => (Base64.decode64(e["Value"]) unless e["Value"].nil?)
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get the name and payload(s) from the raw output
|
69
|
+
def return_payload
|
70
|
+
@value = @raw.map do |e|
|
71
|
+
{ :name => e["Name"],
|
72
|
+
:payload => (Base64.decode64(e["Payload"]) unless e["Payload"].nil?) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
44
76
|
end
|
45
77
|
end
|
data/lib/diplomat/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diplomat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Hamelink
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -180,6 +180,7 @@ files:
|
|
180
180
|
- lib/diplomat/check.rb
|
181
181
|
- lib/diplomat/configuration.rb
|
182
182
|
- lib/diplomat/error.rb
|
183
|
+
- lib/diplomat/event.rb
|
183
184
|
- lib/diplomat/health.rb
|
184
185
|
- lib/diplomat/kv.rb
|
185
186
|
- lib/diplomat/lock.rb
|