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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b10127dfc01ec4af08021f37da130738584bd5468298e7519ba4ec49b87d6dd
4
- data.tar.gz: 785eb00b9009419d7e952c344c642cb831fbd96c10d68b680b3bda68231d35f4
3
+ metadata.gz: 99e721103b6988c5c8e41d11935449de499b29db00513732c031098f29613f29
4
+ data.tar.gz: 19b4bc6ce3b14b759ef100eab8ca95f12809bb0fd41e5c36b709dfd224ab774b
5
5
  SHA512:
6
- metadata.gz: 749b640447638c67ff246dcf8f1fcff049248d08870d2012165b9c7694fd65038533cb365f03b734bac593f9a953ce7ba5e5ce074ef4165ce2132961e9baecea
7
- data.tar.gz: 4ebfa45ebe3cfebbaa8abd6306414539c4e32dee645f7146b93ba081fe61c2b8a8aba5a5e540cc607a7d8b7fcb65bee04b4700ddd2698fe211458103fc1ec9bc
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] # Restart a database
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
@@ -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 ENV['HOME'], '.aptible', 'nag_toolbelt'
214
+ nag_file = File.join aptible_config_path, 'nag_toolbelt'
213
215
  nag_frequency = 12.hours
214
216
 
215
217
  last_nag = begin
@@ -0,0 +1,11 @@
1
+ module Aptible
2
+ module CLI
3
+ module Helpers
4
+ module ConfigPath
5
+ def aptible_config_path
6
+ ENV['APTIBLE_CONFIG_PATH'] || (File.join ENV['HOME'], '.aptible')
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -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 ENV['HOME'], '.aptible', 'ssh'
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 ENV['HOME'], '.aptible', 'tokens.json'
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
- node.value('git_ref', operation.git_ref)
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
- node.value('disk_type', database.disk.ebs_volume_type)
98
- node.value('disk_size', database.disk.size)
99
- node.value('container_size', \
100
- database.service.container_memory_limit_mb)
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
@@ -1,5 +1,5 @@
1
1
  module Aptible
2
2
  module CLI
3
- VERSION = '0.17.1'.freeze
3
+ VERSION = '0.18.3'.freeze
4
4
  end
5
5
  end
@@ -27,6 +27,7 @@ describe Aptible::CLI::ResourceFormatter do
27
27
  'Id: 12',
28
28
  'Hostname: foo.io',
29
29
  'Status: provisioned',
30
+ "Created At: #{fmt_time(service.created_at)}",
30
31
  'Type: https',
31
32
  'Port: default',
32
33
  'Internal: false',
@@ -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') })
@@ -26,4 +26,5 @@ Fabricator(:account, from: :stub_account) do
26
26
  apps { [] }
27
27
  databases { [] }
28
28
  certificates { [] }
29
+ created_at { Time.now }
29
30
  end
@@ -29,6 +29,7 @@ Fabricator(:app, from: :stub_app) do
29
29
  configurations { [] }
30
30
  current_configuration { nil }
31
31
  errors { Aptible::Resource::Errors.new }
32
+ created_at { Time.now }
32
33
 
33
34
  after_create { |app| app.account.apps << app }
34
35
  end
@@ -3,5 +3,6 @@ end
3
3
 
4
4
  Fabricator(:database_disk, from: :stub_database_disk) do
5
5
  size 100
6
- ebs_volume_type { 'gb2' }
6
+ ebs_volume_type { 'gp2' }
7
+ baseline_iops '300'
7
8
  end
@@ -22,6 +22,7 @@ Fabricator(:database, from: :stub_database) do
22
22
 
23
23
  backups { [] }
24
24
  database_credentials { [] }
25
+ created_at { Time.now }
25
26
 
26
27
  after_create do |database, transients|
27
28
  database.account.databases << database
@@ -14,6 +14,7 @@ Fabricator(:service, from: :stub_service) do
14
14
  container_count { 1 }
15
15
  container_memory_limit_mb { 512 }
16
16
  vhosts { [] }
17
+ created_at { Time.now }
17
18
 
18
19
  after_create do |service, transients|
19
20
  if transients[:app]
@@ -7,6 +7,7 @@ Fabricator(:vhost, from: :stub_vhost) do
7
7
  virtual_domain { Fabricate.sequence(:virtual_domain) { |i| "domain#{i}" } }
8
8
  ip_whitelist { [] }
9
9
  container_ports { [] }
10
+ created_at { Time.now }
10
11
 
11
12
  after_create { |vhost| vhost.service.vhosts << vhost }
12
13
  end
data/spec/spec_helper.rb CHANGED
@@ -11,6 +11,10 @@ end
11
11
  # Require library up front
12
12
  require 'aptible/cli'
13
13
 
14
+ def fmt_time(time)
15
+ time.strftime('%Y-%m-%d %H:%M:%S %z')
16
+ end
17
+
14
18
  class SpecRenderer < Aptible::CLI::Renderer::Base
15
19
  def initialize
16
20
  @nodes = []
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.17.1
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-03-16 00:00:00.000000000 Z
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