simplygenius-atmos 0.11.3 → 0.11.4
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/CHANGELOG.md +7 -0
- data/lib/simplygenius/atmos/commands/container.rb +45 -21
- data/lib/simplygenius/atmos/commands/user.rb +1 -1
- data/lib/simplygenius/atmos/config.rb +0 -2
- data/lib/simplygenius/atmos/providers/aws/container_manager.rb +82 -1
- data/lib/simplygenius/atmos/settings_hash.rb +11 -7
- data/lib/simplygenius/atmos/version.rb +1 -1
- data/templates/new/config/atmos/runtime.yml +45 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ca7971744542f8e7e8b9892a57425edbef56c418b22617295f539a4e737a62d
|
4
|
+
data.tar.gz: 7a2e7501ec94b617eb0bb3c1d91a37b76884ca57ebc079d4a14e367b41827063
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4fff280b4474c41e9329bc49ecfdd7ae215fbb2fd33b45161e94056126710bdca0d8461379029ed45ae23672724cce10cd61d7b79413190738d8b8a3121ad42d
|
7
|
+
data.tar.gz: 6d9801ed068c5c007d67e7f0c086134db4aa396a7e6b9c0a983cfa2ac3711ac7c4bd8eeb6092b82011362ed25d79a4bb9f7dfce243470ce928232a256f88efee
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
0.11.4 (11/27/2019)
|
2
|
+
-------------------
|
3
|
+
|
4
|
+
* add the ability to spawn a console for any service container [0d1764e](https://github.com/simplygenius/atmos/commit/0d1764e)
|
5
|
+
* allow escaping atmos interpolations [3d8b59e](https://github.com/simplygenius/atmos/commit/3d8b59e)
|
6
|
+
|
7
|
+
|
1
8
|
0.11.3 (11/12/2019)
|
2
9
|
-------------------
|
3
10
|
|
@@ -14,14 +14,14 @@ module SimplyGenius
|
|
14
14
|
"Manages containers in the cloud provider"
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
option ["-c", "--cluster"],
|
18
|
+
"CLUSTER", "The cluster name\n",
|
19
|
+
required: true
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
required: true
|
21
|
+
option ["-r", "--role"],
|
22
|
+
"ROLE", "The role to assume when deploying\n"
|
22
23
|
|
23
|
-
|
24
|
-
"ROLE", "The role to assume when deploying\n"
|
24
|
+
subcommand "push", "Only push a container image without activating it" do
|
25
25
|
|
26
26
|
option ["-i", "--image"],
|
27
27
|
"IMAGE", "The local container image to deploy\nDefaults to service/task name"
|
@@ -54,15 +54,8 @@ module SimplyGenius
|
|
54
54
|
|
55
55
|
subcommand "activate", "Activate a container that has already been pushed" do
|
56
56
|
|
57
|
-
option ["-c", "--cluster"],
|
58
|
-
"CLUSTER", "The cluster name\n",
|
59
|
-
required: true
|
60
|
-
|
61
|
-
option ["-r", "--role"],
|
62
|
-
"ROLE", "The role to assume when deploying\n"
|
63
|
-
|
64
57
|
option ["-v", "--revision"],
|
65
|
-
"REVISION", "Use the given revision of the pushed image
|
58
|
+
"REVISION", "Use the given revision of the pushed image\nto activate\n"
|
66
59
|
|
67
60
|
option ["-l", "--list"],
|
68
61
|
:flag, "List the most recent pushed images\n"
|
@@ -122,13 +115,6 @@ module SimplyGenius
|
|
122
115
|
|
123
116
|
subcommand "deploy", "Push and activate a container" do
|
124
117
|
|
125
|
-
option ["-c", "--cluster"],
|
126
|
-
"CLUSTER", "The cluster name\n",
|
127
|
-
required: true
|
128
|
-
|
129
|
-
option ["-r", "--role"],
|
130
|
-
"ROLE", "The role to assume when deploying\n"
|
131
|
-
|
132
118
|
option ["-i", "--image"],
|
133
119
|
"IMAGE", "The local container image to deploy\nDefaults to service/task name"
|
134
120
|
|
@@ -164,6 +150,44 @@ module SimplyGenius
|
|
164
150
|
end
|
165
151
|
end
|
166
152
|
|
153
|
+
subcommand "console", "Spawn a console and attach to it" do
|
154
|
+
|
155
|
+
option ["-p", "--persist"],
|
156
|
+
:flag, "Leave the task running after disconnect\n"
|
157
|
+
|
158
|
+
parameter "NAME",
|
159
|
+
"The name of the service (or task) to attach\nthe console to"
|
160
|
+
|
161
|
+
def execute
|
162
|
+
Atmos.config.provider.auth_manager.authenticate(ENV, role: role) do |auth_env|
|
163
|
+
ClimateControl.modify(auth_env) do
|
164
|
+
mgr = Atmos.config.provider.container_manager
|
165
|
+
remote_command = Array(Atmos.config['atmos.container.console.remote_command'])
|
166
|
+
remote_persist_command = Array(Atmos.config['atmos.container.console.remote_persist_command'])
|
167
|
+
log_pattern = Atmos.config['atmos.container.console.remote_log_pattern']
|
168
|
+
local_command = Atmos.config['atmos.container.console.local_command']
|
169
|
+
|
170
|
+
cmd = persist? ? remote_persist_command : remote_command
|
171
|
+
logger.debug "Running remote command: #{cmd.join(" ")}"
|
172
|
+
result = mgr.run_task(cluster, name, command: cmd, waiter_log_pattern: log_pattern)
|
173
|
+
logger.debug "Run task result: #{result}"
|
174
|
+
begin
|
175
|
+
match = result[:log_match]
|
176
|
+
local_command = local_command.collect {|c| match.names.each {|n| c = c.gsub("<#{n}>", match[n]) }; c }
|
177
|
+
system(*local_command)
|
178
|
+
ensure
|
179
|
+
if persist?
|
180
|
+
logger.info "Console disconnected, you can reconnect with: #{local_command.join(" ")}"
|
181
|
+
else
|
182
|
+
logger.info "Console complete, stopping task"
|
183
|
+
mgr.stop_task(cluster, result[:task_id])
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
167
191
|
end
|
168
192
|
|
169
193
|
end
|
@@ -14,7 +14,7 @@ module SimplyGenius
|
|
14
14
|
subcommand "create", "Create a new user" do
|
15
15
|
|
16
16
|
option ["-f", "--force"],
|
17
|
-
:flag, "forces deletion/updates for pre-existing
|
17
|
+
:flag, "forces deletion/updates for pre-existing\nresources",
|
18
18
|
default: false
|
19
19
|
|
20
20
|
option ["-l", "--login"],
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require_relative '../../../atmos'
|
2
2
|
require 'aws-sdk-ecs'
|
3
3
|
require 'aws-sdk-ecr'
|
4
|
+
require 'aws-sdk-cloudwatchlogs'
|
4
5
|
require 'open3'
|
5
6
|
|
6
7
|
module SimplyGenius
|
@@ -159,7 +160,87 @@ module SimplyGenius
|
|
159
160
|
return result
|
160
161
|
end
|
161
162
|
|
162
|
-
|
163
|
+
def run_task(cluster, name, command:, waiter_log_pattern: nil, launch_type: "FARGATE")
|
164
|
+
result = {}
|
165
|
+
|
166
|
+
ecs = ::Aws::ECS::Client.new
|
167
|
+
resp = nil
|
168
|
+
|
169
|
+
task_opts = {
|
170
|
+
count: 1,
|
171
|
+
cluster: cluster,
|
172
|
+
task_definition: name,
|
173
|
+
launch_type: launch_type,
|
174
|
+
overrides: {container_overrides: [{name: name, command: command}]}
|
175
|
+
}
|
176
|
+
|
177
|
+
defn_arn = nil
|
178
|
+
resp = ecs.describe_services(cluster: cluster, services: [name])
|
179
|
+
if resp.services.size > 0
|
180
|
+
svc = resp.services.first
|
181
|
+
task_opts[:launch_type] = svc.launch_type
|
182
|
+
task_opts[:network_configuration] = svc.network_configuration.to_h
|
183
|
+
defn_arn = svc.task_definition
|
184
|
+
logger.info "Running service task as '#{task_opts[:launch_type]}'"
|
185
|
+
else
|
186
|
+
resp = ecs.list_task_definitions(family_prefix: name, sort: 'DESC')
|
187
|
+
defn_arn = resp.task_definition_arns.first
|
188
|
+
logger.info "Running task as '#{task_opts[:launch_type]}'"
|
189
|
+
end
|
190
|
+
|
191
|
+
resp = ecs.describe_task_definition(task_definition: defn_arn)
|
192
|
+
defn = resp.task_definition
|
193
|
+
raise "Invalid Launch type '#{launch_type}'" unless (defn.requires_compatibilities + defn.compatibilities).include?(launch_type)
|
194
|
+
|
195
|
+
log_config = defn.container_definitions.first.log_configuration
|
196
|
+
log_group = nil
|
197
|
+
log_stream_prefix = nil
|
198
|
+
if log_config && log_config.log_driver == "awslogs"
|
199
|
+
log_group = log_config.options["awslogs-group"]
|
200
|
+
log_stream_prefix = log_config.options["awslogs-stream-prefix"]
|
201
|
+
end
|
202
|
+
if waiter_log_pattern && log_group.nil?
|
203
|
+
logger.error "Cannot wait on a log unless task definition uses cloudwatch for logging"
|
204
|
+
waiter_log_pattern = nil
|
205
|
+
end
|
206
|
+
|
207
|
+
resp = ecs.run_task(**task_opts)
|
208
|
+
task_arn = result[:task_arn] = resp.tasks.first.task_arn
|
209
|
+
task_id = result[:task_id] = task_arn.split('/').last
|
210
|
+
|
211
|
+
logger.info "Waiting for task to start"
|
212
|
+
ecs.wait_until(:tasks_running, cluster: cluster, tasks: [task_id])
|
213
|
+
|
214
|
+
if waiter_log_pattern
|
215
|
+
cwl = ::Aws::CloudWatchLogs::Client.new
|
216
|
+
|
217
|
+
waiter_regexp = Regexp.new(waiter_log_pattern)
|
218
|
+
log_stream = "#{log_stream_prefix}/#{name}/#{task_id}"
|
219
|
+
logger.info "Task started, looking for log pattern in group=#{log_group} stream=#{log_stream}"
|
220
|
+
log_token = nil
|
221
|
+
10.times do
|
222
|
+
resp = cwl.get_log_events(log_group_name: log_group, log_stream_name: log_stream, start_from_head: true, next_token: log_token)
|
223
|
+
resp.events.each do |e|
|
224
|
+
logger.debug("Task log #{e.timestamp}: #{e.message}")
|
225
|
+
if e.message =~ waiter_regexp
|
226
|
+
result[:log_match] = Regexp.last_match
|
227
|
+
return result # return, not break due to doubly nested iterator
|
228
|
+
end
|
229
|
+
end
|
230
|
+
log_token = resp.next_forward_token
|
231
|
+
sleep 1
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
return result
|
236
|
+
end
|
237
|
+
|
238
|
+
def stop_task(cluster, task)
|
239
|
+
ecs = ::Aws::ECS::Client.new
|
240
|
+
resp = ecs.stop_task(cluster: cluster, task: task)
|
241
|
+
end
|
242
|
+
|
243
|
+
private
|
163
244
|
|
164
245
|
def run(*args, **opts)
|
165
246
|
logger.debug("Running: #{args}")
|
@@ -12,7 +12,7 @@ module SimplyGenius
|
|
12
12
|
disable_warnings
|
13
13
|
|
14
14
|
PATH_PATTERN = /[\.\[\]]/
|
15
|
-
INTERP_PATTERN = /(
|
15
|
+
INTERP_PATTERN = /(\#?\#\{([^\}]+)\})/
|
16
16
|
|
17
17
|
attr_accessor :_root_, :error_resolver, :enable_expansion
|
18
18
|
|
@@ -84,12 +84,16 @@ module SimplyGenius
|
|
84
84
|
result.scan(INTERP_PATTERN).each do |substr, statement|
|
85
85
|
# TODO: add an explicit check for cycles instead of relying on Stack error
|
86
86
|
begin
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
87
|
+
if substr.start_with?('##')
|
88
|
+
val = substr[1..-1]
|
89
|
+
else
|
90
|
+
# TODO: be consistent with dot notation between eval and
|
91
|
+
# notation_get. eval ends up calling Hashie method_missing,
|
92
|
+
# which returns nil if a key doesn't exist, causing a nil
|
93
|
+
# exception for next item in chain, while notation_get returns
|
94
|
+
# nil gracefully for the entire chain (preferred)
|
95
|
+
val = eval(statement, binding, __FILE__)
|
96
|
+
end
|
93
97
|
rescue SystemStackError => e
|
94
98
|
raise ConfigInterpolationError.new(format_error("Cycle in interpolated config", substr))
|
95
99
|
rescue StandardError => e
|
@@ -64,6 +64,51 @@ atmos:
|
|
64
64
|
# a GUI notification
|
65
65
|
force_inline: false
|
66
66
|
|
67
|
+
# Configure the container components accessible with 'atmos container ....'
|
68
|
+
container:
|
69
|
+
# Configuration for the console subcommand
|
70
|
+
# For this to work, your service container needs to have a recent (>= 2.4)
|
71
|
+
# tmate installed. For example in a debian container:
|
72
|
+
#
|
73
|
+
# # Install locales package for tmate
|
74
|
+
# RUN apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -q -y locales
|
75
|
+
#
|
76
|
+
# # To set utf-8 locale for tmate
|
77
|
+
# RUN sed -i -e 's/# \(en_US\.UTF-8 .*\)/\1/' /etc/locale.gen && \
|
78
|
+
# dpkg-reconfigure --frontend=noninteractive locales && \
|
79
|
+
# update-locale LANG=en_US.UTF-8
|
80
|
+
# ENV LANG en_US.UTF-8
|
81
|
+
#
|
82
|
+
# # Install tmate
|
83
|
+
# RUN curl -Lo /tmp/tmate.tar.xz https://github.com/tmate-io/tmate/releases/download/2.4.0/tmate-2.4.0-static-linux-amd64.tar.xz && \
|
84
|
+
# cd /tmp && \
|
85
|
+
# tar xf /tmp/tmate.tar.xz && \
|
86
|
+
# mv tmate-2.4.0-static-linux-amd64/tmate /usr/bin/tmate && \
|
87
|
+
# rm -rf /tmp/tmate*
|
88
|
+
#
|
89
|
+
# # tmate needs ssh keys
|
90
|
+
# RUN ssh-keygen -f ~/.ssh/id_rsa -N '' -t rsa
|
91
|
+
#
|
92
|
+
console:
|
93
|
+
# The remote command to run when initiating a console (exits on disconnect)
|
94
|
+
remote_command:
|
95
|
+
- bash
|
96
|
+
- -c
|
97
|
+
- echo "set tmate-foreground-restart 0" > ~/.tmate.conf && tmate -F
|
98
|
+
# The remote command to run when initiating a console (persists on disconnect)
|
99
|
+
remote_persist_command:
|
100
|
+
- bash
|
101
|
+
- -c
|
102
|
+
- tmate -F
|
103
|
+
# The regexp to match against remote command output to extract any tokens
|
104
|
+
# needed for the client to connect. The regexp named groups (?<...>) get
|
105
|
+
# substituted within the client command (<...>)
|
106
|
+
remote_log_pattern: "^ssh session: ssh (?<token>\\w+)@nyc1.tmate.io$"
|
107
|
+
# The local command to run when initiating a console
|
108
|
+
local_command:
|
109
|
+
- ssh
|
110
|
+
- <token>@nyc1.tmate.io
|
111
|
+
|
67
112
|
# Configure terraform execution details
|
68
113
|
terraform:
|
69
114
|
# Disable module fetch from convenience plan/apply commands
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simplygenius-atmos
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Conway
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -416,6 +416,20 @@ dependencies:
|
|
416
416
|
- - ">="
|
417
417
|
- !ruby/object:Gem::Version
|
418
418
|
version: '0'
|
419
|
+
- !ruby/object:Gem::Dependency
|
420
|
+
name: aws-sdk-cloudwatchlogs
|
421
|
+
requirement: !ruby/object:Gem::Requirement
|
422
|
+
requirements:
|
423
|
+
- - ">="
|
424
|
+
- !ruby/object:Gem::Version
|
425
|
+
version: '0'
|
426
|
+
type: :runtime
|
427
|
+
prerelease: false
|
428
|
+
version_requirements: !ruby/object:Gem::Requirement
|
429
|
+
requirements:
|
430
|
+
- - ">="
|
431
|
+
- !ruby/object:Gem::Version
|
432
|
+
version: '0'
|
419
433
|
- !ruby/object:Gem::Dependency
|
420
434
|
name: os
|
421
435
|
requirement: !ruby/object:Gem::Requirement
|