aptible-cli 0.6.9 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +1 -1
- data/aptible-cli.gemspec +6 -3
- data/bin/aptible +3 -1
- data/codecov.yml +12 -0
- data/lib/aptible/cli/agent.rb +3 -0
- data/lib/aptible/cli/helpers/app.rb +98 -33
- data/lib/aptible/cli/helpers/database.rb +3 -3
- data/lib/aptible/cli/subcommands/apps.rb +4 -3
- data/lib/aptible/cli/subcommands/backup.rb +55 -0
- data/lib/aptible/cli/subcommands/config.rb +2 -2
- data/lib/aptible/cli/subcommands/db.rb +11 -2
- data/lib/aptible/cli/subcommands/rebuild.rb +1 -1
- data/lib/aptible/cli/subcommands/restart.rb +1 -1
- data/lib/aptible/cli/version.rb +1 -1
- data/spec/aptible/cli/helpers/git_remote_handle_strategy_spec.rb +54 -0
- data/spec/aptible/cli/helpers/{handle_from_git_remote.rb → handle_from_git_remote_spec.rb} +0 -0
- data/spec/aptible/cli/helpers/options_handle_strategy_spec.rb +14 -0
- data/spec/aptible/cli/helpers/tunnel_spec.rb +0 -1
- data/spec/aptible/cli/subcommands/apps_spec.rb +141 -54
- data/spec/aptible/cli/subcommands/backup_spec.rb +115 -0
- data/spec/aptible/cli/subcommands/db_spec.rb +35 -61
- data/spec/aptible/cli/subcommands/domains_spec.rb +21 -38
- data/spec/aptible/cli/subcommands/logs_spec.rb +12 -17
- data/spec/aptible/cli/subcommands/ps_spec.rb +5 -12
- data/spec/fabricators/account_fabricator.rb +10 -0
- data/spec/fabricators/app_fabricator.rb +14 -0
- data/spec/fabricators/backup_fabricator.rb +10 -0
- data/spec/fabricators/database_fabricator.rb +15 -0
- data/spec/fabricators/operation_fabricator.rb +6 -0
- data/spec/fabricators/service_fabricator.rb +9 -0
- data/spec/fabricators/vhost_fabricator.rb +9 -0
- data/spec/spec_helper.rb +9 -1
- metadata +81 -17
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Aptible::CLI::Helpers::App::OptionsHandleStrategy do
|
4
|
+
it 'is usable when app is set' do
|
5
|
+
s = described_class.new(app: 'foo')
|
6
|
+
expect(s.usable?).to be_truthy
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'passes options through' do
|
10
|
+
s = described_class.new(app: 'foo', environment: 'bar')
|
11
|
+
expect(s.app_handle).to eq('foo')
|
12
|
+
expect(s.env_handle).to eq('bar')
|
13
|
+
end
|
14
|
+
end
|
@@ -1,16 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
def dummy_strategy_factory(app_handle, env_handle, usable,
|
2
|
+
options_receiver = [])
|
3
|
+
Class.new do
|
4
|
+
attr_reader :options
|
5
|
+
|
6
|
+
define_method(:initialize) { |options| options_receiver << options }
|
7
|
+
define_method(:app_handle) { app_handle }
|
8
|
+
define_method(:env_handle) { env_handle }
|
9
|
+
define_method(:usable?) { usable }
|
10
|
+
|
11
|
+
def explain
|
12
|
+
'(options from dummy)'
|
13
|
+
end
|
14
|
+
end
|
14
15
|
end
|
15
16
|
|
16
17
|
describe Aptible::CLI::Agent do
|
@@ -19,49 +20,40 @@ describe Aptible::CLI::Agent do
|
|
19
20
|
before { subject.stub(:fetch_token) { double 'token' } }
|
20
21
|
before { subject.stub(:attach_to_operation_logs) }
|
21
22
|
|
22
|
-
let(:
|
23
|
-
let(:
|
24
|
-
let(:
|
25
|
-
|
26
|
-
dumptruck_port: 1234,
|
27
|
-
handle: 'aptible')
|
28
|
-
end
|
29
|
-
let(:services) { [service] }
|
30
|
-
let(:apps) do
|
31
|
-
[App.new(handle: 'hello', services: services, account: account)]
|
32
|
-
end
|
23
|
+
let!(:account) { Fabricate(:account) }
|
24
|
+
let!(:app) { Fabricate(:app, handle: 'hello', account: account) }
|
25
|
+
let!(:service) { Fabricate(:service, app: app) }
|
26
|
+
let(:op) { Fabricate(:operation, status: 'succeeded', resource: app) }
|
33
27
|
|
34
28
|
describe '#apps:scale' do
|
29
|
+
before do
|
30
|
+
allow(Aptible::Api::App).to receive(:all) { [app] }
|
31
|
+
allow(Aptible::Api::Account).to receive(:all) { [account] }
|
32
|
+
end
|
33
|
+
|
35
34
|
it 'should pass given correct parameters' do
|
36
|
-
allow(service).to receive(:create_operation) { op }
|
37
35
|
allow(subject).to receive(:options) do
|
38
36
|
{ app: 'hello', environment: 'foobar' }
|
39
37
|
end
|
40
|
-
|
41
|
-
allow(Aptible::Api::App).to receive(:all) { apps }
|
42
|
-
|
38
|
+
expect(service).to receive(:create_operation!) { op }
|
43
39
|
expect(subject).to receive(:environment_from_handle)
|
44
40
|
.with('foobar')
|
45
41
|
.and_return(account)
|
46
|
-
expect(subject).to receive(:apps_from_handle).and_return(
|
42
|
+
expect(subject).to receive(:apps_from_handle).and_return([app])
|
47
43
|
subject.send('apps:scale', 'web', 3)
|
48
44
|
end
|
49
45
|
|
50
46
|
it 'should pass container size param to operation if given' do
|
51
|
-
expect(service).to receive(:create_operation)
|
52
|
-
.with(type: 'scale', container_count: 3, container_size: 90210)
|
53
|
-
.and_return(op)
|
54
47
|
allow(subject).to receive(:options) do
|
55
48
|
{ app: 'hello', size: 90210, environment: 'foobar' }
|
56
49
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
50
|
+
expect(service).to receive(:create_operation!)
|
51
|
+
.with(type: 'scale', container_count: 3, container_size: 90210)
|
52
|
+
.and_return(op)
|
61
53
|
expect(subject).to receive(:environment_from_handle)
|
62
54
|
.with('foobar')
|
63
55
|
.and_return(account)
|
64
|
-
expect(subject).to receive(:apps_from_handle).and_return(
|
56
|
+
expect(subject).to receive(:apps_from_handle).and_return([app])
|
65
57
|
subject.send('apps:scale', 'web', 3)
|
66
58
|
end
|
67
59
|
|
@@ -69,9 +61,8 @@ describe Aptible::CLI::Agent do
|
|
69
61
|
allow(subject).to receive(:options) do
|
70
62
|
{ environment: 'foo', app: 'web' }
|
71
63
|
end
|
72
|
-
allow(service).to receive(:create_operation) { op }
|
73
64
|
allow(Aptible::Api::Account).to receive(:all) { [] }
|
74
|
-
allow(
|
65
|
+
allow(service).to receive(:create_operation!) { op }
|
75
66
|
|
76
67
|
expect do
|
77
68
|
subject.send('apps:scale', 'web', 3)
|
@@ -79,19 +70,14 @@ describe Aptible::CLI::Agent do
|
|
79
70
|
end
|
80
71
|
|
81
72
|
it 'should fail if app is non-existent' do
|
82
|
-
allow(service).to receive(:create_operation) { op }
|
83
|
-
allow(Aptible::Api::Account).to receive(:all) { [account] }
|
84
|
-
allow(account).to receive(:apps) { [] }
|
85
|
-
|
86
73
|
expect do
|
87
74
|
subject.send('apps:scale', 'web', 3)
|
88
75
|
end.to raise_error(Thor::Error)
|
89
76
|
end
|
90
77
|
|
91
78
|
it 'should fail if number is not a valid number' do
|
92
|
-
allow(service).to receive(:create_operation) { op }
|
93
79
|
allow(subject).to receive(:options) { { app: 'hello' } }
|
94
|
-
allow(
|
80
|
+
allow(service).to receive(:create_operation) { op }
|
95
81
|
|
96
82
|
expect do
|
97
83
|
subject.send('apps:scale', 'web', 'potato')
|
@@ -105,8 +91,7 @@ describe Aptible::CLI::Agent do
|
|
105
91
|
expect(subject).to receive(:environment_from_handle)
|
106
92
|
.with('foobar')
|
107
93
|
.and_return(account)
|
108
|
-
expect(subject).to receive(:apps_from_handle).and_return(
|
109
|
-
allow(Aptible::Api::App).to receive(:all) { apps }
|
94
|
+
expect(subject).to receive(:apps_from_handle).and_return([app])
|
110
95
|
|
111
96
|
expect do
|
112
97
|
subject.send('apps:scale', 'potato', 1)
|
@@ -114,18 +99,16 @@ describe Aptible::CLI::Agent do
|
|
114
99
|
end
|
115
100
|
|
116
101
|
context 'no service' do
|
117
|
-
|
102
|
+
before { app.services = [] }
|
118
103
|
|
119
104
|
it 'should fail if the app has no services' do
|
120
|
-
expect(subject).to receive(:environment_from_handle)
|
121
|
-
.with('foobar')
|
122
|
-
.and_return(account)
|
123
|
-
expect(subject).to receive(:apps_from_handle).and_return(apps)
|
124
105
|
allow(subject).to receive(:options) do
|
125
106
|
{ app: 'hello', environment: 'foobar' }
|
126
107
|
end
|
127
|
-
|
128
|
-
|
108
|
+
expect(subject).to receive(:environment_from_handle)
|
109
|
+
.with('foobar')
|
110
|
+
.and_return(account)
|
111
|
+
expect(subject).to receive(:apps_from_handle).and_return([app])
|
129
112
|
|
130
113
|
expect do
|
131
114
|
subject.send('apps:scale', 'web', 1)
|
@@ -133,4 +116,108 @@ describe Aptible::CLI::Agent do
|
|
133
116
|
end
|
134
117
|
end
|
135
118
|
end
|
119
|
+
|
120
|
+
describe '#ensure_app' do
|
121
|
+
it 'fails if no usable strategy is found' do
|
122
|
+
strategies = [dummy_strategy_factory(nil, nil, false)]
|
123
|
+
subject.stub(:handle_strategies) { strategies }
|
124
|
+
|
125
|
+
expect { subject.ensure_app }.to raise_error(/Could not find app/)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'fails if an environment is specified but not found' do
|
129
|
+
strategies = [dummy_strategy_factory('hello', 'aptible', true)]
|
130
|
+
subject.stub(:handle_strategies) { strategies }
|
131
|
+
|
132
|
+
expect(subject).to receive(:environment_from_handle).and_return(nil)
|
133
|
+
|
134
|
+
expect { subject.ensure_app }.to raise_error(/Could not find environment/)
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'with apps' do
|
138
|
+
let(:apps) { [app] }
|
139
|
+
|
140
|
+
before do
|
141
|
+
account.apps = apps
|
142
|
+
allow(Aptible::Api::App).to receive(:all).and_return(apps)
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'scopes the app search to an environment if provided' do
|
146
|
+
strategies = [dummy_strategy_factory('hello', 'aptible', true)]
|
147
|
+
subject.stub(:handle_strategies) { strategies }
|
148
|
+
|
149
|
+
expect(subject).to receive(:environment_from_handle).with('aptible')
|
150
|
+
.and_return(account)
|
151
|
+
|
152
|
+
expect(subject.ensure_app).to eq(apps.first)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'does not scope the app search to an environment if not provided' do
|
156
|
+
strategies = [dummy_strategy_factory('hello', nil, true)]
|
157
|
+
subject.stub(:handle_strategies) { strategies }
|
158
|
+
|
159
|
+
expect(subject.ensure_app).to eq(apps.first)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'fails if no app is found' do
|
163
|
+
apps.pop
|
164
|
+
|
165
|
+
strategies = [dummy_strategy_factory('hello', nil, true)]
|
166
|
+
subject.stub(:handle_strategies) { strategies }
|
167
|
+
|
168
|
+
expect { subject.ensure_app }.to raise_error(/not find app hello/)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'explains the strategy when it fails' do
|
172
|
+
apps.pop
|
173
|
+
|
174
|
+
strategies = [dummy_strategy_factory('hello', nil, true)]
|
175
|
+
subject.stub(:handle_strategies) { strategies }
|
176
|
+
|
177
|
+
expect { subject.ensure_app }.to raise_error(/from dummy/)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'indicates the environment when the app search was scoped' do
|
181
|
+
apps.pop
|
182
|
+
|
183
|
+
strategies = [dummy_strategy_factory('hello', 'aptible', true)]
|
184
|
+
subject.stub(:handle_strategies) { strategies }
|
185
|
+
|
186
|
+
expect(subject).to receive(:environment_from_handle).with('aptible')
|
187
|
+
.and_return(account)
|
188
|
+
|
189
|
+
expect { subject.ensure_app }.to raise_error(/in environment aptible/)
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'fails if multiple apps are found' do
|
193
|
+
apps << Fabricate(:app, handle: 'hello')
|
194
|
+
|
195
|
+
strategies = [dummy_strategy_factory('hello', nil, true)]
|
196
|
+
subject.stub(:handle_strategies) { strategies }
|
197
|
+
|
198
|
+
expect { subject.ensure_app }.to raise_error(/Multiple apps/)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'falls back to another strategy when the first one is unusable' do
|
202
|
+
strategies = [
|
203
|
+
dummy_strategy_factory('hello', nil, false),
|
204
|
+
dummy_strategy_factory('hello', nil, true)
|
205
|
+
]
|
206
|
+
subject.stub(:handle_strategies) { strategies }
|
207
|
+
|
208
|
+
expect(subject.ensure_app).to eq(apps.first)
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'passes options to the strategy' do
|
212
|
+
receiver = []
|
213
|
+
strategies = [dummy_strategy_factory('hello', nil, false, receiver)]
|
214
|
+
subject.stub(:handle_strategies) { strategies }
|
215
|
+
|
216
|
+
options = { app: 'foo', environment: 'bar' }
|
217
|
+
expect { subject.ensure_app options }.to raise_error(/not find app/)
|
218
|
+
|
219
|
+
expect(receiver).to eq([options])
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
136
223
|
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Aptible::CLI::Agent do
|
4
|
+
let(:token) { 'some-token' }
|
5
|
+
let(:account) { Fabricate(:account) }
|
6
|
+
let(:database) { Fabricate(:database, account: account, handle: 'some-db') }
|
7
|
+
let!(:backup) do
|
8
|
+
# created_at: 2016-06-14 13:24:11 +0000
|
9
|
+
Fabricate(:backup, database: database, created_at: Time.at(1465910651))
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:messages) { [] }
|
13
|
+
|
14
|
+
before do
|
15
|
+
allow(subject).to receive(:fetch_token).and_return(token)
|
16
|
+
allow(subject).to receive(:say) { |m| messages << m }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#backup:restore' do
|
20
|
+
it 'fails if the backup cannot be found' do
|
21
|
+
expect(Aptible::Api::Backup).to receive(:find).with(1, token: token)
|
22
|
+
.and_return(nil)
|
23
|
+
|
24
|
+
expect { subject.send('backup:restore', 1) }
|
25
|
+
.to raise_error('Backup #1 not found')
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'successful restore' do
|
29
|
+
let(:op) { Fabricate(:operation, resource: backup) }
|
30
|
+
|
31
|
+
before do
|
32
|
+
expect(Aptible::Api::Backup).to receive(:find).with(1, token: token)
|
33
|
+
.and_return(backup)
|
34
|
+
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'provides a default handle and no disk size' do
|
38
|
+
h = 'some-db-at-2016-06-14-13-24-11'
|
39
|
+
|
40
|
+
expect(backup).to receive(:create_operation!) do |options|
|
41
|
+
expect(options[:handle]).to eq(h)
|
42
|
+
expect(options[:disk_size]).not_to be_present
|
43
|
+
op
|
44
|
+
end
|
45
|
+
|
46
|
+
subject.send('backup:restore', 1)
|
47
|
+
expect(messages).to eq(["Restoring backup into #{h}"])
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'accepts a custom handle and disk size' do
|
51
|
+
h = 'some-handle'
|
52
|
+
s = 40
|
53
|
+
|
54
|
+
expect(backup).to receive(:create_operation!) do |options|
|
55
|
+
expect(options[:handle]).to eq(h)
|
56
|
+
expect(options[:disk_size]).to eq(s)
|
57
|
+
op
|
58
|
+
end
|
59
|
+
|
60
|
+
subject.options = { handle: h, size: s }
|
61
|
+
subject.send('backup:restore', 1)
|
62
|
+
expect(messages).to eq(["Restoring backup into #{h}"])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#backup:list' do
|
68
|
+
before { allow(Aptible::Api::Account).to receive(:all) { [account] } }
|
69
|
+
before { allow(Aptible::Api::Database).to receive(:all) { [database] } }
|
70
|
+
|
71
|
+
before do
|
72
|
+
m = allow(database).to receive(:each_backup)
|
73
|
+
|
74
|
+
[
|
75
|
+
1.day, 2.days, 3.days, 4.days,
|
76
|
+
5.days, 2.weeks, 3.weeks, 1.month,
|
77
|
+
1.year
|
78
|
+
].each do |age|
|
79
|
+
b = Fabricate(:backup, database: database, created_at: age.ago)
|
80
|
+
m.and_yield(b)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# The default value isn't set when we run sepcs
|
85
|
+
before { subject.options = { max_age: '1w' } }
|
86
|
+
|
87
|
+
it 'can show a subset of backups' do
|
88
|
+
subject.send('backup:list', database.handle)
|
89
|
+
expect(messages.size).to eq(5)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'allows scoping via environment' do
|
93
|
+
subject.options = { max_age: '1w', environment: database.account.handle }
|
94
|
+
subject.send('backup:list', database.handle)
|
95
|
+
expect(messages.size).to eq(5)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'shows more backups if requested' do
|
99
|
+
subject.options = { max_age: '2y' }
|
100
|
+
subject.send('backup:list', database.handle)
|
101
|
+
expect(messages.size).to eq(9)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'errors out if max_age is invalid' do
|
105
|
+
subject.options = { max_age: 'foobar' }
|
106
|
+
expect { subject.send('backup:list', database.handle) }
|
107
|
+
.to raise_error(Thor::Error, 'Invalid age: foobar')
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'fails if the DB is not found' do
|
111
|
+
expect { subject.send('backup:list', 'nope') }
|
112
|
+
.to raise_error(Thor::Error, 'Could not find database nope')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -1,12 +1,5 @@
|
|
1
|
-
require 'ostruct'
|
2
1
|
require 'spec_helper'
|
3
2
|
|
4
|
-
class Database < OpenStruct
|
5
|
-
end
|
6
|
-
|
7
|
-
class Account < OpenStruct
|
8
|
-
end
|
9
|
-
|
10
3
|
class SocatHelperMock < OpenStruct
|
11
4
|
end
|
12
5
|
|
@@ -15,33 +8,16 @@ describe Aptible::CLI::Agent do
|
|
15
8
|
before { subject.stub(:save_token) }
|
16
9
|
before { subject.stub(:fetch_token) { double 'token' } }
|
17
10
|
|
18
|
-
let(:
|
19
|
-
|
20
|
-
|
21
|
-
handle: 'aptible')
|
22
|
-
end
|
23
|
-
let(:database) do
|
24
|
-
Database.new(
|
25
|
-
type: 'postgresql',
|
26
|
-
handle: 'foobar',
|
27
|
-
passphrase: 'password',
|
28
|
-
connection_url: 'postgresql://aptible:password@10.252.1.125:49158/db',
|
29
|
-
account: account
|
30
|
-
)
|
31
|
-
end
|
32
|
-
|
33
|
-
let(:socat_helper) do
|
34
|
-
SocatHelperMock.new(
|
35
|
-
port: 4242
|
36
|
-
)
|
37
|
-
end
|
11
|
+
let(:handle) { 'foobar' }
|
12
|
+
let(:database) { Fabricate(:database, handle: handle) }
|
13
|
+
let(:socat_helper) { SocatHelperMock.new(port: 4242) }
|
38
14
|
|
39
15
|
describe '#db:tunnel' do
|
40
16
|
it 'should fail if database is non-existent' do
|
41
17
|
allow(Aptible::Api::Database).to receive(:all) { [] }
|
42
18
|
expect do
|
43
|
-
subject.send('db:tunnel',
|
44
|
-
end.to raise_error(
|
19
|
+
subject.send('db:tunnel', handle)
|
20
|
+
end.to raise_error("Could not find database #{handle}")
|
45
21
|
end
|
46
22
|
|
47
23
|
it 'should print a message about how to connect' do
|
@@ -55,14 +31,28 @@ describe Aptible::CLI::Agent do
|
|
55
31
|
|
56
32
|
# db:tunnel should also explain each component of the URL:
|
57
33
|
expect(subject).to receive(:say).exactly(7).times
|
58
|
-
subject.send('db:tunnel',
|
34
|
+
subject.send('db:tunnel', handle)
|
59
35
|
end
|
60
36
|
end
|
61
37
|
|
62
38
|
describe '#db:list' do
|
39
|
+
before do
|
40
|
+
staging = Fabricate(:account, handle: 'staging')
|
41
|
+
prod = Fabricate(:account, handle: 'production')
|
42
|
+
|
43
|
+
[[staging, 'staging-redis-db'], [staging, 'staging-postgres-db'],
|
44
|
+
[prod, 'prod-elsearch-db'], [prod, 'prod-postgres-db']].each do |a, h|
|
45
|
+
Fabricate(:database, account: a, handle: h)
|
46
|
+
end
|
47
|
+
|
48
|
+
token = 'the-token'
|
49
|
+
allow(subject).to receive(:fetch_token).and_return(token)
|
50
|
+
allow(Aptible::Api::Account).to receive(:all).with(token: token)
|
51
|
+
.and_return([staging, prod])
|
52
|
+
end
|
53
|
+
|
63
54
|
context 'when no account is specified' do
|
64
55
|
it 'prints out the grouped database handles for all accounts' do
|
65
|
-
setup_prod_and_staging_accounts
|
66
56
|
allow(subject).to receive(:say)
|
67
57
|
|
68
58
|
subject.send('db:list')
|
@@ -79,7 +69,6 @@ describe Aptible::CLI::Agent do
|
|
79
69
|
|
80
70
|
context 'when a valid account is specified' do
|
81
71
|
it 'prints out the database handles for the account' do
|
82
|
-
setup_prod_and_staging_accounts
|
83
72
|
allow(subject).to receive(:say)
|
84
73
|
|
85
74
|
subject.options = { environment: 'staging' }
|
@@ -97,7 +86,6 @@ describe Aptible::CLI::Agent do
|
|
97
86
|
|
98
87
|
context 'when an invalid account is specified' do
|
99
88
|
it 'prints out an error' do
|
100
|
-
setup_prod_and_staging_accounts
|
101
89
|
allow(subject).to receive(:say)
|
102
90
|
|
103
91
|
subject.options = { environment: 'foo' }
|
@@ -108,37 +96,23 @@ describe Aptible::CLI::Agent do
|
|
108
96
|
end
|
109
97
|
end
|
110
98
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
prod_elsearch = Database.new(handle: 'prod-elsearch-db')
|
115
|
-
prod_postgres = Database.new(handle: 'prod-postgres-db')
|
116
|
-
|
117
|
-
stub_local_token_with('the-token')
|
118
|
-
setup_new_accounts_with_dbs(
|
119
|
-
token: 'the-token',
|
120
|
-
account_db_mapping: {
|
121
|
-
'staging' => [staging_redis, staging_postgres],
|
122
|
-
'production' => [prod_elsearch, prod_postgres]
|
123
|
-
}
|
124
|
-
)
|
125
|
-
end
|
99
|
+
describe '#db:backup' do
|
100
|
+
before { allow(Aptible::Api::Account).to receive(:all) { [account] } }
|
101
|
+
before { allow(Aptible::Api::Database).to receive(:all) { [database] } }
|
126
102
|
|
127
|
-
|
128
|
-
token = options.fetch(:token)
|
129
|
-
account_db_mapping = options.fetch(:account_db_mapping)
|
103
|
+
let(:op) { Fabricate(:operation) }
|
130
104
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
end
|
105
|
+
it 'allows creating a new backup' do
|
106
|
+
expect(database).to receive(:create_operation!).and_return(op)
|
107
|
+
expect(subject).to receive(:say).with('Backing up foobar...')
|
108
|
+
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
136
109
|
|
137
|
-
|
138
|
-
|
139
|
-
end
|
110
|
+
subject.send('db:backup', handle)
|
111
|
+
end
|
140
112
|
|
141
|
-
|
142
|
-
|
113
|
+
it 'fails if the DB is not found' do
|
114
|
+
expect { subject.send('db:backup', 'nope') }
|
115
|
+
.to raise_error(Thor::Error, 'Could not find database nope')
|
116
|
+
end
|
143
117
|
end
|
144
118
|
end
|