villein 0.0.2 → 0.1.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: df2731fb88973b484824361021f7e95383f6642c
4
- data.tar.gz: 9b68ffc3464ee705d645446fdf017819da130340
3
+ metadata.gz: 7f55592c52186b2368ce3cdee25bc3726321ab5b
4
+ data.tar.gz: 6f20e0f243da17e2c400d1207069fe796a2022f0
5
5
  SHA512:
6
- metadata.gz: a375d7bc0d40dc65b5fe94bc5b80ed0074a1efd53c48b5ced070d7bb4ed8cab085ecad3cea4994c3a79bf7512338995db5b65b9e7f093f3dcd46fcd8596d056a
7
- data.tar.gz: 4eadcdd42d2619e7d77c5ee1ece33029fb5218f437ed9c4b10a80a0b06a1edcc278f357ac1c195475120f14e3516090f025b2cfe7cbbcf41b56ef80123c37980
6
+ metadata.gz: 202eda9a335d1239cb69f025c9239d715ca566cc710e8e2a0239bf42e1b2542b90cfea5948b65b08442770fe373b5abb2c32dbd459ca4018f8a0428f916e4f42
7
+ data.tar.gz: 320efc986bf0c185db5ce68dcecb296a5e5a4a9b97204927a61ba42c7b90f02d283150e2af9776d16555493de324dea15bc5b61c28e30f703bcc030ed8c2a5f8
@@ -6,6 +6,19 @@ module Villein
6
6
  # Villein::Client allows you to order existing serf agent.
7
7
  # You will need RPC address and agent name to command.
8
8
  class Client
9
+
10
+ ##
11
+ # for serf command failures
12
+ class SerfError < Exception; end
13
+
14
+ ##
15
+ # Error for the given argument exceeds the limit of serf when setting tags and sending events.
16
+ class LengthExceedsLimitError < SerfError; end
17
+
18
+ ##
19
+ # Error for connection failures
20
+ class SerfConnectionError < SerfError; end
21
+
9
22
  def initialize(rpc_addr, name: nil, serf: 'serf', silence: true)
10
23
  @rpc_addr = rpc_addr
11
24
  @name = name
@@ -56,7 +69,7 @@ module Villein
56
69
  options.push('-tag', "#{tag}=#{val}")
57
70
  end
58
71
 
59
- json = IO.popen(['serf', 'members', "-rpc-addr=#{rpc_addr}", *options], 'r', &:read)
72
+ json = call_serf('members', *options)
60
73
  response = JSON.parse(json)
61
74
 
62
75
  response["members"]
@@ -94,14 +107,23 @@ module Villein
94
107
  private
95
108
 
96
109
  def call_serf(cmd, *args)
97
- options = {}
110
+ status, out = IO.popen([@serf, cmd, "-rpc-addr=#{rpc_addr}", *args, err: [:child, :out]], 'r') do |io|
111
+ _, s = Process.waitpid2(io.pid)
112
+ [s, io.read]
113
+ end
98
114
 
99
- if silence?
100
- options[:out] = File::NULL
101
- options[:err] = File::NULL
115
+ unless status.success?
116
+ case out
117
+ when /^Error connecting to Serf agent:/
118
+ raise SerfConnectionError, out.chomp
119
+ when /exceeds limit of \d+ bytes$/
120
+ raise LengthExceedsLimitError, out.chomp
121
+ else
122
+ raise SerfError, out.chomp
123
+ end
102
124
  end
103
125
 
104
- system @serf, cmd, "-rpc-addr=#{rpc_addr}", *args, options
126
+ out
105
127
  end
106
128
  end
107
129
  end
@@ -1,3 +1,3 @@
1
1
  module Villein
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/spec/client_spec.rb CHANGED
@@ -5,58 +5,132 @@ describe Villein::Client do
5
5
  let(:name) { 'the-node' }
6
6
  subject(:client) { described_class.new('x.x.x.x:nnnn', name: name) }
7
7
 
8
- def expect_serf(cmd, *args, retval: true, out: File::NULL)
9
- expect(subject).to receive(:system) \
10
- .with('serf', cmd, '-rpc-addr=x.x.x.x:nnnn', *args, out: out, err: out) \
11
- .and_return(retval)
8
+ def expect_serf(cmd, *args, success: true, message: '')
9
+ if [cmd, *args].compact.empty?
10
+ expect(IO).to receive(:popen) \
11
+ .with(any_args)
12
+ .and_yield(double('io', read: message, pid: 727272))
13
+
14
+ else
15
+ expect(IO).to receive(:popen) \
16
+ .with(['serf', cmd, '-rpc-addr=x.x.x.x:nnnn', *args,
17
+ err: [:child, :out]],
18
+ 'r') \
19
+ .and_yield(double('io', read: message, pid: 727272))
20
+ end
21
+
22
+ status = double('proc-status', pid: 727272, success?: success)
23
+
24
+ allow(Process).to receive(:waitpid2).with(727272).and_return([727272, status])
25
+ end
26
+
27
+ shared_examples "failure cases" do
28
+ context "when command failed" do
29
+ it "raises error" do
30
+ expect_serf(nil, success: false, message: 'err')
31
+
32
+ expect {
33
+ subject
34
+ }.to raise_error(Villein::Client::SerfError, 'err')
35
+ end
36
+ end
37
+
38
+ context "when connection failed" do
39
+ it "raises error" do
40
+ expect_serf(nil,
41
+ success: false,
42
+ message: 'Error connecting to Serf agent: dial tcp x.x.x.x:nnnn: connection refused')
43
+
44
+ expect {
45
+ subject
46
+ }.to raise_error(
47
+ Villein::Client::SerfConnectionError,
48
+ 'Error connecting to Serf agent: dial tcp x.x.x.x:nnnn: connection refused')
49
+ end
50
+ end
12
51
  end
13
52
 
14
53
  describe "#event" do
54
+ subject { client.event('test', 'payload') }
55
+
15
56
  it "sends user event" do
16
57
  expect_serf('event', 'test', 'payload')
17
58
 
18
- client.event('test', 'payload')
59
+ subject
19
60
  end
20
61
 
21
62
  context "with coalesce=false" do
63
+ subject { client.event('test', 'payload', coalesce: false) }
64
+
22
65
  it "sends user event with the option" do
23
66
  expect_serf('event', '-coalesce=false', 'test', 'payload')
24
67
 
25
- client.event('test', 'payload', coalesce: false)
68
+ subject
69
+ end
70
+ end
71
+
72
+ include_examples "failure cases"
73
+
74
+ context "when length exceeds limit" do
75
+ it "raises error" do
76
+ expect_serf('event', 'test', 'payload',
77
+ success: false,
78
+ message: 'Error sending event: user event exceeds limit of 256 bytes')
79
+
80
+ expect {
81
+ subject
82
+ }.to raise_error(
83
+ Villein::Client::LengthExceedsLimitError,
84
+ 'Error sending event: user event exceeds limit of 256 bytes')
26
85
  end
27
86
  end
87
+
28
88
  end
29
89
 
30
90
  describe "#join" do
91
+ subject { client.join('y.y.y.y:nnnn') }
92
+
31
93
  it "attempts to join another node" do
32
94
  expect_serf('join', 'y.y.y.y:nnnn')
33
95
 
34
- client.join('y.y.y.y:nnnn')
96
+ subject
35
97
  end
36
98
 
37
99
  context "with replay=true" do
100
+ subject { client.join('y.y.y.y:nnnn', replay: true) }
101
+
38
102
  it "attempts to join another node with replaying" do
39
103
  expect_serf('join', '-replay', 'y.y.y.y:nnnn')
40
104
 
41
- client.join('y.y.y.y:nnnn', replay: true)
105
+ subject
42
106
  end
43
107
  end
108
+
109
+ include_examples "failure cases"
44
110
  end
45
111
 
46
112
  describe "#leave" do
113
+ subject { client.leave }
114
+
47
115
  it "attempts to leave from cluster" do
48
116
  expect_serf('leave')
49
117
 
50
- client.leave
118
+ subject
51
119
  end
120
+
121
+ include_examples "failure cases"
52
122
  end
53
123
 
54
124
  describe "#force_leave" do
125
+ subject { client.force_leave('the-node') }
126
+
55
127
  it "attempts to remove member forcely" do
56
128
  expect_serf('force-leave', 'the-node')
57
129
 
58
- client.force_leave('the-node')
130
+ subject
59
131
  end
132
+
133
+ include_examples "failure cases"
60
134
  end
61
135
 
62
136
  describe "#members" do
@@ -65,18 +139,18 @@ describe Villein::Client do
65
139
  "tags":{"key":"val"},"status":"alive","protocol":{"max":4,"min":2,"version":4}}]}
66
140
  EOJ
67
141
 
142
+ subject(:members) { client.members }
143
+
68
144
  it "returns member list" do
69
- allow(IO).to receive(:popen).with(%w(serf members -rpc-addr=x.x.x.x:nnnn -format json), 'r') \
70
- .and_yield(double('io', read: json))
145
+ expect_serf('members', '-format', 'json', message: json)
71
146
 
72
- expect(client.members).to be_a_kind_of(Array)
73
- expect(client.members[0]["name"]).to eq "the-node"
147
+ expect(members).to be_a_kind_of(Array)
148
+ expect(members[0]["name"]).to eq "the-node"
74
149
  end
75
150
 
76
151
  context "with status filter" do
77
152
  it "returns member list" do
78
- allow(IO).to receive(:popen).with(%w(serf members -rpc-addr=x.x.x.x:nnnn -format json -status alive), 'r') \
79
- .and_yield(double('io', read: json))
153
+ expect_serf('members', '-format', 'json', '-status', 'alive', message: json)
80
154
 
81
155
  client.members(status: :alive)
82
156
  end
@@ -84,8 +158,7 @@ describe Villein::Client do
84
158
 
85
159
  context "with name filter" do
86
160
  it "returns member list" do
87
- allow(IO).to receive(:popen).with(%w(serf members -rpc-addr=x.x.x.x:nnnn -format json -name node), 'r') \
88
- .and_yield(double('io', read: json))
161
+ expect_serf('members', '-format', 'json', '-name', 'node', message: json)
89
162
 
90
163
  client.members(name: 'node')
91
164
  end
@@ -93,12 +166,13 @@ describe Villein::Client do
93
166
 
94
167
  context "with tag filter" do
95
168
  it "returns member list" do
96
- allow(IO).to receive(:popen).with(%w(serf members -rpc-addr=x.x.x.x:nnnn -format json -tag a=1 -tag b=2), 'r') \
97
- .and_yield(double('io', read: json))
169
+ expect_serf('members', *%w(-format json -tag a=1 -tag b=2), message: json)
98
170
 
99
171
  client.members(tags: {a: '1', b: '2'})
100
172
  end
101
173
  end
174
+
175
+ include_examples "failure cases"
102
176
  end
103
177
 
104
178
  describe "#tags" do
@@ -117,19 +191,41 @@ describe Villein::Client do
117
191
  end
118
192
 
119
193
  describe "#set_tag" do
194
+ subject { client.set_tag('newkey', 'newval') }
195
+
120
196
  it "sets tag" do
121
197
  expect_serf('tags', '-set', 'newkey=newval')
122
198
 
123
- client.set_tag('newkey', 'newval')
199
+ subject
200
+ end
201
+
202
+ include_examples "failure cases"
203
+
204
+ context "when length exceeds limit" do
205
+ it "raises error" do
206
+ expect_serf('tags', '-set', 'newkey=newval',
207
+ success: false,
208
+ message: 'Error setting tags: Encoded length of tags exceeds limit of 512 bytes')
209
+
210
+ expect {
211
+ client.set_tag('newkey', 'newval')
212
+ }.to raise_error(
213
+ Villein::Client::LengthExceedsLimitError,
214
+ 'Error setting tags: Encoded length of tags exceeds limit of 512 bytes')
215
+ end
124
216
  end
125
217
  end
126
218
 
127
219
  describe "#delete_tag" do
220
+ subject { client.delete_tag('newkey') }
221
+
128
222
  it "deletes tag" do
129
223
  expect_serf('tags', '-delete', 'newkey')
130
224
 
131
- client.delete_tag('newkey')
225
+ subject
132
226
  end
227
+
228
+ include_examples "failure cases"
133
229
  end
134
230
 
135
231
  describe "#get_tags" do
@@ -141,8 +237,7 @@ describe Villein::Client do
141
237
  "tags":{"key":"val"},"status":"alive","protocol":{"max":4,"min":2,"version":4}}]}
142
238
  EOJ
143
239
 
144
- allow(IO).to receive(:popen).with(%w(serf members -rpc-addr=x.x.x.x:nnnn -format json -name the-node), 'r') \
145
- .and_yield(double('io', read: json))
240
+ expect_serf('members', *%w(-format json -name the-node), message: json)
146
241
 
147
242
  expect(tags).to be_a_kind_of(Hash)
148
243
  expect(tags['key']).to eq 'val'
@@ -155,6 +250,8 @@ describe Villein::Client do
155
250
  expect { tags }.to raise_error
156
251
  end
157
252
  end
253
+
254
+ include_examples "failure cases"
158
255
  end
159
256
  end
160
257
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: villein
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shota Fukumori (sora_h)