ecs_cmd 0.1.2 → 0.1.3
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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +9 -5
- data/bin/ecs-cmd +52 -1
- data/ecs_cmd.gemspec +1 -0
- data/lib/ecs_cmd/exec.rb +46 -0
- data/lib/ecs_cmd/service.rb +59 -1
- data/lib/ecs_cmd/version.rb +1 -1
- data/lib/ecs_cmd.rb +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 364c2ce1e5efde7c1b03633a2a49538bb3e67a8b7a144ae7f64fe0cd6bf01237
|
4
|
+
data.tar.gz: acb50a84aa34496a6cead40dac6e6eac938685b59ce6d0fdf1dee7a48de065e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 499703cbf2f95e27647ed1f735523aade77009bf078161151dc4609d53ebd3551cddf87ae0d4cb530f63d5397276405caef17c6ed14060e1500bfb74bf460604
|
7
|
+
data.tar.gz: 84b96c418ac4fe57931185e3f032b5612fddb95b13b11e4c8b25fdb1672babc81f2af94837733f2b42651755ac9f5f89644cc431f027e5739f417e67a7f6f321
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ecs_cmd (0.1.
|
4
|
+
ecs_cmd (0.1.3)
|
5
|
+
aws-sdk-ec2
|
5
6
|
aws-sdk-ecs
|
6
7
|
gli (= 2.17.1)
|
7
8
|
terminal-table
|
@@ -10,14 +11,17 @@ GEM
|
|
10
11
|
remote: https://rubygems.org/
|
11
12
|
specs:
|
12
13
|
aws-eventstream (1.0.1)
|
13
|
-
aws-partitions (1.
|
14
|
-
aws-sdk-core (3.
|
14
|
+
aws-partitions (1.103.0)
|
15
|
+
aws-sdk-core (3.27.0)
|
15
16
|
aws-eventstream (~> 1.0)
|
16
17
|
aws-partitions (~> 1.0)
|
17
18
|
aws-sigv4 (~> 1.0)
|
18
19
|
jmespath (~> 1.0)
|
19
|
-
aws-sdk-
|
20
|
-
aws-sdk-core (~> 3)
|
20
|
+
aws-sdk-ec2 (1.45.0)
|
21
|
+
aws-sdk-core (~> 3, >= 3.26.0)
|
22
|
+
aws-sigv4 (~> 1.0)
|
23
|
+
aws-sdk-ecs (1.19.0)
|
24
|
+
aws-sdk-core (~> 3, >= 3.26.0)
|
21
25
|
aws-sigv4 (~> 1.0)
|
22
26
|
aws-sigv4 (1.0.3)
|
23
27
|
coderay (1.1.2)
|
data/bin/ecs-cmd
CHANGED
@@ -11,7 +11,7 @@ subcommand_option_handling :normal
|
|
11
11
|
arguments :strict
|
12
12
|
|
13
13
|
desc 'Set the aws region'
|
14
|
-
default_value 'us-east-1'
|
14
|
+
default_value ENV['AWS_DEFAULT_REGION'] || 'us-east-1'
|
15
15
|
arg_name 'region'
|
16
16
|
flag %i[r region]
|
17
17
|
|
@@ -73,6 +73,57 @@ command :'run-task' do |c|
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
desc 'SSH into Host Task is Running On'
|
77
|
+
command :ssh do |c|
|
78
|
+
c.flag %i[c cluster], desc: 'cluster name', arg_name: 'cluster', required: true
|
79
|
+
c.flag %i[s service], desc: 'service name', arg_name: 'service', required: true
|
80
|
+
c.action do |global_options, options, args|
|
81
|
+
ip = EcsCmd::Service.new(options[:c], options[:s], global_options[:region]).container_instance_ips[0]
|
82
|
+
puts "opening ssh connection to #{ip}"
|
83
|
+
EcsCmd::Exec.ssh(ip)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
desc 'Execute a Command Within a Service\'s Container'
|
88
|
+
arg_name 'command', :required
|
89
|
+
command :exec do |c|
|
90
|
+
c.flag %i[c cluster], desc: 'cluster name', arg_name: 'cluster', required: true
|
91
|
+
c.flag %i[s service], desc: 'service name', arg_name: 'service', required: true
|
92
|
+
c.action do |global_options, options, args|
|
93
|
+
service = EcsCmd::Service.new(options[:c], options[:s], global_options[:region])
|
94
|
+
ip = service.container_instance_ips[0]
|
95
|
+
task_family = service.task_family
|
96
|
+
command = args.join(' ')
|
97
|
+
EcsCmd::Exec.execute(task_family, ip, command)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
desc "Open a Shell Inside a Service's Container"
|
102
|
+
command 'shell' do |c|
|
103
|
+
c.flag %i[c cluster], desc: 'cluster name', arg_name: 'cluster', required: true
|
104
|
+
c.flag %i[s service], desc: 'service name', arg_name: 'service', required: true
|
105
|
+
c.switch %i[sh], desc: 'use sh instead of bash', default_value: false
|
106
|
+
c.action do |global_options, options, args|
|
107
|
+
service = EcsCmd::Service.new(options[:c], options[:s], global_options[:region])
|
108
|
+
ip = service.container_instance_ips[0]
|
109
|
+
task_family = service.task_family
|
110
|
+
shell = options[:sh] ? 'sh' : 'bash'
|
111
|
+
EcsCmd::Exec.shell(task_family, ip, shell)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
desc "Tail Logs From a Service's Container"
|
116
|
+
command 'logs' do |c|
|
117
|
+
c.flag %i[c cluster], desc: 'cluster name', arg_name: 'cluster', required: true
|
118
|
+
c.flag %i[s service], desc: 'service name', arg_name: 'service', required: true
|
119
|
+
c.flag %i[l lines], desc: 'number of historical lines to tail', arg_name: 'lines', default_value: 30, required: false
|
120
|
+
c.action do |global_options, options, args|
|
121
|
+
service = EcsCmd::Service.new(options[:c], options[:s], global_options[:region])
|
122
|
+
ip = service.container_instance_ips[0]
|
123
|
+
task_family = service.task_family
|
124
|
+
EcsCmd::Exec.logs(task_family, ip, options[:lines])
|
125
|
+
end
|
126
|
+
end
|
76
127
|
# desc 'Describe complete here'
|
77
128
|
# arg_name 'Describe arguments to complete here'
|
78
129
|
# command :complete do |c|
|
data/ecs_cmd.gemspec
CHANGED
@@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.bindir = 'bin'
|
32
32
|
spec.executables << 'ecs-cmd'
|
33
33
|
spec.require_paths = ['lib']
|
34
|
+
spec.add_runtime_dependency 'aws-sdk-ec2'
|
34
35
|
spec.add_runtime_dependency 'aws-sdk-ecs'
|
35
36
|
spec.add_runtime_dependency 'gli', '2.17.1'
|
36
37
|
spec.add_runtime_dependency 'terminal-table'
|
data/lib/ecs_cmd/exec.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'aws-sdk-ec2'
|
2
|
+
require 'aws-sdk-ecs'
|
3
|
+
require 'open3'
|
4
|
+
require 'shellwords'
|
5
|
+
|
6
|
+
module EcsCmd
|
7
|
+
module Exec
|
8
|
+
class << self
|
9
|
+
# move this to a config
|
10
|
+
def ssh_cmd(ip)
|
11
|
+
cmd = 'ssh -tt -o StrictHostKeyChecking=no '
|
12
|
+
cmd << ip.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def ssh(ip)
|
16
|
+
exec(ssh_cmd(ip))
|
17
|
+
end
|
18
|
+
|
19
|
+
# used to run arbitrary command inside a container
|
20
|
+
def execute(task_family, ip, command)
|
21
|
+
cmd = "docker exec -i -t `#{docker_ps_task(task_family)}` #{command}"
|
22
|
+
Open3.popen2e(ssh_cmd(ip) + " '#{cmd}' ") do |stdin, stdout, stderr, status_thread|
|
23
|
+
stdout.each_line do |line|
|
24
|
+
puts line
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# used to open a shell within a container?
|
30
|
+
def shell(task_family, ip, shell='bash')
|
31
|
+
cmd = "docker exec -i -t `#{docker_ps_task(task_family)}` #{shell}"
|
32
|
+
exec(ssh_cmd(ip) + " '#{cmd}' ")
|
33
|
+
end
|
34
|
+
|
35
|
+
def logs(task_family, ip, lines)
|
36
|
+
cmd = "docker logs -f --tail=#{lines} `#{docker_ps_task(task_family)}`"
|
37
|
+
exec(ssh_cmd(ip) + " '#{cmd}' ")
|
38
|
+
end
|
39
|
+
|
40
|
+
# docker ps command to get container id
|
41
|
+
def docker_ps_task(task_family)
|
42
|
+
"docker ps -n 1 -q --filter name=#{Shellwords.shellescape(task_family)}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/ecs_cmd/service.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
require 'aws-sdk-ecs'
|
2
|
+
require 'aws-sdk-ec2'
|
2
3
|
require 'terminal-table'
|
3
4
|
|
4
5
|
module EcsCmd
|
5
6
|
class Service
|
6
7
|
def initialize(cluster, name, region)
|
7
8
|
@client = Aws::ECS::Client.new(region: region)
|
9
|
+
@ec2_client = Aws::EC2::Client.new(region: region)
|
10
|
+
@cluster = cluster
|
11
|
+
@name = name
|
8
12
|
@service_stats = @client.describe_services(cluster: cluster, services: [name])[0]
|
9
13
|
raise 'service does not appear to exist' if @service_stats.empty?
|
10
14
|
end
|
@@ -30,7 +34,7 @@ module EcsCmd
|
|
30
34
|
t << ['updated at', e['updated_at']]
|
31
35
|
t << ["\n"]
|
32
36
|
end
|
33
|
-
table = Terminal::Table.new headings: ['DEPLOYMENTS'], rows: t
|
37
|
+
table = Terminal::Table.new headings: ['DEPLOYMENTS', ''], rows: t
|
34
38
|
table
|
35
39
|
end
|
36
40
|
|
@@ -54,6 +58,50 @@ module EcsCmd
|
|
54
58
|
@service_stats[0]['task_definition']
|
55
59
|
end
|
56
60
|
|
61
|
+
def task_family
|
62
|
+
# known issue, won't work with / in task family names
|
63
|
+
# TODO: improve this later
|
64
|
+
@service_stats[0]['task_definition'].split('/')[1].split(':')[0]
|
65
|
+
end
|
66
|
+
|
67
|
+
def tasks
|
68
|
+
@client.list_tasks(cluster: @cluster, service_name: @name)[0]
|
69
|
+
end
|
70
|
+
|
71
|
+
def container_instances
|
72
|
+
instances = []
|
73
|
+
@client.describe_tasks(cluster: @cluster, tasks: tasks)[0].each do |e|
|
74
|
+
instances << e[:container_instance_arn]
|
75
|
+
end
|
76
|
+
instances
|
77
|
+
end
|
78
|
+
|
79
|
+
def container_instance_id(arn)
|
80
|
+
instance = [arn.to_s]
|
81
|
+
@client.describe_container_instances(cluster: @cluster, container_instances: instance)[0][0][:ec2_instance_id]
|
82
|
+
end
|
83
|
+
|
84
|
+
def container_instance_ids
|
85
|
+
ids = []
|
86
|
+
@client.describe_container_instances(cluster: @cluster, container_instances: container_instances)[0].each do |e|
|
87
|
+
ids << e[:ec2_instance_id]
|
88
|
+
end
|
89
|
+
ids.uniq
|
90
|
+
end
|
91
|
+
|
92
|
+
def container_instance_ip(instance_id)
|
93
|
+
id = [instance_id]
|
94
|
+
@ec2_client.describe_instances(instance_ids: id)[:reservations][0][:instances][0][:private_ip_address]
|
95
|
+
end
|
96
|
+
|
97
|
+
def container_instance_ips
|
98
|
+
ips = []
|
99
|
+
@ec2_client.describe_instances(instance_ids: container_instance_ids)[:reservations][0][:instances].each do |e|
|
100
|
+
ips << e[:private_ip_address]
|
101
|
+
end
|
102
|
+
ips
|
103
|
+
end
|
104
|
+
|
57
105
|
def health_check_grace_period
|
58
106
|
@service_stats[0]['health_check_grace_period_seconds']
|
59
107
|
end
|
@@ -68,6 +116,15 @@ module EcsCmd
|
|
68
116
|
@service_stats[0]['service_name']
|
69
117
|
end
|
70
118
|
|
119
|
+
def list_container_instances
|
120
|
+
t = []
|
121
|
+
container_instances.each do |e|
|
122
|
+
t << [container_instance_id(e), container_instance_ip(container_instance_id(e))]
|
123
|
+
end
|
124
|
+
table = Terminal::Table.new headings: ['INSTANCE ID', 'IP'], rows: t
|
125
|
+
table
|
126
|
+
end
|
127
|
+
|
71
128
|
def list_service
|
72
129
|
row1 = []
|
73
130
|
row1 << [name, status, running_count, desired_count, pending_count,
|
@@ -80,6 +137,7 @@ module EcsCmd
|
|
80
137
|
table2 = Terminal::Table.new headings: ['TASK DEFINITION'], rows: row2
|
81
138
|
puts table1
|
82
139
|
puts table2
|
140
|
+
puts list_container_instances
|
83
141
|
puts deployments
|
84
142
|
end
|
85
143
|
end
|
data/lib/ecs_cmd/version.rb
CHANGED
data/lib/ecs_cmd.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ecs_cmd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Schaaff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-10 00:00:00.000000000 Z
|
12
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: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: aws-sdk-ecs
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -132,6 +146,7 @@ files:
|
|
132
146
|
- ecs_cmd.gemspec
|
133
147
|
- lib/ecs_cmd.rb
|
134
148
|
- lib/ecs_cmd/clusters.rb
|
149
|
+
- lib/ecs_cmd/exec.rb
|
135
150
|
- lib/ecs_cmd/run_task.rb
|
136
151
|
- lib/ecs_cmd/service.rb
|
137
152
|
- lib/ecs_cmd/services.rb
|