scout-camp 0.1.4 → 0.1.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc2855face5f3cb3ced365171398295b656f378fc681da6f0cd530c2c2977ea6
4
- data.tar.gz: baacce8525b32344f5391d9fa61b62dbb639a91bbddb2ca392a8f7ac8ce762f3
3
+ metadata.gz: dd5f35a6409cd8556f8fb6cb8641c28c36fb3b0dcc9110eeef8c8d9a5ea42594
4
+ data.tar.gz: 7bb5e7f5b07ac7d9ca601909bc3c5632d6f9d1630020e308d901d8b3a771d0f5
5
5
  SHA512:
6
- metadata.gz: c4e5de039eaba61b854f1b0af3a41172d95bbd872f64750d8bd9775b6321bcc0cbe174adbdf684a14ff836195b6cc840be06d97ddd4803ceb2b56cb032302d91
7
- data.tar.gz: ca4e6b9e69160ba22e57b3b2cadc9a669f628fdf47b20ea696cf2678b998f686bb6eebc6abcc9aba03369356a5257175b701f080dafd9bb464b3f71cbcceb779
6
+ metadata.gz: e460301e94edf73163f57309498db7d04b38b202c0437938dc0bf10cb0a31e1683f8d908309b0876fe106e781f2b69e24563656562eb57e0a759116bfb38f904
7
+ data.tar.gz: 6a78670a91b259399cad19a95411c214f3382173c37bb2611f4b13deb8a32a1626d0f2dfb793e8462253e6322156b104816a0bc5f3f37ce9d0cf3017bf735adf
data/.vimproject CHANGED
@@ -26,12 +26,17 @@ scout-camp=/$PWD filter="*" {
26
26
  offsite
27
27
  terraform=terraform{
28
28
  list
29
+ add=add{
30
+ lambda
31
+ relay
32
+ }
29
33
  add
30
34
  status
31
35
  apply
32
36
  plan
33
37
  destroy
34
38
  remove
39
+ lambda_task
35
40
  }
36
41
  }
37
42
  share=share {
@@ -66,11 +71,36 @@ scout-camp=/$PWD filter="*" {
66
71
  output.tf
67
72
  variables.tf
68
73
  }
74
+ fargate=fargate{
75
+ locals.tf
76
+ main.tf
77
+ variables.tf
78
+ }
69
79
  provider=provider {
70
80
  data.tf
71
81
  output.tf
72
82
  }
73
83
  }
84
+ ssh=ssh{
85
+ cmd=cmd{
86
+ main.tf
87
+ variables.tf
88
+ }
89
+ ollama=ollama{
90
+ main.tf
91
+ variables.tf
92
+ }
93
+ vllm=vllm{
94
+ main.tf
95
+ variables.tf
96
+ }
97
+ relay=relay{
98
+
99
+ }
100
+ }
101
+ }
102
+ aws=aws{
103
+ lambda_function.rb
74
104
  }
75
105
  }
76
106
  test=test {
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.1.6
data/lib/scout/aws/s3.rb CHANGED
@@ -10,7 +10,11 @@ module Open
10
10
  extend Hook
11
11
 
12
12
  def self.lock(*args, &block)
13
- yield nil
13
+ begin
14
+ yield nil
15
+ rescue KeepLocked
16
+ $!.payload
17
+ end
14
18
  end
15
19
 
16
20
  def self.is_s3?(uri)
@@ -51,6 +55,7 @@ module Open
51
55
  bucket, key = parse_s3_uri(uri)
52
56
  s3 = Aws::S3::Client.new
53
57
  content = Open.open_pipe(&block).read if block_given?
58
+ content = content.read if IO === content
54
59
  s3.put_object(bucket: bucket, key: key, body: content)
55
60
  end
56
61
 
@@ -69,8 +74,13 @@ module Open
69
74
 
70
75
  resp.contents.each do |object|
71
76
  key = object.key
72
- remaining = key[prefix.length..-1] || ''
73
- remaining = remaining.sub(%r{^/}, '') if prefix.empty? # Handle root-level keys with leading slash
77
+
78
+ if prefix.empty?
79
+ remaining = key.sub(%r{^/}, '')
80
+ else
81
+ remaining = key[prefix.length..-1] || ''
82
+ remaining = remaining.sub(%r{^/}, '')
83
+ end
74
84
 
75
85
  if File.fnmatch?(pattern, remaining, File::FNM_PATHNAME)
76
86
  matches << "s3://#{bucket}/#{key}"
@@ -125,6 +135,18 @@ module Open
125
135
  false
126
136
  end
127
137
 
138
+ def self.cp(source, target)
139
+ source_bucket, source_key = parse_s3_uri(source)
140
+ target_bucket, target_key = parse_s3_uri(target)
141
+
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
+ })
148
+ end
149
+
128
150
  def self.exists?(uri)
129
151
  bucket, key = parse_s3_uri(uri)
130
152
  return false if key.empty? # Can't check existence of bucket this way
@@ -137,12 +159,26 @@ module Open
137
159
  end
138
160
 
139
161
  self.singleton_class.alias_method :exist?, :exists?
140
-
141
162
 
142
163
  def self.sensible_write(path, content = nil, options = {}, &block)
164
+ content = content.to_s if content.respond_to?(:write_file)
143
165
  Open::S3.write(path, content)
144
166
  end
145
167
 
168
+ def self.mkdir(path)
169
+ end
170
+
171
+ def self.link(source, target, options = {})
172
+ cp(source, target)
173
+ end
174
+
175
+ def self.ln(source, target, options = {})
176
+ cp(source, target)
177
+ end
178
+
179
+ def self.ln_s(source, target, options = {})
180
+ cp(source, target)
181
+ end
146
182
  end
147
183
  end
148
184
 
@@ -155,8 +191,8 @@ module Path
155
191
  end
156
192
 
157
193
  def glob(*args)
158
- if Open::S3.is_s3?(self)
159
- Open::S3.glob(self, *args)
194
+ if Open::S3.is_s3?(self.find)
195
+ Open::S3.glob(self.find, *args)
160
196
  else
161
197
  orig_glob(*args)
162
198
  end
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.4 ruby lib
5
+ # stub: scout-camp 0.1.6 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "scout-camp".freeze
9
- s.version = "0.1.4".freeze
9
+ s.version = "0.1.6".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 = "2025-03-25"
14
+ s.date = "2025-04-08"
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]
@@ -38,13 +38,17 @@ Gem::Specification.new do |s|
38
38
  "lib/scout/terraform_dsl/util.rb",
39
39
  "scout-camp.gemspec",
40
40
  "scout_commands/offsite",
41
- "scout_commands/terraform/add",
41
+ "scout_commands/terraform/add/lambda",
42
+ "scout_commands/terraform/add/relay",
42
43
  "scout_commands/terraform/apply",
43
44
  "scout_commands/terraform/destroy",
45
+ "scout_commands/terraform/lambda_task",
44
46
  "scout_commands/terraform/list",
45
47
  "scout_commands/terraform/plan",
46
48
  "scout_commands/terraform/remove",
47
49
  "scout_commands/terraform/status",
50
+ "scout_commands/terraform/task",
51
+ "share/aws/lambda_function.rb",
48
52
  "share/terraform/aws/bucket/main.tf",
49
53
  "share/terraform/aws/bucket/output.tf",
50
54
  "share/terraform/aws/bucket/variables.tf",
@@ -64,6 +68,8 @@ Gem::Specification.new do |s|
64
68
  "share/terraform/aws/role/main.tf",
65
69
  "share/terraform/aws/role/output.tf",
66
70
  "share/terraform/aws/role/variables.tf",
71
+ "share/terraform/ssh/cmd/main.tf",
72
+ "share/terraform/ssh/cmd/variables.tf",
67
73
  "test/scout/aws/test_s3.rb",
68
74
  "test/scout/offsite/test_ssh.rb",
69
75
  "test/scout/offsite/test_step.rb",
@@ -14,6 +14,7 @@ $ #{$0} [<options>] <name>
14
14
  -w--workflows* Workflows to provision
15
15
  -w--dependencies* Workflows to provision
16
16
  -b--bucket* Bucket to connect
17
+ --pkg* Pkgdir, scout or rbbt (defaults to scout)
17
18
  EOF
18
19
  if options[:help]
19
20
  if defined? scout_usage
@@ -31,37 +32,20 @@ deployments = Scout.var.deployments.glob_all("*").collect(&:basename)
31
32
  raise "Deployment clash" if deployments.include? name
32
33
  dir = Scout.var.deployments[name]
33
34
 
34
- IndiferentHash.add_defaults options, workflows: '', dependencies: 'scout-gear,scout-camp', bucket: 'scout.var'
35
+ IndiferentHash.add_defaults options, workflows: '', dependencies: 'scout-gear,scout-camp', bucket: 'scout.var', pkg: 'scout'
35
36
 
36
37
  workflows = options[:workflows].split(",")
37
38
  dependencies = options[:dependencies].split(",")
39
+ dependencies.push 'scout-camp' unless dependencies.include?('scout-camp')
40
+ pkg = options[:pkg]
38
41
 
39
- code =<<-'EOF'
40
- def lambda_handler(event:, context:)
41
- require 'scout'
42
- Path.path_maps[:bucket] = "s3://#{ENV["AWS_BUCKET"]}/{TOPLEVEL}/{SUBPATH}"
43
- Path.path_maps[:default] = :bucket
44
-
45
- require 'scout/workflow'
46
- require 'scout/aws/s3'
47
-
48
- workflow, task_name, jobname, inputs = IndiferentHash.process_options event,
49
- :workflow, :task_name, :jobname, :inputs
50
-
51
- wf = Workflow.require_workflow workflow
52
-
53
- job = wf.job(task_name, jobname, inputs)
54
- job.run
55
- end
56
- EOF
57
-
58
- def lambda_package(dependencies, workflows, code)
42
+ def lambda_package(dependencies, workflows, function_file, pkg)
59
43
  TmpFile.with_path do |dir|
60
- dir["lambda_function.rb"].write code
44
+ Open.cp function_file, dir["lambda_function.rb"]
61
45
  dir["Gemfile"].write "source 'https://rubygems.org'\n" + dependencies.collect{|d| "gem '#{d}'"}*"\n"
62
46
  workflows.each do |workflow|
63
- Open.mkdir dir[".scout"].workflows
64
- Open.cp Scout.workflows[workflow], dir[".scout"].workflows[workflow]
47
+ Open.mkdir dir[".#{pkg}"].workflows
48
+ Open.ln_s Scout.workflows[workflow], dir[".#{pkg}"].workflows[workflow]
65
49
  end
66
50
  Misc.in_dir dir do
67
51
  `bundle config set path 'vendor/bundle'`
@@ -69,19 +53,18 @@ def lambda_package(dependencies, workflows, code)
69
53
  `rm -Rf vendor/bundle/ruby/*/cache`
70
54
  `rm -Rf vendor/bundle/ruby/*/gems/RubyInline*`
71
55
  TmpFile.with_file nil, extension: :zip do |zip|
72
- `zip -r "#{zip}" vendor/bundle lambda_function.rb .scout`
56
+ `zip -r "#{zip}" vendor/bundle lambda_function.rb .#{pkg}`
73
57
  yield zip
74
58
  end
75
59
  end
76
60
  end
77
61
  end
78
62
 
79
- require 'aws-sdk'
80
- lambda_package dependencies, workflows, code do |file|
81
- terraform = TerraformDSL.new
63
+ lambda_package dependencies, workflows, Scout.share.aws.lambda_function.set_extension('rb'), options[:pkg] do |file|
82
64
  filename = 'lambda_package.zip'
83
65
  Open.cp file, dir[filename]
84
66
 
67
+ terraform = TerraformDSL.new
85
68
  role = terraform.add :aws, :role, role_name: "lambda_execution_role", principal: {Service: ["lambda.amazonaws.com"]}
86
69
 
87
70
  terraform.add :aws, :policy_attachment, name: "exec_policy", policy_name: "lamda_basic_execution",
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'scout'
4
+
5
+ $0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
6
+
7
+ options = SOPT.setup <<EOF
8
+
9
+ Add a new deployment
10
+
11
+ $ #{$0} [<options>] <name>
12
+
13
+ -h--help Print this help
14
+ -s--server* Server name
15
+ -u--user* User in server
16
+ -m--model* Model name
17
+ EOF
18
+ if options[:help]
19
+ if defined? scout_usage
20
+ scout_usage
21
+ else
22
+ puts SOPT.doc
23
+ end
24
+ exit 0
25
+ end
26
+
27
+ name = ARGV.shift
28
+ raise MissingParameterException, :name if name.nil?
29
+
30
+ server, user, model = IndiferentHash.process_options options, :server, :user, :model
31
+
32
+ deployments = Scout.var.deployments.glob_all("*").collect(&:basename)
33
+ raise "Deployment clash" if deployments.include? name
34
+ dir = Scout.var.deployments[name]
35
+
36
+ terraform = TerraformDSL.new
37
+
38
+ ollama = terraform.add :ssh, :cmd, service_id: "#{name}_ollama", name: "ollama", host: server, user: user, command: 'module load ollama; ollama serve'
39
+ terraform.add :ssh, :cmd, service_id: "#{name}_ollama", name: "process", host: server, user: user, command: %Q(bash -l -c "scout-ai llm process -ck 'backend ollama ask,model #{model} ask'"), depends_on: [ollama]
40
+ terraform.config dir
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'scout'
4
+
5
+ $0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
6
+
7
+ options = SOPT.setup <<EOF
8
+
9
+ Call a task on AWS
10
+
11
+ $ #{$0} [<options>] <workflow> <task> [<other|->]*
12
+
13
+ -h--help Print this help
14
+ --prefix* Prefix, defaults to Scout
15
+ --clean Clean job
16
+ --recursive_clean Clean job recursively
17
+ EOF
18
+ workflow, task_name = ARGV
19
+
20
+ if workflow.nil? && options[:help]
21
+ if defined? scout_usage
22
+ scout_usage
23
+ else
24
+ puts SOPT.doc
25
+ end
26
+ exit 0
27
+ end
28
+
29
+ raise ParamterException, "No workflow specified" if workflow.nil?
30
+
31
+ prefix, clean, recursive_clean = IndiferentHash.process_options options, :prefix, :clean, :recursive_clean,
32
+ prefix: "Scout"
33
+
34
+ require 'aws-sdk-lambda'
35
+
36
+ payload = {}
37
+ payload["workflow"] = workflow
38
+ payload["task_name"] = task_name
39
+
40
+ if clean
41
+ payload["clean"] = true
42
+ elsif recursive_clean
43
+ payload["clean"] = 'recursive'
44
+ end
45
+
46
+ lambda_handler = "#{prefix}Job"
47
+
48
+ def aws_lambda(name, payload)
49
+ client = Aws::Lambda::Client.new
50
+ resp = client.invoke({
51
+ function_name: name,
52
+ payload: payload.to_json,
53
+ })
54
+
55
+ JSON.load(resp.payload)
56
+ end
57
+
58
+ def SOPT_str(task_info)
59
+ sopt_options = []
60
+ task_info[:inputs].each do |name|
61
+ options = task_info[:input_options][name]
62
+ type = task_info[:input_types][name]
63
+ shortcut = (options && options[:shortcut]) || name.to_s.slice(0,1)
64
+ boolean = type.to_sym == :boolean
65
+
66
+ sopt_options << "-#{shortcut}--#{name}#{boolean ? "" : "*"}"
67
+ end
68
+
69
+ sopt_options * ":"
70
+ end
71
+
72
+ def get_SOPT(task_info)
73
+ IndiferentHash.setup task_info
74
+ sopt_option_string = self.SOPT_str(task_info)
75
+ job_options = SOPT.get sopt_option_string
76
+
77
+ task_info[:inputs].each do |name|
78
+ options = task_info[:input_options][name]
79
+ type = task_info[:input_types][name]
80
+ next unless type.to_s.include?('array')
81
+ if job_options.include?(name) && (! Open.exist?(job_options[name]) || type.to_s.include?('file') || type.to_s.include?('path'))
82
+ job_options[name] = job_options[name].split(",")
83
+ end
84
+ end
85
+ job_options
86
+ end
87
+
88
+ res = case task_name
89
+ when nil
90
+
91
+ if options[:help]
92
+ if defined? scout_usage
93
+ scout_usage
94
+ else
95
+ puts SOPT.doc
96
+ end
97
+ exit 0
98
+ end
99
+
100
+ aws_lambda(lambda_handler, payload)
101
+ else
102
+ task_info = aws_lambda(lambda_handler, payload.merge(task_name: "info", inputs: {task_name: task_name}))
103
+
104
+ payload["inputs"] = get_SOPT(task_info)
105
+
106
+ if options[:help]
107
+ if defined? scout_usage
108
+ scout_usage
109
+ else
110
+ puts SOPT.doc
111
+ end
112
+ exit 0
113
+ end
114
+
115
+ aws_lambda(lambda_handler, payload)
116
+ end
117
+
118
+ if Hash === res && res["errorMessage"]
119
+ Log.error res["errorMessage"]
120
+ Log.stack res["stackTrace"] if res["stackTrace"]
121
+ exit -1
122
+ else
123
+ iii res
124
+ end
@@ -11,6 +11,7 @@ List all deployments
11
11
  $ #{$0} [<options>] <filename>
12
12
 
13
13
  -h--help Print this help
14
+ -a--active Show if they are active
14
15
  EOF
15
16
  if options[:help]
16
17
  if defined? scout_usage
@@ -26,7 +27,7 @@ deployments = Scout.var.deployments.glob_all("*")
26
27
  deployments.each do |dir|
27
28
  name = File.basename dir
28
29
  deployment = TerraformDSL::Deployment.new dir
29
- active = deployment.provisioned_elements.any?
30
+ active = options[:active] && deployment.provisioned_elements.any?
30
31
 
31
32
  if active
32
33
  puts Log.color(:title, name ) + "\t" + dir + "\t" + "Active"
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'scout'
4
+
5
+ $0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
6
+
7
+ options = SOPT.setup <<EOF
8
+
9
+ Call a task on AWS
10
+
11
+ $ #{$0} [<options>] <workflow> <task> [<other|->]*
12
+
13
+ -h--help Print this help
14
+ --prefix* Prefix, defaults to Scout
15
+ EOF
16
+ if options[:help]
17
+ if defined? scout_usage
18
+ scout_usage
19
+ else
20
+ puts SOPT.doc
21
+ end
22
+ exit 0
23
+ end
24
+
25
+ workflow, task_name = ARGV
26
+
27
+ raise ParamterException, "No workflow specified" if workflow.nil?
28
+
29
+ prefix = IndiferentHash.process_options options, :prefix, prefix: "Scout"
30
+ require 'aws-sdk-lambda'
31
+ payload = {}
32
+ payload["workflow"] = workflow
33
+ payload["task_name"] = task_name
34
+ lambda_handler = "#{prefix}Job"
35
+
36
+ def aws_lambda(name, payload)
37
+ client = Aws::Lambda::Client.new
38
+ resp = client.invoke({
39
+ function_name: name,
40
+ payload: payload.to_json,
41
+ })
42
+
43
+ JSON.load(resp.payload)
44
+ end
45
+
46
+ def SOPT_str(task_info)
47
+ sopt_options = []
48
+ task_info[:inputs].each do |name|
49
+ options = task_info[:input_options][name]
50
+ type = task_info[:input_types][name]
51
+ shortcut = (options && options[:shortcut]) || name.to_s.slice(0,1)
52
+ boolean = type.to_sym == :boolean
53
+
54
+ sopt_options << "-#{shortcut}--#{name}#{boolean ? "" : "*"}"
55
+ end
56
+
57
+ sopt_options * ":"
58
+ end
59
+
60
+ def get_SOPT(task_info)
61
+ IndiferentHash.setup task_info
62
+ sopt_option_string = self.SOPT_str(task_info)
63
+ job_options = SOPT.get sopt_option_string
64
+
65
+ task_info[:inputs].each do |name|
66
+ options = task_info[:input_options][name]
67
+ type = task_info[:input_types][name]
68
+ next unless type.to_s.include?('array')
69
+ if job_options.include?(name) && (! Open.exist?(job_options[name]) || type.to_s.include?('file') || type.to_s.include?('path'))
70
+ job_options[name] = job_options[name].split(",")
71
+ end
72
+ end
73
+ job_options
74
+ end
75
+
76
+ res = case task_name
77
+ when nil
78
+ aws_lambda(lambda_handler, payload)
79
+ else
80
+ task_info = aws_lambda(lambda_handler, payload.merge(task_name: "info", inputs: {task_name: task_name}))
81
+
82
+ payload["inputs"] = get_SOPT(task_info)
83
+
84
+ aws_lambda(lambda_handler, payload)
85
+ end
86
+
87
+ if res["errorMessage"]
88
+ Log.error res["errorMessage"]
89
+ Log.stack res["stackTrace"]
90
+ else
91
+ iii res
92
+ end
@@ -0,0 +1,27 @@
1
+ def lambda_handler(event:, context:)
2
+ require 'scout'
3
+
4
+ Path.path_maps[:bucket] = "s3://#{ENV["AWS_BUCKET"]}/{TOPLEVEL}/{SUBPATH}"
5
+ Path.path_maps[:default] = :bucket
6
+
7
+ require 'scout/workflow'
8
+ require 'scout/aws/s3'
9
+
10
+ workflow, task_name, jobname, inputs = IndiferentHash.process_options event,
11
+ :workflow, :task_name, :jobname, :inputs
12
+
13
+ raise ParamterException, "No workflow specified" if workflow.nil?
14
+
15
+ workflow = Workflow.require_workflow workflow
16
+
17
+ case task_name
18
+ when nil
19
+ return {tasks: workflow.tasks.keys, documentation: workflow.documentation}
20
+ when "info"
21
+ raise ParamterException, "No task_name specified" if task_name.nil?
22
+ return workflow.task_info(inputs["task_name"])
23
+ else
24
+ job = workflow.job(task_name, jobname, inputs)
25
+ job.run
26
+ end
27
+ end
@@ -1,4 +1,3 @@
1
-
2
1
  variable "ami" {
3
2
  description = "AMI id for host"
4
3
  type = string
@@ -0,0 +1,34 @@
1
+ terraform {
2
+ required_providers {
3
+ ssh = {
4
+ source = "loafoe/ssh"
5
+ version = ">= 1.0.0"
6
+ }
7
+ }
8
+ }
9
+
10
+ resource "ssh_resource" "up" {
11
+ host = var.host
12
+ user = var.user
13
+ agent = true
14
+ when = "create"
15
+
16
+ commands = [
17
+ "${var.command} > ${var.service_id}.log 2>&1 & echo $! > /tmp/${var.service_id}.pid"
18
+ ]
19
+
20
+ }
21
+
22
+ resource "ssh_resource" "down" {
23
+ host = var.host
24
+ user = var.user
25
+ agent = true
26
+ when = "destroy"
27
+
28
+ commands = [
29
+ "kill $(cat /tmp/${var.service_id}.pid) || true",
30
+ "rm -f /tmp/${var.service_id}.pid"
31
+ ]
32
+ }
33
+
34
+
@@ -0,0 +1,19 @@
1
+ variable "host" {
2
+ description = "Target host for SSH"
3
+ type = string
4
+ }
5
+
6
+ variable "user" {
7
+ description = "Username for SSH"
8
+ type = string
9
+ }
10
+
11
+ variable "service_id" {
12
+ description = "Identifier of the service, should be unique to avoid collisions"
13
+ type = string
14
+ }
15
+
16
+ variable "command" {
17
+ description = "Command to execute"
18
+ type = string
19
+ }
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
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Vazquez
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-25 00:00:00.000000000 Z
10
+ date: 2025-04-08 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: scout-essentials
@@ -50,13 +50,17 @@ files:
50
50
  - lib/scout/terraform_dsl/util.rb
51
51
  - scout-camp.gemspec
52
52
  - scout_commands/offsite
53
- - scout_commands/terraform/add
53
+ - scout_commands/terraform/add/lambda
54
+ - scout_commands/terraform/add/relay
54
55
  - scout_commands/terraform/apply
55
56
  - scout_commands/terraform/destroy
57
+ - scout_commands/terraform/lambda_task
56
58
  - scout_commands/terraform/list
57
59
  - scout_commands/terraform/plan
58
60
  - scout_commands/terraform/remove
59
61
  - scout_commands/terraform/status
62
+ - scout_commands/terraform/task
63
+ - share/aws/lambda_function.rb
60
64
  - share/terraform/aws/bucket/main.tf
61
65
  - share/terraform/aws/bucket/output.tf
62
66
  - share/terraform/aws/bucket/variables.tf
@@ -76,6 +80,8 @@ files:
76
80
  - share/terraform/aws/role/main.tf
77
81
  - share/terraform/aws/role/output.tf
78
82
  - share/terraform/aws/role/variables.tf
83
+ - share/terraform/ssh/cmd/main.tf
84
+ - share/terraform/ssh/cmd/variables.tf
79
85
  - test/scout/aws/test_s3.rb
80
86
  - test/scout/offsite/test_ssh.rb
81
87
  - test/scout/offsite/test_step.rb