aptible-cli 0.25.0 → 0.26.1

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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +27 -0
  3. data/.github/workflows/test.yml +1 -1
  4. data/Dockerfile +8 -5
  5. data/Gemfile.lock +28 -17
  6. data/Makefile +50 -2
  7. data/README.md +2 -1
  8. data/aptible-cli.gemspec +5 -2
  9. data/docker-compose.yml +5 -1
  10. data/lib/aptible/cli/agent.rb +9 -0
  11. data/lib/aptible/cli/helpers/aws_account.rb +158 -0
  12. data/lib/aptible/cli/helpers/database.rb +182 -2
  13. data/lib/aptible/cli/helpers/token.rb +14 -0
  14. data/lib/aptible/cli/renderer/text.rb +33 -2
  15. data/lib/aptible/cli/subcommands/aws_accounts.rb +252 -0
  16. data/lib/aptible/cli/subcommands/db.rb +67 -3
  17. data/lib/aptible/cli/subcommands/deploy.rb +45 -11
  18. data/lib/aptible/cli/subcommands/organizations.rb +55 -0
  19. data/lib/aptible/cli/subcommands/services.rb +20 -8
  20. data/lib/aptible/cli/version.rb +1 -1
  21. data/spec/aptible/cli/helpers/database_spec.rb +118 -0
  22. data/spec/aptible/cli/helpers/token_spec.rb +70 -0
  23. data/spec/aptible/cli/subcommands/db_spec.rb +553 -0
  24. data/spec/aptible/cli/subcommands/deploy_spec.rb +42 -7
  25. data/spec/aptible/cli/subcommands/external_aws_accounts_spec.rb +737 -0
  26. data/spec/aptible/cli/subcommands/organizations_spec.rb +90 -0
  27. data/spec/aptible/cli/subcommands/services_spec.rb +77 -0
  28. data/spec/fabricators/app_external_aws_rds_connection_fabricator.rb +55 -0
  29. data/spec/fabricators/external_aws_account_fabricator.rb +49 -0
  30. data/spec/fabricators/external_aws_database_credential_fabricator.rb +46 -0
  31. data/spec/fabricators/external_aws_resource_fabricator.rb +72 -0
  32. metadata +65 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c07b217cf8ee2a23f5823638e205e780d43b3adf57397a4ecb01c8aff5998b7
4
- data.tar.gz: aefbe672ac77da98c9fd445b6ee0ffbbc044f531a97f36bc6d7bf48db46a1b4c
3
+ metadata.gz: 546bd229e854b1c8fb1e859d884aaace908bfb8d1c41384478e80f4867c304bf
4
+ data.tar.gz: c51945840657af4bc8b8ef1f932cf851b87450c5dd2c8fdfc08161bf454563ca
5
5
  SHA512:
6
- metadata.gz: 3710b7014df38552ebce0b5780921be9020227a965fd6d67e0a5718f1ac223fde476f59c3a7e3289c268a7cf24d96c8057fe87b553b30941102028106e00d54c
7
- data.tar.gz: c2122ad6901292782834cdaedcda8b3b2638a0bcac815dec175e9fa4704282955953fa94b02f6c322daf9e47584eb944416071d907ffcd301b65d7b4f08470c8
6
+ metadata.gz: 0401e5a7a7f621e6eee0151f2e50e568b4dd7f2458da2a34cc18789bab180868c8c6d4cbc1d008f54f9c8ab9c13cccc2c9a8b8ddcc0829caf013e45abe6cbfde
7
+ data.tar.gz: c34e045d20f5edd8325d5fe1a2390ae0b304b94a227011c4ed29e57f293ddd7969c54fbc77b902b52be34e89bd44274b0215dff92165bb7f2460b4113b84349f
@@ -0,0 +1,27 @@
1
+ on:
2
+ release:
3
+ types: [published]
4
+
5
+ jobs:
6
+ push:
7
+ name: Push gem to RubyGems.org
8
+ runs-on: ubuntu-latest
9
+
10
+ permissions:
11
+ id-token: write
12
+ contents: write
13
+
14
+ steps:
15
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
16
+ with:
17
+ persist-credentials: false
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@211ffaaa5f8dda97e9e8bca4e70d0fbaf2f8c41c
20
+ with:
21
+ bundler-cache: false
22
+ ruby-version: "3.3"
23
+
24
+ - run: bundle install
25
+
26
+ - uses: rubygems/release-gem@1c162a739e8b4cb21a676e97b087e8268d8fc40b
27
+
@@ -15,7 +15,7 @@ jobs:
15
15
  strategy:
16
16
  fail-fast: false
17
17
  matrix:
18
- ruby-version: [2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7]
18
+ ruby-version: [2.3, 2.4, 2.5, 2.6, 2.7]
19
19
  steps:
20
20
  - name: Check out code
21
21
  uses: actions/checkout@v4
data/Dockerfile CHANGED
@@ -1,8 +1,11 @@
1
- FROM ruby:2.7.8
1
+ ARG RUBY_VERSION=2.3.1
2
+ FROM ruby:${RUBY_VERSION}
2
3
 
3
- # Install and use an compatible bundler
4
- ENV BUNDLER_VERSION=1.17.3
5
- RUN gem install bundler -v "${BUNDLER_VERSION}"
4
+ ARG BUNDLER_VERSION=1.17.3
5
+ ENV BUNDLER_VERSION=${BUNDLER_VERSION}
6
+ RUN if [ "${BUNDLER_VERSION}" != "" ] ; then \
7
+ gem install bundler -v "${BUNDLER_VERSION}" ; \
8
+ fi
6
9
 
7
10
  # Install required gems before copying in code
8
11
  # to avoid re-installing gems when developing
@@ -12,7 +15,7 @@ COPY Gemfile.lock /app
12
15
  COPY aptible-cli.gemspec /app
13
16
 
14
17
  # We reference the version, so copy that in, too
15
- CMD mkdir -p /app/lib/aptible/cli/
18
+ RUN mkdir -p /app/lib/aptible/cli/
16
19
  COPY lib/aptible/cli/version.rb /app/lib/aptible/cli/
17
20
 
18
21
  RUN bundle install
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- aptible-cli (0.25.0)
4
+ aptible-cli (0.26.1)
5
5
  activesupport (>= 4.0, < 6.0)
6
- aptible-api (~> 1.8.0)
7
- aptible-auth (~> 1.2.5)
6
+ aptible-api (~> 1.12)
7
+ aptible-auth (~> 1.4)
8
8
  aptible-billing (~> 1.0)
9
9
  aptible-resource (~> 1.1)
10
10
  aws-eventstream (~> 1.1.1)
@@ -35,21 +35,21 @@ GEM
35
35
  tzinfo (~> 1.1)
36
36
  addressable (2.8.0)
37
37
  public_suffix (>= 2.0.2, < 5.0)
38
- aptible-api (1.8.1)
38
+ aptible-api (1.12.0)
39
39
  aptible-auth
40
40
  aptible-resource
41
41
  gem_config
42
42
  multipart-post (< 2.2.0)
43
- aptible-auth (1.2.5)
43
+ aptible-auth (1.5.0)
44
44
  aptible-resource (~> 1.0)
45
45
  gem_config
46
46
  multipart-post (= 2.1.1)
47
- oauth2 (= 1.4.7)
47
+ oauth2 (= 2.0.9)
48
48
  aptible-billing (1.0.1)
49
49
  activesupport (>= 4.0, < 6.0)
50
50
  aptible-resource (~> 1.0)
51
51
  stripe (>= 1.13.0)
52
- aptible-resource (1.1.3)
52
+ aptible-resource (1.1.4)
53
53
  activesupport
54
54
  fridge
55
55
  gem_config (~> 0.3.1)
@@ -71,7 +71,7 @@ GEM
71
71
  aws-sigv4 (1.2.4)
72
72
  aws-eventstream (~> 1, >= 1.0.2)
73
73
  bigdecimal (1.3.5)
74
- cbor (0.5.9.8)
74
+ cbor (0.5.10.1)
75
75
  chronic_duration (0.10.6)
76
76
  numerizer (~> 0.1.1)
77
77
  climate_control (0.0.3)
@@ -86,37 +86,41 @@ GEM
86
86
  fabrication (2.15.2)
87
87
  faraday (0.17.6)
88
88
  multipart-post (>= 1.2, < 3)
89
- fridge (1.0.0)
89
+ fridge (1.0.1)
90
90
  gem_config
91
91
  jwt (~> 2.3.0)
92
92
  gem_config (0.3.2)
93
93
  git (1.7.0)
94
94
  rchardet (~> 1.8)
95
95
  hashdiff (1.1.1)
96
+ hashie (5.0.0)
96
97
  httpclient (2.8.3)
98
+ httplog (1.5.0)
99
+ rack (>= 1.0)
100
+ rainbow (>= 2.0.0)
97
101
  i18n (0.9.5)
98
102
  concurrent-ruby (~> 1.0)
99
103
  jmespath (1.6.2)
100
104
  json (2.5.1)
101
105
  jwt (2.3.0)
102
106
  method_source (1.1.0)
103
- minitest (5.12.0)
104
- multi_json (1.15.0)
107
+ minitest (5.15.0)
105
108
  multi_xml (0.6.0)
106
109
  multipart-post (2.1.1)
107
110
  net-http-persistent (3.1.0)
108
111
  connection_pool (~> 2.2)
109
112
  numerizer (0.1.1)
110
- oauth2 (1.4.7)
111
- faraday (>= 0.8, < 2.0)
113
+ oauth2 (2.0.9)
114
+ faraday (>= 0.17.3, < 3.0)
112
115
  jwt (>= 1.0, < 3.0)
113
- multi_json (~> 1.3)
114
116
  multi_xml (~> 0.5)
115
- rack (>= 1.2, < 3)
117
+ rack (>= 1.2, < 4)
118
+ snaky_hash (~> 2.0)
119
+ version_gem (~> 1.1)
116
120
  parser (2.7.2.0)
117
121
  ast (~> 2.4.1)
118
122
  powerpack (0.1.3)
119
- pry (0.14.2)
123
+ pry (0.15.2)
120
124
  coderay (~> 1.1)
121
125
  method_source (~> 1.0)
122
126
  public_suffix (3.1.1)
@@ -146,6 +150,9 @@ GEM
146
150
  ruby-progressbar (~> 1.7)
147
151
  unicode-display_width (~> 1.0, >= 1.0.1)
148
152
  ruby-progressbar (1.13.0)
153
+ snaky_hash (2.0.3)
154
+ hashie (>= 0.1.0, < 6)
155
+ version_gem (>= 1.1.8, < 3)
149
156
  stripe (4.24.0)
150
157
  faraday (~> 0.13)
151
158
  net-http-persistent (~> 3.0)
@@ -154,13 +161,14 @@ GEM
154
161
  tins (~> 1.0)
155
162
  thor (0.20.3)
156
163
  thread_safe (0.3.6)
157
- tins (1.38.0)
164
+ tins (1.43.0)
158
165
  bigdecimal
159
166
  sync
160
167
  tzinfo (1.2.11)
161
168
  thread_safe (~> 0.1)
162
169
  unicode-display_width (1.8.0)
163
170
  uri_template (0.7.0)
171
+ version_gem (1.1.9)
164
172
  webmock (3.16.2)
165
173
  addressable (>= 2.8.0)
166
174
  crack (>= 0.3.2)
@@ -176,6 +184,9 @@ DEPENDENCIES
176
184
  bundler (~> 1.3)
177
185
  climate_control (= 0.0.3)
178
186
  fabrication (~> 2.15.2)
187
+ hashie (< 5.1)
188
+ httplog (< 1.6)
189
+ minitest (< 5.16)
179
190
  pry
180
191
  rack (~> 1.0)
181
192
  rake
data/Makefile CHANGED
@@ -1,10 +1,58 @@
1
+
2
+ export COMPOSE_IGNORE_ORPHANS ?= true
3
+ export RUBY_VERSION ?= 2.3.1
4
+ RUBY_VERSION_MAJOR = $(word 1,$(subst ., ,$(RUBY_VERSION)))
5
+ export BUNDLER_VERSION ?=
6
+ ifeq ($(BUNDLER_VERSION),)
7
+ ifeq ($(RUBY_VERSION_MAJOR),2)
8
+ export BUNDLER_VERSION = 1.17.3
9
+ endif
10
+ endif
11
+ export COMPOSE_PROJECT_NAME ?= aptible-cli-$(subst .,_,$(RUBY_VERSION))
12
+
13
+ ## Build and pull docker compose images
1
14
  build:
2
15
  docker compose build --pull
3
16
 
17
+ ## Open shell in a docker container, supports CMD=
4
18
  bash: build
5
- docker compose run cli bash
19
+ $(MAKE) run CMD=bash
20
+
21
+ CMD ?= bash
22
+ ## Run command in a docker container, supports CMD=
23
+ run:
24
+ docker compose run cli $(CMD)
6
25
 
26
+ ## Run tests in a docker container, supports ARGS=
7
27
  test: build
8
- docker compose run cli bundle exec rake
28
+ $(MAKE) test-direct ARGS="$(ARGS)"
29
+
30
+ ## Run tests in a docker container without building, supports ARGS=
31
+ test-direct:
32
+ docker compose run cli bundle exec rake $(ARGS)
33
+
34
+ ## Run rubocop in a docker container, supports ARGS=
35
+ lint: build
36
+ $(MAKE) lint-direct ARGS="$(ARGS)"
37
+
38
+ ## Run rubocop in a docker container without building, supports ARGS=
39
+ lint-direct:
40
+ docker compose run cli bundle exec rake rubocop $(ARGS)
41
+
42
+ ## Clean up docker compose resources
43
+ clean:
44
+ docker compose down --remove-orphans --volumes
45
+
46
+ ## Alias for clean
47
+ down: clean
48
+
49
+ ## Show this help message
50
+ help:
51
+ @echo "\n\033[1;34mAvailable targets:\033[0m\n"
52
+ @awk 'BEGIN {FS = ":"; prev = ""} \
53
+ /^## / {prev = substr($$0, 4); next} \
54
+ /^[a-zA-Z_-]+:/ {if (prev != "") printf " \033[1;36m%-20s\033[0m %s\n", $$1, prev; prev = ""} \
55
+ {prev = ""}' $(MAKEFILE_LIST) | sort
56
+ @echo
9
57
 
10
58
  .PHONY: build bash test
data/README.md CHANGED
@@ -100,12 +100,13 @@ Commands:
100
100
  aptible operation:cancel OPERATION_ID # Cancel a running operation
101
101
  aptible operation:follow OPERATION_ID # Follow logs of a running operation
102
102
  aptible operation:logs OPERATION_ID # View logs for given operation
103
+ aptible organizations # List all organizations
103
104
  aptible rebuild # Rebuild an app, and restart its services
104
105
  aptible restart # Restart all services associated with an app
105
106
  aptible services # List Services for an App
106
107
  aptible services:autoscaling_policy SERVICE # Returns the associated sizing policy, if any
107
108
  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] [--restart-free-scale|--no-restart-free-scale] # 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.
108
- 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
109
+ aptible services:settings SERVICE [--force-zero-downtime|--no-force-zero-downtime] [--simple-health-check|--no-simple-health-check] [--restart-free-scaling|--no-restart-free-scaling] [--stop-timeout SECONDS] # Modifies the deployment settings for a service
109
110
  aptible ssh [COMMAND] # Run a command against an app
110
111
  aptible version # Print Aptible CLI version
111
112
  ```
data/aptible-cli.gemspec CHANGED
@@ -21,8 +21,8 @@ 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.8.0'
25
- spec.add_dependency 'aptible-auth', '~> 1.2.5'
24
+ spec.add_dependency 'aptible-api', '~> 1.12'
25
+ spec.add_dependency 'aptible-auth', '~> 1.4'
26
26
  spec.add_dependency 'aptible-billing', '~> 1.0'
27
27
  spec.add_dependency 'aptible-resource', '~> 1.1'
28
28
  spec.add_dependency 'aws-eventstream', '~> 1.1.1'
@@ -54,4 +54,7 @@ Gem::Specification.new do |spec|
54
54
  spec.add_development_dependency 'pry'
55
55
  spec.add_development_dependency 'climate_control', '= 0.0.3'
56
56
  spec.add_development_dependency 'fabrication', '~> 2.15.2'
57
+ spec.add_development_dependency 'httplog', '< 1.6'
58
+ spec.add_development_dependency 'minitest', '< 5.16'
59
+ spec.add_development_dependency 'hashie', '< 5.1'
57
60
  end
data/docker-compose.yml CHANGED
@@ -1,6 +1,10 @@
1
1
  services:
2
2
  cli:
3
- build: .
3
+ build:
4
+ context: .
5
+ args:
6
+ RUBY_VERSION: ${RUBY_VERSION:-2.3.1}
7
+ BUNDLER_VERSION: ${BUNDLER_VERSION:-}
4
8
  volumes:
5
9
  - type: bind
6
10
  source: .
@@ -26,6 +26,7 @@ require_relative 'helpers/metric_drain'
26
26
  require_relative 'helpers/date_helpers'
27
27
  require_relative 'helpers/s3_log_helpers'
28
28
  require_relative 'helpers/maintenance'
29
+ require_relative 'helpers/aws_account'
29
30
 
30
31
  require_relative 'subcommands/apps'
31
32
  require_relative 'subcommands/config'
@@ -45,6 +46,8 @@ require_relative 'subcommands/log_drain'
45
46
  require_relative 'subcommands/metric_drain'
46
47
  require_relative 'subcommands/maintenance'
47
48
  require_relative 'subcommands/backup_retention_policy'
49
+ require_relative 'subcommands/aws_accounts'
50
+ require_relative 'subcommands/organizations'
48
51
 
49
52
  module Aptible
50
53
  module CLI
@@ -74,6 +77,8 @@ module Aptible
74
77
  include Subcommands::MetricDrain
75
78
  include Subcommands::Maintenance
76
79
  include Subcommands::BackupRetentionPolicy
80
+ include Subcommands::AwsAccounts
81
+ include Subcommands::Organizations
77
82
 
78
83
  # Forward return codes on failures.
79
84
  def self.exit_on_failure?
@@ -87,6 +92,10 @@ module Aptible
87
92
  level = Logger::WARN
88
93
  debug_level = ENV['APTIBLE_DEBUG']
89
94
  level = debug_level if debug_level
95
+ require 'httplog' if ENV['BUNDLER_VERSION'] && \
96
+ ENV['APTIBLE_LOG_HTTP_REQUEST_RESPONSE'] && \
97
+ !ENV['APTIBLE_LOG_HTTP_REQUEST_RESPONSE'] \
98
+ .downcase.start_with?('f')
90
99
  conf.logger.tap { |l| l.level = level }
91
100
  end
92
101
  warn_sso_enforcement
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aptible/api'
4
+
5
+ module Aptible
6
+ module CLI
7
+ module Helpers
8
+ module AwsAccount
9
+ include Helpers::Token
10
+
11
+ def aws_accounts_href
12
+ if Renderer.format == 'json'
13
+ '/external_aws_accounts'
14
+ else
15
+ '/external_aws_accounts?per_page=5000&no_embed=true'
16
+ end
17
+ end
18
+
19
+ def aws_accounts_all
20
+ Aptible::Api::ExternalAwsAccount.all(
21
+ token: fetch_token,
22
+ href: aws_accounts_href
23
+ )
24
+ end
25
+
26
+ def aws_account_from_id(id)
27
+ Aptible::Api::ExternalAwsAccount.find(id.to_s, token: fetch_token)
28
+ end
29
+
30
+ def ensure_external_aws_account(id)
31
+ acct = aws_account_from_id(id)
32
+ if acct.nil?
33
+ raise Thor::Error, "External AWS account not found: #{id}"
34
+ end
35
+
36
+ acct
37
+ end
38
+
39
+ def fetch_organization_id
40
+ orgs = Aptible::Auth::Organization.all(token: fetch_token)
41
+ raise Thor::Error, 'No organizations found, specify one with ' \
42
+ '--organization-id=ORG_ID' if orgs.empty?
43
+ raise Thor::Error, 'Multiple organizations found, indicate which ' \
44
+ 'one to use with --organization-id=ORG_ID ' \
45
+ "\n\tFound organization ids:" \
46
+ "\n\t\t#{orgs.map do |o|
47
+ "#{o.id} (#{o.name})"
48
+ end.join("\n\t\t")}" \
49
+ if orgs.count > 1
50
+
51
+ orgs.first.id
52
+ end
53
+
54
+ def organization_id_from_opts_or_auth(options)
55
+ return options[:organization_id] if options.key? :organization_id
56
+
57
+ fetch_organization_id
58
+ end
59
+
60
+ def build_external_aws_account_attrs(options)
61
+ discovery_role_arn = if options[:remove_discovery_role_arn]
62
+ ''
63
+ else
64
+ options[:discovery_role_arn]
65
+ end
66
+ discovery_enabled = if options.key?(:discovery_enabled)
67
+ options[:discovery_enabled]
68
+ end
69
+ attrs = {
70
+ account_name: options[:account_name] || options[:name],
71
+ aws_account_id: options[:aws_account_id],
72
+ aws_region_primary: options[:aws_region_primary],
73
+ status: options[:status],
74
+ discovery_enabled: discovery_enabled,
75
+ discovery_role_arn: discovery_role_arn,
76
+ discovery_frequency: options[:discovery_frequency]
77
+ }
78
+ attrs.reject { |_, v| v.nil? }
79
+ end
80
+
81
+ def create_external_aws_account!(options)
82
+ attrs = build_external_aws_account_attrs(options)
83
+ attrs[:organization_id] = organization_id_from_opts_or_auth(options)
84
+ begin
85
+ resource = Aptible::Api::ExternalAwsAccount.create(
86
+ token: fetch_token,
87
+ **attrs
88
+ )
89
+ if resource.errors.any?
90
+ raise Thor::Error, resource.errors.full_messages.first
91
+ end
92
+ resource
93
+ rescue HyperResource::ClientError => e
94
+ raise Thor::Error, e.message
95
+ end
96
+ end
97
+
98
+ def update_external_aws_account!(id, options)
99
+ ext = ensure_external_aws_account(id)
100
+ attrs = build_external_aws_account_attrs(options)
101
+ begin
102
+ unless attrs.empty?
103
+ ext.update!(**attrs)
104
+ if ext.errors.any?
105
+ raise Thor::Error, ext.errors.full_messages.first
106
+ end
107
+ end
108
+ ext
109
+ rescue HyperResource::ClientError => e
110
+ raise Thor::Error, e.message
111
+ end
112
+ end
113
+
114
+ def delete_external_aws_account!(id)
115
+ ext = ensure_external_aws_account(id)
116
+ begin
117
+ if ext.respond_to?(:destroy!)
118
+ ext.destroy!
119
+ elsif ext.respond_to?(:destroy)
120
+ ext.destroy
121
+ elsif ext.respond_to?(:delete!)
122
+ ext.delete!
123
+ elsif ext.respond_to?(:delete)
124
+ ext.delete
125
+ else
126
+ raise Thor::Error, 'Delete is not supported for this resource'
127
+ end
128
+ rescue HyperResource::ClientError => e
129
+ raise Thor::Error, e.message
130
+ end
131
+ true
132
+ end
133
+
134
+ def check_external_aws_account!(id)
135
+ ext = ensure_external_aws_account(id)
136
+ begin
137
+ ext.check!
138
+ rescue HyperResource::ClientError => e
139
+ raise Thor::Error, e.message
140
+ end
141
+ end
142
+
143
+ def format_check_state(state)
144
+ case state
145
+ when 'success'
146
+ '✅ success'
147
+ when 'failed'
148
+ '❌ failed'
149
+ when 'not_run'
150
+ '⏭️ not_run'
151
+ else
152
+ state
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end