scout-camp 0.1.13 → 0.1.14

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +52 -11
  3. data/Rakefile +5 -0
  4. data/VERSION +1 -1
  5. data/bin/scout-camp +46 -0
  6. data/doc/terraform.md +188 -0
  7. data/lib/scout/aws/s3.rb +6 -4
  8. data/lib/scout/offsite/resource.rb +110 -5
  9. data/lib/scout/offsite/step.rb +21 -14
  10. data/lib/scout/offsite/sync.rb +38 -10
  11. data/lib/scout/offsite.rb +1 -0
  12. data/lib/scout/render/engine.rb +119 -0
  13. data/lib/scout/render/helpers.rb +92 -0
  14. data/lib/scout/render/resource.rb +54 -0
  15. data/lib/scout/render.rb +3 -0
  16. data/lib/scout/sinatra/auth.rb +158 -0
  17. data/lib/scout/sinatra/base/assets.rb +245 -0
  18. data/lib/scout/sinatra/base/favicon.rb +43 -0
  19. data/lib/scout/sinatra/base/headers.rb +77 -0
  20. data/lib/scout/sinatra/base/helpers.rb +14 -0
  21. data/lib/scout/sinatra/base/parameters.rb +147 -0
  22. data/lib/scout/sinatra/base/post_processing.rb +18 -0
  23. data/lib/scout/sinatra/base/session.rb +72 -0
  24. data/lib/scout/sinatra/base.rb +253 -0
  25. data/lib/scout/sinatra/entity.rb +259 -0
  26. data/lib/scout/sinatra/finder.rb +9 -0
  27. data/lib/scout/sinatra/fragment.rb +275 -0
  28. data/lib/scout/sinatra/htmx.rb +68 -0
  29. data/lib/scout/sinatra/knowledge_base.rb +14 -0
  30. data/lib/scout/sinatra/tool.rb +11 -0
  31. data/lib/scout/sinatra/workflow.rb +129 -0
  32. data/lib/scout-camp.rb +1 -1
  33. data/scout-camp.gemspec +39 -3
  34. data/scout_commands/find +83 -0
  35. data/scout_commands/glob +90 -0
  36. data/share/aws/lambda_function.rb +53 -30
  37. data/share/terraform/aws/efs_host/data.tf +1 -2
  38. data/share/terraform/aws/efs_host/main.tf +1 -1
  39. data/share/terraform/aws/efs_host/variables.tf +5 -1
  40. data/test/scout/render/test_engine.rb +88 -0
  41. data/test/scout/render/test_resource.rb +29 -0
  42. data/test/scout/sinatra/base/test_headers.rb +125 -0
  43. data/test/scout/sinatra/base/test_parameters.rb +88 -0
  44. data/test/scout/sinatra/test_base.rb +27 -0
  45. data/test/scout/sinatra/test_entity.rb +44 -0
  46. data/test/scout/sinatra/test_render.rb +44 -0
  47. data/test/scout/sinatra/test_workflow.rb +157 -0
  48. data/test/test_helper.rb +26 -0
  49. metadata +103 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b67e89dae365eb1464f34a19d600247a18d9698de5a8337d5cda677b1623396a
4
- data.tar.gz: f5f37fce02c5a92ef3d370fd4f1e0367955bcaffc993ba5a963dca94f4ec255c
3
+ metadata.gz: 5535e519a380d0c2d9f9ce786c35d8ec780f58c2376901385ceb7e4bc2a9f8ef
4
+ data.tar.gz: 2c8ba6faccd6c9d3ebbb7951cfa6aa2b67f8ea2c374cc39a05875a1c77d2cb0e
5
5
  SHA512:
6
- metadata.gz: 50d5d0ee70db54470257f49ad6b5595beb0b1d5be73df1471088fc336800a075b2d723082834f6dc6252abf1867b95323b84a3e09dd975c6be1ed2a129e2e46a
7
- data.tar.gz: 6908c7789074017d48612f538878657dab8165a286ac8468fd5c243549ff1cbe599ef2868e2d5f88ef8df4f859c57aaa95c3fcd9b9603729fd662756c7faefc5
6
+ metadata.gz: bb1a6148578827919e2a4c4216db0c9ba69cd8666882a08bce5cf3c2e3c5e3ab56ae99bb40de806ba5b0baef93c3d2a6c76bb972a73bd3e6e82258f481760661
7
+ data.tar.gz: e29a4bca9bd0d91574769c57e5f99beb2317926c2ed5863448883d5a9e3ec253a108dd849984c9ed9225575988870f05ddc20a8784e03109fb2e8b533cbd4875
data/.vimproject CHANGED
@@ -2,6 +2,14 @@ scout-camp=/$PWD filter="*" {
2
2
  bin=bin {
3
3
  scout-camp
4
4
  }
5
+ chats=chats filter="*"{
6
+ auth
7
+
8
+ intro
9
+ javascript
10
+ sinatra
11
+ unit
12
+ }
5
13
  lib=lib {
6
14
  scout-camp.rb
7
15
  scout=scout {
@@ -21,27 +29,58 @@ scout-camp=/$PWD filter="*" {
21
29
  sync.rb
22
30
  resource.rb
23
31
  }
32
+
33
+ render=render{
34
+ resource.rb
35
+ helpers.rb
36
+ engine.rb
37
+ }
38
+ render.rb
39
+ sinatra=sinatra{
40
+ entity.rb
41
+ workflow.rb
42
+
43
+ base=base{
44
+ post_processing.rb
45
+ parameters.rb
46
+
47
+ helpers.rb
48
+ assets.rb
49
+ headers.rb
50
+ session.rb
51
+ favicon.rb
52
+ }
53
+ base.rb
54
+
55
+ tool.rb
56
+
57
+ fragment.rb
58
+ auth.rb
59
+ htmx.rb
60
+ finder.rb
61
+ knowledge_base.rb
62
+ }
24
63
  }
25
64
  }
26
65
  scout_commands=scout_commands {
66
+ find
67
+ glob
27
68
  offsite
28
69
  sync
29
-
30
70
  terraform=terraform{
71
+ apply
72
+ destroy
73
+ lambda_task
31
74
  list
32
- add=add{
33
- relay
34
- lambda
35
- host
36
- fargate
37
- }
38
- status
39
75
  outputs
40
- apply
41
76
  plan
42
- destroy
43
77
  remove
44
- lambda_task
78
+ status
79
+ task
80
+ add=add{
81
+ lambda
82
+ relay
83
+ }
45
84
  }
46
85
  }
47
86
  share=share {
@@ -166,6 +205,8 @@ scout-camp=/$PWD filter="*" {
166
205
  aws=aws{
167
206
  lambda_function.rb
168
207
  }
208
+ views=views{
209
+ }
169
210
  }
170
211
  test=test {
171
212
  test_helper.rb
data/Rakefile CHANGED
@@ -42,6 +42,11 @@ Juwelier::Tasks.new do |gem|
42
42
  #gem.add_development_dependency "simplecov", ">= 0"
43
43
 
44
44
  gem.add_runtime_dependency 'scout-essentials', '>= 0'
45
+ gem.add_runtime_dependency 'aws-sdk-s3', '>= 0'
46
+ gem.add_runtime_dependency 'sinatra', '>= 0'
47
+ gem.add_runtime_dependency 'omniauth', '>= 0'
48
+ gem.add_runtime_dependency 'mimemagic', '>= 0'
49
+ gem.add_runtime_dependency 'omniauth-google-oauth2', '>= 0'
45
50
  end
46
51
  Juwelier::RubygemsDotOrgTasks.new
47
52
  require 'rake/testtask'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.13
1
+ 0.1.14
data/bin/scout-camp CHANGED
@@ -2,6 +2,52 @@
2
2
 
3
3
  $LOAD_PATH.unshift File.join(__dir__, '../lib')
4
4
 
5
+ if _i = ARGV.index("--log")
6
+ require 'scout/log'
7
+ log = ARGV[_i+1]
8
+ Log.severity = log.to_i
9
+ ARGV.delete "--log"
10
+ ARGV.delete log
11
+ end
12
+
13
+ dev_dir = nil
14
+ if _i = ARGV.index("--dev")
15
+ dev_dir = ARGV[_i+1]
16
+ ARGV.delete "--dev"
17
+ ARGV.delete dev_dir
18
+ end
19
+
20
+ if dev_dir.nil?
21
+ _s = nil
22
+ ARGV.each_with_index do |s,i|
23
+ if s.match(/^--dev(?:=(.*))?/)
24
+ dev_dir = $1
25
+ _s = s
26
+ next
27
+ end
28
+ end
29
+ ARGV.delete _s if _s
30
+ end
31
+
32
+ if dev_dir.nil? && ENV["SCOUT_DEV"]
33
+ dev_dir = ENV["SCOUT_DEV"]
34
+ ARGV.delete "--dev"
35
+ ARGV.delete dev_dir
36
+ end
37
+
38
+ if dev_dir
39
+ ['scout-*/lib'].each do |pattern|
40
+ Dir.glob(File.join(File.expand_path(dev_dir), pattern)).each do |f|
41
+ $LOAD_PATH.unshift f
42
+ end
43
+ end
44
+ ['rbbt-*/lib'].each do |pattern|
45
+ Dir.glob(File.join(File.expand_path(dev_dir), pattern)).each do |f|
46
+ $LOAD_PATH.unshift f
47
+ end
48
+ end
49
+ end
50
+
5
51
  require 'scout-camp'
6
52
 
7
53
  load Scout.bin.scout.find
data/doc/terraform.md ADDED
@@ -0,0 +1,188 @@
1
+ # Using the Terraform DLS (Domain Specific Language)
2
+
3
+ This document describes how to use the Terraform DLS implemented in lib/scout/terraform_dsl to programmatically compose Terraform configurations and manage deployments from Ruby. It is written for AI agents (or developers) that will generate Ruby code to create, plan, apply and inspect Terraform deployments using the provided DSL.
4
+
5
+ Where things live
6
+
7
+ - Library implementation: lib/scout/terraform_dsl.rb and lib/scout/terraform_dsl/*.rb
8
+ - Utilities and runtime: lib/scout/terraform_dsl/util.rb and lib/scout/terraform_dsl/deployment.rb
9
+ - Example module templates: share/terraform (e.g. share/terraform/aws/*)
10
+
11
+ Key classes and concepts
12
+
13
+ - TerraformDSL: main class that models a planned Terraform deployment. You create a TerraformDSL instance, add modules, providers, backends, custom files, then call config to write template files into a directory.
14
+
15
+ - TerraformDSL::Module: returned by add(...) and acts as a reference to a module instance inside the generated Terraform configuration. You can call arbitrary methods on it to get references to its outputs (e.g. my_module.some_output), which serialize to Terraform references like module.<instance>.<output>.
16
+
17
+ - TerraformDSL::Module::Output: representation of an output reference that serializes to a module output reference in Terraform JSON form.
18
+
19
+ - TerraformDSL::Deployment: helper for interacting with Terraform in a directory created by TerraformDSL#config. It wraps terraform init/plan/apply/destroy/refresh and provides helpers for reading outputs and state.
20
+
21
+ - Misc helpers in TerraformDSL (util.rb):
22
+ - TerraformDSL.module_variables(module_dir) -> inspect variables.tf for a module
23
+ - TerraformDSL.module_outputs(module_dir) -> inspect output.tf for a module
24
+
25
+ Common workflow (example)
26
+
27
+ 1) Create a TerraformDSL and add elements/modules
28
+
29
+ ```ruby
30
+ require 'scout/terraform_dsl'
31
+
32
+ # Create DSL (by default it uses share/terraform as modules dir)
33
+ # You can pass a custom modules dir if needed
34
+ dsl = TerraformDSL.new
35
+
36
+ # Add a provider block (creates a provider config file)
37
+ # Returns a Module reference if a provider module exists at modules_dir/<name>/provider
38
+ # Example: add AWS provider configuration (set credentials/region via variables)
39
+ dsl.provider('aws', region: 'eu-west-1')
40
+
41
+ # Add a module instance using the shared templates under share/terraform
42
+ # add(provider, module_name, variables)
43
+ # variables[:name] defaults to "<provider>_<module_name>" but you can override
44
+ web = dsl.add('aws', 'host', name: 'web1', ami: 'ami-01234567', instance_type: 't3.micro')
45
+ db = dsl.add('aws', 'host', name: 'db1', ami: 'ami-01234567', instance_type: 't3.small')
46
+
47
+ # You can connect modules using module output references returned by Module instances
48
+ # E.g. use an output from db as input to web
49
+ # (Assuming the module exposes the output name you want)
50
+ # web2 = dsl.add('aws', 'some_module', name: 'web2', subnet_id: db.subnet_id)
51
+
52
+ # Request that specific outputs from a module become deployment outputs
53
+ # Provide outputs in variables[:outputs] or use :outputs => 'all'
54
+ app = dsl.add('aws','host', name: 'app1', ami: 'ami-01234567', outputs: ['aws_instance_id', 'aws_instance_ip'])
55
+ ```
56
+
57
+ 2) Add custom provider/backend/remote files if needed
58
+
59
+ ```ruby
60
+ # Add a backend configuration (example for s3 backend)
61
+ dsl.backend('s3', bucket: 'my-bucket', key: 'path/to/state', region: 'eu-west-1')
62
+
63
+ # Add a remote data block pointing to another state
64
+ # Returns a direct reference object you can use as a value in variables
65
+ other_state = dsl.remote('s3', 'shared_state', bucket: 'my-bucket', region: 'eu-west-1')
66
+ # other_state is a DirectReference object that serializes to a terraform reference
67
+
68
+ # Add arbitrary terraform content (for uncommon provider configs)
69
+ dsl.custom('provider.aws.extra', <<~TF)
70
+ provider "aws" {
71
+ # extra provider settings
72
+ }
73
+ TF
74
+ ```
75
+
76
+ 3) Generate config files into a directory
77
+
78
+ ```ruby
79
+ # Write files into a working dir (if you pass no arg, a directory based on elements digest is used)
80
+ config_dir = dsl.config # returns the directory path (Path-like) containing .tf files
81
+ # You can pass a path: dsl.config('/tmp/my-deploy')
82
+ ```
83
+
84
+ 4) Manage the terraform deployment
85
+
86
+ ```ruby
87
+ # Create a Deployment helper for that directory
88
+ deployment = TerraformDSL::Deployment.new(config_dir)
89
+
90
+ # Initialize provider plugins and backend
91
+ deployment.init
92
+
93
+ # Validate if wanted
94
+ deployment.validate
95
+
96
+ # Create a plan (saves plan to main.plan)
97
+ deployment.plan
98
+
99
+ # Apply (will run plan if you didn't)
100
+ deployment.apply
101
+
102
+ # Read outputs (hash with output_name => value)
103
+ outs = deployment.outputs
104
+ puts outs['app1_aws_instance_ip']
105
+
106
+ # Destroy the whole deployment
107
+ deployment.destroy
108
+ ```
109
+
110
+ Notes about Module references and variables
111
+
112
+ - When you call add(...) you get back a TerraformDSL::Module object representing that instance.
113
+ - Calling arbitrary methods on that object returns a Module::Output that serializes into the Terraform reference module.<instance>.<output>. Example: web.ami_id or web.aws_instance_id depending on module output name.
114
+ - You can directly use these Module output references when setting variables for other modules (they will be serialized correctly into the .tf generated files).
115
+
116
+ - The DSL also accepts values that are already Terraform-style strings such as "module.some_mod.some_output" — the DSL converts those into Output references when generating variable assignments.
117
+
118
+ Inspection utilities
119
+
120
+ - Inspect module variables (what variables a module expects):
121
+
122
+ ```ruby
123
+ module_dir = Scout.share.terraform['aws']['host']
124
+ vars = TerraformDSL.module_variables(module_dir)
125
+ # vars is a hash: { 'ami' => {description: '...', type: 'string', default: ...}, ... }
126
+
127
+ outs = TerraformDSL.module_outputs(module_dir)
128
+ # outs is a hash of available outputs and their descriptions
129
+ ```
130
+
131
+ Deployment helper details
132
+
133
+ - TerraformDSL::Deployment.run(cmd)
134
+ - Executes terraform <cmd> and returns stdout. Raises TerraformException on non-zero exit.
135
+
136
+ - TerraformDSL::Deployment.run_log(cmd, log_file=nil)
137
+ - Runs terraform <cmd> streaming STDERR and STDOUT into logs and raising TerraformException on error. Accepts a log_file to capture full logs.
138
+
139
+ - Useful methods on Deployment objects:
140
+ - init, plan, apply, refresh, validate, update (init+plan+apply), destroy
141
+ - plan_file -> path to stored plan (main.plan)
142
+ - log_file -> path to log file for that work directory
143
+ - outputs -> reads terraform output -json and returns a Ruby hash with values
144
+ - element_state(element) -> shows terraform state show <element>
145
+ - provisioned_elements -> terraform state list
146
+
147
+ Advanced: bundling and loading
148
+
149
+ - You can bundle a deployment directory into a tar.gz with Deployment#bundle(file) and load it back with Deployment.load(file). The loader will extract the bundle into a working dir and refresh the state.
150
+
151
+ Where to find module templates
152
+
153
+ - The default module directory is Scout.share.terraform which points to share/terraform in this repository. Look under share/terraform/aws, share/terraform/ssh etc. Each module is a directory containing Terraform templates (main.tf, variables.tf, output.tf, ...).
154
+
155
+ Example full script (end-to-end)
156
+
157
+ ```ruby
158
+ require 'scout/terraform_dsl'
159
+
160
+ # Build DSL
161
+ dsl = TerraformDSL.new
162
+ dsl.provider('aws', region: 'eu-west-1')
163
+ app = dsl.add('aws', 'host', name: 'app1', ami: 'ami-01234567', instance_type: 't3.micro', outputs: ['aws_instance_id','aws_instance_ip'])
164
+
165
+ # Generate files
166
+ config_dir = dsl.config
167
+
168
+ # Manage terraform
169
+ deployment = TerraformDSL::Deployment.new(config_dir)
170
+ deployment.init
171
+ deployment.plan
172
+ deployment.apply
173
+ puts deployment.outputs # => hash of outputs
174
+
175
+ # Cleanup
176
+ deployment.destroy
177
+ ```
178
+
179
+ Tips for agents generating code
180
+
181
+ - Always call dsl.config before creating a Deployment. config writes the .tf files and returns the directory path used by Deployment.
182
+ - Prefer using Module objects to pass references between modules instead of hard-coding strings. Example: db.private_ip (where db is the Module returned by add).
183
+ - Use TerraformDSL.module_variables and module_outputs to discover what a module expects/returns when generating variables and wiring between modules.
184
+ - Use Deployment.run_log when you want log files and streamed logs for troubleshooting.
185
+
186
+ If you need more examples, look at the modules under share/terraform/aws and share/terraform/ssh for real-world templates.
187
+
188
+ End of document
data/lib/scout/aws/s3.rb CHANGED
@@ -24,8 +24,10 @@ module Open
24
24
  def self.claim_uri(uri)
25
25
  if Path === uri and not uri.located?
26
26
  is_s3?(uri.find)
27
- else
27
+ elsif String === uri
28
28
  is_s3? uri
29
+ else
30
+ false
29
31
  end
30
32
  end
31
33
 
@@ -286,9 +288,9 @@ module Open
286
288
  end
287
289
 
288
290
  if Open.directory?(source)
289
- cmd = "aws s3 sync #{sync_args * " "} #{source} #{target}"
291
+ cmd = "aws s3 sync #{sync_args * " "} '#{source}' '#{target}'"
290
292
  else
291
- cmd = "aws s3 cp #{source} #{target}"
293
+ cmd = "aws s3 cp '#{source}' '#{target}'"
292
294
  end
293
295
  case other
294
296
  when String
@@ -296,7 +298,7 @@ module Open
296
298
  when Array
297
299
  cmd << " " << other * " "
298
300
  end
299
- cmd << " && rm -Rf #{source}" if delete && ! files
301
+ cmd << " && rm -Rf '#{source}'" if delete && ! files
300
302
 
301
303
  if print
302
304
  cmd
@@ -1,12 +1,45 @@
1
1
  require 'scout/resource'
2
2
  require_relative 'sync'
3
3
  module Resource
4
- def self.sync(path, map = nil, source: nil, target: nil, resource: nil, **kwargs)
5
- map = 'user' if map.nil?
4
+ class << self
5
+ attr_accessor :sync_servers, :file_servers
6
+
7
+ def sync_servers
8
+ @sync_servers ||= begin
9
+ config_file = Scout.etc.sync_servers.find_with_extension('yaml', produce: false)
10
+ if config_file.exists?(produce: false)
11
+ config_file.yaml
12
+ else
13
+ {}
14
+ end
15
+ end
16
+ end
17
+
18
+ def sync_server(resource)
19
+ return sync_servers[resource.to_s]
20
+ end
21
+
22
+ def file_servers
23
+ @file_servers ||= begin
24
+ config_file = Scout.etc.file_servers.find_with_extension('yaml', produce: false)
25
+ if config_file.exists?(produce: false)
26
+ config_file.yaml
27
+ else
28
+ {}
29
+ end
30
+ end
31
+ end
32
+
33
+ def file_server(resource)
34
+ return file_servers[resource.to_s]
35
+ end
36
+
37
+ end
6
38
 
39
+ def self.sync(path, map = nil, source: nil, target: nil, resource: nil, **kwargs)
7
40
  if source
8
41
  paths = [path]
9
- real_paths, identified_paths = SSHLine.locate(source, paths)
42
+ real_paths, identified_paths = SSHLine.locate(source, paths, map: nil)
10
43
  else
11
44
  resource = path.pkgdir if resource.nil? and path.is_a?(Path) and path.pkgdir.is_a?(Resource)
12
45
  resource = Resource.default_resource if resource.nil?
@@ -17,18 +50,90 @@ module Resource
17
50
  path = Path.setup(path, pkgdir: resource) unless path.is_a?(Path)
18
51
  real_paths = path.directory? ? path.find_all : path.glob_all
19
52
  end
20
-
53
+
21
54
  identified_paths = real_paths.collect{|path| resource.identify(path) }
22
55
  end
23
56
 
24
57
  if target
25
- target_paths = SSHLine.locate(target, identified_paths, map: map)
58
+ map = 'user' if map.nil?
59
+ target_paths, identified_paths = SSHLine.locate(target, identified_paths, map: map)
26
60
  else
27
61
  target_paths = identified_paths.collect{|p| p.find(map) }
28
62
  end
29
63
 
30
64
  real_paths.zip(target_paths).each do |source_path,target_path|
65
+ next if source_path.nil?
31
66
  Open.sync(source_path, target_path, kwargs.merge(source: source, target: target))
32
67
  end
33
68
  end
69
+
70
+ def self.get_from_server(path, final_path, remote_server)
71
+ url = File.join(remote_server, '/resource/', self.to_s, 'get_file')
72
+ url << "?" << Misc.hash2GET_params(:file => path, :create => false)
73
+
74
+ begin
75
+ @server_missing_resource_cache ||= Set.new
76
+ raise "Resource Not Found" if @server_missing_resource_cache.include? url
77
+ Net::HTTP.get_response URI(url) do |response|
78
+ case response
79
+ when Net::HTTPSuccess, Net::HTTPOK
80
+ Misc.sensiblewrite(final_path) do |file|
81
+ response.read_body do |chunk|
82
+ file.write chunk
83
+ end
84
+ end
85
+ when Net::HTTPRedirection, Net::HTTPFound
86
+ location = response['location']
87
+ Log.debug("Feching directory from: #{location}. Into: #{final_path}")
88
+ FileUtils.mkdir_p final_path unless File.exist? final_path
89
+ Misc.in_dir final_path do
90
+ CMD.cmd('tar xvfz -', :in => Open.open(location, :nocache => true))
91
+ end
92
+ when Net::HTTPInternalServerError
93
+ @server_missing_resource_cache << url
94
+ raise "Resource Not Found"
95
+ else
96
+ raise "Response not understood: #{response.inspect}"
97
+ end
98
+ end
99
+ rescue
100
+ Log.warn "Could not retrieve (#{self.to_s}) #{ path } from #{ remote_server }"
101
+ Log.error $!.message
102
+ Open.rm_rf final_path if Open.exist? final_path
103
+ raise $!
104
+ end
105
+ end
106
+
107
+ def file_server
108
+ Resource.file_server(self)
109
+ end
110
+
111
+ def sync_server
112
+ Resource.sync_server(self)
113
+ end
114
+
115
+ alias local_produce produce
116
+ def produce(path, *args, **kwargs)
117
+ if sync_server = self.sync_server
118
+ begin
119
+ Resource.sync(Resource.default_resource.identify(path), source: sync_server)
120
+ return path if Open.exists?(path)
121
+ rescue
122
+ Log.exception $!
123
+ end
124
+ end
125
+
126
+ if file_server = self.file_server
127
+ begin
128
+ Resource.get_from_server(Resource.default_resource.identify(path), path.find, file_server)
129
+ return path if Open.exists?(path)
130
+ rescue
131
+ Log.exception $!
132
+ end
133
+ end
134
+
135
+ local_produce(path, *args, **kwargs)
136
+ end
137
+
138
+
34
139
  end
@@ -5,7 +5,7 @@ require 'scout/workflow/step'
5
5
  module OffsiteStep
6
6
 
7
7
  extend Annotation
8
- annotation :server, :workflow_name, :clean_id, :slurm
8
+ annotation :server, :workflow_name, :clean_id, :batch
9
9
 
10
10
  def inputs_directory
11
11
  @inputs_directory ||= begin
@@ -13,7 +13,7 @@ module OffsiteStep
13
13
  file = ".scout/tmp/step_inputs/#{workflow}/#{task_name}/#{name}"
14
14
  TmpFile.with_path do |inputs_dir|
15
15
  save_inputs(inputs_dir)
16
- SSHLine.rsync(inputs_dir, file, target: server, directory: true)
16
+ SSHLine.rsync(inputs_dir, file, target: server, directory: inputs_dir.directory?)
17
17
  end
18
18
  file
19
19
  end
@@ -30,6 +30,13 @@ module OffsiteStep
30
30
  wf = Workflow.require_workflow "#{workflow_name}";
31
31
  EOF
32
32
 
33
+ rec_dependencies.collect{|d| d.workflow }.compact.uniq.each do |other_workflow|
34
+ next if workflow_name == other_workflow.to_s
35
+ parts << <<~EOF.strip
36
+ Workflow.require_workflow "#{other_workflow}" rescue nil;
37
+ EOF
38
+ end
39
+
33
40
  if inputs_directory
34
41
  parts << <<~EOF.strip
35
42
  job = wf.job(:#{task_name}, "#{clean_name}", :load_inputs => "#{inputs_directory}");
@@ -68,33 +75,33 @@ job = wf.job(:#{task_name}, "#{clean_name}");
68
75
  status == :done
69
76
  end
70
77
 
71
- def orchestrate_slurm
78
+ def orchestrate_batch
72
79
  bundle_files = offsite_job_ssh <<~EOF
73
80
  require 'rbbt/hpc'
74
- HPC::BATCH_MODULE = HPC.batch_system "SLURM"
75
- HPC::BATCH_MODULE.orchestrate_job(job, {})
81
+ rules = Workflow::Orchestrator.load_rules_for_job(job)
82
+ Workflow::Scheduler.produce(job, rules)
76
83
  job.join
77
84
  job.bundle_files
78
85
  EOF
79
86
  SSHLine.sync(bundle_files, source: server)
80
- self.load
81
87
  end
82
88
 
83
-
84
- def exec
89
+ def exec(noload)
85
90
  bundle_files = offsite_job_ssh <<~EOF
86
- job.run
91
+ Workflow.produce(job)
92
+ job.join
87
93
  job.bundle_files
88
94
  EOF
89
95
  SSHLine.sync(bundle_files, source: server)
90
- self.load
96
+ noload ? self.path : self.load
91
97
  end
92
98
 
93
- def run
94
- if slurm
95
- orchestrate_slurm
99
+ def run(noload=false)
100
+ if batch
101
+ orchestrate_batch
102
+ noload ? self.path : self.load
96
103
  else
97
- exec
104
+ exec(noload)
98
105
  end
99
106
  end
100
107
  end