scout-camp 0.1.5 → 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: 225a937ec9eac0522929e3da409bed070cf387a725d8c8cc5e4041832746fee5
4
- data.tar.gz: 5d88f8bc6d5d382b0de9b1765a5cf95e688708dfdbe67cb4372055876fcc5f4c
3
+ metadata.gz: dd5f35a6409cd8556f8fb6cb8641c28c36fb3b0dcc9110eeef8c8d9a5ea42594
4
+ data.tar.gz: 7bb5e7f5b07ac7d9ca601909bc3c5632d6f9d1630020e308d901d8b3a771d0f5
5
5
  SHA512:
6
- metadata.gz: 7008e9b2ae08a9f6c8fdef48e913d09a6d07eb42825c246bd6182b23868798c1d5227fbcd8acf9147dc1918e0b920d90851539c6a8d74cae481e1cc65afce22a
7
- data.tar.gz: 9cfc47356b2225417cceab5625e43a047df912011b655ff6754f770d6cdf9beca85dd6cddfe266ffe6a4018ba5ee52728d7a199051dfcfa4a026aa7248801f10
6
+ metadata.gz: e460301e94edf73163f57309498db7d04b38b202c0437938dc0bf10cb0a31e1683f8d908309b0876fe106e781f2b69e24563656562eb57e0a759116bfb38f904
7
+ data.tar.gz: 6a78670a91b259399cad19a95411c214f3382173c37bb2611f4b13deb8a32a1626d0f2dfb793e8462253e6322156b104816a0bc5f3f37ce9d0cf3017bf735adf
data/.vimproject CHANGED
@@ -26,14 +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
- fargate
31
34
  status
32
35
  apply
33
36
  plan
34
37
  destroy
35
38
  remove
36
- task
39
+ lambda_task
37
40
  }
38
41
  }
39
42
  share=share {
@@ -78,6 +81,23 @@ scout-camp=/$PWD filter="*" {
78
81
  output.tf
79
82
  }
80
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
+ }
81
101
  }
82
102
  aws=aws{
83
103
  lambda_function.rb
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.5
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
 
@@ -130,6 +135,18 @@ module Open
130
135
  false
131
136
  end
132
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
+
133
150
  def self.exists?(uri)
134
151
  bucket, key = parse_s3_uri(uri)
135
152
  return false if key.empty? # Can't check existence of bucket this way
@@ -142,14 +159,26 @@ module Open
142
159
  end
143
160
 
144
161
  self.singleton_class.alias_method :exist?, :exists?
145
-
146
162
 
147
163
  def self.sensible_write(path, content = nil, options = {}, &block)
164
+ content = content.to_s if content.respond_to?(:write_file)
148
165
  Open::S3.write(path, content)
149
166
  end
150
167
 
151
168
  def self.mkdir(path)
152
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
153
182
  end
154
183
  end
155
184
 
@@ -162,8 +191,8 @@ module Path
162
191
  end
163
192
 
164
193
  def glob(*args)
165
- if Open::S3.is_s3?(self)
166
- Open::S3.glob(self, *args)
194
+ if Open::S3.is_s3?(self.find)
195
+ Open::S3.glob(self.find, *args)
167
196
  else
168
197
  orig_glob(*args)
169
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.5 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.5".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-31"
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,9 +38,11 @@ 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",
@@ -66,6 +68,8 @@ Gem::Specification.new do |s|
66
68
  "share/terraform/aws/role/main.tf",
67
69
  "share/terraform/aws/role/output.tf",
68
70
  "share/terraform/aws/role/variables.tf",
71
+ "share/terraform/ssh/cmd/main.tf",
72
+ "share/terraform/ssh/cmd/variables.tf",
69
73
  "test/scout/aws/test_s3.rb",
70
74
  "test/scout/offsite/test_ssh.rb",
71
75
  "test/scout/offsite/test_step.rb",
@@ -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,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.5
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-31 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,9 +50,11 @@ 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
@@ -78,6 +80,8 @@ files:
78
80
  - share/terraform/aws/role/main.tf
79
81
  - share/terraform/aws/role/output.tf
80
82
  - share/terraform/aws/role/variables.tf
83
+ - share/terraform/ssh/cmd/main.tf
84
+ - share/terraform/ssh/cmd/variables.tf
81
85
  - test/scout/aws/test_s3.rb
82
86
  - test/scout/offsite/test_ssh.rb
83
87
  - test/scout/offsite/test_step.rb
File without changes