mamiya 0.0.1.alpha24 → 0.0.1.beta1

Sign up to get free protection for your applications and to get access to all the features.
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