scout-camp 0.1.10 → 0.1.12
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/.vimproject +13 -5
- data/VERSION +1 -1
- data/lib/scout/aws/s3.rb +88 -13
- data/lib/scout/offsite/resource.rb +1 -1
- data/scout-camp.gemspec +8 -4
- data/scout_commands/sync +1 -0
- data/scout_commands/terraform/lambda_task +5 -2
- data/share/aws/lambda_function.rb +16 -5
- data/share/terraform/aws/event_bridge/data.tf +10 -0
- data/share/terraform/aws/event_bridge/main.tf +85 -0
- data/share/terraform/aws/event_bridge/variables.tf +19 -0
- data/share/terraform/aws/fargate/output.tf +10 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aca4938597e0fc0bed97dbb0aa2b88821a71c27dfd3b4d96ec9876acaee294be
|
4
|
+
data.tar.gz: c6d270e7f0b8fb479f6032cb39643b54c4e7182444746b52eb78e0875b7355f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b178c0cf9038d614f0a0c4f19a8d03ea3b5f18194c803d13eb98ee3e06fa818568e0796d094c37402ae8396ddfb861d15fb9a91aef184cd1ce6180daa95618c8
|
7
|
+
data.tar.gz: db7cb1136f29a209b8e64ef2953132bc0de7f87a5484efe2d9f3f59eb263020c8e7ceff53f51f919568981cf9ffc5691fe4e8880dc59b55ecc6fdfbcb4925bdb
|
data/.vimproject
CHANGED
@@ -47,10 +47,22 @@ scout-camp=/$PWD filter="*" {
|
|
47
47
|
share=share {
|
48
48
|
terraform=terraform {
|
49
49
|
aws=aws {
|
50
|
+
event_bridge=event_bridge{
|
51
|
+
main.tf
|
52
|
+
data.tf
|
53
|
+
variables.tf
|
54
|
+
}
|
55
|
+
|
56
|
+
lambda=lambda {
|
57
|
+
main.tf
|
58
|
+
variables.tf
|
59
|
+
}
|
60
|
+
|
50
61
|
fargate=fargate{
|
51
62
|
main.tf
|
52
63
|
variables.tf
|
53
64
|
locals.tf
|
65
|
+
output.tf
|
54
66
|
}
|
55
67
|
|
56
68
|
efs_host=efs_host{
|
@@ -82,13 +94,9 @@ scout-camp=/$PWD filter="*" {
|
|
82
94
|
variables.tf
|
83
95
|
}
|
84
96
|
|
85
|
-
lambda=lambda {
|
86
|
-
main.tf
|
87
|
-
variables.tf
|
88
|
-
}
|
89
|
-
|
90
97
|
container_lambda=container_lambda{
|
91
98
|
main.tf
|
99
|
+
data.tf
|
92
100
|
locals.tf
|
93
101
|
variables.tf
|
94
102
|
}
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.12
|
data/lib/scout/aws/s3.rb
CHANGED
@@ -21,14 +21,18 @@ module Open
|
|
21
21
|
uri.start_with? 's3://'
|
22
22
|
end
|
23
23
|
|
24
|
-
def self.
|
24
|
+
def self.claim_uri(uri)
|
25
25
|
if Path === uri and not uri.located?
|
26
|
-
is_s3?
|
26
|
+
is_s3?(uri.find)
|
27
27
|
else
|
28
28
|
is_s3? uri
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
def self.claim(uri, uri2=nil, ...)
|
33
|
+
claim_uri(uri) || (String === uri2 && claim_uri(uri2))
|
34
|
+
end
|
35
|
+
|
32
36
|
def self.parse_s3_uri(uri)
|
33
37
|
uri = uri.find if Path === uri and not uri.located?
|
34
38
|
uri = uri.sub(%r{^s3://}, '')
|
@@ -66,13 +70,12 @@ module Open
|
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
69
|
-
def self.glob(uri, pattern="
|
73
|
+
def self.glob(uri, pattern="*")
|
70
74
|
bucket, prefix = parse_s3_uri(uri)
|
71
75
|
s3 = Aws::S3::Client.new
|
72
76
|
matches = []
|
73
77
|
continuation_token = nil
|
74
78
|
|
75
|
-
Log.debug "Glob: #{uri} #{pattern}"
|
76
79
|
loop do
|
77
80
|
resp = s3.list_objects_v2(
|
78
81
|
bucket: bucket,
|
@@ -156,20 +159,29 @@ module Open
|
|
156
159
|
|
157
160
|
def self.cp(source, target)
|
158
161
|
if is_s3?(target)
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
162
|
+
if is_s3?(source)
|
163
|
+
source_bucket, source_key = parse_s3_uri(source)
|
164
|
+
target_bucket, target_key = parse_s3_uri(target)
|
165
|
+
|
166
|
+
s3 = Aws::S3::Client.new
|
167
|
+
s3.copy_object({
|
168
|
+
copy_source: "#{source_bucket}/#{source_key}",
|
169
|
+
bucket: target_bucket,
|
170
|
+
key: target_key
|
171
|
+
})
|
172
|
+
else
|
173
|
+
self.write(target, Open.get_stream(source))
|
174
|
+
end
|
168
175
|
else
|
169
176
|
Open.sensible_write(target, get_stream(source))
|
170
177
|
end
|
171
178
|
end
|
172
179
|
|
180
|
+
def self.mv(source, target)
|
181
|
+
self.cp(source, target)
|
182
|
+
Open.rm_rf source
|
183
|
+
end
|
184
|
+
|
173
185
|
def self.file_exists?(uri)
|
174
186
|
bucket, key = parse_s3_uri(uri)
|
175
187
|
return false if key.empty? # Can't check existence of bucket this way
|
@@ -185,6 +197,7 @@ module Open
|
|
185
197
|
bucket, key = parse_s3_uri(uri)
|
186
198
|
return false if key.empty? # Can't check existence of bucket this way
|
187
199
|
|
200
|
+
key += '/' unless key.end_with?('/')
|
188
201
|
s3 = Aws::S3::Client.new
|
189
202
|
response = s3.list_objects_v2({
|
190
203
|
bucket: bucket,
|
@@ -224,6 +237,68 @@ module Open
|
|
224
237
|
def self.ln_s(source, target, options = {})
|
225
238
|
cp(source, target)
|
226
239
|
end
|
240
|
+
|
241
|
+
def self.sync(source, target, options = {})
|
242
|
+
excludes, files, hard_link, test, print, delete, other = IndiferentHash.process_options options,
|
243
|
+
:excludes, :files, :hard_link, :test, :print, :delete, :other
|
244
|
+
|
245
|
+
excludes ||= %w(.save .crap .source tmp filecache open-remote)
|
246
|
+
excludes = excludes.split(/,\s*/) if excludes.is_a?(String) and not excludes.include?("--exclude")
|
247
|
+
|
248
|
+
if File.directory?(source) || source.end_with?("/")
|
249
|
+
source += "/" unless source.end_with? '/'
|
250
|
+
target += "/" unless target.end_with? '/'
|
251
|
+
end
|
252
|
+
|
253
|
+
if source == target
|
254
|
+
Log.warn "Asking to sync with itself"
|
255
|
+
return
|
256
|
+
end
|
257
|
+
|
258
|
+
Log.low "Migrating #{source} #{files.length} files to #{target} - #{Misc.fingerprint(files)}}" if files
|
259
|
+
|
260
|
+
sync_args = %w()
|
261
|
+
sync_args << excludes.collect{|s| "--exclude '#{s}'" } if excludes and excludes.any?
|
262
|
+
sync_args << "-nv" if test
|
263
|
+
|
264
|
+
if files
|
265
|
+
tmp_files = TmpFile.tmp_file 's3_sync_files-'
|
266
|
+
Open.write(tmp_files, files * "\n")
|
267
|
+
sync_args << "--files-from='#{tmp_files}'"
|
268
|
+
end
|
269
|
+
|
270
|
+
if Open.directory?(source)
|
271
|
+
cmd = "aws s3 sync #{sync_args * " "} #{source} #{target}"
|
272
|
+
else
|
273
|
+
cmd = "aws s3 cp #{source} #{target}"
|
274
|
+
end
|
275
|
+
case other
|
276
|
+
when String
|
277
|
+
cmd << " " << other
|
278
|
+
when Array
|
279
|
+
cmd << " " << other * " "
|
280
|
+
end
|
281
|
+
cmd << " && rm -Rf #{source}" if delete && ! files
|
282
|
+
|
283
|
+
if print
|
284
|
+
cmd
|
285
|
+
else
|
286
|
+
CMD.cmd_log(cmd, :log => Log::HIGH)
|
287
|
+
|
288
|
+
if delete && files
|
289
|
+
remove_files = files.collect{|f| File.join(source, f) }
|
290
|
+
dirs = remove_files.select{|f| File.directory? f }
|
291
|
+
remove_files.each do |file|
|
292
|
+
next if dirs.include? file
|
293
|
+
Open.rm file
|
294
|
+
end
|
295
|
+
|
296
|
+
dirs.each do |dir|
|
297
|
+
FileUtils.rmdir dir if Dir.glob(dir).empty?
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
227
302
|
end
|
228
303
|
end
|
229
304
|
|
@@ -11,7 +11,7 @@ module Resource
|
|
11
11
|
resource = path.pkgdir if resource.nil? and path.is_a?(Path) and path.pkgdir.is_a?(Resource)
|
12
12
|
resource = Resource.default_resource if resource.nil?
|
13
13
|
|
14
|
-
if
|
14
|
+
if Path.located?(path)
|
15
15
|
real_paths = [path]
|
16
16
|
else
|
17
17
|
path = Path.setup(path, pkgdir: resource) unless path.is_a?(Path)
|
data/scout-camp.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: scout-camp 0.1.
|
5
|
+
# stub: scout-camp 0.1.12 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "scout-camp".freeze
|
9
|
-
s.version = "0.1.
|
9
|
+
s.version = "0.1.12".freeze
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Miguel Vazquez".freeze]
|
14
|
-
s.date = "
|
14
|
+
s.date = "1980-01-02"
|
15
15
|
s.description = "Functionalities to deploy and use scouts in remote servers like AWS".freeze
|
16
16
|
s.email = "mikisvaz@gmail.com".freeze
|
17
17
|
s.executables = ["scout-camp".freeze]
|
@@ -72,8 +72,12 @@ Gem::Specification.new do |s|
|
|
72
72
|
"share/terraform/aws/efs_host/main.tf",
|
73
73
|
"share/terraform/aws/efs_host/output.tf",
|
74
74
|
"share/terraform/aws/efs_host/variables.tf",
|
75
|
+
"share/terraform/aws/event_bridge/data.tf",
|
76
|
+
"share/terraform/aws/event_bridge/main.tf",
|
77
|
+
"share/terraform/aws/event_bridge/variables.tf",
|
75
78
|
"share/terraform/aws/fargate/locals.tf",
|
76
79
|
"share/terraform/aws/fargate/main.tf",
|
80
|
+
"share/terraform/aws/fargate/output.tf",
|
77
81
|
"share/terraform/aws/fargate/variables.tf",
|
78
82
|
"share/terraform/aws/host/locals.tf",
|
79
83
|
"share/terraform/aws/host/main.tf",
|
@@ -112,7 +116,7 @@ Gem::Specification.new do |s|
|
|
112
116
|
]
|
113
117
|
s.homepage = "http://github.com/mikisvaz/scout-camp".freeze
|
114
118
|
s.licenses = ["MIT".freeze]
|
115
|
-
s.rubygems_version = "3.6.
|
119
|
+
s.rubygems_version = "3.6.7".freeze
|
116
120
|
s.summary = "Deploy you scouts".freeze
|
117
121
|
|
118
122
|
s.specification_version = 4
|
data/scout_commands/sync
CHANGED
@@ -14,6 +14,7 @@ $ #{$0} [<options>] <workflow> <task> [<other|->]*
|
|
14
14
|
--prefix* Prefix, defaults to Scout
|
15
15
|
--queue Queue job
|
16
16
|
--clean Clean job
|
17
|
+
--info Return job info
|
17
18
|
--recursive_clean Clean job recursively
|
18
19
|
EOF
|
19
20
|
workflow, task_name = ARGV
|
@@ -27,9 +28,9 @@ if workflow.nil? && options[:help]
|
|
27
28
|
exit 0
|
28
29
|
end
|
29
30
|
|
30
|
-
raise
|
31
|
+
raise ParameterException, "No workflow specified" if workflow.nil?
|
31
32
|
|
32
|
-
prefix, clean, recursive_clean, queue = IndiferentHash.process_options options, :prefix, :clean, :recursive_clean, :queue,
|
33
|
+
prefix, clean, recursive_clean, queue, info = IndiferentHash.process_options options, :prefix, :clean, :recursive_clean, :queue, :info,
|
33
34
|
prefix: "Scout"
|
34
35
|
|
35
36
|
require 'aws-sdk-lambda'
|
@@ -116,6 +117,8 @@ res = case task_name
|
|
116
117
|
exit 0
|
117
118
|
end
|
118
119
|
|
120
|
+
payload["info"] = true if info
|
121
|
+
|
119
122
|
aws_lambda(lambda_handler, payload)
|
120
123
|
end
|
121
124
|
|
@@ -7,8 +7,13 @@ def lambda_handler(event:, context:)
|
|
7
7
|
require 'scout/workflow'
|
8
8
|
require 'scout/aws/s3'
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
TmpFile.tmpdir = Path.setup('/tmp')
|
11
|
+
Open.sensible_write_dir = Path.setup('/tmp/sensible_write')
|
12
|
+
|
13
|
+
Log.info "Payload: #{Log.fingerprint(event)}"
|
14
|
+
|
15
|
+
workflow, task_name, jobname, inputs, clean, queue, info = IndiferentHash.process_options event,
|
16
|
+
:workflow, :task_name, :jobname, :inputs, :clean, :queue, :info
|
12
17
|
|
13
18
|
raise ParameterException, "No workflow specified" if workflow.nil?
|
14
19
|
|
@@ -21,6 +26,8 @@ def lambda_handler(event:, context:)
|
|
21
26
|
raise ParameterException, "No task_name specified" if task_name.nil?
|
22
27
|
return workflow.task_info(inputs["task_name"])
|
23
28
|
else
|
29
|
+
Workflow.job_cache.clear
|
30
|
+
|
24
31
|
job = workflow.job(task_name, jobname, inputs)
|
25
32
|
|
26
33
|
case clean
|
@@ -30,7 +37,11 @@ def lambda_handler(event:, context:)
|
|
30
37
|
job.recursive_clean
|
31
38
|
end
|
32
39
|
|
33
|
-
if
|
40
|
+
if info
|
41
|
+
info = job.info.dup
|
42
|
+
info["path"] = job.path
|
43
|
+
info
|
44
|
+
elsif job.done?
|
34
45
|
job.load
|
35
46
|
elsif job.error?
|
36
47
|
raise job.exception
|
@@ -40,8 +51,8 @@ def lambda_handler(event:, context:)
|
|
40
51
|
body: job.path
|
41
52
|
}
|
42
53
|
elsif queue
|
43
|
-
save_inputs = Scout.var.queue[workflow.to_s][task_name][job.name].find
|
44
|
-
job.
|
54
|
+
save_inputs = Scout.var.queue[workflow.to_s][task_name][job.name].find :bucket
|
55
|
+
job.save_input_bundle(save_inputs) unless save_inputs.exists?
|
45
56
|
{
|
46
57
|
statusCode: 202,
|
47
58
|
body: job.path
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# IAM Role for EventBridge to trigger ECS task
|
2
|
+
resource "aws_iam_role" "eventbridge_invoke_ecs" {
|
3
|
+
name = "eventbridge_invoke_ecs"
|
4
|
+
|
5
|
+
assume_role_policy = jsonencode({
|
6
|
+
Version = "2012-10-17",
|
7
|
+
Statement = [
|
8
|
+
{
|
9
|
+
Effect = "Allow",
|
10
|
+
Principal = {
|
11
|
+
Service = "events.amazonaws.com"
|
12
|
+
},
|
13
|
+
Action = "sts:AssumeRole"
|
14
|
+
}
|
15
|
+
]
|
16
|
+
})
|
17
|
+
}
|
18
|
+
|
19
|
+
# Permissions for EventBridge to run the task
|
20
|
+
resource "aws_iam_role_policy" "ecs_task_invoke_policy" {
|
21
|
+
role = aws_iam_role.eventbridge_invoke_ecs.name
|
22
|
+
|
23
|
+
policy = jsonencode({
|
24
|
+
Version = "2012-10-17",
|
25
|
+
Statement = [
|
26
|
+
{
|
27
|
+
Effect = "Allow",
|
28
|
+
Action = [
|
29
|
+
"ecs:RunTask"
|
30
|
+
],
|
31
|
+
Resource = "*"
|
32
|
+
},
|
33
|
+
{
|
34
|
+
Effect = "Allow",
|
35
|
+
Action = [
|
36
|
+
"iam:PassRole"
|
37
|
+
],
|
38
|
+
Resource = "*"
|
39
|
+
}
|
40
|
+
]
|
41
|
+
})
|
42
|
+
}
|
43
|
+
|
44
|
+
# EventBridge rule triggered on S3 put event
|
45
|
+
resource "aws_cloudwatch_event_rule" "s3_put_event" {
|
46
|
+
name = "s3-put-to-uploads"
|
47
|
+
description = "Triggers Fargate task on S3 file upload"
|
48
|
+
event_pattern = jsonencode({
|
49
|
+
source = ["aws.s3"],
|
50
|
+
"detail-type" = ["Object Created"],
|
51
|
+
detail = {
|
52
|
+
bucket = {
|
53
|
+
name = [var.bucket]
|
54
|
+
},
|
55
|
+
object = {
|
56
|
+
key = [{
|
57
|
+
prefix = var.directory
|
58
|
+
}]
|
59
|
+
}
|
60
|
+
}
|
61
|
+
})
|
62
|
+
}
|
63
|
+
|
64
|
+
# Target: ECS Fargate task
|
65
|
+
resource "aws_cloudwatch_event_target" "run_fargate" {
|
66
|
+
rule = aws_cloudwatch_event_rule.s3_put_event.name
|
67
|
+
arn = var.cluster_arn # Replace with your ECS Cluster ARN
|
68
|
+
role_arn = aws_iam_role.eventbridge_invoke_ecs.arn
|
69
|
+
|
70
|
+
ecs_target {
|
71
|
+
task_definition_arn = var.task_arn
|
72
|
+
launch_type = "FARGATE"
|
73
|
+
network_configuration {
|
74
|
+
assign_public_ip = true
|
75
|
+
subnets = data.aws_subnets.default.ids
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
# Allow S3 to send events to EventBridge
|
81
|
+
#resource "aws_s3_bucket_notification" "s3_event" {
|
82
|
+
# bucket = var.bucket_name
|
83
|
+
#
|
84
|
+
# eventbridge = true
|
85
|
+
#}
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scout-camp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: scout-essentials
|
@@ -84,8 +84,12 @@ files:
|
|
84
84
|
- share/terraform/aws/efs_host/main.tf
|
85
85
|
- share/terraform/aws/efs_host/output.tf
|
86
86
|
- share/terraform/aws/efs_host/variables.tf
|
87
|
+
- share/terraform/aws/event_bridge/data.tf
|
88
|
+
- share/terraform/aws/event_bridge/main.tf
|
89
|
+
- share/terraform/aws/event_bridge/variables.tf
|
87
90
|
- share/terraform/aws/fargate/locals.tf
|
88
91
|
- share/terraform/aws/fargate/main.tf
|
92
|
+
- share/terraform/aws/fargate/output.tf
|
89
93
|
- share/terraform/aws/fargate/variables.tf
|
90
94
|
- share/terraform/aws/host/locals.tf
|
91
95
|
- share/terraform/aws/host/main.tf
|
@@ -139,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
143
|
- !ruby/object:Gem::Version
|
140
144
|
version: '0'
|
141
145
|
requirements: []
|
142
|
-
rubygems_version: 3.6.
|
146
|
+
rubygems_version: 3.6.7
|
143
147
|
specification_version: 4
|
144
148
|
summary: Deploy you scouts
|
145
149
|
test_files: []
|