reel-eye 0.3.1 → 0.3.2
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.
- data/.gitignore +2 -1
- data/.travis.yml +1 -0
- data/CHANGES.md +19 -0
- data/Gemfile +1 -0
- data/README.md +10 -8
- data/bin/eye +30 -45
- data/examples/notify.eye +3 -2
- data/examples/puma.eye +2 -2
- data/examples/rbenv.eye +2 -2
- data/examples/sidekiq.eye +2 -2
- data/examples/thin-farm.eye +1 -0
- data/examples/unicorn.eye +1 -1
- data/eye.gemspec +1 -1
- data/lib/eye.rb +1 -1
- data/lib/eye/application.rb +1 -1
- data/lib/eye/checker.rb +10 -0
- data/lib/eye/controller/commands.rb +0 -5
- data/lib/eye/controller/helpers.rb +15 -1
- data/lib/eye/controller/load.rb +3 -0
- data/lib/eye/controller/options.rb +1 -1
- data/lib/eye/controller/send_command.rb +44 -14
- data/lib/eye/controller/status.rb +4 -8
- data/lib/eye/dsl/application_opts.rb +6 -2
- data/lib/eye/dsl/group_opts.rb +7 -6
- data/lib/eye/dsl/main.rb +1 -1
- data/lib/eye/dsl/opts.rb +22 -15
- data/lib/eye/dsl/process_opts.rb +3 -6
- data/lib/eye/dsl/pure_opts.rb +12 -1
- data/lib/eye/group.rb +1 -1
- data/lib/eye/http.rb +3 -0
- data/lib/eye/loader.rb +0 -10
- data/lib/eye/logger.rb +4 -4
- data/lib/eye/process/scheduler.rb +4 -0
- data/lib/eye/process/validate.rb +9 -1
- data/lib/eye/process/watchers.rb +3 -3
- data/lib/eye/settings.rb +17 -5
- data/lib/eye/system.rb +9 -0
- data/lib/eye/utils/alive_array.rb +23 -1
- metadata +267 -231
- checksums.yaml +0 -7
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGES.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
0.3.3.dev
|
|
2
|
+
---------
|
|
3
|
+
|
|
4
|
+
0.3.2
|
|
5
|
+
---------
|
|
6
|
+
* improve matching targers
|
|
7
|
+
* possibility to add many checkers with the same type per process (ex: checks :http_2, ...)
|
|
8
|
+
* add uid,gid options (only for ruby 2.0)
|
|
9
|
+
|
|
10
|
+
0.3.1
|
|
11
|
+
-----
|
|
12
|
+
* load multiple configs (folder,...) now not breaks on first error (each config loads separately)
|
|
13
|
+
* load ~/.eyeconfig with first eye load
|
|
14
|
+
* some concurrency fixes
|
|
15
|
+
* custom checker
|
|
16
|
+
|
|
17
|
+
0.3
|
|
18
|
+
---
|
|
19
|
+
* stable version
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
Eye
|
|
1
|
+
Eye
|
|
2
2
|
===
|
|
3
|
+
[](http://rubygems.org/gems/eye)
|
|
4
|
+
[](http://travis-ci.org/kostya/eye)
|
|
5
|
+
[](https://coveralls.io/r/kostya/eye?branch=master)
|
|
3
6
|
|
|
4
7
|
Process monitoring tool. An alternative to God and Bluepill. With Bluepill like config syntax. Requires MRI Ruby >= 1.9.3-p194. Uses Celluloid and Celluloid::IO.
|
|
5
8
|
|
|
@@ -150,6 +153,10 @@ Check config syntax:
|
|
|
150
153
|
|
|
151
154
|
$ eye c(heck) examples/test.eye
|
|
152
155
|
|
|
156
|
+
Config explain (for debug):
|
|
157
|
+
|
|
158
|
+
$ eye e(xplain) examples/test.eye
|
|
159
|
+
|
|
153
160
|
Log tracing:
|
|
154
161
|
|
|
155
162
|
$ eye trace
|
|
@@ -160,11 +167,6 @@ Quit monitoring:
|
|
|
160
167
|
|
|
161
168
|
$ eye q(uit)
|
|
162
169
|
|
|
163
|
-
Config
|
|
164
|
-
|
|
165
|
-
$ eye explain examples/test.eye
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
### Config api:
|
|
170
|
+
### Config options:
|
|
169
171
|
|
|
170
|
-
Waiting for pull requests ..., until that you can read `examples` and `spec/dsl` folders.
|
|
172
|
+
Waiting for pull requests here..., until that you can read `examples` and `spec/dsl` folders.
|
data/bin/eye
CHANGED
|
@@ -10,9 +10,7 @@ class Cli < Thor
|
|
|
10
10
|
|
|
11
11
|
desc "info [MASK]", "show process statuses"
|
|
12
12
|
def info(mask = nil)
|
|
13
|
-
|
|
14
|
-
puts res if res && !res.empty?
|
|
15
|
-
puts
|
|
13
|
+
print cmd(:info, mask)
|
|
16
14
|
end
|
|
17
15
|
|
|
18
16
|
desc "status ", "show process statuses"
|
|
@@ -25,31 +23,22 @@ class Cli < Thor
|
|
|
25
23
|
method_option :config, :type => :boolean, :aliases => "-c"
|
|
26
24
|
method_option :show_processes, :type => :boolean, :aliases => "-p"
|
|
27
25
|
def xinfo
|
|
28
|
-
|
|
29
|
-
puts res if res && !res.empty?
|
|
30
|
-
puts
|
|
26
|
+
print cmd(:xinfo, options[:config], options[:show_processes])
|
|
31
27
|
end
|
|
32
28
|
|
|
33
29
|
desc "oinfo", "onelined info"
|
|
34
30
|
def oinfo
|
|
35
|
-
|
|
36
|
-
puts res if res && !res.empty?
|
|
37
|
-
puts
|
|
31
|
+
print cmd(:oinfo)
|
|
38
32
|
end
|
|
39
33
|
|
|
40
34
|
desc "load [CONF, ...]", "load config (and start server if needed) (-f for foregraund start)"
|
|
41
35
|
method_option :foregraund, :type => :boolean, :aliases => "-f"
|
|
42
|
-
method_option :logger, :type => :string, :aliases => "-l"
|
|
43
36
|
def load(*configs)
|
|
44
37
|
configs.map!{ |c| File.expand_path(c) } if !configs.empty?
|
|
45
38
|
|
|
46
39
|
if options[:foregraund]
|
|
47
40
|
# in foregraund we stop another server, and run just 1 current config version
|
|
48
|
-
if configs.size != 1
|
|
49
|
-
say "foregraund expected only one config", :red
|
|
50
|
-
exit 1
|
|
51
|
-
end
|
|
52
|
-
|
|
41
|
+
error!("foregraund expected only one config") if configs.size != 1
|
|
53
42
|
server_start_foregraund(configs.first)
|
|
54
43
|
|
|
55
44
|
elsif server_started?
|
|
@@ -90,9 +79,7 @@ class Cli < Thor
|
|
|
90
79
|
|
|
91
80
|
desc "history TARGET[,...]", "show process states history"
|
|
92
81
|
def history(*targets)
|
|
93
|
-
|
|
94
|
-
puts res if res && !res.empty?
|
|
95
|
-
puts
|
|
82
|
+
print cmd(:history, *targets)
|
|
96
83
|
end
|
|
97
84
|
|
|
98
85
|
desc "trace [TARGET]", "tracing log for app,group or process"
|
|
@@ -146,6 +133,16 @@ class Cli < Thor
|
|
|
146
133
|
|
|
147
134
|
private
|
|
148
135
|
|
|
136
|
+
def error!(msg)
|
|
137
|
+
say msg, :red
|
|
138
|
+
exit 1
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def print(msg, new_line = true)
|
|
142
|
+
say msg if msg && !msg.empty?
|
|
143
|
+
say if new_line
|
|
144
|
+
end
|
|
145
|
+
|
|
149
146
|
def client
|
|
150
147
|
@client ||= Eye::Client.new(Eye::Settings.socket_path)
|
|
151
148
|
end
|
|
@@ -160,11 +157,9 @@ private
|
|
|
160
157
|
res = _cmd(cmd, *args)
|
|
161
158
|
|
|
162
159
|
if res == :not_started
|
|
163
|
-
|
|
164
|
-
exit 1
|
|
160
|
+
error! "eye monitoring not found, did you start it?"
|
|
165
161
|
elsif res == :timeouted
|
|
166
|
-
|
|
167
|
-
exit 1
|
|
162
|
+
error! "eye does not answer, timeouted..."
|
|
168
163
|
end
|
|
169
164
|
|
|
170
165
|
res
|
|
@@ -175,18 +170,12 @@ private
|
|
|
175
170
|
end
|
|
176
171
|
|
|
177
172
|
def say_load_result(res = {}, opts = {})
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
say_filename = (res.size > 1)
|
|
185
|
-
say "eye started!", :green if opts[:started]
|
|
186
|
-
res.each do |filename, _res|
|
|
187
|
-
say "#{filename}: ", nil, true if say_filename
|
|
188
|
-
show_load_message(_res, opts)
|
|
189
|
-
end
|
|
173
|
+
error!(res) unless res.is_a?(Hash)
|
|
174
|
+
say_filename = (res.size > 1)
|
|
175
|
+
say "eye started!", :green if opts[:started]
|
|
176
|
+
res.each do |filename, _res|
|
|
177
|
+
say "#{filename}: ", nil, true if say_filename
|
|
178
|
+
show_load_message(_res, opts)
|
|
190
179
|
end
|
|
191
180
|
end
|
|
192
181
|
|
|
@@ -212,11 +201,11 @@ private
|
|
|
212
201
|
def send_command(_cmd, *args)
|
|
213
202
|
res = cmd(_cmd, *args)
|
|
214
203
|
if res == :unknown_command
|
|
215
|
-
|
|
204
|
+
error! "unknown command :#{_cmd}"
|
|
216
205
|
elsif res == :corrupred_marshal
|
|
217
|
-
|
|
206
|
+
error! "something crazy wrong, check eye logs!"
|
|
218
207
|
elsif res == []
|
|
219
|
-
|
|
208
|
+
error! "command :#{_cmd}, targets not found!"
|
|
220
209
|
else
|
|
221
210
|
say "command :#{_cmd} sended to [#{res * ", "}]"
|
|
222
211
|
end
|
|
@@ -227,7 +216,7 @@ private
|
|
|
227
216
|
if log_file && File.exists?(log_file)
|
|
228
217
|
Process.exec "tail -n 100 -f #{log_file} | grep '#{tag}'"
|
|
229
218
|
else
|
|
230
|
-
|
|
219
|
+
error! "log file not found #{log_file.inspect}"
|
|
231
220
|
end
|
|
232
221
|
end
|
|
233
222
|
|
|
@@ -250,8 +239,7 @@ private
|
|
|
250
239
|
|
|
251
240
|
def ensure_loader_path
|
|
252
241
|
unless loader_path
|
|
253
|
-
|
|
254
|
-
exit 1
|
|
242
|
+
error! "start monitoring needs to run under ruby with installed gem 'eye'"
|
|
255
243
|
end
|
|
256
244
|
end
|
|
257
245
|
|
|
@@ -275,18 +263,15 @@ private
|
|
|
275
263
|
Eye::Settings.ensure_eye_dir
|
|
276
264
|
|
|
277
265
|
ensure_stop_previous_server
|
|
278
|
-
|
|
279
|
-
args = []
|
|
280
|
-
args += ['-l', options[:logger]] if options[:logger]
|
|
281
266
|
|
|
267
|
+
args = []
|
|
282
268
|
pid = Process.spawn(ruby_path, loader_path, *args, :out => '/dev/null', :err => '/dev/null', :in => '/dev/null',
|
|
283
269
|
:chdir => '/', :pgroup => true)
|
|
284
270
|
Process.detach(pid)
|
|
285
271
|
File.open(Eye::Settings.pid_path, 'w'){|f| f.write(pid) }
|
|
286
272
|
|
|
287
273
|
unless wait_server
|
|
288
|
-
|
|
289
|
-
exit 1
|
|
274
|
+
error! "server not runned in 15 seconds, something crazy wrong"
|
|
290
275
|
end
|
|
291
276
|
|
|
292
277
|
configs.unshift(Eye::Settings.eyeconfig) if File.exists?(Eye::Settings.eyeconfig)
|
data/examples/notify.eye
CHANGED
data/examples/puma.eye
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
RUBY = '/usr/local/ruby/1.9.3-p392/bin/ruby'
|
|
2
2
|
RAILS_ENV = 'production'
|
|
3
|
-
ROOT =
|
|
3
|
+
ROOT = File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
|
4
4
|
CURRENT = File.expand_path(File.join(ROOT, %w{current}))
|
|
5
5
|
LOGS = File.expand_path(File.join(ROOT, %w{shared log}))
|
|
6
6
|
PIDS = File.expand_path(File.join(ROOT, %w{shared pids}))
|
|
@@ -12,7 +12,7 @@ end
|
|
|
12
12
|
|
|
13
13
|
Eye.application :super_app do
|
|
14
14
|
env 'RAILS_ENV' => RAILS_ENV
|
|
15
|
-
working_dir
|
|
15
|
+
working_dir ROOT
|
|
16
16
|
triggers :flapping, :times => 10, :within => 1.minute
|
|
17
17
|
|
|
18
18
|
process :puma do
|
data/examples/rbenv.eye
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Eye.application "rbenv_example" do
|
|
2
2
|
env 'RBENV_ROOT' => '/usr/local/rbenv', 'PATH' => "/usr/local/rbenv/shims:/usr/local/rbenv/bin:#{ENV['PATH']}"
|
|
3
|
-
working_dir
|
|
3
|
+
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
|
4
4
|
|
|
5
5
|
process "some_process" do
|
|
6
6
|
pid_file "some.pid"
|
|
@@ -8,4 +8,4 @@ Eye.application "rbenv_example" do
|
|
|
8
8
|
daemonize true
|
|
9
9
|
stdall "some.log"
|
|
10
10
|
end
|
|
11
|
-
end
|
|
11
|
+
end
|
data/examples/sidekiq.eye
CHANGED
|
@@ -16,8 +16,8 @@ def sidekiq_process(proxy, name)
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
Eye.application :sidekiq_test do
|
|
19
|
-
working_dir
|
|
19
|
+
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
|
20
20
|
env "RAILS_ENV" => 'production'
|
|
21
21
|
|
|
22
22
|
sidekiq_process self, :sidekiq
|
|
23
|
-
end
|
|
23
|
+
end
|
data/examples/thin-farm.eye
CHANGED
data/examples/unicorn.eye
CHANGED
|
@@ -5,7 +5,7 @@ RAILS_ENV = 'production'
|
|
|
5
5
|
|
|
6
6
|
Eye.application "rails_unicorn" do
|
|
7
7
|
env "RAILS_ENV" => RAILS_ENV, "PATH" => "#{File.dirname(RUBY)}:#{ENV['PATH']}"
|
|
8
|
-
working_dir
|
|
8
|
+
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
|
9
9
|
|
|
10
10
|
process("unicorn") do
|
|
11
11
|
pid_file "tmp/pids/unicorn.pid"
|
data/eye.gemspec
CHANGED
|
@@ -30,7 +30,6 @@ Gem::Specification.new do |gem|
|
|
|
30
30
|
|
|
31
31
|
gem.add_development_dependency 'rake'
|
|
32
32
|
gem.add_development_dependency 'rspec'
|
|
33
|
-
gem.add_development_dependency 'simplecov'
|
|
34
33
|
gem.add_development_dependency 'rr'
|
|
35
34
|
gem.add_development_dependency 'ruby-graphviz'
|
|
36
35
|
gem.add_development_dependency 'forking'
|
|
@@ -39,4 +38,5 @@ Gem::Specification.new do |gem|
|
|
|
39
38
|
gem.add_development_dependency 'sinatra'
|
|
40
39
|
gem.add_development_dependency 'thin'
|
|
41
40
|
gem.add_development_dependency 'xmpp4r'
|
|
41
|
+
gem.add_development_dependency 'coveralls'
|
|
42
42
|
end
|
data/lib/eye.rb
CHANGED
data/lib/eye/application.rb
CHANGED
data/lib/eye/checker.rb
CHANGED
|
@@ -13,6 +13,16 @@ class Eye::Checker
|
|
|
13
13
|
|
|
14
14
|
attr_accessor :value, :values, :options, :pid, :type, :check_count
|
|
15
15
|
|
|
16
|
+
def self.name_and_class(type)
|
|
17
|
+
type = type.to_sym
|
|
18
|
+
return {:name => type, :type => type} if TYPES[type]
|
|
19
|
+
|
|
20
|
+
if type =~ /\A(.*?)_?[0-9]+\z/
|
|
21
|
+
ctype = $1.to_sym
|
|
22
|
+
return {:name => type, :type => ctype} if TYPES[ctype]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
16
26
|
def self.get_class(type)
|
|
17
27
|
klass = eval("Eye::Checker::#{TYPES[type]}") rescue nil
|
|
18
28
|
raise "Unknown checker #{type}" unless klass
|
|
@@ -6,10 +6,24 @@ module Eye::Controller::Helpers
|
|
|
6
6
|
$0 = str
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
def save_cache
|
|
10
|
+
File.open(Eye::Settings.cache_path, 'w') { |f| f.write(cache_str) }
|
|
11
|
+
rescue => ex
|
|
12
|
+
warn "save cache crashed with #{ex.message}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def cache_str
|
|
16
|
+
all_processes.map{ |p| "#{p.full_name}=#{p.state}" } * "\n"
|
|
17
|
+
end
|
|
18
|
+
|
|
9
19
|
def process_by_name(name)
|
|
10
20
|
all_processes.detect{|c| c.name == name}
|
|
11
21
|
end
|
|
12
22
|
|
|
23
|
+
def process_by_full_name(name)
|
|
24
|
+
all_processes.detect{|c| c.full_name == name }
|
|
25
|
+
end
|
|
26
|
+
|
|
13
27
|
def group_by_name(name)
|
|
14
28
|
all_groups.detect{|c| c.name == name}
|
|
15
29
|
end
|
|
@@ -58,4 +72,4 @@ module Eye::Controller::Helpers
|
|
|
58
72
|
res
|
|
59
73
|
end
|
|
60
74
|
|
|
61
|
-
end
|
|
75
|
+
end
|
data/lib/eye/controller/load.rb
CHANGED
|
@@ -22,6 +22,7 @@ module Eye::Controller::Load
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
set_proc_line
|
|
25
|
+
save_cache
|
|
25
26
|
|
|
26
27
|
res
|
|
27
28
|
end
|
|
@@ -35,6 +36,8 @@ private
|
|
|
35
36
|
{ :error => false, :config => yield }
|
|
36
37
|
|
|
37
38
|
rescue Eye::Dsl::Error, Exception, NoMethodError => ex
|
|
39
|
+
raise if ex.class.to_s.include?('RR') # skip RR exceptions
|
|
40
|
+
|
|
38
41
|
error "load: config error <#{filename}>: #{ex.message}"
|
|
39
42
|
|
|
40
43
|
# filter backtrace for user output
|
|
@@ -18,7 +18,7 @@ module Eye::Controller::Options
|
|
|
18
18
|
def set_opt_http(params = {})
|
|
19
19
|
if params[:enable]
|
|
20
20
|
if @http
|
|
21
|
-
if params[:host] != @http.host || params[:
|
|
21
|
+
if params[:host] != @http.host || params[:port].to_i != @http.port
|
|
22
22
|
stop_http
|
|
23
23
|
start_http(params[:host], params[:port])
|
|
24
24
|
end
|
|
@@ -4,7 +4,9 @@ module Eye::Controller::SendCommand
|
|
|
4
4
|
matched_objects(*obj_strs) do |obj|
|
|
5
5
|
if command.to_sym == :delete
|
|
6
6
|
remove_object_from_tree(obj)
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
set_proc_line
|
|
9
|
+
save_cache
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
obj.send_command(command)
|
|
@@ -61,32 +63,44 @@ private
|
|
|
61
63
|
return [] if obj_strs.blank?
|
|
62
64
|
return @applications.dup if obj_strs.size == 1 && (obj_strs[0].strip == 'all' || obj_strs[0].strip == '*')
|
|
63
65
|
|
|
64
|
-
res =
|
|
66
|
+
res = Eye::Utils::AliveArray.new
|
|
65
67
|
obj_strs.map{|c| c.split(",")}.flatten.each do |mask|
|
|
66
|
-
res += find_objects_by_mask(mask)
|
|
68
|
+
res += find_objects_by_mask(mask.to_s.strip)
|
|
67
69
|
end
|
|
70
|
+
res
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def find_objects_by_mask(mask)
|
|
74
|
+
res = find_all_objects_by_mask(mask)
|
|
68
75
|
|
|
69
76
|
if res.size > 1
|
|
70
|
-
|
|
77
|
+
final = Eye::Utils::AliveArray.new
|
|
71
78
|
|
|
72
|
-
|
|
79
|
+
if mask[-1] != '*'
|
|
80
|
+
# try to find exactly matched
|
|
81
|
+
r = right_regexp(mask)
|
|
82
|
+
res.each do |obj|
|
|
83
|
+
final << obj if obj.full_name =~ r
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
return final if final.present?
|
|
88
|
+
|
|
89
|
+
# remove inherited targets
|
|
73
90
|
res.each do |obj|
|
|
74
91
|
sub_object = res.any?{|a| a.sub_object?(obj) }
|
|
75
92
|
final << obj unless sub_object
|
|
76
93
|
end
|
|
77
94
|
|
|
78
95
|
res = final
|
|
79
|
-
end
|
|
96
|
+
end
|
|
80
97
|
|
|
81
|
-
res
|
|
98
|
+
res
|
|
82
99
|
end
|
|
83
100
|
|
|
84
|
-
def
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
res = []
|
|
88
|
-
str = Regexp.escape(mask).gsub('\*', '.*?')
|
|
89
|
-
r = %r{\A#{str}}
|
|
101
|
+
def find_all_objects_by_mask(mask)
|
|
102
|
+
res = Eye::Utils::AliveArray
|
|
103
|
+
r = left_regexp(mask)
|
|
90
104
|
|
|
91
105
|
# find app
|
|
92
106
|
res = @applications.select{|a| a.name =~ r || a.full_name =~ r }
|
|
@@ -102,9 +116,16 @@ private
|
|
|
102
116
|
gr.processes.each do |p|
|
|
103
117
|
res << p if p.name =~ r || p.full_name =~ r
|
|
104
118
|
|
|
119
|
+
# child matching
|
|
105
120
|
if p.childs.present?
|
|
106
|
-
|
|
121
|
+
childs = p.childs.values
|
|
122
|
+
res += childs.select do |ch|
|
|
123
|
+
name = ch.name rescue ''
|
|
124
|
+
full_name = ch.full_name rescue ''
|
|
125
|
+
name =~ r || full_name =~ r
|
|
126
|
+
end
|
|
107
127
|
end
|
|
128
|
+
|
|
108
129
|
end
|
|
109
130
|
end
|
|
110
131
|
end
|
|
@@ -112,4 +133,13 @@ private
|
|
|
112
133
|
res
|
|
113
134
|
end
|
|
114
135
|
|
|
136
|
+
def left_regexp(mask)
|
|
137
|
+
str = Regexp.escape(mask).gsub('\*', '.*?')
|
|
138
|
+
%r|\A#{str}|
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def right_regexp(mask)
|
|
142
|
+
str = Regexp.escape(mask).gsub('\*', '.*?')
|
|
143
|
+
%r|#{str}\z|
|
|
144
|
+
end
|
|
115
145
|
end
|