wrapbox 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/wrapbox.rb +6 -2
- data/lib/wrapbox/cli.rb +1 -0
- data/lib/wrapbox/configuration.rb +6 -4
- data/lib/wrapbox/log_fetcher.rb +9 -1
- data/lib/wrapbox/log_fetcher/awslogs.rb +104 -0
- data/lib/wrapbox/log_fetcher/papertrail.rb +1 -1
- data/lib/wrapbox/runner/docker.rb +3 -5
- data/lib/wrapbox/runner/ecs.rb +13 -11
- data/lib/wrapbox/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 207f24c9cc5e7fc32e69652b7ff9f012b32da2203ac5c044b6adb755fa34ba6c
|
4
|
+
data.tar.gz: 6a1dcfd5cd2e09cba65449184f2d736074e5436419abe20b54dcb1117c8af81a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a02a9ab56bf3f0d4bdd2d24fab5acef9d41a128bbdd477f0e4cab16f2a00d90cb20d23c93bc6ec5c7416faa059eacb3dd9a46a050559b994ce772b28f1dabaeb
|
7
|
+
data.tar.gz: c0e5595b908a11924854830867af67312f851430d4b5dadf058c273178d111d63d8164a4573efc3a20bbbff8b2f6386dfca8bcb1bd829d1624004b96aa87a853
|
data/lib/wrapbox.rb
CHANGED
@@ -4,6 +4,10 @@ module Wrapbox
|
|
4
4
|
METHOD_ARGS_ENV = "WRAPBOX_METHOD_ARGS".freeze
|
5
5
|
|
6
6
|
class << self
|
7
|
+
def load_config(filename)
|
8
|
+
configs.load_yaml(filename)
|
9
|
+
end
|
10
|
+
|
7
11
|
def configs
|
8
12
|
@configs ||= ConfigRepository.new
|
9
13
|
end
|
@@ -12,12 +16,12 @@ module Wrapbox
|
|
12
16
|
yield configs
|
13
17
|
end
|
14
18
|
|
15
|
-
def run(*args, config_name: nil, **options)
|
19
|
+
def run(*args, runner: nil, config_name: nil, **options)
|
16
20
|
config = @configs.get(config_name)
|
17
21
|
config.run(*args, **options)
|
18
22
|
end
|
19
23
|
|
20
|
-
def run_cmd(*args, config_name: nil, **options)
|
24
|
+
def run_cmd(*args, runner: nil, config_name: nil, **options)
|
21
25
|
config = @configs.get(config_name)
|
22
26
|
config.run_cmd(*args, **options)
|
23
27
|
end
|
data/lib/wrapbox/cli.rb
CHANGED
@@ -4,6 +4,7 @@ require "active_support/core_ext/string"
|
|
4
4
|
module Wrapbox
|
5
5
|
Configuration = Struct.new(
|
6
6
|
:name,
|
7
|
+
:task_definition_name,
|
7
8
|
:revision,
|
8
9
|
:runner,
|
9
10
|
:cluster,
|
@@ -32,6 +33,7 @@ module Wrapbox
|
|
32
33
|
def self.load_config(config)
|
33
34
|
new(
|
34
35
|
config["name"],
|
36
|
+
config["task_definition_name"],
|
35
37
|
config["revision"],
|
36
38
|
config["runner"] ? config["runner"].to_sym : :docker,
|
37
39
|
config["cluster"],
|
@@ -72,12 +74,12 @@ module Wrapbox
|
|
72
74
|
Wrapbox::Runner.const_get(r.to_s.camelcase).new(to_h)
|
73
75
|
end
|
74
76
|
|
75
|
-
def run(class_name, method_name, args, **options)
|
76
|
-
build_runner.run(class_name, method_name, args, **options)
|
77
|
+
def run(class_name, method_name, args, runner: nil, **options)
|
78
|
+
build_runner(runner).run(class_name, method_name, args, **options)
|
77
79
|
end
|
78
80
|
|
79
|
-
def run_cmd(*cmd, **options)
|
80
|
-
build_runner.run_cmd(*cmd, **options)
|
81
|
+
def run_cmd(*cmd, runner: nil, **options)
|
82
|
+
build_runner(runner).run_cmd(*cmd, **options)
|
81
83
|
end
|
82
84
|
end
|
83
85
|
end
|
data/lib/wrapbox/log_fetcher.rb
CHANGED
@@ -8,7 +8,15 @@ module Wrapbox
|
|
8
8
|
def self.new(type, **options)
|
9
9
|
raise "log_fetcher config needs `type`" unless type
|
10
10
|
require "wrapbox/log_fetcher/#{type}"
|
11
|
-
self.const_get(type.
|
11
|
+
self.const_get(type.camelize).new(**options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(task:)
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
def stop
|
19
|
+
raise NotImplementedError
|
12
20
|
end
|
13
21
|
end
|
14
22
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Wrapbox
|
2
|
+
module LogFetcher
|
3
|
+
class Awslogs
|
4
|
+
STOP_WAIT_TIMELIMIT = 10
|
5
|
+
|
6
|
+
def initialize(log_group:, log_stream_prefix:, filter_pattern: nil, region: nil, access_key_id: nil, secret_access_key: nil, timestamp_format: "%Y-%m-%d %H:%M:%S.%3N", delay: 2, **options)
|
7
|
+
begin
|
8
|
+
require 'aws-sdk-cloudwatchlogs'
|
9
|
+
rescue LoadError
|
10
|
+
$stderr.puts "Require aws-sdk-cloudwatchlogs gem"
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
@log_group = log_group
|
15
|
+
@log_stream_prefix = log_stream_prefix
|
16
|
+
@filter_pattern = filter_pattern
|
17
|
+
@region = region
|
18
|
+
@access_key_id = access_key_id
|
19
|
+
@secret_access_key = secret_access_key
|
20
|
+
@timestamp_format = timestamp_format
|
21
|
+
@delay = delay
|
22
|
+
@options = options.reject { |_, v| v.nil? }
|
23
|
+
@displayed_log_stream_names = {}
|
24
|
+
@displayed_log_stream_number = 0
|
25
|
+
@displayed_event_ids = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def run(task:)
|
29
|
+
@loop_thread = Thread.start do
|
30
|
+
main_loop(task)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def stop
|
35
|
+
@stop = true
|
36
|
+
@loop_thread&.join(STOP_WAIT_TIMELIMIT)
|
37
|
+
end
|
38
|
+
|
39
|
+
def main_loop(task)
|
40
|
+
task_id = task.task_arn.split("/").last
|
41
|
+
log_stream_names = task.containers.map do |container|
|
42
|
+
[@log_stream_prefix, container.name, task_id].join("/")
|
43
|
+
end
|
44
|
+
filter_log_opts = {
|
45
|
+
log_group_name: @log_group,
|
46
|
+
log_stream_names: log_stream_names,
|
47
|
+
filter_pattern: @filter_pattern,
|
48
|
+
interleaved: true,
|
49
|
+
}.compact
|
50
|
+
@max_timestamp = ((Time.now.to_f - 120) * 1000).round
|
51
|
+
|
52
|
+
until @stop do
|
53
|
+
filter_log_opts[:start_time] = @max_timestamp + 1
|
54
|
+
resp = client.filter_log_events(filter_log_opts) rescue nil
|
55
|
+
resp&.each do |r|
|
56
|
+
r.events.each do |ev|
|
57
|
+
next if @displayed_event_ids.member?(ev.event_id)
|
58
|
+
display_message(ev)
|
59
|
+
@displayed_event_ids[ev.event_id] = ev.timestamp
|
60
|
+
@max_timestamp = ev.timestamp if @max_timestamp < ev.timestamp
|
61
|
+
end
|
62
|
+
end
|
63
|
+
Thread.start do
|
64
|
+
@displayed_event_ids.each do |event_id, ts|
|
65
|
+
if ts < (Time.now.to_f - 600) * 1000
|
66
|
+
@displayed_event_ids.delete(event_id)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end.tap do
|
70
|
+
sleep @delay
|
71
|
+
end.join
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
COLOR_ESCAPE_SEQUENCES = [33, 31, 32, 34, 35, 36]
|
76
|
+
def display_message(ev, output: $stdout)
|
77
|
+
num = @displayed_log_stream_names.fetch(ev.log_stream_name) do |key|
|
78
|
+
current = @displayed_log_stream_number
|
79
|
+
@displayed_log_stream_names[key] = current
|
80
|
+
@displayed_log_stream_number += 1
|
81
|
+
current
|
82
|
+
end
|
83
|
+
|
84
|
+
sequence_number = COLOR_ESCAPE_SEQUENCES[num % COLOR_ESCAPE_SEQUENCES.length]
|
85
|
+
|
86
|
+
time = Time.at(ev.timestamp / 1000.0)
|
87
|
+
output.puts("\e[#{sequence_number}m#{time.strftime(@timestamp_format)} #{ev.log_stream_name}\e[0m #{ev.message}")
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def client
|
93
|
+
return @client if @client
|
94
|
+
|
95
|
+
options = {
|
96
|
+
region: @region,
|
97
|
+
access_key_id: @access_key_id,
|
98
|
+
secret_access_key: @secret_access_key,
|
99
|
+
}.compact
|
100
|
+
@client = Aws::CloudWatchLogs::Client.new(**options)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -139,10 +139,8 @@ module Wrapbox
|
|
139
139
|
method_option :environments, aliases: "-e"
|
140
140
|
method_option :ignore_signal, type: :boolean, default: false, desc: "Even if receive a signal (like TERM, INT, QUIT), Docker container continue running"
|
141
141
|
def run_cmd(*args)
|
142
|
-
|
143
|
-
config =
|
144
|
-
config.runner = :docker
|
145
|
-
runner = config.build_runner
|
142
|
+
Wrapbox.load_config(options[:config])
|
143
|
+
config = Wrapbox.configs[options[:config_name]]
|
146
144
|
environments = options[:environments].to_s.split(/,\s*/).map { |kv| kv.split("=") }.map do |k, v|
|
147
145
|
{name: k, value: v}
|
148
146
|
end
|
@@ -151,7 +149,7 @@ module Wrapbox
|
|
151
149
|
else
|
152
150
|
container_definition_overrides = {}
|
153
151
|
end
|
154
|
-
unless
|
152
|
+
unless config.run_cmd(args, runner: "docker", environments: environments, container_definition_overrides: container_definition_overrides, ignore_signal: options[:ignore_signal])
|
155
153
|
exit 1
|
156
154
|
end
|
157
155
|
end
|
data/lib/wrapbox/runner/ecs.rb
CHANGED
@@ -48,6 +48,7 @@ module Wrapbox
|
|
48
48
|
|
49
49
|
def initialize(options)
|
50
50
|
@name = options[:name]
|
51
|
+
@task_definition_name = options[:task_definition_name]
|
51
52
|
@revision = options[:revision]
|
52
53
|
@cluster = options[:cluster]
|
53
54
|
@region = options[:region]
|
@@ -75,7 +76,7 @@ module Wrapbox
|
|
75
76
|
@task_definition_info = options[:task_definition]
|
76
77
|
|
77
78
|
if !@container_definitions.empty?
|
78
|
-
@task_definition_name
|
79
|
+
@task_definition_name ||= "wrapbox_#{@name}"
|
79
80
|
@main_container_name = @container_definitions[0][:name] || @task_definition_name
|
80
81
|
elsif @task_definition_info
|
81
82
|
@task_definition_name = @task_definition_info[:task_definition_name]
|
@@ -107,6 +108,7 @@ module Wrapbox
|
|
107
108
|
:execution_role_arn,
|
108
109
|
:cluster,
|
109
110
|
:timeout,
|
111
|
+
:launch_type,
|
110
112
|
:launch_timeout,
|
111
113
|
:launch_retry,
|
112
114
|
:retry_interval,
|
@@ -114,7 +116,7 @@ module Wrapbox
|
|
114
116
|
:max_retry_interval,
|
115
117
|
:execution_retry
|
116
118
|
|
117
|
-
def initialize(environments: [], task_role_arn: nil, cluster: nil, timeout: 3600 * 24, launch_timeout: 60 * 10, launch_retry: 10, retry_interval: 1, retry_interval_multiplier: 2, max_retry_interval: 120, execution_retry: 0)
|
119
|
+
def initialize(environments: [], task_role_arn: nil, cluster: nil, timeout: 3600 * 24, launch_type: "EC2", launch_timeout: 60 * 10, launch_retry: 10, retry_interval: 1, retry_interval_multiplier: 2, max_retry_interval: 120, execution_retry: 0)
|
118
120
|
b = binding
|
119
121
|
method(:initialize).parameters.each do |param|
|
120
122
|
instance_variable_set("@#{param[1]}", b.local_variable_get(param[1]))
|
@@ -186,8 +188,6 @@ module Wrapbox
|
|
186
188
|
task = create_task(task_definition_arn, class_name, method_name, args, command, parameter)
|
187
189
|
return unless task # only Task creation aborted by SignalException
|
188
190
|
|
189
|
-
@log_fetcher.run if @log_fetcher
|
190
|
-
|
191
191
|
@logger.debug("Launch Task: #{task.task_arn}")
|
192
192
|
|
193
193
|
wait_task_stopped(cl, task.task_arn, parameter.timeout)
|
@@ -237,16 +237,18 @@ module Wrapbox
|
|
237
237
|
|
238
238
|
def create_task(task_definition_arn, class_name, method_name, args, command, parameter)
|
239
239
|
cl = parameter.cluster || self.cluster
|
240
|
+
launch_type = parameter.launch_type || self.launch_type
|
240
241
|
args = Array(args)
|
241
242
|
|
242
243
|
launch_try_count = 0
|
243
244
|
current_retry_interval = parameter.retry_interval
|
244
245
|
|
245
246
|
begin
|
246
|
-
run_task_options = build_run_task_options(task_definition_arn, class_name, method_name, args, command, cl, parameter.environments, parameter.task_role_arn)
|
247
|
+
run_task_options = build_run_task_options(task_definition_arn, class_name, method_name, args, command, cl, launch_type, parameter.environments, parameter.task_role_arn)
|
247
248
|
@logger.debug("Task Options: #{run_task_options}")
|
248
249
|
resp = client.run_task(run_task_options)
|
249
250
|
task = resp.tasks[0]
|
251
|
+
@log_fetcher.run(task: task) if @log_fetcher
|
250
252
|
|
251
253
|
resp.failures.each do |failure|
|
252
254
|
@logger.debug("Failure: Arn=#{failure.arn}, Reason=#{failure.reason}")
|
@@ -438,7 +440,7 @@ module Wrapbox
|
|
438
440
|
)
|
439
441
|
end
|
440
442
|
|
441
|
-
def build_run_task_options(task_definition_arn, class_name, method_name, args, command, cluster, environments, task_role_arn)
|
443
|
+
def build_run_task_options(task_definition_arn, class_name, method_name, args, command, cluster, launch_type, environments, task_role_arn)
|
442
444
|
env = environments
|
443
445
|
env += [
|
444
446
|
{
|
@@ -502,16 +504,15 @@ module Wrapbox
|
|
502
504
|
method_option :environments, aliases: "-e"
|
503
505
|
method_option :task_role_arn
|
504
506
|
method_option :timeout, type: :numeric
|
507
|
+
method_option :launch_type, type: :string, default: "EC2", enum: ["EC2", "FARGATE"]
|
505
508
|
method_option :launch_timeout, type: :numeric
|
506
509
|
method_option :launch_retry, type: :numeric
|
507
510
|
method_option :execution_retry, type: :numeric
|
508
511
|
method_option :max_retry_interval, type: :numeric
|
509
512
|
method_option :ignore_signal, type: :boolean, default: false, desc: "Even if receive a signal (like TERM, INT, QUIT), ECS Tasks continue running"
|
510
513
|
def run_cmd(*args)
|
511
|
-
|
512
|
-
config =
|
513
|
-
config.runner = :ecs
|
514
|
-
runner = config.build_runner
|
514
|
+
Wrapbox.load_config(options[:config])
|
515
|
+
config = Wrapbox.configs[options[:config_name]]
|
515
516
|
environments = options[:environments].to_s.split(/,\s*/).map { |kv| kv.split("=") }.map do |k, v|
|
516
517
|
{name: k, value: v}
|
517
518
|
end
|
@@ -519,6 +520,7 @@ module Wrapbox
|
|
519
520
|
cluster: options[:cluster],
|
520
521
|
task_role_arn: options[:task_role_arn],
|
521
522
|
timeout: options[:timeout],
|
523
|
+
launch_type: options[:launch_type],
|
522
524
|
launch_timeout: options[:launch_timeout],
|
523
525
|
launch_retry: options[:launch_retry],
|
524
526
|
execution_retry: options[:execution_retry],
|
@@ -530,7 +532,7 @@ module Wrapbox
|
|
530
532
|
else
|
531
533
|
container_definition_overrides = {}
|
532
534
|
end
|
533
|
-
unless
|
535
|
+
unless config.run_cmd(args, runner: "ecs", environments: environments, container_definition_overrides: container_definition_overrides, **run_options)
|
534
536
|
exit 1
|
535
537
|
end
|
536
538
|
end
|
data/lib/wrapbox/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wrapbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- joker1007
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-ecs
|
@@ -203,6 +203,7 @@ files:
|
|
203
203
|
- lib/wrapbox/configuration.rb
|
204
204
|
- lib/wrapbox/job.rb
|
205
205
|
- lib/wrapbox/log_fetcher.rb
|
206
|
+
- lib/wrapbox/log_fetcher/awslogs.rb
|
206
207
|
- lib/wrapbox/log_fetcher/papertrail.rb
|
207
208
|
- lib/wrapbox/runner/docker.rb
|
208
209
|
- lib/wrapbox/runner/ecs.rb
|