scout-gear 10.7.4 → 10.7.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/.gitmodules +0 -4
- data/.vimproject +9 -14
- data/Rakefile +1 -4
- data/VERSION +1 -1
- data/lib/scout/association/index.rb +3 -3
- data/lib/scout/entity/identifiers.rb +5 -2
- data/lib/scout/entity/property.rb +1 -1
- data/lib/scout/knowledge_base/description.rb +108 -0
- data/lib/scout/knowledge_base/entity.rb +6 -1
- data/lib/scout/knowledge_base/registry.rb +43 -15
- data/lib/scout/knowledge_base.rb +3 -2
- data/lib/scout/tsv/change_id/translate.rb +9 -2
- data/lib/scout/tsv/open.rb +10 -0
- data/lib/scout/tsv/parser.rb +14 -3
- data/lib/scout/workflow/deployment/orchestrator.rb +9 -1
- data/lib/scout/workflow/deployment/queue.rb +26 -0
- data/lib/scout/workflow/entity.rb +99 -0
- data/lib/scout/workflow/export.rb +72 -0
- data/lib/scout/workflow/persist.rb +6 -0
- data/lib/scout/workflow/step/file.rb +3 -3
- data/lib/scout/workflow/step/info.rb +6 -0
- data/lib/scout/workflow/step/inputs.rb +11 -1
- data/lib/scout/workflow/step/provenance.rb +1 -2
- data/lib/scout/workflow/step/status.rb +1 -0
- data/lib/scout/workflow/step.rb +5 -3
- data/lib/scout/workflow/task/inputs.rb +2 -1
- data/lib/scout/workflow/task.rb +2 -1
- data/lib/scout/workflow.rb +11 -3
- data/lib/scout-gear.rb +5 -1
- data/scout-gear.gemspec +14 -18
- data/scout_commands/kb/config +3 -0
- data/scout_commands/kb/list +1 -0
- data/scout_commands/kb/query +2 -1
- data/scout_commands/kb/register +3 -1
- data/scout_commands/kb/show +4 -2
- data/scout_commands/workflow/cmd +116 -0
- data/scout_commands/workflow/process +82 -0
- data/scout_commands/workflow/task +15 -3
- data/test/data/person/README.md +17 -0
- data/test/scout/knowledge_base/test_description.rb +59 -0
- data/test/scout/workflow/task/test_dependencies.rb +7 -7
- data/test/scout/workflow/test_definition.rb +2 -2
- data/test/scout/workflow/test_entity.rb +58 -0
- data/test/scout/workflow/test_step.rb +1 -1
- metadata +14 -57
- data/lib/scout/offsite/exceptions.rb +0 -9
- data/lib/scout/offsite/ssh.rb +0 -175
- data/lib/scout/offsite/step.rb +0 -100
- data/lib/scout/offsite/sync.rb +0 -55
- data/lib/scout/offsite.rb +0 -3
- data/scout_commands/offsite +0 -30
- data/test/scout/offsite/test_ssh.rb +0 -15
- data/test/scout/offsite/test_step.rb +0 -32
- data/test/scout/offsite/test_sync.rb +0 -36
- data/test/scout/offsite/test_task.rb +0 -0
- data/test/scout/test_offsite.rb +0 -0
data/lib/scout/offsite/ssh.rb
DELETED
@@ -1,175 +0,0 @@
|
|
1
|
-
require 'net/ssh'
|
2
|
-
require_relative 'exceptions'
|
3
|
-
|
4
|
-
class SSHLine
|
5
|
-
class << self
|
6
|
-
attr_accessor :default_server
|
7
|
-
def default_server
|
8
|
-
@@default_server ||= begin
|
9
|
-
ENV["SCOUT_OFFSITE"] || ENV["SCOUT_SERVER"] || 'localhost'
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(host = :default, user = nil)
|
15
|
-
host = SSHLine.default_server if host.nil? || host == :default
|
16
|
-
@host = host
|
17
|
-
@user = user
|
18
|
-
|
19
|
-
@ssh = Net::SSH.start(@host, @user)
|
20
|
-
|
21
|
-
@ch = @ssh.open_channel do |ch|
|
22
|
-
ch.exec 'bash -l'
|
23
|
-
end
|
24
|
-
|
25
|
-
@ch.send_data("[[ -f ~/.scout/environment ]] && source ~/.scout/environment\n")
|
26
|
-
@ch.send_data("[[ -f ~/.rbbt/environment ]] && source ~/.rbbt/environment\n")
|
27
|
-
|
28
|
-
@ch.on_data do |_,data|
|
29
|
-
if m = data.match(/DONECMD: (\d+)\n/)
|
30
|
-
@exit_status = m[1].to_i
|
31
|
-
@output << data.sub(m[0],'')
|
32
|
-
serve_output
|
33
|
-
else
|
34
|
-
@output << data
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
@ch.on_extended_data do |_,c,err|
|
39
|
-
STDERR.write err
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
def self.reach?(server = SSHLine.default_server)
|
45
|
-
Persist.memory(server, :key => "Reach server") do
|
46
|
-
begin
|
47
|
-
CMD.cmd("ssh #{server} bash -l -c \"scout\"")
|
48
|
-
true
|
49
|
-
rescue Exception
|
50
|
-
false
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def send_cmd(command)
|
56
|
-
@output = ""
|
57
|
-
@complete_output = false
|
58
|
-
@ch.send_data(command+"\necho DONECMD: $?\n")
|
59
|
-
end
|
60
|
-
|
61
|
-
def serve_output
|
62
|
-
@complete_output = true
|
63
|
-
end
|
64
|
-
|
65
|
-
def run(command)
|
66
|
-
send_cmd(command)
|
67
|
-
@ssh.loop{ ! @complete_output}
|
68
|
-
if @exit_status.to_i == 0
|
69
|
-
return @output
|
70
|
-
else
|
71
|
-
raise SSHProcessFailed.new @host, command
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def ruby(script)
|
76
|
-
@output = ""
|
77
|
-
@complete_output = false
|
78
|
-
cmd = "ruby -e \"#{script.gsub('"','\\"')}\"\n"
|
79
|
-
Log.debug "Running ruby on #{@host}:\n#{ script }"
|
80
|
-
@ch.send_data(cmd)
|
81
|
-
@ch.send_data("echo DONECMD: $?\n")
|
82
|
-
@ssh.loop{ !@complete_output }
|
83
|
-
if @exit_status.to_i == 0
|
84
|
-
return @output
|
85
|
-
else
|
86
|
-
raise SSHProcessFailed.new @host, "Ruby script:\n#{script}"
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def scout(script)
|
91
|
-
scout_script =<<-EOF
|
92
|
-
require 'scout'
|
93
|
-
SSHLine.run_local do
|
94
|
-
#{script.strip}
|
95
|
-
end
|
96
|
-
EOF
|
97
|
-
|
98
|
-
m = ruby(scout_script)
|
99
|
-
Marshal.load m
|
100
|
-
end
|
101
|
-
|
102
|
-
def workflow(workflow, script)
|
103
|
-
preamble =<<-EOF
|
104
|
-
wf = Workflow.require_workflow('#{workflow}')
|
105
|
-
EOF
|
106
|
-
|
107
|
-
scout(preamble + "\n" + script)
|
108
|
-
end
|
109
|
-
|
110
|
-
class Mock < SSHLine
|
111
|
-
def initialize
|
112
|
-
end
|
113
|
-
|
114
|
-
def run(command)
|
115
|
-
CMD.cmd(command)
|
116
|
-
end
|
117
|
-
|
118
|
-
def ruby(script)
|
119
|
-
cmd = "ruby -e \"#{script.gsub('"','\\"')}\"\n"
|
120
|
-
CMD.cmd(cmd)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
@connections = {}
|
125
|
-
def self.open(host, user = nil)
|
126
|
-
@connections[[host, user]] ||=
|
127
|
-
begin
|
128
|
-
if host == 'localhost'
|
129
|
-
SSHLine::Mock.new
|
130
|
-
else
|
131
|
-
SSHLine.new host, user
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def self.run(server, cmd, options = nil)
|
137
|
-
cmd = cmd * " " if Array === cmd
|
138
|
-
cmd += " " + CMD.process_cmd_options(options) if options
|
139
|
-
open(server).run(cmd)
|
140
|
-
end
|
141
|
-
|
142
|
-
def self.ruby(server, script)
|
143
|
-
open(server).ruby(script)
|
144
|
-
end
|
145
|
-
|
146
|
-
def self.scout(server, script)
|
147
|
-
open(server).scout(script)
|
148
|
-
end
|
149
|
-
|
150
|
-
def self.workflow(server, workflow, script)
|
151
|
-
open(server).workflow(workflow, script)
|
152
|
-
end
|
153
|
-
|
154
|
-
def self.command(server, command, argv = [], options = nil)
|
155
|
-
command = "scout #{command}" unless command && command.include?('scout')
|
156
|
-
argv_str = (argv - ["--"]).collect{|v| '"' + v.to_s + '"' } * " "
|
157
|
-
command = "#{command} #{argv_str}"
|
158
|
-
Log.debug "Offsite #{server} running: #{command}"
|
159
|
-
run(server, command, options)
|
160
|
-
end
|
161
|
-
|
162
|
-
def self.mkdir(server, path)
|
163
|
-
self.run server, "mkdir -p '#{path}'"
|
164
|
-
end
|
165
|
-
|
166
|
-
def self.run_local(&block)
|
167
|
-
res = begin
|
168
|
-
old_stdout = STDOUT.dup; STDOUT.reopen(STDERR)
|
169
|
-
block.call
|
170
|
-
ensure
|
171
|
-
STDOUT.reopen(old_stdout)
|
172
|
-
end
|
173
|
-
puts Marshal.dump(res)
|
174
|
-
end
|
175
|
-
end
|
data/lib/scout/offsite/step.rb
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
require_relative '../workflow/step'
|
2
|
-
require_relative 'ssh'
|
3
|
-
require_relative 'sync'
|
4
|
-
|
5
|
-
module OffsiteStep
|
6
|
-
|
7
|
-
extend Annotation
|
8
|
-
annotation :server, :workflow_name, :clean_id, :slurm
|
9
|
-
|
10
|
-
def inputs_directory
|
11
|
-
@inputs_directory ||= begin
|
12
|
-
if provided_inputs && provided_inputs.any?
|
13
|
-
file = ".scout/tmp/step_inputs/#{workflow}/#{task_name}/#{name}"
|
14
|
-
TmpFile.with_path do |inputs_dir|
|
15
|
-
save_inputs(inputs_dir)
|
16
|
-
SSHLine.rsync(inputs_dir, file, target: server, directory: true)
|
17
|
-
end
|
18
|
-
file
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def workflow_name
|
24
|
-
@workflow_name || workflow.to_s
|
25
|
-
end
|
26
|
-
|
27
|
-
def offsite_job_ssh(script)
|
28
|
-
parts = []
|
29
|
-
parts << <<~EOF.strip
|
30
|
-
wf = Workflow.require_workflow "#{workflow_name}";
|
31
|
-
EOF
|
32
|
-
|
33
|
-
if inputs_directory
|
34
|
-
parts << <<~EOF.strip
|
35
|
-
job = wf.job(:#{task_name}, "#{clean_name}", :load_inputs => "#{inputs_directory}");
|
36
|
-
EOF
|
37
|
-
else
|
38
|
-
parts << <<~EOF.strip
|
39
|
-
job = wf.job(:#{task_name}, "#{clean_name}");
|
40
|
-
EOF
|
41
|
-
end
|
42
|
-
|
43
|
-
parts << script
|
44
|
-
|
45
|
-
|
46
|
-
SSHLine.scout server, parts * "\n"
|
47
|
-
end
|
48
|
-
|
49
|
-
def offsite_path
|
50
|
-
@path = offsite_job_ssh <<~EOF
|
51
|
-
job.path.identify
|
52
|
-
EOF
|
53
|
-
end
|
54
|
-
|
55
|
-
def info
|
56
|
-
info = @info ||= offsite_job_ssh <<~EOF
|
57
|
-
info = Open.exists?(job.info_file) ? job.info : {}
|
58
|
-
info[:running] = true if job.running?
|
59
|
-
info
|
60
|
-
EOF
|
61
|
-
|
62
|
-
@info = nil unless %w(done aborted error).include?(info[:status].to_s)
|
63
|
-
|
64
|
-
info
|
65
|
-
end
|
66
|
-
|
67
|
-
def done?
|
68
|
-
status == :done
|
69
|
-
end
|
70
|
-
|
71
|
-
def orchestrate_slurm
|
72
|
-
bundle_files = offsite_job_ssh <<~EOF
|
73
|
-
require 'rbbt/hpc'
|
74
|
-
HPC::BATCH_MODULE = HPC.batch_system "SLURM"
|
75
|
-
HPC::BATCH_MODULE.orchestrate_job(job, {})
|
76
|
-
job.join
|
77
|
-
job.bundle_files
|
78
|
-
EOF
|
79
|
-
SSHLine.sync(bundle_files, source: server)
|
80
|
-
self.load
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
def exec
|
85
|
-
bundle_files = offsite_job_ssh <<~EOF
|
86
|
-
job.run
|
87
|
-
job.bundle_files
|
88
|
-
EOF
|
89
|
-
SSHLine.sync(bundle_files, source: server)
|
90
|
-
self.load
|
91
|
-
end
|
92
|
-
|
93
|
-
def run
|
94
|
-
if slurm
|
95
|
-
orchestrate_slurm
|
96
|
-
else
|
97
|
-
exec
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
data/lib/scout/offsite/sync.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
class SSHLine
|
2
|
-
def self.locate(server, paths, map: :user)
|
3
|
-
SSHLine.scout server, <<-EOF
|
4
|
-
map = :#{map}
|
5
|
-
paths = [#{paths.collect{|p| "'" + p + "'" } * ", " }]
|
6
|
-
located = paths.collect{|p| Path.setup(p).find(map) }
|
7
|
-
identified = paths.collect{|p| Resource.identify(p) }
|
8
|
-
[located, identified]
|
9
|
-
EOF
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.rsync(source_path, target_path, directory: false, source: nil, target: nil, dry_run: false, hard_link: false)
|
13
|
-
rsync_args = "-avztHP --copy-unsafe-links --omit-dir-times "
|
14
|
-
|
15
|
-
rsync_args << "--link-dest '#{source_path}' " if hard_link && ! source
|
16
|
-
|
17
|
-
source_path = source_path + "/" if directory && ! source_path.end_with?("/")
|
18
|
-
target_path = target_path + "/" if directory && ! target_path.end_with?("/")
|
19
|
-
if target
|
20
|
-
SSHLine.mkdir target, File.dirname(target_path)
|
21
|
-
else
|
22
|
-
Open.mkdir(File.dirname(target_path))
|
23
|
-
end
|
24
|
-
|
25
|
-
cmd = 'rsync '
|
26
|
-
cmd << rsync_args
|
27
|
-
cmd << '-nv ' if dry_run
|
28
|
-
cmd << (source ? [source, source_path] * ":" : source_path) << " "
|
29
|
-
cmd << (target ? [target, target_path] * ":" : target_path) << " "
|
30
|
-
|
31
|
-
CMD.cmd_log(cmd, :log => Log::HIGH)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.sync(paths, source: nil, target: nil, map: :user, **kwargs)
|
35
|
-
source = nil if source == 'localhost'
|
36
|
-
target = nil if target == 'localhost'
|
37
|
-
|
38
|
-
if source
|
39
|
-
source_paths, identified_paths = SSHLine.locate(source, paths)
|
40
|
-
else
|
41
|
-
source_paths = paths.collect{|p| Path === p ? p.find : p }
|
42
|
-
identified_paths = paths.collect{|p| Resource.identify(p) }
|
43
|
-
end
|
44
|
-
|
45
|
-
if target
|
46
|
-
target_paths = SSHLine.locate(target, identified_paths, map: map)
|
47
|
-
else
|
48
|
-
target_paths = identified_paths.collect{|p| p.find(map) }
|
49
|
-
end
|
50
|
-
|
51
|
-
source_paths.zip(target_paths).each do |source_path,target_path|
|
52
|
-
rsync(source_path, target_path, source: source, target: target, **kwargs)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
data/lib/scout/offsite.rb
DELETED
data/scout_commands/offsite
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'scout'
|
4
|
-
require 'scout/offsite'
|
5
|
-
|
6
|
-
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
7
|
-
|
8
|
-
options = SOPT.setup <<EOF
|
9
|
-
|
10
|
-
Description of the tool
|
11
|
-
|
12
|
-
$ #{$0} [<options>] <where> <command> ... -- [<protected options>]
|
13
|
-
|
14
|
-
Run a command offsite. Use -- to make sure options reach the offsite
|
15
|
-
|
16
|
-
-h--help Print this help
|
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
|
-
where = ARGV.shift
|
28
|
-
command = ARGV.shift
|
29
|
-
|
30
|
-
puts SSHLine.command(where, command, ARGV)
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
-
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
-
|
4
|
-
class TestSSH < Test::Unit::TestCase
|
5
|
-
def test_marshal
|
6
|
-
return unless SSHLine.reach?
|
7
|
-
|
8
|
-
assert TrueClass === SSHLine.scout(:default, 'true')
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_localhost
|
12
|
-
assert SSHLine.scout('localhost', 'true')
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
-
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
-
|
4
|
-
class TestOffsiteStep < Test::Unit::TestCase
|
5
|
-
def test_offsite_task
|
6
|
-
workflow_code =<<-EOF
|
7
|
-
module TestWF
|
8
|
-
extend Workflow
|
9
|
-
|
10
|
-
input :string, :string, "String", "string"
|
11
|
-
task :string => :string do |string| string end
|
12
|
-
end
|
13
|
-
|
14
|
-
TestWF.directory = Path.setup("#{tmpdir.offsite.TestWF}")
|
15
|
-
EOF
|
16
|
-
|
17
|
-
TmpFile.with_file workflow_code, :extension => 'rb' do |wffile|
|
18
|
-
wf = Workflow.require_workflow wffile
|
19
|
-
|
20
|
-
job = wf.job(:string)
|
21
|
-
|
22
|
-
off = OffsiteStep.setup job, server: 'localhost', workflow_name: wffile
|
23
|
-
|
24
|
-
refute off.done?
|
25
|
-
assert_equal 'string', off.run
|
26
|
-
|
27
|
-
assert off.done?
|
28
|
-
assert_equal 'string', off.run
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
-
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
-
|
4
|
-
class TestSync < Test::Unit::TestCase
|
5
|
-
def test_sync
|
6
|
-
TmpFile.with_path do |tmpdir|
|
7
|
-
tmpdir = Scout.tmp.tmpdir_sync
|
8
|
-
tmpdir.dir1.foo.write("FOO")
|
9
|
-
tmpdir.dir1.bar.write("BAR")
|
10
|
-
|
11
|
-
TmpFile.with_path do |tmpdir2|
|
12
|
-
Misc.in_dir tmpdir2 do
|
13
|
-
SSHLine.sync([tmpdir.dir1], map: :current)
|
14
|
-
|
15
|
-
assert tmpdir2.glob("**/*").select{|f| f.include?('foo') }.any?
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_sync_dir_map
|
22
|
-
TmpFile.with_path do |tmpdir|
|
23
|
-
tmpdir = Scout.tmp.tmpdir_sync
|
24
|
-
tmpdir.dir1.foo.write("FOO")
|
25
|
-
tmpdir.dir1.bar.write("BAR")
|
26
|
-
|
27
|
-
TmpFile.with_path do |tmpdir2|
|
28
|
-
SSHLine.sync([tmpdir.dir1], map: tmpdir2)
|
29
|
-
Misc.in_dir tmpdir2 do
|
30
|
-
assert tmpdir2.glob("**/*").select{|f| f.include?('foo') }.any?
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
File without changes
|
data/test/scout/test_offsite.rb
DELETED
File without changes
|