aptible-cli 0.17.1 → 0.18.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/aptible/cli/agent.rb +3 -1
- data/lib/aptible/cli/helpers/config_path.rb +11 -0
- data/lib/aptible/cli/helpers/ssh.rb +5 -1
- data/lib/aptible/cli/helpers/token.rb +5 -1
- data/lib/aptible/cli/resource_formatter.rb +38 -6
- data/lib/aptible/cli/subcommands/db.rb +27 -2
- data/lib/aptible/cli/version.rb +1 -1
- data/spec/aptible/cli/resource_formatter_spec.rb +1 -0
- data/spec/aptible/cli/subcommands/apps_spec.rb +10 -4
- data/spec/aptible/cli/subcommands/db_spec.rb +72 -0
- data/spec/aptible/cli/subcommands/environment_spec.rb +4 -2
- data/spec/fabricators/account_fabricator.rb +1 -0
- data/spec/fabricators/app_fabricator.rb +1 -0
- data/spec/fabricators/database_disk_fabricator.rb +2 -1
- data/spec/fabricators/database_fabricator.rb +1 -0
- data/spec/fabricators/service_fabricator.rb +1 -0
- data/spec/fabricators/vhost_fabricator.rb +1 -0
- data/spec/spec_helper.rb +4 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99e721103b6988c5c8e41d11935449de499b29db00513732c031098f29613f29
|
4
|
+
data.tar.gz: 19b4bc6ce3b14b759ef100eab8ca95f12809bb0fd41e5c36b709dfd224ab774b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c5e417a9ab05f619e140ff6c444bdd9723aa6d9b5063678201e018873a8065f245074ba872fc0fd00763a54e9f7c156e67762118bdcb156893f8a9668aab8b6
|
7
|
+
data.tar.gz: 9355ca55bb61608245dfd0c8a1a7463ac555ab365cf389f12bec78b293861ab43f8776aef2c3c5fe8f0a0b42e3730f59ea3025d03c84ffc46d048c7b6933e90c
|
data/README.md
CHANGED
@@ -48,9 +48,10 @@ Commands:
|
|
48
48
|
aptible db:dump HANDLE [pg_dump options] # Dump a remote database to file
|
49
49
|
aptible db:execute HANDLE SQL_FILE [--on-error-stop] # Executes sql against a database
|
50
50
|
aptible db:list # List all databases
|
51
|
+
aptible db:modify HANDLE [--iops IOPS] [--volume-type [gp2, gp3]] # Modify a database disk
|
51
52
|
aptible db:reload HANDLE # Reload a database
|
52
53
|
aptible db:replicate HANDLE REPLICA_HANDLE [--container-size SIZE_MB] [--disk-size SIZE_GB] [--logical --version VERSION] [--key-arn KEY_ARN] # Create a replica/follower of a database
|
53
|
-
aptible db:restart HANDLE [--container-size SIZE_MB] [--disk-size SIZE_GB]
|
54
|
+
aptible db:restart HANDLE [--container-size SIZE_MB] [--disk-size SIZE_GB] [--iops IOPS] [--volume-type [gp2, gp3]] # Restart a database
|
54
55
|
aptible db:tunnel HANDLE # Create a local tunnel to a database
|
55
56
|
aptible db:url HANDLE # Display a database URL
|
56
57
|
aptible db:versions # List available database versions
|
data/lib/aptible/cli/agent.rb
CHANGED
@@ -18,6 +18,7 @@ require_relative 'helpers/vhost/option_set_builder'
|
|
18
18
|
require_relative 'helpers/tunnel'
|
19
19
|
require_relative 'helpers/system'
|
20
20
|
require_relative 'helpers/security_key'
|
21
|
+
require_relative 'helpers/config_path'
|
21
22
|
|
22
23
|
require_relative 'subcommands/apps'
|
23
24
|
require_relative 'subcommands/config'
|
@@ -43,6 +44,7 @@ module Aptible
|
|
43
44
|
include Helpers::Token
|
44
45
|
include Helpers::Ssh
|
45
46
|
include Helpers::System
|
47
|
+
include Helpers::ConfigPath
|
46
48
|
include Subcommands::Apps
|
47
49
|
include Subcommands::Config
|
48
50
|
include Subcommands::DB
|
@@ -209,7 +211,7 @@ module Aptible
|
|
209
211
|
# further: to do so, edit the file `.aptible/nag_toolbelt` and put a
|
210
212
|
# timestamp far into the future. For example, writing 1577836800 will
|
211
213
|
# disable the warning until 2020.
|
212
|
-
nag_file = File.join
|
214
|
+
nag_file = File.join aptible_config_path, 'nag_toolbelt'
|
213
215
|
nag_frequency = 12.hours
|
214
216
|
|
215
217
|
last_nag = begin
|
@@ -1,7 +1,11 @@
|
|
1
|
+
require_relative 'config_path'
|
2
|
+
|
1
3
|
module Aptible
|
2
4
|
module CLI
|
3
5
|
module Helpers
|
4
6
|
module Ssh
|
7
|
+
include Helpers::ConfigPath
|
8
|
+
|
5
9
|
def connect_to_ssh_portal(operation, *extra_ssh_args)
|
6
10
|
# NOTE: This is a little tricky to get rigt, so before you make any
|
7
11
|
# changes, read this.
|
@@ -126,7 +130,7 @@ module Aptible
|
|
126
130
|
end
|
127
131
|
|
128
132
|
def ssh_dir
|
129
|
-
File.join
|
133
|
+
File.join aptible_config_path, 'ssh'
|
130
134
|
end
|
131
135
|
|
132
136
|
def ssh_config_file
|
@@ -1,9 +1,13 @@
|
|
1
1
|
require 'aptible/auth'
|
2
2
|
|
3
|
+
require_relative 'config_path'
|
4
|
+
|
3
5
|
module Aptible
|
4
6
|
module CLI
|
5
7
|
module Helpers
|
6
8
|
module Token
|
9
|
+
include Helpers::ConfigPath
|
10
|
+
|
7
11
|
TOKEN_ENV_VAR = 'APTIBLE_ACCESS_TOKEN'.freeze
|
8
12
|
|
9
13
|
def fetch_token
|
@@ -40,7 +44,7 @@ module Aptible
|
|
40
44
|
end
|
41
45
|
|
42
46
|
def token_file
|
43
|
-
File.join
|
47
|
+
File.join(aptible_config_path, 'tokens.json').freeze
|
44
48
|
end
|
45
49
|
end
|
46
50
|
end
|
@@ -5,8 +5,17 @@ module Aptible
|
|
5
5
|
NO_NESTING = Object.new.freeze
|
6
6
|
|
7
7
|
def inject_backup(node, backup, include_db: false)
|
8
|
+
origin = if backup.manual && !backup.copied_from
|
9
|
+
"manual, #{backup.created_from_operation.user_email}"
|
10
|
+
elsif backup.manual && backup.copied_from
|
11
|
+
'manual, copy'
|
12
|
+
elsif backup.copied_from
|
13
|
+
'automatic, copy'
|
14
|
+
else
|
15
|
+
'automatic'
|
16
|
+
end
|
8
17
|
description = "#{backup.id}: #{backup.created_at}, " \
|
9
|
-
"#{backup.aws_region}"
|
18
|
+
"#{backup.aws_region}, #{origin}"
|
10
19
|
|
11
20
|
if include_db
|
12
21
|
db = backup.database_with_deleted
|
@@ -30,6 +39,13 @@ module Aptible
|
|
30
39
|
inject_backup(n, backup.copied_from)
|
31
40
|
end
|
32
41
|
end
|
42
|
+
|
43
|
+
if backup.created_from_operation && \
|
44
|
+
backup.manual && !backup.copied_from
|
45
|
+
node.keyed_object('created_from_operation', 'id') do |n|
|
46
|
+
inject_operation(n, backup.created_from_operation)
|
47
|
+
end
|
48
|
+
end
|
33
49
|
end
|
34
50
|
|
35
51
|
def inject_deleted_database(node, database, account)
|
@@ -43,12 +59,15 @@ module Aptible
|
|
43
59
|
def inject_account(node, account)
|
44
60
|
node.value('id', account.id)
|
45
61
|
node.value('handle', account.handle)
|
62
|
+
node.value('created_at', account.created_at)
|
46
63
|
end
|
47
64
|
|
48
65
|
def inject_operation(node, operation)
|
49
66
|
node.value('id', operation.id)
|
50
67
|
node.value('status', operation.status)
|
51
|
-
|
68
|
+
if %w(deploy rebuild).include?(operation.type)
|
69
|
+
node.value('git_ref', operation.git_ref)
|
70
|
+
end
|
52
71
|
node.value('user_email', operation.user_email)
|
53
72
|
node.value('created_at', operation.created_at)
|
54
73
|
end
|
@@ -56,6 +75,7 @@ module Aptible
|
|
56
75
|
def inject_app(node, app, account)
|
57
76
|
node.value('id', app.id)
|
58
77
|
node.value('handle', app.handle)
|
78
|
+
node.value('created_at', app.created_at)
|
59
79
|
|
60
80
|
node.value('status', app.status)
|
61
81
|
node.value('git_remote', app.git_repo)
|
@@ -80,6 +100,7 @@ module Aptible
|
|
80
100
|
def inject_database(node, database, account)
|
81
101
|
node.value('id', database.id)
|
82
102
|
node.value('handle', database.handle)
|
103
|
+
node.value('created_at', database.created_at)
|
83
104
|
|
84
105
|
node.value('type', database.type)
|
85
106
|
node.value('version', database.database_image.version)
|
@@ -94,10 +115,19 @@ module Aptible
|
|
94
115
|
end
|
95
116
|
attach_account(node, account)
|
96
117
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
118
|
+
if database.disk
|
119
|
+
node.value('disk_type', database.disk.ebs_volume_type)
|
120
|
+
node.value('disk_size', database.disk.size)
|
121
|
+
node.value('disk_modification_progress',
|
122
|
+
database.disk.modification_progress)
|
123
|
+
node.value('disk_modification_status', database.disk.status)
|
124
|
+
node.value('disk_provisioned_iops', database.disk.baseline_iops)
|
125
|
+
end
|
126
|
+
|
127
|
+
if database.service
|
128
|
+
node.value('container_size', \
|
129
|
+
database.service.container_memory_limit_mb)
|
130
|
+
end
|
101
131
|
end
|
102
132
|
|
103
133
|
def inject_credential(node, credential)
|
@@ -111,6 +141,7 @@ module Aptible
|
|
111
141
|
def inject_service(node, service, app)
|
112
142
|
node.value('id', service.id)
|
113
143
|
node.value('service', service.process_type)
|
144
|
+
node.value('created_at', service.created_at)
|
114
145
|
|
115
146
|
node.value('command', service.command || 'CMD')
|
116
147
|
node.value('container_count', service.container_count)
|
@@ -123,6 +154,7 @@ module Aptible
|
|
123
154
|
node.value('id', vhost.id)
|
124
155
|
node.value('hostname', vhost.external_host)
|
125
156
|
node.value('status', vhost.status)
|
157
|
+
node.value('created_at', vhost.created_at)
|
126
158
|
|
127
159
|
case vhost.type
|
128
160
|
when 'tcp', 'tls'
|
@@ -279,19 +279,24 @@ module Aptible
|
|
279
279
|
end
|
280
280
|
|
281
281
|
desc 'db:restart HANDLE ' \
|
282
|
-
'[--container-size SIZE_MB] [--disk-size SIZE_GB]'
|
282
|
+
'[--container-size SIZE_MB] [--disk-size SIZE_GB] ' \
|
283
|
+
'[--iops IOPS] [--volume-type [gp2, gp3]]',
|
283
284
|
'Restart a database'
|
284
285
|
option :environment
|
285
286
|
option :container_size, type: :numeric
|
286
287
|
option :disk_size, type: :numeric
|
287
288
|
option :size, type: :numeric
|
289
|
+
option :iops, type: :numeric
|
290
|
+
option :volume_type
|
288
291
|
define_method 'db:restart' do |handle|
|
289
292
|
database = ensure_database(options.merge(db: handle))
|
290
293
|
|
291
294
|
opts = {
|
292
295
|
type: 'restart',
|
293
296
|
container_size: options[:container_size],
|
294
|
-
disk_size: options[:disk_size] || options[:size]
|
297
|
+
disk_size: options[:disk_size] || options[:size],
|
298
|
+
provisioned_iops: options[:iops],
|
299
|
+
ebs_volume_type: options[:volume_type]
|
295
300
|
}.delete_if { |_, v| v.nil? }
|
296
301
|
|
297
302
|
CLI.logger.warn([
|
@@ -305,6 +310,26 @@ module Aptible
|
|
305
310
|
attach_to_operation_logs(op)
|
306
311
|
end
|
307
312
|
|
313
|
+
desc 'db:modify HANDLE ' \
|
314
|
+
'[--iops IOPS] [--volume-type [gp2, gp3]]',
|
315
|
+
'Modify a database disk'
|
316
|
+
option :environment
|
317
|
+
option :iops, type: :numeric
|
318
|
+
option :volume_type
|
319
|
+
define_method 'db:modify' do |handle|
|
320
|
+
database = ensure_database(options.merge(db: handle))
|
321
|
+
|
322
|
+
opts = {
|
323
|
+
type: 'modify',
|
324
|
+
provisioned_iops: options[:iops],
|
325
|
+
ebs_volume_type: options[:volume_type]
|
326
|
+
}.delete_if { |_, v| v.nil? }
|
327
|
+
|
328
|
+
CLI.logger.info "Modifying #{database.handle}..."
|
329
|
+
op = database.create_operation!(opts)
|
330
|
+
attach_to_operation_logs(op)
|
331
|
+
end
|
332
|
+
|
308
333
|
desc 'db:url HANDLE', 'Display a database URL'
|
309
334
|
option :environment
|
310
335
|
option :type, type: :string
|
data/lib/aptible/cli/version.rb
CHANGED
@@ -104,26 +104,30 @@ describe Aptible::CLI::Agent do
|
|
104
104
|
{
|
105
105
|
'environment' => {
|
106
106
|
'id' => account.id,
|
107
|
-
'handle' => account.handle
|
107
|
+
'handle' => account.handle,
|
108
|
+
'created_at' => fmt_time(account.created_at)
|
108
109
|
},
|
109
110
|
'handle' => app.handle,
|
110
111
|
'id' => app.id,
|
111
112
|
'status' => app.status,
|
112
113
|
'git_remote' => app.git_repo,
|
114
|
+
'created_at' => fmt_time(app.created_at),
|
113
115
|
'services' => [
|
114
116
|
{
|
115
117
|
'service' => s1.process_type,
|
116
118
|
'id' => s1.id,
|
117
119
|
'command' => s1.command,
|
118
120
|
'container_count' => s1.container_count,
|
119
|
-
'container_size' => s1.container_memory_limit_mb
|
121
|
+
'container_size' => s1.container_memory_limit_mb,
|
122
|
+
'created_at' => fmt_time(s1.created_at)
|
120
123
|
},
|
121
124
|
{
|
122
125
|
'service' => s2.process_type,
|
123
126
|
'id' => s2.id,
|
124
127
|
'command' => 'CMD',
|
125
128
|
'container_count' => s2.container_count,
|
126
|
-
'container_size' => s2.container_memory_limit_mb
|
129
|
+
'container_size' => s2.container_memory_limit_mb,
|
130
|
+
'created_at' => fmt_time(s2.created_at)
|
127
131
|
}
|
128
132
|
]
|
129
133
|
}
|
@@ -145,12 +149,14 @@ describe Aptible::CLI::Agent do
|
|
145
149
|
{
|
146
150
|
'environment' => {
|
147
151
|
'id' => account.id,
|
148
|
-
'handle' => account.handle
|
152
|
+
'handle' => account.handle,
|
153
|
+
'created_at' => fmt_time(account.created_at)
|
149
154
|
},
|
150
155
|
'handle' => app.handle,
|
151
156
|
'id' => app.id,
|
152
157
|
'status' => app.status,
|
153
158
|
'git_remote' => app.git_repo,
|
159
|
+
'created_at' => fmt_time(app.created_at),
|
154
160
|
'last_deploy_operation' =>
|
155
161
|
{
|
156
162
|
'id' => op.id,
|
@@ -389,6 +389,31 @@ describe Aptible::CLI::Agent do
|
|
389
389
|
expect(captured_logs).to match(/restarting foobar/i)
|
390
390
|
end
|
391
391
|
|
392
|
+
it 'allows restarting a database with provisioned iops' do
|
393
|
+
expect(database).to receive(:create_operation!)
|
394
|
+
.with(type: 'restart', provisioned_iops: 3001)
|
395
|
+
.and_return(op)
|
396
|
+
|
397
|
+
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
398
|
+
|
399
|
+
subject.options = { iops: 3001 }
|
400
|
+
subject.send('db:restart', handle)
|
401
|
+
|
402
|
+
expect(captured_logs).to match(/restarting foobar/i)
|
403
|
+
end
|
404
|
+
|
405
|
+
it 'allows restarting a database with ebs volume type' do
|
406
|
+
expect(database).to receive(:create_operation!)
|
407
|
+
.with(type: 'restart', ebs_volume_type: 'gp2').and_return(op)
|
408
|
+
|
409
|
+
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
410
|
+
|
411
|
+
subject.options = { volume_type: 'gp2' }
|
412
|
+
subject.send('db:restart', handle)
|
413
|
+
|
414
|
+
expect(captured_logs).to match(/restarting foobar/i)
|
415
|
+
end
|
416
|
+
|
392
417
|
it 'allows restarting a database with (implicitly disk) size' do
|
393
418
|
expect(database).to receive(:create_operation!)
|
394
419
|
.with(type: 'restart', disk_size: 40).and_return(op)
|
@@ -419,6 +444,53 @@ describe Aptible::CLI::Agent do
|
|
419
444
|
end
|
420
445
|
end
|
421
446
|
|
447
|
+
describe '#db:modify' do
|
448
|
+
before { allow(Aptible::Api::Account).to receive(:all) { [account] } }
|
449
|
+
before { allow(Aptible::Api::Database).to receive(:all) { [database] } }
|
450
|
+
|
451
|
+
let(:op) { Fabricate(:operation) }
|
452
|
+
|
453
|
+
it 'allows modifying a database' do
|
454
|
+
expect(database).to receive(:create_operation!)
|
455
|
+
.with(type: 'modify').and_return(op)
|
456
|
+
|
457
|
+
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
458
|
+
|
459
|
+
subject.send('db:modify', handle)
|
460
|
+
|
461
|
+
expect(captured_logs).to match(/modifying foobar/i)
|
462
|
+
end
|
463
|
+
|
464
|
+
it 'allows modifying a database with provisioned iops' do
|
465
|
+
expect(database).to receive(:create_operation!)
|
466
|
+
.with(type: 'modify', provisioned_iops: 3001).and_return(op)
|
467
|
+
|
468
|
+
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
469
|
+
|
470
|
+
subject.options = { iops: 3001 }
|
471
|
+
subject.send('db:modify', handle)
|
472
|
+
|
473
|
+
expect(captured_logs).to match(/modifying foobar/i)
|
474
|
+
end
|
475
|
+
|
476
|
+
it 'allows modifying a database with ebs volume type' do
|
477
|
+
expect(database).to receive(:create_operation!)
|
478
|
+
.with(type: 'modify', ebs_volume_type: 'gp2').and_return(op)
|
479
|
+
|
480
|
+
expect(subject).to receive(:attach_to_operation_logs).with(op)
|
481
|
+
|
482
|
+
subject.options = { volume_type: 'gp2' }
|
483
|
+
subject.send('db:modify', handle)
|
484
|
+
|
485
|
+
expect(captured_logs).to match(/modifying foobar/i)
|
486
|
+
end
|
487
|
+
|
488
|
+
it 'fails if the DB is not found' do
|
489
|
+
expect { subject.send('db:modify', 'nope') }
|
490
|
+
.to raise_error(Thor::Error, 'Could not find database nope')
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
422
494
|
describe '#db:url' do
|
423
495
|
let(:databases) { [database] }
|
424
496
|
before { expect(Aptible::Api::Database).to receive(:all) { databases } }
|
@@ -32,11 +32,13 @@ describe Aptible::CLI::Agent do
|
|
32
32
|
expected_accounts = [
|
33
33
|
{
|
34
34
|
'handle' => 'foo',
|
35
|
-
'ca_body' => 'account 1 cert'
|
35
|
+
'ca_body' => 'account 1 cert',
|
36
|
+
'created_at' => fmt_time(a1.created_at)
|
36
37
|
},
|
37
38
|
{
|
38
39
|
'handle' => 'bar',
|
39
|
-
'ca_body' => '--account 2 cert--'
|
40
|
+
'ca_body' => '--account 2 cert--',
|
41
|
+
'created_at' => fmt_time(a2.created_at)
|
40
42
|
}
|
41
43
|
]
|
42
44
|
expect(captured_output_json.map! { |account| account.except('id') })
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aptible-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Frank Macreery
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aptible-resource
|
@@ -274,6 +274,7 @@ files:
|
|
274
274
|
- lib/aptible/cli/formatter/value.rb
|
275
275
|
- lib/aptible/cli/helpers/app.rb
|
276
276
|
- lib/aptible/cli/helpers/app_or_database.rb
|
277
|
+
- lib/aptible/cli/helpers/config_path.rb
|
277
278
|
- lib/aptible/cli/helpers/database.rb
|
278
279
|
- lib/aptible/cli/helpers/environment.rb
|
279
280
|
- lib/aptible/cli/helpers/operation.rb
|