ecs_cmd 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47a57e9187e720bc1b0d82d6fb1509f0f4fcb70bf593b18838d46d2966b0d8d8
4
- data.tar.gz: 3934d820b3a774b45cc675c4b1f7fc36f9d0fdf35d71f617c00ea57e05679fcd
3
+ metadata.gz: 364c2ce1e5efde7c1b03633a2a49538bb3e67a8b7a144ae7f64fe0cd6bf01237
4
+ data.tar.gz: acb50a84aa34496a6cead40dac6e6eac938685b59ce6d0fdf1dee7a48de065e2
5
5
  SHA512:
6
- metadata.gz: b3de007e28f83c6d76db7834e28a141ad1162754f458137397e91d362e172970ce7d4c5679338fc3ef60cf3235ad75fbd3867eb9f757e25361835016eb9c028a
7
- data.tar.gz: ed7906caeb48818e79729374ebf355da530b5f8a49f6631cf7babdd1caff7aa9ea2ab38ed693dead570ffe62e8ab6987cab587441e5ae165bc3f980d9ed7de3d
6
+ metadata.gz: 499703cbf2f95e27647ed1f735523aade77009bf078161151dc4609d53ebd3551cddf87ae0d4cb530f63d5397276405caef17c6ed14060e1500bfb74bf460604
7
+ data.tar.gz: 84b96c418ac4fe57931185e3f032b5612fddb95b13b11e4c8b25fdb1672babc81f2af94837733f2b42651755ac9f5f89644cc431f027e5739f417e67a7f6f321
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ .vscode
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ecs_cmd (0.1.2)
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.100.0)
14
- aws-sdk-core (3.24.1)
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-ecs (1.17.0)
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'
@@ -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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module EcsCmd
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
data/lib/ecs_cmd.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'ecs_cmd/version'
2
2
  require 'ecs_cmd/clusters.rb'
3
+ require 'ecs_cmd/exec.rb'
3
4
  require 'ecs_cmd/run_task.rb'
4
5
  require 'ecs_cmd/services.rb'
5
6
  require 'ecs_cmd/service.rb'
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.2
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-08-21 00:00:00.000000000 Z
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