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 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