mamiya 0.0.1.alpha2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +16 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +43 -0
- data/Rakefile +6 -0
- data/bin/mamiya +17 -0
- data/config.example.yml +11 -0
- data/docs/sequences/deploy.png +0 -0
- data/docs/sequences/deploy.uml +58 -0
- data/example.rb +74 -0
- data/lib/mamiya.rb +5 -0
- data/lib/mamiya/agent.rb +181 -0
- data/lib/mamiya/agent/actions.rb +12 -0
- data/lib/mamiya/agent/fetcher.rb +137 -0
- data/lib/mamiya/agent/handlers/abstract.rb +20 -0
- data/lib/mamiya/agent/handlers/fetch.rb +68 -0
- data/lib/mamiya/cli.rb +322 -0
- data/lib/mamiya/cli/client.rb +172 -0
- data/lib/mamiya/config.rb +57 -0
- data/lib/mamiya/dsl.rb +192 -0
- data/lib/mamiya/helpers/git.rb +75 -0
- data/lib/mamiya/logger.rb +190 -0
- data/lib/mamiya/master.rb +118 -0
- data/lib/mamiya/master/agent_monitor.rb +146 -0
- data/lib/mamiya/master/agent_monitor_handlers.rb +44 -0
- data/lib/mamiya/master/web.rb +148 -0
- data/lib/mamiya/package.rb +122 -0
- data/lib/mamiya/script.rb +117 -0
- data/lib/mamiya/steps/abstract.rb +19 -0
- data/lib/mamiya/steps/build.rb +72 -0
- data/lib/mamiya/steps/extract.rb +26 -0
- data/lib/mamiya/steps/fetch.rb +24 -0
- data/lib/mamiya/steps/push.rb +34 -0
- data/lib/mamiya/storages.rb +17 -0
- data/lib/mamiya/storages/abstract.rb +48 -0
- data/lib/mamiya/storages/mock.rb +61 -0
- data/lib/mamiya/storages/s3.rb +127 -0
- data/lib/mamiya/util/label_matcher.rb +38 -0
- data/lib/mamiya/version.rb +3 -0
- data/mamiya.gemspec +35 -0
- data/misc/logger_test.rb +12 -0
- data/spec/agent/actions_spec.rb +37 -0
- data/spec/agent/fetcher_spec.rb +199 -0
- data/spec/agent/handlers/fetch_spec.rb +121 -0
- data/spec/agent_spec.rb +255 -0
- data/spec/config_spec.rb +50 -0
- data/spec/dsl_spec.rb +291 -0
- data/spec/fixtures/dsl_test_load.rb +1 -0
- data/spec/fixtures/dsl_test_use.rb +1 -0
- data/spec/fixtures/helpers/foo.rb +1 -0
- data/spec/fixtures/test-package-source/.mamiya.meta.json +1 -0
- data/spec/fixtures/test-package-source/greeting +1 -0
- data/spec/fixtures/test-package.tar.gz +0 -0
- data/spec/fixtures/test.yml +4 -0
- data/spec/logger_spec.rb +68 -0
- data/spec/master/agent_monitor_spec.rb +269 -0
- data/spec/master/web_spec.rb +121 -0
- data/spec/master_spec.rb +94 -0
- data/spec/package_spec.rb +394 -0
- data/spec/script_spec.rb +78 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/steps/build_spec.rb +261 -0
- data/spec/steps/extract_spec.rb +68 -0
- data/spec/steps/fetch_spec.rb +96 -0
- data/spec/steps/push_spec.rb +73 -0
- data/spec/storages/abstract_spec.rb +22 -0
- data/spec/storages/s3_spec.rb +342 -0
- data/spec/storages_spec.rb +33 -0
- data/spec/support/dummy_serf.rb +70 -0
- data/spec/util/label_matcher_spec.rb +85 -0
- metadata +272 -0
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mamiya/storages'
|
3
|
+
|
4
|
+
require 'mamiya/config'
|
5
|
+
|
6
|
+
describe Mamiya::Config do
|
7
|
+
let(:source) do
|
8
|
+
{
|
9
|
+
"test" => {
|
10
|
+
"a" => ["b" => {"c" => {"d" => "e"}}]
|
11
|
+
},
|
12
|
+
:test2 => :hello
|
13
|
+
}
|
14
|
+
end
|
15
|
+
subject(:config) { described_class.new(source) }
|
16
|
+
|
17
|
+
describe ".load" do
|
18
|
+
let(:fixture_path) { File.join(__dir__, 'fixtures', 'test.yml') }
|
19
|
+
|
20
|
+
subject(:config) { described_class.load(fixture_path) }
|
21
|
+
|
22
|
+
it { should be_a(described_class) }
|
23
|
+
|
24
|
+
it "loads configuration from file" do
|
25
|
+
expect(config[:a][:e]).to eq "f"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "symbolizes keys" do
|
30
|
+
expect(config[:test][:a][0][:b][:c][:d]).to eq "e"
|
31
|
+
expect(config[:test2]).to eq :hello
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#storage_class" do
|
35
|
+
let(:source) do
|
36
|
+
{storage: {type: :foobar, conf: :iguration}}
|
37
|
+
end
|
38
|
+
let(:klass) { Class.new }
|
39
|
+
|
40
|
+
before do
|
41
|
+
allow(Mamiya::Storages).to receive(:find).with(:foobar).and_return(klass)
|
42
|
+
end
|
43
|
+
|
44
|
+
subject(:storage_class) { config.storage_class }
|
45
|
+
|
46
|
+
it "finds class using Storages.find" do
|
47
|
+
expect(storage_class).to eq klass
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/dsl_spec.rb
ADDED
@@ -0,0 +1,291 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mamiya/dsl'
|
3
|
+
require 'mamiya/util/label_matcher'
|
4
|
+
|
5
|
+
describe Mamiya::DSL do
|
6
|
+
let(:klass) { Class.new(Mamiya::DSL) }
|
7
|
+
subject(:dsl) { klass.new }
|
8
|
+
|
9
|
+
describe ".set_default" do
|
10
|
+
it "sets default" do
|
11
|
+
expect { dsl.testvar }.to raise_error
|
12
|
+
klass.set_default :testvar, 1
|
13
|
+
expect(dsl.testvar).to eq 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe ".add_hook" do
|
18
|
+
it "adds hook" do
|
19
|
+
expect { dsl.testhook }.to raise_error
|
20
|
+
klass.add_hook :testhook
|
21
|
+
expect(dsl.testhook).to be_a(Proc)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#evaluate!" do
|
26
|
+
context "with block" do
|
27
|
+
it "evaluates block within its object" do
|
28
|
+
flag = false
|
29
|
+
expect {
|
30
|
+
dsl.evaluate! { flag = true }
|
31
|
+
}.to change { flag }.from(false).to(true)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with string" do
|
36
|
+
it "evaluates string within its object" do
|
37
|
+
expect(dsl).to receive(:flag!)
|
38
|
+
dsl.evaluate! "flag!"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#load!" do
|
44
|
+
before do
|
45
|
+
dsl.set :foo, 42
|
46
|
+
end
|
47
|
+
|
48
|
+
it "loads file" do
|
49
|
+
expect {
|
50
|
+
dsl.load! "#{__dir__}/fixtures/dsl_test_load.rb"
|
51
|
+
}.to change { dsl.foo }.from(42).to(72)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#use" do
|
56
|
+
before do
|
57
|
+
dsl.set :foo, 42
|
58
|
+
end
|
59
|
+
|
60
|
+
it "loads file" do
|
61
|
+
dsl.set :load_path, ["#{__dir__}/fixtures/helpers"]
|
62
|
+
expect {
|
63
|
+
dsl.use :foo
|
64
|
+
}.to change { dsl.foo }.from(42).to(72)
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when file not exists" do
|
68
|
+
it "raises error" do
|
69
|
+
expect {
|
70
|
+
dsl.use :blahblahblah
|
71
|
+
}.to raise_error(Mamiya::DSL::HelperNotFound)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "with options" do
|
76
|
+
it "passes to file" do
|
77
|
+
dsl.set :load_path, ["#{__dir__}/fixtures/helpers"]
|
78
|
+
expect {
|
79
|
+
dsl.use :foo, value: 100
|
80
|
+
}.to change { dsl.foo }.from(42).to(100)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when loading file" do
|
85
|
+
it "loads file with suitable load path" do
|
86
|
+
expect {
|
87
|
+
dsl.load! "#{__dir__}/fixtures/dsl_test_use.rb"
|
88
|
+
}.to change { dsl.foo }.from(42).to(72)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#set" do
|
94
|
+
it "sets variable" do
|
95
|
+
expect{ dsl.foo }.to raise_error
|
96
|
+
dsl.set :foo, 100
|
97
|
+
expect(dsl.foo).to eq 100
|
98
|
+
dsl.set :foo, 200
|
99
|
+
expect(dsl.foo).to eq 200
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "#set_default" do
|
104
|
+
it "sets variable" do
|
105
|
+
dsl.set_default :foo, 100
|
106
|
+
expect(dsl.foo).to eq 100
|
107
|
+
end
|
108
|
+
|
109
|
+
context "when already assigned" do
|
110
|
+
it "doesn't nothing" do
|
111
|
+
dsl.set :foo, 100
|
112
|
+
dsl.set_default :foo, 200
|
113
|
+
expect(dsl.foo).to eq 100
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "tasks" do
|
119
|
+
it "defines callable tasks" do
|
120
|
+
flag = false
|
121
|
+
dsl.task :test do
|
122
|
+
flag = true
|
123
|
+
end
|
124
|
+
|
125
|
+
expect {
|
126
|
+
dsl.invoke :test
|
127
|
+
}.to change { flag }.from(false).to(true)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "can be called from another tasks" do
|
131
|
+
flag = false
|
132
|
+
|
133
|
+
dsl.task :a do
|
134
|
+
invoke :b
|
135
|
+
end
|
136
|
+
|
137
|
+
dsl.task :b do
|
138
|
+
flag = true
|
139
|
+
end
|
140
|
+
|
141
|
+
expect {
|
142
|
+
dsl.invoke :a
|
143
|
+
}.to change { flag }.from(false).to(true)
|
144
|
+
end
|
145
|
+
|
146
|
+
context "when task doesn't exist" do
|
147
|
+
it "raises error" do
|
148
|
+
expect {
|
149
|
+
dsl.invoke :nul
|
150
|
+
}.to raise_error
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "hook method" do
|
156
|
+
before do
|
157
|
+
klass.add_hook(:testhook)
|
158
|
+
end
|
159
|
+
|
160
|
+
context "without block" do
|
161
|
+
it "returns Proc to run hooks" do
|
162
|
+
expect(dsl.testhook).to be_a_kind_of(Proc)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "with block" do
|
167
|
+
it "appends given block to hooks" do
|
168
|
+
flag = false
|
169
|
+
dsl.testhook { flag = true }
|
170
|
+
expect { dsl.testhook.call }.to \
|
171
|
+
change { flag }.from(false).to(true)
|
172
|
+
end
|
173
|
+
|
174
|
+
it "appends given block to hooks (multiple)" do
|
175
|
+
flags = []
|
176
|
+
dsl.testhook { flags << :a }
|
177
|
+
dsl.testhook { flags << :b }
|
178
|
+
|
179
|
+
expect { dsl.testhook.call }.to \
|
180
|
+
change { flags }.from([]).to([:a,:b])
|
181
|
+
end
|
182
|
+
|
183
|
+
it "can call hooks with argument" do
|
184
|
+
flag = nil
|
185
|
+
dsl.testhook { |a| flag = a }
|
186
|
+
|
187
|
+
expect { dsl.testhook.call(42) }.to \
|
188
|
+
change { flag }.from(nil).to(42)
|
189
|
+
end
|
190
|
+
|
191
|
+
context "with :prepend" do
|
192
|
+
it "prepends given block to hooks" do
|
193
|
+
flag = nil
|
194
|
+
dsl.testhook { |a| flag = 1 }
|
195
|
+
dsl.testhook(:prepend) { flag = 0 }
|
196
|
+
|
197
|
+
expect { dsl.testhook.call }.to \
|
198
|
+
change { flag }.from(nil).to(1)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context "with :overwrite" do
|
203
|
+
it "overwrites all existing hooks with given block" do
|
204
|
+
flags = []
|
205
|
+
dsl.testhook { |a| flags << :a }
|
206
|
+
dsl.testhook { |a| flags << :b }
|
207
|
+
dsl.testhook(:overwrite) { |a| flags << :c }
|
208
|
+
|
209
|
+
expect { dsl.testhook.call }.to \
|
210
|
+
change { flags }.from([]).to([:c])
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "limiting by label" do
|
216
|
+
context "using kwarg :only" do
|
217
|
+
it "runs only for specified label" do
|
218
|
+
matcher = double('matcher')
|
219
|
+
expect(Mamiya::Util::LabelMatcher::Simple).to receive(:new).with([:a,:b,:d]).and_return(matcher)
|
220
|
+
expect(matcher).to receive(:match?).with(:a).and_return(true)
|
221
|
+
expect(matcher).to receive(:match?).with([:a]).and_return(true)
|
222
|
+
expect(matcher).to receive(:match?).with([:b, :c]).and_return(false)
|
223
|
+
|
224
|
+
flags = []
|
225
|
+
dsl.testhook(only: [:a]) { flags << 1 }
|
226
|
+
dsl.testhook { flags << 2 }
|
227
|
+
dsl.testhook(only: [[:b, :c]]) { flags << 3 }
|
228
|
+
dsl.testhook(:prepend, only: [[:a]]) { flags << 4 }
|
229
|
+
|
230
|
+
expect { dsl.testhook(:a, :b, :d).call }.to \
|
231
|
+
change { flags }.from([]).to([4,1,2])
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context "using kwarg :except" do
|
236
|
+
it "doesn't run for specified label" do
|
237
|
+
matcher = double('matcher')
|
238
|
+
expect(Mamiya::Util::LabelMatcher::Simple).to receive(:new).with([:a,:b,:d]).and_return(matcher)
|
239
|
+
expect(matcher).to receive(:match?).with(:a).and_return(true)
|
240
|
+
expect(matcher).to receive(:match?).with([:a]).and_return(true)
|
241
|
+
expect(matcher).to receive(:match?).with([:b, :c]).and_return(false)
|
242
|
+
|
243
|
+
flags = []
|
244
|
+
dsl.testhook(except: [:a]) { flags << 1 }
|
245
|
+
dsl.testhook { flags << 2 }
|
246
|
+
dsl.testhook(except: [[:b, :c]]) { flags << 3 }
|
247
|
+
dsl.testhook(:prepend, except: [[:a]]) { flags << 4 }
|
248
|
+
|
249
|
+
expect { dsl.testhook(:a, :b, :d).call }.to \
|
250
|
+
change { flags }.from([]).to([2,3])
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe "chain hooks" do
|
256
|
+
before do
|
257
|
+
klass.add_hook(:testchain, chain: true)
|
258
|
+
end
|
259
|
+
|
260
|
+
it "injects the result of blocks" do
|
261
|
+
dsl.testchain { |result, arg| result += arg * 3 }
|
262
|
+
dsl.testchain { |result, arg| result -= arg }
|
263
|
+
|
264
|
+
expect(dsl.testchain[2, 5]).to eq 12
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
describe "naming" do
|
269
|
+
it "ables to name defined hooks" do
|
270
|
+
dsl.testhook('the-name') { }
|
271
|
+
expect(dsl.hooks[:testhook].first[:name]).to eq 'the-name'
|
272
|
+
end
|
273
|
+
|
274
|
+
context "with other option" do
|
275
|
+
it "ables to name defined hooks" do
|
276
|
+
dsl.testhook('the-name2', :prepend) { }
|
277
|
+
dsl.testhook('the-name', :prepend) { }
|
278
|
+
expect(dsl.hooks[:testhook].first[:name]).to eq 'the-name'
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
describe "#servers" do
|
285
|
+
pending "Hey!"
|
286
|
+
end
|
287
|
+
|
288
|
+
describe "#use_servers" do
|
289
|
+
pending "Hey!"
|
290
|
+
end
|
291
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
set :foo, 72
|
@@ -0,0 +1 @@
|
|
1
|
+
use :foo
|
@@ -0,0 +1 @@
|
|
1
|
+
set :foo, options[:value] || 72
|
@@ -0,0 +1 @@
|
|
1
|
+
{}
|
@@ -0,0 +1 @@
|
|
1
|
+
hello
|
Binary file
|
data/spec/logger_spec.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
require 'mamiya/logger'
|
7
|
+
|
8
|
+
describe Mamiya::Logger do
|
9
|
+
it "can log" do
|
10
|
+
sio = StringIO.new('', 'w')
|
11
|
+
logger = described_class.new(outputs: [sio])
|
12
|
+
logger.info 'hello'
|
13
|
+
logger.close
|
14
|
+
|
15
|
+
expect(sio.string).to match(/hello/)
|
16
|
+
end
|
17
|
+
|
18
|
+
context "with multiple outputs" do
|
19
|
+
let!(:tmpdir) { Dir.mktmpdir('mamiya-logger-spec') }
|
20
|
+
after { FileUtils.remove_entry_secure tmpdir }
|
21
|
+
|
22
|
+
it "can log" do
|
23
|
+
sio = StringIO.new('', 'w')
|
24
|
+
i,o = IO.pipe
|
25
|
+
path = File.join(tmpdir, 'test.log')
|
26
|
+
|
27
|
+
logger = described_class.new(outputs: [sio, o, path])
|
28
|
+
logger.info 'hello'
|
29
|
+
logger.close
|
30
|
+
|
31
|
+
io_out = i.read; i.close
|
32
|
+
|
33
|
+
expect(sio.string).to match(/hello/)
|
34
|
+
expect(io_out).to match(/hello/)
|
35
|
+
expect(File.read(path)).to match(/hello/)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#[]" do
|
40
|
+
it "can log" do
|
41
|
+
sio = StringIO.new('', 'w')
|
42
|
+
logger = described_class.new(outputs: [sio])
|
43
|
+
test_logger = logger['test']
|
44
|
+
logger.info 'hello'
|
45
|
+
test_logger.info ''
|
46
|
+
|
47
|
+
expect(test_logger.progname).to eq 'test'
|
48
|
+
expect(logger.progname).to be_nil
|
49
|
+
|
50
|
+
logger.close
|
51
|
+
|
52
|
+
expect(sio.string).to match(/^.*hello.*$/)
|
53
|
+
expect(sio.string).to match(/^.*test.*$/)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#reopen" do
|
58
|
+
it "reopens file IOs" do
|
59
|
+
io = double('io', path: 'foo', tty?: false, write: 0, sync: true)
|
60
|
+
expect(io).to receive(:reopen).with('foo', 'a')
|
61
|
+
expect(io).to receive(:sync=).with(true)
|
62
|
+
|
63
|
+
logger = described_class.new(outputs: [io])
|
64
|
+
|
65
|
+
logger.reopen
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require 'villein/event'
|
5
|
+
|
6
|
+
require 'mamiya/master/agent_monitor'
|
7
|
+
|
8
|
+
describe Mamiya::Master::AgentMonitor do
|
9
|
+
let(:serf) { double('serf') }
|
10
|
+
let(:config) { {} }
|
11
|
+
let(:master) do
|
12
|
+
double('master', logger: Mamiya::Logger.new, serf: serf, config: config)
|
13
|
+
end
|
14
|
+
|
15
|
+
subject(:agent_monitor) do
|
16
|
+
described_class.new(master)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#refresh" do
|
20
|
+
let(:query_response) do
|
21
|
+
{
|
22
|
+
"Acks" => ['a'],
|
23
|
+
"Responses" => {
|
24
|
+
'a' => {"foo" => "bar"}.to_json,
|
25
|
+
},
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:members) do
|
30
|
+
[
|
31
|
+
{
|
32
|
+
"name"=>"a", "status"=>"alive",
|
33
|
+
"addr"=>"x.x.x.x:7676", "port"=>7676,
|
34
|
+
"protocol"=>{"max"=>4, "min"=>2, "version"=>4},
|
35
|
+
"tags"=>{},
|
36
|
+
},
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
before do
|
41
|
+
allow(serf).to receive(:query).with('mamiya:status', '', {}).and_return(query_response)
|
42
|
+
allow(serf).to receive(:members).and_return(members)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "updates #statuses" do
|
46
|
+
expect {
|
47
|
+
agent_monitor.refresh
|
48
|
+
}.to change {
|
49
|
+
agent_monitor.statuses["a"]
|
50
|
+
}.to("foo" => "bar")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "updates #agents" do
|
54
|
+
expect {
|
55
|
+
agent_monitor.refresh
|
56
|
+
}.to change {
|
57
|
+
agent_monitor.agents
|
58
|
+
}.from({}).to("a" => members[0])
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when some member is failing" do
|
62
|
+
let(:members) do
|
63
|
+
[
|
64
|
+
{
|
65
|
+
"name"=>"a", "status"=>"failed",
|
66
|
+
"addr"=>"x.x.x.x:7676", "port"=>7676,
|
67
|
+
"protocol"=>{"max"=>4, "min"=>2, "version"=>4},
|
68
|
+
"tags"=>{},
|
69
|
+
},
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
it "appends to failed_agents" do
|
74
|
+
expect {
|
75
|
+
agent_monitor.refresh
|
76
|
+
}.to change {
|
77
|
+
agent_monitor.failed_agents
|
78
|
+
}.from([]).to(['a'])
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when some agent returned invalid status" do
|
83
|
+
let(:query_response) do
|
84
|
+
{
|
85
|
+
"Acks" => ['a'],
|
86
|
+
"Responses" => {
|
87
|
+
'a' => '{',
|
88
|
+
},
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
it "appends to failed_agents" do
|
93
|
+
expect {
|
94
|
+
agent_monitor.refresh
|
95
|
+
}.to change {
|
96
|
+
agent_monitor.failed_agents
|
97
|
+
}.from([]).to(['a'])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "with argument" do
|
102
|
+
it "passes args to serf query" do
|
103
|
+
expect(serf).to receive(:query).with('mamiya:status', '', node: 'foo').and_return(query_response)
|
104
|
+
agent_monitor.refresh(node: 'foo')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "(commiting events)" do
|
110
|
+
let(:query_response) do
|
111
|
+
{
|
112
|
+
"Acks" => ['a'],
|
113
|
+
"Responses" => {
|
114
|
+
'a' => status.to_json,
|
115
|
+
},
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
let(:members) do
|
120
|
+
[
|
121
|
+
{
|
122
|
+
"name"=>"a", "status"=>"alive",
|
123
|
+
"addr"=>"x.x.x.x:7676", "port"=>7676,
|
124
|
+
"protocol"=>{"max"=>4, "min"=>2, "version"=>4},
|
125
|
+
"tags"=>{},
|
126
|
+
},
|
127
|
+
]
|
128
|
+
end
|
129
|
+
|
130
|
+
let(:status) do
|
131
|
+
{}
|
132
|
+
end
|
133
|
+
|
134
|
+
def commit(event, payload)
|
135
|
+
agent_monitor.commit_event(Villein::Event.new(
|
136
|
+
{
|
137
|
+
'SERF_EVENT' => 'user',
|
138
|
+
'SERF_USER_EVENT' => event,
|
139
|
+
},
|
140
|
+
payload: {name: "a"}.merge(payload).to_json
|
141
|
+
))
|
142
|
+
end
|
143
|
+
|
144
|
+
before do
|
145
|
+
allow(serf).to receive(:query).with('mamiya:status', '', {}).and_return(query_response)
|
146
|
+
allow(serf).to receive(:members).and_return(members)
|
147
|
+
|
148
|
+
agent_monitor.refresh
|
149
|
+
end
|
150
|
+
|
151
|
+
subject(:new_status) { agent_monitor.statuses["a"] }
|
152
|
+
|
153
|
+
describe "fetch-result" do
|
154
|
+
describe ":ack" do
|
155
|
+
let(:status) do
|
156
|
+
{fetcher: {fetching: nil, pending: 0}}
|
157
|
+
end
|
158
|
+
|
159
|
+
it "updates pending" do
|
160
|
+
commit('mamiya:fetch-result:ack', pending: 72)
|
161
|
+
expect(new_status["fetcher"]["pending"]).to eq 72
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe ":start" do
|
166
|
+
let(:status) do
|
167
|
+
{fetcher: {fetching: nil, pending: 0}}
|
168
|
+
end
|
169
|
+
|
170
|
+
it "updates fetching" do
|
171
|
+
commit('mamiya:fetch-result:start',
|
172
|
+
application: 'app', package: 'pkg', pending: 0)
|
173
|
+
expect(new_status["fetcher"]["fetching"]).to eq ['app', 'pkg']
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe ":error" do
|
178
|
+
let(:status) do
|
179
|
+
{fetcher: {fetching: ['app', 'pkg'], pending: 0}}
|
180
|
+
end
|
181
|
+
|
182
|
+
it "updates fetching" do
|
183
|
+
commit('mamiya:fetch-result:error',
|
184
|
+
application: 'app', package: 'pkg', pending: 0)
|
185
|
+
|
186
|
+
expect(new_status["fetcher"]["fetching"]).to eq nil
|
187
|
+
end
|
188
|
+
|
189
|
+
context "when package doesn't match with present state" do
|
190
|
+
it "doesn't updates fetching" do
|
191
|
+
commit('mamiya:fetch-result:error',
|
192
|
+
application: 'app', package: 'pkg2', pending: 0)
|
193
|
+
|
194
|
+
expect(new_status["fetcher"]["fetching"]).to \
|
195
|
+
eq(['app', 'pkg'])
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe ":success" do
|
201
|
+
let(:status) do
|
202
|
+
{fetcher: {fetching: ['app', 'pkg'], pending: 0},
|
203
|
+
packages: {}}
|
204
|
+
end
|
205
|
+
|
206
|
+
it "updates fetching" do
|
207
|
+
commit('mamiya:fetch-result:success',
|
208
|
+
application: 'app', package: 'pkg', pending: 0)
|
209
|
+
|
210
|
+
expect(new_status["fetcher"]["fetching"]).to eq nil
|
211
|
+
end
|
212
|
+
|
213
|
+
it "updates packages" do
|
214
|
+
commit('mamiya:fetch-result:success',
|
215
|
+
application: 'app', package: 'pkg', pending: 0)
|
216
|
+
|
217
|
+
expect(new_status["packages"]["app"]).to eq ["pkg"]
|
218
|
+
end
|
219
|
+
|
220
|
+
context "with existing packages" do
|
221
|
+
let(:status) do
|
222
|
+
{fetcher: {fetching: ['app', 'pkg2'], pending: 0},
|
223
|
+
packages: {"app" => ['pkg1']}}
|
224
|
+
end
|
225
|
+
|
226
|
+
it "updates packages" do
|
227
|
+
commit('mamiya:fetch-result:success',
|
228
|
+
application: 'app', package: 'pkg2', pending: 0)
|
229
|
+
|
230
|
+
expect(new_status["packages"]["app"]).to eq %w(pkg1 pkg2)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context "when package doesn't match with present state" do
|
235
|
+
it "doesn't updates fetching" do
|
236
|
+
commit('mamiya:fetch-result:success',
|
237
|
+
application: 'app', package: 'pkg2', pending: 0)
|
238
|
+
|
239
|
+
expect(agent_monitor.statuses["a"]["fetcher"]["fetching"]).to \
|
240
|
+
eq(['app', 'pkg'])
|
241
|
+
end
|
242
|
+
|
243
|
+
it "updates packages" do
|
244
|
+
commit('mamiya:fetch-result:success',
|
245
|
+
application: 'app', package: 'pkg', pending: 0)
|
246
|
+
|
247
|
+
expect(new_status["packages"]["app"]).to eq ["pkg"]
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
describe ":remove" do
|
253
|
+
context "with existing packages" do
|
254
|
+
let(:status) do
|
255
|
+
{fetcher: {fetching: ['app', 'pkg2'], pending: 0},
|
256
|
+
packages: {"app" => ['pkg1']}}
|
257
|
+
end
|
258
|
+
|
259
|
+
it "updates packages" do
|
260
|
+
commit('mamiya:fetch-result:remove',
|
261
|
+
application: 'app', package: 'pkg1', pending: 0)
|
262
|
+
|
263
|
+
expect(new_status["packages"]["app"]).to eq []
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|