aptible-cli 0.26.2 → 0.26.5
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -0
- data/Gemfile.lock +1 -1
- data/lib/aptible/cli/agent.rb +7 -4
- data/lib/aptible/cli/helpers/app.rb +29 -16
- data/lib/aptible/cli/helpers/database.rb +49 -32
- data/lib/aptible/cli/helpers/environment.rb +5 -4
- data/lib/aptible/cli/helpers/log_drain.rb +3 -1
- data/lib/aptible/cli/helpers/metric_drain.rb +3 -1
- data/lib/aptible/cli/resource_formatter.rb +14 -1
- data/lib/aptible/cli/subcommands/backup.rb +1 -1
- data/lib/aptible/cli/subcommands/config.rb +2 -2
- data/lib/aptible/cli/subcommands/db.rb +4 -3
- data/lib/aptible/cli/subcommands/log_drain.rb +2 -0
- data/lib/aptible/cli/subcommands/logs.rb +5 -5
- data/lib/aptible/cli/subcommands/metric_drain.rb +2 -0
- data/lib/aptible/cli/version.rb +1 -1
- data/lib/aptible/cli.rb +14 -0
- data/spec/aptible/cli/subcommands/apps_spec.rb +34 -21
- data/spec/aptible/cli/subcommands/backup_retention_policy_spec.rb +3 -1
- data/spec/aptible/cli/subcommands/backup_spec.rb +28 -3
- data/spec/aptible/cli/subcommands/config_spec.rb +11 -3
- data/spec/aptible/cli/subcommands/db_spec.rb +49 -95
- data/spec/aptible/cli/subcommands/deploy_spec.rb +8 -3
- data/spec/aptible/cli/subcommands/endpoints_spec.rb +20 -4
- data/spec/aptible/cli/subcommands/environment_spec.rb +4 -0
- data/spec/aptible/cli/subcommands/log_drain_spec.rb +15 -0
- data/spec/aptible/cli/subcommands/logs_spec.rb +16 -4
- data/spec/aptible/cli/subcommands/maintenance_spec.rb +7 -2
- data/spec/aptible/cli/subcommands/metric_drain_spec.rb +14 -2
- data/spec/aptible/cli/subcommands/services_spec.rb +3 -4
- data/spec/fabricators/account_fabricator.rb +9 -1
- data/spec/fabricators/app_external_aws_rds_connection_fabricator.rb +1 -1
- data/spec/fabricators/app_fabricator.rb +1 -1
- data/spec/fabricators/backup_fabricator.rb +1 -1
- data/spec/fabricators/backup_retention_policy_fabricator.rb +1 -1
- data/spec/fabricators/certificate_fabricator.rb +1 -1
- data/spec/fabricators/configuration_fabricator.rb +1 -1
- data/spec/fabricators/database_credential_fabricator.rb +1 -1
- data/spec/fabricators/database_disk_fabricator.rb +1 -1
- data/spec/fabricators/database_fabricator.rb +10 -1
- data/spec/fabricators/database_image_fabricator.rb +1 -1
- data/spec/fabricators/external_aws_account_fabricator.rb +1 -1
- data/spec/fabricators/external_aws_database_credential_fabricator.rb +1 -1
- data/spec/fabricators/external_aws_resource_fabricator.rb +1 -1
- data/spec/fabricators/log_drain_fabricator.rb +1 -1
- data/spec/fabricators/maintenance_app_fabricator.rb +1 -1
- data/spec/fabricators/maintenance_database_fabricator.rb +1 -1
- data/spec/fabricators/metric_drain_fabricator.rb +15 -1
- data/spec/fabricators/operation_fabricator.rb +1 -1
- data/spec/fabricators/service_fabricator.rb +1 -1
- data/spec/fabricators/service_sizing_policy_fabricator.rb +1 -1
- data/spec/fabricators/stack_fabricator.rb +1 -1
- data/spec/fabricators/vhost_fabricator.rb +1 -1
- data/spec/spec_helper.rb +7 -0
- data/spec/support/stub_aptible_resource.rb +25 -0
- metadata +5 -2
|
@@ -20,7 +20,24 @@ describe Aptible::CLI::Agent do
|
|
|
20
20
|
|
|
21
21
|
before do
|
|
22
22
|
allow(subject).to receive(:fetch_token).and_return(token)
|
|
23
|
-
allow(Aptible::Api::Account).to receive(:
|
|
23
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
24
|
+
.with("/find/account?handle=#{account.handle}", token: token)
|
|
25
|
+
.and_return(account)
|
|
26
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
27
|
+
.with("/find/account?handle=#{alt_account.handle}", token: token)
|
|
28
|
+
.and_return(alt_account)
|
|
29
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
30
|
+
.with("/find/database?handle=#{default_handle}", token: token)
|
|
31
|
+
.and_return(database)
|
|
32
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
33
|
+
.with("/find/database?handle=#{default_handle}&environment=#{account.handle}", token: token)
|
|
34
|
+
.and_return(database)
|
|
35
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
36
|
+
.with("/find/database?handle=#{database.handle}", token: token)
|
|
37
|
+
.and_return(database)
|
|
38
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
39
|
+
.with("/find/database?handle=#{database.handle}&environment=#{account.handle}", token: token)
|
|
40
|
+
.and_return(database)
|
|
24
41
|
end
|
|
25
42
|
|
|
26
43
|
describe '#backup:restore' do
|
|
@@ -60,6 +77,11 @@ describe Aptible::CLI::Agent do
|
|
|
60
77
|
|
|
61
78
|
it 'accepts a handle' do
|
|
62
79
|
h = 'some-handle'
|
|
80
|
+
restored = Fabricate(:database, account: account, handle: h)
|
|
81
|
+
|
|
82
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
83
|
+
.with("/find/database?handle=#{h}&environment=#{account.handle}", token: token)
|
|
84
|
+
.and_return(database)
|
|
63
85
|
|
|
64
86
|
expect(backup).to receive(:create_operation!) do |options|
|
|
65
87
|
expect(options[:handle]).to eq(h)
|
|
@@ -70,7 +92,7 @@ describe Aptible::CLI::Agent do
|
|
|
70
92
|
end
|
|
71
93
|
|
|
72
94
|
expect(subject).to receive(:attach_to_operation_logs).with(op) do
|
|
73
|
-
|
|
95
|
+
restored
|
|
74
96
|
end
|
|
75
97
|
|
|
76
98
|
subject.options = { handle: h }
|
|
@@ -143,6 +165,9 @@ describe Aptible::CLI::Agent do
|
|
|
143
165
|
end
|
|
144
166
|
|
|
145
167
|
subject.options = { environment: 'alt' }
|
|
168
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
169
|
+
.with("/find/database?handle=#{default_handle}&environment=alt", token: token)
|
|
170
|
+
.and_return(database)
|
|
146
171
|
subject.send('backup:restore', 1)
|
|
147
172
|
end
|
|
148
173
|
end
|
|
@@ -150,7 +175,6 @@ describe Aptible::CLI::Agent do
|
|
|
150
175
|
|
|
151
176
|
describe '#backup:list' do
|
|
152
177
|
before { allow(Aptible::Api::Account).to receive(:all) { [account] } }
|
|
153
|
-
before { allow(Aptible::Api::Database).to receive(:all) { [database] } }
|
|
154
178
|
|
|
155
179
|
before do
|
|
156
180
|
m = allow(database).to receive(:each_backup)
|
|
@@ -192,6 +216,7 @@ describe Aptible::CLI::Agent do
|
|
|
192
216
|
end
|
|
193
217
|
|
|
194
218
|
it 'fails if the DB is not found' do
|
|
219
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
195
220
|
expect { subject.send('backup:list', 'nope') }
|
|
196
221
|
.to raise_error(Thor::Error, 'Could not find database nope')
|
|
197
222
|
end
|
|
@@ -8,15 +8,18 @@ describe Aptible::CLI::Agent do
|
|
|
8
8
|
before { allow(subject).to receive(:fetch_token).and_return(token) }
|
|
9
9
|
|
|
10
10
|
before do
|
|
11
|
-
allow(Aptible::Api::App).to receive(:
|
|
12
|
-
.with(token: token
|
|
13
|
-
.and_return(
|
|
11
|
+
allow(Aptible::Api::App).to receive(:find_by_url)
|
|
12
|
+
.with("/find/app?handle=#{app.handle}", token: token)
|
|
13
|
+
.and_return(app)
|
|
14
14
|
allow(Aptible::Api::Account).to receive(:all)
|
|
15
15
|
.with(token: token, href: '/apps?per_page=5000&no_embed=true')
|
|
16
16
|
.and_return([account])
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
before { allow(subject).to receive(:options) { { app: app.handle } } }
|
|
20
|
+
before do
|
|
21
|
+
allow(subject).to receive(:current_configuration, &:current_configuration)
|
|
22
|
+
end
|
|
20
23
|
let(:operation) { Fabricate(:operation, resource: app) }
|
|
21
24
|
|
|
22
25
|
describe '#config' do
|
|
@@ -60,6 +63,11 @@ describe Aptible::CLI::Agent do
|
|
|
60
63
|
end
|
|
61
64
|
|
|
62
65
|
describe '#config:get' do
|
|
66
|
+
it 'shows nothing for an unconfigured app' do
|
|
67
|
+
subject.send('config:get', 'FOO')
|
|
68
|
+
expect(captured_output_text).to eq('')
|
|
69
|
+
end
|
|
70
|
+
|
|
63
71
|
it 'should show single environment variable specified' do
|
|
64
72
|
app.current_configuration = Fabricate(
|
|
65
73
|
:configuration, app: app, env: { 'FOO' => 'BAR', 'QUX' => 'two words' }
|
|
@@ -10,11 +10,20 @@ describe Aptible::CLI::Agent do
|
|
|
10
10
|
allow(subject).to receive(:ask)
|
|
11
11
|
allow(subject).to receive(:save_token)
|
|
12
12
|
allow(subject).to receive(:fetch_token) { token }
|
|
13
|
+
allow(Aptible::Api::DatabaseCredential).to receive(:all) do
|
|
14
|
+
database.database_credentials
|
|
15
|
+
end
|
|
16
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
17
|
+
.with("/find/database?handle=#{handle}", token: token)
|
|
18
|
+
.and_return(database)
|
|
19
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
20
|
+
.with("/find/database?handle=#{handle}&environment=#{account.handle}", token: token)
|
|
21
|
+
.and_return(database)
|
|
13
22
|
end
|
|
14
23
|
|
|
15
24
|
let(:handle) { 'foobar' }
|
|
16
25
|
let(:stack) { Fabricate(:stack, internal_domain: 'aptible.in') }
|
|
17
|
-
let(:account) { Fabricate(:account, stack: stack) }
|
|
26
|
+
let(:account) { Fabricate(:account, stack: stack, handle: 'aptible') }
|
|
18
27
|
let(:database) { Fabricate(:database, handle: handle, account: account) }
|
|
19
28
|
let(:socat_helper) { SocatHelperMock.new(port: 4242) }
|
|
20
29
|
|
|
@@ -148,15 +157,15 @@ describe Aptible::CLI::Agent do
|
|
|
148
157
|
|
|
149
158
|
describe '#db:tunnel' do
|
|
150
159
|
it 'should fail if database is non-existent' do
|
|
151
|
-
allow(Aptible::Api::Database).to receive(:
|
|
160
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
161
|
+
.with("/find/database?handle=#{handle}", token: token)
|
|
162
|
+
.and_return(nil)
|
|
152
163
|
expect do
|
|
153
164
|
subject.send('db:tunnel', handle)
|
|
154
165
|
end.to raise_error("Could not find database #{handle}")
|
|
155
166
|
end
|
|
156
167
|
|
|
157
168
|
context 'valid database' do
|
|
158
|
-
before { allow(Aptible::Api::Database).to receive(:all) { [database] } }
|
|
159
|
-
|
|
160
169
|
it 'prints a message explaining how to connect' do
|
|
161
170
|
cred = Fabricate(:database_credential, default: true, type: 'foo',
|
|
162
171
|
database: database)
|
|
@@ -226,41 +235,6 @@ describe Aptible::CLI::Agent do
|
|
|
226
235
|
expect { subject.send('db:tunnel', handle) }
|
|
227
236
|
.to raise_error(/foobar is not provisioned/im)
|
|
228
237
|
end
|
|
229
|
-
|
|
230
|
-
context 'v1 stack' do
|
|
231
|
-
before do
|
|
232
|
-
allow(database.account.stack).to receive(:version) { 'v1' }
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
it 'falls back to the database itself if no type is given' do
|
|
236
|
-
expect(subject).to receive(:with_local_tunnel).with(database, 0)
|
|
237
|
-
subject.send('db:tunnel', handle)
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
it 'falls back to the database itself if type matches' do
|
|
241
|
-
subject.options = { type: 'bar' }
|
|
242
|
-
allow(database).to receive(:type) { 'bar' }
|
|
243
|
-
|
|
244
|
-
expect(subject).to receive(:with_local_tunnel).with(database, 0)
|
|
245
|
-
subject.send('db:tunnel', handle)
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
it 'does not fall back to the database itself if type mismatches' do
|
|
249
|
-
subject.options = { type: 'bar' }
|
|
250
|
-
allow(database).to receive(:type) { 'foo' }
|
|
251
|
-
|
|
252
|
-
expect { subject.send('db:tunnel', handle) }
|
|
253
|
-
.to raise_error(/no credential with type bar/im)
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
it 'does not suggest other types that do not exist' do
|
|
257
|
-
expect(subject).to receive(:with_local_tunnel).with(database, 0)
|
|
258
|
-
|
|
259
|
-
subject.send('db:tunnel', handle)
|
|
260
|
-
|
|
261
|
-
expect(captured_logs).not_to match(/use --type type/i)
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
238
|
end
|
|
265
239
|
end
|
|
266
240
|
|
|
@@ -403,6 +377,9 @@ describe Aptible::CLI::Agent do
|
|
|
403
377
|
allow(Aptible::Api::Account).to receive(:all)
|
|
404
378
|
.with(token: token, href: '/accounts?per_page=5000&no_embed=true')
|
|
405
379
|
.and_return([staging, prod])
|
|
380
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
381
|
+
.with("/find/account?handle=#{staging.handle}", token: token)
|
|
382
|
+
.and_return(staging)
|
|
406
383
|
allow(Aptible::Api::ExternalAwsResource).to receive(:all)
|
|
407
384
|
.with(token: token)
|
|
408
385
|
.and_return([])
|
|
@@ -438,6 +415,7 @@ describe Aptible::CLI::Agent do
|
|
|
438
415
|
end
|
|
439
416
|
|
|
440
417
|
context 'when an invalid account is specified' do
|
|
418
|
+
before { allow(Aptible::Api::Account).to receive(:find_by_url).and_return(nil) }
|
|
441
419
|
it 'prints out an error' do
|
|
442
420
|
subject.options = { environment: 'foo' }
|
|
443
421
|
expect { subject.send('db:list') }
|
|
@@ -576,6 +554,9 @@ describe Aptible::CLI::Agent do
|
|
|
576
554
|
allow(Aptible::Api::Account).to receive(:all)
|
|
577
555
|
.with(token: token, href: '/accounts?per_page=5000&no_embed=true')
|
|
578
556
|
.and_return([staging, prod])
|
|
557
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
558
|
+
.with("/find/account?handle=#{staging.handle}", token: token)
|
|
559
|
+
.and_return(staging)
|
|
579
560
|
allow(Aptible::Api::ExternalAwsResource).to receive(:all)
|
|
580
561
|
.with(token: token)
|
|
581
562
|
.and_return([staging_rds, prod_rds, unattached_rds])
|
|
@@ -659,7 +640,6 @@ describe Aptible::CLI::Agent do
|
|
|
659
640
|
|
|
660
641
|
describe '#db:backup' do
|
|
661
642
|
before { allow(Aptible::Api::Account).to receive(:all) { [account] } }
|
|
662
|
-
before { allow(Aptible::Api::Database).to receive(:all) { [database] } }
|
|
663
643
|
|
|
664
644
|
let(:op) { Fabricate(:operation) }
|
|
665
645
|
|
|
@@ -674,6 +654,7 @@ describe Aptible::CLI::Agent do
|
|
|
674
654
|
end
|
|
675
655
|
|
|
676
656
|
it 'fails if the DB is not found' do
|
|
657
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
677
658
|
expect { subject.send('db:backup', 'nope') }
|
|
678
659
|
.to raise_error(Thor::Error, 'Could not find database nope')
|
|
679
660
|
end
|
|
@@ -681,7 +662,6 @@ describe Aptible::CLI::Agent do
|
|
|
681
662
|
|
|
682
663
|
describe '#db:reload' do
|
|
683
664
|
before { allow(Aptible::Api::Account).to receive(:all) { [account] } }
|
|
684
|
-
before { allow(Aptible::Api::Database).to receive(:all) { [database] } }
|
|
685
665
|
|
|
686
666
|
let(:op) { Fabricate(:operation) }
|
|
687
667
|
|
|
@@ -696,6 +676,7 @@ describe Aptible::CLI::Agent do
|
|
|
696
676
|
end
|
|
697
677
|
|
|
698
678
|
it 'fails if the DB is not found' do
|
|
679
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
699
680
|
expect { subject.send('db:reload', 'nope') }
|
|
700
681
|
.to raise_error(Thor::Error, 'Could not find database nope')
|
|
701
682
|
end
|
|
@@ -703,7 +684,6 @@ describe Aptible::CLI::Agent do
|
|
|
703
684
|
|
|
704
685
|
describe '#db:restart' do
|
|
705
686
|
before { allow(Aptible::Api::Account).to receive(:all) { [account] } }
|
|
706
|
-
before { allow(Aptible::Api::Database).to receive(:all) { [database] } }
|
|
707
687
|
|
|
708
688
|
let(:op) { Fabricate(:operation) }
|
|
709
689
|
|
|
@@ -768,6 +748,7 @@ describe Aptible::CLI::Agent do
|
|
|
768
748
|
end
|
|
769
749
|
|
|
770
750
|
it 'fails if the DB is not found' do
|
|
751
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
771
752
|
expect { subject.send('db:restart', 'nope') }
|
|
772
753
|
.to raise_error(Thor::Error, 'Could not find database nope')
|
|
773
754
|
end
|
|
@@ -775,7 +756,6 @@ describe Aptible::CLI::Agent do
|
|
|
775
756
|
|
|
776
757
|
describe '#db:modify' do
|
|
777
758
|
before { allow(Aptible::Api::Account).to receive(:all) { [account] } }
|
|
778
|
-
before { allow(Aptible::Api::Database).to receive(:all) { [database] } }
|
|
779
759
|
|
|
780
760
|
let(:op) { Fabricate(:operation) }
|
|
781
761
|
|
|
@@ -815,16 +795,15 @@ describe Aptible::CLI::Agent do
|
|
|
815
795
|
end
|
|
816
796
|
|
|
817
797
|
it 'fails if the DB is not found' do
|
|
798
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
818
799
|
expect { subject.send('db:modify', 'nope') }
|
|
819
800
|
.to raise_error(Thor::Error, 'Could not find database nope')
|
|
820
801
|
end
|
|
821
802
|
end
|
|
822
803
|
|
|
823
804
|
describe '#db:url' do
|
|
824
|
-
let(:databases) { [database] }
|
|
825
|
-
before { expect(Aptible::Api::Database).to receive(:all) { databases } }
|
|
826
|
-
|
|
827
805
|
it 'fails if the DB is not found' do
|
|
806
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
828
807
|
expect { subject.send('db:url', 'nope') }
|
|
829
808
|
.to raise_error(Thor::Error, 'Could not find database nope')
|
|
830
809
|
end
|
|
@@ -840,41 +819,32 @@ describe Aptible::CLI::Agent do
|
|
|
840
819
|
end
|
|
841
820
|
|
|
842
821
|
it 'fails if multiple DBs are found' do
|
|
843
|
-
|
|
822
|
+
error = HyperResource::ClientError.new('multiple resources found')
|
|
823
|
+
allow(error).to receive(:body)
|
|
824
|
+
.and_return('error' => 'multiple_resources_found')
|
|
825
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
826
|
+
.with("/find/database?handle=#{handle}", token: token)
|
|
827
|
+
.and_raise(error)
|
|
844
828
|
|
|
845
829
|
expect { subject.send('db:url', handle) }
|
|
846
830
|
.to raise_error(/Multiple databases/)
|
|
847
831
|
end
|
|
848
|
-
|
|
849
|
-
context 'v1 stack' do
|
|
850
|
-
before do
|
|
851
|
-
allow(database.account.stack).to receive(:version) { 'v1' }
|
|
852
|
-
end
|
|
853
|
-
|
|
854
|
-
it 'returns the URL of a specified DB' do
|
|
855
|
-
connection_url = 'postgresql://aptible-v1:password@lega.cy:4242/db'
|
|
856
|
-
expect(database).to receive(:connection_url)
|
|
857
|
-
.and_return(connection_url)
|
|
858
|
-
|
|
859
|
-
subject.send('db:url', handle)
|
|
860
|
-
|
|
861
|
-
expect(captured_output_text.chomp).to eq(connection_url)
|
|
862
|
-
end
|
|
863
|
-
end
|
|
864
832
|
end
|
|
865
833
|
end
|
|
866
834
|
|
|
867
835
|
describe '#db:replicate' do
|
|
868
|
-
let(:
|
|
869
|
-
|
|
836
|
+
let(:master) { Fabricate(:database, handle: 'master') }
|
|
837
|
+
let(:replica) { Fabricate(:database, account: master.account, handle: 'replica') }
|
|
838
|
+
before do
|
|
839
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
840
|
+
.with("/find/database?handle=#{master.handle}", token: token)
|
|
841
|
+
.and_return(master)
|
|
842
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
843
|
+
.with("/find/database?handle=#{replica.handle}&environment=#{account.handle}", token: token)
|
|
844
|
+
.and_return(replica)
|
|
845
|
+
end
|
|
870
846
|
|
|
871
847
|
def expect_replicate_database(opts = {})
|
|
872
|
-
master = Fabricate(:database, handle: 'master')
|
|
873
|
-
databases << master
|
|
874
|
-
replica = Fabricate(:database,
|
|
875
|
-
account: master.account,
|
|
876
|
-
handle: 'replica')
|
|
877
|
-
|
|
878
848
|
op = Fabricate(:operation)
|
|
879
849
|
|
|
880
850
|
params = { type: 'replicate', handle: 'replica' }.merge(opts)
|
|
@@ -883,7 +853,6 @@ describe Aptible::CLI::Agent do
|
|
|
883
853
|
.with(**params).and_return(op)
|
|
884
854
|
|
|
885
855
|
expect(subject).to receive(:attach_to_operation_logs).with(op) do
|
|
886
|
-
databases << replica
|
|
887
856
|
replica
|
|
888
857
|
end
|
|
889
858
|
|
|
@@ -915,17 +884,12 @@ describe Aptible::CLI::Agent do
|
|
|
915
884
|
end
|
|
916
885
|
|
|
917
886
|
it 'fails if the DB is not found' do
|
|
887
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
918
888
|
expect { subject.send('db:replicate', 'nope', 'replica') }
|
|
919
889
|
.to raise_error(Thor::Error, 'Could not find database nope')
|
|
920
890
|
end
|
|
921
891
|
|
|
922
892
|
it 'allows logical replication of a database with --version set' do
|
|
923
|
-
master = Fabricate(:database, handle: 'master')
|
|
924
|
-
databases << master
|
|
925
|
-
replica = Fabricate(:database,
|
|
926
|
-
account: master.account,
|
|
927
|
-
handle: 'replica')
|
|
928
|
-
|
|
929
893
|
dbimg = Fabricate(:database_image,
|
|
930
894
|
type: 'postgresql',
|
|
931
895
|
version: 10,
|
|
@@ -942,7 +906,6 @@ describe Aptible::CLI::Agent do
|
|
|
942
906
|
.with(**params).and_return(op)
|
|
943
907
|
|
|
944
908
|
expect(subject).to receive(:attach_to_operation_logs).with(op) do
|
|
945
|
-
databases << replica
|
|
946
909
|
replica
|
|
947
910
|
end
|
|
948
911
|
|
|
@@ -962,9 +925,6 @@ describe Aptible::CLI::Agent do
|
|
|
962
925
|
end
|
|
963
926
|
|
|
964
927
|
it 'fails if logical replication requested without --version' do
|
|
965
|
-
master = Fabricate(:database, handle: 'master', type: 'postgresql')
|
|
966
|
-
databases << master
|
|
967
|
-
|
|
968
928
|
subject.options = { type: 'replicate', handle: 'replica', logical: true }
|
|
969
929
|
expect { subject.send('db:replicate', 'master', 'replica') }
|
|
970
930
|
.to raise_error(Thor::Error, '--version is required for logical ' \
|
|
@@ -972,9 +932,7 @@ describe Aptible::CLI::Agent do
|
|
|
972
932
|
end
|
|
973
933
|
|
|
974
934
|
it 'fails if logical replication requested for non-postgres db' do
|
|
975
|
-
master =
|
|
976
|
-
databases << master
|
|
977
|
-
|
|
935
|
+
master.type = 'mysql'
|
|
978
936
|
subject.options = { type: 'replicate', handle: 'replica',
|
|
979
937
|
logical: true, version: 10 }
|
|
980
938
|
expect { subject.send('db:replicate', 'master', 'replica') }
|
|
@@ -985,17 +943,13 @@ describe Aptible::CLI::Agent do
|
|
|
985
943
|
|
|
986
944
|
describe '#db:dump' do
|
|
987
945
|
it 'should fail if database is non-existent' do
|
|
988
|
-
allow(Aptible::Api::Database).to receive(:
|
|
946
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
989
947
|
expect do
|
|
990
948
|
subject.send('db:dump', handle)
|
|
991
949
|
end.to raise_error("Could not find database #{handle}")
|
|
992
950
|
end
|
|
993
951
|
|
|
994
952
|
context 'valid database' do
|
|
995
|
-
before do
|
|
996
|
-
allow(Aptible::Api::Database).to receive(:all) { [database] }
|
|
997
|
-
end
|
|
998
|
-
|
|
999
953
|
it 'exits with the same code as pg_dump' do
|
|
1000
954
|
exit_status = 123
|
|
1001
955
|
cred = Fabricate(:database_credential, default: true, type: 'foo',
|
|
@@ -1180,7 +1134,7 @@ describe Aptible::CLI::Agent do
|
|
|
1180
1134
|
describe '#db:execute' do
|
|
1181
1135
|
sql_path = 'file.sql'
|
|
1182
1136
|
it 'should fail if database is non-existent' do
|
|
1183
|
-
allow(Aptible::Api::Database).to receive(:
|
|
1137
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
1184
1138
|
expect do
|
|
1185
1139
|
subject.send('db:execute', handle, sql_path)
|
|
1186
1140
|
end.to raise_error("Could not find database #{handle}")
|
|
@@ -1188,7 +1142,6 @@ describe Aptible::CLI::Agent do
|
|
|
1188
1142
|
|
|
1189
1143
|
context 'valid database' do
|
|
1190
1144
|
before do
|
|
1191
|
-
allow(Aptible::Api::Database).to receive(:all) { [database] }
|
|
1192
1145
|
allow(subject).to receive(:`).with(/psql .*/) { `exit 0` }
|
|
1193
1146
|
end
|
|
1194
1147
|
|
|
@@ -1386,8 +1339,6 @@ describe Aptible::CLI::Agent do
|
|
|
1386
1339
|
end
|
|
1387
1340
|
|
|
1388
1341
|
describe '#db:deprovision' do
|
|
1389
|
-
before { expect(Aptible::Api::Database).to receive(:all) { [database] } }
|
|
1390
|
-
|
|
1391
1342
|
let(:operation) { Fabricate(:operation, resource: database) }
|
|
1392
1343
|
|
|
1393
1344
|
it 'deprovisions a database' do
|
|
@@ -1457,7 +1408,9 @@ describe Aptible::CLI::Agent do
|
|
|
1457
1408
|
before do
|
|
1458
1409
|
allow(subject).to receive(:options)
|
|
1459
1410
|
.and_return(environment: account.handle)
|
|
1460
|
-
allow(Aptible::Api::Account).to receive(:
|
|
1411
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
1412
|
+
.with("/find/account?handle=#{account.handle}", token: token)
|
|
1413
|
+
.and_return(account)
|
|
1461
1414
|
end
|
|
1462
1415
|
context 'with environment and db' do
|
|
1463
1416
|
it 'should rename properly' do
|
|
@@ -1470,6 +1423,7 @@ describe Aptible::CLI::Agent do
|
|
|
1470
1423
|
)
|
|
1471
1424
|
end
|
|
1472
1425
|
it 'should fail if db does not exist' do
|
|
1426
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
1473
1427
|
expect { subject.send('db:rename', 'foo2', 'foo3') }
|
|
1474
1428
|
.to raise_error(/Could not find database foo2/)
|
|
1475
1429
|
end
|
|
@@ -4,12 +4,17 @@ describe Aptible::CLI::Agent do
|
|
|
4
4
|
let!(:account) { Fabricate(:account, handle: 'foobar') }
|
|
5
5
|
let!(:app) { Fabricate(:app, handle: 'hello', account: account) }
|
|
6
6
|
let(:operation) { Fabricate(:operation) }
|
|
7
|
+
let(:token) { double 'token' }
|
|
7
8
|
|
|
8
9
|
describe '#deploy' do
|
|
9
10
|
before do
|
|
10
|
-
allow(Aptible::Api::App).to receive(:
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
allow(Aptible::Api::App).to receive(:find_by_url)
|
|
12
|
+
.with("/find/app?handle=#{app.handle}&environment=#{account.handle}", token: token)
|
|
13
|
+
.and_return(app)
|
|
14
|
+
allow(subject).to receive(:fetch_token) { token }
|
|
15
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
16
|
+
.with("/find/account?handle=#{account.handle}", token: token)
|
|
17
|
+
.and_return(account)
|
|
13
18
|
end
|
|
14
19
|
|
|
15
20
|
context 'with app' do
|
|
@@ -12,6 +12,9 @@ describe Aptible::CLI::Agent do
|
|
|
12
12
|
.to receive(:all)
|
|
13
13
|
.with(token: token, href: '/accounts?per_page=5000&no_embed=true')
|
|
14
14
|
.and_return([a1, a2])
|
|
15
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
16
|
+
.with("/find/account?handle=#{a2.handle}", token: token)
|
|
17
|
+
.and_return(a2)
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
def expect_create_certificate(account, options)
|
|
@@ -67,10 +70,12 @@ describe Aptible::CLI::Agent do
|
|
|
67
70
|
end
|
|
68
71
|
|
|
69
72
|
before do
|
|
70
|
-
allow(Aptible::Api::Database)
|
|
71
|
-
.
|
|
72
|
-
.
|
|
73
|
-
|
|
73
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
74
|
+
.with("/find/database?handle=#{incomplete.handle}", token: token)
|
|
75
|
+
.and_return(incomplete)
|
|
76
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
77
|
+
.with("/find/database?handle=#{db.handle}", token: token)
|
|
78
|
+
.and_return(db)
|
|
74
79
|
allow(db).to receive(:class).and_return(Aptible::Api::Database)
|
|
75
80
|
allow(incomplete).to receive(:class).and_return(Aptible::Api::Database)
|
|
76
81
|
stub_options
|
|
@@ -78,6 +83,7 @@ describe Aptible::CLI::Agent do
|
|
|
78
83
|
|
|
79
84
|
describe 'endpoints:database:create' do
|
|
80
85
|
it 'fails if the DB does not exist' do
|
|
86
|
+
allow(Aptible::Api::Database).to receive(:find_by_url).and_return(nil)
|
|
81
87
|
expect { subject.send('endpoints:database:create', 'some') }
|
|
82
88
|
.to raise_error(/could not find database some/im)
|
|
83
89
|
end
|
|
@@ -90,6 +96,9 @@ describe Aptible::CLI::Agent do
|
|
|
90
96
|
|
|
91
97
|
it 'fails if the DB is not in the account' do
|
|
92
98
|
stub_options(environment: 'bar')
|
|
99
|
+
expect(Aptible::Api::Database).to receive(:find_by_url)
|
|
100
|
+
.with("/find/database?handle=#{db.handle}&environment=bar", token: token)
|
|
101
|
+
.and_return(nil)
|
|
93
102
|
expect { subject.send('endpoints:database:create', 'mydb') }
|
|
94
103
|
.to raise_error(/could not find database mydb/im)
|
|
95
104
|
end
|
|
@@ -223,6 +232,13 @@ describe Aptible::CLI::Agent do
|
|
|
223
232
|
.to receive(:all)
|
|
224
233
|
.with(token: token, href: '/apps?per_page=5000&no_embed=true')
|
|
225
234
|
.and_return([app])
|
|
235
|
+
|
|
236
|
+
allow(Aptible::Api::App).to receive(:find_by_url)
|
|
237
|
+
.and_return(nil)
|
|
238
|
+
allow(Aptible::Api::App).to receive(:find_by_url)
|
|
239
|
+
.with("/find/app?handle=#{app.handle}", token: token)
|
|
240
|
+
.and_return(app)
|
|
241
|
+
|
|
226
242
|
allow(app).to receive(:class).and_return(Aptible::Api::App)
|
|
227
243
|
stub_options
|
|
228
244
|
end
|
|
@@ -16,6 +16,9 @@ describe Aptible::CLI::Agent do
|
|
|
16
16
|
.to receive(:all)
|
|
17
17
|
.with(token: token, href: '/accounts?per_page=5000&no_embed=true')
|
|
18
18
|
.and_return([a1, a2])
|
|
19
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
20
|
+
.with("/find/account?handle=#{a1.handle}", token: token)
|
|
21
|
+
.and_return(a1)
|
|
19
22
|
end
|
|
20
23
|
|
|
21
24
|
describe('#environment:list') do
|
|
@@ -123,6 +126,7 @@ describe Aptible::CLI::Agent do
|
|
|
123
126
|
)
|
|
124
127
|
end
|
|
125
128
|
it 'should fail if env does not exist' do
|
|
129
|
+
allow(Aptible::Api::Account).to receive(:find_by_url).and_return(nil)
|
|
126
130
|
expect { subject.send('environment:rename', 'foo1', 'foo2') }
|
|
127
131
|
.to raise_error(/Could not find environment foo1/)
|
|
128
132
|
end
|
|
@@ -14,9 +14,19 @@ describe Aptible::CLI::Agent do
|
|
|
14
14
|
.with(token: token, href: '/log_drains?per_page=5000')
|
|
15
15
|
.and_return([log_drain])
|
|
16
16
|
|
|
17
|
+
allow(Aptible::Api::LogDrain).to receive(:all)
|
|
18
|
+
.with(token: token, href: "/accounts/#{account.id}/log_drains")
|
|
19
|
+
.and_return([log_drain])
|
|
20
|
+
|
|
17
21
|
allow(Aptible::Api::Account).to receive(:all)
|
|
18
22
|
.with(token: token, href: '/accounts?per_page=5000&no_embed=true')
|
|
19
23
|
.and_return([account])
|
|
24
|
+
|
|
25
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
26
|
+
.with("/find/account?handle=#{account.handle}", token: token)
|
|
27
|
+
.and_return(account)
|
|
28
|
+
|
|
29
|
+
allow(account).to receive(:reload).and_return(account)
|
|
20
30
|
end
|
|
21
31
|
|
|
22
32
|
describe '#log_drain:list' do
|
|
@@ -81,6 +91,11 @@ describe Aptible::CLI::Agent do
|
|
|
81
91
|
|
|
82
92
|
context 'elasticsearch' do
|
|
83
93
|
let(:db) { Fabricate(:database, account: account, id: 5) }
|
|
94
|
+
before do
|
|
95
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
96
|
+
.with("/find/database?handle=#{db.handle}&environment=#{db.account.handle}", token: token)
|
|
97
|
+
.and_return(db)
|
|
98
|
+
end
|
|
84
99
|
|
|
85
100
|
it 'creates a new Elasticsearch log drain' do
|
|
86
101
|
opts = {
|
|
@@ -4,18 +4,23 @@ describe Aptible::CLI::Agent do
|
|
|
4
4
|
before do
|
|
5
5
|
allow(subject).to receive(:ask)
|
|
6
6
|
allow(subject).to receive(:save_token)
|
|
7
|
-
allow(subject).to receive(:fetch_token) {
|
|
7
|
+
allow(subject).to receive(:fetch_token) { token }
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
let(:token) { 'some token' }
|
|
10
11
|
let(:app) { Fabricate(:app, handle: 'foo') }
|
|
11
12
|
let(:database) { Fabricate(:database, handle: 'bar', status: 'provisioned') }
|
|
12
13
|
let(:service) { Fabricate(:service, app: app) }
|
|
13
14
|
|
|
14
15
|
describe '#logs' do
|
|
15
|
-
before
|
|
16
|
+
before do
|
|
17
|
+
allow(Aptible::Api::Account).to receive(:all) { [app.account] }
|
|
18
|
+
allow(Aptible::Api::App).to receive(:find_by_url)
|
|
19
|
+
.with("/find/app?handle=#{app.handle}", token: 'some token')
|
|
20
|
+
.and_return(app)
|
|
21
|
+
end
|
|
16
22
|
|
|
17
23
|
context 'App resource' do
|
|
18
|
-
before { allow(Aptible::Api::App).to receive(:all) { [app] } }
|
|
19
24
|
before { subject.options = { app: app.handle } }
|
|
20
25
|
|
|
21
26
|
it 'should fail if the app is unprovisioned' do
|
|
@@ -35,7 +40,14 @@ describe Aptible::CLI::Agent do
|
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
context 'Database resource' do
|
|
38
|
-
before
|
|
43
|
+
before do
|
|
44
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
45
|
+
.with("/find/database?handle=#{database.handle}&environment=#{database.account.handle}", token: token)
|
|
46
|
+
.and_return(database)
|
|
47
|
+
allow(Aptible::Api::Database).to receive(:find_by_url)
|
|
48
|
+
.with("/find/database?handle=#{database.handle}", token: token)
|
|
49
|
+
.and_return(database)
|
|
50
|
+
end
|
|
39
51
|
before { subject.options = { database: database.handle } }
|
|
40
52
|
|
|
41
53
|
it 'should fail if the database is unprovisioned' do
|
|
@@ -9,6 +9,9 @@ describe Aptible::CLI::Agent do
|
|
|
9
9
|
allow(subject).to receive(:ask)
|
|
10
10
|
allow(subject).to receive(:save_token)
|
|
11
11
|
allow(subject).to receive(:fetch_token) { token }
|
|
12
|
+
allow(Aptible::Api::Account).to receive(:find_by_url)
|
|
13
|
+
.with("/find/account?handle=#{staging.handle}", token: token)
|
|
14
|
+
.and_return(staging)
|
|
12
15
|
end
|
|
13
16
|
|
|
14
17
|
let(:handle) { 'foobar' }
|
|
@@ -52,7 +55,6 @@ describe Aptible::CLI::Agent do
|
|
|
52
55
|
|
|
53
56
|
describe '#maintenance:dbs' do
|
|
54
57
|
before do
|
|
55
|
-
token = 'the-token'
|
|
56
58
|
allow(subject).to receive(:fetch_token) { token }
|
|
57
59
|
allow(Aptible::Api::Account).to receive(:all)
|
|
58
60
|
.with(token: token, href: '/accounts?per_page=5000&no_embed=true')
|
|
@@ -112,6 +114,8 @@ describe Aptible::CLI::Agent do
|
|
|
112
114
|
end
|
|
113
115
|
|
|
114
116
|
context 'when an invalid account is specified' do
|
|
117
|
+
before { allow(Aptible::Api::Account).to receive(:find_by_url).and_return(nil) }
|
|
118
|
+
|
|
115
119
|
it 'prints out an error' do
|
|
116
120
|
subject.options = { environment: 'foo' }
|
|
117
121
|
expect { subject.send('maintenance:dbs') }
|
|
@@ -121,7 +125,6 @@ describe Aptible::CLI::Agent do
|
|
|
121
125
|
end
|
|
122
126
|
describe '#maintenance:apps' do
|
|
123
127
|
before do
|
|
124
|
-
token = 'the-token'
|
|
125
128
|
allow(subject).to receive(:fetch_token) { token }
|
|
126
129
|
allow(Aptible::Api::Account).to receive(:all)
|
|
127
130
|
.with(token: token, href: '/accounts?per_page=5000&no_embed=true')
|
|
@@ -180,6 +183,8 @@ describe Aptible::CLI::Agent do
|
|
|
180
183
|
end
|
|
181
184
|
|
|
182
185
|
context 'when an invalid account is specified' do
|
|
186
|
+
before { allow(Aptible::Api::Account).to receive(:find_by_url).and_return(nil) }
|
|
187
|
+
|
|
183
188
|
it 'prints out an error' do
|
|
184
189
|
subject.options = { environment: 'foo' }
|
|
185
190
|
expect { subject.send('maintenance:apps') }
|