scout-gear 7.3.0 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +44 -16
  3. data/Rakefile +6 -1
  4. data/VERSION +1 -1
  5. data/bin/scout +21 -7
  6. data/doc/lib/scout/path.md +35 -0
  7. data/doc/lib/scout/workflow/task.md +13 -0
  8. data/lib/rbbt-scout.rb +1 -0
  9. data/lib/scout/cmd.rb +24 -25
  10. data/lib/scout/concurrent_stream.rb +59 -39
  11. data/lib/scout/config.rb +1 -1
  12. data/lib/scout/exceptions.rb +10 -0
  13. data/lib/scout/log/color.rb +15 -12
  14. data/lib/scout/log/progress/report.rb +8 -6
  15. data/lib/scout/log/progress/util.rb +61 -54
  16. data/lib/scout/log/progress.rb +1 -1
  17. data/lib/scout/log/trap.rb +107 -0
  18. data/lib/scout/log.rb +115 -52
  19. data/lib/scout/meta_extension.rb +47 -6
  20. data/lib/scout/misc/digest.rb +12 -3
  21. data/lib/scout/misc/format.rb +24 -7
  22. data/lib/scout/misc/insist.rb +1 -1
  23. data/lib/scout/misc/monitor.rb +22 -0
  24. data/lib/scout/misc/system.rb +58 -0
  25. data/lib/scout/named_array.rb +73 -3
  26. data/lib/scout/offsite/ssh.rb +171 -0
  27. data/lib/scout/offsite/step.rb +83 -0
  28. data/lib/scout/offsite/sync.rb +55 -0
  29. data/lib/scout/offsite.rb +3 -0
  30. data/lib/scout/open/lock/lockfile.rb +587 -0
  31. data/lib/scout/open/lock.rb +9 -2
  32. data/lib/scout/open/remote.rb +16 -1
  33. data/lib/scout/open/stream.rb +146 -83
  34. data/lib/scout/open/util.rb +22 -3
  35. data/lib/scout/open.rb +5 -4
  36. data/lib/scout/path/find.rb +24 -11
  37. data/lib/scout/path/util.rb +40 -0
  38. data/lib/scout/persist/serialize.rb +19 -6
  39. data/lib/scout/persist.rb +29 -13
  40. data/lib/scout/resource/path.rb +57 -0
  41. data/lib/scout/resource/produce.rb +0 -8
  42. data/lib/scout/resource/util.rb +12 -5
  43. data/lib/scout/tmpfile.rb +7 -8
  44. data/lib/scout/tsv/attach.rb +177 -0
  45. data/lib/scout/tsv/change_id.rb +40 -0
  46. data/lib/scout/tsv/dumper.rb +74 -46
  47. data/lib/scout/tsv/index.rb +85 -87
  48. data/lib/scout/tsv/open.rb +160 -85
  49. data/lib/scout/tsv/parser.rb +142 -80
  50. data/lib/scout/tsv/path.rb +1 -2
  51. data/lib/scout/tsv/persist/adapter.rb +15 -45
  52. data/lib/scout/tsv/persist/fix_width_table.rb +3 -0
  53. data/lib/scout/tsv/persist/tokyocabinet.rb +6 -1
  54. data/lib/scout/tsv/persist.rb +4 -0
  55. data/lib/scout/tsv/stream.rb +204 -0
  56. data/lib/scout/tsv/transformer.rb +152 -0
  57. data/lib/scout/tsv/traverse.rb +96 -92
  58. data/lib/scout/tsv/util/filter.rb +9 -0
  59. data/lib/scout/tsv/util/reorder.rb +81 -0
  60. data/lib/scout/tsv/util/select.rb +78 -33
  61. data/lib/scout/tsv/util/unzip.rb +86 -0
  62. data/lib/scout/tsv/util.rb +60 -11
  63. data/lib/scout/tsv.rb +34 -4
  64. data/lib/scout/work_queue/socket.rb +6 -1
  65. data/lib/scout/work_queue/worker.rb +5 -2
  66. data/lib/scout/work_queue.rb +51 -20
  67. data/lib/scout/workflow/definition.rb +23 -3
  68. data/lib/scout/workflow/deployment/orchestrator.rb +245 -0
  69. data/lib/scout/workflow/deployment.rb +1 -0
  70. data/lib/scout/workflow/step/dependencies.rb +56 -10
  71. data/lib/scout/workflow/step/file.rb +5 -0
  72. data/lib/scout/workflow/step/info.rb +40 -7
  73. data/lib/scout/workflow/step/load.rb +1 -1
  74. data/lib/scout/workflow/step/provenance.rb +9 -7
  75. data/lib/scout/workflow/step/status.rb +43 -0
  76. data/lib/scout/workflow/step.rb +160 -49
  77. data/lib/scout/workflow/task/dependencies.rb +114 -0
  78. data/lib/scout/workflow/task/inputs.rb +40 -32
  79. data/lib/scout/workflow/task.rb +38 -102
  80. data/lib/scout/workflow/usage.rb +48 -18
  81. data/lib/scout/workflow.rb +4 -2
  82. data/lib/scout-gear.rb +2 -0
  83. data/lib/scout.rb +6 -0
  84. data/scout-gear.gemspec +52 -23
  85. data/scout_commands/doc +37 -0
  86. data/scout_commands/find +1 -0
  87. data/scout_commands/offsite +30 -0
  88. data/scout_commands/update +29 -0
  89. data/scout_commands/workflow/info +15 -3
  90. data/scout_commands/workflow/install +102 -0
  91. data/scout_commands/workflow/task +57 -9
  92. data/test/scout/offsite/test_ssh.rb +15 -0
  93. data/test/scout/offsite/test_step.rb +33 -0
  94. data/test/scout/offsite/test_sync.rb +36 -0
  95. data/test/scout/offsite/test_task.rb +0 -0
  96. data/test/scout/open/test_stream.rb +60 -58
  97. data/test/scout/path/test_find.rb +10 -1
  98. data/test/scout/resource/test_path.rb +6 -0
  99. data/test/scout/resource/test_produce.rb +15 -0
  100. data/test/scout/test_meta_extension.rb +25 -0
  101. data/test/scout/test_named_array.rb +24 -0
  102. data/test/scout/test_persist.rb +9 -2
  103. data/test/scout/test_tsv.rb +229 -2
  104. data/test/scout/test_work_queue.rb +65 -41
  105. data/test/scout/tsv/persist/test_tokyocabinet.rb +29 -1
  106. data/test/scout/tsv/test_attach.rb +227 -0
  107. data/test/scout/tsv/test_change_id.rb +98 -0
  108. data/test/scout/tsv/test_dumper.rb +1 -1
  109. data/test/scout/tsv/test_index.rb +49 -3
  110. data/test/scout/tsv/test_open.rb +160 -2
  111. data/test/scout/tsv/test_parser.rb +33 -2
  112. data/test/scout/tsv/test_persist.rb +2 -0
  113. data/test/scout/tsv/test_stream.rb +200 -0
  114. data/test/scout/tsv/test_transformer.rb +120 -0
  115. data/test/scout/tsv/test_traverse.rb +88 -3
  116. data/test/scout/tsv/test_util.rb +1 -0
  117. data/test/scout/tsv/util/test_reorder.rb +94 -0
  118. data/test/scout/tsv/util/test_select.rb +25 -11
  119. data/test/scout/tsv/util/test_unzip.rb +112 -0
  120. data/test/scout/work_queue/test_socket.rb +0 -1
  121. data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
  122. data/test/scout/workflow/step/test_dependencies.rb +68 -0
  123. data/test/scout/workflow/step/test_info.rb +18 -0
  124. data/test/scout/workflow/step/test_status.rb +30 -0
  125. data/test/scout/workflow/task/test_dependencies.rb +355 -0
  126. data/test/scout/workflow/task/test_inputs.rb +67 -14
  127. data/test/scout/workflow/test_definition.rb +18 -0
  128. data/test/scout/workflow/test_documentation.rb +24 -0
  129. data/test/scout/workflow/test_step.rb +112 -3
  130. data/test/scout/workflow/test_task.rb +0 -151
  131. data/test/scout/workflow/test_usage.rb +33 -6
  132. data/test/test_scout.rb +9 -0
  133. metadata +100 -8
  134. data/scout_commands/workflow/task_old +0 -706
@@ -0,0 +1,272 @@
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 TestOrchestrator < Test::Unit::TestCase
5
+ setup do
6
+ module TestWF
7
+ extend Workflow
8
+
9
+ MULT = 0.01
10
+ task :a => :text do
11
+ sleep(TestWF::MULT * (rand(10) + 2))
12
+ end
13
+
14
+ dep :a
15
+ task :b => :text do
16
+ sleep(TestWF::MULT * (rand(10) + 2))
17
+ end
18
+
19
+ dep :a
20
+ dep :b
21
+ task :c => :text do
22
+ sleep(TestWF::MULT * (rand(10) + 2))
23
+ end
24
+
25
+ dep :c
26
+ task :d => :text do
27
+ sleep(TestWF::MULT * (rand(10) + 2))
28
+ end
29
+
30
+ dep :c
31
+ task :e => :text do
32
+ sleep(TestWF::MULT * (rand(10) + 2))
33
+ end
34
+ end
35
+ end
36
+
37
+ def TODO_test_orchestrate_resources
38
+
39
+ jobs =[]
40
+
41
+ num = 10
42
+ num.times do |i|
43
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
44
+ end
45
+ jobs.each do |j| j.recursive_clean end
46
+
47
+ rules = YAML.load <<-EOF
48
+ defaults:
49
+ log: 4
50
+ default_resources:
51
+ IO: 1
52
+ TestWF:
53
+ a:
54
+ resources:
55
+ cpus: 7
56
+ b:
57
+ resources:
58
+ cpus: 2
59
+ c:
60
+ resources:
61
+ cpus: 10
62
+ d:
63
+ resources:
64
+ cpus: 15
65
+ EOF
66
+
67
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
68
+ Log.with_severity 0 do
69
+ orchestrator.process(rules, jobs)
70
+ end
71
+
72
+ data = Workflow.trace jobs, :plot_data => true
73
+ eend = data.column("End.second").values.collect{|v| v.to_f}.max
74
+ second_cpus = TSV.setup({}, "Second~CPUS#:type=:single#:cast=:to_f")
75
+ (0..eend.to_i).each do |second|
76
+ tasks = data.select("Start.second"){|s| s <= second}.select("End.second"){|s| s > second}
77
+ cpus = 0
78
+ tasks.through :key, ["Workflow", "Task"] do |k, values|
79
+ workflow, task = values
80
+ cpus += rules[workflow][task.to_s]["resources"]["cpus"]
81
+ end
82
+ second_cpus[second] = cpus
83
+ end
84
+
85
+ assert Misc.mean(second_cpus.values) > 15
86
+ assert Misc.mean(second_cpus.values) < 30
87
+ end
88
+
89
+ def TODO_test_orchestrate_erase
90
+
91
+ jobs =[]
92
+
93
+ num = 10
94
+ num.times do |i|
95
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
96
+ end
97
+ jobs.each do |j| j.recursive_clean end
98
+
99
+ rules = YAML.load <<-EOF
100
+ defaults:
101
+ log: 4
102
+ default_resources:
103
+ IO: 1
104
+ TestWF:
105
+ a:
106
+ erase: true
107
+ resources:
108
+ cpus: 7
109
+ b:
110
+ erase: true
111
+ resources:
112
+ cpus: 2
113
+ c:
114
+ resources:
115
+ cpus: 10
116
+ d:
117
+ resources:
118
+ cpus: 15
119
+ EOF
120
+
121
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
122
+ Log.with_severity 3 do
123
+ orchestrator.process(rules, jobs)
124
+ end
125
+
126
+ jobs.each do |job|
127
+ assert job.step(:c).dependencies.empty?
128
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/a/")}.any?
129
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/b/")}.any?
130
+ end
131
+
132
+ end
133
+
134
+ def TODO_test_orchestrate_default
135
+
136
+ jobs =[]
137
+
138
+ num = 3
139
+ num.times do |i|
140
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
141
+ end
142
+ jobs.each do |j| j.recursive_clean end
143
+
144
+ rules = YAML.load <<-EOF
145
+ defaults:
146
+ erase: true
147
+ log: 4
148
+ default_resources:
149
+ IO: 1
150
+ TestWF:
151
+ a:
152
+ erase: true
153
+ resources:
154
+ cpus: 7
155
+ b:
156
+ erase: true
157
+ resources:
158
+ cpus: 2
159
+ c:
160
+ erase: false
161
+ resources:
162
+ cpus: 10
163
+ d:
164
+ resources:
165
+ cpus: 15
166
+ EOF
167
+
168
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
169
+ Log.with_severity 3 do
170
+ orchestrator.process(rules, jobs)
171
+ end
172
+
173
+ jobs.each do |job|
174
+ assert job.step(:c).dependencies.empty?
175
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/a/")}.any?
176
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/b/")}.any?
177
+ end
178
+
179
+ end
180
+
181
+ def TODO_test_orchestrate_top_level
182
+
183
+ jobs =[]
184
+
185
+ num = 3
186
+ num.times do |i|
187
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
188
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:c, name + " #{i}") }
189
+ end
190
+ jobs.each do |j| j.recursive_clean end
191
+
192
+ rules = YAML.load <<-EOF
193
+ defaults:
194
+ erase: true
195
+ log: 4
196
+ default_resources:
197
+ IO: 1
198
+ TestWF:
199
+ a:
200
+ resources:
201
+ cpus: 7
202
+ b:
203
+ resources:
204
+ cpus: 2
205
+ c:
206
+ resources:
207
+ cpus: 10
208
+ d:
209
+ resources:
210
+ cpus: 15
211
+ EOF
212
+
213
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
214
+ Log.with_severity 3 do
215
+ orchestrator.process(rules, jobs)
216
+ end
217
+
218
+ jobs.each do |job|
219
+ next unless job.task_name.to_s == 'd'
220
+ assert job.step(:c).dependencies.empty?
221
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/a/")}.any?
222
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/b/")}.any?
223
+ end
224
+
225
+ end
226
+
227
+ def TODO_test_orchestrate_top_level_double_dep
228
+
229
+ jobs =[]
230
+
231
+ num = 10
232
+ num.times do |i|
233
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:e, name + " #{i}") }
234
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
235
+ end
236
+ jobs.each do |j| j.recursive_clean end
237
+
238
+ rules = YAML.load <<-EOF
239
+ defaults:
240
+ erase: true
241
+ log: 4
242
+ default_resources:
243
+ IO: 1
244
+ TestWF:
245
+ a:
246
+ resources:
247
+ cpus: 7
248
+ b:
249
+ resources:
250
+ cpus: 2
251
+ c:
252
+ resources:
253
+ cpus: 10
254
+ d:
255
+ resources:
256
+ cpus: 15
257
+ EOF
258
+
259
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
260
+ Log.with_severity 3 do
261
+ orchestrator.process(rules, jobs)
262
+ end
263
+
264
+ jobs.each do |job|
265
+ next unless job.task_name.to_s == 'd' || job.task_name.to_s == 'e'
266
+ assert job.info[:archived_info].keys.select{|k| k.include?("TestWF/c/")}.any?
267
+ assert job.info[:archived_info].keys.select{|k| k.include?("TestWF/c/")}.any?
268
+ end
269
+
270
+ end
271
+ end
272
+
@@ -21,5 +21,73 @@ class TestStepDependencies < Test::Unit::TestCase
21
21
  assert_equal 2, step2.inputs[:input2]
22
22
  assert_equal "12", step2.recursive_inputs[:input1]
23
23
  end
24
+
25
+ def test_can_fail
26
+ tmpfile = tmpdir.test_step
27
+ step1 = Step.new tmpfile.step1, NamedArray.setup(["12"], %w(input1)) do |s|
28
+ raise ScoutException
29
+ end
30
+
31
+ step2 = Step.new tmpfile.step2, NamedArray.setup([2], %w(input2)) do |times|
32
+ step1 = dependencies.first
33
+ if step1.error?
34
+ (step1.inputs.first + " has unknown characters") * times
35
+ else
36
+ (step1.inputs.first + " has " + step1.load.to_s + " characters") * times
37
+ end
38
+ end
39
+
40
+ step2.dependencies = [step1]
41
+ step2.compute = {step1.path => [:canfail] }
42
+
43
+ assert_include step2.run, "unknown"
44
+ end
45
+
46
+ def test_can_stream
47
+ tmpfile = tmpdir.test_step
48
+
49
+ Misc.with_env "SCOUT_EXPLICIT_STREAMING", "true" do
50
+ times = 10_000
51
+ sleep = 1 / times
52
+
53
+ step1 = Step.new tmpfile.step1, [times, sleep] do |times,sleep|
54
+ Open.open_pipe do |sin|
55
+ times.times do |i|
56
+ sin.puts "line-#{i}"
57
+ sleep sleep
58
+ end
59
+ end
60
+ end
61
+ step1.type = :array
62
+
63
+ step2 = Step.new tmpfile.step2 do
64
+ step1 = dependencies.first
65
+ raise ScoutException unless step1.streaming?
66
+ stream = step1.stream
67
+
68
+ Open.open_pipe do |sin|
69
+ while line = stream.gets
70
+ num = line.split("-").last
71
+ next if num.to_i % 2 == 1
72
+ sin.puts line
73
+ end
74
+ end
75
+ end
76
+ step2.type = :array
77
+ step2.dependencies = [step1]
78
+
79
+ assert_raise ScoutException do
80
+ step2.run
81
+ end
82
+
83
+ step2.recursive_clean
84
+
85
+ step2.compute = {step1.path => [:stream]}
86
+
87
+ assert_nothing_raised do
88
+ step2.run
89
+ end
90
+ end
91
+ end
24
92
  end
25
93
 
@@ -25,4 +25,22 @@ class TestStepInfo < Test::Unit::TestCase
25
25
  assert_equal "12 has 2 characters", step2.run
26
26
  end
27
27
  end
28
+
29
+ def test_inputs_marshal
30
+ TmpFile.with_file do |tmpdir|
31
+ Path.setup(tmpdir)
32
+ tmpfile = tmpdir.test_step
33
+
34
+ path = tmpfile.foo
35
+ step1 = Step.new tmpfile.step1, [path] do |s|
36
+ s.length
37
+ end
38
+
39
+ step1.run
40
+
41
+ refute Path === step1.info[:inputs][0]
42
+
43
+ end
44
+
45
+ end
28
46
  end
@@ -0,0 +1,30 @@
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 TestStepStatus < Test::Unit::TestCase
5
+ def test_dependency
6
+ tmpfile = tmpdir.test_step
7
+ step1 = Step.new tmpfile.step1, ["12"] do |s|
8
+ s.length
9
+ end
10
+
11
+ step2 = Step.new tmpfile.step2 do
12
+ step1 = dependencies.first
13
+ step1.inputs.first + " has " + step1.load.to_s + " characters"
14
+ end
15
+
16
+ step2.dependencies = [step1]
17
+
18
+ Misc.with_env "SCOUT_UPDATE", "true" do
19
+ step2.run
20
+ assert step2.updated?
21
+
22
+ sleep 0.1
23
+ step1.clean
24
+ step1.run
25
+ refute step2.updated?
26
+ end
27
+ end
28
+
29
+ end
30
+