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 +4 -4
- data/.vimproject +22 -2
- data/VERSION +1 -1
- data/lib/scout/aws/s3.rb +33 -4
- data/scout-camp.gemspec +8 -4
- data/scout_commands/terraform/add/relay +40 -0
- data/scout_commands/terraform/lambda_task +124 -0
- data/scout_commands/terraform/list +2 -1
- data/share/terraform/ssh/cmd/main.tf +34 -0
- data/share/terraform/ssh/cmd/variables.tf +19 -0
- metadata +7 -3
- /data/scout_commands/terraform/{add → add/lambda} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd5f35a6409cd8556f8fb6cb8641c28c36fb3b0dcc9110eeef8c8d9a5ea42594
|
4
|
+
data.tar.gz: 7bb5e7f5b07ac7d9ca601909bc3c5632d6f9d1630020e308d901d8b3a771d0f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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.
|
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
|
-
|
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
|
+
# 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.
|
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-
|
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.
|
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-
|
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
|