aptible-cli 0.6.9 → 0.7.0
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/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
|