ecs-rails-console 0.0.2
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 +7 -0
- data/bin/ecs_rails_console +63 -0
- data/lib/ecs_rails_console.rb +7 -0
- data/lib/ecs_rails_console/cli.rb +56 -0
- data/lib/ecs_rails_console/core.rb +118 -0
- data/lib/ecs_rails_console/version.rb +5 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 89bf0d51f3784badf31b3b907df33c184653dff3e03b4907bde2a80f9558c750
|
4
|
+
data.tar.gz: 53630b5f467b6fd0d0f2c596fa636a710ab6384affd78e713bb970ce197fb177
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 365b37aeb0780b5f724e4f702650af90d7698793e8fb4edb9e02f2a41560058a7f3dd72b86c21f6c9f40e861cc2a2ef97e8aa075f4a003a823e8d619ff0c80ae
|
7
|
+
data.tar.gz: 84a2fd356d3553979c7dbd833ec2a1b9b249cc80547ca30800e0b22119a7615461d660c96c19e4f5c11df6394e11278b6d227b6707371abefbd427d5f30b07ee
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
require 'ecs_rails_console'
|
6
|
+
|
7
|
+
$LOAD_PATH.push File.expand_path('../lib', __dir__)
|
8
|
+
|
9
|
+
options = {
|
10
|
+
environment: 'production',
|
11
|
+
command: 'bin/rails console'
|
12
|
+
}
|
13
|
+
|
14
|
+
opts = OptionParser.new do |option|
|
15
|
+
option.banner = 'Usage: ecs_rails_console [options]'
|
16
|
+
|
17
|
+
option.on('-g', '--generate-config', 'Generate config file') do
|
18
|
+
template = File.expand_path('../config/ecs_rails_console.yml', __dir__)
|
19
|
+
config_file = 'config/ecs_rails_console.yml'
|
20
|
+
|
21
|
+
if File.exist?(config_file)
|
22
|
+
puts 'Configuration file already exists and will be kept untouched.'
|
23
|
+
else
|
24
|
+
FileUtils.mkdir_p(File.dirname(config_file))
|
25
|
+
FileUtils.cp(template, "#{Dir.pwd}/#{config_file}")
|
26
|
+
puts "File generated: #{config_file}"
|
27
|
+
end
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
|
31
|
+
option.on('-h', '--help', 'Display this help') do
|
32
|
+
puts option
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
option.on('-eENVIRONMENT', '--environment=ENVIRONMENT', 'Rails environment') do |environment|
|
37
|
+
options[:environment] = environment
|
38
|
+
end
|
39
|
+
|
40
|
+
option.on('-v', '--version', 'Display version') do
|
41
|
+
require 'ecs_rails_console/version'
|
42
|
+
puts EcsRailsConsole::VERSION
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
begin
|
48
|
+
opts.parse!
|
49
|
+
rescue OptionParser::InvalidOption => e
|
50
|
+
puts e
|
51
|
+
puts
|
52
|
+
puts opts
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
|
56
|
+
options[:command] = ARGV.join(' ') unless ARGV.empty?
|
57
|
+
|
58
|
+
begin
|
59
|
+
EcsRailsConsole::Cli.run!(options)
|
60
|
+
rescue Gem::LoadError
|
61
|
+
puts 'ecs_rails_console is not in your Gemfile.'
|
62
|
+
exit 1
|
63
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "yaml"
|
5
|
+
|
6
|
+
module EcsRailsConsole
|
7
|
+
CONFIG_FILE = "#{Dir.pwd}/config/ecs_rails_console.yml"
|
8
|
+
SSH_OPTIONS = '-tq -oStrictHostKeyChecking=no'
|
9
|
+
|
10
|
+
class Cli < Core
|
11
|
+
def self.run!(options)
|
12
|
+
new(options).run!
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(options)
|
16
|
+
super()
|
17
|
+
@environment = options[:environment]
|
18
|
+
@command = options[:command]
|
19
|
+
end
|
20
|
+
|
21
|
+
def run!
|
22
|
+
puts "Cluster name: #{cluster_name}"
|
23
|
+
|
24
|
+
task_description = run_task
|
25
|
+
|
26
|
+
public_ip = get_public_ip(task_description)
|
27
|
+
|
28
|
+
puts "it is running on: #{public_ip}"
|
29
|
+
|
30
|
+
system("ssh #{SSH_OPTIONS} #{ssh_user}@#{public_ip} 'cd /app ; #{command}'")
|
31
|
+
rescue Aws::ECS::Errors::ExpiredTokenException
|
32
|
+
puts "\nHey, it seems your token expired. Authenticate on AWS give another try."
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :environment, :command
|
38
|
+
|
39
|
+
def aws_credentials
|
40
|
+
config.slice(
|
41
|
+
"profile",
|
42
|
+
"access_key_id",
|
43
|
+
"secret_access_key",
|
44
|
+
"region"
|
45
|
+
).transform_keys(&:to_sym)
|
46
|
+
end
|
47
|
+
|
48
|
+
def config
|
49
|
+
@config ||= YAML.load_file(CONFIG_FILE)[environment] || {}
|
50
|
+
end
|
51
|
+
|
52
|
+
def ssh_user
|
53
|
+
config[:ssh_user] || 'root'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "aws-sdk-ecs"
|
4
|
+
require "aws-sdk-ec2"
|
5
|
+
|
6
|
+
module EcsRailsConsole
|
7
|
+
class Core
|
8
|
+
private
|
9
|
+
|
10
|
+
def ecs_client
|
11
|
+
@ecs_client ||= Aws::ECS::Client.new(aws_credentials)
|
12
|
+
end
|
13
|
+
|
14
|
+
def ec2_client
|
15
|
+
@ec2_client ||= Aws::EC2::Client.new(aws_credentials)
|
16
|
+
end
|
17
|
+
|
18
|
+
def vpc_id
|
19
|
+
@vpc_id ||= begin
|
20
|
+
id = ec2_client.describe_vpcs(
|
21
|
+
{
|
22
|
+
filters: [{
|
23
|
+
name: "tag:aws:cloudformation:stack-name",
|
24
|
+
values: ["#{cluster_name}InfraStack"]
|
25
|
+
}]
|
26
|
+
}
|
27
|
+
)[:vpcs].map(&:vpc_id).first
|
28
|
+
abort "Could not find VPC" if id.empty?
|
29
|
+
|
30
|
+
id
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def subnet_ids(vpc_id)
|
35
|
+
@subnet_ids ||= begin
|
36
|
+
ids = ec2_client.describe_subnets(
|
37
|
+
{
|
38
|
+
filters: [
|
39
|
+
{name: "vpc-id", values: [vpc_id]},
|
40
|
+
{name: "tag:aws-cdk:subnet-type", values: ["Public"]}
|
41
|
+
]
|
42
|
+
}
|
43
|
+
)[:subnets].map(&:subnet_id)
|
44
|
+
abort "Could not find subnets" if ids.empty?
|
45
|
+
|
46
|
+
ids
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def console_security_group_ids(vpc_id)
|
51
|
+
@console_security_group_ids ||= begin
|
52
|
+
ids = ec2_client.describe_security_groups(
|
53
|
+
filters: [
|
54
|
+
{name: "vpc-id", values: [vpc_id]},
|
55
|
+
{name: "group-name",
|
56
|
+
values: config["security_groups"]}
|
57
|
+
]
|
58
|
+
)[:security_groups].map(&:group_id)
|
59
|
+
abort "Could not find security groups" if ids.empty?
|
60
|
+
|
61
|
+
ids
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def task_definition
|
66
|
+
@task_definition ||= begin
|
67
|
+
task_definition_name_regex = %r{.*/(#{config['task_definition']}):\d+}
|
68
|
+
task_definitions = ecs_client.list_task_definitions(status: "ACTIVE")
|
69
|
+
definition_arn = task_definitions[:task_definition_arns].detect do |arn|
|
70
|
+
arn.match(task_definition_name_regex)
|
71
|
+
end
|
72
|
+
abort "Could not find console task definition" if definition_arn.empty?
|
73
|
+
|
74
|
+
definition_arn.match(task_definition_name_regex).captures.first
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def run_task
|
79
|
+
task = ecs_client.run_task(
|
80
|
+
{
|
81
|
+
cluster: cluster_name,
|
82
|
+
launch_type: "FARGATE",
|
83
|
+
task_definition: task_definition,
|
84
|
+
network_configuration: {
|
85
|
+
awsvpc_configuration: {
|
86
|
+
subnets: subnet_ids(vpc_id),
|
87
|
+
security_groups: console_security_group_ids(vpc_id),
|
88
|
+
assign_public_ip: "ENABLED"
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
)[:tasks].first
|
93
|
+
|
94
|
+
task_id = task[:task_arn].match(%r{.*/(\w+)$}).captures.first
|
95
|
+
|
96
|
+
ecs_client
|
97
|
+
.wait_until(:tasks_running, {cluster: cluster_name, tasks: [task_id]})[:tasks]
|
98
|
+
.first
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_public_ip(task_description)
|
102
|
+
network_interface_id =
|
103
|
+
task_description[:attachments]
|
104
|
+
.first[:details]
|
105
|
+
.detect { |detail| detail[:name] == "networkInterfaceId" }[:value]
|
106
|
+
|
107
|
+
ec2_client.describe_network_interfaces(
|
108
|
+
network_interface_ids: [
|
109
|
+
network_interface_id
|
110
|
+
]
|
111
|
+
)[:network_interfaces].first[:association][:public_ip]
|
112
|
+
end
|
113
|
+
|
114
|
+
def cluster_name
|
115
|
+
@cluster_name ||= config["cluster_name"]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ecs-rails-console
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eduardo Ramos
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-04-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk-ec2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.227'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.227'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk-ecs
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.75'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.75'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: standard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1'
|
55
|
+
description: Provide a way to run Rails Console in a container running on AWS ECS
|
56
|
+
Fargate.
|
57
|
+
email:
|
58
|
+
- ramos.eduardo87@gmail.com
|
59
|
+
executables:
|
60
|
+
- ecs_rails_console
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- bin/ecs_rails_console
|
65
|
+
- lib/ecs_rails_console.rb
|
66
|
+
- lib/ecs_rails_console/cli.rb
|
67
|
+
- lib/ecs_rails_console/core.rb
|
68
|
+
- lib/ecs_rails_console/version.rb
|
69
|
+
homepage: http://rubygems.org/gems/ecs-rails-console
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
metadata: {}
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.7'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubygems_version: 3.1.4
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Run Rails Console in AWS ECS
|
92
|
+
test_files: []
|