zabcon 0.0.1
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/README +10 -0
- data/libs/argument_processor.rb +768 -0
- data/libs/command_help.rb +106 -0
- data/libs/command_tree.rb +307 -0
- data/libs/defines.rb +46 -0
- data/libs/exceptions.rb +119 -0
- data/libs/help.xml +275 -0
- data/libs/input.rb +55 -0
- data/libs/printer.rb +383 -0
- data/libs/zabcon_core.rb +742 -0
- data/libs/zabcon_exceptions.rb +45 -0
- data/libs/zabcon_globals.rb +210 -0
- data/libs/zbxcliserver.rb +310 -0
- data/libs/zdebug.rb +163 -0
- data/zabcon.conf.default +6 -0
- data/zabcon.rb +236 -0
- metadata +124 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
#GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.html
|
2
|
+
#Zabbix CLI Tool and associated files
|
3
|
+
#Copyright (C) 2009,2010 Andrew Nelson nelsonab(at)red-tux(dot)net
|
4
|
+
#
|
5
|
+
#This program is free software; you can redistribute it and/or
|
6
|
+
#modify it under the terms of the GNU General Public License
|
7
|
+
#as published by the Free Software Foundation; either version 2
|
8
|
+
#of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
#This program is distributed in the hope that it will be useful,
|
11
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
#GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
#You should have received a copy of the GNU General Public License
|
16
|
+
#along with this program; if not, write to the Free Software
|
17
|
+
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
18
|
+
|
19
|
+
##########################################
|
20
|
+
# Subversion information
|
21
|
+
# $Id: command_help.rb 258 2010-12-28 22:49:21Z nelsonab $
|
22
|
+
# $Revision: 258 $
|
23
|
+
##########################################
|
24
|
+
|
25
|
+
require 'libs/zdebug'
|
26
|
+
|
27
|
+
require 'pp'
|
28
|
+
require 'rexml/document'
|
29
|
+
|
30
|
+
# CommandHelp is the class which behaves as a wrapper to the help text stored in a separate file.
|
31
|
+
# All help functions are dynamically generated by default. This is done through the lambda procedure
|
32
|
+
# in the method "method". The overloaded method "method" attempts to determine if the symbol passed
|
33
|
+
# in matches a pre-existing method. If it does not a local default lambda is created and returned.
|
34
|
+
class CommandHelp
|
35
|
+
|
36
|
+
include ZDebug
|
37
|
+
|
38
|
+
def initialize(language)
|
39
|
+
@file = File.new("libs/help.xml")
|
40
|
+
|
41
|
+
@doc=REXML::Document.new(@file).elements["//help[@language='#{language}']"]
|
42
|
+
# puts @doc.root.attributes
|
43
|
+
|
44
|
+
EnvVars.instance.register_notifier("language",self.method(:language=))
|
45
|
+
end
|
46
|
+
|
47
|
+
def language=(language)
|
48
|
+
@file.rewind
|
49
|
+
@doc=REXML::Document.new(@file).elements["//help[@language='#{language}']"]
|
50
|
+
end
|
51
|
+
|
52
|
+
alias o_method method
|
53
|
+
|
54
|
+
# This overloaded method returns a local lambda if the symbol passed in is not found
|
55
|
+
# The lambda behaves as a default help function looking up the passed in symbol in the help file
|
56
|
+
# If the command is found but no help exists, a message stating this is printed
|
57
|
+
def method(sym)
|
58
|
+
debug(8,sym,"CommandHelp.method overload (sym)")
|
59
|
+
methods=self.methods
|
60
|
+
index=methods.index(sym.to_s)
|
61
|
+
if !index.nil?
|
62
|
+
method_local=o_method(sym)
|
63
|
+
else
|
64
|
+
method_local=lambda do |not_used| #not_used is here due to zabcon_globals and callbacks.
|
65
|
+
debug(6, sym, "auto generated help func for")
|
66
|
+
item=@doc.elements["//item[@command='#{sym.to_s}']"]
|
67
|
+
if item.nil?
|
68
|
+
puts "Help not available for internal command: #{sym.to_s}"
|
69
|
+
else
|
70
|
+
puts item.text
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
debug(8,method_local,"returning")
|
75
|
+
method_local
|
76
|
+
end
|
77
|
+
|
78
|
+
def help(command_tree,input)
|
79
|
+
debug(6,command_tree.commands,"command_tree",350)
|
80
|
+
debug(6,input,"input")
|
81
|
+
|
82
|
+
items=input.split(" ")
|
83
|
+
if items.length==1
|
84
|
+
debug(6)
|
85
|
+
|
86
|
+
puts @doc.elements["//item[@command='help']"].text
|
87
|
+
else # more than "help" was typed by the user
|
88
|
+
items.delete("help")
|
89
|
+
help_cmd=items.join(" ").lstrip.chomp
|
90
|
+
|
91
|
+
if help_cmd=="commands"
|
92
|
+
puts @doc.elements["//item[@command='help_commands']"].text
|
93
|
+
else
|
94
|
+
debug(4,help_cmd,"Searching for help on")
|
95
|
+
|
96
|
+
cmd=command_tree.search(help_cmd)[0] #search returns an array
|
97
|
+
|
98
|
+
if !cmd.helpproc.nil?
|
99
|
+
cmd.helpproc.call(nil) #TODO: need to fix, see line 67 above
|
100
|
+
else
|
101
|
+
puts "Unable to find help for \"#{help_cmd}\""
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end #def help
|
106
|
+
end
|
@@ -0,0 +1,307 @@
|
|
1
|
+
#GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.html
|
2
|
+
#Zabbix CLI Tool and associated files
|
3
|
+
#Copyright (C) 2009,2010 Andrew Nelson nelsonab(at)red-tux(dot)net
|
4
|
+
#
|
5
|
+
#This program is free software; you can redistribute it and/or
|
6
|
+
#modify it under the terms of the GNU General Public License
|
7
|
+
#as published by the Free Software Foundation; either version 2
|
8
|
+
#of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
#This program is distributed in the hope that it will be useful,
|
11
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
#GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
#You should have received a copy of the GNU General Public License
|
16
|
+
#along with this program; if not, write to the Free Software
|
17
|
+
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
18
|
+
|
19
|
+
##########################################
|
20
|
+
# Subversion information
|
21
|
+
# $Id: command_tree.rb 258 2010-12-28 22:49:21Z nelsonab $
|
22
|
+
# $Revision: 258 $
|
23
|
+
##########################################
|
24
|
+
|
25
|
+
require 'libs/zdebug'
|
26
|
+
require 'libs/zabcon_exceptions'
|
27
|
+
|
28
|
+
class Parser
|
29
|
+
|
30
|
+
include ZDebug
|
31
|
+
|
32
|
+
attr_reader :commands
|
33
|
+
|
34
|
+
def initialize(default_argument_processor)
|
35
|
+
@commands=CommandTree.new("",nil,0,nil,nil,nil,nil)
|
36
|
+
@default_argument_processor=default_argument_processor
|
37
|
+
end
|
38
|
+
|
39
|
+
def strip_comments(str)
|
40
|
+
str.lstrip!
|
41
|
+
str.chomp!
|
42
|
+
if str =~ /^ ## .*/ then
|
43
|
+
str = ""
|
44
|
+
elsif str =~ /(.+) ## .*/ then
|
45
|
+
str = Regexp.last_match(1)
|
46
|
+
else
|
47
|
+
str
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def search(str)
|
52
|
+
debug(7,str,"Searching")
|
53
|
+
|
54
|
+
str=strip_comments(str)
|
55
|
+
|
56
|
+
nodes = [""]+str.split
|
57
|
+
|
58
|
+
cmd_node=@commands.search(nodes) # a side effect of the function is that it also manipulates nodes
|
59
|
+
debug(7,cmd_node,"search result")
|
60
|
+
args=nodes.join(" ")
|
61
|
+
|
62
|
+
return cmd_node,args
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# Returns nil if the command is incomplete or unknown
|
68
|
+
# If the command is known the associated argument processor is also called and it's results are returned as part
|
69
|
+
# of the return hash
|
70
|
+
# the return hash consists of:
|
71
|
+
# :proc - the name of the procedure which will execute the associated command
|
72
|
+
# :api_params - parameters to pass to the API call
|
73
|
+
# :show_params - parameters to pass to the print routines
|
74
|
+
# :helpproc - help procedure associated with the command
|
75
|
+
# The argument processor function is passed a string of the arguments after the command, along with the
|
76
|
+
# array of valid arguments and the help function associated with the command.
|
77
|
+
# If the argument processor has an error it should call the help function and return nil. In which case this function
|
78
|
+
# will return nil
|
79
|
+
def parse(str,user_vars=nil)
|
80
|
+
debug(7,str,"Parsing")
|
81
|
+
# options=
|
82
|
+
debug(7,user_vars,"User Variables")
|
83
|
+
cmd_node,args=search(str)
|
84
|
+
|
85
|
+
if cmd_node.commandproc.nil? then
|
86
|
+
raise ParseError.new("Parse error, incomplete/unknown command: #{str}",:retry=>true)
|
87
|
+
else
|
88
|
+
# The call here to the argument process requires one argument as it's a lambda block which is setup when the
|
89
|
+
# command node is created
|
90
|
+
debug(6,args,"calling argument processor")
|
91
|
+
args=cmd_node.argument_processor.call(args,user_vars)
|
92
|
+
debug(6,args,"received from argument processor")
|
93
|
+
retval = args.nil? ? nil : {:proc=>cmd_node.commandproc, :helpproc=>cmd_node.helpproc, :options=>cmd_node.options}.merge(args)
|
94
|
+
return retval
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def complete(str,loggedin=false)
|
99
|
+
nodes = str.split
|
100
|
+
cmd_node=@commands
|
101
|
+
i=0
|
102
|
+
while i<nodes.length
|
103
|
+
tmp=cmd_node.search(nodes[i])
|
104
|
+
break if tmp.nil?
|
105
|
+
cmd_node=tmp
|
106
|
+
i+=1
|
107
|
+
end
|
108
|
+
|
109
|
+
if cmd_node.commandproc.nil? then
|
110
|
+
# roll up the list of available commands.
|
111
|
+
commands = cmd_node.children.collect {|node| node.command}
|
112
|
+
|
113
|
+
# don't include the current node if the command is empty
|
114
|
+
if cmd_node.command!="" then commands += [cmd_node.command] end
|
115
|
+
return commands
|
116
|
+
else
|
117
|
+
puts "complete"
|
118
|
+
return nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def insert(insert_path,command,commandproc,arguments=[],helpproc=nil,argument_processor=nil,*options)
|
123
|
+
debug(10,{"insert_path"=>insert_path, "command"=>command, "commandproc"=>commandproc, "arguments"=> arguments, "helpproc"=>helpproc, "argument_processor"=>argument_processor, "options"=>options})
|
124
|
+
insert_path_arr=[""]+insert_path.split # we must pre-load our array with a blank node at the front
|
125
|
+
# p insert_path_arr
|
126
|
+
|
127
|
+
# If the parameter "argument_processor" is nil use the default argument processor
|
128
|
+
arg_processor = argument_processor.nil? ? @default_argument_processor : argument_processor
|
129
|
+
@commands.insert(insert_path_arr,command,commandproc,arguments,helpproc,arg_processor,options)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
class CommandTree
|
136
|
+
|
137
|
+
include ZDebug
|
138
|
+
|
139
|
+
attr_reader :command, :commandproc, :children, :arguments, :helpproc, :depth, :argument_processor, :options
|
140
|
+
|
141
|
+
# Arguments hash takes the form of {"name"=>{:type=>Class, :optional=>true/false}}
|
142
|
+
# If type is nil then the argument takes no options
|
143
|
+
def initialize(command,commandproc,depth,arguments,helpproc,argument_processor,options)
|
144
|
+
debug(10,{"command"=>command, "commandproc"=>commandproc, "arguments"=> arguments,"helpproc"=>helpproc,
|
145
|
+
"verify_func"=>argument_processor, "depth"=>depth, "options"=>options})
|
146
|
+
@command=command
|
147
|
+
@commandproc=commandproc
|
148
|
+
@children=[]
|
149
|
+
@arguments=arguments
|
150
|
+
@helpproc=helpproc
|
151
|
+
@depth=depth
|
152
|
+
# verify functions are special.
|
153
|
+
# We pass them the list of valid arguments first and then the parameters which need to be verified
|
154
|
+
# This will allow for either unique or generalized verification functions
|
155
|
+
# The verify function can safely be called with objects with no verify function as nil checking is performed in the
|
156
|
+
# lambda
|
157
|
+
# If no verify function was setup we return true
|
158
|
+
@argument_processor=lambda do |params,user_vars|
|
159
|
+
if argument_processor.nil?
|
160
|
+
nil
|
161
|
+
else
|
162
|
+
argument_processor.call(@helpproc,@arguments,params,user_vars,options) # We pass the list of valid arguments to
|
163
|
+
end
|
164
|
+
end
|
165
|
+
if options.nil?
|
166
|
+
@options=nil
|
167
|
+
else
|
168
|
+
@options = Hash[*options.collect { |v|
|
169
|
+
[v, true]
|
170
|
+
}.flatten]
|
171
|
+
end
|
172
|
+
debug(10,self.inspect,"Initialization complete")
|
173
|
+
end
|
174
|
+
|
175
|
+
def inspect
|
176
|
+
r_str ="#<#{self.class.to_s}:0x#{self.object_id.to_s(16)} @command=#{@command.inspect}, @commandproc=#{@commandproc.inspect}, "
|
177
|
+
r_str+="@helpproc=#{@helpproc.inspect}, @argument_processor=#{@argument_processor.inspect}, @arguments=#{@arguments.inspect}, "
|
178
|
+
r_str+="@options=#{@options.inspect}, "
|
179
|
+
r_str+="@depth=#{@depth}, @children="
|
180
|
+
if @children.empty?
|
181
|
+
r_str+= "[]"
|
182
|
+
else
|
183
|
+
children=@children.map {|child| child.command }
|
184
|
+
r_str+= children.inspect
|
185
|
+
end
|
186
|
+
r_str+=">"
|
187
|
+
r_str
|
188
|
+
end
|
189
|
+
|
190
|
+
# search will search check to see if the parameter command is found in the current node
|
191
|
+
# or the immediate children nodes. It does not search the tree beyond one level.
|
192
|
+
# The loggedin argument is used to differentiate searching for commands which require a valid
|
193
|
+
# login or not. If loggedin is false it will return commands which do not require a valid login.
|
194
|
+
def search(search_path)
|
195
|
+
debug(10,search_path,"search_path")
|
196
|
+
debug(10,self,"self",300)
|
197
|
+
|
198
|
+
return nil if search_path.nil?
|
199
|
+
return nil if search_path.empty?
|
200
|
+
|
201
|
+
retval=nil
|
202
|
+
|
203
|
+
retval=self if search_path[0]==@command
|
204
|
+
|
205
|
+
|
206
|
+
search_path.shift
|
207
|
+
debug(10,search_path, "shifted search path")
|
208
|
+
|
209
|
+
return retval if search_path.length==0
|
210
|
+
|
211
|
+
# p search_path
|
212
|
+
# p @children.map {|child| child.command}
|
213
|
+
debug(10,@children.map{|child| child.command},"Current children")
|
214
|
+
|
215
|
+
results=@children.map {|child| child.command==search_path[0] ? child : nil }
|
216
|
+
results.compact!
|
217
|
+
debug(10,results,"Children search results",200)
|
218
|
+
return retval if results.empty? # no more children to search, return retval which may be self or nil, see logic above
|
219
|
+
debug(10)
|
220
|
+
|
221
|
+
return results[0].search(search_path)
|
222
|
+
debug(10,"Not digging deeper")
|
223
|
+
|
224
|
+
return self if search_path[0]==@command
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
def insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options)
|
229
|
+
do_insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options,0)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Insert path is the path to insert the item into the tree
|
233
|
+
# Insert path is passed in as an array of names which associate with pre-existing nodes
|
234
|
+
# The function will recursively insert the command and will remove the top of the input path stack at each level until it
|
235
|
+
# finds the appropraite level. If the appropriate level is never found an exception is raised.
|
236
|
+
def do_insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options,depth)
|
237
|
+
debug(11,{"insert_path"=>insert_path, "command"=>command, "commandproc"=>commandproc, "arguments"=> arguments,
|
238
|
+
"helpproc"=>helpproc, "verify_func"=>argument_processor, "depth"=>depth})
|
239
|
+
debug(11,@command,"self.command")
|
240
|
+
# debug(11,@children.map {|child| child.command},"children")
|
241
|
+
|
242
|
+
if insert_path[0]==@command then
|
243
|
+
debug(11,"Found node")
|
244
|
+
if insert_path.length==1 then
|
245
|
+
debug(11,command,"inserting")
|
246
|
+
@children << CommandTree.new(command,commandproc,depth+1,arguments,helpproc,argument_processor,options)
|
247
|
+
else
|
248
|
+
debug(11,"Not found walking tree")
|
249
|
+
insert_path.shift
|
250
|
+
if !@children.empty? then
|
251
|
+
@children.each { |node| node.do_insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options,depth+1)}
|
252
|
+
else
|
253
|
+
raise(Command_Tree_Exception,"Unable to find insert point in Command Tree")
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
|
261
|
+
|
262
|
+
if __FILE__ == $0
|
263
|
+
|
264
|
+
require 'pp'
|
265
|
+
require 'argument_processor'
|
266
|
+
|
267
|
+
arg_processor=ArgumentProcessor.new()
|
268
|
+
commands=Parser.new(arg_processoor.method(:default))
|
269
|
+
commands.set_debug_level(6)
|
270
|
+
|
271
|
+
|
272
|
+
def test_parse(cmd)
|
273
|
+
puts "\ntesting \"#{cmd}\""
|
274
|
+
retval=commands.parse(cmd)
|
275
|
+
puts "result:"
|
276
|
+
return retval
|
277
|
+
end
|
278
|
+
commands.set_debug_level(0)
|
279
|
+
commands.insert "", "help", lambda { puts "This is a generic help stub" }
|
280
|
+
puts
|
281
|
+
commands.insert "", "get", nil
|
282
|
+
puts
|
283
|
+
commands.insert "get", "host", :gethost, {"show"=>{:type=>nil,:optional=>true}}
|
284
|
+
commands.set_debug_level(0)
|
285
|
+
puts
|
286
|
+
commands.insert "get", "user", :getuser
|
287
|
+
puts
|
288
|
+
commands.insert "get user", "group", :getusergroup
|
289
|
+
puts
|
290
|
+
|
291
|
+
pp commands
|
292
|
+
|
293
|
+
commands.set_debug_level(0)
|
294
|
+
|
295
|
+
test_parse("get user")
|
296
|
+
test_parse("get user show=all arg1 arg2")
|
297
|
+
test_parse("get user show=\"id, one, two, three\" arg1 arg2")
|
298
|
+
test_parse("get user group show=all arg1")
|
299
|
+
test_parse("set value")
|
300
|
+
test_parse("help")[:proc].call
|
301
|
+
|
302
|
+
|
303
|
+
p commands.complete("hel")
|
304
|
+
p commands.complete("help")
|
305
|
+
p commands.complete("get user all")
|
306
|
+
|
307
|
+
end
|
data/libs/defines.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
#GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.html
|
4
|
+
#Zabbix CLI Tool and associated files
|
5
|
+
#Copyright (C) 2009,2010 Andrew Nelson nelsonab(at)red-tux(dot)net
|
6
|
+
#
|
7
|
+
#This program is free software; you can redistribute it and/or
|
8
|
+
#modify it under the terms of the GNU General Public License
|
9
|
+
#as published by the Free Software Foundation; either version 2
|
10
|
+
#of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
#This program 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 this program; if not, write to the Free Software
|
19
|
+
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
20
|
+
|
21
|
+
##########################################
|
22
|
+
# Subversion information
|
23
|
+
# $Id: defines.rb 215 2010-09-25 21:22:37Z richlv $
|
24
|
+
# $Revision: 215 $
|
25
|
+
##########################################
|
26
|
+
|
27
|
+
# Zabbix constants
|
28
|
+
|
29
|
+
# Sysmap elements (Create Element Type drop down menu):
|
30
|
+
ME_HOST=0
|
31
|
+
ME_MAP=1
|
32
|
+
ME_TRIGGER=2
|
33
|
+
ME_HOSTGROUP=3
|
34
|
+
ME_IMAGE=4
|
35
|
+
|
36
|
+
# Sysmap connection draw type
|
37
|
+
MC_DT_LINE=1
|
38
|
+
MC_DT_BOLD=2
|
39
|
+
MC_DT_DOT=3
|
40
|
+
MC_DT_DASHED=4
|
41
|
+
|
42
|
+
# Sysmap label location
|
43
|
+
ML_BOTTOM=0
|
44
|
+
ML_LEFT=1
|
45
|
+
ML_RIGHT=2
|
46
|
+
ML_TOP=3
|