aptible-cli 0.14.1 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -1
- data/aptible-cli.gemspec +1 -0
- data/bin/aptible +9 -5
- data/lib/aptible/cli.rb +36 -0
- data/lib/aptible/cli/agent.rb +10 -6
- data/lib/aptible/cli/error.rb +6 -0
- data/lib/aptible/cli/formatter.rb +21 -0
- data/lib/aptible/cli/formatter/grouped_keyed_list.rb +54 -0
- data/lib/aptible/cli/formatter/keyed_list.rb +25 -0
- data/lib/aptible/cli/formatter/keyed_object.rb +16 -0
- data/lib/aptible/cli/formatter/list.rb +33 -0
- data/lib/aptible/cli/formatter/node.rb +8 -0
- data/lib/aptible/cli/formatter/object.rb +38 -0
- data/lib/aptible/cli/formatter/root.rb +46 -0
- data/lib/aptible/cli/formatter/value.rb +25 -0
- data/lib/aptible/cli/helpers/app.rb +1 -0
- data/lib/aptible/cli/helpers/database.rb +22 -6
- data/lib/aptible/cli/helpers/operation.rb +3 -2
- data/lib/aptible/cli/helpers/tunnel.rb +1 -3
- data/lib/aptible/cli/helpers/vhost.rb +9 -46
- data/lib/aptible/cli/renderer.rb +26 -0
- data/lib/aptible/cli/renderer/base.rb +8 -0
- data/lib/aptible/cli/renderer/json.rb +26 -0
- data/lib/aptible/cli/renderer/text.rb +99 -0
- data/lib/aptible/cli/resource_formatter.rb +136 -0
- data/lib/aptible/cli/subcommands/apps.rb +26 -14
- data/lib/aptible/cli/subcommands/backup.rb +22 -4
- data/lib/aptible/cli/subcommands/config.rb +15 -11
- data/lib/aptible/cli/subcommands/db.rb +82 -31
- data/lib/aptible/cli/subcommands/deploy.rb +1 -1
- data/lib/aptible/cli/subcommands/endpoints.rb +11 -8
- data/lib/aptible/cli/subcommands/operation.rb +2 -1
- data/lib/aptible/cli/subcommands/rebuild.rb +1 -1
- data/lib/aptible/cli/subcommands/restart.rb +1 -1
- data/lib/aptible/cli/subcommands/services.rb +8 -9
- data/lib/aptible/cli/version.rb +1 -1
- data/spec/aptible/cli/agent_spec.rb +11 -14
- data/spec/aptible/cli/formatter_spec.rb +4 -0
- data/spec/aptible/cli/renderer/json_spec.rb +63 -0
- data/spec/aptible/cli/renderer/text_spec.rb +150 -0
- data/spec/aptible/cli/resource_formatter_spec.rb +113 -0
- data/spec/aptible/cli/subcommands/apps_spec.rb +144 -28
- data/spec/aptible/cli/subcommands/backup_spec.rb +37 -16
- data/spec/aptible/cli/subcommands/config_spec.rb +95 -0
- data/spec/aptible/cli/subcommands/db_spec.rb +185 -93
- data/spec/aptible/cli/subcommands/endpoints_spec.rb +10 -8
- data/spec/aptible/cli/subcommands/operation_spec.rb +0 -1
- data/spec/aptible/cli/subcommands/rebuild_spec.rb +17 -0
- data/spec/aptible/cli/subcommands/services_spec.rb +8 -12
- data/spec/aptible/cli_spec.rb +31 -0
- data/spec/fabricators/account_fabricator.rb +11 -0
- data/spec/fabricators/app_fabricator.rb +15 -0
- data/spec/fabricators/configuration_fabricator.rb +8 -0
- data/spec/fabricators/database_image_fabricator.rb +17 -0
- data/spec/fabricators/operation_fabricator.rb +1 -0
- data/spec/fabricators/service_fabricator.rb +4 -0
- data/spec/spec_helper.rb +63 -1
- metadata +55 -4
- data/spec/aptible/cli/helpers/vhost_spec.rb +0 -105
@@ -4,10 +4,12 @@ class SocatHelperMock < OpenStruct
|
|
4
4
|
end
|
5
5
|
|
6
6
|
describe Aptible::CLI::Agent do
|
7
|
+
let(:token) { double('token') }
|
8
|
+
|
7
9
|
before do
|
8
10
|
allow(subject).to receive(:ask)
|
9
11
|
allow(subject).to receive(:save_token)
|
10
|
-
allow(subject).to receive(:fetch_token) {
|
12
|
+
allow(subject).to receive(:fetch_token) { token }
|
11
13
|
end
|
12
14
|
|
13
15
|
let(:handle) { 'foobar' }
|
@@ -15,79 +17,114 @@ describe Aptible::CLI::Agent do
|
|
15
17
|
let(:socat_helper) { SocatHelperMock.new(port: 4242) }
|
16
18
|
|
17
19
|
describe '#db:create' do
|
18
|
-
let(:db) { Fabricate(:database) }
|
19
|
-
let(:op) { Fabricate(:operation) }
|
20
|
-
let(:account) { Fabricate(:account) }
|
21
|
-
|
22
20
|
before do
|
23
21
|
allow(Aptible::Api::Account).to receive(:all).and_return([account])
|
24
|
-
allow(db).to receive(:reload).and_return(db)
|
25
|
-
allow(op).to receive(:errors).and_return(Aptible::Resource::Errors.new)
|
26
22
|
end
|
27
23
|
|
28
|
-
|
24
|
+
def expect_provision_database(create_opts, provision_opts = {})
|
25
|
+
db = Fabricate(:database)
|
26
|
+
expect(db).to receive(:reload).and_return(db)
|
27
|
+
|
28
|
+
op = Fabricate(:operation)
|
29
|
+
|
29
30
|
expect(account).to receive(:create_database!)
|
30
|
-
.with(
|
31
|
-
.and_return(db)
|
31
|
+
.with(**create_opts).and_return(db)
|
32
32
|
|
33
33
|
expect(db).to receive(:create_operation)
|
34
|
-
.with(type: 'provision')
|
35
|
-
|
34
|
+
.with(type: 'provision', **provision_opts).and_return(op)
|
35
|
+
|
36
|
+
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
37
|
+
end
|
38
|
+
|
39
|
+
let(:account) { Fabricate(:account) }
|
36
40
|
|
37
|
-
|
38
|
-
|
41
|
+
it 'creates a new DB' do
|
42
|
+
expect_provision_database(handle: 'foo', type: 'postgresql')
|
39
43
|
|
40
44
|
subject.options = { type: 'postgresql' }
|
41
45
|
subject.send('db:create', 'foo')
|
42
46
|
end
|
43
47
|
|
44
48
|
it 'creates a new DB with a container size' do
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
expect(db).to receive(:create_operation)
|
50
|
-
.with(type: 'provision', container_size: 1024)
|
51
|
-
.and_return(op)
|
52
|
-
|
53
|
-
expect(subject).to receive(:attach_to_operation_logs)
|
54
|
-
.with(op)
|
49
|
+
expect_provision_database(
|
50
|
+
{ handle: 'foo', type: 'postgresql', initial_container_size: 1024 },
|
51
|
+
{ container_size: 1024 }
|
52
|
+
)
|
55
53
|
|
56
54
|
subject.options = { type: 'postgresql', container_size: 1024 }
|
57
55
|
subject.send('db:create', 'foo')
|
58
56
|
end
|
59
57
|
|
60
58
|
it 'creates a new DB with a disk size' do
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
expect(db).to receive(:create_operation)
|
66
|
-
.with(type: 'provision', disk_size: 200)
|
67
|
-
.and_return(op)
|
68
|
-
|
69
|
-
expect(subject).to receive(:attach_to_operation_logs)
|
70
|
-
.with(op)
|
59
|
+
expect_provision_database(
|
60
|
+
{ handle: 'foo', type: 'postgresql', initial_disk_size: 200 },
|
61
|
+
{ disk_size: 200 }
|
62
|
+
)
|
71
63
|
|
72
64
|
subject.options = { type: 'postgresql', size: 200 }
|
73
65
|
subject.send('db:create', 'foo')
|
74
66
|
end
|
75
67
|
|
76
68
|
it 'deprovisions the database if the operation cannot be created' do
|
77
|
-
|
69
|
+
db = Fabricate(:database)
|
70
|
+
|
71
|
+
provision_op = Fabricate(:operation)
|
72
|
+
provision_op.errors.full_messages << 'oops'
|
73
|
+
|
74
|
+
deprovision_op = Fabricate(:operation)
|
78
75
|
|
79
76
|
expect(account).to receive(:create_database!).and_return(db)
|
80
77
|
|
81
78
|
expect(db).to receive(:create_operation)
|
82
|
-
.with(type: 'provision')
|
83
|
-
.once.ordered.and_return(op)
|
79
|
+
.with(type: 'provision').once.ordered.and_return(provision_op)
|
84
80
|
|
85
81
|
expect(db).to receive(:create_operation!)
|
86
|
-
.with(type: 'deprovision')
|
87
|
-
.once.ordered
|
82
|
+
.with(type: 'deprovision').once.ordered.and_return(deprovision_op)
|
88
83
|
|
89
84
|
expect { subject.send('db:create', 'foo') }.to raise_error(/oops/im)
|
90
85
|
end
|
86
|
+
|
87
|
+
context 'with version' do
|
88
|
+
let(:img) do
|
89
|
+
Fabricate(:database_image, type: 'postgresql', version: '9.4')
|
90
|
+
end
|
91
|
+
|
92
|
+
let(:alt_version) do
|
93
|
+
Fabricate(:database_image, type: 'postgresql', version: '10')
|
94
|
+
end
|
95
|
+
|
96
|
+
let(:alt_type) do
|
97
|
+
Fabricate(:database_image, type: 'redis', version: '9.4')
|
98
|
+
end
|
99
|
+
|
100
|
+
before do
|
101
|
+
allow(Aptible::Api::DatabaseImage).to receive(:all)
|
102
|
+
.with(token: token).and_return([alt_version, alt_type, img])
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'provisions a Database with a matching Database Image' do
|
106
|
+
expect_provision_database(
|
107
|
+
handle: 'foo',
|
108
|
+
type: 'postgresql',
|
109
|
+
database_image: img
|
110
|
+
)
|
111
|
+
|
112
|
+
subject.options = { type: 'postgresql', version: '9.4' }
|
113
|
+
subject.send('db:create', 'foo')
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'fails if the Database Image does not exist' do
|
117
|
+
subject.options = { type: 'postgresql', version: '123' }
|
118
|
+
expect { subject.send('db:create', 'foo') }
|
119
|
+
.to raise_error(Thor::Error, /no database image/i)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'fails if type is not passed' do
|
123
|
+
subject.options = { version: '123' }
|
124
|
+
expect { subject.send('db:create', 'foo') }
|
125
|
+
.to raise_error(Thor::Error, /type is required/i)
|
126
|
+
end
|
127
|
+
end
|
91
128
|
end
|
92
129
|
|
93
130
|
describe '#db:tunnel' do
|
@@ -108,17 +145,20 @@ describe Aptible::CLI::Agent do
|
|
108
145
|
expect(subject).to receive(:with_local_tunnel).with(cred, 0)
|
109
146
|
.and_yield(socat_helper)
|
110
147
|
|
111
|
-
|
112
|
-
.with('Creating foo tunnel to foobar...', :green)
|
148
|
+
subject.send('db:tunnel', handle)
|
113
149
|
|
114
150
|
local_url = 'postgresql://aptible:password@localhost.aptible.in:4242/db'
|
115
|
-
expect(subject).to receive(:say)
|
116
|
-
.with("Connect at #{local_url}", :green)
|
117
151
|
|
118
|
-
|
119
|
-
|
120
|
-
expect(
|
121
|
-
|
152
|
+
expect(captured_logs)
|
153
|
+
.to match(/creating foo tunnel to foobar/i)
|
154
|
+
expect(captured_logs)
|
155
|
+
.to match(/connect at #{Regexp.escape(local_url)}/i)
|
156
|
+
|
157
|
+
expect(captured_logs).to match(/host: localhost\.aptible\.in/i)
|
158
|
+
expect(captured_logs).to match(/port: 4242/i)
|
159
|
+
expect(captured_logs).to match(/username: aptible/i)
|
160
|
+
expect(captured_logs).to match(/password: password/i)
|
161
|
+
expect(captured_logs).to match(/database: db/i)
|
122
162
|
end
|
123
163
|
|
124
164
|
it 'defaults to a default credential' do
|
@@ -126,14 +166,12 @@ describe Aptible::CLI::Agent do
|
|
126
166
|
Fabricate(:database_credential, database: database, type: 'foo')
|
127
167
|
Fabricate(:database_credential, database: database, type: 'bar')
|
128
168
|
|
129
|
-
messages = []
|
130
|
-
allow(subject).to receive(:say) { |m, *| messages << m }
|
131
169
|
expect(subject).to receive(:with_local_tunnel).with(ok, 0)
|
132
170
|
|
133
171
|
subject.send('db:tunnel', handle)
|
134
172
|
|
135
|
-
expect(
|
136
|
-
expect(
|
173
|
+
expect(captured_logs).to match(/use --type type/i)
|
174
|
+
expect(captured_logs).to match(/valid types.*foo.*bar/i)
|
137
175
|
end
|
138
176
|
|
139
177
|
it 'supports --type' do
|
@@ -143,7 +181,6 @@ describe Aptible::CLI::Agent do
|
|
143
181
|
ok = Fabricate(:database_credential, type: 'foo', database: database)
|
144
182
|
Fabricate(:database_credential, type: 'bar', database: database)
|
145
183
|
|
146
|
-
allow(subject).to receive(:say)
|
147
184
|
expect(subject).to receive(:with_local_tunnel).with(ok, 0)
|
148
185
|
subject.send('db:tunnel', handle)
|
149
186
|
end
|
@@ -174,7 +211,6 @@ describe Aptible::CLI::Agent do
|
|
174
211
|
context 'v1 stack' do
|
175
212
|
before do
|
176
213
|
allow(database.account.stack).to receive(:version) { 'v1' }
|
177
|
-
allow(subject).to receive(:say)
|
178
214
|
end
|
179
215
|
|
180
216
|
it 'falls back to the database itself if no type is given' do
|
@@ -199,13 +235,11 @@ describe Aptible::CLI::Agent do
|
|
199
235
|
end
|
200
236
|
|
201
237
|
it 'does not suggest other types that do not exist' do
|
202
|
-
messages = []
|
203
|
-
allow(subject).to receive(:say) { |m, *| messages << m }
|
204
238
|
expect(subject).to receive(:with_local_tunnel).with(database, 0)
|
205
239
|
|
206
240
|
subject.send('db:tunnel', handle)
|
207
241
|
|
208
|
-
expect(
|
242
|
+
expect(captured_logs).not_to match(/use --type type/i)
|
209
243
|
end
|
210
244
|
end
|
211
245
|
end
|
@@ -216,9 +250,14 @@ describe Aptible::CLI::Agent do
|
|
216
250
|
staging = Fabricate(:account, handle: 'staging')
|
217
251
|
prod = Fabricate(:account, handle: 'production')
|
218
252
|
|
219
|
-
[
|
220
|
-
|
221
|
-
|
253
|
+
[
|
254
|
+
[staging, 'staging-redis-db'],
|
255
|
+
[staging, 'staging-postgres-db'],
|
256
|
+
[prod, 'prod-elsearch-db'],
|
257
|
+
[prod, 'prod-postgres-db']
|
258
|
+
].each do |a, h|
|
259
|
+
d = Fabricate(:database, account: a, handle: h)
|
260
|
+
Fabricate(:database_credential, database: d)
|
222
261
|
end
|
223
262
|
|
224
263
|
token = 'the-token'
|
@@ -229,45 +268,38 @@ describe Aptible::CLI::Agent do
|
|
229
268
|
|
230
269
|
context 'when no account is specified' do
|
231
270
|
it 'prints out the grouped database handles for all accounts' do
|
232
|
-
allow(subject).to receive(:say)
|
233
|
-
|
234
271
|
subject.send('db:list')
|
235
272
|
|
236
|
-
expect(
|
237
|
-
expect(
|
238
|
-
expect(
|
273
|
+
expect(captured_output_text).to include('=== staging')
|
274
|
+
expect(captured_output_text).to include('staging-redis-db')
|
275
|
+
expect(captured_output_text).to include('staging-postgres-db')
|
239
276
|
|
240
|
-
expect(
|
241
|
-
expect(
|
242
|
-
expect(
|
277
|
+
expect(captured_output_text).to include('=== production')
|
278
|
+
expect(captured_output_text).to include('prod-elsearch-db')
|
279
|
+
expect(captured_output_text).to include('prod-postgres-db')
|
243
280
|
end
|
244
281
|
end
|
245
282
|
|
246
283
|
context 'when a valid account is specified' do
|
247
284
|
it 'prints out the database handles for the account' do
|
248
|
-
allow(subject).to receive(:say)
|
249
|
-
|
250
285
|
subject.options = { environment: 'staging' }
|
251
286
|
subject.send('db:list')
|
252
287
|
|
253
|
-
expect(
|
254
|
-
expect(
|
255
|
-
expect(
|
288
|
+
expect(captured_output_text).to include('=== staging')
|
289
|
+
expect(captured_output_text).to include('staging-redis-db')
|
290
|
+
expect(captured_output_text).to include('staging-postgres-db')
|
256
291
|
|
257
|
-
expect(
|
258
|
-
expect(
|
259
|
-
expect(
|
292
|
+
expect(captured_output_text).not_to include('=== production')
|
293
|
+
expect(captured_output_text).not_to include('prod-elsearch-db')
|
294
|
+
expect(captured_output_text).not_to include('prod-postgres-db')
|
260
295
|
end
|
261
296
|
end
|
262
297
|
|
263
298
|
context 'when an invalid account is specified' do
|
264
299
|
it 'prints out an error' do
|
265
|
-
allow(subject).to receive(:say)
|
266
|
-
|
267
300
|
subject.options = { environment: 'foo' }
|
268
|
-
expect { subject.send('db:list') }
|
269
|
-
'Specified account does not exist'
|
270
|
-
)
|
301
|
+
expect { subject.send('db:list') }
|
302
|
+
.to raise_error('Specified account does not exist')
|
271
303
|
end
|
272
304
|
end
|
273
305
|
end
|
@@ -281,10 +313,11 @@ describe Aptible::CLI::Agent do
|
|
281
313
|
it 'allows creating a new backup' do
|
282
314
|
expect(database).to receive(:create_operation!)
|
283
315
|
.with(type: 'backup').and_return(op)
|
284
|
-
expect(subject).to receive(:say).with('Backing up foobar...')
|
285
316
|
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
286
317
|
|
287
318
|
subject.send('db:backup', handle)
|
319
|
+
|
320
|
+
expect(captured_logs).to match(/backing up foobar/i)
|
288
321
|
end
|
289
322
|
|
290
323
|
it 'fails if the DB is not found' do
|
@@ -302,10 +335,11 @@ describe Aptible::CLI::Agent do
|
|
302
335
|
it 'allows reloading a database' do
|
303
336
|
expect(database).to receive(:create_operation!)
|
304
337
|
.with(type: 'reload').and_return(op)
|
305
|
-
expect(subject).to receive(:say).with('Reloading foobar...')
|
306
338
|
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
307
339
|
|
308
340
|
subject.send('db:reload', handle)
|
341
|
+
|
342
|
+
expect(captured_logs).to match(/reloading foobar/i)
|
309
343
|
end
|
310
344
|
|
311
345
|
it 'fails if the DB is not found' do
|
@@ -324,32 +358,35 @@ describe Aptible::CLI::Agent do
|
|
324
358
|
expect(database).to receive(:create_operation!)
|
325
359
|
.with(type: 'restart').and_return(op)
|
326
360
|
|
327
|
-
expect(subject).to receive(:say).with('Restarting foobar...')
|
328
361
|
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
329
362
|
|
330
363
|
subject.send('db:restart', handle)
|
364
|
+
|
365
|
+
expect(captured_logs).to match(/restarting foobar/i)
|
331
366
|
end
|
332
367
|
|
333
368
|
it 'allows restarting a database with a container size' do
|
334
369
|
expect(database).to receive(:create_operation!)
|
335
370
|
.with(type: 'restart', container_size: 40).and_return(op)
|
336
371
|
|
337
|
-
expect(subject).to receive(:say).with('Restarting foobar...')
|
338
372
|
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
339
373
|
|
340
374
|
subject.options = { container_size: 40 }
|
341
375
|
subject.send('db:restart', handle)
|
376
|
+
|
377
|
+
expect(captured_logs).to match(/restarting foobar/i)
|
342
378
|
end
|
343
379
|
|
344
380
|
it 'allows restarting a database with a disk size' do
|
345
381
|
expect(database).to receive(:create_operation!)
|
346
382
|
.with(type: 'restart', disk_size: 40).and_return(op)
|
347
383
|
|
348
|
-
expect(subject).to receive(:say).with('Restarting foobar...')
|
349
384
|
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
350
385
|
|
351
386
|
subject.options = { size: 40 }
|
352
387
|
subject.send('db:restart', handle)
|
388
|
+
|
389
|
+
expect(captured_logs).to match(/restarting foobar/i)
|
353
390
|
end
|
354
391
|
|
355
392
|
it 'fails if the DB is not found' do
|
@@ -369,13 +406,12 @@ describe Aptible::CLI::Agent do
|
|
369
406
|
|
370
407
|
context 'valid database' do
|
371
408
|
it 'returns the URL of a specified DB' do
|
372
|
-
cred = Fabricate(
|
373
|
-
|
374
|
-
|
375
|
-
expect(subject).to receive(:say).with(cred.connection_url)
|
409
|
+
cred = Fabricate(
|
410
|
+
:database_credential, default: true, type: 'foo', database: database
|
411
|
+
)
|
376
412
|
expect(database).not_to receive(:connection_url)
|
377
|
-
|
378
413
|
subject.send('db:url', handle)
|
414
|
+
expect(captured_output_text.chomp).to eq(cred.connection_url)
|
379
415
|
end
|
380
416
|
|
381
417
|
it 'fails if multiple DBs are found' do
|
@@ -388,19 +424,75 @@ describe Aptible::CLI::Agent do
|
|
388
424
|
context 'v1 stack' do
|
389
425
|
before do
|
390
426
|
allow(database.account.stack).to receive(:version) { 'v1' }
|
391
|
-
allow(subject).to receive(:say)
|
392
427
|
end
|
393
428
|
|
394
429
|
it 'returns the URL of a specified DB' do
|
395
430
|
connection_url = 'postgresql://aptible-v1:password@lega.cy:4242/db'
|
396
|
-
|
397
|
-
expect(subject).to receive(:say).with(connection_url)
|
398
431
|
expect(database).to receive(:connection_url)
|
399
432
|
.and_return(connection_url)
|
400
433
|
|
401
434
|
subject.send('db:url', handle)
|
435
|
+
|
436
|
+
expect(captured_output_text.chomp).to eq(connection_url)
|
402
437
|
end
|
403
438
|
end
|
404
439
|
end
|
405
440
|
end
|
441
|
+
|
442
|
+
describe '#db:deprovision' do
|
443
|
+
before { expect(Aptible::Api::Database).to receive(:all) { [database] } }
|
444
|
+
|
445
|
+
let(:operation) { Fabricate(:operation, resource: database) }
|
446
|
+
|
447
|
+
it 'deprovisions a database' do
|
448
|
+
expect(database).to receive(:create_operation!)
|
449
|
+
.with(type: 'deprovision').and_return(operation)
|
450
|
+
|
451
|
+
expect(subject).not_to receive(:attach_to_operation_logs)
|
452
|
+
|
453
|
+
subject.send('db:deprovision', handle)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
describe '#db:versions' do
|
458
|
+
let(:token) { double('token') }
|
459
|
+
|
460
|
+
before do
|
461
|
+
allow(subject).to receive(:save_token)
|
462
|
+
allow(subject).to receive(:fetch_token) { token }
|
463
|
+
end
|
464
|
+
|
465
|
+
let(:i1) do
|
466
|
+
Fabricate(:database_image, type: 'postgresql', version: '9.4')
|
467
|
+
end
|
468
|
+
|
469
|
+
let(:i2) do
|
470
|
+
Fabricate(:database_image, type: 'postgresql', version: '10')
|
471
|
+
end
|
472
|
+
|
473
|
+
let(:i3) do
|
474
|
+
Fabricate(:database_image, type: 'redis', version: '3.0')
|
475
|
+
end
|
476
|
+
|
477
|
+
before do
|
478
|
+
allow(Aptible::Api::DatabaseImage).to receive(:all)
|
479
|
+
.with(token: token).and_return([i1, i2, i3])
|
480
|
+
end
|
481
|
+
|
482
|
+
it 'lists grouped existing Database versions' do
|
483
|
+
subject.send('db:versions')
|
484
|
+
|
485
|
+
expected = [
|
486
|
+
'=== postgresql',
|
487
|
+
'9.4',
|
488
|
+
'10',
|
489
|
+
'',
|
490
|
+
'=== redis',
|
491
|
+
'3.0',
|
492
|
+
''
|
493
|
+
].join("\n")
|
494
|
+
|
495
|
+
expect(captured_output_text).to eq(expected)
|
496
|
+
end
|
497
|
+
end
|
406
498
|
end
|