aptible-cli 0.24.4 → 0.24.6

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: 2b52a3b2e10513aea9042d2aaa69ce9b224b07ab6eb19bf510a2cad0839d402c
4
- data.tar.gz: 441fe200c9ea43e7b0abebfcab263f940fa3cfb6a381e9432b5f98c2ea603bd6
3
+ metadata.gz: c377cdde67c48c466c298fefd1963e10acc35aa48eb195b0f55017cc5a70bd19
4
+ data.tar.gz: '0559b0079810eccc17d7ba47f111d6042020d37b03a84e08f1f448925e94a6e6'
5
5
  SHA512:
6
- metadata.gz: 55b8a89a9708614233fc95df1cfc9ee27a6653d8f22f3a6781b03bc19d9f6661b32bb86843312a9e22866fc8caee55fa912a2ce473857e3592f3bd8214ef7e90
7
- data.tar.gz: 743783a9426bcd48c1efa2f367d50affdf8d67cac2d838698496ce44c29eb225f4e65577d1d220fed5a916c00b9cf3388806f258e562c45549c84c80ff26298b
6
+ metadata.gz: 9a9f45050a3f006bb9c205036dad348616596015245dd907bb20e83960c0f6c1447d4eb69636d064959248a418b772c188079699dd7f8b32983f027857717a98
7
+ data.tar.gz: 50af33f6fecc55556ca7df1c0e63cec1d44865b8c4e0cde57b05aa25740f78aed65ba0d9113b8d874de5539f78bdf86bb588f88a7f0683a4916d83b6872266e7
data/Gemfile.lock CHANGED
@@ -1,20 +1,27 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- aptible-cli (0.24.4)
4
+ aptible-cli (0.24.6)
5
5
  activesupport (>= 4.0, < 6.0)
6
- aptible-api (~> 1.6.5)
6
+ aptible-api (~> 1.8.0)
7
7
  aptible-auth (~> 1.2.5)
8
8
  aptible-billing (~> 1.0)
9
9
  aptible-resource (~> 1.1)
10
+ aws-eventstream (~> 1.1.1)
10
11
  aws-sdk (~> 2.0)
12
+ aws-sigv4 (~> 1.2.4)
11
13
  bigdecimal (~> 1.3.5)
12
14
  cbor
13
15
  chronic_duration (~> 0.10.6)
14
16
  concurrent-ruby (< 1.1.10)
15
- git (< 1.10)
17
+ connection_pool (< 2.2.4)
18
+ faraday (~> 0.17.6)
19
+ git (~> 1.7.0)
20
+ httpclient (~> 2.8.0)
21
+ json (~> 2.5.0)
16
22
  jwt (~> 2.3.0)
17
23
  rack (~> 1.0)
24
+ stripe (< 5.0)
18
25
  term-ansicolor (~> 1.8.0)
19
26
  thor (~> 0.20.0)
20
27
 
@@ -28,7 +35,7 @@ GEM
28
35
  tzinfo (~> 1.1)
29
36
  addressable (2.8.0)
30
37
  public_suffix (>= 2.0.2, < 5.0)
31
- aptible-api (1.6.5)
38
+ aptible-api (1.8.1)
32
39
  aptible-auth
33
40
  aptible-resource
34
41
  gem_config
@@ -42,7 +49,7 @@ GEM
42
49
  activesupport (>= 4.0, < 6.0)
43
50
  aptible-resource (~> 1.0)
44
51
  stripe (>= 1.13.0)
45
- aptible-resource (1.1.2)
52
+ aptible-resource (1.1.3)
46
53
  activesupport
47
54
  fridge
48
55
  gem_config (~> 0.3.1)
@@ -79,9 +86,9 @@ GEM
79
86
  fabrication (2.15.2)
80
87
  faraday (0.17.6)
81
88
  multipart-post (>= 1.2, < 3)
82
- fridge (0.2.2)
89
+ fridge (1.0.0)
83
90
  gem_config
84
- jwt
91
+ jwt (~> 2.3.0)
85
92
  gem_config (0.3.2)
86
93
  git (1.7.0)
87
94
  rchardet (~> 1.8)
@@ -147,7 +154,7 @@ GEM
147
154
  tins (~> 1.0)
148
155
  thor (0.20.3)
149
156
  thread_safe (0.3.6)
150
- tins (1.33.0)
157
+ tins (1.38.0)
151
158
  bigdecimal
152
159
  sync
153
160
  tzinfo (1.2.11)
data/README.md CHANGED
@@ -76,13 +76,13 @@ Commands:
76
76
  aptible environment:list # List all environments
77
77
  aptible environment:rename OLD_HANDLE NEW_HANDLE # Rename an environment handle. In order for the new environment handle to appear in log drain/metric destinations, you must restart the apps/databases in this environment.
78
78
  aptible help [COMMAND] # Describe available commands or one specific command
79
- aptible log_drain:create:datadog HANDLE --url DATADOG_URL --environment ENVIRONMENT [--drain-apps true/false] [--drain_databases true/false] [--drain_ephemeral_sessions true/false] [--drain_proxies true/false] # Create a Datadog Log Drain
80
- aptible log_drain:create:elasticsearch HANDLE --db DATABASE_HANDLE --environment ENVIRONMENT [--drain-apps true/false] [--drain_databases true/false] [--drain_ephemeral_sessions true/false] [--drain_proxies true/false] # Create an Elasticsearch Log Drain
81
- aptible log_drain:create:https HANDLE --url URL --environment ENVIRONMENT [--drain-apps true/false] [--drain_databases true/false] [--drain_ephemeral_sessions true/false] [--drain_proxies true/false] # Create a HTTPS Drain
82
- aptible log_drain:create:logdna HANDLE --url LOGDNA_URL --environment ENVIRONMENT [--drain-apps true/false] [--drain_databases true/false] [--drain_ephemeral_sessions true/false] [--drain_proxies true/false] # Create a LogDNA Log Drain
83
- aptible log_drain:create:papertrail HANDLE --host PAPERTRAIL_HOST --port PAPERTRAIL_PORT --environment ENVIRONMENT [--drain-apps true/false] [--drain_databases true/false] [--drain_ephemeral_sessions true/false] [--drain_proxies true/false] # Create a Papertrail Log Drain
84
- aptible log_drain:create:sumologic HANDLE --url SUMOLOGIC_URL --environment ENVIRONMENT [--drain-apps true/false] [--drain_databases true/false] [--drain_ephemeral_sessions true/false] [--drain_proxies true/false] # Create a Sumologic Drain
85
- aptible log_drain:create:syslog HANDLE --host SYSLOG_HOST --port SYSLOG_PORT [--token TOKEN] --environment ENVIRONMENT [--drain-apps true/false] [--drain_databases true/false] [--drain_ephemeral_sessions true/false] [--drain_proxies true/false] # Create a Papertrail Log Drain
79
+ aptible log_drain:create:datadog HANDLE --url DATADOG_URL --environment ENVIRONMENT [--drain-apps|--no-drain-apps] [--drain-databases|--no-drain-databases] [--drain-ephemeral-sessions|--no-drain-ephemeral-sessions] [--drain_proxies|--no-drain-proxies] # Create a Datadog Log Drain. By default, App, Database, Ephemeral Session, and Proxy logs will be sent to your chosen destination.
80
+ aptible log_drain:create:elasticsearch HANDLE --db DATABASE_HANDLE --environment ENVIRONMENT [--drain-apps|--no-drain-apps] [--drain-databases|--no-drain-databases] [--drain-ephemeral-sessions|--no-drain-ephemeral-sessions] [--drain_proxies|--no-drain-proxies] # Create an Elasticsearch Log Drain. By default, App, Database, Ephemeral Session, and Proxy logs will be sent to your chosen destination.
81
+ aptible log_drain:create:https HANDLE --url URL --environment ENVIRONMENT [--drain-apps|--no-drain-apps] [--drain-databases|--no-drain-databases] [--drain-ephemeral-sessions|--no-drain-ephemeral-sessions] [--drain_proxies|--no-drain-proxies] # Create a HTTPS Drain
82
+ aptible log_drain:create:logdna HANDLE --url LOGDNA_URL --environment ENVIRONMENT [--drain-apps|--no-drain-apps] [--drain-databases|--no-drain-databases] [--drain-ephemeral-sessions|--no-drain-ephemeral-sessions] [--drain_proxies|--no-drain-proxies] # Create a LogDNA/Mezmo Log Drain. By default, App, Database, Ephemeral Session, and Proxy logs will be sent to your chosen destination.
83
+ aptible log_drain:create:papertrail HANDLE --host PAPERTRAIL_HOST --port PAPERTRAIL_PORT --environment ENVIRONMENT [--drain-apps|--no-drain-apps] [--drain-databases|--no-drain-databases] [--drain-ephemeral-sessions|--no-drain-ephemeral-sessions] [--drain_proxies|--no-drain-proxies] # Create a Papertrail Log Drain. By default, App, Database, Ephemeral Session, and Proxy logs will be sent to your chosen destination.
84
+ aptible log_drain:create:sumologic HANDLE --url SUMOLOGIC_URL --environment ENVIRONMENT [--drain-apps|--no-drain-apps] [--drain-databases|--no-drain-databases] [--drain-ephemeral-sessions|--no-drain-ephemeral-sessions] [--drain_proxies|--no-drain-proxies] # Create a Sumologic Drain. By default, App, Database, Ephemeral Session, and Proxy logs will be sent to your chosen destination.
85
+ aptible log_drain:create:syslog HANDLE --host SYSLOG_HOST --port SYSLOG_PORT [--token TOKEN] --environment ENVIRONMENT [--drain-apps|--no-drain-apps] [--drain-databases|--no-drain-databases] [--drain-ephemeral-sessions|--no-drain-ephemeral-sessions] [--drain_proxies|--no-drain-proxies] # Create a Syslog Log Drain. By default, App, Database, Ephemeral Session, and Proxy logs will be sent to your chosen destination.
86
86
  aptible log_drain:deprovision HANDLE --environment ENVIRONMENT # Deprovisions a log drain
87
87
  aptible log_drain:list # List all Log Drains
88
88
  aptible login # Log in to Aptible
@@ -104,7 +104,7 @@ Commands:
104
104
  aptible services # List Services for an App
105
105
  aptible services:autoscaling_policy SERVICE # Returns the associated sizing policy, if any
106
106
  aptible services:autoscaling_policy:set SERVICE --autoscaling-type (horizontal|vertical) [--metric-lookback-seconds SECONDS] [--percentile PERCENTILE] [--post-scale-up-cooldown-seconds SECONDS] [--post-scale-down-cooldown-seconds SECONDS] [--post-release-cooldown-seconds SECONDS] [--mem-cpu-ratio-r-threshold RATIO] [--mem-cpu-ratio-c-threshold RATIO] [--mem-scale-up-threshold THRESHOLD] [--mem-scale-down-threshold THRESHOLD] [--minimum-memory MEMORY] [--maximum-memory MEMORY] [--min-cpu-threshold THRESHOLD] [--max-cpu-threshold THRESHOLD] [--min-containers CONTAINERS] [--max-containers CONTAINERS] [--scale-up-step STEPS] [--scale-down-step STEPS] # Sets the sizing (autoscaling) policy for a service. This is not incremental, all arguments must be sent at once or they will be set to defaults.
107
- aptible services:settings SERVICE [--force-zero-downtime|--no-force-zero-downtime] [--simple-health-check|--no-simple-health-check] # Modifies the zero-downtime deploy setting for a service
107
+ aptible services:settings SERVICE [--force-zero-downtime|--no-force-zero-downtime] [--simple-health-check|--no-simple-health-check] [--stop-timeout SECONDS] # Modifies the deployment settings for a service
108
108
  aptible ssh [COMMAND] # Run a command against an app
109
109
  aptible version # Print Aptible CLI version
110
110
  ```
data/aptible-cli.gemspec CHANGED
@@ -21,18 +21,25 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ['lib']
22
22
 
23
23
  spec.add_dependency 'activesupport', '>= 4.0', '< 6.0'
24
- spec.add_dependency 'aptible-api', '~> 1.6.5'
24
+ spec.add_dependency 'aptible-api', '~> 1.8.0'
25
25
  spec.add_dependency 'aptible-auth', '~> 1.2.5'
26
26
  spec.add_dependency 'aptible-billing', '~> 1.0'
27
27
  spec.add_dependency 'aptible-resource', '~> 1.1'
28
+ spec.add_dependency 'aws-eventstream', '~> 1.1.1'
28
29
  spec.add_dependency 'aws-sdk', '~> 2.0'
30
+ spec.add_dependency 'aws-sigv4', '~> 1.2.4'
29
31
  spec.add_dependency 'bigdecimal', '~> 1.3.5' # https://github.com/ruby/bigdecimal#which-version-should-you-select
30
32
  spec.add_dependency 'cbor'
31
33
  spec.add_dependency 'chronic_duration', '~> 0.10.6'
32
34
  spec.add_dependency 'concurrent-ruby', '< 1.1.10'
35
+ spec.add_dependency 'connection_pool', '< 2.2.4'
36
+ spec.add_dependency 'faraday', '~> 0.17.6'
37
+ spec.add_dependency 'git', '~> 1.7.0'
38
+ spec.add_dependency 'httpclient', '~> 2.8.0'
39
+ spec.add_dependency 'json', '~> 2.5.0'
33
40
  spec.add_dependency 'jwt', '~> 2.3.0'
34
- spec.add_dependency 'git', '< 1.10'
35
41
  spec.add_dependency 'rack', '~> 1.0'
42
+ spec.add_dependency 'stripe', '< 5.0'
36
43
  spec.add_dependency 'term-ansicolor', '~> 1.8.0'
37
44
  spec.add_dependency 'thor', '~> 0.20.0'
38
45
 
@@ -349,9 +349,30 @@ module Aptible
349
349
  "v#{Aptible::CLI::VERSION}"
350
350
  ]
351
351
  bits << 'toolbelt' if toolbelt?
352
+ bits << "(#{ci_string})" if ci?
352
353
  bits.join ' '
353
354
  end
354
355
 
356
+ def ci_string
357
+ if ENV['GITHUB_ACTIONS'] == 'true'
358
+ 'GitHub Actions'
359
+ elsif ENV['CIRCLECI'] == 'true'
360
+ 'CircleCI'
361
+ elsif ENV['TRAVIS'] == 'true'
362
+ 'Travis CI'
363
+ elsif ENV['GITLAB_CI'] == 'true'
364
+ 'GitLab CI'
365
+ elsif ENV['DRONE'] == 'true'
366
+ 'Harness'
367
+ else
368
+ 'CI'
369
+ end
370
+ end
371
+
372
+ def ci?
373
+ ENV['CI'] == 'true'
374
+ end
375
+
355
376
  def toolbelt?
356
377
  ENV['APTIBLE_TOOLBELT']
357
378
  end
@@ -33,8 +33,18 @@ module Aptible
33
33
  klass = resource.class
34
34
 
35
35
  if klass == Aptible::Api::App
36
+ # We could also raise the error here, but it would technically be a
37
+ # breaking change:we currently return an empty list if the App is
38
+ # not provisioned.
39
+ # if resource.services.empty?
40
+ # raise Thor::Error, 'App is not provisioned'
41
+ # end
36
42
  resource.each_service(&block)
37
43
  elsif klass == Aptible::Api::Database
44
+ if resource.service.nil?
45
+ raise Thor::Error, 'Database is not provisioned'
46
+ end
47
+
38
48
  [resource.service].each(&block)
39
49
  else
40
50
  raise "Unexpected resource: #{klass}"
@@ -67,10 +67,22 @@ module Aptible
67
67
  attach_account(node, account)
68
68
  end
69
69
 
70
- def inject_account(node, account)
70
+ def inject_account(node, account, include_stack = false)
71
71
  node.value('id', account.id)
72
72
  node.value('handle', account.handle)
73
73
  node.value('created_at', account.created_at)
74
+
75
+ if include_stack && account.stack
76
+ node.keyed_object('stack', 'name') do |n|
77
+ n.value('name', account.stack.name)
78
+ n.value('id', account.stack.id)
79
+ n.value('region', account.stack.region)
80
+ n.value(
81
+ 'outbound_ip_addresses',
82
+ account.stack.outbound_ip_addresses
83
+ )
84
+ end
85
+ end
74
86
  end
75
87
 
76
88
  def inject_operation(node, operation)
@@ -145,6 +157,8 @@ module Aptible
145
157
  if database.service
146
158
  node.value('container_size', \
147
159
  database.service.container_memory_limit_mb)
160
+ node.value('container_profile', \
161
+ database.service.instance_class.to_s[/[a-z]/])
148
162
  end
149
163
  end
150
164
 
@@ -309,10 +323,10 @@ module Aptible
309
323
 
310
324
  private
311
325
 
312
- def attach_account(node, account)
326
+ def attach_account(node, account, include_stack = false)
313
327
  return if NO_NESTING.eql?(account)
314
328
  node.keyed_object('environment', 'handle') do |n|
315
- inject_account(n, account)
329
+ inject_account(n, account, include_stack)
316
330
  end
317
331
  end
318
332
 
@@ -19,7 +19,7 @@ module Aptible
19
19
  ) do |node|
20
20
  scoped_environments(options).each do |account|
21
21
  node.object do |n|
22
- ResourceFormatter.inject_account(n, account)
22
+ ResourceFormatter.inject_account(n, account, true)
23
23
  end
24
24
  end
25
25
  end
@@ -10,10 +10,11 @@ module Aptible
10
10
  include Helpers::Telemetry
11
11
 
12
12
  drain_flags = '--environment ENVIRONMENT ' \
13
- '[--drain-apps true/false] ' \
14
- '[--drain_databases true/false] ' \
15
- '[--drain_ephemeral_sessions true/false] ' \
16
- '[--drain_proxies true/false]'
13
+ '[--drain-apps|--no-drain-apps] ' \
14
+ '[--drain-databases|--no-drain-databases] ' \
15
+ '[--drain-ephemeral-sessions|' \
16
+ +'--no-drain-ephemeral-sessions] ' \
17
+ '[--drain_proxies|--no-drain-proxies]'
17
18
 
18
19
  def self.drain_options
19
20
  option :drain_apps, default: true, type: :boolean
@@ -54,7 +55,9 @@ module Aptible
54
55
  desc 'log_drain:create:elasticsearch HANDLE '\
55
56
  '--db DATABASE_HANDLE ' \
56
57
  + drain_flags,
57
- 'Create an Elasticsearch Log Drain'
58
+ 'Create an Elasticsearch Log Drain. By default, App, ' \
59
+ +'Database, Ephemeral Session, and Proxy logs will be sent ' \
60
+ +'to your chosen destination.'
58
61
  drain_options
59
62
  option :db, type: :string
60
63
  option :pipeline, type: :string
@@ -81,7 +84,9 @@ module Aptible
81
84
  desc 'log_drain:create:datadog HANDLE ' \
82
85
  '--url DATADOG_URL ' \
83
86
  + drain_flags,
84
- 'Create a Datadog Log Drain'
87
+ 'Create a Datadog Log Drain. By default, App, Database, ' \
88
+ + 'Ephemeral Session, and Proxy logs will be sent ' \
89
+ + 'to your chosen destination.'
85
90
  drain_options
86
91
  option :url, type: :string
87
92
  define_method 'log_drain:create:datadog' do |handle|
@@ -107,7 +112,9 @@ module Aptible
107
112
  desc 'log_drain:create:sumologic HANDLE ' \
108
113
  '--url SUMOLOGIC_URL ' \
109
114
  + drain_flags,
110
- 'Create a Sumologic Drain'
115
+ 'Create a Sumologic Drain. By default, App, Database, ' \
116
+ + 'Ephemeral Session, and Proxy logs will be sent ' \
117
+ + 'to your chosen destination.'
111
118
  option :url, type: :string
112
119
  drain_options
113
120
  define_method 'log_drain:create:sumologic' do |handle|
@@ -118,7 +125,9 @@ module Aptible
118
125
  desc 'log_drain:create:logdna HANDLE ' \
119
126
  '--url LOGDNA_URL ' \
120
127
  + drain_flags,
121
- 'Create a LogDNA Log Drain'
128
+ 'Create a LogDNA/Mezmo Log Drain. By default, App, ' \
129
+ + 'Database, Ephemeral Session, and Proxy logs ' \
130
+ + 'will be sent to your chosen destination.'
122
131
  option :url, type: :string
123
132
  drain_options
124
133
  define_method 'log_drain:create:logdna' do |handle|
@@ -132,7 +141,9 @@ module Aptible
132
141
  desc 'log_drain:create:papertrail HANDLE ' \
133
142
  '--host PAPERTRAIL_HOST --port PAPERTRAIL_PORT ' \
134
143
  + drain_flags,
135
- 'Create a Papertrail Log Drain'
144
+ 'Create a Papertrail Log Drain. By default, App, Database, ' \
145
+ + 'Ephemeral Session, and Proxy logs will be sent ' \
146
+ + 'to your chosen destination.'
136
147
  option :host, type: :string
137
148
  option :port, type: :string
138
149
  drain_options
@@ -145,7 +156,9 @@ module Aptible
145
156
  '--host SYSLOG_HOST --port SYSLOG_PORT ' \
146
157
  '[--token TOKEN] ' \
147
158
  + drain_flags,
148
- 'Create a Papertrail Log Drain'
159
+ 'Create a Syslog Log Drain. By default, App, Database, ' \
160
+ + 'Ephemeral Session, and Proxy logs will be sent ' \
161
+ + 'to your chosen destination.'
149
162
  option :host, type: :string
150
163
  option :port, type: :string
151
164
  option :token, type: :string
@@ -27,8 +27,9 @@ module Aptible
27
27
 
28
28
  desc 'services:settings SERVICE'\
29
29
  ' [--force-zero-downtime|--no-force-zero-downtime]'\
30
- ' [--simple-health-check|--no-simple-health-check]',
31
- 'Modifies the zero-downtime deploy setting for a service'
30
+ ' [--simple-health-check|--no-simple-health-check]'\
31
+ ' [--stop-timeout SECONDS]',
32
+ 'Modifies the deployment settings for a service'
32
33
  app_options
33
34
  option :force_zero_downtime,
34
35
  type: :boolean, default: false,
@@ -37,6 +38,10 @@ module Aptible
37
38
  option :simple_health_check,
38
39
  type: :boolean, default: false,
39
40
  desc: 'Use a simple uptime healthcheck during deployments'
41
+ option :stop_timeout,
42
+ type: :numeric,
43
+ desc: 'The number of seconds to wait for the service '\
44
+ 'containers to stop gracefully on release before killing it.'
40
45
  define_method 'services:settings' do |service|
41
46
  telemetry(__method__, options.merge(service: service))
42
47
 
@@ -46,6 +51,8 @@ module Aptible
46
51
  options[:force_zero_downtime] if options[:force_zero_downtime]
47
52
  updates[:naive_health_check] =
48
53
  options[:simple_health_check] if options[:simple_health_check]
54
+ updates[:stop_timeout] =
55
+ options[:stop_timeout] if options[:stop_timeout]
49
56
 
50
57
  service.update!(**updates) if updates.any?
51
58
  end
@@ -1,5 +1,5 @@
1
1
  module Aptible
2
2
  module CLI
3
- VERSION = '0.24.4'.freeze
3
+ VERSION = '0.24.6'.freeze
4
4
  end
5
5
  end
@@ -8,12 +8,21 @@ describe Aptible::CLI::Agent do
8
8
  end
9
9
 
10
10
  describe '#version' do
11
+ before do
12
+ # Reset CI-related environment variables before each test
13
+ ENV['APTIBLE_TOOLBELT'] = nil
14
+ ENV['CI'] = nil
15
+ ENV['GITHUB_ACTIONS'] = nil
16
+ ENV['CIRCLECI'] = nil
17
+ ENV['TRAVIS'] = nil
18
+ ENV['GITLAB_CI'] = nil
19
+ ENV['DRONE'] = nil
20
+ end
21
+
11
22
  it 'should print the version' do
12
- ClimateControl.modify(APTIBLE_TOOLBELT: nil) do
13
- version = Aptible::CLI::VERSION
14
- subject.version
15
- expect(captured_output_text).to eq("aptible-cli v#{version}\n")
16
- end
23
+ version = Aptible::CLI::VERSION
24
+ subject.version
25
+ expect(captured_output_text).to eq("aptible-cli v#{version}\n")
17
26
  end
18
27
 
19
28
  it 'should print the version (with toolbelt)' do
@@ -23,6 +32,144 @@ describe Aptible::CLI::Agent do
23
32
  expect(captured_output_text).to eq("aptible-cli v#{version} toolbelt\n")
24
33
  end
25
34
  end
35
+
36
+ it 'should print the version with CI suffix' do
37
+ ClimateControl.modify(CI: 'true') do
38
+ version = Aptible::CLI::VERSION
39
+ subject.version
40
+ expect(captured_output_text).to eq("aptible-cli v#{version} (CI)\n")
41
+ end
42
+ end
43
+
44
+ it 'should print the version (with toolbelt and CI)' do
45
+ ClimateControl.modify(APTIBLE_TOOLBELT: '1', CI: 'true') do
46
+ version = Aptible::CLI::VERSION
47
+ subject.version
48
+ expect(captured_output_text).to eq(
49
+ "aptible-cli v#{version} toolbelt (CI)\n"
50
+ )
51
+ end
52
+ end
53
+
54
+ it 'should print the version with GHA suffix' do
55
+ ClimateControl.modify(CI: 'true', GITHUB_ACTIONS: 'true') do
56
+ version = Aptible::CLI::VERSION
57
+ subject.version
58
+ expect(captured_output_text).to eq(
59
+ "aptible-cli v#{version} (GitHub Actions)\n"
60
+ )
61
+ end
62
+ end
63
+
64
+ it 'should print the version (with toolbelt and GHA)' do
65
+ ClimateControl.modify(
66
+ APTIBLE_TOOLBELT: '1',
67
+ CI: 'true',
68
+ GITHUB_ACTIONS: 'true'
69
+ ) do
70
+ version = Aptible::CLI::VERSION
71
+ subject.version
72
+ expect(captured_output_text).to eq(
73
+ "aptible-cli v#{version} toolbelt (GitHub Actions)\n"
74
+ )
75
+ end
76
+ end
77
+
78
+ it 'should print the version with Circle suffix' do
79
+ ClimateControl.modify(CI: 'true', CIRCLECI: 'true') do
80
+ version = Aptible::CLI::VERSION
81
+ subject.version
82
+ expect(captured_output_text).to eq(
83
+ "aptible-cli v#{version} (CircleCI)\n"
84
+ )
85
+ end
86
+ end
87
+
88
+ it 'should print the version (with toolbelt and Circle)' do
89
+ ClimateControl.modify(
90
+ APTIBLE_TOOLBELT: '1',
91
+ CI: 'true',
92
+ CIRCLECI: 'true'
93
+ ) do
94
+ version = Aptible::CLI::VERSION
95
+ subject.version
96
+ expect(captured_output_text).to eq(
97
+ "aptible-cli v#{version} toolbelt (CircleCI)\n"
98
+ )
99
+ end
100
+ end
101
+
102
+ it 'should print the version with Travis suffix' do
103
+ ClimateControl.modify(CI: 'true', TRAVIS: 'true') do
104
+ version = Aptible::CLI::VERSION
105
+ subject.version
106
+ expect(captured_output_text).to eq(
107
+ "aptible-cli v#{version} (Travis CI)\n"
108
+ )
109
+ end
110
+ end
111
+
112
+ it 'should print the version (with toolbelt and Travis)' do
113
+ ClimateControl.modify(
114
+ APTIBLE_TOOLBELT: '1',
115
+ CI: 'true',
116
+ TRAVIS: 'true'
117
+ ) do
118
+ version = Aptible::CLI::VERSION
119
+ subject.version
120
+ expect(captured_output_text).to eq(
121
+ "aptible-cli v#{version} toolbelt (Travis CI)\n"
122
+ )
123
+ end
124
+ end
125
+
126
+ it 'should print the version with GitLab suffix' do
127
+ ClimateControl.modify(CI: 'true', GITLAB_CI: 'true') do
128
+ version = Aptible::CLI::VERSION
129
+ subject.version
130
+ expect(captured_output_text).to eq(
131
+ "aptible-cli v#{version} (GitLab CI)\n"
132
+ )
133
+ end
134
+ end
135
+
136
+ it 'should print the version (with toolbelt and GitLab)' do
137
+ ClimateControl.modify(
138
+ APTIBLE_TOOLBELT: '1',
139
+ CI: 'true',
140
+ GITLAB_CI: 'true'
141
+ ) do
142
+ version = Aptible::CLI::VERSION
143
+ subject.version
144
+ expect(captured_output_text).to eq(
145
+ "aptible-cli v#{version} toolbelt (GitLab CI)\n"
146
+ )
147
+ end
148
+ end
149
+
150
+ it 'should print the version with Harness suffix' do
151
+ ClimateControl.modify(CI: 'true', DRONE: 'true') do
152
+ version = Aptible::CLI::VERSION
153
+ subject.version
154
+ expect(captured_output_text).to eq(
155
+ "aptible-cli v#{version} (Harness)\n"
156
+ )
157
+ end
158
+ end
159
+
160
+ it 'should print the version (with toolbelt and Harness)' do
161
+ ClimateControl.modify(
162
+ APTIBLE_TOOLBELT: '1',
163
+ CI: 'true',
164
+ DRONE: 'true'
165
+ ) do
166
+ version = Aptible::CLI::VERSION
167
+ subject.version
168
+ expect(captured_output_text).to eq(
169
+ "aptible-cli v#{version} toolbelt (Harness)\n"
170
+ )
171
+ end
172
+ end
26
173
  end
27
174
 
28
175
  describe '#login' do
@@ -184,7 +184,7 @@ describe Aptible::CLI::Helpers::S3LogHelpers do
184
184
  ]
185
185
  )
186
186
  before do
187
- subject.stub(:s3_client) do
187
+ allow(subject).to receive(:s3_client) do
188
188
  Aws::S3::Resource.new(region: 'us-east-1', client: client_stub)
189
189
  end
190
190
  end
@@ -227,7 +227,7 @@ describe Aptible::CLI::Helpers::S3LogHelpers do
227
227
  { key: v3app }
228
228
  ]
229
229
  )
230
- subject.stub(:s3_client) do
230
+ allow(subject).to receive(:s3_client) do
231
231
  Aws::S3::Resource.new(region: 'us-east-1', client: client_stub)
232
232
  end
233
233
  end
@@ -23,7 +23,7 @@ describe Aptible::CLI::Agent do
23
23
  allow(Aptible::Api::Account).to receive(:all).and_return([account])
24
24
  end
25
25
  before do
26
- subject.stub(:validate_image_type) { true }
26
+ allow(subject).to receive(:validate_image_type).and_return(true)
27
27
  end
28
28
 
29
29
  def expect_provision_database(create_opts, provision_opts = {})
@@ -60,13 +60,19 @@ describe Aptible::CLI::Agent do
60
60
  end
61
61
 
62
62
  let!(:db) { Fabricate(:database, handle: 'mydb', account: a1) }
63
+ let!(:incomplete) do
64
+ Fabricate(:database, handle: 'incomplete',
65
+ status: 'provisioning',
66
+ account: a1)
67
+ end
63
68
 
64
69
  before do
65
70
  allow(Aptible::Api::Database)
66
71
  .to receive(:all)
67
72
  .with(token: token, href: '/databases?per_page=5000&no_embed=true')
68
- .and_return([db])
73
+ .and_return([db, incomplete])
69
74
  allow(db).to receive(:class).and_return(Aptible::Api::Database)
75
+ allow(incomplete).to receive(:class).and_return(Aptible::Api::Database)
70
76
  stub_options
71
77
  end
72
78
 
@@ -76,6 +82,12 @@ describe Aptible::CLI::Agent do
76
82
  .to raise_error(/could not find database some/im)
77
83
  end
78
84
 
85
+ it 'returns an error if the database is not fully provisioned' do
86
+ stub_options(database: incomplete.handle)
87
+ expect { subject.send('endpoints:database:create', 'incomplete') }
88
+ .to raise_error(/database is not provisioned/im)
89
+ end
90
+
79
91
  it 'fails if the DB is not in the account' do
80
92
  stub_options(environment: 'bar')
81
93
  expect { subject.send('endpoints:database:create', 'mydb') }
@@ -137,6 +149,12 @@ describe Aptible::CLI::Agent do
137
149
  expect { subject.send('endpoints:database:modify', v.external_host) }
138
150
  .to raise_error(/conflicting.*no-ip-whitelist.*ip-whitelist/im)
139
151
  end
152
+
153
+ it 'returns an error if the database is not fully provisioned' do
154
+ stub_options(database: incomplete.handle)
155
+ expect { subject.send('endpoints:database:modify', 'something') }
156
+ .to raise_error(/database is not provisioned/im)
157
+ end
140
158
  end
141
159
 
142
160
  describe 'endpoints:list' do
@@ -156,6 +174,12 @@ describe Aptible::CLI::Agent do
156
174
  expect(lines[0]).not_to eq("\n")
157
175
  expect(lines[-1]).not_to eq("\n")
158
176
  end
177
+
178
+ it 'returns an error if the database is not fully provisioned' do
179
+ stub_options(database: incomplete.handle)
180
+ expect { subject.send('endpoints:list') }
181
+ .to raise_error(/database is not provisioned/im)
182
+ end
159
183
  end
160
184
 
161
185
  describe 'endpoints:deprovison' do
@@ -176,6 +200,12 @@ describe Aptible::CLI::Agent do
176
200
  expect { subject.send('endpoints:deprovision', 'foo.io') }
177
201
  .to raise_error(/endpoint.*foo\.io.*does not exist/im)
178
202
  end
203
+
204
+ it 'returns an error if the database is not fully provisioned' do
205
+ stub_options(database: incomplete.handle)
206
+ expect { subject.send('endpoints:deprovision', 'foo') }
207
+ .to raise_error(/database is not provisioned/im)
208
+ end
179
209
  end
180
210
  end
181
211
 
@@ -19,12 +19,58 @@ describe Aptible::CLI::Agent do
19
19
  end
20
20
 
21
21
  describe('#environment:list') do
22
- it 'lists avaliable environments' do
22
+ it 'lists available environments' do
23
23
  subject.send('environment:list')
24
24
 
25
25
  expect(captured_output_text.split("\n")).to include('foo')
26
26
  expect(captured_output_text.split("\n")).to include('bar')
27
27
  end
28
+
29
+ it 'includes stack information in JSON output' do
30
+ stack1 = Fabricate(
31
+ :stack,
32
+ name: 'stack1',
33
+ region: 'us-east-1',
34
+ outbound_ip_addresses: ['1.1.1.1']
35
+ )
36
+ stack2 = Fabricate(
37
+ :stack,
38
+ name: 'stack2',
39
+ region: 'us-west-1',
40
+ outbound_ip_addresses: ['2.2.2.2']
41
+ )
42
+ a1.stack = stack1
43
+ a2.stack = stack2
44
+
45
+ subject.send('environment:list')
46
+
47
+ expected_json = [
48
+ {
49
+ 'id' => a1.id,
50
+ 'handle' => 'foo',
51
+ 'created_at' => fmt_time(a1.created_at),
52
+ 'stack' => {
53
+ 'id' => stack1.id,
54
+ 'name' => 'stack1',
55
+ 'region' => 'us-east-1',
56
+ 'outbound_ip_addresses' => ['1.1.1.1']
57
+ }
58
+ },
59
+ {
60
+ 'id' => a2.id,
61
+ 'handle' => 'bar',
62
+ 'created_at' => fmt_time(a2.created_at),
63
+ 'stack' => {
64
+ 'id' => stack2.id,
65
+ 'name' => 'stack2',
66
+ 'region' => 'us-west-1',
67
+ 'outbound_ip_addresses' => ['2.2.2.2']
68
+ }
69
+ }
70
+ ]
71
+
72
+ expect(captured_output_json).to eq(expected_json)
73
+ end
28
74
  end
29
75
 
30
76
  describe('#environment:ca_cert') do
@@ -46,8 +92,9 @@ describe Aptible::CLI::Agent do
46
92
  'created_at' => fmt_time(a2.created_at)
47
93
  }
48
94
  ]
49
- expect(captured_output_json.map! { |account| account.except('id') })
50
- .to eq(expected_accounts)
95
+ expect(
96
+ captured_output_json.map! { |account| account.except('id', 'stack') }
97
+ ).to eq(expected_accounts)
51
98
  end
52
99
 
53
100
  it 'fetches certs for specified environment' do
@@ -73,8 +73,9 @@ describe Aptible::CLI::Agent do
73
73
  string_matches: 'foo',
74
74
  download_location: './'
75
75
  }
76
- subject.stub(:info_from_path) { { shasum: 'foo' } }
77
- subject.stub(:encryption_key) { subject.options[:decryption_keys] }
76
+ allow(subject).to receive(:info_from_path).and_return(shasum: 'foo')
77
+ allow(subject).to receive(:encryption_key)
78
+ .and_return(subject.options[:decryption_keys])
78
79
  end
79
80
 
80
81
  it 'download all files' do
@@ -116,8 +117,9 @@ describe Aptible::CLI::Agent do
116
117
  app_id: 123,
117
118
  download_location: './'
118
119
  }
119
- subject.stub(:info_from_path) { { shasum: 'foo' } }
120
- subject.stub(:encryption_key) { subject.options[:decryption_keys] }
120
+ allow(subject).to receive(:info_from_path).and_return(shasum: 'foo')
121
+ allow(subject).to receive(:encryption_key)
122
+ .and_return(subject.options[:decryption_keys])
121
123
  end
122
124
 
123
125
  it 'download all files' do
@@ -161,8 +163,9 @@ describe Aptible::CLI::Agent do
161
163
  '9080b96447f98b31ef9831d5fd98b09e3c5c545269734e2e825644571152457c',
162
164
  download_location: './'
163
165
  }
164
- subject.stub(:info_from_path) { { shasum: 'foo' } }
165
- subject.stub(:encryption_key) { subject.options[:decryption_keys] }
166
+ allow(subject).to receive(:info_from_path).and_return(shasum: 'foo')
167
+ allow(subject).to receive(:encryption_key)
168
+ .and_return(subject.options[:decryption_keys])
166
169
  end
167
170
 
168
171
  it 'download all files' do
@@ -87,6 +87,25 @@ describe Aptible::CLI::Agent do
87
87
 
88
88
  subject.send('services:settings', 'foo')
89
89
  end
90
+
91
+ it 'allows setting stop timeout' do
92
+ stub_options(stop_timeout: 30)
93
+ service = Fabricate(:service, app: app, process_type: 'foo')
94
+
95
+ expect(service).to receive(:update!).with(stop_timeout: 30)
96
+
97
+ subject.send('services:settings', 'foo')
98
+ end
99
+
100
+ it 'allows setting stop timeout with other options' do
101
+ stub_options(stop_timeout: 30, force_zero_downtime: true)
102
+ service = Fabricate(:service, app: app, process_type: 'foo')
103
+
104
+ expect(service).to receive(:update!)
105
+ .with(stop_timeout: 30, force_zero_downtime: true)
106
+
107
+ subject.send('services:settings', 'foo')
108
+ end
90
109
  end
91
110
 
92
111
  describe '#services:sizing_policy' do
@@ -34,8 +34,10 @@ Fabricator(:database, from: :stub_database) do
34
34
 
35
35
  after_create do |database, transients|
36
36
  database.account.databases << database
37
- database.service = transients[:service] || Fabricate(
38
- :service, app: nil, database: database
39
- )
37
+ unless status == 'provisioning'
38
+ database.service = transients[:service] || Fabricate(
39
+ :service, app: nil, database: database
40
+ )
41
+ end
40
42
  end
41
43
  end
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.24.4
4
+ version: 0.24.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Macreery
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-13 00:00:00.000000000 Z
11
+ date: 2025-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 1.6.5
39
+ version: 1.8.0
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: 1.6.5
46
+ version: 1.8.0
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: aptible-auth
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +86,20 @@ dependencies:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
88
  version: '1.1'
89
+ - !ruby/object:Gem::Dependency
90
+ name: aws-eventstream
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 1.1.1
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 1.1.1
89
103
  - !ruby/object:Gem::Dependency
90
104
  name: aws-sdk
91
105
  requirement: !ruby/object:Gem::Requirement
@@ -100,6 +114,20 @@ dependencies:
100
114
  - - "~>"
101
115
  - !ruby/object:Gem::Version
102
116
  version: '2.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: aws-sigv4
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: 1.2.4
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 1.2.4
103
131
  - !ruby/object:Gem::Dependency
104
132
  name: bigdecimal
105
133
  requirement: !ruby/object:Gem::Requirement
@@ -157,33 +185,89 @@ dependencies:
157
185
  - !ruby/object:Gem::Version
158
186
  version: 1.1.10
159
187
  - !ruby/object:Gem::Dependency
160
- name: jwt
188
+ name: connection_pool
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - "<"
192
+ - !ruby/object:Gem::Version
193
+ version: 2.2.4
194
+ type: :runtime
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - "<"
199
+ - !ruby/object:Gem::Version
200
+ version: 2.2.4
201
+ - !ruby/object:Gem::Dependency
202
+ name: faraday
161
203
  requirement: !ruby/object:Gem::Requirement
162
204
  requirements:
163
205
  - - "~>"
164
206
  - !ruby/object:Gem::Version
165
- version: 2.3.0
207
+ version: 0.17.6
166
208
  type: :runtime
167
209
  prerelease: false
168
210
  version_requirements: !ruby/object:Gem::Requirement
169
211
  requirements:
170
212
  - - "~>"
171
213
  - !ruby/object:Gem::Version
172
- version: 2.3.0
214
+ version: 0.17.6
173
215
  - !ruby/object:Gem::Dependency
174
216
  name: git
175
217
  requirement: !ruby/object:Gem::Requirement
176
218
  requirements:
177
- - - "<"
219
+ - - "~>"
178
220
  - !ruby/object:Gem::Version
179
- version: '1.10'
221
+ version: 1.7.0
180
222
  type: :runtime
181
223
  prerelease: false
182
224
  version_requirements: !ruby/object:Gem::Requirement
183
225
  requirements:
184
- - - "<"
226
+ - - "~>"
185
227
  - !ruby/object:Gem::Version
186
- version: '1.10'
228
+ version: 1.7.0
229
+ - !ruby/object:Gem::Dependency
230
+ name: httpclient
231
+ requirement: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - "~>"
234
+ - !ruby/object:Gem::Version
235
+ version: 2.8.0
236
+ type: :runtime
237
+ prerelease: false
238
+ version_requirements: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - "~>"
241
+ - !ruby/object:Gem::Version
242
+ version: 2.8.0
243
+ - !ruby/object:Gem::Dependency
244
+ name: json
245
+ requirement: !ruby/object:Gem::Requirement
246
+ requirements:
247
+ - - "~>"
248
+ - !ruby/object:Gem::Version
249
+ version: 2.5.0
250
+ type: :runtime
251
+ prerelease: false
252
+ version_requirements: !ruby/object:Gem::Requirement
253
+ requirements:
254
+ - - "~>"
255
+ - !ruby/object:Gem::Version
256
+ version: 2.5.0
257
+ - !ruby/object:Gem::Dependency
258
+ name: jwt
259
+ requirement: !ruby/object:Gem::Requirement
260
+ requirements:
261
+ - - "~>"
262
+ - !ruby/object:Gem::Version
263
+ version: 2.3.0
264
+ type: :runtime
265
+ prerelease: false
266
+ version_requirements: !ruby/object:Gem::Requirement
267
+ requirements:
268
+ - - "~>"
269
+ - !ruby/object:Gem::Version
270
+ version: 2.3.0
187
271
  - !ruby/object:Gem::Dependency
188
272
  name: rack
189
273
  requirement: !ruby/object:Gem::Requirement
@@ -198,6 +282,20 @@ dependencies:
198
282
  - - "~>"
199
283
  - !ruby/object:Gem::Version
200
284
  version: '1.0'
285
+ - !ruby/object:Gem::Dependency
286
+ name: stripe
287
+ requirement: !ruby/object:Gem::Requirement
288
+ requirements:
289
+ - - "<"
290
+ - !ruby/object:Gem::Version
291
+ version: '5.0'
292
+ type: :runtime
293
+ prerelease: false
294
+ version_requirements: !ruby/object:Gem::Requirement
295
+ requirements:
296
+ - - "<"
297
+ - !ruby/object:Gem::Version
298
+ version: '5.0'
201
299
  - !ruby/object:Gem::Dependency
202
300
  name: term-ansicolor
203
301
  requirement: !ruby/object:Gem::Requirement
@@ -473,7 +571,7 @@ homepage: https://github.com/aptible/aptible-cli
473
571
  licenses:
474
572
  - MIT
475
573
  metadata: {}
476
- post_install_message:
574
+ post_install_message:
477
575
  rdoc_options: []
478
576
  require_paths:
479
577
  - lib
@@ -488,8 +586,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
488
586
  - !ruby/object:Gem::Version
489
587
  version: '0'
490
588
  requirements: []
491
- rubygems_version: 3.0.3.1
492
- signing_key:
589
+ rubygems_version: 3.1.6
590
+ signing_key:
493
591
  specification_version: 4
494
592
  summary: Command-line interface for Aptible services
495
593
  test_files: