gat 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +84 -0
- data/PostInstall.txt +22 -0
- data/README.txt +49 -0
- data/Rakefile +12 -0
- data/bin/gat +15 -0
- data/lib/gat.rb +323 -0
- data/lib/gat/action/base.rb +197 -0
- data/lib/gat/action/ruby_method.rb +35 -0
- data/lib/gat/action/shell_command.rb +185 -0
- data/lib/gat/boot.rb +63 -0
- data/lib/gat/checks.rb +136 -0
- data/lib/gat/debug.rb +29 -0
- data/lib/gat/dependence/argument.rb +62 -0
- data/lib/gat/dependence/base.rb +54 -0
- data/lib/gat/dependence/folder.rb +104 -0
- data/lib/gat/dependence/program.rb +36 -0
- data/lib/gat/email.rb +80 -0
- data/lib/gat/exceptions.rb +163 -0
- data/lib/gat/extends.rb +102 -0
- data/lib/gat/help.rb +79 -0
- data/lib/gat/interpreter.rb +93 -0
- data/lib/gat/launcher.rb +100 -0
- data/lib/gat/logger.rb +331 -0
- data/lib/gat/operation.rb +253 -0
- data/lib/gat/version.rb +20 -0
- data/lib/gatgets/dar_backup/dar_backup.rb +367 -0
- data/lib/gatgets/dar_backup/dar_backup.yml +387 -0
- data/lib/gatgets/dar_backup/launcher.rb +44 -0
- data/lib/gatgets/dar_backup/templates/list_backups.erb +31 -0
- data/lib/gatgets/dar_backup/templates/search.erb +33 -0
- data/lib/gatgets/gatgets_manager/gatgets_manager.rb +65 -0
- data/lib/gatgets/gatgets_manager/gatgets_manager.yml +71 -0
- data/lib/gatgets/gatgets_manager/templates/list.erb +9 -0
- data/lib/gatgets/synchronization/README +26 -0
- data/lib/gatgets/synchronization/launcher.rb +20 -0
- data/lib/gatgets/synchronization/launcher_cron.sh +69 -0
- data/lib/gatgets/synchronization/synchronization.rb +123 -0
- data/lib/gatgets/synchronization/synchronization.yml +144 -0
- data/test/test_gat.rb +36 -0
- data/test/test_helper.rb +3 -0
- metadata +131 -0
@@ -0,0 +1,197 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
:file => action/base.rb
|
4
|
+
:author => (c) 2008-2009 A.C. Gnoxys info@gnoxys.net
|
5
|
+
|
6
|
+
######################################################################################
|
7
|
+
## This file is part of GAT: http://gat.rubyforge.org ##
|
8
|
+
## ##
|
9
|
+
## GAT (Gnoxys Administration Tools) is released under the GPL License 3 or higher. ##
|
10
|
+
## You can get a copy of the license easily at http://www.gnu.org/licenses/gpl.html.##
|
11
|
+
######################################################################################
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
14
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
15
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
16
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
17
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
18
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
19
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
|
21
|
+
=end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
module Gat
|
26
|
+
|
27
|
+
|
28
|
+
# Gat::Action::Base
|
29
|
+
#
|
30
|
+
# Action are pieces of operations. Actions are the objetives of dependences
|
31
|
+
# Actions have the next config options at YML definition
|
32
|
+
#
|
33
|
+
# <action_name> *must be uniq*
|
34
|
+
# type: <shell_command> || <ruby_method>
|
35
|
+
# Type of the action. It can be
|
36
|
+
# - shell_command: Action will execute a shell command
|
37
|
+
# - ruby_method: Action will call a ruby_method called by action.name
|
38
|
+
# flags: [ <action flags> ]
|
39
|
+
# Conditional flags have to been passed to execute action. Action is skipped if only one flag failed
|
40
|
+
# Flags can be marked as negative. For example, [ '!file_doesnt_exist' ]. In this case, flags must be marked as false
|
41
|
+
# to result in action execution
|
42
|
+
#
|
43
|
+
# syntax: "<shell_command_syntax">
|
44
|
+
# Only in Shell Commands types, syntax is the command line form to be executed by Ruby Terminal.
|
45
|
+
#
|
46
|
+
# multiple: ["<n multiple parameters>"]
|
47
|
+
# Only in shell commands types.
|
48
|
+
# If multiple isnt empty, Action will interprete multiple parameters as multiple values. That means, that gat expect
|
49
|
+
# that multiple paramters return an array of values. Gat::Action will loop and execute each shell_command with these parameters substitions
|
50
|
+
# For example, that is usefull to exec one command peer each File in one Dir.
|
51
|
+
#
|
52
|
+
# onfail: "<continue> || <abort>"
|
53
|
+
# What happens is action end with non 0 status
|
54
|
+
#
|
55
|
+
# onfail_message: "<onfail_message>"
|
56
|
+
# Custom message to be logged at error
|
57
|
+
#
|
58
|
+
# onfail_callback: "<on_fail_callback>"
|
59
|
+
# Custom ruby method that is executed if action fails
|
60
|
+
|
61
|
+
module Action
|
62
|
+
|
63
|
+
class Base
|
64
|
+
|
65
|
+
include Gat::Interpreter
|
66
|
+
|
67
|
+
attr_reader :operation
|
68
|
+
attr_reader :config
|
69
|
+
attr_reader :name
|
70
|
+
attr_reader :argument
|
71
|
+
attr_reader :description
|
72
|
+
attr_reader :flags
|
73
|
+
attr_accessor :error
|
74
|
+
|
75
|
+
|
76
|
+
attr_accessor :times
|
77
|
+
attr_accessor :output
|
78
|
+
attr_accessor :errors
|
79
|
+
attr_accessor :exit_level
|
80
|
+
|
81
|
+
attr_accessor :status
|
82
|
+
|
83
|
+
attr_accessor :parsed_syntax
|
84
|
+
|
85
|
+
attr_accessor :onfail
|
86
|
+
attr_accessor :onfail_message
|
87
|
+
attr_accessor :onfail_callback
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
# Get the current action
|
92
|
+
def self.get_current_action
|
93
|
+
@@current_action
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def initialize(name, config, operation)
|
98
|
+
|
99
|
+
operation.gatget.logger.log("trace", "action", "Initialize action #{ self.class } @#{ name }")
|
100
|
+
|
101
|
+
@times = Hash.new
|
102
|
+
@times['init'] = Time.now
|
103
|
+
@operation = operation
|
104
|
+
@config = config
|
105
|
+
@name = name
|
106
|
+
@description = config['description'] || "Another Action named #{ name }"
|
107
|
+
@flags = config['flags'] || [ ]
|
108
|
+
@output = ''
|
109
|
+
@error = nil
|
110
|
+
|
111
|
+
@onfail = config['onfail'] || 'abort'
|
112
|
+
@onfail_message = config['onfail_message']
|
113
|
+
@onfail_callback = config['onfail_callback']
|
114
|
+
|
115
|
+
@@current_action = self
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
def execute
|
120
|
+
|
121
|
+
if self.execute?
|
122
|
+
|
123
|
+
self.run
|
124
|
+
|
125
|
+
#self.set_outputs
|
126
|
+
|
127
|
+
unless self.exit_level == 0
|
128
|
+
self.operation.gatget.logger.log("warning", "action_error", "#{self.error}")
|
129
|
+
self.operation.gatget.logger.log("warning", "action_error", "Action #{ self.name } finished with status #{self.exit_level}")
|
130
|
+
|
131
|
+
if self.onfail_callback
|
132
|
+
self.operation.gatget.send(self.onfail_callback)
|
133
|
+
end
|
134
|
+
|
135
|
+
if self.onfail == 'abort'
|
136
|
+
self.operation.gatget.logger.log('error', 'action_execute', "Action #{ self.name } abort Gatget")
|
137
|
+
self.operation.status = 'fail'
|
138
|
+
|
139
|
+
raise GatgetProcessException.new(self.error, "execute_action", self.onfail_message ? {:message => self.onfail_message} : {} )
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
@times['end'] = Time.now
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
# Execute? Method check if action must be executed. It test the follow conditions
|
150
|
+
# If flags is set, check that all flags are true
|
151
|
+
# If operation state is to abort or skip actions, skip actions
|
152
|
+
def execute?
|
153
|
+
flags_ok? and status_ok?
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
private
|
158
|
+
# Check if action flags are ok...
|
159
|
+
def flags_ok?
|
160
|
+
flags_ok = true
|
161
|
+
marker_flag = nil
|
162
|
+
|
163
|
+
if @flags and @flags.any?
|
164
|
+
@flags.each do |flag|
|
165
|
+
|
166
|
+
if flag[0..0] == '!'
|
167
|
+
compare_with = false
|
168
|
+
flag = flag.gsub(/^!/,'')
|
169
|
+
else
|
170
|
+
compare_with = true
|
171
|
+
end
|
172
|
+
|
173
|
+
unless self.operation.gatget.get_flag(flag) == compare_with
|
174
|
+
flags_ok = false
|
175
|
+
marker_flag = flag
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
unless flags_ok
|
181
|
+
self.operation.gatget.logger.log("message", "action", "Action #{ self.class } @#{ self.name } not mark to exec by flag: #{ marker_flag }")
|
182
|
+
end
|
183
|
+
flags_ok
|
184
|
+
end
|
185
|
+
|
186
|
+
def status_ok?
|
187
|
+
status_ok = self.operation.status == 'ok'
|
188
|
+
unless status_ok
|
189
|
+
self.operation.gatget.logger.log("message", "action", "Operation #{ self.operation.name } is not marked as OK. Actions are skipped")
|
190
|
+
end
|
191
|
+
status_ok
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
module Gat
|
3
|
+
module Action
|
4
|
+
class RubyMethod < Base
|
5
|
+
|
6
|
+
attr_accessor :status
|
7
|
+
|
8
|
+
def run
|
9
|
+
|
10
|
+
self.exec
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def exec
|
16
|
+
self.operation.gatget.logger.log("trace", "action_syntax", "Action #{ self.name } exec ruby method." )
|
17
|
+
self.times['init'] ||= Time.now
|
18
|
+
|
19
|
+
begin
|
20
|
+
self.operation.gatget.send(self.name)
|
21
|
+
self.status = 'ok'
|
22
|
+
self.exit_level = 0
|
23
|
+
rescue => e
|
24
|
+
self.error = e
|
25
|
+
self.status = 'failed'
|
26
|
+
self.exit_level = 1
|
27
|
+
end
|
28
|
+
|
29
|
+
self.times['end'] ||= Time.now
|
30
|
+
self.exit_level
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
module Gat
|
2
|
+
module Action
|
3
|
+
|
4
|
+
class ShellCommand < Base
|
5
|
+
|
6
|
+
attr_reader :syntax
|
7
|
+
attr_reader :childs
|
8
|
+
attr_accessor :arguments
|
9
|
+
|
10
|
+
attr_accessor :pid
|
11
|
+
attr_accessor :status
|
12
|
+
|
13
|
+
def initialize(name, config, operation)
|
14
|
+
super(name, config, operation)
|
15
|
+
|
16
|
+
@syntax = config['syntax'] || raise(GatgetConfigException.new("Shell Command Action #{ name } has not a syntax attribute", "initialize_shell_command"))
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def run
|
21
|
+
ret = nil
|
22
|
+
# Shell Command can be multiple, that means the command will be execute over a foreach variable subtitutions.
|
23
|
+
# That is usefull, for example, when you need to do the same actions with some variable subtition, like
|
24
|
+
# a multiple files compression.
|
25
|
+
@childs = (@config['multiple'] and @config['multiple'].any?) ? set_multiple_childs(@config['multiple']) : [ ]
|
26
|
+
|
27
|
+
# If ShellCommand is multiple, then, we exec all of its childs
|
28
|
+
# If not, we just execute ShellCommand instance
|
29
|
+
if @childs.any?
|
30
|
+
@childs.each { |child|
|
31
|
+
if not child.exec
|
32
|
+
ret = false
|
33
|
+
end
|
34
|
+
}
|
35
|
+
else
|
36
|
+
self.parsed_syntax = interpreter_parameters(self.syntax, self.operation.gatget)
|
37
|
+
ret = exec(self.parsed_syntax)
|
38
|
+
end
|
39
|
+
|
40
|
+
if self.config['output']
|
41
|
+
self.operation.gatget.logger.log("direct", "action_output", self.output)
|
42
|
+
end
|
43
|
+
ret
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Execute shell command with Open4
|
48
|
+
#
|
49
|
+
# Open4 module is the next generation Ruby module for executing shell commands.
|
50
|
+
# Open4 works better thant the standard Open3 module, and has built inside the feature
|
51
|
+
# to return exit status through Process.status Class.
|
52
|
+
# Even it has some problems too. Open4 module has big problems when the stdout or the stderr comes
|
53
|
+
# with tons of information. For example, with a mysqldump output.
|
54
|
+
#
|
55
|
+
# The solution presented here is a wapper through Process.fork. We create a new fork, making
|
56
|
+
# and the output is not managed by the ruby script itself but by the fork process.
|
57
|
+
# IO.pipes are created to pass the stdout, stderr and stdin data through Gat proccess and Fork process
|
58
|
+
#
|
59
|
+
# Some disccusion about this can be readed here: http://stackoverflow.com/questions/1076257/returning-data-from-forked-processes
|
60
|
+
#
|
61
|
+
# Maybe, we could use Theread.new, and maybe it would be better, but... =)
|
62
|
+
#
|
63
|
+
def exec(shell_command, multiple_name = '')
|
64
|
+
|
65
|
+
trap_save = trap( 0, "IGNORE" )
|
66
|
+
|
67
|
+
self.operation.gatget.logger.log("trace", "action_syntax", "Action #{ self.name }#{ multiple_name } exec command syntax : #{ shell_command }" )
|
68
|
+
|
69
|
+
self.times['init'] ||= Time.now
|
70
|
+
|
71
|
+
read_stdout, write_stdout = IO.pipe
|
72
|
+
read_stderr, write_stderr = IO.pipe
|
73
|
+
|
74
|
+
pid = fork do
|
75
|
+
trap( 0, "IGNORE" )
|
76
|
+
read_stdout.close
|
77
|
+
read_stderr.close
|
78
|
+
|
79
|
+
pid_open4, stdin, stdout, stderr = Open4::popen4 "#{ shell_command }"
|
80
|
+
|
81
|
+
write_stdout.puts stdout.read
|
82
|
+
write_stderr.puts stderr.read
|
83
|
+
|
84
|
+
ignored, status_open4 = Process::waitpid2 pid_open4
|
85
|
+
exit status_open4.exitstatus
|
86
|
+
end
|
87
|
+
trap( 0, trap_save )
|
88
|
+
|
89
|
+
write_stdout.close
|
90
|
+
write_stderr.close
|
91
|
+
|
92
|
+
result_stdout = read_stdout.read
|
93
|
+
result_stderr = read_stderr.read
|
94
|
+
|
95
|
+
pid, status = Process.wait2(pid)
|
96
|
+
|
97
|
+
self.output, self.error, self.exit_level = reinterpret_output_and_error(result_stdout, result_stderr, status.exitstatus)
|
98
|
+
|
99
|
+
self.pid = pid
|
100
|
+
self.status = status
|
101
|
+
self.times['end'] = Time.now
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def set_multiple_childs(multiples_parameters)
|
106
|
+
# get multiples values
|
107
|
+
multiples_values = {}
|
108
|
+
multiples_parameters.each do |parameter|
|
109
|
+
values = interpreter_parameter(parameter, self.operation.gatget)
|
110
|
+
multiples_values[parameter] = values
|
111
|
+
end
|
112
|
+
|
113
|
+
# all multiple values must have the same size for substitution
|
114
|
+
last_multiple_vales_size = multiples_values.values.first.size
|
115
|
+
multiples_values.values.each do |values|
|
116
|
+
unless values.size == last_multiple_vales_size
|
117
|
+
raise GatgetConfigException.new("Multiples values at Action #{ self.name } doesnt have the same size. Substitution cannot be interpreted", "set_multiple_chids")
|
118
|
+
end
|
119
|
+
last_multiple_vales_size == values.size
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
unless last_multiple_vales_size > 0
|
124
|
+
raise GatgetConfigException.new("Multiples values at Action #{ self.name } are empty", "set_multiple_chids")
|
125
|
+
end
|
126
|
+
|
127
|
+
# create childs objects
|
128
|
+
childs = []
|
129
|
+
i = 0
|
130
|
+
last_multiple_vales_size.times do
|
131
|
+
child_multiple_parameters = {}
|
132
|
+
multiples_values.each_pair do |parameter, values|
|
133
|
+
child_multiple_parameters[parameter] = values[i]
|
134
|
+
end
|
135
|
+
childs << ShellCommandChild.new(self, child_multiple_parameters)
|
136
|
+
i += 1
|
137
|
+
end
|
138
|
+
|
139
|
+
# return child
|
140
|
+
childs
|
141
|
+
end
|
142
|
+
|
143
|
+
# Redefine this two methods in your class to clean or reinterpret the output and error
|
144
|
+
def reinterpret_output_and_error(output, error, status)
|
145
|
+
return output == "\n" ? "" : output,
|
146
|
+
error == "\n" ? "" : error, status
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
class ShellCommandChild
|
153
|
+
include Gat::Interpreter
|
154
|
+
|
155
|
+
attr_reader :parent
|
156
|
+
attr_reader :syntax
|
157
|
+
attr_reader :values
|
158
|
+
attr_reader :name
|
159
|
+
|
160
|
+
attr_accessor :syntax
|
161
|
+
attr_accessor :arguments
|
162
|
+
|
163
|
+
|
164
|
+
def initialize(parent, values)
|
165
|
+
@parent = parent
|
166
|
+
@values = values
|
167
|
+
|
168
|
+
|
169
|
+
@syntax = parent.syntax
|
170
|
+
@name = "#{ parent.name }*over* #{ values.values.join("_") }"
|
171
|
+
end
|
172
|
+
|
173
|
+
def exec
|
174
|
+
# make the substitution of each parameter and exec like other action
|
175
|
+
values.each_pair do |parameter_key, parameter_value |
|
176
|
+
self.syntax = self.syntax.gsub(/\{\{#{ parameter_key }\}\}/, parameter_value)
|
177
|
+
end
|
178
|
+
|
179
|
+
parse_syntax = interpreter_parameters(self.syntax, self.parent.operation.gatget)
|
180
|
+
self.parent.exec(parse_syntax, " *over* #{ values.values.join("_") }")
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
data/lib/gat/boot.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
:file => boot.rb
|
4
|
+
:author => (c) 2008-2009 A.C. Gnoxys info@gnoxys.net
|
5
|
+
|
6
|
+
######################################################################################
|
7
|
+
## This file is part of GAT: http://gat.rubyforge.org ##
|
8
|
+
## ##
|
9
|
+
## GAT (Gnoxys Administration Tools) is released under the GPL License 3 or higher. ##
|
10
|
+
## You can get a copy of the license easily at http://www.gnu.org/licenses/gpl.html.##
|
11
|
+
######################################################################################
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
14
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
15
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
16
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
17
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
18
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
19
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
|
21
|
+
=end
|
22
|
+
|
23
|
+
|
24
|
+
# Boot File provides the starting point to execute gatget based script.
|
25
|
+
#
|
26
|
+
# Boot load required modules && classes for Gat::Base and other gems.
|
27
|
+
# Differents exit levels are launched if requires files fails.
|
28
|
+
#
|
29
|
+
# Gat constants
|
30
|
+
GAT_GATGETS = GAT_ROOT + '/gatgets'
|
31
|
+
GAT_TEMPLATES = GAT_ROOT + '/templates'
|
32
|
+
|
33
|
+
# External gems
|
34
|
+
gems = [ 'ftools', 'rubygems', 'open4', 'yaml', 'erb', 'rdoc/usage', 'rdoc/code_objects',
|
35
|
+
'rdoc/markup/simple_markup', 'rdoc/markup/simple_markup/to_flow', 'rdoc/ri/ri_formatter',
|
36
|
+
'rdoc/ri/ri_options', 'net/smtp', 'tmail', 'erb' ]
|
37
|
+
|
38
|
+
# Gat Modules
|
39
|
+
modules = [ 'debug', 'help', 'interpreter', 'extends', 'version', 'launcher', 'checks', 'email' ]
|
40
|
+
|
41
|
+
# Gat Classes
|
42
|
+
classes = [ 'exceptions', 'operation', 'dependence/base', 'dependence/program', 'dependence/argument', 'dependence/folder',
|
43
|
+
'action/base.rb', 'action/shell_command.rb', 'action/ruby_method.rb', 'logger' ]
|
44
|
+
|
45
|
+
|
46
|
+
# Build required hash
|
47
|
+
load_data = { 'gems' => { 'data' => gems, 'path' => '', 'exit' => 9 },
|
48
|
+
'modules' => { 'data' => modules, 'path' => "#{ GAT_ROOT + '/lib/gat/' }", 'exit' => 10 },
|
49
|
+
'classes' => { 'data' => classes, 'path' => "#{ GAT_ROOT + '/lib/gat/' }", 'exit' => 11 } }
|
50
|
+
|
51
|
+
# Require all data
|
52
|
+
load_data.each_pair do |key, value|
|
53
|
+
value['data'].each do |dependency|
|
54
|
+
begin
|
55
|
+
require value['path'] + dependency
|
56
|
+
rescue LoadError => msg
|
57
|
+
$stderr.puts "Error while loading #{ key }: #{ msg }"
|
58
|
+
$stderr.puts "[ ERROR ] Backtrace \n" + msg.backtrace.join("\n")
|
59
|
+
$stderr.puts "\nexit level #{ value['exit'] }"
|
60
|
+
exit value['exit']
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|