contexto 0.3.1 → 0.4.0
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/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