aptible-cli 0.17.1 → 0.18.3
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/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
|