wrapbox 0.7.0 → 0.8.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/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
|