eye 0.4.2 → 0.5
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/.gitignore +2 -0
- data/.travis.yml +4 -0
- data/CHANGES.md +11 -0
- data/README.md +3 -3
- data/Rakefile +8 -0
- data/bin/eye +0 -316
- data/bin/loader_eye +3 -3
- data/examples/test.eye +2 -2
- data/eye.gemspec +4 -9
- data/lib/eye.rb +4 -2
- data/lib/eye/application.rb +3 -3
- data/lib/eye/checker.rb +14 -5
- data/lib/eye/checker/cputime.rb +23 -0
- data/lib/eye/checker/file_touched.rb +15 -0
- data/lib/eye/checker/http.rb +7 -9
- data/lib/eye/checker/memory.rb +1 -1
- data/lib/eye/checker/runtime.rb +28 -0
- data/lib/eye/checker/socket.rb +4 -4
- data/lib/eye/cli.rb +166 -0
- data/lib/eye/cli/commands.rb +79 -0
- data/lib/eye/cli/render.rb +137 -0
- data/lib/eye/cli/server.rb +85 -0
- data/lib/eye/client.rb +3 -3
- data/lib/eye/config.rb +17 -14
- data/lib/eye/controller.rb +6 -10
- data/lib/eye/controller/commands.rb +6 -10
- data/lib/eye/controller/helpers.rb +1 -1
- data/lib/eye/controller/send_command.rb +5 -2
- data/lib/eye/controller/status.rb +37 -105
- data/lib/eye/dsl.rb +1 -1
- data/lib/eye/dsl/application_opts.rb +6 -2
- data/lib/eye/dsl/child_process_opts.rb +3 -2
- data/lib/eye/dsl/config_opts.rb +2 -2
- data/lib/eye/dsl/group_opts.rb +2 -1
- data/lib/eye/dsl/main.rb +4 -2
- data/lib/eye/dsl/opts.rb +11 -4
- data/lib/eye/dsl/validation.rb +49 -43
- data/lib/eye/group.rb +1 -1
- data/lib/eye/loader.rb +5 -9
- data/lib/eye/{settings.rb → local.rb} +1 -1
- data/lib/eye/logger.rb +5 -0
- data/lib/eye/notify.rb +12 -6
- data/lib/eye/notify/jabber.rb +2 -2
- data/lib/eye/process/child.rb +3 -1
- data/lib/eye/process/commands.rb +2 -2
- data/lib/eye/process/controller.rb +1 -1
- data/lib/eye/process/trigger.rb +1 -1
- data/lib/eye/sigar.rb +5 -0
- data/lib/eye/system.rb +7 -6
- data/lib/eye/system_resources.rb +46 -41
- data/lib/eye/trigger.rb +15 -8
- data/lib/eye/trigger/flapping.rb +1 -1
- data/lib/eye/trigger/stop_childs.rb +1 -1
- data/lib/eye/trigger/transition.rb +15 -0
- data/lib/eye/utils.rb +12 -0
- data/lib/eye/utils/leak_19.rb +7 -0
- data/lib/eye/utils/mini_active_support.rb +106 -0
- metadata +24 -15
- data/lib/eye/controller/show_history.rb +0 -63
- data/lib/eye/trigger/state.rb +0 -11
data/lib/eye.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Eye
|
2
|
-
VERSION = "0.
|
2
|
+
VERSION = "0.5"
|
3
3
|
ABOUT = "Eye v#{VERSION} (c) 2012-2013 @kostya"
|
4
4
|
PROCLINE = "eye monitoring v#{VERSION}"
|
5
5
|
|
@@ -14,13 +14,15 @@ module Eye
|
|
14
14
|
autoload :Group, 'eye/group'
|
15
15
|
autoload :Dsl, 'eye/dsl'
|
16
16
|
autoload :Application, 'eye/application'
|
17
|
-
autoload :
|
17
|
+
autoload :Local, 'eye/local'
|
18
18
|
autoload :Client, 'eye/client'
|
19
19
|
autoload :Utils, 'eye/utils'
|
20
20
|
autoload :Notify, 'eye/notify'
|
21
21
|
autoload :Config, 'eye/config'
|
22
22
|
autoload :Reason, 'eye/reason'
|
23
|
+
autoload :Sigar, 'eye/sigar'
|
23
24
|
|
24
25
|
autoload :Controller, 'eye/controller'
|
25
26
|
autoload :Control, 'eye/control'
|
27
|
+
autoload :Cli, 'eye/cli'
|
26
28
|
end
|
data/lib/eye/application.rb
CHANGED
@@ -33,14 +33,14 @@ class Eye::Application
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def status_data_short
|
36
|
-
h = Hash.new
|
36
|
+
h = Hash.new
|
37
37
|
@groups.each do |c|
|
38
38
|
c.processes.each do |p|
|
39
|
+
h[p.state] ||= 0
|
39
40
|
h[p.state] += 1
|
40
41
|
end
|
41
42
|
end
|
42
|
-
|
43
|
-
{ name: @name, type: :application, state: str}
|
43
|
+
{ name: @name, type: :application, states: h}
|
44
44
|
end
|
45
45
|
|
46
46
|
def debug_data
|
data/lib/eye/checker.rb
CHANGED
@@ -1,20 +1,23 @@
|
|
1
1
|
class Eye::Checker
|
2
|
+
include Eye::Dsl::Validation
|
2
3
|
|
3
4
|
autoload :Memory, 'eye/checker/memory'
|
4
5
|
autoload :Cpu, 'eye/checker/cpu'
|
5
6
|
autoload :Http, 'eye/checker/http'
|
6
7
|
autoload :FileCTime, 'eye/checker/file_ctime'
|
7
8
|
autoload :FileSize, 'eye/checker/file_size'
|
9
|
+
autoload :FileTouched,'eye/checker/file_touched'
|
8
10
|
autoload :Socket, 'eye/checker/socket'
|
9
11
|
autoload :Nop, 'eye/checker/nop'
|
12
|
+
autoload :Runtime, 'eye/checker/runtime'
|
13
|
+
autoload :Cputime, 'eye/checker/cputime'
|
10
14
|
|
11
|
-
TYPES = {:memory =>
|
12
|
-
:ctime =>
|
13
|
-
:nop =>
|
15
|
+
TYPES = {:memory => 'Memory', :cpu => 'Cpu', :http => 'Http',
|
16
|
+
:ctime => 'FileCTime', :fsize => 'FileSize', :file_touched => 'FileTouched',
|
17
|
+
:socket => 'Socket', :nop => 'Nop', :runtime => 'Runtime', :cputime => 'Cputime' }
|
14
18
|
|
15
19
|
attr_accessor :value, :values, :options, :pid, :type, :check_count, :process
|
16
20
|
|
17
|
-
extend Eye::Dsl::Validation
|
18
21
|
param :every, [Fixnum, Float], false, 5
|
19
22
|
param :times, [Fixnum, Array], nil, 1
|
20
23
|
param :fires, [Symbol, Array], nil, nil, [:stop, :restart, :unmonitor, :nothing, :start, :delete]
|
@@ -34,6 +37,9 @@ class Eye::Checker
|
|
34
37
|
def self.get_class(type)
|
35
38
|
klass = eval("Eye::Checker::#{TYPES[type]}") rescue nil
|
36
39
|
raise "Unknown checker #{type}" unless klass
|
40
|
+
if deps = klass.depends_on
|
41
|
+
Array(deps).each { |d| require d }
|
42
|
+
end
|
37
43
|
klass
|
38
44
|
end
|
39
45
|
|
@@ -185,12 +191,15 @@ class Eye::Checker
|
|
185
191
|
end
|
186
192
|
|
187
193
|
def self.register(base)
|
188
|
-
name = base.to_s.gsub(
|
194
|
+
name = base.to_s.gsub('Eye::Checker::', '')
|
189
195
|
type = name.underscore.to_sym
|
190
196
|
Eye::Checker::TYPES[type] = name
|
191
197
|
Eye::Checker.const_set(name, base)
|
192
198
|
end
|
193
199
|
|
200
|
+
def self.depends_on
|
201
|
+
end
|
202
|
+
|
194
203
|
class CustomCell < Eye::Checker
|
195
204
|
def self.inherited(base)
|
196
205
|
super
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Eye::Checker::Cputime < Eye::Checker
|
2
|
+
|
3
|
+
# check :cputime, :every => 1.minute, :below => 120.minutes
|
4
|
+
|
5
|
+
param :below, [Fixnum, Float], true
|
6
|
+
|
7
|
+
def get_value
|
8
|
+
Eye::SystemResources.cputime(@pid).to_f
|
9
|
+
end
|
10
|
+
|
11
|
+
def human_value(value)
|
12
|
+
"#{value / 60}m"
|
13
|
+
end
|
14
|
+
|
15
|
+
def good?(value)
|
16
|
+
if below
|
17
|
+
value < below
|
18
|
+
else
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Eye::Checker::FileTouched < Eye::Checker
|
2
|
+
|
3
|
+
param :file, [String], true
|
4
|
+
param :delete, [TrueClass, FalseClass]
|
5
|
+
|
6
|
+
def get_value
|
7
|
+
File.exists?(file)
|
8
|
+
end
|
9
|
+
|
10
|
+
def good?(value)
|
11
|
+
File.delete(file) if value && delete
|
12
|
+
!value
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
data/lib/eye/checker/http.rb
CHANGED
@@ -7,7 +7,7 @@ class Eye::Checker::Http < Eye::Checker::Defer
|
|
7
7
|
|
8
8
|
param :url, String, true
|
9
9
|
param :pattern, [String, Regexp]
|
10
|
-
param :kind
|
10
|
+
param :kind, [String, Fixnum, Symbol]
|
11
11
|
param :timeout, [Fixnum, Float]
|
12
12
|
param :open_timeout, [Fixnum, Float]
|
13
13
|
param :read_timeout, [Fixnum, Float]
|
@@ -17,8 +17,7 @@ class Eye::Checker::Http < Eye::Checker::Defer
|
|
17
17
|
def initialize(*args)
|
18
18
|
super
|
19
19
|
|
20
|
-
@uri = URI.parse(url)
|
21
|
-
@pattern = pattern
|
20
|
+
@uri = URI.parse(url)
|
22
21
|
@kind = case kind
|
23
22
|
when Fixnum then Net::HTTPResponse::CODE_TO_OBJ[kind]
|
24
23
|
when String, Symbol then Net.const_get("HTTP#{kind.to_s.camelize}") rescue Net::HTTPSuccess
|
@@ -40,7 +39,6 @@ class Eye::Checker::Http < Eye::Checker::Defer
|
|
40
39
|
mes = ex.class.is_a?(Net::OpenTimeout) ? "OpenTimeout<#{@open_timeout}>" : "ReadTimeout<#{@read_timeout}>"
|
41
40
|
{:exception => mes}
|
42
41
|
else
|
43
|
-
error "#{ex.message}"
|
44
42
|
{:exception => "Timeout<#{@open_timeout},#{@read_timeout}>"}
|
45
43
|
end
|
46
44
|
|
@@ -55,13 +53,13 @@ class Eye::Checker::Http < Eye::Checker::Defer
|
|
55
53
|
return false
|
56
54
|
end
|
57
55
|
|
58
|
-
if
|
59
|
-
matched = if
|
60
|
-
|
56
|
+
if pattern
|
57
|
+
matched = if pattern.is_a?(Regexp)
|
58
|
+
pattern === value[:result].body
|
61
59
|
else
|
62
|
-
value[:result].body.include?(
|
60
|
+
value[:result].body.include?(pattern.to_s)
|
63
61
|
end
|
64
|
-
value[:notice] = "missing '#{
|
62
|
+
value[:notice] = "missing '#{pattern.to_s}'" unless matched
|
65
63
|
matched
|
66
64
|
else
|
67
65
|
true
|
data/lib/eye/checker/memory.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
class Eye::Checker::Runtime < Eye::Checker
|
2
|
+
|
3
|
+
# check :runtime, :every => 1.minute, :below => 120.minutes
|
4
|
+
|
5
|
+
param :below, [Fixnum, Float], true
|
6
|
+
|
7
|
+
def get_value
|
8
|
+
st = Eye::SystemResources.start_time(@pid)
|
9
|
+
if st
|
10
|
+
Time.now.to_i - st.to_i
|
11
|
+
else
|
12
|
+
0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def human_value(value)
|
17
|
+
"#{value / 60}m"
|
18
|
+
end
|
19
|
+
|
20
|
+
def good?(value)
|
21
|
+
if below
|
22
|
+
value < below
|
23
|
+
else
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/lib/eye/checker/socket.rb
CHANGED
@@ -80,7 +80,7 @@ class Eye::Checker::Socket < Eye::Checker::Defer
|
|
80
80
|
|
81
81
|
unless match
|
82
82
|
warn "proc #{expect_data} not matched (#{value[:result].truncate(30)}) answer"
|
83
|
-
value[:notice] =
|
83
|
+
value[:notice] = 'missing proc validation'
|
84
84
|
end
|
85
85
|
|
86
86
|
return match
|
@@ -104,7 +104,7 @@ class Eye::Checker::Socket < Eye::Checker::Defer
|
|
104
104
|
value[:exception]
|
105
105
|
else
|
106
106
|
if value[:result] == :listen
|
107
|
-
|
107
|
+
'listen'
|
108
108
|
else
|
109
109
|
res = "#{value[:result].to_s.size}b"
|
110
110
|
res += "<#{value[:notice]}>" if value[:notice]
|
@@ -138,7 +138,7 @@ private
|
|
138
138
|
def _read_data(socket)
|
139
139
|
case protocol
|
140
140
|
when :em_object
|
141
|
-
content =
|
141
|
+
content = ''
|
142
142
|
msg_size = socket.recv(4).unpack('N')[0] rescue 0
|
143
143
|
content << socket.recv(msg_size - content.length) while content.length < msg_size
|
144
144
|
if content.present?
|
@@ -149,4 +149,4 @@ private
|
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
|
-
end
|
152
|
+
end
|
data/lib/eye/cli.rb
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
gem 'thor'
|
2
|
+
require 'thor'
|
3
|
+
|
4
|
+
class Eye::Cli < Thor
|
5
|
+
autoload :Server, 'eye/cli/server'
|
6
|
+
autoload :Commands, 'eye/cli/commands'
|
7
|
+
autoload :Render, 'eye/cli/render'
|
8
|
+
|
9
|
+
include Eye::Cli::Server
|
10
|
+
include Eye::Cli::Commands
|
11
|
+
include Eye::Cli::Render
|
12
|
+
|
13
|
+
desc "info [MASK]", "processes info"
|
14
|
+
def info(mask = nil)
|
15
|
+
res = cmd(:info_data, *Array(mask))
|
16
|
+
say render_info(res)
|
17
|
+
say
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "status", "processes info (deprecated)"
|
21
|
+
def status
|
22
|
+
say ":status is deprecated, use :info instead", :yellow
|
23
|
+
info
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "xinfo", "eye-deamon info (-c show current config)"
|
27
|
+
method_option :config, :type => :boolean, :aliases => "-c"
|
28
|
+
def xinfo
|
29
|
+
res = cmd(:debug_data, :config => options[:config])
|
30
|
+
say render_debug_info(res)
|
31
|
+
say
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "oinfo", "onelined info"
|
35
|
+
def oinfo
|
36
|
+
res = cmd(:short_data)
|
37
|
+
say render_info(res)
|
38
|
+
say
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "history [MASK,...]", "processes history"
|
42
|
+
def history(*masks)
|
43
|
+
res = cmd(:history_data, *masks)
|
44
|
+
say render_history(res)
|
45
|
+
say
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "load [CONF, ...]", "load config (start eye-daemon if not) (-f foreground start)"
|
49
|
+
method_option :foreground, :type => :boolean, :aliases => "-f"
|
50
|
+
def load(*configs)
|
51
|
+
configs.map!{ |c| File.expand_path(c) } if !configs.empty?
|
52
|
+
|
53
|
+
if options[:foreground]
|
54
|
+
# in foreground we stop another server, and run just 1 current config version
|
55
|
+
error!("foreground expected only one config") if configs.size != 1
|
56
|
+
server_start_foreground(configs.first)
|
57
|
+
|
58
|
+
elsif server_started?
|
59
|
+
say_load_result cmd(:load, *configs)
|
60
|
+
|
61
|
+
else
|
62
|
+
server_start(configs)
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "quit", "eye-daemon quit"
|
68
|
+
def quit
|
69
|
+
res = _cmd(:quit)
|
70
|
+
|
71
|
+
# if eye server got crazy, stop by force
|
72
|
+
ensure_stop_previous_server if res != :corrupted_data
|
73
|
+
|
74
|
+
# remove pid_file
|
75
|
+
File.delete(Eye::Local.pid_path) if File.exists?(Eye::Local.pid_path)
|
76
|
+
|
77
|
+
say "quit...", :yellow
|
78
|
+
end
|
79
|
+
|
80
|
+
[:start, :stop, :restart, :unmonitor, :monitor, :delete, :match].each do |_cmd|
|
81
|
+
desc "#{_cmd} MASK[,...]", "#{_cmd} app,group or process"
|
82
|
+
define_method(_cmd) do |*masks|
|
83
|
+
send_command(_cmd, *masks)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
desc "signal SIG MASK[,...]", "send signal to app,group or process"
|
88
|
+
def signal(sig, *masks)
|
89
|
+
send_command(:signal, sig, *masks)
|
90
|
+
end
|
91
|
+
|
92
|
+
desc "break MASK[,...]", "break chain executing"
|
93
|
+
def break(*masks)
|
94
|
+
send_command(:break_chain, *masks)
|
95
|
+
end
|
96
|
+
|
97
|
+
desc "trace [MASK]", "tracing log(tail + grep) for app,group or process"
|
98
|
+
def trace(mask = "")
|
99
|
+
log_trace(mask)
|
100
|
+
end
|
101
|
+
|
102
|
+
map ["-v", "--version"] => :version
|
103
|
+
desc "version", "version"
|
104
|
+
def version
|
105
|
+
say Eye::ABOUT
|
106
|
+
end
|
107
|
+
|
108
|
+
desc "check CONF", "check config file syntax"
|
109
|
+
method_option :host, :type => :string, :aliases => "-h"
|
110
|
+
method_option :verbose, :type => :boolean, :aliases => "-v"
|
111
|
+
def check(conf)
|
112
|
+
conf = File.expand_path(conf) if conf && !conf.empty?
|
113
|
+
|
114
|
+
Eye::System.host = options[:host] if options[:host]
|
115
|
+
Eye::Dsl.verbose = options[:verbose]
|
116
|
+
|
117
|
+
say_load_result Eye::Controller.new.check(conf), :syntax => true
|
118
|
+
end
|
119
|
+
|
120
|
+
desc "explain CONF", "explain config tree"
|
121
|
+
method_option :host, :type => :string, :aliases => "-h"
|
122
|
+
method_option :verbose, :type => :boolean, :aliases => "-v"
|
123
|
+
def explain(conf)
|
124
|
+
conf = File.expand_path(conf) if conf && !conf.empty?
|
125
|
+
|
126
|
+
Eye::System.host = options[:host] if options[:host]
|
127
|
+
Eye::Dsl.verbose = options[:verbose]
|
128
|
+
|
129
|
+
say_load_result Eye::Controller.new.explain(conf), :print_config => true, :syntax => true
|
130
|
+
end
|
131
|
+
|
132
|
+
desc "watch [MASK]", "interactive processes info"
|
133
|
+
def watch(*args)
|
134
|
+
cmd = if `watch --version 2>&1`.chop > '0.2.0'
|
135
|
+
"watch -n 1 --color #{$0} i #{args * ' '}"
|
136
|
+
else
|
137
|
+
"watch -n 1 #{$0} i #{args * ' '}"
|
138
|
+
end
|
139
|
+
|
140
|
+
pid = Process.spawn(cmd)
|
141
|
+
Process.waitpid(pid)
|
142
|
+
rescue Interrupt
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def error!(msg)
|
148
|
+
say msg, :red
|
149
|
+
exit 1
|
150
|
+
end
|
151
|
+
|
152
|
+
def print(msg, new_line = true)
|
153
|
+
say msg if msg && !msg.empty?
|
154
|
+
say if new_line
|
155
|
+
end
|
156
|
+
|
157
|
+
def log_trace(tag = '')
|
158
|
+
log_file = cmd(:logger_dev)
|
159
|
+
if log_file && File.exists?(log_file)
|
160
|
+
Process.exec "tail -n 100 -f #{log_file} | grep '#{tag}'"
|
161
|
+
else
|
162
|
+
error! "log file not found #{log_file.inspect}"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Eye::Cli::Commands
|
2
|
+
private
|
3
|
+
|
4
|
+
def client
|
5
|
+
@client ||= Eye::Client.new(Eye::Local.socket_path)
|
6
|
+
end
|
7
|
+
|
8
|
+
def _cmd(cmd, *args)
|
9
|
+
client.command(cmd, *args)
|
10
|
+
rescue Errno::ECONNREFUSED, Errno::ENOENT
|
11
|
+
:not_started
|
12
|
+
end
|
13
|
+
|
14
|
+
def cmd(cmd, *args)
|
15
|
+
res = _cmd(cmd, *args)
|
16
|
+
|
17
|
+
if res == :not_started
|
18
|
+
error! "socket(#{Eye::Local.socket_path}) not found, did you `eye load`?"
|
19
|
+
elsif res == :timeouted
|
20
|
+
error! 'eye does not answer, timeouted...'
|
21
|
+
end
|
22
|
+
|
23
|
+
res
|
24
|
+
end
|
25
|
+
|
26
|
+
def say_load_result(res = {}, opts = {})
|
27
|
+
error!(res) unless res.is_a?(Hash)
|
28
|
+
say_filename = (res.size > 1)
|
29
|
+
say 'eye started!', :green if opts[:started]
|
30
|
+
error = false
|
31
|
+
res.each do |filename, _res|
|
32
|
+
say "#{filename}: ", nil, true if say_filename
|
33
|
+
show_load_message(_res, opts)
|
34
|
+
error = true if _res[:error]
|
35
|
+
end
|
36
|
+
|
37
|
+
exit(1) if error
|
38
|
+
end
|
39
|
+
|
40
|
+
def show_load_message(res, opts = {})
|
41
|
+
if res[:error]
|
42
|
+
say res[:message], :red
|
43
|
+
res[:backtrace].to_a.each{|line| say line, :red }
|
44
|
+
else
|
45
|
+
if opts[:syntax]
|
46
|
+
say 'config ok!', :green if !res[:empty]
|
47
|
+
else
|
48
|
+
say 'config loaded!', :green if !res[:empty]
|
49
|
+
end
|
50
|
+
|
51
|
+
if opts[:print_config]
|
52
|
+
require 'pp'
|
53
|
+
PP.pp res[:config], STDOUT, 150
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def send_command(_cmd, *args)
|
59
|
+
res = cmd(_cmd, *args)
|
60
|
+
if res == :unknown_command
|
61
|
+
error! "unknown command :#{_cmd}"
|
62
|
+
elsif res == :corrupted_data
|
63
|
+
error! 'something crazy wrong, check eye logs!'
|
64
|
+
elsif res.is_a?(Hash)
|
65
|
+
if res[:error]
|
66
|
+
error! "Error: #{res[:error]}"
|
67
|
+
elsif res = res[:result]
|
68
|
+
if res == []
|
69
|
+
error! "command :#{_cmd}, objects not found!"
|
70
|
+
else
|
71
|
+
say "command :#{_cmd} sended to [#{res * ", "}]"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
else
|
75
|
+
error! "unknown result #{res.inspect}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|