mamiya 0.0.1.alpha24 → 0.0.1.beta1

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -18
  3. data/example/config.agent.rb +3 -0
  4. data/example/config.rb +27 -0
  5. data/example/deploy.rb +19 -11
  6. data/lib/mamiya/agent.rb +38 -2
  7. data/lib/mamiya/agent/actions.rb +4 -0
  8. data/lib/mamiya/agent/tasks/clean.rb +35 -0
  9. data/lib/mamiya/agent/tasks/notifyable.rb +4 -1
  10. data/lib/mamiya/agent/tasks/prepare.rb +2 -0
  11. data/lib/mamiya/agent/tasks/switch.rb +123 -0
  12. data/lib/mamiya/cli.rb +1 -20
  13. data/lib/mamiya/cli/client.rb +225 -3
  14. data/lib/mamiya/configuration.rb +18 -0
  15. data/lib/mamiya/master/agent_monitor.rb +19 -4
  16. data/lib/mamiya/master/agent_monitor_handlers.rb +10 -0
  17. data/lib/mamiya/master/application_status.rb +72 -0
  18. data/lib/mamiya/master/package_status.rb +178 -0
  19. data/lib/mamiya/master/web.rb +48 -44
  20. data/lib/mamiya/steps/build.rb +1 -1
  21. data/lib/mamiya/steps/prepare.rb +1 -1
  22. data/lib/mamiya/steps/switch.rb +2 -1
  23. data/lib/mamiya/storages/filesystem.rb +1 -1
  24. data/lib/mamiya/storages/mock.rb +1 -1
  25. data/lib/mamiya/storages/s3.rb +1 -1
  26. data/lib/mamiya/storages/s3_proxy.rb +1 -1
  27. data/lib/mamiya/version.rb +1 -1
  28. data/spec/agent/actions_spec.rb +26 -1
  29. data/spec/agent/tasks/clean_spec.rb +88 -2
  30. data/spec/agent/tasks/notifyable_spec.rb +3 -3
  31. data/spec/agent/tasks/switch_spec.rb +176 -0
  32. data/spec/agent_spec.rb +142 -1
  33. data/spec/configuration_spec.rb +23 -0
  34. data/spec/master/agent_monitor_spec.rb +128 -38
  35. data/spec/master/application_status_spec.rb +171 -0
  36. data/spec/master/package_status_spec.rb +560 -0
  37. data/spec/master/web_spec.rb +116 -1
  38. data/spec/steps/build_spec.rb +1 -1
  39. data/spec/steps/prepare_spec.rb +6 -1
  40. data/spec/steps/switch_spec.rb +6 -2
  41. data/spec/storages/filesystem_spec.rb +2 -21
  42. data/spec/storages/s3_proxy_spec.rb +2 -22
  43. data/spec/storages/s3_spec.rb +2 -20
  44. metadata +11 -2
@@ -12,7 +12,7 @@ describe Mamiya::Agent::Tasks::Notifyable do
12
12
 
13
13
  describe "#execute" do
14
14
  it "notifies first, then :run" do
15
- expect(agent).to receive(:trigger).with('task', action: 'start', task: job).ordered
15
+ expect(agent).to receive(:trigger).with('task', action: 'start', task: job, coalesce: false).ordered
16
16
  expect(task).to receive(:before).ordered
17
17
  expect(task).to receive(:run).ordered
18
18
  task.execute
@@ -21,12 +21,12 @@ describe Mamiya::Agent::Tasks::Notifyable do
21
21
  it "calls after, then notify" do
22
22
  expect(task).to receive(:run).ordered
23
23
  expect(task).to receive(:after).ordered
24
- expect(agent).to receive(:trigger).with('task', action: 'finish', task: job).ordered
24
+ expect(agent).to receive(:trigger).with('task', action: 'finish', task: job, coalesce: false).ordered
25
25
  task.execute
26
26
  end
27
27
 
28
28
  it "handles error" do
29
- expect(agent).to receive(:trigger).with('task', action: 'error', task: job, error: RuntimeError.name)
29
+ expect(agent).to receive(:trigger).with('task', action: 'error', task: job, error: RuntimeError.name, coalesce: false)
30
30
  err = RuntimeError.new
31
31
  allow(task).to receive(:run).and_raise(err)
32
32
  task.execute
@@ -0,0 +1,176 @@
1
+ require 'spec_helper'
2
+ require 'tmpdir'
3
+ require 'pathname'
4
+
5
+ require 'mamiya/agent/tasks/switch'
6
+
7
+ require 'mamiya/steps/switch'
8
+
9
+ describe Mamiya::Agent::Tasks::Switch do
10
+ let!(:tmpdir) { Pathname.new Dir.mktmpdir("mamiya-agent-tasks-switch-spec") }
11
+ after { FileUtils.remove_entry_secure tmpdir }
12
+
13
+ let(:deploy_to) { tmpdir.join('deploy_to').tap(&:mkpath) }
14
+ let(:packages_dir) { tmpdir.join('packages').tap(&:mkpath) }
15
+ let(:packages_app_dir) { tmpdir.join('packages', 'myapp').tap(&:mkpath) }
16
+ let(:prereleases_dir) { tmpdir.join('prereleases').tap(&:mkpath) }
17
+ let(:prereleases_app_dir) { tmpdir.join('prereleases', 'myapp').tap(&:mkpath) }
18
+
19
+
20
+ let(:config) do
21
+ _pkg, _pre, _dto = packages_dir, prereleases_dir, deploy_to
22
+ Mamiya::Configuration.new.evaluate! do
23
+ set :packages_dir, _pkg
24
+ set :prereleases_dir, _pre
25
+ applications[:myapp] = {deploy_to: _dto}
26
+ end
27
+ end
28
+
29
+ let(:agent) { double('agent', config: config, trigger: nil, labels: [:foo, :bar]) }
30
+ let(:task_queue) { double('task_queue', enqueue: nil) }
31
+
32
+ let(:switch_step) { double('switch step', run!: nil) }
33
+
34
+ let(:job) { {'app' => 'myapp', 'pkg' => 'mypkg'} }
35
+
36
+ subject(:task) { described_class.new(task_queue, job, agent: agent, raise_error: true) }
37
+
38
+ it 'inherits notifyable task' do
39
+ expect(described_class.ancestors).to include(Mamiya::Agent::Tasks::Notifyable)
40
+ end
41
+
42
+ describe "#execute" do
43
+ context "when package not fetched and not prepared" do
44
+ before do
45
+ expect(Mamiya::Steps::Switch).not_to receive(:new)
46
+ end
47
+
48
+ it "enqueues fetch task and finish" do
49
+ expect(task_queue).to receive(:enqueue).with(
50
+ :fetch, job.merge('task' => 'switch', '_chain' => ['prepare', 'switch'])
51
+ )
52
+
53
+ task.execute
54
+ end
55
+
56
+ context "with _chain-ed job" do
57
+ let(:job) { {'app' => 'myapp', 'pkg' => 'mypkg', '_chain' => ['next']} }
58
+
59
+ it "enqueues prepare task and finish" do
60
+ expect(task_queue).to receive(:enqueue).with(
61
+ :fetch, job.merge('task' => 'switch', '_chain' => ['prepare', 'switch', 'next'])
62
+ )
63
+
64
+ task.execute
65
+ end
66
+ end
67
+ end
68
+
69
+ context "when package fetched but not prepared" do
70
+ before do
71
+ File.write packages_app_dir.join('mypkg.tar.gz'), "\n"
72
+ File.write packages_app_dir.join('mypkg.json'), "{}\n"
73
+ expect(Mamiya::Steps::Switch).not_to receive(:new)
74
+ end
75
+
76
+ it "enqueues prepare task and finish" do
77
+ expect(task_queue).to receive(:enqueue).with(
78
+ :prepare, job.merge('task' => 'switch', '_chain' => ['switch'])
79
+ )
80
+
81
+ task.execute
82
+ end
83
+
84
+ context "with _chain-ed job" do
85
+ let(:job) { {'app' => 'myapp', 'pkg' => 'mypkg', '_chain' => ['next']} }
86
+
87
+ it "enqueues prepare task and finish" do
88
+ expect(task_queue).to receive(:enqueue).with(
89
+ :prepare, job.merge('task' => 'switch', '_chain' => ['switch', 'next'])
90
+ )
91
+
92
+ task.execute
93
+ end
94
+ end
95
+ end
96
+
97
+ context "when package prepared" do
98
+ before do
99
+ File.write packages_app_dir.join('mypkg.tar.gz'), "\n"
100
+ File.write packages_app_dir.join('mypkg.json'), "{}\n"
101
+
102
+ prerelease = prereleases_app_dir.join('mypkg').tap(&:mkpath)
103
+ File.write prerelease.join('hello'), "hola\n"
104
+ File.write prerelease.join('.mamiya.prepared'), "#{Time.now.to_i}\n"
105
+
106
+ allow(Mamiya::Steps::Switch).to receive(:new).with(
107
+ target: deploy_to.join('releases', 'mypkg'),
108
+ labels: [:foo, :bar],
109
+ no_release: false,
110
+ config: config,
111
+ logger: task.logger,
112
+ ).and_return(switch_step)
113
+ end
114
+
115
+ it "copies prerelease to releases_dir" do
116
+ expect {
117
+ task.execute
118
+ }.to change {
119
+ deploy_to.join('releases', 'mypkg', 'hello').exist? &&
120
+ deploy_to.join('releases', 'mypkg', 'hello').read
121
+ }.from(false).to "hola\n"
122
+ end
123
+
124
+ it "calls switch step" do
125
+ expect(switch_step).to receive(:run!) do
126
+ expect(deploy_to.join('releases', 'mypkg', 'hello')).to be_exist
127
+ end
128
+ task.execute
129
+ end
130
+
131
+ context "when prepared release exists in releases_dir" do
132
+ before do
133
+ release = deploy_to.join('releases', 'mypkg').tap(&:mkpath)
134
+ File.write release.join('hehe'), ":)\n"
135
+ File.write release.join('.mamiya.prepared'), "#{Time.now.to_i}\n"
136
+ end
137
+
138
+ it "re-uses existing release" do
139
+ task.execute
140
+ expect(deploy_to.join('releases', 'mypkg', 'hehe').read).to eq ":)\n"
141
+ end
142
+ end
143
+
144
+ context "when non-prepared release exists in releases_dir" do
145
+ before do
146
+ release = deploy_to.join('releases', 'mypkg').tap(&:mkpath)
147
+ File.write release.join('hehe'), ":)\n"
148
+ end
149
+
150
+ it "re-uses existing release" do
151
+ task.execute
152
+ expect(deploy_to.join('releases', 'mypkg', 'hehe')).not_to be_exist
153
+ expect(deploy_to.join('releases', 'mypkg', 'hello')).to be_exist
154
+ end
155
+ end
156
+
157
+ context "with no_release" do
158
+ let(:job) { {'app' => 'myapp', 'pkg' => 'mypkg', 'no_release' => true} }
159
+
160
+ it "calls switch step with no_release" do
161
+ expect(Mamiya::Steps::Switch).to receive(:new).with(
162
+ target: deploy_to.join('releases', 'mypkg'),
163
+ labels: [:foo, :bar],
164
+ no_release: true,
165
+ config: config,
166
+ logger: task.logger,
167
+ ).and_return(switch_step)
168
+
169
+ expect(switch_step).to receive(:run!)
170
+
171
+ task.execute
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
data/spec/agent_spec.rb CHANGED
@@ -92,8 +92,13 @@ describe Mamiya::Agent do
92
92
  before do
93
93
  allow(agent).to receive(:existing_packages).and_return("app" => ["pkg"])
94
94
  allow(agent).to receive(:existing_prereleases).and_return("app" => ["pkg"])
95
+
96
+ allow(agent).to receive(:releases).and_return("app" => ["pkg"])
97
+ allow(agent).to receive(:currents).and_return("app" => "pkg")
98
+
95
99
  allow(agent).to receive(:labels).and_return([:foo,:bar])
96
100
 
101
+
97
102
  allow(task_queue).to receive(:status).and_return({a: {working: nil, queue: []}})
98
103
  end
99
104
 
@@ -119,6 +124,14 @@ describe Mamiya::Agent do
119
124
  expect(status[:prereleases]).to eq agent.existing_prereleases
120
125
  end
121
126
 
127
+ it "includes releases" do
128
+ expect(status[:releases]).to eq agent.releases
129
+ end
130
+
131
+ it "includes currents" do
132
+ expect(status[:currents]).to eq agent.currents
133
+ end
134
+
122
135
  it "includes status" do
123
136
  expect(status[:labels]).to eq agent.labels
124
137
  end
@@ -130,9 +143,17 @@ describe Mamiya::Agent do
130
143
  expect(status.has_key?(:packages)).to be_false
131
144
  end
132
145
 
133
- it "doesn't include existing packages" do
146
+ it "doesn't include existing prereleases" do
134
147
  expect(status.has_key?(:prereleases)).to be_false
135
148
  end
149
+
150
+ it "doesn't include existing releases" do
151
+ expect(status.has_key?(:releases)).to be_false
152
+ end
153
+
154
+ it "doesn't include existing currents" do
155
+ expect(status.has_key?(:currents)).to be_false
156
+ end
136
157
  end
137
158
 
138
159
  describe "(task queue)" do
@@ -192,6 +213,118 @@ describe Mamiya::Agent do
192
213
  end
193
214
  end
194
215
 
216
+ describe "#releases" do
217
+ let!(:tmpdir) { Pathname.new Dir.mktmpdir('mamiya-agent-spec') }
218
+ after { FileUtils.remove_entry_secure(tmpdir) }
219
+
220
+ let(:deploy_to_a) { tmpdir.join('a').tap(&:mkdir) }
221
+ let(:deploy_to_b) { tmpdir.join('b').tap(&:mkdir) }
222
+
223
+ # To test unexist directory (should return empty element)
224
+ let(:deploy_to_c) { tmpdir.join('c') }
225
+
226
+ let(:config) do
227
+ _a, _b, _c = deploy_to_a, deploy_to_b, deploy_to_c
228
+ Mamiya::Configuration.new.evaluate! do
229
+ set :applications, {
230
+ a: {deploy_to: _a.to_s},
231
+ b: {deploy_to: _b.to_s},
232
+ c: {deploy_to: _c.to_s},
233
+ }
234
+ end
235
+ end
236
+
237
+ before do
238
+ deploy_to_a.join('releases').tap do |releases|
239
+ releases.mkdir
240
+
241
+ releases.join('1').mkdir
242
+ releases.join('2').mkdir
243
+ end
244
+
245
+ deploy_to_b.join('releases').tap do |releases|
246
+ releases.mkdir
247
+
248
+ releases.join('3').mkdir
249
+ releases.join('4').mkdir
250
+ releases.join('5').mkdir
251
+ end
252
+ end
253
+
254
+ subject(:releases) { agent.releases }
255
+
256
+ it "returns releases" do
257
+ expect(releases).to eq(
258
+ a: ['1','2'],
259
+ b: ['3','4','5'],
260
+ c: [],
261
+ )
262
+ end
263
+ end
264
+
265
+ describe "#currents" do
266
+ let!(:tmpdir) { Pathname.new Dir.mktmpdir('mamiya-agent-spec') }
267
+ after { FileUtils.remove_entry_secure(tmpdir) }
268
+
269
+ let(:deploy_to_a) { tmpdir.join('a').tap(&:mkdir) }
270
+ let(:deploy_to_b) { tmpdir.join('b').tap(&:mkdir) }
271
+
272
+ let(:release_a) { deploy_to_a.join('releases', '1').tap(&:mkpath) }
273
+ let(:release_b) { deploy_to_b.join('releases', '2').tap(&:mkpath) }
274
+
275
+ let(:current_a) { deploy_to_a.join('current') }
276
+ let(:current_b) { deploy_to_b.join('current') }
277
+
278
+ let(:target_a) { release_a.realpath }
279
+ let(:target_b) { release_b.realpath }
280
+
281
+ let(:config) do
282
+ _a, _b = deploy_to_a, deploy_to_b
283
+ Mamiya::Configuration.new.evaluate! do
284
+ set :applications, {
285
+ a: {deploy_to: _a.to_s},
286
+ b: {deploy_to: _b.to_s},
287
+ }
288
+ end
289
+ end
290
+
291
+ before do
292
+ deploy_to_a.join('current').make_symlink(target_a)
293
+ deploy_to_b.join('current').make_symlink(target_b)
294
+ end
295
+
296
+ subject(:currents) { agent.currents }
297
+
298
+ it "returns releases" do
299
+ expect(currents).to eq(
300
+ a: '1',
301
+ b: '2',
302
+ )
303
+ end
304
+
305
+ context "when relative" do
306
+ let(:target_a) { release_a.relative_path_from(deploy_to_a) }
307
+ let(:target_b) { release_b.relative_path_from(deploy_to_b) }
308
+
309
+ it "returns releases" do
310
+ expect(currents).to eq(
311
+ a: '1',
312
+ b: '2',
313
+ )
314
+ end
315
+ end
316
+
317
+ context "when noexist" do
318
+ before do
319
+ FileUtils.remove_entry_secure release_a
320
+ FileUtils.remove_entry_secure release_b
321
+ end
322
+
323
+ it "returns releases" do
324
+ expect(currents).to eq({})
325
+ end
326
+ end
327
+ end
195
328
 
196
329
  describe "#labels" do
197
330
  subject(:labels) { agent.labels }
@@ -226,6 +359,8 @@ describe Mamiya::Agent do
226
359
  it "responds to 'mamiya:packages'" do
227
360
  allow(agent).to receive(:existing_packages).and_return("app" => %w(pkg1 pkg2))
228
361
  allow(agent).to receive(:existing_prereleases).and_return("app" => %w(pkg2))
362
+ allow(agent).to receive(:currents).and_return("app" => 'pkg2')
363
+ allow(agent).to receive(:releases).and_return("app" => %w(pkg3))
229
364
 
230
365
  response = serf.trigger_query('mamiya:packages', '')
231
366
 
@@ -236,6 +371,12 @@ describe Mamiya::Agent do
236
371
  "prereleases" => {
237
372
  "app" => %w(pkg2)
238
373
  },
374
+ "currents" => {
375
+ "app" => 'pkg2'
376
+ },
377
+ "releases" => {
378
+ "app" => %w(pkg3)
379
+ },
239
380
  )
240
381
  end
241
382
  end
@@ -32,4 +32,27 @@ describe Mamiya::Configuration do
32
32
  expect(storage_class).to eq klass
33
33
  end
34
34
  end
35
+
36
+ describe "#deploy_to_for(app)" do
37
+ before do
38
+ config.evaluate! do
39
+ applications[:myapp] = {deploy_to: '/apps/myapp'}
40
+ end
41
+ end
42
+
43
+ it "returns deploy_to" do
44
+ expect(config.deploy_to_for(:myapp)).to eq Pathname.new('/apps/myapp')
45
+ end
46
+
47
+ it "returns deploy_to" do
48
+ expect(config.deploy_to_for('myapp')).to eq Pathname.new('/apps/myapp')
49
+ end
50
+
51
+ context "for nonexistent" do
52
+ it "returns nil" do
53
+ expect(config.deploy_to_for('nonexistent')).to be_nil
54
+ expect(config.deploy_to_for(:nonexistent)).to be_nil
55
+ end
56
+ end
57
+ end
35
58
  end
@@ -32,7 +32,13 @@ describe Mamiya::Master::AgentMonitor do
32
32
  {
33
33
  "Acks" => ['a'],
34
34
  "Responses" => {
35
- 'a' => {"foo" => "bar", 'packages' => {"app" => ['pkg1']}, 'prereleases' => {"app" => ['pkg2']}}.to_json,
35
+ 'a' => {
36
+ "foo" => "bar",
37
+ 'packages' => {"app" => ['pkg1']},
38
+ 'prereleases' => {"app" => ['pkg2']},
39
+ 'releases' => {"app" => ['pkg3']},
40
+ 'currents' => {"app" => 'pkg4'},
41
+ }.to_json,
36
42
  },
37
43
  }
38
44
  end
@@ -41,7 +47,12 @@ describe Mamiya::Master::AgentMonitor do
41
47
  {
42
48
  "Acks" => ['a'],
43
49
  "Responses" => {
44
- 'a' => {"packages" => {"app" => ['pkg1','pkg2']}, "prereleases" => {"app" => ['pkg2']}}.to_json,
50
+ 'a' => {
51
+ 'packages' => {"app" => ['pkg1', 'pkg2']},
52
+ 'prereleases' => {"app" => ['pkg2']},
53
+ 'releases' => {"app" => ['pkg4']},
54
+ 'currents' => {"app" => 'pkg5'},
55
+ }.to_json,
45
56
  },
46
57
  }
47
58
  end
@@ -121,20 +132,18 @@ describe Mamiya::Master::AgentMonitor do
121
132
  }
122
133
  end
123
134
 
124
- it "updates status .packages by packages query" do
135
+ it "updates package statuses from status" do
125
136
  expect {
126
137
  agent_monitor.refresh
127
138
  }.to change {
128
- agent_monitor.statuses["a"] && agent_monitor.statuses["a"]['packages']
129
- }.to("app" => %w(pkg1 pkg2))
130
- end
131
-
132
- it "updates status .prereleases by packages query" do
133
- expect {
134
- agent_monitor.refresh
135
- }.to change {
136
- agent_monitor.statuses["a"] && agent_monitor.statuses["a"]['prereleases']
137
- }.to("app" => %w(pkg2))
139
+ agent_monitor.statuses["a"] && \
140
+ agent_monitor.statuses["a"].values_at('packages', 'prereleases', 'releases', 'currents')
141
+ }.to([
142
+ {"app" => %w(pkg1 pkg2)},
143
+ {"app" => %w(pkg2)},
144
+ {"app" => %w(pkg4)},
145
+ {"app" => 'pkg5'},
146
+ ])
138
147
  end
139
148
 
140
149
  context "when packages query unavailable, but available in status query" do
@@ -146,24 +155,31 @@ describe Mamiya::Master::AgentMonitor do
146
155
  }
147
156
  end
148
157
 
149
- it "updates status .packages from status" do
150
- expect {
151
- agent_monitor.refresh
152
- }.to change {
153
- agent_monitor.statuses["a"] && agent_monitor.statuses["a"]['packages']
154
- }.to("app" => %w(pkg1))
155
- end
156
-
157
- it "updates status .prereleases from status" do
158
+ it "updates package statuses from status" do
158
159
  expect {
159
160
  agent_monitor.refresh
160
161
  }.to change {
161
- agent_monitor.statuses["a"] && agent_monitor.statuses["a"]['prereleases']
162
- }.to("app" => %w(pkg2))
162
+ agent_monitor.statuses["a"] && \
163
+ agent_monitor.statuses["a"].values_at('packages', 'prereleases', 'releases', 'currents')
164
+ }.to([
165
+ {"app" => %w(pkg1)},
166
+ {"app" => %w(pkg2)},
167
+ {"app" => %w(pkg3)},
168
+ {"app" => 'pkg4'},
169
+ ])
163
170
  end
164
171
  end
165
172
 
166
173
  context "when failed to retrieve package list, but it was available previously in packages query" do
174
+ let(:status_query_response) do
175
+ {
176
+ "Acks" => ['a'],
177
+ "Responses" => {
178
+ 'a' => {"foo" => "bar"}.to_json,
179
+ },
180
+ }
181
+ end
182
+
167
183
  before do
168
184
  agent_monitor.refresh
169
185
  packages_query_response['Responses'] = {}
@@ -173,7 +189,7 @@ describe Mamiya::Master::AgentMonitor do
173
189
  expect {
174
190
  agent_monitor.refresh
175
191
  }.not_to change {
176
- agent_monitor.statuses["a"]['packages']
192
+ agent_monitor.statuses["a"].values_at('packages', 'prereleases', 'releases', 'currents')
177
193
  }
178
194
  end
179
195
  end
@@ -256,18 +272,9 @@ describe Mamiya::Master::AgentMonitor do
256
272
  }
257
273
  end
258
274
 
259
- let(:packages_query_response) do
260
- {
261
- "Acks" => ['a'],
262
- "Responses" => {
263
- 'a' => {"packages" => {"app" => ['pkg1','pkg2']}, "prereleases" => {"app" => ['pkg2']}}.to_json,
264
- },
265
- }
266
- end
267
-
268
275
  let(:status_query_response_part) do
269
276
  {
270
- "Acks" => ['a'],
277
+ "Acks" => ['b'],
271
278
  "Responses" => {
272
279
  'b' => {"foo" => "bar"}.to_json,
273
280
  },
@@ -276,9 +283,14 @@ describe Mamiya::Master::AgentMonitor do
276
283
 
277
284
  let(:packages_query_response_part) do
278
285
  {
279
- "Acks" => ['a'],
286
+ "Acks" => ['b'],
280
287
  "Responses" => {
281
- 'b' => {"packages" => {"app" => ['pkg1']}, "prereleases" => {"app" => ['pkg2']}}.to_json,
288
+ 'b' => {
289
+ "packages" => {"app" => ['pkg1']},
290
+ "prereleases" => {"app" => ['pkg2']},
291
+ "releases" => {"app" => ['pkg4','pkg5']},
292
+ "currents" => {"app" => ['pkg6']},
293
+ }.to_json,
282
294
  },
283
295
  }
284
296
  end
@@ -311,7 +323,13 @@ describe Mamiya::Master::AgentMonitor do
311
323
 
312
324
  expect(agent_monitor.failed_agents).to eq []
313
325
  expect(agent_monitor.statuses['b']).to eq(
314
- {"foo" => "bar", "packages" => {"app" => ['pkg1']}, "prereleases" => {"app" => ['pkg2']}}
326
+ {
327
+ "foo" => "bar",
328
+ "packages" => {"app" => ['pkg1']},
329
+ "prereleases" => {"app" => ['pkg2']},
330
+ "releases" => {"app" => ['pkg4','pkg5']},
331
+ "currents" => {"app" => ['pkg6']},
332
+ }
315
333
  )
316
334
  expect(agent_monitor.agents['b']).to eq(
317
335
  {
@@ -325,6 +343,9 @@ describe Mamiya::Master::AgentMonitor do
325
343
  end
326
344
  end
327
345
 
346
+ describe "#package_status(application, package)", pending: 'WIP' do
347
+ end
348
+
328
349
  describe "(commiting events)" do
329
350
  let(:status_query_response) do
330
351
  {
@@ -593,6 +614,47 @@ describe Mamiya::Master::AgentMonitor do
593
614
  end
594
615
  end
595
616
 
617
+ describe "release" do
618
+ describe ":remove" do
619
+ let(:status) do
620
+ {releases: {'myapp' => ['pkg1']}}
621
+ end
622
+
623
+ it "removes removed release from releases" do
624
+ commit('mamiya:release:remove',
625
+ app: 'myapp', pkg: 'pkg1')
626
+
627
+ expect(new_status["releases"]['myapp']).to eq []
628
+ end
629
+
630
+ context "with existing packages" do
631
+ let(:status) do
632
+ {releases: {'myapp' => ['pkg1', 'pkg2']}}
633
+ end
634
+
635
+ it "removes removed release from releases" do
636
+ commit('mamiya:release:remove',
637
+ app: 'myapp', pkg: 'pkg1')
638
+
639
+ expect(new_status["releases"]['myapp']).to eq ['pkg2']
640
+ end
641
+ end
642
+
643
+ context "with inexist package" do
644
+ let(:status) do
645
+ {releases: {'myapp' => ['pkg1', 'pkg3']}}
646
+ end
647
+
648
+ it "removes removed release from packages" do
649
+ commit('mamiya:release:remove',
650
+ app: 'myapp', pkg: 'pkg2')
651
+
652
+ expect(new_status["releases"]['myapp']).to eq ['pkg1', 'pkg3']
653
+ end
654
+ end
655
+ end
656
+ end
657
+
596
658
  describe "fetch" do
597
659
  describe "success" do
598
660
  let(:status) do
@@ -648,6 +710,34 @@ describe Mamiya::Master::AgentMonitor do
648
710
  end
649
711
  end
650
712
  end
713
+
714
+ describe "switch" do
715
+ describe "success" do
716
+ let(:status) do
717
+ {currents: {}}
718
+ end
719
+
720
+ it "updates current" do
721
+ commit('mamiya:task:finish',
722
+ task: {task: 'switch', app: 'myapp', pkg: 'pkg'})
723
+
724
+ expect(new_status["currents"]['myapp']).to eq "pkg"
725
+ end
726
+
727
+ context "with existing current" do
728
+ let(:status) do
729
+ {currents: {'myapp' => 'pkg1'}}
730
+ end
731
+
732
+ it "updates current" do
733
+ commit('mamiya:task:finish',
734
+ task: {task: 'switch', app: 'myapp', pkg: 'pkg2'})
735
+
736
+ expect(new_status["currents"]['myapp']).to eq 'pkg2'
737
+ end
738
+ end
739
+ end
740
+ end
651
741
  end
652
742
  end
653
743
  end