etcd-rb 1.0.0 → 1.1.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 +4 -4
- data/lib/etcd/client/failover.rb +6 -11
- data/lib/etcd/client/observing.rb +2 -2
- data/lib/etcd/client/protocol.rb +40 -30
- data/lib/etcd/cluster.rb +6 -12
- data/lib/etcd/constants.rb +4 -4
- data/lib/etcd/heartbeat.rb +2 -2
- data/lib/etcd/loggable.rb +1 -1
- data/lib/etcd/node.rb +27 -10
- data/lib/etcd/observer.rb +3 -2
- data/lib/etcd/version.rb +2 -2
- data/spec/etcd/client_spec.rb +51 -49
- data/spec/etcd/cluster_spec.rb +22 -32
- data/spec/etcd/node_spec.rb +24 -12
- data/spec/etcd/observer_spec.rb +48 -48
- data/spec/integration/etcd_spec.rb +29 -16
- data/spec/resources/cluster_controller.rb +2 -2
- data/spec/support/client_helper.rb +6 -2
- data/spec/support/cluster_helper.rb +28 -30
- metadata +3 -3
data/spec/etcd/cluster_spec.rb
CHANGED
@@ -15,35 +15,24 @@ module Etcd
|
|
15
15
|
it "returns parsed data" do
|
16
16
|
with_stubbed_status(cluster_uri) do
|
17
17
|
res = Etcd::Cluster.cluster_status(cluster_uri)
|
18
|
-
res[0][:name].should
|
18
|
+
res[0][:name].should eq("node1")
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
describe '#parse_cluster_status' do
|
24
|
-
it "works with correct parsed json" do
|
25
|
-
res = Etcd::Cluster.parse_cluster_status(status_data)
|
26
|
-
res[0].should == {
|
27
|
-
:name => "node1",
|
28
|
-
:raft => "http://127.0.0.1:7001",
|
29
|
-
:etcd => "http://127.0.0.1:4001",
|
30
|
-
}
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
23
|
describe '#nodes_from_uri' do
|
35
24
|
it "returns node instances created from uri" do
|
36
25
|
with_stubbed_status(cluster_uri) do
|
37
26
|
nodes = Etcd::Cluster.nodes_from_uri(cluster_uri)
|
38
|
-
nodes.size.should
|
39
|
-
nodes.first.class.should
|
27
|
+
nodes.size.should eq(3)
|
28
|
+
nodes.first.class.should eq(Etcd::Node)
|
40
29
|
end
|
41
30
|
end
|
42
31
|
|
43
32
|
it "but those instances have no real status yet" do
|
44
33
|
with_stubbed_status(cluster_uri) do
|
45
34
|
nodes = Etcd::Cluster.nodes_from_uri(cluster_uri)
|
46
|
-
nodes.size.should
|
35
|
+
nodes.size.should eq(3)
|
47
36
|
nodes.first.status == :unknown
|
48
37
|
end
|
49
38
|
end
|
@@ -55,9 +44,10 @@ module Etcd
|
|
55
44
|
with_stubbed_status(cluster_uri) do
|
56
45
|
with_stubbed_leaders(healthy_cluster_config) do
|
57
46
|
cluster = Etcd::Cluster.init_from_uris(cluster_uri)
|
47
|
+
puts "nodes: #{cluster}"
|
58
48
|
nodes = cluster.nodes
|
59
|
-
nodes.size.should
|
60
|
-
nodes.map{|x| x.status}.uniq.should
|
49
|
+
nodes.size.should eq(3)
|
50
|
+
nodes.map{|x| x.status}.uniq.should eq([:running])
|
61
51
|
end
|
62
52
|
end
|
63
53
|
end
|
@@ -67,7 +57,7 @@ module Etcd
|
|
67
57
|
with_stubbed_leaders(healthy_cluster_config) do
|
68
58
|
cluster = Etcd::Cluster.init_from_uris(cluster_uri)
|
69
59
|
leader = cluster.leader
|
70
|
-
leader.
|
60
|
+
expect(leader.client_urls.first).to eq(cluster_uri)
|
71
61
|
end
|
72
62
|
end
|
73
63
|
end
|
@@ -80,8 +70,8 @@ module Etcd
|
|
80
70
|
with_stubbed_leaders(one_down_cluster_config) do
|
81
71
|
cluster = Etcd::Cluster.init_from_uris(cluster_uri)
|
82
72
|
nodes = cluster.nodes
|
83
|
-
nodes.size.should
|
84
|
-
nodes.map{|x| x.status}.uniq.should
|
73
|
+
nodes.size.should eq(3)
|
74
|
+
nodes.map{|x| x.status}.uniq.should eq([:running, :down])
|
85
75
|
end
|
86
76
|
end
|
87
77
|
end
|
@@ -93,7 +83,7 @@ module Etcd
|
|
93
83
|
describe '#new' do
|
94
84
|
it "will not request any info on initialization" do
|
95
85
|
cluster = Etcd::Cluster.new(cluster_uri)
|
96
|
-
WebMock.should_not have_requested(:get, "http://127.0.0.1:4001/
|
86
|
+
WebMock.should_not have_requested(:get, "http://127.0.0.1:4001/v2/members/")
|
97
87
|
end
|
98
88
|
end
|
99
89
|
|
@@ -103,7 +93,7 @@ module Etcd
|
|
103
93
|
with_stubbed_leaders(healthy_cluster_config) do
|
104
94
|
cluster = Etcd::Cluster.new(cluster_uri)
|
105
95
|
nodes = cluster.nodes
|
106
|
-
nodes.size.should
|
96
|
+
nodes.size.should eq(3)
|
107
97
|
end
|
108
98
|
end
|
109
99
|
end
|
@@ -113,13 +103,13 @@ module Etcd
|
|
113
103
|
with_stubbed_leaders(healthy_cluster_config) do
|
114
104
|
cluster = Etcd::Cluster.new(cluster_uri)
|
115
105
|
nodes = cluster.nodes
|
116
|
-
nodes.map{|x| x.status}.uniq.should
|
106
|
+
nodes.map{|x| x.status}.uniq.should eq([:running])
|
117
107
|
with_stubbed_leaders(one_down_cluster_config) do
|
118
108
|
nodes = cluster.nodes
|
119
109
|
nodes.map{|x| x.status}.uniq.should_not == [:running, :down]
|
120
110
|
# now update for real
|
121
111
|
nodes = cluster.update_status
|
122
|
-
nodes.map{|x| x.status}.uniq.should
|
112
|
+
nodes.map{|x| x.status}.uniq.should eq([:running, :down])
|
123
113
|
end
|
124
114
|
end
|
125
115
|
end
|
@@ -133,11 +123,11 @@ module Etcd
|
|
133
123
|
with_stubbed_leaders(healthy_cluster_config) do
|
134
124
|
cluster = Etcd::Cluster.new(cluster_uri)
|
135
125
|
nodes = cluster.update_status
|
136
|
-
nodes.size.should
|
137
|
-
nodes.map{|x| x.status}.uniq.should
|
126
|
+
nodes.size.should eq(3)
|
127
|
+
nodes.map{|x| x.status}.uniq.should eq([:running])
|
138
128
|
with_stubbed_leaders(one_down_cluster_config) do
|
139
129
|
nodes = cluster.update_status
|
140
|
-
nodes.map{|x| x.status}.uniq.should
|
130
|
+
nodes.map{|x| x.status}.uniq.should eq([:running, :down])
|
141
131
|
end
|
142
132
|
end
|
143
133
|
end
|
@@ -151,8 +141,8 @@ module Etcd
|
|
151
141
|
with_stubbed_leaders(healthy_cluster_config) do
|
152
142
|
cluster = Etcd::Cluster.new(cluster_uri)
|
153
143
|
leader = cluster.leader
|
154
|
-
leader.
|
155
|
-
leader.is_leader.
|
144
|
+
expect(leader.client_urls.first).to eq(cluster_uri)
|
145
|
+
expect(leader.is_leader).to eq(true)
|
156
146
|
end
|
157
147
|
end
|
158
148
|
end
|
@@ -161,10 +151,10 @@ module Etcd
|
|
161
151
|
with_stubbed_status(cluster_uri) do
|
162
152
|
with_stubbed_leaders(healthy_cluster_config) do
|
163
153
|
cluster = Etcd::Cluster.new(cluster_uri)
|
164
|
-
cluster.leader.
|
154
|
+
expect(cluster.leader.client_urls.first).to eq(cluster_uri)
|
165
155
|
with_stubbed_leaders(healthy_cluster_changed_leader_config) do
|
166
|
-
nodes
|
167
|
-
cluster.leader.
|
156
|
+
nodes = cluster.update_status
|
157
|
+
expect(cluster.leader.client_urls.first).to eq("http://127.0.0.1:4002")
|
168
158
|
end
|
169
159
|
end
|
170
160
|
end
|
data/spec/etcd/node_spec.rb
CHANGED
@@ -1,23 +1,35 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
|
5
4
|
module Etcd
|
6
5
|
describe Node do
|
7
6
|
|
7
|
+
let :node_data do
|
8
|
+
[
|
9
|
+
{"id" => "14306b09b8d69fc4","name" => "node1","peerURLs"=> ["http://127.0.0.1:7001"],"clientURLs" => ["http://127.0.0.1:4001"]},
|
10
|
+
{"id" => "d2356cd527a56a4","name" => "node2","peerURLs" => ["http://127.0.0.1:7002"],"clientURLs" => ["http://127.0.0.1:4002"]}
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
8
14
|
def default_node(opts = {})
|
9
|
-
|
10
|
-
Etcd::Node.new(
|
15
|
+
data = Etcd::Node.parse_node_data(node_data[0])
|
16
|
+
Etcd::Node.new(data.merge(opts))
|
11
17
|
end
|
12
18
|
|
13
19
|
describe '#initialize' do
|
14
20
|
it "works with all required parameters" do
|
15
|
-
default_node({}).should_not
|
21
|
+
default_node({}).should_not be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "raises if :client_urls is missing" do
|
25
|
+
expect {
|
26
|
+
default_node({:client_urls => nil})
|
27
|
+
}.to raise_error(ArgumentError)
|
16
28
|
end
|
17
29
|
|
18
|
-
it "raises if :
|
30
|
+
it "raises if :id is missing" do
|
19
31
|
expect {
|
20
|
-
default_node({:
|
32
|
+
default_node({:id => nil})
|
21
33
|
}.to raise_error(ArgumentError)
|
22
34
|
end
|
23
35
|
end
|
@@ -25,31 +37,31 @@ module Etcd
|
|
25
37
|
describe '#update_status' do
|
26
38
|
it "sets status :running if alive" do
|
27
39
|
node = default_node
|
28
|
-
stub_request(:get, node.leader_uri).to_return(body: node.
|
40
|
+
stub_request(:get, node.leader_uri).to_return(body: node.to_json)
|
29
41
|
node.update_status
|
30
|
-
node.status.should
|
42
|
+
node.status.should eq(:running)
|
31
43
|
end
|
32
44
|
|
33
45
|
it "sets status :down if down" do
|
34
46
|
node = default_node
|
35
47
|
stub_request(:get, node.leader_uri).to_timeout
|
36
48
|
node.update_status
|
37
|
-
node.status.should
|
49
|
+
node.status.should eq(:down)
|
38
50
|
end
|
39
51
|
|
40
52
|
it "marks leader-flag if leader" do
|
41
53
|
node = default_node
|
42
|
-
stub_request(:get, node.leader_uri).to_return(body: node.
|
54
|
+
stub_request(:get, node.leader_uri).to_return(body: node.to_json)
|
43
55
|
node.update_status
|
44
56
|
node.is_leader.should eq(true)
|
45
57
|
end
|
46
58
|
|
47
59
|
it "marks leader-flag as :false if leader looses leadership" do
|
48
60
|
node = default_node
|
49
|
-
stub_request(:get, node.leader_uri).to_return(body: node.
|
61
|
+
stub_request(:get, node.leader_uri).to_return(body: node.to_json)
|
50
62
|
node.update_status
|
51
63
|
node.is_leader.should eq(true)
|
52
|
-
stub_request(:get, node.leader_uri).to_return(body:
|
64
|
+
stub_request(:get, node.leader_uri).to_return(body: node_data[1].to_json)
|
53
65
|
node.update_status
|
54
66
|
node.is_leader.should eq(false)
|
55
67
|
end
|
data/spec/etcd/observer_spec.rb
CHANGED
@@ -7,7 +7,7 @@ module Etcd
|
|
7
7
|
include ClientHelper
|
8
8
|
|
9
9
|
def base_uri
|
10
|
-
"http://127.0.0.1:4001/
|
10
|
+
"http://127.0.0.1:4001/v2"
|
11
11
|
end
|
12
12
|
|
13
13
|
let :client do
|
@@ -16,95 +16,95 @@ module Etcd
|
|
16
16
|
|
17
17
|
describe '#watch' do
|
18
18
|
it 'sends a GET request for a watch of a key prefix' do
|
19
|
-
stub_request(:get, "#{base_uri}/
|
19
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {wait: 'true'}).to_return(body: MultiJson.dump({}))
|
20
20
|
client.watch('/foo') { }
|
21
|
-
WebMock.should have_requested(:get, "#{base_uri}/
|
21
|
+
WebMock.should have_requested(:get, "#{base_uri}/keys/foo").with(query: {wait: 'true'})
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'sends a GET request for a watch of a key prefix from a specified index' do
|
25
|
-
stub_request(:
|
25
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true', 'index' => 3}).to_return(body: MultiJson.dump({}))
|
26
26
|
client.watch('/foo', index: 3) { }
|
27
|
-
WebMock.should have_requested(:
|
27
|
+
WebMock.should have_requested(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true', 'index' => 3})
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'yields the value' do
|
31
|
-
body = MultiJson.dump({'value' => 'bar'})
|
32
|
-
stub_request(:get, "#{base_uri}/
|
31
|
+
body = MultiJson.dump({'node' => {'value' => 'bar'}})
|
32
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'}).to_return(body: body)
|
33
33
|
value = nil
|
34
34
|
client.watch('/foo') do |v|
|
35
35
|
value = v
|
36
36
|
end
|
37
|
-
value.should
|
37
|
+
value.should eq('bar')
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'yields the changed key' do
|
41
|
-
body = MultiJson.dump({'key' => '/foo/bar', 'value' => 'bar'})
|
42
|
-
stub_request(:get, "#{base_uri}/
|
41
|
+
body = MultiJson.dump({'node' => {'key' => '/foo/bar', 'value' => 'bar'}})
|
42
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'}).to_return(body: body)
|
43
43
|
key = nil
|
44
44
|
client.watch('/foo') do |_, k|
|
45
45
|
key = k
|
46
46
|
end
|
47
|
-
key.should
|
47
|
+
key.should eq('/foo/bar')
|
48
48
|
end
|
49
49
|
|
50
50
|
it 'yields info about the key, when it is a new key' do
|
51
|
-
body = MultiJson.dump({'action' => 'SET', 'key' => '/foo/bar', 'value' => 'bar', 'index' => 3
|
52
|
-
stub_request(:get, "#{base_uri}/
|
51
|
+
body = MultiJson.dump({'action' => 'SET', 'node' => {'key' => '/foo/bar', 'value' => 'bar', 'index' => 3}})
|
52
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'}).to_return(body: body)
|
53
53
|
info = nil
|
54
54
|
client.watch('/foo') do |_, _, i|
|
55
55
|
info = i
|
56
56
|
end
|
57
|
-
info[:action].should
|
58
|
-
info[:key].should
|
59
|
-
info[:value].should
|
60
|
-
info[:index].should
|
57
|
+
info[:action].should eq(:set)
|
58
|
+
info[:key].should eq('/foo/bar')
|
59
|
+
info[:value].should eq('bar')
|
60
|
+
info[:index].should eq(3)
|
61
61
|
info[:new_key].should eq(true)
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'yields info about the key, when the key was changed' do
|
65
|
-
body = MultiJson.dump({'action' => '
|
66
|
-
stub_request(:get, "#{base_uri}/
|
65
|
+
body = MultiJson.dump({'action' => 'set', 'node' => {'key' => '/foo/bar', 'value' => 'bar', 'index' => 3}, 'prevNode' => {'value' => 'baz'}})
|
66
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'}).to_return(body: body)
|
67
67
|
info = nil
|
68
68
|
client.watch('/foo') do |_, _, i|
|
69
69
|
info = i
|
70
70
|
end
|
71
|
-
info[:action].should
|
72
|
-
info[:key].should
|
73
|
-
info[:value].should
|
74
|
-
info[:index].should
|
75
|
-
info[:previous_value].should
|
71
|
+
info[:action].should eq(:set)
|
72
|
+
info[:key].should eq('/foo/bar')
|
73
|
+
info[:value].should eq('bar')
|
74
|
+
info[:index].should eq(3)
|
75
|
+
info[:previous_value].should eq('baz')
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'yields info about the key, when the key has a TTL' do
|
79
|
-
body = MultiJson.dump({'action' => '
|
80
|
-
stub_request(:get, "#{base_uri}/
|
79
|
+
body = MultiJson.dump({'action' => 'set', 'node' => {'key' => '/foo/bar', 'value' => 'bar', 'index' => 3, 'expiration' => '2013-12-11T12:09:08.123+02:00', 'ttl' => 7}})
|
80
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'}).to_return(body: body)
|
81
81
|
info = nil
|
82
82
|
client.watch('/foo') do |_, _, i|
|
83
83
|
info = i
|
84
84
|
end
|
85
|
-
info[:action].should
|
86
|
-
info[:key].should
|
87
|
-
info[:value].should
|
88
|
-
info[:index].should
|
85
|
+
info[:action].should eq(:set)
|
86
|
+
info[:key].should eq('/foo/bar')
|
87
|
+
info[:value].should eq('bar')
|
88
|
+
info[:index].should eq(3)
|
89
89
|
# rounding because of ruby 2.0 time parsing bug @see https://gist.github.com/mindreframer/6746829
|
90
|
-
info[:expiration].to_f.round.should
|
91
|
-
info[:ttl].should
|
90
|
+
info[:expiration].to_f.round.should eq((Time.utc(2013, 12, 11, 10, 9, 8) + 0.123).to_f.round)
|
91
|
+
info[:ttl].should eq(7)
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'returns the return value of the block' do
|
95
|
-
body = MultiJson.dump({'action' => '
|
96
|
-
stub_request(:get, "#{base_uri}/
|
95
|
+
body = MultiJson.dump({'action' => 'set', 'node' => {'key' => '/foo/bar', 'value' => 'bar', 'index' => 3, 'expiration' => '2013-12-11T12:09:08.123+02:00', 'ttl' => 7}})
|
96
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'}).to_return(body: body)
|
97
97
|
return_value = client.watch('/foo') do |_, k, _|
|
98
98
|
k
|
99
99
|
end
|
100
|
-
return_value.should
|
100
|
+
return_value.should eq('/foo/bar')
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
104
|
|
105
105
|
describe '#observe' do
|
106
106
|
it 'watches the specified key prefix' do
|
107
|
-
stub_request(:get, "#{base_uri}/
|
107
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'}).to_return(body: MultiJson.dump({'node' => {}}))
|
108
108
|
barrier = Queue.new
|
109
109
|
observer = client.observe('/foo') do
|
110
110
|
barrier << :ping
|
@@ -112,12 +112,12 @@ module Etcd
|
|
112
112
|
observer.join
|
113
113
|
end
|
114
114
|
barrier.pop
|
115
|
-
WebMock.should have_requested(:get, "#{base_uri}/
|
115
|
+
WebMock.should have_requested(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'})
|
116
116
|
end
|
117
117
|
|
118
118
|
it 're-watches the prefix with the (last seen index + 1) immediately' do
|
119
|
-
stub_request(:get, "#{base_uri}/
|
120
|
-
stub_request(:
|
119
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'}).to_return(body: MultiJson.dump({'node' => {'index' => 3}}))
|
120
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true', 'index' => 4}).to_return(body: MultiJson.dump({'node' => {'index' => 4}}))
|
121
121
|
barrier = Queue.new
|
122
122
|
observer = client.observe('/foo') do |_, _, info|
|
123
123
|
if info[:index] == 4
|
@@ -127,14 +127,14 @@ module Etcd
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
barrier.pop
|
130
|
-
WebMock.should have_requested(:get, "#{base_uri}/
|
131
|
-
WebMock.should have_requested(:
|
130
|
+
WebMock.should have_requested(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'})
|
131
|
+
WebMock.should have_requested(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true', 'index' => 4})
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'yields the value, key and info to the block given' do
|
135
|
-
stub_request(:get, "#{base_uri}/
|
136
|
-
stub_request(:
|
137
|
-
stub_request(:
|
135
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true'}).to_return(body: MultiJson.dump({'action' => 'set', 'node' => {'key' => '/foo/bar', 'value' => 'bar', 'index' => 3}}))
|
136
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true', 'index' => 4}).to_return(body: MultiJson.dump({'action' => 'delete', 'node' => {'key' => '/foo/baz', 'value' => 'foo', 'index' => 4}, 'prevNode' => {}}))
|
137
|
+
stub_request(:get, "#{base_uri}/keys/foo").with(query: {'wait' => 'true', 'index' => 5}).to_return(body: MultiJson.dump({'action' => 'set', 'node' => {'key' => '/foo/bar', 'value' => 'hello', 'index' => 5}, 'prevNode' => {}}))
|
138
138
|
barrier = Queue.new
|
139
139
|
values = []
|
140
140
|
keys = []
|
@@ -152,10 +152,10 @@ module Etcd
|
|
152
152
|
end
|
153
153
|
end
|
154
154
|
barrier.pop
|
155
|
-
values.should
|
156
|
-
keys.should
|
157
|
-
actions.should
|
158
|
-
new_keys.should
|
155
|
+
values.should eq(%w[bar foo hello])
|
156
|
+
keys.should eq(%w[/foo/bar /foo/baz /foo/bar])
|
157
|
+
actions.should eq([:set, :delete, :set])
|
158
|
+
new_keys.should eq([true, false, false])
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
@@ -6,10 +6,6 @@ require 'open-uri'
|
|
6
6
|
|
7
7
|
describe 'With real server an etcd client' do
|
8
8
|
|
9
|
-
let :client do
|
10
|
-
Etcd::Client.test_client
|
11
|
-
end
|
12
|
-
|
13
9
|
let :prefix do
|
14
10
|
"/etcd-rb/#{rand(234234)}"
|
15
11
|
end
|
@@ -23,8 +19,18 @@ describe 'With real server an etcd client' do
|
|
23
19
|
WebMock.allow_net_connect!
|
24
20
|
end
|
25
21
|
|
26
|
-
before do
|
22
|
+
before(:all) do
|
23
|
+
ClusterController.stop_cluster
|
27
24
|
ClusterController.start_cluster
|
25
|
+
sleep 2 # wait a little for the cluster to come up
|
26
|
+
end
|
27
|
+
|
28
|
+
after(:all) do
|
29
|
+
ClusterController.stop_cluster
|
30
|
+
end
|
31
|
+
|
32
|
+
let :client do
|
33
|
+
Etcd::Client.test_client
|
28
34
|
end
|
29
35
|
|
30
36
|
before do
|
@@ -37,7 +43,7 @@ describe 'With real server an etcd client' do
|
|
37
43
|
|
38
44
|
it 'sets and gets the value for a key' do
|
39
45
|
client.set(key, 'foo')
|
40
|
-
client.get(key).should
|
46
|
+
client.get(key).should eq('foo')
|
41
47
|
end
|
42
48
|
|
43
49
|
it 'sets a key with a TTL' do
|
@@ -49,8 +55,8 @@ describe 'With real server an etcd client' do
|
|
49
55
|
it 'watches for changes to a key' do
|
50
56
|
Thread.start { sleep(0.1); client.set(key, 'baz') }
|
51
57
|
new_value, info = *client.watch(key) { |v, k, info| [v, info] }
|
52
|
-
new_value.should
|
53
|
-
info[:new_key].should
|
58
|
+
new_value.should eq('baz')
|
59
|
+
info[:new_key].should eq(true)
|
54
60
|
end
|
55
61
|
|
56
62
|
it 'conditionally sets the value for a key' do
|
@@ -59,11 +65,12 @@ describe 'With real server an etcd client' do
|
|
59
65
|
client.update(key, 'qux', 'bar').should eq(true)
|
60
66
|
end
|
61
67
|
|
62
|
-
|
68
|
+
# FIXME: this test does not pass consistently. There seem to issues
|
69
|
+
# with the leader re-election handling (causing Errno::ECONNREFUSED)
|
63
70
|
it "has heartbeat, that resets observed watches" do
|
64
|
-
|
65
|
-
client
|
66
|
-
client.cluster.nodes.map(&:status).uniq.should
|
71
|
+
client = Etcd::Client.test_client(:heartbeat_freq => 0.1)
|
72
|
+
puts client.cluster.nodes.map(&:inspect)
|
73
|
+
client.cluster.nodes.map(&:status).uniq.should eq([:running])
|
67
74
|
changes = Queue.new
|
68
75
|
|
69
76
|
client.observe('/foo') do |v,k,info|
|
@@ -71,7 +78,7 @@ describe 'With real server an etcd client' do
|
|
71
78
|
changes << info
|
72
79
|
end
|
73
80
|
|
74
|
-
changes.size.should
|
81
|
+
changes.size.should eq(0)
|
75
82
|
|
76
83
|
### simulate second console
|
77
84
|
a = Thread.new do
|
@@ -83,9 +90,15 @@ describe 'With real server an etcd client' do
|
|
83
90
|
sleep 0.4
|
84
91
|
puts "2.nd try"
|
85
92
|
client.set("/foo", "barss")
|
93
|
+
sleep 0.4
|
86
94
|
end
|
87
95
|
|
88
|
-
|
89
|
-
changes.size.should
|
96
|
+
a.join
|
97
|
+
changes.size.should eq(2)
|
98
|
+
|
99
|
+
# restore cluster
|
100
|
+
ClusterController.stop_cluster
|
101
|
+
ClusterController.start_cluster
|
102
|
+
sleep 2
|
90
103
|
end
|
91
|
-
end
|
104
|
+
end
|