contexto 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +43 -94
- data/bin/contexto +2 -5
- data/lib/contexto/contextualize.rb +76 -100
- data/lib/contexto/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9d853b62cb8229724967564e62e2859f8beca0f
|
4
|
+
data.tar.gz: c432ccfaa18265460d64091e55c4cb35576c4306
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04c68752563ed98910f38857298457ab690a5e09f6bab7797409226747b9bf874c949a284c3f24bde25b3ffc56cff875bce93fd364f2f3d8b2bab264af22aa55
|
7
|
+
data.tar.gz: a52c31323a4499e5869f37f19195c67d72335b11c1290a2d6d900e2926354725219014cd6bbb9f0c098be2abe8a8df872d964059fc72a00f2f2929e7a9130a8b
|
data/README.md
CHANGED
@@ -12,111 +12,60 @@ $ gem install contexto
|
|
12
12
|
|
13
13
|
## Usage
|
14
14
|
|
15
|
-
Run the binary to
|
16
|
-
|
17
|
-
### Cluster
|
18
|
-
|
19
|
-
```shell
|
20
|
-
$ contexto -c sandbox
|
21
|
-
|
22
|
-
** Contexto Contextualizes **
|
23
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
24
|
-
|
25
|
-
Cluster sandbox
|
26
|
-
|
27
|
-
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
|
28
|
-
┃ Name ┃ Status ┃ Instances ┃ Services ┃ RunningTasks ┃ PendingTasks ┃
|
29
|
-
┣━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━┫
|
30
|
-
┃ sandbox ┃ ACTIVE ┃ 4 ┃ 3 ┃ 3 ┃ 0 ┃
|
31
|
-
┗━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┛
|
32
|
-
```
|
33
|
-
|
34
|
-
### Service
|
15
|
+
Run the binary to connect to a container in a specific cluster and
|
16
|
+
service.
|
35
17
|
|
36
18
|
```shell
|
37
|
-
$ contexto
|
19
|
+
$ contexto
|
38
20
|
|
39
|
-
** Contexto Contextualizes **
|
40
21
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
41
|
-
|
42
|
-
Cluster sandbox
|
43
|
-
|
44
|
-
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
|
45
|
-
┃ Name ┃ Status ┃ Instances ┃ Services ┃ RunningTasks ┃ PendingTasks ┃
|
46
|
-
┣━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━┫
|
47
|
-
┃ sandbox ┃ ACTIVE ┃ 4 ┃ 3 ┃ 3 ┃ 0 ┃
|
48
|
-
┗━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┛
|
49
|
-
|
50
|
-
Service backend-app
|
51
|
-
|
52
|
-
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
|
53
|
-
┃ Name ┃ Status ┃ Desired ┃ Running ┃ Pending ┃
|
54
|
-
┣━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━┫
|
55
|
-
┃ backend-app ┃ ACTIVE ┃ 1 ┃ 1 ┃ 0 ┃
|
56
|
-
┗━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┛
|
57
|
-
|
58
|
-
Containers
|
59
|
-
|
60
|
-
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
|
61
|
-
┃ Container ┃ Status ┃ IP ┃
|
62
|
-
┣━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━┫
|
63
|
-
┃ sidekiq ┃ RUNNING ┃ 10.2.1.218 ┃
|
64
|
-
┣━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━┫
|
65
|
-
┃ app ┃ RUNNING ┃ 10.2.1.218 ┃
|
66
|
-
┗━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┛
|
67
|
-
```
|
68
|
-
|
69
|
-
### SSH
|
70
|
-
|
71
|
-
You can also get Contexto to connect via SSH to a Bash shell, or a Rails console.
|
72
|
-
|
73
|
-
#### Bash shell on container
|
74
|
-
|
75
|
-
To connect to a Bash shell in a specific container, specify the cluster, service and container and the `--type` flag.
|
76
|
-
|
77
|
-
```shell
|
78
|
-
$ contexto -c sandbox -s backend-app -v app -t=bash
|
79
|
-
|
80
22
|
** Contexto Contextualizes **
|
81
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
82
|
-
circleci@4e65666c9414:/usr/src/app$
|
83
|
-
```
|
84
|
-
|
85
|
-
#### Rails console
|
86
|
-
|
87
|
-
To connect to a Rails console, specify the cluster, service and container and the `--type` flag.
|
88
|
-
|
89
|
-
```shell
|
90
|
-
$ contexto -c sandbox -s backend-app -v app --type=console
|
91
23
|
|
92
|
-
|
93
|
-
|
24
|
+
Clusters :
|
25
|
+
1. production
|
26
|
+
2. sandbox
|
27
|
+
3. nah
|
28
|
+
Please choose a cluster? 1
|
29
|
+
|
30
|
+
Services :
|
31
|
+
1. backend-app
|
32
|
+
2. starter-site
|
33
|
+
3. backend-authn
|
34
|
+
4. logspout
|
35
|
+
5. wombat
|
36
|
+
6. nah
|
37
|
+
Please choose a service? 1
|
94
38
|
|
95
|
-
|
96
|
-
|
97
|
-
|
39
|
+
Containers
|
40
|
+
┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
|
41
|
+
┃ Container ┃ Status ┃ IP ┃
|
42
|
+
┣━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━┫
|
43
|
+
┃ sidekiq ┃ RUNNING ┃ 10.1.2.25 ┃
|
44
|
+
┣━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━╊━━━━━━━━━━━━━━━┫
|
45
|
+
┃ app ┃ RUNNING ┃ 10.1.2.25 ┃
|
46
|
+
┗━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━┛
|
47
|
+
|
48
|
+
Containers :
|
49
|
+
1. sidekiq
|
50
|
+
2. app
|
51
|
+
3. nah
|
52
|
+
Please choose a container? 1
|
53
|
+
|
54
|
+
Do you want to connect to container sidekiq? :
|
55
|
+
1. console
|
56
|
+
2. bash
|
57
|
+
3. ssh
|
58
|
+
4. nah
|
59
|
+
Please choose a connection type?
|
98
60
|
```
|
99
61
|
|
100
|
-
|
101
|
-
|
102
|
-
You can get an SSH shell on the Docker host too using the `--type` task.
|
103
|
-
|
104
|
-
```shell
|
105
|
-
$ contexto -c sandbox -s backend-app -v sidekiq --t=ssh
|
106
|
-
|
107
|
-
** Contexto Contextualizes **
|
108
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
109
|
-
|
110
|
-
Last login: Sat Apr 1 18:58:38 2017 from ip-172-31-12-234.ec2.internal
|
62
|
+
You can get Contexto to connect via SSH to a Bash shell, or a Rails console.
|
111
63
|
|
112
|
-
|
113
|
-
|
114
|
-
____|\___|____/
|
64
|
+
You can also specify a cluster and service to take a shortcut to a
|
65
|
+
specific set of containers.
|
115
66
|
|
116
|
-
|
117
|
-
|
118
|
-
Run "sudo yum update" to apply all updates.
|
119
|
-
[ec2-user@ip-10-2-1-221 ~]$
|
67
|
+
```bash
|
68
|
+
$ contexto -c production -s backend-app
|
120
69
|
```
|
121
70
|
|
122
71
|
## Development
|
data/bin/contexto
CHANGED
@@ -11,14 +11,11 @@ require 'English'
|
|
11
11
|
$stderr.sync = true
|
12
12
|
|
13
13
|
options = {}
|
14
|
-
options[:connection_type] = false
|
15
14
|
|
16
15
|
optparse = OptionParser.new do |opts|
|
17
16
|
opts.banner = 'Usage: contexto [options]'
|
18
17
|
opts.on('-c', '--cluster CLUSTER', 'Cluster') { |v| options[:cluster] = v }
|
19
18
|
opts.on('-s', '--service SERVICE', 'Service') { |v| options[:service] = v }
|
20
|
-
opts.on('-v', '--container CONTAINER', 'Container') { |v| options[:container] = v }
|
21
|
-
opts.on('-t', "--type [TYPE]", [:console, :ssh, :bash], "Select connection type (console, ssh, bash)") { |v| options[:connection_type] = v }
|
22
19
|
opts.on_tail("-h", "--help", "Show this message") do
|
23
20
|
puts opts
|
24
21
|
exit
|
@@ -27,8 +24,8 @@ end
|
|
27
24
|
|
28
25
|
begin
|
29
26
|
optparse.parse!
|
30
|
-
if options[:
|
31
|
-
raise OptionParser::MissingArgument.new("If you want to connect to a
|
27
|
+
if options[:service] && !options[:cluster]
|
28
|
+
raise OptionParser::MissingArgument.new("If you want to connect to a service you need to specify a cluster name.")
|
32
29
|
puts "\n"
|
33
30
|
end
|
34
31
|
rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument
|
@@ -5,123 +5,73 @@ require 'highline'
|
|
5
5
|
module Contexto
|
6
6
|
# ECS class
|
7
7
|
class Contextualize
|
8
|
-
attr_reader :display, :cluster, :service
|
8
|
+
attr_reader :display, :cluster, :service
|
9
9
|
|
10
10
|
def initialize(params = {})
|
11
11
|
@cluster = params.fetch(:cluster) if params[:cluster]
|
12
12
|
@service = params.fetch(:service) if params[:service]
|
13
|
-
@container = params.fetch(:container) if params[:container]
|
14
|
-
@connection_type = params.fetch(:connection_type) if params[:connection_type]
|
15
13
|
@display = Contexto::Display.new
|
16
14
|
end
|
17
15
|
|
18
16
|
def run
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def show
|
28
|
-
if !cluster
|
29
|
-
show_clusters
|
30
|
-
return
|
31
|
-
elsif cluster
|
32
|
-
show_cluster
|
33
|
-
puts "\n"
|
34
|
-
end
|
35
|
-
if !service
|
36
|
-
show_services
|
37
|
-
return
|
38
|
-
elsif service
|
39
|
-
puts "\n"
|
40
|
-
show_service
|
41
|
-
end
|
42
|
-
if !container
|
43
|
-
show_tasks
|
44
|
-
return
|
45
|
-
elsif container
|
46
|
-
puts "\n"
|
47
|
-
show_tasks
|
17
|
+
if (cluster || service)
|
18
|
+
if (cluster && !service)
|
19
|
+
select_services(cluster)
|
20
|
+
elsif (cluster && service)
|
21
|
+
select_tasks(cluster, service)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
select_clusters
|
48
25
|
end
|
49
26
|
end
|
50
27
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
28
|
+
def select_clusters
|
29
|
+
clusters = list_clusters
|
30
|
+
cli.choose do |menu|
|
31
|
+
puts "\n"
|
32
|
+
menu.header = "Clusters "
|
33
|
+
menu.prompt = "Please choose a cluster? "
|
34
|
+
clusters.each do |cluster|
|
35
|
+
c = esplit(cluster)
|
36
|
+
menu.choice(c) { select_services(c) }
|
37
|
+
end
|
38
|
+
menu.choice(:nah) { return }
|
39
|
+
end
|
60
40
|
end
|
61
41
|
|
62
|
-
def
|
63
|
-
|
42
|
+
def select_services(cluster)
|
43
|
+
services = list_services(cluster)
|
64
44
|
cli.choose do |menu|
|
65
45
|
puts "\n"
|
66
|
-
menu.header = "
|
67
|
-
menu.prompt = "Please choose a
|
68
|
-
|
69
|
-
|
70
|
-
|
46
|
+
menu.header = "Services "
|
47
|
+
menu.prompt = "Please choose a service? "
|
48
|
+
services.each do |service|
|
49
|
+
s = esplit(service)
|
50
|
+
menu.choice(s) { select_tasks(cluster, s) }
|
51
|
+
end
|
71
52
|
menu.choice(:nah) { return }
|
72
53
|
end
|
73
54
|
end
|
74
55
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
title = "Cluster #{cluster}"
|
88
|
-
headings = %w(Name Status Instances Services RunningTasks PendingTasks)
|
89
|
-
cluster = describe_clusters
|
90
|
-
rows = []
|
91
|
-
rows << [cluster[:cluster_name], cluster[:status], cluster[:registered_container_instances_count], cluster[:active_services_count], cluster[:running_tasks_count], cluster[:pending_tasks_count]]
|
92
|
-
@display.create_display(title, headings, rows)
|
93
|
-
end
|
94
|
-
|
95
|
-
def show_services
|
96
|
-
title = "Services"
|
97
|
-
headings = %w(Name)
|
98
|
-
services = list_services
|
99
|
-
rows = []
|
100
|
-
services.each do |service|
|
101
|
-
rows << [service.split('/')[-1]]
|
56
|
+
def select_tasks(cluster, service)
|
57
|
+
show_tasks(cluster, service)
|
58
|
+
task = describe_tasks(cluster, service)
|
59
|
+
containers = task[:containers]
|
60
|
+
cli.choose do |menu|
|
61
|
+
puts "\n"
|
62
|
+
menu.header = "Containers "
|
63
|
+
menu.prompt = "Please choose a container? "
|
64
|
+
containers.each do |container|
|
65
|
+
menu.choice(container[:name]) { prompt_endpoint(cluster, service, container[:name]) }
|
66
|
+
end
|
67
|
+
menu.choice(:nah) { return }
|
102
68
|
end
|
103
|
-
@display.create_display(title, headings, rows)
|
104
|
-
end
|
105
|
-
|
106
|
-
def show_service
|
107
|
-
title = "Service #{service}"
|
108
|
-
headings = %w(Name Status Desired Running Pending)
|
109
|
-
service = describe_services
|
110
|
-
rows = []
|
111
|
-
rows << [service[:service_name], service[:status], service[:desired_count], service[:running_count], service[:pending_count]]
|
112
|
-
@display.create_display(title, headings, rows)
|
113
|
-
rescue Aws::ECS::Errors::ServiceNotFoundException
|
114
|
-
puts 'Service not found'
|
115
69
|
end
|
116
70
|
|
117
|
-
def show_tasks
|
118
|
-
task = describe_tasks
|
119
|
-
|
120
|
-
|
121
|
-
else
|
122
|
-
containers = task[:containers]
|
123
|
-
end
|
124
|
-
ec2_instance_id = describe_container_instance(task[:container_instance_arn])
|
71
|
+
def show_tasks(cluster, service)
|
72
|
+
task = describe_tasks(cluster, service)
|
73
|
+
containers = task[:containers]
|
74
|
+
ec2_instance_id = describe_container_instance(cluster, task[:container_instance_arn])
|
125
75
|
title = 'Containers'
|
126
76
|
headings = %w(Container Status IP)
|
127
77
|
rows = []
|
@@ -131,6 +81,24 @@ module Contexto
|
|
131
81
|
@display.create_display(title, headings, rows)
|
132
82
|
end
|
133
83
|
|
84
|
+
def prompt_endpoint(cluster, service, container)
|
85
|
+
cli.choose do |menu|
|
86
|
+
puts "\n"
|
87
|
+
menu.header = "Do you want to connect to container #{container}? "
|
88
|
+
menu.prompt = "Please choose a connection type? "
|
89
|
+
menu.choice(:console) { connect(cluster, service, container).console }
|
90
|
+
menu.choice(:bash) { connect(cluster, service, container).bash }
|
91
|
+
menu.choice(:ssh) { connect(cluster, service, container).ssh }
|
92
|
+
menu.choice(:nah) { return }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def connect(cluster, service, container)
|
97
|
+
task = describe_tasks(cluster, service)
|
98
|
+
ec2_instance_id = describe_container_instance(cluster, task[:container_instance_arn])
|
99
|
+
Contexto::SSH.new(describe_instances(ec2_instance_id), cluster, service, container)
|
100
|
+
end
|
101
|
+
|
134
102
|
def list_clusters
|
135
103
|
resp = ecs_client.list_clusters
|
136
104
|
resp.cluster_arns
|
@@ -145,7 +113,7 @@ module Contexto
|
|
145
113
|
resp.clusters[0].to_h
|
146
114
|
end
|
147
115
|
|
148
|
-
def list_services
|
116
|
+
def list_services(cluster)
|
149
117
|
resp = ecs_client.list_services(
|
150
118
|
cluster: cluster
|
151
119
|
)
|
@@ -162,15 +130,15 @@ module Contexto
|
|
162
130
|
resp.services[0].to_h
|
163
131
|
end
|
164
132
|
|
165
|
-
def describe_tasks
|
133
|
+
def describe_tasks(cluster, service)
|
166
134
|
resp = ecs_client.describe_tasks(
|
167
135
|
cluster: cluster,
|
168
|
-
tasks: [task_arn]
|
136
|
+
tasks: [task_arn(cluster, service)]
|
169
137
|
)
|
170
138
|
resp.tasks[0].to_h
|
171
139
|
end
|
172
140
|
|
173
|
-
def task_arn
|
141
|
+
def task_arn(cluster, service)
|
174
142
|
resp = ecs_client.list_tasks(
|
175
143
|
cluster: cluster,
|
176
144
|
service_name: service
|
@@ -178,7 +146,7 @@ module Contexto
|
|
178
146
|
resp.task_arns[0]
|
179
147
|
end
|
180
148
|
|
181
|
-
def describe_container_instance(container_instance_arn)
|
149
|
+
def describe_container_instance(cluster, container_instance_arn)
|
182
150
|
resp = ecs_client.describe_container_instances(
|
183
151
|
cluster: cluster,
|
184
152
|
container_instances: [
|
@@ -195,6 +163,14 @@ module Contexto
|
|
195
163
|
resp.reservations[0].instances[0].private_ip_address
|
196
164
|
end
|
197
165
|
|
166
|
+
def esplit(name)
|
167
|
+
name.split('/')[-1]
|
168
|
+
end
|
169
|
+
|
170
|
+
def cli
|
171
|
+
HighLine.new
|
172
|
+
end
|
173
|
+
|
198
174
|
def region_name
|
199
175
|
ENV['AWS_REGION'] || 'us-east-1'
|
200
176
|
end
|
data/lib/contexto/version.rb
CHANGED