Skip to content
This repository was archived by the owner on Aug 31, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
FROM ruby:2.7.8
ARG RUBY_VERSION=2.3.1
FROM ruby:${RUBY_VERSION}

# Install and use an compatible bundler
ENV BUNDLER_VERSION=1.17.3
RUN gem install bundler -v "${BUNDLER_VERSION}"
ARG BUNDLER_VERSION=1.17.3
ENV BUNDLER_VERSION=${BUNDLER_VERSION}
RUN if [ "${BUNDLER_VERSION}" != "" ] ; then \
gem install bundler -v "${BUNDLER_VERSION}" ; \
fi

# Install required gems before copying in code
# to avoid re-installing gems when developing
Expand All @@ -12,7 +15,7 @@ COPY Gemfile.lock /app
COPY aptible-cli.gemspec /app

# We reference the version, so copy that in, too
CMD mkdir -p /app/lib/aptible/cli/
RUN mkdir -p /app/lib/aptible/cli/
COPY lib/aptible/cli/version.rb /app/lib/aptible/cli/

RUN bundle install
Expand Down
29 changes: 19 additions & 10 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ PATH
specs:
aptible-cli (0.25.1)
activesupport (>= 4.0, < 6.0)
aptible-api (~> 1.10.0)
aptible-auth (~> 1.2.5)
aptible-api (~> 1.12)
aptible-auth (~> 1.4)
aptible-billing (~> 1.0)
aptible-resource (~> 1.1)
aws-eventstream (~> 1.1.1)
Expand Down Expand Up @@ -35,16 +35,16 @@ GEM
tzinfo (~> 1.1)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
aptible-api (1.10.0)
aptible-api (1.12.0)
aptible-auth
aptible-resource
gem_config
multipart-post (< 2.2.0)
aptible-auth (1.2.5)
aptible-auth (1.4.0)
aptible-resource (~> 1.0)
gem_config
multipart-post (= 2.1.1)
oauth2 (= 1.4.7)
oauth2 (= 2.0.9)
aptible-billing (1.0.1)
activesupport (>= 4.0, < 6.0)
aptible-resource (~> 1.0)
Expand Down Expand Up @@ -93,26 +93,30 @@ GEM
git (1.7.0)
rchardet (~> 1.8)
hashdiff (1.1.1)
hashie (5.0.0)
httpclient (2.8.3)
httplog (1.5.0)
rack (>= 1.0)
rainbow (>= 2.0.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jmespath (1.6.2)
json (2.5.1)
jwt (2.3.0)
method_source (1.1.0)
minitest (5.12.0)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
net-http-persistent (3.1.0)
connection_pool (~> 2.2)
numerizer (0.1.1)
oauth2 (1.4.7)
faraday (>= 0.8, < 2.0)
oauth2 (2.0.9)
faraday (>= 0.17.3, < 3.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
rack (>= 1.2, < 4)
snaky_hash (~> 2.0)
version_gem (~> 1.1)
parser (2.7.2.0)
ast (~> 2.4.1)
powerpack (0.1.3)
Expand Down Expand Up @@ -146,6 +150,9 @@ GEM
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.13.0)
snaky_hash (2.0.3)
hashie (>= 0.1.0, < 6)
version_gem (>= 1.1.8, < 3)
stripe (4.24.0)
faraday (~> 0.13)
net-http-persistent (~> 3.0)
Expand All @@ -161,6 +168,7 @@ GEM
thread_safe (~> 0.1)
unicode-display_width (1.8.0)
uri_template (0.7.0)
version_gem (1.1.9)
webmock (3.16.2)
addressable (>= 2.8.0)
crack (>= 0.3.2)
Expand All @@ -176,6 +184,7 @@ DEPENDENCIES
bundler (~> 1.3)
climate_control (= 0.0.3)
fabrication (~> 2.15.2)
httplog (< 1.6)
pry
rack (~> 1.0)
rake
Expand Down
52 changes: 50 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,58 @@

export COMPOSE_IGNORE_ORPHANS ?= true
export RUBY_VERSION ?= 2.3.1
RUBY_VERSION_MAJOR = $(word 1,$(subst ., ,$(RUBY_VERSION)))
export BUNDLER_VERSION ?=
ifeq ($(BUNDLER_VERSION),)
ifeq ($(RUBY_VERSION_MAJOR),2)
export BUNDLER_VERSION = 1.17.3
endif
endif
export COMPOSE_PROJECT_NAME ?= aptible-cli-$(subst .,_,$(RUBY_VERSION))

## Build and pull docker compose images
build:
docker compose build --pull

## Open shell in a docker container, supports CMD=
bash: build
docker compose run cli bash
$(MAKE) run CMD=bash

CMD ?= bash
## Run command in a docker container, supports CMD=
run:
docker compose run cli $(CMD)

## Run tests in a docker container, supports ARGS=
test: build
docker compose run cli bundle exec rake
$(MAKE) test-direct ARGS="$(ARGS)"

## Run tests in a docker container without building, supports ARGS=
test-direct:
docker compose run cli bundle exec rake $(ARGS)

## Run rubocop in a docker container, supports ARGS=
lint: build
$(MAKE) lint-direct ARGS="$(ARGS)"

## Run rubocop in a docker container without building, supports ARGS=
lint-direct:
docker compose run cli bundle exec rake rubocop $(ARGS)

## Clean up docker compose resources
clean:
docker compose down --remove-orphans --volumes

## Alias for clean
down: clean

## Show this help message
help:
@echo "\n\033[1;34mAvailable targets:\033[0m\n"
@awk 'BEGIN {FS = ":"; prev = ""} \
/^## / {prev = substr($$0, 4); next} \
/^[a-zA-Z_-]+:/ {if (prev != "") printf " \033[1;36m%-20s\033[0m %s\n", $$1, prev; prev = ""} \
{prev = ""}' $(MAKEFILE_LIST) | sort
@echo

.PHONY: build bash test
5 changes: 3 additions & 2 deletions aptible-cli.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ Gem::Specification.new do |spec|
spec.require_paths = ['lib']

spec.add_dependency 'activesupport', '>= 4.0', '< 6.0'
spec.add_dependency 'aptible-api', '~> 1.10.0'
spec.add_dependency 'aptible-auth', '~> 1.2.5'
spec.add_dependency 'aptible-api', '~> 1.12'
spec.add_dependency 'aptible-auth', '~> 1.4'
spec.add_dependency 'aptible-billing', '~> 1.0'
spec.add_dependency 'aptible-resource', '~> 1.1'
spec.add_dependency 'aws-eventstream', '~> 1.1.1'
Expand Down Expand Up @@ -54,4 +54,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'pry'
spec.add_development_dependency 'climate_control', '= 0.0.3'
spec.add_development_dependency 'fabrication', '~> 2.15.2'
spec.add_development_dependency 'httplog', '< 1.6'
end
6 changes: 5 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
services:
cli:
build: .
build:
context: .
args:
RUBY_VERSION: ${RUBY_VERSION:-2.3.1}
BUNDLER_VERSION: ${BUNDLER_VERSION:-}
volumes:
- type: bind
source: .
Expand Down
4 changes: 4 additions & 0 deletions lib/aptible/cli/agent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ def initialize(*)
level = Logger::WARN
debug_level = ENV['APTIBLE_DEBUG']
level = debug_level if debug_level
require 'httplog' if ENV['BUNDLER_VERSION'] && \
Comment thread
madhuravius marked this conversation as resolved.
ENV['APTIBLE_LOG_HTTP_REQUEST_RESPONSE'] && \
!ENV['APTIBLE_LOG_HTTP_REQUEST_RESPONSE'] \
.downcase.start_with?('f')
conf.logger.tap { |l| l.level = level }
end
warn_sso_enforcement
Expand Down
110 changes: 88 additions & 22 deletions lib/aptible/cli/helpers/aws_account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ def aws_accounts_all
end

def aws_account_from_id(id)
Aptible::Api::ExternalAwsAccount.all(token: fetch_token).find do |a|
a.id.to_s == id.to_s
end
Aptible::Api::ExternalAwsAccount.find(id.to_s, token: fetch_token)
end

def ensure_external_aws_account(id)
Expand All @@ -38,54 +36,122 @@ def ensure_external_aws_account(id)
acct
end

def fetch_organization_id
orgs = Aptible::Auth::Organization.all(token: fetch_token)
raise Thor::Error, 'No organizations found, specify one with ' \
'--organization-id=ORG_ID' if orgs.empty?
raise Thor::Error, 'Multiple organizations found, indicate which ' \
'one to use with --organization-id=ORG_ID ' \
"\n\tFound organization ids:" \
"\n\t\t#{orgs.map do |o|
"#{o.id} (#{o.name})"
end.join("\n\t\t")}" \
if orgs.count > 1

orgs.first.id
end

def organization_id_from_opts_or_auth(options)
return options[:organization_id] if options.key? :organization_id

fetch_organization_id
end

def build_external_aws_account_attrs(options)
role_arn = options[:role_arn] || options[:arn]
discovery_role_arn = if options[:remove_discovery_role_arn]
''
else
options[:discovery_role_arn]
end
discovery_enabled = if options.key?(:discovery_enabled)
options[:discovery_enabled]
end
attrs = {
role_arn: role_arn,
account_name: options[:account_name] || options[:name],
aws_account_id: options[:aws_account_id],
organization_id: options[:organization_id],
aws_region_primary: options[:aws_region_primary],
status: options[:status],
discovery_enabled: discovery_enabled,
discovery_role_arn: discovery_role_arn,
discovery_frequency: options[:discovery_frequency]
}
attrs.reject { |_, v| v.nil? }
end

def create_external_aws_account!(options)
attrs = build_external_aws_account_attrs(options)
Aptible::Api::ExternalAwsAccount.create(
token: fetch_token,
**attrs
)
attrs[:organization_id] = organization_id_from_opts_or_auth(options)
begin
resource = Aptible::Api::ExternalAwsAccount.create(
token: fetch_token,
**attrs
)
if resource.errors.any?
raise Thor::Error, resource.errors.full_messages.first
end
resource
rescue HyperResource::ClientError => e
raise Thor::Error, e.message
end
end

def update_external_aws_account!(id, options)
ext = ensure_external_aws_account(id)
attrs = build_external_aws_account_attrs(options)
ext.update!(**attrs) unless attrs.empty?
ext
begin
unless attrs.empty?
ext.update!(**attrs)
if ext.errors.any?
raise Thor::Error, ext.errors.full_messages.first
end
end
ext
rescue HyperResource::ClientError => e
raise Thor::Error, e.message
end
end

def delete_external_aws_account!(id)
ext = ensure_external_aws_account(id)
if ext.respond_to?(:destroy!)
ext.destroy!
elsif ext.respond_to?(:destroy)
ext.destroy
elsif ext.respond_to?(:delete!)
ext.delete!
elsif ext.respond_to?(:delete)
ext.delete
else
raise Thor::Error, 'Delete is not supported for this resource'
begin
if ext.respond_to?(:destroy!)
ext.destroy!
elsif ext.respond_to?(:destroy)
ext.destroy
elsif ext.respond_to?(:delete!)
ext.delete!
elsif ext.respond_to?(:delete)
ext.delete
else
raise Thor::Error, 'Delete is not supported for this resource'
end
rescue HyperResource::ClientError => e
raise Thor::Error, e.message
end
true
end

def check_external_aws_account!(id)
ext = ensure_external_aws_account(id)
begin
ext.check!
rescue HyperResource::ClientError => e
raise Thor::Error, e.message
end
end

def format_check_state(state)
case state
when 'success'
'✅ success'
when 'failed'
'❌ failed'
when 'not_run'
'⏭️ not_run'
else
state
end
end
end
end
end
Expand Down
Loading