zabcon 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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