etcd 0.2.0.alpha → 0.2.0.beta.1

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.
data/lib/etcd/node.rb CHANGED
@@ -1,15 +1,16 @@
1
1
  # Encoding: utf-8
2
2
 
3
3
  module Etcd
4
+ # This class represents an etcd node
4
5
  class Node
5
-
6
6
  include Comparable
7
7
 
8
8
  attr_reader :created_index, :modified_index, :expiration, :ttl, :key, :value
9
- alias :createdIndex :created_index
10
- alias :modifiedIndex :modified_index
9
+ alias_method :createdIndex, :created_index
10
+ alias_method :modifiedIndex, :modified_index
11
11
 
12
- def initialize(opts={})
12
+ # rubocop:disable MethodLength
13
+ def initialize(opts = {})
13
14
  @created_index = opts['createdIndex']
14
15
  @modified_index = opts['modifiedIndex']
15
16
  @ttl = opts['ttl']
@@ -18,7 +19,7 @@ module Etcd
18
19
  @expiration = opts['expiration']
19
20
  @dir = opts['dir']
20
21
 
21
- if opts['dir'] and (!!opts['nodes'])
22
+ if opts['dir'] && (!!opts['nodes'])
22
23
  opts['nodes'].each do |data|
23
24
  children << Node.new(data)
24
25
  end
@@ -33,7 +34,7 @@ module Etcd
33
34
  if directory?
34
35
  @children ||= []
35
36
  else
36
- raise "This is not a directory, cant have children"
37
+ fail 'This is not a directory, cant have children'
37
38
  end
38
39
  end
39
40
 
data/lib/etcd/response.rb CHANGED
@@ -2,18 +2,18 @@
2
2
 
3
3
  require 'etcd/node'
4
4
  require 'json'
5
+ require 'forwardable'
5
6
 
6
7
  module Etcd
7
-
8
+ # manage http responses
8
9
  class Response
9
-
10
10
  extend Forwardable
11
11
 
12
12
  attr_reader :action, :node, :etcd_index, :raft_index, :raft_term
13
13
 
14
14
  def_delegators :@node, :key, :value, :directory?, :children
15
15
 
16
- def initialize(opts, headers={})
16
+ def initialize(opts, headers = {})
17
17
  @action = opts['action']
18
18
  @node = Node.new(opts['node'])
19
19
  @etcd_index = headers[:etcd_index]
@@ -23,11 +23,11 @@ module Etcd
23
23
 
24
24
  def self.from_http_response(response)
25
25
  data = JSON.parse(response.body)
26
- headers = Hash.new
26
+ headers = {}
27
27
  headers[:etcd_index] = response['X-Etcd-Index'].to_i
28
28
  headers[:raft_index] = response['X-Raft-Index'].to_i
29
29
  headers[:raft_term] = response['X-Raft-Term'].to_i
30
- response = Response.new(data, headers)
30
+ Response.new(data, headers)
31
31
  end
32
32
  end
33
33
  end
data/lib/etcd/stats.rb CHANGED
@@ -3,8 +3,8 @@
3
3
  require 'json'
4
4
 
5
5
  module Etcd
6
+ # Support stats
6
7
  module Stats
7
-
8
8
  def stats_endpoint
9
9
  version_prefix + '/stats'
10
10
  end
@@ -12,13 +12,13 @@ module Etcd
12
12
  def stats(type)
13
13
  case type
14
14
  when :leader
15
- JSON.parse(api_execute(stats_endpoint+'/leader', :get).body)
15
+ JSON.parse(api_execute(stats_endpoint + '/leader', :get).body)
16
16
  when :store
17
- JSON.parse(api_execute(stats_endpoint+'/store', :get).body)
17
+ JSON.parse(api_execute(stats_endpoint + '/store', :get).body)
18
18
  when :self
19
- JSON.parse(api_execute(stats_endpoint+'/self', :get).body)
19
+ JSON.parse(api_execute(stats_endpoint + '/self', :get).body)
20
20
  else
21
- raise ArgumentError, "Invalid stats type '#{type}'"
21
+ fail ArgumentError, "Invalid stats type '#{type}'"
22
22
  end
23
23
  end
24
24
  end
data/lib/etcd/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # Encoding: utf-8
2
-
2
+ # Version const
3
3
  module Etcd
4
- VERSION = "0.2.0.alpha"
4
+ VERSION = '0.2.0.beta.1'
5
5
  end
@@ -0,0 +1,27 @@
1
+ # Encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Etcd basic auth client' do
6
+
7
+ let(:client) do
8
+ Etcd.client(user_name: 'test', password: 'pwd')
9
+ end
10
+
11
+ it '#user_name' do
12
+ expect(client.user_name).to eq('test')
13
+ end
14
+
15
+ it '#password' do
16
+ expect(client.password).to eq('pwd')
17
+ end
18
+
19
+ it 'should set basic auth' do
20
+ Net::HTTPRequest.any_instance.should_receive(:basic_auth).with('test', 'pwd')
21
+ key = random_key
22
+ value = uuid.generate
23
+ client.set(key, value: value)
24
+ sleep 1
25
+ expect(read_only_client.get(key).value).to eq(value)
26
+ end
27
+ end
@@ -15,7 +15,7 @@ describe Etcd::Client do
15
15
  end
16
16
 
17
17
  it '#version' do
18
- expect(client.version).to match(/^etcd v0\.2\./)
18
+ expect(client.version).to match(/^etcd v?0\.\d+\.\d+(\+git)?/)
19
19
  end
20
20
 
21
21
  it '#version_prefix' do
@@ -29,14 +29,22 @@ describe Etcd::Client do
29
29
  end.to raise_error
30
30
  end
31
31
 
32
- it 'should redirect api request when allo_redirect is set'
32
+ it 'should redirect api request when allow_redirect is set' do
33
+ key = random_key
34
+ value = uuid.generate
35
+ rd_client = Etcd.client host: 'localhost', port: 4003
36
+ resp = rd_client.set(key, value: value)
37
+ resp.node.key.should eql key
38
+ resp.node.value.should eql value
39
+ client.get(key).value.should eql resp.value
40
+ end
33
41
  end
34
42
 
35
43
  context '#http header based metadata' do
36
44
  before(:all) do
37
45
  key = random_key
38
46
  value = uuid.generate
39
- @response = Etcd.client.set(key,value)
47
+ @response = Etcd.client.set(key, value: value)
40
48
  end
41
49
 
42
50
  it '#etcd_index' do
@@ -9,18 +9,60 @@ describe Etcd::Keys do
9
9
  it '#set/#get' do
10
10
  key = random_key
11
11
  value = uuid.generate
12
- client.set(key, value)
12
+ client.set(key, value: value)
13
13
  expect(client.get(key).value).to eq(value)
14
14
  end
15
15
 
16
16
  context '#exists?' do
17
17
  it 'should be true for existing keys' do
18
18
  key = random_key
19
- client.create(key, 10)
19
+ client.create(key, value: 10)
20
20
  expect(client.exists?(key)).to be_true
21
21
  end
22
22
  it 'should be true for existing keys' do
23
23
  expect(client.exists?(random_key)).to be_false
24
24
  end
25
25
  end
26
+
27
+ context 'directory' do
28
+ it 'should be able to create a directory' do
29
+ d = random_key
30
+ client.create(d, dir: true)
31
+ expect(client.get(d)).to be_true
32
+ end
33
+ context 'empty' do
34
+ it 'should be able to delete with dir flag' do
35
+ d = random_key
36
+ client.create(d, dir: true)
37
+ expect(client.delete(d, dir: true)).to be_true
38
+ end
39
+
40
+ it 'should not be able to delete without dir flag' do
41
+ d = random_key
42
+ client.create(d, dir: true)
43
+ client.create("#{d}/foobar", value: 10)
44
+ expect do
45
+ client.delete(d)
46
+ end.to raise_error(Etcd::NotFile)
47
+ end
48
+ end
49
+ context 'not empty' do
50
+ it 'should be able to delete with recursive flag' do
51
+ d = random_key
52
+ client.create(d, dir: true)
53
+ client.create("#{d}/foobar")
54
+ expect do
55
+ client.delete(d, dir: true, recursive: true)
56
+ end.to_not raise_error
57
+ end
58
+ it 'should be not able to delete without recursive flag' do
59
+ d = random_key
60
+ client.create(d, dir: true)
61
+ client.create("#{d}/foobar")
62
+ expect do
63
+ client.delete(d, dir: true)
64
+ end.to raise_error(Etcd::DirNotEmpty)
65
+ end
66
+ end
67
+ end
26
68
  end
@@ -10,7 +10,7 @@ describe 'lock' do
10
10
 
11
11
  it 'should be able to acquire a lock' do
12
12
  expect do
13
- client.acquire_lock('/my_lock',10)
13
+ client.acquire_lock('/my_lock', 10)
14
14
  end.to_not raise_error
15
15
  end
16
16
 
@@ -23,7 +23,7 @@ describe 'lock' do
23
23
 
24
24
  it 'should be able to renew a lock based on index' do
25
25
  client.acquire_lock('/my_lock2', 10)
26
- index = client.get_lock('/my_lock2', field:'index')
26
+ index = client.get_lock('/my_lock2', field: 'index')
27
27
  expect do
28
28
  client.renew_lock('/my_lock2', 10, index: index)
29
29
  end.to_not raise_error
@@ -38,7 +38,7 @@ describe 'lock' do
38
38
 
39
39
  it 'should be able to delete a lock based on index' do
40
40
  client.acquire_lock('/my_lock4', 10)
41
- index = client.get_lock('/my_lock4', field:'index')
41
+ index = client.get_lock('/my_lock4', field: 'index')
42
42
  expect do
43
43
  client.delete_lock('/my_lock4', index: index)
44
44
  end.to_not raise_error
@@ -6,19 +6,19 @@ describe Etcd::Node do
6
6
  Etcd.client
7
7
  end
8
8
 
9
- it "should create a directory with parent key when nested keys are set" do
9
+ it 'should create a directory with parent key when nested keys are set' do
10
10
  parent = random_key
11
11
  child = random_key
12
12
  value = uuid.generate
13
- client.set(parent+child, value)
14
- expect(client.get(parent+child)).to_not be_directory
13
+ client.set(parent + child, value: value)
14
+ expect(client.get(parent + child)).to_not be_directory
15
15
  expect(client.get(parent)).to be_directory
16
16
  end
17
17
 
18
18
  context '#children' do
19
19
  it 'should raise exception when invoked against a leaf node' do
20
20
  parent = random_key
21
- client.create(random_key, 10)
21
+ client.create(random_key, value: 10)
22
22
  expect do
23
23
  client.get(random_key).children
24
24
  end.to raise_error
@@ -2,32 +2,31 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe "Etcd read only client" do
5
+ describe 'Etcd read only client' do
6
6
 
7
7
  let(:client) do
8
8
  Etcd.client
9
9
  end
10
10
 
11
- it "should not allow write" do
12
- key= random_key
13
- expect{
14
- read_only_client.set(key, uuid.generate)
15
- }.to raise_error(Net::HTTPRetriableError)
11
+ it 'should not allow write' do
12
+ key = random_key
13
+ expect do
14
+ read_only_client.set(key, value: uuid.generate)
15
+ end.to raise_error(Net::HTTPRetriableError)
16
16
  end
17
17
 
18
- it "should allow reads" do
18
+ it 'should allow reads' do
19
19
  key = random_key
20
20
  value = uuid.generate
21
- client.set(key, value)
21
+ client.set(key, value: value)
22
22
  sleep 1
23
23
  expect(read_only_client.get(key).value).to eq(value)
24
24
  end
25
25
 
26
- it "should allow watch" do
26
+ it 'should allow watch' do
27
27
  key = random_key
28
28
  value = uuid.generate
29
- index = client.set(key, value).node.modified_index
29
+ index = client.set(key, value: value).node.modified_index
30
30
  expect(read_only_client.watch(key, index: index).value).to eq(value)
31
31
  end
32
32
  end
33
-
@@ -53,10 +53,9 @@ describe 'Etcd specs for the main etcd README examples' do
53
53
  end
54
54
 
55
55
  context 'set a key named "/message"' do
56
-
57
56
 
58
57
  before(:all) do
59
- @response = Etcd.client.set('/message', 'PinkFloyd')
58
+ @response = Etcd.client.set('/message', value: 'PinkFloyd')
60
59
  end
61
60
 
62
61
  it_should_behave_like 'response with valid http headers'
@@ -70,7 +69,7 @@ describe 'Etcd specs for the main etcd README examples' do
70
69
  context 'get a key named "/message"' do
71
70
 
72
71
  before(:all) do
73
- Etcd.client.set('/message', 'PinkFloyd')
72
+ Etcd.client.set('/message', value: 'PinkFloyd')
74
73
  @response = Etcd.client.get('/message')
75
74
  end
76
75
 
@@ -85,8 +84,8 @@ describe 'Etcd specs for the main etcd README examples' do
85
84
  context 'change the value of a key named "/message"' do
86
85
 
87
86
  before(:all) do
88
- Etcd.client.set('/message', 'World')
89
- @response = Etcd.client.set('/message','PinkFloyd')
87
+ Etcd.client.set('/message', value: 'World')
88
+ @response = Etcd.client.set('/message', value: 'PinkFloyd')
90
89
  end
91
90
 
92
91
  it_should_behave_like 'response with valid http headers'
@@ -100,8 +99,8 @@ describe 'Etcd specs for the main etcd README examples' do
100
99
  context 'delete a key named "/message"' do
101
100
 
102
101
  before(:all) do
103
- Etcd.client.set('/message', 'World')
104
- Etcd.client.set('/message','PinkFloyd')
102
+ Etcd.client.set('/message', value: 'World')
103
+ Etcd.client.set('/message', value: 'PinkFloyd')
105
104
  @response = Etcd.client.delete('/message')
106
105
  end
107
106
 
@@ -116,9 +115,9 @@ describe 'Etcd specs for the main etcd README examples' do
116
115
  context 'using ttl a key named "/message"' do
117
116
 
118
117
  before(:all) do
119
- Etcd.client.set('/message', 'World')
118
+ Etcd.client.set('/message', value: 'World')
120
119
  @set_time = Time.now
121
- @response = Etcd.client.set('/message','PinkFloyd', 5)
120
+ @response = Etcd.client.set('/message', value: 'PinkFloyd', ttl: 5)
122
121
  end
123
122
 
124
123
  it_should_behave_like 'response with valid http headers'
@@ -148,11 +147,11 @@ describe 'Etcd specs for the main etcd README examples' do
148
147
  context 'waiting for a change against a key named "/message"' do
149
148
 
150
149
  before(:all) do
151
- Etcd.client.set('/message', 'foo')
150
+ Etcd.client.set('/message', value: 'foo')
152
151
  thr = Thread.new do
153
152
  @response = Etcd.client.watch('/message')
154
153
  end
155
- Etcd.client.set('/message', 'PinkFloyd')
154
+ Etcd.client.set('/message', value: 'PinkFloyd')
156
155
  thr.join
157
156
  end
158
157
 
@@ -164,7 +163,7 @@ describe 'Etcd specs for the main etcd README examples' do
164
163
  end
165
164
 
166
165
  it 'should get the exact value by specifying a waitIndex' do
167
- client.set('/message', 'someshit')
166
+ client.set('/message', value: 'someshit')
168
167
  w_response = client.watch('/message', index: @response.node.modified_index)
169
168
  expect(w_response.node.value).to eq('PinkFloyd')
170
169
  end
@@ -173,7 +172,7 @@ describe 'Etcd specs for the main etcd README examples' do
173
172
  context 'atomic in-order keys' do
174
173
 
175
174
  before(:all) do
176
- @response = Etcd.client.create_in_order('/queue', 'PinkFloyd')
175
+ @response = Etcd.client.create_in_order('/queue', value: 'PinkFloyd')
177
176
  end
178
177
 
179
178
  it_should_behave_like 'response with valid http headers'
@@ -188,8 +187,8 @@ describe 'Etcd specs for the main etcd README examples' do
188
187
  end
189
188
 
190
189
  it 'should have the child keys as monotonically increasing' do
191
- first_response = client.create_in_order('/queue', 'The Jimi Hendrix Experience')
192
- second_response = client.create_in_order('/queue', 'The Doors')
190
+ first_response = client.create_in_order('/queue', value: 'The Jimi Hendrix Experience')
191
+ second_response = client.create_in_order('/queue', value: 'The Doors')
193
192
  first_key = first_response.key.split('/').last.to_i
194
193
  second_key = second_response.key.split('/').last.to_i
195
194
  expect(first_key).to be < second_key
@@ -198,12 +197,12 @@ describe 'Etcd specs for the main etcd README examples' do
198
197
  it 'should enlist all children in sorted manner' do
199
198
  responses = []
200
199
  10.times do |n|
201
- responses << client.create_in_order('/queue', 'Deep Purple - Track #{n}')
200
+ responses << client.create_in_order('/queue', value: 'Deep Purple - Track #{n}')
202
201
  end
203
202
  directory = client.get('/queue', sorted: true)
204
203
  past_index = directory.children.index(responses.first.node)
205
204
  9.times do |n|
206
- current_index = directory.children.index(responses[n+1].node)
205
+ current_index = directory.children.index(responses[n + 1].node)
207
206
  expect(current_index).to be > past_index
208
207
  past_index = current_index
209
208
  end
@@ -230,18 +229,18 @@ describe 'Etcd specs for the main etcd README examples' do
230
229
 
231
230
  it 'will throw error if updated without setting prevExist' do
232
231
  expect do
233
- client.set('/directory', dir:true, ttl:5)
232
+ client.set('/directory', dir: true, ttl: 5)
234
233
  end.to raise_error
235
234
  end
236
235
 
237
236
  it 'can be updated by setting prevExist to true' do
238
- client.set('/directory', prevExist: true, dir:true, ttl:5)
237
+ client.set('/directory', prevExist: true, dir: true, ttl: 5)
239
238
  expect(client.get('/directory').node.ttl).to eq(5)
240
239
  end
241
240
 
242
241
  it 'watchers should get expriy notification' do
243
- client.set('/directory/a', 'Test')
244
- client.set('/directory', prevExist: true, dir:true, ttl:2)
242
+ client.set('/directory/a', value: 'Test')
243
+ client.set('/directory', prevExist: true, dir: true, ttl: 2)
245
244
  response = client.watch('/directory/a', consistent: true, timeout: 3)
246
245
  expect(response.action).to eq('expire')
247
246
  end
@@ -256,37 +255,37 @@ describe 'Etcd specs for the main etcd README examples' do
256
255
  context 'atomic compare and swap' do
257
256
 
258
257
  it 'should raise error if prevExist is passed a false' do
259
- client.set('/foo', 'one')
258
+ client.set('/foo', value: 'one')
260
259
  expect do
261
- client.set('/foo','three', prevExist: false)
260
+ client.set('/foo', value: 'three', prevExist: false)
262
261
  end.to raise_error
263
262
  end
264
263
 
265
264
  it 'should raise error is prevValue is wrong' do
266
- client.set('/foo', 'one')
265
+ client.set('/foo', value: 'one')
267
266
  expect do
268
- client.set('/foo','three', prevValue: 'two')
267
+ client.set('/foo', value: 'three', prevValue: 'two')
269
268
  end.to raise_error
270
269
  end
271
270
 
272
271
  it 'should allow setting the value when prevValue is right' do
273
- client.set('/foo', 'one')
274
- expect(client.set('/foo','three', prevValue: 'one').value).to eq('three')
272
+ client.set('/foo', value: 'one')
273
+ expect(client.set('/foo', value: 'three', prevValue: 'one').value).to eq('three')
275
274
  end
276
275
  end
277
276
  context 'directory manipulation' do
278
277
  it 'should allow creating directory' do
279
- expect(client.set('/dir',dir:true)).to be_directory
278
+ expect(client.set('/dir', dir: true)).to be_directory
280
279
  end
281
280
 
282
281
  it 'should allow listing directory' do
283
- client.set('/foo_dir/foo','bar')
282
+ client.set('/foo_dir/foo', value: 'bar')
284
283
  expect(client.get('/').children.map(&:key)).to include('/foo_dir')
285
284
  end
286
285
 
287
286
  it 'should allow recursive directory listing' do
288
287
  response = client.get('/', recursive: true)
289
- expect(response.children.find{|n|n.key=='/foo_dir'}.children).to_not be_empty
288
+ expect(response.children.find { |n|n.key == '/foo_dir' }.children).to_not be_empty
290
289
  end
291
290
 
292
291
  it 'should be able to delete empty directory without the recusrive flag' do
@@ -301,8 +300,8 @@ describe 'Etcd specs for the main etcd README examples' do
301
300
  context 'hidden nodes' do
302
301
 
303
302
  before(:all) do
304
- Etcd.client.set('/_message', 'Hello Hidden World')
305
- Etcd.client.set('/message', 'Hello World')
303
+ Etcd.client.set('/_message', value: 'Hello Hidden World')
304
+ Etcd.client.set('/message', value: 'Hello World')
306
305
  end
307
306
 
308
307
  it 'should not be visible in directory listing' do