laborantin 0.0.14 → 0.0.21

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 (46) hide show
  1. data/INFO +1 -0
  2. data/README +148 -4
  3. data/Rakefile +73 -27
  4. data/TODO +27 -6
  5. data/bin/labor +2 -404
  6. data/lib/laborantin.rb +13 -26
  7. data/lib/laborantin/core/analysis.rb +231 -0
  8. data/lib/laborantin/core/command.rb +234 -0
  9. data/lib/laborantin/core/completeable.rb +30 -0
  10. data/lib/laborantin/core/configurable.rb +28 -0
  11. data/lib/laborantin/core/datable.rb +13 -0
  12. data/lib/laborantin/core/describable.rb +11 -0
  13. data/lib/laborantin/core/environment.rb +90 -52
  14. data/lib/laborantin/core/hookable.rb +20 -0
  15. data/lib/laborantin/core/monkey_patches.rb +0 -1
  16. data/lib/laborantin/core/multi_name.rb +25 -0
  17. data/lib/laborantin/core/parameter.rb +5 -12
  18. data/lib/laborantin/core/parameter_hash.rb +6 -2
  19. data/lib/laborantin/core/scenario.rb +93 -70
  20. data/lib/laborantin/core/table.rb +84 -0
  21. data/lib/laborantin/extra/commands/git.rb +40 -0
  22. data/lib/laborantin/extra/commands/git/check.rb +25 -0
  23. data/lib/laborantin/extra/commands/git/run.rb +100 -0
  24. data/lib/laborantin/extra/vectorial_product.rb +31 -0
  25. data/lib/laborantin/runner.rb +247 -0
  26. data/lib/laborantin/runner/commands/analyze.rb +58 -0
  27. data/lib/laborantin/runner/commands/cleanup.rb +40 -0
  28. data/lib/laborantin/runner/commands/complete.rb +111 -0
  29. data/lib/laborantin/runner/commands/config.rb +169 -0
  30. data/lib/laborantin/runner/commands/create.rb +61 -0
  31. data/lib/laborantin/runner/commands/describe.rb +215 -0
  32. data/lib/laborantin/runner/commands/find.rb +82 -0
  33. data/lib/laborantin/runner/commands/load_classes.rb +75 -0
  34. data/lib/laborantin/runner/commands/load_results.rb +143 -0
  35. data/lib/laborantin/runner/commands/note.rb +35 -0
  36. data/lib/laborantin/runner/commands/replay.rb +89 -0
  37. data/lib/laborantin/runner/commands/rm.rb +107 -0
  38. data/lib/laborantin/runner/commands/run.rb +131 -0
  39. data/lib/laborantin/runner/commands/scan.rb +77 -0
  40. metadata +45 -13
  41. data/bin/files/README.erb +0 -29
  42. data/bin/files/TODO.erb +0 -2
  43. data/bin/files/config/ftp.yaml.erb +0 -6
  44. data/bin/files/config/xmpp.yaml.erb +0 -7
  45. data/bin/files/environments/environment.rb.erb +0 -10
  46. data/bin/files/scenarii/scenario.rb.erb +0 -13
@@ -0,0 +1,58 @@
1
+ #runner/commands/analyze.rb
2
+
3
+ =begin
4
+
5
+ This file is part of Laborantin.
6
+
7
+ Laborantin is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Laborantin is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with Laborantin. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ Copyright (c) 2009, Lucas Di Cioccio
21
+
22
+ =end
23
+
24
+ module Laborantin
25
+ module Commands
26
+ class Analyze < Command
27
+ describe "Runs the analyses"
28
+
29
+ option(:analyses) do
30
+ describe "comma separated list of analyses"
31
+ short '-a'
32
+ long '--analyses=OPTIONAL'
33
+ default []
34
+ type Array
35
+ complete do |cmd|
36
+ completion_propositions_iterating_on(cmd, Laborantin::Analysis.all.map(&:cli_name))
37
+ end
38
+ end
39
+
40
+ execute do
41
+ anae = if opts[:analyses].empty?
42
+ Analysis.all
43
+ else
44
+ Analysis.all.select do |e|
45
+ opts[:analyses].find do |cli_name|
46
+ cli_name == e.cli_name
47
+ end
48
+ end
49
+ end
50
+
51
+ anae.each do |klass|
52
+ puts "Analyzing: #{klass.name}"
53
+ klass.new.analyze
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,40 @@
1
+ #runner/commands/cleanup.rb
2
+
3
+ =begin
4
+
5
+ This file is part of Laborantin.
6
+
7
+ Laborantin is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Laborantin is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with Laborantin. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ Copyright (c) 2009, Lucas Di Cioccio
21
+
22
+ =end
23
+
24
+ module Laborantin
25
+ module Commands
26
+ class Cleanup < Command
27
+ plumbery!
28
+ describe "Removes the result directories of the environments without scenarios"
29
+ execute do
30
+ results = Laborantin::Commands::LoadResults.new.run([],opts)
31
+ results[:envs].each do |env|
32
+ scii = env.populate
33
+ if scii.empty?
34
+ FileUtils.rm_rf(env.rundir, :verbose => true)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,111 @@
1
+
2
+ #$DEBUG = true
3
+
4
+ module Laborantin
5
+ module Commands
6
+ class Complete < Laborantin::Command
7
+ describe "completes a command line"
8
+ plumbery!
9
+
10
+ def maps_to_a_klass?(cmd)
11
+ runner.command_for_argv(cmd.split(' '))
12
+ end
13
+
14
+ def list_mapping_klasses(str)
15
+ #separate the case for modules
16
+ # labor config <tab>
17
+ # should propose config set|foo
18
+ if str == 'labor'
19
+ Command.reject(&:plumbery?).map{|cmd| runner.argv_klass_name(cmd).first}
20
+ else
21
+ size = str.split.size
22
+ cmds = Command.reject{|cmd| cmd.plumbery?}.map do |cmd|
23
+ runner.argv_klass_name(cmd).slice(0, size)
24
+ end
25
+
26
+ match = cmds.find do |cmd|
27
+ cmd.join(' ') == str
28
+ end
29
+
30
+ if match
31
+ cmds = Command.reject{|cmd| cmd.plumbery?}.map do |cmd|
32
+ runner.argv_klass_name(cmd).slice(0, size+1)
33
+ end
34
+ end
35
+
36
+ cmds.select do |cmd|
37
+ tst = cmd.join(' ').start_with?(str)
38
+ STDERR.puts "#{cmd} | #{str} | #{tst}" if $DEBUG
39
+ tst
40
+ end.map do |cmd|
41
+ cmd.last
42
+ end
43
+ end
44
+ end
45
+
46
+ def complete_option(opt, cmd)
47
+ opt.completion_block.call(cmd) if opt.completion_block
48
+ end
49
+
50
+ def list_long_option(klass, cmd)
51
+ # in the options of the command look for the one with long
52
+ opt = klass.options.find{|o| o.cli_long == cmd.split.last}
53
+
54
+ if opt
55
+ complete_option(opt,cmd)
56
+ else
57
+ end
58
+ end
59
+
60
+ def list_short_option(klass, cmd)
61
+ # in the options of the command look for the one with long
62
+ opt = klass.options.find{|o| o.cli_short == cmd.split.last}
63
+ if opt
64
+ complete_option(opt,cmd)
65
+ else
66
+ if cmd.split[-2].start_with?('-')
67
+ opt = klass.options.find{|o| o.cli_short == cmd.split[-2]}
68
+ complete_option(opt,cmd) if opt
69
+ else
70
+ klass.options.map(&:cli_short).select{|w|
71
+ w.start_with?(cmd)
72
+ }
73
+ end
74
+ end
75
+ end
76
+
77
+ def list_argv_and_options_line(klass, cmd)
78
+ klass.completion_block.call(cmd) if klass.completion_block
79
+ end
80
+
81
+ execute do |me|
82
+ STDERR.puts me.args if $DEBUG
83
+ cmd = STDIN.read.chomp
84
+ arg = me.args
85
+ cmd = cmd.sub(/^labor\s+/,'')
86
+
87
+ klass = maps_to_a_klass?(cmd)
88
+ list = if klass
89
+ if cmd.split.last.start_with?('--')
90
+ list_long_option(klass, cmd)
91
+ elsif cmd.split.last.start_with?('-')
92
+ list_short_option(klass, cmd)
93
+ elsif cmd.split[-2] and cmd.split[-2].start_with?('--')
94
+ list_long_option(klass, cmd)
95
+ elsif cmd.split[-2] and cmd.split[-2].start_with?('-')
96
+ list_short_option(klass, cmd)
97
+ else
98
+ list_argv_and_options_line(klass, cmd)
99
+ end
100
+ else
101
+ # complete finding a class
102
+ list_mapping_klasses(cmd)
103
+ end
104
+
105
+ list ||= []
106
+
107
+ puts list.compact.uniq.join("\n")
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,169 @@
1
+
2
+ module Laborantin::Commands
3
+ module Config
4
+
5
+ class ConfigError < StandardError ; end
6
+
7
+ class PathError < ConfigError ; end
8
+
9
+ class RootNotHashError < PathError
10
+ def initialize
11
+ super "The root node of the config must be a Hash"
12
+ end
13
+ end
14
+
15
+ class PathNotHashError < PathError
16
+ def initialize(path)
17
+ super "There already is a non-hash value at: '#{path}'."
18
+ end
19
+ end
20
+
21
+ # Stores the runner configuration into the configuration file.
22
+ def save_config
23
+ raise RootNotHashError unless runner.config.is_a? Hash
24
+ File.open(runner.config_path, 'w') do |f|
25
+ f.puts YAML.dump(runner.config)
26
+ end
27
+ end
28
+
29
+ # Interprets a string provided path as an array of symbols (the nodes of the config tree).
30
+ def interpret_path(path)
31
+ path.split(':').map{|i| i.to_sym}
32
+ end
33
+
34
+ # Interprets a string provided value into a ruby object.
35
+ # * if val is 'true' then the true object of class TrueClass
36
+ # * if val is 'false' then the false object of class FalseClass * if val is
37
+ # a string that can be read like a decimal, it's a decimal (Fixnum or
38
+ # Bignum), unlike in ruby interpreter 1_000 is not valid for 1000, see
39
+ # source for details * otherwise the string val itself
40
+ def interpret_value(val)
41
+ case val
42
+ when 'true'
43
+ true
44
+ when 'false'
45
+ false
46
+ when val.to_i.to_s == val
47
+ val.to_i
48
+ else
49
+ val
50
+ end
51
+ end
52
+
53
+ # Given a path made of an array of nodes (i.e., symbols to respect the syntax).
54
+ # Returns the object corresponding to this node in the configuration tree.
55
+ # Returns nil if there is no such object.
56
+ # If path is empty, simply returns the root node (i.e., the runner's config).
57
+ def get_node(path)
58
+ tree = runner.config
59
+ return tree if path.empty? #easy solution
60
+ path = path.clone
61
+ while (node = path.shift)
62
+ if tree.is_a? Hash
63
+ if path.empty? #terminal node
64
+ return tree[node]
65
+ else
66
+ tree = tree[node]
67
+ end
68
+ else #error
69
+ return nil
70
+ end
71
+ end
72
+ end
73
+
74
+ # Creates a path structure in the runner's config.
75
+ # If there already a non-hash node, will raise an error.
76
+ def build_path(path_arg)
77
+ path = path_arg.clone
78
+ tree = runner.config
79
+ while (node = path.shift)
80
+ case tree[node]
81
+ when Hash
82
+ tree = tree[node]
83
+ when NilClass
84
+ tree[node] = Hash.new
85
+ tree = tree[node]
86
+ else
87
+ raise PathNotHashError.new(orig.join(':'))
88
+ end
89
+ end
90
+ end
91
+
92
+ class Get < Laborantin::Command
93
+ include Config
94
+ describe "Show a configuration tree"
95
+ option(:path) do
96
+ describe "a column separated path of the config"
97
+ short '-p'
98
+ long '--path=OPTIONAL'
99
+ type String
100
+ default ''
101
+ end
102
+ execute do
103
+ path = interpret_path(opts[:path])
104
+ p get_node(path)
105
+ end
106
+ end
107
+
108
+ class Set < Laborantin::Command
109
+ include Config
110
+ describe "Set a configuration node"
111
+ option(:path) do
112
+ describe "a column separated path of the config"
113
+ short '-p'
114
+ long '--path=MANDATORY'
115
+ type String
116
+ default ''
117
+ end
118
+ option(:value) do
119
+ describe "the value to set the node to, interprets true, false, decimal integers, or string"
120
+ short '-v'
121
+ long '--value=MANDATORY'
122
+ type String
123
+ default ''
124
+ end
125
+ execute do
126
+ path = interpret_path(opts[:path])
127
+ value = interpret_value(opts[:value])
128
+ if path.empty?
129
+ puts "--path= should not be empty"
130
+ end
131
+ if value.is_a? String and value.empty?
132
+ puts "--value= should not be empty"
133
+ end
134
+
135
+ node = path.pop
136
+ begin
137
+ build_path(path)
138
+ rescue PathError => err
139
+ puts err
140
+ exit
141
+ end
142
+ get_node(path)[node] = value
143
+ save_config
144
+ end
145
+ end
146
+
147
+ class Del < Laborantin::Command
148
+ include Config
149
+ describe "Deletes a node from the configuration tree."
150
+ option(:path) do
151
+ describe "a column separated path"
152
+ short '-p'
153
+ long '--path=MANDATORY'
154
+ type String
155
+ default ''
156
+ end
157
+ execute do
158
+ path = interpret_path(opts[:path])
159
+ if path.empty?
160
+ puts "Cannot delete empty path, if you really want, remove #{runner.config_path}"
161
+ end
162
+ node = path.pop
163
+ tree = get_node(path)
164
+ tree.delete(node)
165
+ save_config
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,61 @@
1
+ #runner/commands/create.rb
2
+
3
+ =begin
4
+
5
+ This file is part of Laborantin.
6
+
7
+ Laborantin is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Laborantin is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with Laborantin. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ Copyright (c) 2009, Lucas Di Cioccio
21
+
22
+ =end
23
+
24
+ require 'fileutils'
25
+ require 'find'
26
+ require 'erb'
27
+
28
+ module Laborantin
29
+ module Commands
30
+ class Create < Command
31
+ describe "prepares a directory structure for Laborantin"
32
+
33
+ option(:force) do
34
+ describe 'force overwrite, use with care'
35
+ short '-f'
36
+ long '--force'
37
+ default false
38
+ end
39
+
40
+ execute do
41
+ #Build Tree Structure
42
+ dirs_to_build = []
43
+
44
+ rootdir = File.join('.', (args.first) || '')
45
+
46
+ dirs_to_build << rootdir
47
+
48
+ %w{analyses commands lib config environments reports results scripts scenarii}.each do |dirname|
49
+ dirs_to_build << File.join(rootdir, dirname)
50
+ end
51
+
52
+ dirs_to_build.each do |path|
53
+ FileUtils::Verbose.mkdir_p(path)
54
+ end
55
+
56
+ #TODO: create a README, a NOTEBOOK
57
+ end
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,215 @@
1
+ #runner/commands/describe.rb
2
+
3
+ =begin
4
+
5
+ This file is part of Laborantin.
6
+
7
+ Laborantin is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Laborantin is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with Laborantin. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ Copyright (c) 2009, Lucas Di Cioccio
21
+
22
+ =end
23
+
24
+ autoload :ERB, 'erb'
25
+ module Laborantin
26
+ module Commands
27
+ class Describe < Command
28
+ describe "Gives a summary of what the current Laborantin project is"
29
+
30
+
31
+ option(:scenarii) do
32
+ describe "comma separated list of scenarios to describe"
33
+ short "-s"
34
+ long "--scenarii=OPTIONAL"
35
+ type Array
36
+ default []
37
+ complete do |cmd|
38
+ completion_propositions_iterating_on(cmd, Laborantin::Scenario.all.map(&:cli_name))
39
+ end
40
+ end
41
+
42
+ option(:environments) do
43
+ describe "comma separated list of environments to describe"
44
+ short "-e"
45
+ long "--envs=OPTIONAL"
46
+ type Array
47
+ default []
48
+ complete do |cmd|
49
+ completion_propositions_iterating_on(cmd, Laborantin::Environment.all.map(&:cli_name))
50
+ end
51
+ end
52
+
53
+ option(:analyses) do
54
+ describe "comma separated list of analyses to describe"
55
+ short "-a"
56
+ long "--analyses=OPTIONAL"
57
+ type Array
58
+ default []
59
+ complete do |cmd|
60
+ completion_propositions_iterating_on(cmd, Laborantin::Analysis.all.map(&:cli_name))
61
+ end
62
+ end
63
+
64
+ option(:output) do
65
+ describe "print in a file instead of STDOUT"
66
+ short '-o'
67
+ long '--output=OPTIONAL'
68
+ type String
69
+ default ''
70
+ end
71
+
72
+ FORMATS = ['default', 'txt', 'html']
73
+
74
+ option(:format) do
75
+ describe "format the output in a certain form, among: [#{FORMATS.join(', ')}]"
76
+ short '-f'
77
+ long '--format=OPTIONAL'
78
+ type String
79
+ default 'default'
80
+ end
81
+
82
+ def stdout?
83
+ opts[:output].empty?
84
+ end
85
+
86
+ def out
87
+ @out ||= if stdout?
88
+ self #self.puts forward to the runner
89
+ else
90
+ File.open(opts[:output], 'w')
91
+ end
92
+ end
93
+
94
+ def close_out
95
+ @out.close unless stdout?
96
+ end
97
+
98
+ def environments
99
+ Environment.all
100
+ end
101
+
102
+ def scenarii
103
+ Scenario.all
104
+ end
105
+
106
+ def analyses
107
+ Analysis.all
108
+ end
109
+
110
+
111
+ HTML_TPL = <<ERB
112
+ <html>
113
+ <head>
114
+ </head>
115
+ <body>
116
+ <h1>Laborantin's description</h1>
117
+ <p>Project located at: <%= runner.root_dir %> </p>
118
+ <h2>List of environments</h2>
119
+ <ul>
120
+ <% Environment.all.each do |env| %>
121
+ <li><%= env.name %>
122
+ (<%= env.description %>)
123
+ </li>
124
+ <% end %>
125
+ </ul>
126
+ <h2>List of scenarios</h2>
127
+ <ul>
128
+ <% Scenario.all.each do |sc| %>
129
+ <li><%= sc.name %>
130
+ (<%= sc.description %>)
131
+ <ul>
132
+ <% sc.parameters.each_pair do |name, spec| %>
133
+ <li><%= name %></li>
134
+ <ul>
135
+ <li><%= spec.description %></li>
136
+ <li><%= spec.values.inspect %></li>
137
+ </ul>
138
+ <% end %>
139
+ </ul>
140
+ </li>
141
+ <% end %>
142
+ </ul>
143
+ <h2>List of analyses</h2>
144
+ <ul>
145
+ <% Analysis.all.each do |a| %>
146
+ <li><%= a.name %>
147
+ (<%= a.description %>)
148
+ <ul>
149
+ <% a.analyses.each do |hash| %>
150
+ <li>
151
+ <%= hash[:str] %>
152
+ </li>
153
+ <% end %>
154
+ </ul>
155
+ </li>
156
+ <% end %>
157
+ </ul>
158
+ </body>
159
+ </html>
160
+ ERB
161
+
162
+ TXT_TPL = <<ERB
163
+ Available environments:
164
+ <% Environment.all.each do |env| %>
165
+ * <%= env.name %> (<%= env.description %>)
166
+ <% end %>
167
+ Available scenarios:
168
+ <% Scenario.all.each do |sc| %>
169
+ * <%= sc.name %> (<%= sc.description %>)
170
+ <% sc.parameters.each_pair do |name, spec| %>
171
+ + <%= name %> (<%= spec.description %>) | <%= spec.values.inspect %>
172
+ <% end %>
173
+ <% end %>
174
+ Available analyses:
175
+ <% Analysis.all.each do |a| %>
176
+ * <%= a.name %> (<%= a.description %>)
177
+ <% a.analyses.each do |hash| %>
178
+ <% if hash[:params][:type] %>
179
+ + <%= hash[:str] %> (<%= hash[:params][:type] %>)
180
+ <% else %>
181
+ + <%= hash[:str] %>
182
+ <% end %>
183
+ <% end %>
184
+ <% end %>
185
+ ERB
186
+
187
+ def html_format
188
+ ERB.new(HTML_TPL).result(binding)
189
+ end
190
+
191
+ def txt_format
192
+ ERB.new(TXT_TPL).result(binding).lines.reject{|l| l =~/^\s*$/}.join
193
+ end
194
+
195
+ alias :default_format :txt_format
196
+
197
+ def format_str
198
+ case opts[:format]
199
+ when 'html'
200
+ html_format
201
+ else
202
+ default_format
203
+ end
204
+ end
205
+
206
+ execute do
207
+ begin
208
+ out.puts format_str
209
+ ensure
210
+ close_out
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end