scout-camp 0.1.8 → 0.1.11

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +26 -0
  3. data/VERSION +1 -1
  4. data/lib/scout/aws/s3.rb +123 -15
  5. data/lib/scout/offsite/resource.rb +1 -1
  6. data/lib/scout/terraform_dsl.rb +7 -0
  7. data/lib/scout-camp.rb +1 -0
  8. data/scout-camp.gemspec +16 -4
  9. data/scout_commands/sync +1 -0
  10. data/scout_commands/terraform/lambda_task +9 -5
  11. data/share/aws/lambda_function.rb +24 -7
  12. data/share/terraform/aws/container_lambda/data.tf +15 -0
  13. data/share/terraform/aws/container_lambda/locals.tf +8 -0
  14. data/share/terraform/aws/container_lambda/main.tf +47 -0
  15. data/share/terraform/aws/container_lambda/variables.tf +44 -0
  16. data/share/terraform/aws/efs_host/main.tf +2 -1
  17. data/share/terraform/aws/efs_host/variables.tf +9 -1
  18. data/share/terraform/aws/fargate/main.tf +4 -1
  19. data/share/terraform/aws/fargate/variables.tf +16 -5
  20. data/share/terraform/aws/iam_instance_profile/main.tf +5 -0
  21. data/share/terraform/aws/iam_instance_profile/output.tf +15 -0
  22. data/share/terraform/aws/iam_instance_profile/variables.tf +9 -0
  23. data/share/terraform/aws/lambda/main.tf +1 -1
  24. data/share/terraform/aws/lambda/variables.tf +3 -4
  25. data/share/terraform/aws/policy/main.tf +8 -0
  26. data/share/terraform/aws/policy/output.tf +15 -0
  27. data/share/terraform/aws/policy/variables.tf +12 -0
  28. data/share/terraform/aws/role/main.tf +1 -1
  29. data/share/terraform/aws/role/output.tf +1 -1
  30. data/share/terraform/aws/role/variables.tf +4 -1
  31. data/share/terraform/aws/role_policy/main.tf +9 -0
  32. data/share/terraform/aws/role_policy/variables.tf +16 -0
  33. data/test/scout/aws/test_s3.rb +14 -1
  34. metadata +15 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e451509a388ca0463eccc9609ef4e506cc793a6ee3df3c720ed441f806641c13
4
- data.tar.gz: 3950a94e466395630140a5265f3351f8e482b7a983402488587f840af4f177d3
3
+ metadata.gz: 4310a29a500f7fe04fb974b8a5cb3ae5aae506a9a3663663ec6bd86270c17fd2
4
+ data.tar.gz: a6e9b6a396a76f9ddde67a502658b9cb37cddeb12355c1bbe244c5f1ff7c3f36
5
5
  SHA512:
6
- metadata.gz: 96ee495972e08312e7b1f9ed10e8e47d7f72983d554b3113c17967c5080a20ec01ff6317939da97e90cb5db6b5b2ad2ffd9aeb2cf7fb092e3e8a2faaadc0543b
7
- data.tar.gz: 16daf0c75fbe0028eaf44d5be4a174f2de7ad05866568fd27e1376851397e4c493607bdce1e03f8943e47b22a7533dfe13599c7f10126a3e60f3b6dfe20f226b
6
+ metadata.gz: 86dbee75e288daf9d1be188a9d13e79b9656314ef3345e24d226fd79fa987c7723c4bd1d2df488a5a2e56e04cdcb97bf69e4a2ef0f2a88bde00713978ff3b4be
7
+ data.tar.gz: 7d7bd20736cad39b68d9dc0406490a5ea2a5095bec45dfe550fd2e5131ecbbdf4ecfbd21ac523cfcddadd163c4988465ad6358038d38a9c3d5151a48c50cb6cb
data/.vimproject CHANGED
@@ -87,15 +87,41 @@ scout-camp=/$PWD filter="*" {
87
87
  variables.tf
88
88
  }
89
89
 
90
+ container_lambda=container_lambda{
91
+ main.tf
92
+ data.tf
93
+ locals.tf
94
+ variables.tf
95
+ }
96
+
90
97
  role=role{
91
98
  main.tf
92
99
  variables.tf
93
100
  output.tf
94
101
  }
102
+
103
+ policy=policy{
104
+ main.tf
105
+ variables.tf
106
+ output.tf
107
+ }
108
+
109
+ role_policy=role_policy{
110
+ main.tf
111
+ variables.tf
112
+ }
113
+
95
114
  policy_attachment=policy_attachment {
96
115
  main.tf
97
116
  variables.tf
98
117
  }
118
+
119
+ iam_instance_profile=iam_instance_profile{
120
+ main.tf
121
+ variables.tf
122
+ output.tf
123
+ }
124
+
99
125
  cluster=cluster {
100
126
  main.tf
101
127
  output.tf
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.8
1
+ 0.1.11
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.claim(uri, ...)
24
+ def self.claim_uri(uri)
25
25
  if Path === uri and not uri.located?
26
- is_s3? uri.find
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://}, '')
@@ -59,7 +63,14 @@ module Open
59
63
  s3.put_object(bucket: bucket, key: key, body: content)
60
64
  end
61
65
 
62
- def self.glob(uri, pattern="**/*")
66
+ def self.touch(uri)
67
+ if self.exists?(uri)
68
+ else
69
+ self.cp(uri, uri)
70
+ end
71
+ end
72
+
73
+ def self.glob(uri, pattern="*")
63
74
  bucket, prefix = parse_s3_uri(uri)
64
75
  s3 = Aws::S3::Client.new
65
76
  matches = []
@@ -82,8 +93,19 @@ module Open
82
93
  remaining = remaining.sub(%r{^/}, '')
83
94
  end
84
95
 
96
+ Log.debug "Glob: #{remaining}"
97
+
85
98
  if File.fnmatch?(pattern, remaining, File::FNM_PATHNAME)
86
99
  matches << "s3://#{bucket}/#{key}"
100
+ else
101
+ dir = File.dirname(remaining)
102
+ while dir
103
+ if File.fnmatch?(pattern, dir, File::FNM_PATHNAME)
104
+ matches << "s3://#{bucket}/#{File.join(prefix,dir)}"
105
+ end
106
+ break if dir == File.dirname(dir)
107
+ dir = File.dirname(dir)
108
+ end
87
109
  end
88
110
  end
89
111
 
@@ -136,18 +158,22 @@ module Open
136
158
  end
137
159
 
138
160
  def self.cp(source, target)
139
- source_bucket, source_key = parse_s3_uri(source)
140
- target_bucket, target_key = parse_s3_uri(target)
161
+ if is_s3?(target)
162
+ source_bucket, source_key = parse_s3_uri(source)
163
+ target_bucket, target_key = parse_s3_uri(target)
141
164
 
142
- s3 = Aws::S3::Client.new
143
- s3.copy_object({
144
- copy_source: "#{source_bucket}/#{source_key}",
145
- bucket: target_bucket,
146
- key: target_key
147
- })
165
+ s3 = Aws::S3::Client.new
166
+ s3.copy_object({
167
+ copy_source: "#{source_bucket}/#{source_key}",
168
+ bucket: target_bucket,
169
+ key: target_key
170
+ })
171
+ else
172
+ Open.sensible_write(target, get_stream(source))
173
+ end
148
174
  end
149
175
 
150
- def self.exists?(uri)
176
+ def self.file_exists?(uri)
151
177
  bucket, key = parse_s3_uri(uri)
152
178
  return false if key.empty? # Can't check existence of bucket this way
153
179
 
@@ -157,6 +183,29 @@ module Open
157
183
  rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::NoSuchBucket
158
184
  false
159
185
  end
186
+
187
+ def self.directory?(uri)
188
+ bucket, key = parse_s3_uri(uri)
189
+ return false if key.empty? # Can't check existence of bucket this way
190
+
191
+ key += '/' unless key.end_with?('/')
192
+ s3 = Aws::S3::Client.new
193
+ response = s3.list_objects_v2({
194
+ bucket: bucket,
195
+ prefix: key,
196
+ max_keys: 1
197
+ })
198
+
199
+ !response.contents.empty?
200
+ end
201
+
202
+ def self.exists?(uri)
203
+ begin
204
+ file_exists?(uri) || directory?(uri)
205
+ rescue
206
+ false
207
+ end
208
+ end
160
209
 
161
210
  self.singleton_class.alias_method :exist?, :exists?
162
211
 
@@ -179,6 +228,68 @@ module Open
179
228
  def self.ln_s(source, target, options = {})
180
229
  cp(source, target)
181
230
  end
231
+
232
+ def self.sync(source, target, options = {})
233
+ excludes, files, hard_link, test, print, delete, other = IndiferentHash.process_options options,
234
+ :excludes, :files, :hard_link, :test, :print, :delete, :other
235
+
236
+ excludes ||= %w(.save .crap .source tmp filecache open-remote)
237
+ excludes = excludes.split(/,\s*/) if excludes.is_a?(String) and not excludes.include?("--exclude")
238
+
239
+ if File.directory?(source) || source.end_with?("/")
240
+ source += "/" unless source.end_with? '/'
241
+ target += "/" unless target.end_with? '/'
242
+ end
243
+
244
+ if source == target
245
+ Log.warn "Asking to sync with itself"
246
+ return
247
+ end
248
+
249
+ Log.low "Migrating #{source} #{files.length} files to #{target} - #{Misc.fingerprint(files)}}" if files
250
+
251
+ sync_args = %w()
252
+ sync_args << excludes.collect{|s| "--exclude '#{s}'" } if excludes and excludes.any?
253
+ sync_args << "-nv" if test
254
+
255
+ if files
256
+ tmp_files = TmpFile.tmp_file 's3_sync_files-'
257
+ Open.write(tmp_files, files * "\n")
258
+ sync_args << "--files-from='#{tmp_files}'"
259
+ end
260
+
261
+ if Open.directory?(source)
262
+ cmd = "aws s3 sync #{sync_args * " "} #{source} #{target}"
263
+ else
264
+ cmd = "aws s3 cp #{source} #{target}"
265
+ end
266
+ case other
267
+ when String
268
+ cmd << " " << other
269
+ when Array
270
+ cmd << " " << other * " "
271
+ end
272
+ cmd << " && rm -Rf #{source}" if delete && ! files
273
+
274
+ if print
275
+ cmd
276
+ else
277
+ CMD.cmd_log(cmd, :log => Log::HIGH)
278
+
279
+ if delete && files
280
+ remove_files = files.collect{|f| File.join(source, f) }
281
+ dirs = remove_files.select{|f| File.directory? f }
282
+ remove_files.each do |file|
283
+ next if dirs.include? file
284
+ Open.rm file
285
+ end
286
+
287
+ dirs.each do |dir|
288
+ FileUtils.rmdir dir if Dir.glob(dir).empty?
289
+ end
290
+ end
291
+ end
292
+ end
182
293
  end
183
294
  end
184
295
 
@@ -202,6 +313,3 @@ end
202
313
 
203
314
  Hook.apply(Open::S3, Open)
204
315
  Hook.apply(Path::S3, Path)
205
-
206
-
207
- #$ ask -t code --file /home/miki/git/scout-camp/lib/scout/aws/s3.rb extend this file [[...]] to include a function called self.exists? that determines if a uri exists {{{
@@ -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 File.exist?(path)
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)
@@ -86,6 +86,11 @@ class TerraformDSL
86
86
  def to_json(*_args)
87
87
  self
88
88
  end
89
+
90
+ def method_missing(elem)
91
+ new = self + '.' + elem.to_s
92
+ new.extend DirectReference
93
+ end
89
94
  end
90
95
 
91
96
  MODULES_DIR = Scout.share.terraform
@@ -134,6 +139,8 @@ class TerraformDSL
134
139
 
135
140
  if value.is_a?(String) && (m = value.match(/^module\.(.*)\.(.*)/))
136
141
  value = Module::Output.new m[1], m[2]
142
+ elsif value.is_a?(Symbol)
143
+ value = variables[value]
137
144
  end
138
145
 
139
146
  acc << " #{name} = #{value.to_json}"
data/lib/scout-camp.rb CHANGED
@@ -4,3 +4,4 @@ require 'scout/resource'
4
4
  Path.add_path :scout_camp, File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}/{SUBPATH}")
5
5
  require 'scout/terraform_dsl'
6
6
  require 'scout/offsite'
7
+ require 'scout/aws/s3'
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.8 ruby lib
5
+ # stub: scout-camp 0.1.11 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "scout-camp".freeze
9
- s.version = "0.1.8".freeze
9
+ s.version = "0.1.11".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 = "1980-01-02"
14
+ s.date = "2025-04-16"
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]
@@ -58,6 +58,10 @@ Gem::Specification.new do |s|
58
58
  "share/terraform/aws/cluster/main.tf",
59
59
  "share/terraform/aws/cluster/output.tf",
60
60
  "share/terraform/aws/cluster/variables.tf",
61
+ "share/terraform/aws/container_lambda/data.tf",
62
+ "share/terraform/aws/container_lambda/locals.tf",
63
+ "share/terraform/aws/container_lambda/main.tf",
64
+ "share/terraform/aws/container_lambda/variables.tf",
61
65
  "share/terraform/aws/efs/data.tf",
62
66
  "share/terraform/aws/efs/locals.tf",
63
67
  "share/terraform/aws/efs/main.tf",
@@ -75,12 +79,18 @@ Gem::Specification.new do |s|
75
79
  "share/terraform/aws/host/main.tf",
76
80
  "share/terraform/aws/host/output.tf",
77
81
  "share/terraform/aws/host/variables.tf",
82
+ "share/terraform/aws/iam_instance_profile/main.tf",
83
+ "share/terraform/aws/iam_instance_profile/output.tf",
84
+ "share/terraform/aws/iam_instance_profile/variables.tf",
78
85
  "share/terraform/aws/lambda/main.tf",
79
86
  "share/terraform/aws/lambda/variables.tf",
80
87
  "share/terraform/aws/network/data.tf",
81
88
  "share/terraform/aws/network/main.tf",
82
89
  "share/terraform/aws/network/output.tf",
83
90
  "share/terraform/aws/network/variables.tf",
91
+ "share/terraform/aws/policy/main.tf",
92
+ "share/terraform/aws/policy/output.tf",
93
+ "share/terraform/aws/policy/variables.tf",
84
94
  "share/terraform/aws/policy_attachment/main.tf",
85
95
  "share/terraform/aws/policy_attachment/variables.tf",
86
96
  "share/terraform/aws/provider/data.tf",
@@ -88,6 +98,8 @@ Gem::Specification.new do |s|
88
98
  "share/terraform/aws/role/main.tf",
89
99
  "share/terraform/aws/role/output.tf",
90
100
  "share/terraform/aws/role/variables.tf",
101
+ "share/terraform/aws/role_policy/main.tf",
102
+ "share/terraform/aws/role_policy/variables.tf",
91
103
  "share/terraform/ssh/cmd/main.tf",
92
104
  "share/terraform/ssh/cmd/variables.tf",
93
105
  "test/scout/aws/test_s3.rb",
@@ -100,7 +112,7 @@ Gem::Specification.new do |s|
100
112
  ]
101
113
  s.homepage = "http://github.com/mikisvaz/scout-camp".freeze
102
114
  s.licenses = ["MIT".freeze]
103
- s.rubygems_version = "3.6.7".freeze
115
+ s.rubygems_version = "3.6.6".freeze
104
116
  s.summary = "Deploy you scouts".freeze
105
117
 
106
118
  s.specification_version = 4
data/scout_commands/sync CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'scout'
4
4
  require 'scout/offsite/resource'
5
+ require 'scout/aws/s3'
5
6
 
6
7
  $0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
7
8
 
@@ -12,6 +12,7 @@ $ #{$0} [<options>] <workflow> <task> [<other|->]*
12
12
 
13
13
  -h--help Print this help
14
14
  --prefix* Prefix, defaults to Scout
15
+ --queue Queue job
15
16
  --clean Clean job
16
17
  --recursive_clean Clean job recursively
17
18
  EOF
@@ -28,14 +29,14 @@ end
28
29
 
29
30
  raise ParamterException, "No workflow specified" if workflow.nil?
30
31
 
31
- prefix, clean, recursive_clean = IndiferentHash.process_options options, :prefix, :clean, :recursive_clean,
32
+ prefix, clean, recursive_clean, queue = IndiferentHash.process_options options, :prefix, :clean, :recursive_clean, :queue,
32
33
  prefix: "Scout"
33
34
 
34
35
  require 'aws-sdk-lambda'
35
36
 
36
37
  payload = {}
37
- payload["workflow"] = workflow
38
- payload["task_name"] = task_name
38
+ payload[:workflow] = workflow
39
+ payload[:task_name] = task_name
39
40
 
40
41
  if clean
41
42
  payload["clean"] = true
@@ -43,10 +44,13 @@ elsif recursive_clean
43
44
  payload["clean"] = 'recursive'
44
45
  end
45
46
 
47
+ payload["queue"] = true if queue
48
+
46
49
  lambda_handler = "#{prefix}Job"
47
50
 
48
51
  def aws_lambda(name, payload)
49
52
  client = Aws::Lambda::Client.new
53
+ Log.debug "Sending Lambda #{name} #{Log.fingerprint payload}"
50
54
  resp = client.invoke({
51
55
  function_name: name,
52
56
  payload: payload.to_json,
@@ -64,7 +68,7 @@ def SOPT_str(task_info)
64
68
  boolean = type.to_sym == :boolean
65
69
 
66
70
  sopt_options << "-#{shortcut}--#{name}#{boolean ? "" : "*"}"
67
- end
71
+ end if task_info[:inputs]
68
72
 
69
73
  sopt_options * ":"
70
74
  end
@@ -81,7 +85,7 @@ def get_SOPT(task_info)
81
85
  if job_options.include?(name) && (! Open.exist?(job_options[name]) || type.to_s.include?('file') || type.to_s.include?('path'))
82
86
  job_options[name] = job_options[name].split(",")
83
87
  end
84
- end
88
+ end if task_info[:inputs]
85
89
  job_options
86
90
  end
87
91
 
@@ -7,10 +7,10 @@ def lambda_handler(event:, context:)
7
7
  require 'scout/workflow'
8
8
  require 'scout/aws/s3'
9
9
 
10
- workflow, task_name, jobname, inputs, clean = IndiferentHash.process_options event,
11
- :workflow, :task_name, :jobname, :inputs, :clean
10
+ workflow, task_name, jobname, inputs, clean, queue = IndiferentHash.process_options event,
11
+ :workflow, :task_name, :jobname, :inputs, :clean, :queue
12
12
 
13
- raise ParamterException, "No workflow specified" if workflow.nil?
13
+ raise ParameterException, "No workflow specified" if workflow.nil?
14
14
 
15
15
  workflow = Workflow.require_workflow workflow
16
16
 
@@ -18,7 +18,7 @@ def lambda_handler(event:, context:)
18
18
  when nil
19
19
  return {tasks: workflow.tasks.keys, documentation: workflow.documentation}
20
20
  when "info"
21
- raise ParamterException, "No task_name specified" if task_name.nil?
21
+ raise ParameterException, "No task_name specified" if task_name.nil?
22
22
  return workflow.task_info(inputs["task_name"])
23
23
  else
24
24
  job = workflow.job(task_name, jobname, inputs)
@@ -30,8 +30,25 @@ def lambda_handler(event:, context:)
30
30
  job.recursive_clean
31
31
  end
32
32
 
33
- job.produce
34
-
35
- job.load
33
+ if job.done?
34
+ job.load
35
+ elsif job.error?
36
+ raise job.exception
37
+ elsif job.started?
38
+ {
39
+ statusCode: 202,
40
+ body: job.path
41
+ }
42
+ elsif queue
43
+ save_inputs = Scout.var.queue[workflow.to_s][task_name][job.name].find :bucket
44
+ job.save_inputs(save_inputs)
45
+ {
46
+ statusCode: 202,
47
+ body: job.path
48
+ }
49
+ else
50
+ job.produce
51
+ job.load
52
+ end
36
53
  end
37
54
  end
@@ -0,0 +1,15 @@
1
+ data "aws_vpc" "default" {
2
+ default = true
3
+ }
4
+
5
+ data "aws_subnets" "default_vpc_subnets" {
6
+ filter {
7
+ name = "vpc-id"
8
+ values = [data.aws_vpc.default.id]
9
+ }
10
+
11
+ filter {
12
+ name = "default-for-az"
13
+ values = ["true"]
14
+ }
15
+ }
@@ -0,0 +1,8 @@
1
+ locals {
2
+ security_group_ids = [
3
+ for sg_key in var.sg_keys :
4
+ lookup(var.network.outputs, sg_key, null)
5
+ ]
6
+
7
+ efs_id = lookup(var.efs.outputs, "aws_efs_id", null)
8
+ }
@@ -0,0 +1,47 @@
1
+ resource "aws_efs_access_point" "lambda_ap" {
2
+ file_system_id = local.efs_id
3
+
4
+ posix_user {
5
+ uid = 1000
6
+ gid = 1000
7
+ }
8
+
9
+ root_directory {
10
+ path = var.mount_point
11
+ creation_info {
12
+ owner_uid = 1000
13
+ owner_gid = 1000
14
+ permissions = "755"
15
+ }
16
+ }
17
+ }
18
+
19
+ resource "aws_lambda_function" "this" {
20
+ function_name = var.function_name
21
+ package_type = "Image"
22
+
23
+ image_uri = var.image
24
+
25
+ role = var.role_arn
26
+
27
+ timeout = var.timeout
28
+ memory_size = var.memory
29
+
30
+ environment {
31
+ variables = var.environment_variables
32
+ }
33
+
34
+ vpc_config {
35
+ subnet_ids = data.aws_subnets.default_vpc_subnets.ids
36
+ security_group_ids = local.security_group_ids
37
+ }
38
+
39
+ file_system_config {
40
+ arn = aws_efs_access_point.lambda_ap.arn
41
+ local_mount_path = "/mnt/efs"
42
+ }
43
+
44
+ image_config {
45
+ command = ["app.handler"]
46
+ }
47
+ }
@@ -0,0 +1,44 @@
1
+ variable "function_name" {
2
+ description = "Lambda function name"
3
+ type = string
4
+ }
5
+ variable "timeout" {
6
+ description = "Timeout for call"
7
+ type = number
8
+ default = 30
9
+ }
10
+ variable "environment_variables" {
11
+ type = map(string)
12
+ description = "A map of environment variables to pass to the resource"
13
+ default = {}
14
+ }
15
+ variable "role_arn" {
16
+ }
17
+ variable "image" {
18
+ }
19
+ variable "memory" {
20
+ type = number
21
+ description = "The memory (MiB) for the task"
22
+ default = 512
23
+ }
24
+
25
+ variable "network" {
26
+ description = "Name of the remote state block to use for the network"
27
+ }
28
+
29
+ variable "efs" {
30
+ description = "Name of the remote state block to use for the EFS"
31
+ }
32
+
33
+ variable "sg_keys" {
34
+ description = "List of output names in the remote state representing security group IDs"
35
+ type = list(string)
36
+ default = ["aws_network_efs_sg_id", "aws_network_ssh_sg_id"]
37
+ }
38
+
39
+ variable "mount_point" {
40
+ description = "Where to mount the efs drive"
41
+ type = string
42
+ default = "/mnt/efs"
43
+ }
44
+
@@ -6,6 +6,7 @@ resource "aws_key_pair" "this" {
6
6
  resource "aws_instance" "this" {
7
7
  ami = data.aws_ami.amazon_linux_2.id
8
8
  instance_type = "t2.micro"
9
+ iam_instance_profile = var.policies.outputs.ec2_host_profile_id
9
10
 
10
11
  key_name = aws_key_pair.this.key_name
11
12
 
@@ -23,7 +24,7 @@ resource "aws_instance" "this" {
23
24
  packages:
24
25
  - amazon-efs-utils
25
26
  runcmd:
26
- - mkdir -p /mnt/efs
27
+ - mkdir -p ${var.mount_point}
27
28
  - mount -t efs -o tls ${local.efs_id}:/ ${var.mount_point}
28
29
  - echo "${local.efs_id}:/ ${var.mount_point} efs defaults,_netdev 0 0" >> /etc/fstab
29
30
  EOF
@@ -6,15 +6,23 @@ variable "efs" {
6
6
  description = "Name of the remote state block to use for the EFS"
7
7
  }
8
8
 
9
+ variable "policies" {
10
+ description = "Name of the remote state block to use for the policies"
11
+ }
12
+
9
13
  variable "sg_keys" {
10
14
  description = "List of output names in the remote state representing security group IDs"
11
15
  type = list(string)
12
16
  default = ["aws_network_efs_sg_id", "aws_network_ssh_sg_id"]
13
17
  }
14
-
15
18
  variable "mount_point" {
16
19
  description = "Where to mount the efs drive"
17
20
  type = string
18
21
  default = "/mnt/efs"
19
22
  }
20
23
 
24
+ #variable "iam_instance_profile" {
25
+ # description = "Instance profile"
26
+ # type = string
27
+ # default = null
28
+ #}
@@ -4,16 +4,19 @@ resource "aws_ecs_task_definition" "this" {
4
4
  network_mode = "awsvpc"
5
5
  cpu = var.cpu
6
6
  memory = var.memory
7
- execution_role_arn = var.role_arn
7
+ execution_role_arn = var.policies.outputs.fargate_execution_role_arn
8
+ task_role_arn = var.policies.outputs.fargate_task_role_arn
8
9
 
9
10
  container_definitions = jsonencode([
10
11
  {
11
12
  name = var.container_name
12
13
  image = var.image
14
+ user = var.user
13
15
  essential = true
14
16
  portMappings = var.port_mappings
15
17
  //entryPoint = var.entry_point
16
18
  command = var.command
19
+ environment = var.environment
17
20
 
18
21
  mountPoints = [
19
22
  {
@@ -6,6 +6,10 @@ variable "efs" {
6
6
  description = "Name of the remote state block to use for the EFS"
7
7
  }
8
8
 
9
+ variable "policies" {
10
+ description = "Name of the remote state block to use for the policies"
11
+ }
12
+
9
13
  variable "sg_keys" {
10
14
  description = "List of output names in the remote state representing security group IDs"
11
15
  type = list(string)
@@ -35,11 +39,6 @@ variable "memory" {
35
39
  default = 512
36
40
  }
37
41
 
38
- variable "role_arn" {
39
- type = string
40
- description = "ARN of the task execution role"
41
- }
42
-
43
42
  variable "container_name" {
44
43
  type = string
45
44
  description = "Name of the container"
@@ -51,6 +50,12 @@ variable "image" {
51
50
  description = "Docker image URL for the container"
52
51
  }
53
52
 
53
+ variable "user" {
54
+ description = "User to use"
55
+ type = string
56
+ default = null
57
+ }
58
+
54
59
  variable "port_mappings" {
55
60
  type = list(object({
56
61
  containerPort = number
@@ -71,3 +76,9 @@ variable "entry_point" {
71
76
  description = "Container entry point"
72
77
  default = ["bash"]
73
78
  }
79
+
80
+ variable "environment" {
81
+ type = map(string)
82
+ description = "A map of environment variables to pass to the resource"
83
+ default = null
84
+ }
@@ -0,0 +1,5 @@
1
+ resource "aws_iam_instance_profile" "this" {
2
+ name = var.profile_name
3
+ role = var.role
4
+ }
5
+
@@ -0,0 +1,15 @@
1
+ output "arn" {
2
+ description = "Instance profile arn"
3
+ value = aws_iam_instance_profile.this.arn
4
+ }
5
+
6
+ output "profile_name" {
7
+ description = "Instance profile name"
8
+ value = aws_iam_instance_profile.this.name
9
+ }
10
+
11
+ output "id" {
12
+ description = "Instance profile id"
13
+ value = aws_iam_instance_profile.this.id
14
+ }
15
+
@@ -0,0 +1,9 @@
1
+ variable "role" {
2
+ description = "Role to assign to the instance profile"
3
+ type = string
4
+ }
5
+
6
+ variable "profile_name" {
7
+ description = "Profile name"
8
+ type = string
9
+ }
@@ -5,7 +5,7 @@ resource "aws_lambda_function" "this" {
5
5
  filename = var.filename
6
6
  source_code_hash = filebase64sha256(var.filename)
7
7
  timeout = var.timeout
8
- role = var.role
8
+ role = var.policies.outputs.lambda_execution_role_arn
9
9
 
10
10
  environment {
11
11
  variables = var.environment_variables
@@ -5,7 +5,7 @@ variable "function_name" {
5
5
  variable "runtime" {
6
6
  description = "Ruby runtime"
7
7
  type = string
8
- default = "ruby3.2"
8
+ default = "ruby3.3"
9
9
  }
10
10
  variable "filename" {
11
11
  description = "ZIP filename with lambda handler"
@@ -21,7 +21,6 @@ variable "environment_variables" {
21
21
  description = "A map of environment variables to pass to the resource"
22
22
  default = {}
23
23
  }
24
- variable "role" {
25
- description = "Role to assume"
26
- type = string
24
+ variable "policies" {
25
+ description = "Name of the remote state block to use for the policies"
27
26
  }
@@ -0,0 +1,8 @@
1
+ resource "aws_iam_policy" "this" {
2
+ name = var.policy_name
3
+ policy = jsonencode({
4
+ Version = "2012-10-17",
5
+ Statement = var.statement
6
+ })
7
+ }
8
+
@@ -0,0 +1,15 @@
1
+ output "arn" {
2
+ description = "Policy arn"
3
+ value = aws_iam_policy.this.arn
4
+ }
5
+
6
+ output "name" {
7
+ description = "Policy name"
8
+ value = aws_iam_policy.this.name
9
+ }
10
+
11
+ output "id" {
12
+ description = "Policy id"
13
+ value = aws_iam_policy.this.id
14
+ }
15
+
@@ -0,0 +1,12 @@
1
+ variable "policy_name" {
2
+ type = string
3
+ }
4
+
5
+ variable "statement" {
6
+ type = list(object({
7
+ Action = any
8
+ Effect = string
9
+ Resource = any
10
+ }))
11
+ }
12
+
@@ -5,7 +5,7 @@ resource "aws_iam_role" "this" {
5
5
  Version = "2012-10-17"
6
6
  Statement = [
7
7
  {
8
- Action = "sts:AssumeRole"
8
+ Action = var.action
9
9
  Effect = "Allow"
10
10
  Principal = var.principal
11
11
  }
@@ -3,7 +3,7 @@ output "arn" {
3
3
  value = aws_iam_role.this.arn
4
4
  }
5
5
 
6
- output "name" {
6
+ output "role_name" {
7
7
  description = "Role name"
8
8
  value = aws_iam_role.this.name
9
9
  }
@@ -8,4 +8,7 @@ variable "principal" {
8
8
  type = map(any)
9
9
  }
10
10
 
11
-
11
+ variable "action" {
12
+ description = "Action of the role"
13
+ default = "sts:AssumeRole"
14
+ }
@@ -0,0 +1,9 @@
1
+ resource "aws_iam_role_policy" "this" {
2
+ name = var.policy_name
3
+ role = var.role
4
+
5
+ policy = jsonencode({
6
+ Version = "2012-10-17"
7
+ Statement = var.statement
8
+ })
9
+ }
@@ -0,0 +1,16 @@
1
+ variable "policy_name" {
2
+ type = string
3
+ }
4
+
5
+ variable "statement" {
6
+ type = list(object({
7
+ Action = any
8
+ Effect = string
9
+ Resource = string
10
+ }))
11
+ }
12
+
13
+ variable "role" {
14
+ description = "Role id to which to attach policy"
15
+ type = string
16
+ }
@@ -7,7 +7,7 @@ class TestS3 < Test::Unit::TestCase
7
7
  file = "s3://herlab/tmp/foo.txt"
8
8
 
9
9
  Open::S3.write file, "TEST"
10
-
10
+
11
11
  dir = "s3://herlab/tmp"
12
12
 
13
13
  assert_include Open::S3.glob(dir, "**/*"), file
@@ -30,6 +30,19 @@ class TestS3 < Test::Unit::TestCase
30
30
  Open::S3.rm uri
31
31
  end
32
32
 
33
+ def test_cp
34
+ uri = "s3://herlab/tmp/foo.txt"
35
+
36
+ Open::S3.write uri, "TEST"
37
+ io = Open::S3.get_stream uri
38
+ assert_equal "TEST", io.read
39
+ TmpFile.with_path do |file|
40
+ Open.cp uri, file
41
+ assert_equal "TEST", Open.read(file)
42
+ end
43
+ Open::S3.rm uri
44
+ end
45
+
33
46
  def test_write_block
34
47
  uri = "s3://herlab/tmp/foo.txt"
35
48
 
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.8
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Vazquez
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2025-04-16 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: scout-essentials
@@ -70,6 +70,10 @@ files:
70
70
  - share/terraform/aws/cluster/main.tf
71
71
  - share/terraform/aws/cluster/output.tf
72
72
  - share/terraform/aws/cluster/variables.tf
73
+ - share/terraform/aws/container_lambda/data.tf
74
+ - share/terraform/aws/container_lambda/locals.tf
75
+ - share/terraform/aws/container_lambda/main.tf
76
+ - share/terraform/aws/container_lambda/variables.tf
73
77
  - share/terraform/aws/efs/data.tf
74
78
  - share/terraform/aws/efs/locals.tf
75
79
  - share/terraform/aws/efs/main.tf
@@ -87,12 +91,18 @@ files:
87
91
  - share/terraform/aws/host/main.tf
88
92
  - share/terraform/aws/host/output.tf
89
93
  - share/terraform/aws/host/variables.tf
94
+ - share/terraform/aws/iam_instance_profile/main.tf
95
+ - share/terraform/aws/iam_instance_profile/output.tf
96
+ - share/terraform/aws/iam_instance_profile/variables.tf
90
97
  - share/terraform/aws/lambda/main.tf
91
98
  - share/terraform/aws/lambda/variables.tf
92
99
  - share/terraform/aws/network/data.tf
93
100
  - share/terraform/aws/network/main.tf
94
101
  - share/terraform/aws/network/output.tf
95
102
  - share/terraform/aws/network/variables.tf
103
+ - share/terraform/aws/policy/main.tf
104
+ - share/terraform/aws/policy/output.tf
105
+ - share/terraform/aws/policy/variables.tf
96
106
  - share/terraform/aws/policy_attachment/main.tf
97
107
  - share/terraform/aws/policy_attachment/variables.tf
98
108
  - share/terraform/aws/provider/data.tf
@@ -100,6 +110,8 @@ files:
100
110
  - share/terraform/aws/role/main.tf
101
111
  - share/terraform/aws/role/output.tf
102
112
  - share/terraform/aws/role/variables.tf
113
+ - share/terraform/aws/role_policy/main.tf
114
+ - share/terraform/aws/role_policy/variables.tf
103
115
  - share/terraform/ssh/cmd/main.tf
104
116
  - share/terraform/ssh/cmd/variables.tf
105
117
  - test/scout/aws/test_s3.rb
@@ -127,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
139
  - !ruby/object:Gem::Version
128
140
  version: '0'
129
141
  requirements: []
130
- rubygems_version: 3.6.7
142
+ rubygems_version: 3.6.6
131
143
  specification_version: 4
132
144
  summary: Deploy you scouts
133
145
  test_files: []