mamiya 0.0.1.alpha2

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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +16 -0
  5. data/Gemfile +8 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +43 -0
  8. data/Rakefile +6 -0
  9. data/bin/mamiya +17 -0
  10. data/config.example.yml +11 -0
  11. data/docs/sequences/deploy.png +0 -0
  12. data/docs/sequences/deploy.uml +58 -0
  13. data/example.rb +74 -0
  14. data/lib/mamiya.rb +5 -0
  15. data/lib/mamiya/agent.rb +181 -0
  16. data/lib/mamiya/agent/actions.rb +12 -0
  17. data/lib/mamiya/agent/fetcher.rb +137 -0
  18. data/lib/mamiya/agent/handlers/abstract.rb +20 -0
  19. data/lib/mamiya/agent/handlers/fetch.rb +68 -0
  20. data/lib/mamiya/cli.rb +322 -0
  21. data/lib/mamiya/cli/client.rb +172 -0
  22. data/lib/mamiya/config.rb +57 -0
  23. data/lib/mamiya/dsl.rb +192 -0
  24. data/lib/mamiya/helpers/git.rb +75 -0
  25. data/lib/mamiya/logger.rb +190 -0
  26. data/lib/mamiya/master.rb +118 -0
  27. data/lib/mamiya/master/agent_monitor.rb +146 -0
  28. data/lib/mamiya/master/agent_monitor_handlers.rb +44 -0
  29. data/lib/mamiya/master/web.rb +148 -0
  30. data/lib/mamiya/package.rb +122 -0
  31. data/lib/mamiya/script.rb +117 -0
  32. data/lib/mamiya/steps/abstract.rb +19 -0
  33. data/lib/mamiya/steps/build.rb +72 -0
  34. data/lib/mamiya/steps/extract.rb +26 -0
  35. data/lib/mamiya/steps/fetch.rb +24 -0
  36. data/lib/mamiya/steps/push.rb +34 -0
  37. data/lib/mamiya/storages.rb +17 -0
  38. data/lib/mamiya/storages/abstract.rb +48 -0
  39. data/lib/mamiya/storages/mock.rb +61 -0
  40. data/lib/mamiya/storages/s3.rb +127 -0
  41. data/lib/mamiya/util/label_matcher.rb +38 -0
  42. data/lib/mamiya/version.rb +3 -0
  43. data/mamiya.gemspec +35 -0
  44. data/misc/logger_test.rb +12 -0
  45. data/spec/agent/actions_spec.rb +37 -0
  46. data/spec/agent/fetcher_spec.rb +199 -0
  47. data/spec/agent/handlers/fetch_spec.rb +121 -0
  48. data/spec/agent_spec.rb +255 -0
  49. data/spec/config_spec.rb +50 -0
  50. data/spec/dsl_spec.rb +291 -0
  51. data/spec/fixtures/dsl_test_load.rb +1 -0
  52. data/spec/fixtures/dsl_test_use.rb +1 -0
  53. data/spec/fixtures/helpers/foo.rb +1 -0
  54. data/spec/fixtures/test-package-source/.mamiya.meta.json +1 -0
  55. data/spec/fixtures/test-package-source/greeting +1 -0
  56. data/spec/fixtures/test-package.tar.gz +0 -0
  57. data/spec/fixtures/test.yml +4 -0
  58. data/spec/logger_spec.rb +68 -0
  59. data/spec/master/agent_monitor_spec.rb +269 -0
  60. data/spec/master/web_spec.rb +121 -0
  61. data/spec/master_spec.rb +94 -0
  62. data/spec/package_spec.rb +394 -0
  63. data/spec/script_spec.rb +78 -0
  64. data/spec/spec_helper.rb +38 -0
  65. data/spec/steps/build_spec.rb +261 -0
  66. data/spec/steps/extract_spec.rb +68 -0
  67. data/spec/steps/fetch_spec.rb +96 -0
  68. data/spec/steps/push_spec.rb +73 -0
  69. data/spec/storages/abstract_spec.rb +22 -0
  70. data/spec/storages/s3_spec.rb +342 -0
  71. data/spec/storages_spec.rb +33 -0
  72. data/spec/support/dummy_serf.rb +70 -0
  73. data/spec/util/label_matcher_spec.rb +85 -0
  74. metadata +272 -0
@@ -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
+ hello
Binary file
@@ -0,0 +1,4 @@
1
+ a:
2
+ b:
3
+ - c: d
4
+ e: f
@@ -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