zabby 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,19 @@
2
2
 
3
3
  List of visible changes:
4
4
 
5
+ == v0.1.0 (2012/03/14)
6
+
7
+ * Major refactoring: Zabbix items are now represented by classes instead
8
+ of class instances ("Host" vs. "host", "Item" vs. "item") and their
9
+ methods are now class methods.
10
+ * Simplify code, remove unused or useless methods.
11
+ * Move helper methods to their own module.
12
+ * Update documentation and improve code samples.
13
+ * Online "help" command.
14
+ * Get rid of the elegant but buggy "set <param> <value>" syntax, the only
15
+ valid syntax for setting parameters is "set :<param> => <value>".
16
+ * Improve exceptions definition.
17
+
5
18
  == v0.0.5 (2012/01/05)
6
19
 
7
20
  * Better command file parsing and add rcfile support.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2011 Farzad FARID / Pragmatic Source. All rights reserved.
1
+ Copyright 2011-2012 Farzad FARID / Pragmatic Source. All rights reserved.
2
2
 
3
3
  Redistribution and use in source and binary forms, with or without modification, are
4
4
  permitted provided that the following conditions are met:
@@ -5,11 +5,6 @@ clean interface to the {Zabbix Web Services}[http://www.zabbix.com/documentation
5
5
 
6
6
  == Goals
7
7
 
8
- There already are Ruby Zabbix libraries but some of them are unfinished (and apparently
9
- abandonned) and some other's code is too complicated or poorly designed. This is why I decided
10
- to write another tool for which my primary goal is to keep the code design, the user interaction
11
- and application interface clean and simple.
12
-
13
8
  Zabby has the following caracteristics:
14
9
  - Works both as a Ruby API and a command line tool.
15
10
  - Uses an internal Ruby DSL (Domain Specific Langage) that give access to the full power of
@@ -17,6 +12,11 @@ Zabby has the following caracteristics:
17
12
  - Simple design: avoids spaghetti code, WTF and facepalm, unlike some other
18
13
  Ruby Zabbix libraries.
19
14
 
15
+ There already are Ruby Zabbix libraries but some of them are unfinished (and apparently
16
+ abandonned) and some other's code is too complicated or poorly designed. This is why I decided
17
+ to write this tool for which my primary goal is to keep the code design the user interaction
18
+ and application interface clean and simple.
19
+
20
20
  == Features
21
21
 
22
22
  - Low level Ruby API that maps every Zabbix API (JSON RPC) to Ruby hashes.
@@ -24,14 +24,22 @@ Zabby has the following caracteristics:
24
24
  - Supports SSL and authenticated HTTP proxies.
25
25
  - Full featured IRB like shell included with Readline support. You can mix Zabbix instructions
26
26
  with Ruby calls transparently.
27
+ - Reads a configuration file on startup.
28
+
29
+ == Changes
30
+
31
+ See the [ChangeLog.rdoc] file.
27
32
 
28
33
  == Configuration
29
34
 
30
- The file <tt>~/.zabbyrc</tt> is read on startup unless the option "<tt>--no-rcfile</tt>" is
35
+ All the settings can be used interactively or written in a configuration file. The file
36
+ <tt>~/.zabbyrc</tt> is read on startup unless the option "<tt>--no-rcfile</tt>" is
31
37
  used.
32
38
 
33
39
  === Command line
34
40
 
41
+ The main configuration parameters are:
42
+
35
43
  --[no-]rcfile [CONFIG FILE]: Configuration file to load on startup. Default is '~/.zabbyrc'. With the 'no' prefix no configuration file will be loaded.
36
44
  -f, --extra-file COMMAND_FILE: Execute the instructions in COMMAND_FILE
37
45
 
@@ -62,33 +70,7 @@ This is a configuration <tt>.zabbyrc</tt> file example, it will be loaded at sta
62
70
 
63
71
  == Examples
64
72
 
65
- === API use
66
-
67
- The barebone API can be used in Ruby like this:
68
-
69
- require "rubygems"
70
- require "zabby"
71
- require "pp"
72
-
73
- z = Zabby.init do
74
- server "https://monitoring.example.com"
75
- user "api_user"
76
- password "s3cr3t"
77
- proxy_host "http://10.10.10.10"
78
- proxy_user "john"
79
- proxy_password "D0e"
80
- end
81
- z.login
82
-
83
- pp z.connection.perform_request("host", "get", { "filter" => { "host" => "master.example.com" } })
84
- pp z.connection.perform_request("item", "get", { "host" => "master.example.com", "output" => "shorten" })
85
-
86
- - The _server_, _user_ and _passord_ are necessary.
87
- - If you don't provide the path to the JSON-RPC script "/api_jsonrpc.php" is appended
88
- to the URI automatically.
89
- - The <em>proxy_*</em> settings are optionnal.
90
-
91
- === Shell
73
+ === Zabby on the Command Line
92
74
 
93
75
  *zabbysh* is an simple Zabbix Shell. It runs either interactively or
94
76
  can be used to execute a command file with the "-f CMD_FILE" option.
@@ -99,36 +81,114 @@ the shell after executing the file.
99
81
  *zabbysh* provides Readline support but does no support advanced IRB features likes
100
82
  multi-lines instructions.
101
83
 
102
- *zabbyrb* is another Zabbix Shell based on *IRB*. It provides the whole power of IRB
84
+ *Note*: *zabbyrb* is another Zabbix Shell based on *IRB*. It provides the whole power of IRB
103
85
  but may be less stable than zabbysh because the IRB API is poorly documented and hard
104
86
  to use.
105
87
 
106
88
  ==== Interactive shell
107
89
 
90
+ Provided you created a <tt>~/.zabbyrc</tt> configuration file with authentication settings
91
+ you can launch the interactive shell and start talking to the Zabbix server:
92
+
108
93
  # zabbysh
109
- zabby> set server "https://monitoring.example.com"
110
- zabby> set user "api_user"
111
- zabby> set password "s3cr3t"
112
- zabby> set proxy_host "http://10.10.10.10"
113
- zabby> set proxy_user "john"
114
- zabby> set proxy_password "D0e"
115
- zabby> login
116
- zabby> puts logged_in?
117
- zabby> host.get "filter" => { "host" => "monitor.example.com" }, "output" => "extend"
118
- zabby> item.get "host" => "monitor.example.com", "output" => "refer"
94
+ Zabby Shell 0.1.0
95
+
96
+ ** This is a simple irb like Zabbix Shell. Multiline commands do not work for e.g. **
97
+ Type "help" for online documentation.
98
+ zabby> logged_in?
99
+ => true
100
+ zabby> Host.get "filter" => { "host" => "monitor.example.com" }, "output" => "extend"
101
+ => [{"snmp_errors_from"=>"0", "ipmi_port"=>"623", "outbytes"=>"0", "proxy_hostid"=>"0",
102
+ "maintenance_status"=>"0", "ipmi_password"=>"", "ipmi_privilege"=>"2",
103
+ "ipmi_disable_until"=>"0", "available"=>"1", "maintenances"=>[{"maintenanceid"=>"0"}],
104
+ "ipmi_error"=>"", "maintenanceid"=>"0", "useipmi"=>"0", "port"=>"10050", "useip"=>"1",
105
+ "ipmi_errors_from"=>"0", "maintenance_from"=>"0", "ipmi_ip"=>"", "hostid"=>"10017",
106
+ "ipmi_available"=>"0", "disable_until"=>"0", "ip"=>"127.0.0.1", "maintenance_type"=>"0",
107
+ "ipmi_authtype"=>"0", "inbytes"=>"0", "lastaccess"=>"0",
108
+ "host"=>"monitor.example.com", "snmp_error"=>"", "ipmi_username"=>"", "status"=>"0",
109
+ "dns"=>"monitor.example.com", "snmp_available"=>"0", "snmp_disable_until"=>"0",
110
+ "errors_from"=>"0", "error"=>""}]
111
+ zabby> Item.get "host" => "monitor.example.com", "output" => "refer"
112
+ => [{"itemid"=>"18435", "host"=>"monitor.example.com"},
113
+ {"itemid"=>"18436", "host"=>"monitor.example.com"},
114
+ {"itemid"=>"18438", "host"=>"monitor.example.com"},
115
+ {"itemid"=>"18439",....]
119
116
  zabby> [...]
120
117
  zabby> logout
118
+ => nil
121
119
  zabby> exit
122
120
 
121
+ To execute a script file before dropping into the shell type:
122
+
123
+ # zabbysh --extra-file some_zabbix_cmds.zby
124
+
125
+ ===== Online help
126
+
127
+ Type *help* to get a brief description of available commands.
128
+
123
129
  ==== Execute a command script
124
130
 
125
- Create a file and put the same instructions as above in it, then execute *zabbysh*:
131
+ To execute a script non interactively create a file and put the same
132
+ instructions as above in it then execute *zabbysh*:
126
133
 
127
- # zabbysh --file my_zabbix_commands.txt
134
+ # zabbysh my_zabbix_commands.zby
135
+
136
+ You can even create auto-executable scripts! Just add "<tt>#!/usr/bin/env zabbysh</tt>"
137
+ on the first line of the script and make it executable with "<tt>chmod +x my_zabby_commands.zby</tt>".
138
+
139
+ For example create the script "my_zabbix_command.zby":
140
+
141
+ #!/usr/bin/env zabbysh
142
+ #
143
+ # Zabby configuration
144
+ set :server => "https://monitoring.example.com"
145
+ set :user => "api_user"
146
+ set :password => "s3cr3t"
147
+ set :proxy_host => "http://10.10.10.10"
148
+ set :proxy_user => "john"
149
+ set :proxy_password => "D0e"
150
+ login
151
+
152
+ hosts = Host.get "filter" => { "host" => "monitor.example.com" }, "output" => "extend"
153
+ h = hosts.first
154
+ puts "Host #{h['host']} has IP address #{h['ip']}"
155
+
156
+ exit 0
157
+
158
+ Now to execute the script you just have to type:
159
+
160
+ # ./my_zabbix_commands.zby
161
+
162
+ === API use
163
+
164
+ The barebone API can be used in Ruby like this:
165
+
166
+ require "rubygems"
167
+ require "zabby"
168
+ require "pp"
169
+
170
+ z = Zabby.init do
171
+ set :server => "https://monitoring.example.com"
172
+ set :user => "api_user"
173
+ set :password => "s3cr3t"
174
+ set :proxy_host => "http://10.10.10.10"
175
+ set :proxy_user => "john"
176
+ set :proxy_password => "D0e"
177
+ login
178
+ end
179
+
180
+ pp z.run { Host.get "filter" => { "host" => "master.example.com" } }
181
+ pp z.run { Item.get "host" => "master.example.com", "output" => "shorten" }
182
+
183
+
184
+ - The _server_, _user_ and _passord_ are necessary.
185
+ - If you don't provide the path to the JSON-RPC script "/api_jsonrpc.php" is appended
186
+ to the URI automatically.
187
+ - The <em>proxy_*</em> settings are optionnal.
128
188
 
129
189
  == Requirements
130
190
 
131
- - Ruby 1.8.5. IT BASICALLY RUNS ANYWHERE!
191
+ - Ruby 1.8.5. <b>IT BASICALLY RUNS ANYWHERE!</b>
132
192
  - JSON library: 'json' or 'json_pure'
133
193
  - OptionParser
134
194
  - Readline (optionnal, used by the interactive shell)
@@ -142,7 +202,8 @@ Create a file and put the same instructions as above in it, then execute *zabbys
142
202
 
143
203
  == Contributing
144
204
 
145
- All contributions are welcome. You can either open a ticket on Github, send a pull request
205
+ All contributions are welcome. You can either
206
+ {open a ticket on Github}[https://github.com/Pragmatic-Source/zabby/issues], send a pull request
146
207
  with a patch or send an email to the author.
147
208
 
148
209
  == Author
@@ -154,6 +215,7 @@ Farzad FARID mailto:ffarid@pragmatic-source.com
154
215
  - Jean-Hadrien Chabran (jhchabran): Advices on code design.
155
216
  - Nicolas Blanco (slainer68): Advices on code design and Triple Facepalming after reading other Ruby/Zabbix code.
156
217
  - Renaud Chaput (renchap): For suggesting the "zabby" name.
218
+ - Folks on the irc channel #rubyonrails.fr@Freenode
157
219
 
158
220
  === Sources of inspiration
159
221
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- encoding: utf-8 -*-
3
3
  # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
4
- # Copyright:: Copyright (c) 2011 Farzad FARID
4
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
5
5
  # License:: Simplified BSD License
6
6
 
7
7
  # This is an experimental Zabby Shell based on IRB. It is still buggy and the code
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- encoding: utf-8 -*-
3
3
  # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
4
- # Copyright:: Copyright (c) 2011 Farzad FARID
4
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
5
5
  # License:: Simplified BSD License
6
6
 
7
7
 
@@ -49,7 +49,8 @@ EOT
49
49
  opts.on_tail("--version", "Show version") do
50
50
  puts <<EOT
51
51
  Zabby #{Zabby::VERSION}
52
- Copyright (c) 2011 Farzad FARID / Pragmatic Source
52
+ Copyright (c) 2011-2012-2012 Farzad FARID / Pragmatic Source
53
+ Home page: http://www.zabby.org/
53
54
  License: Simplified BSD
54
55
  EOT
55
56
  exit
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
- # Copyright:: Copyright (c) 2011 Farzad FARID
3
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
4
4
  # License:: Simplified BSD License
5
5
 
6
6
  require 'rubygems'
@@ -14,8 +14,9 @@ require 'pp'
14
14
  require 'zabby/version'
15
15
  require 'zabby/exceptions'
16
16
  require 'zabby/config'
17
- require 'zabby/zobject'
17
+ require 'zabby/zclass'
18
18
  require 'zabby/connection'
19
+ require 'zabby/shell_helpers'
19
20
  require 'zabby/runner'
20
21
 
21
22
  module Zabby
@@ -1,27 +1,33 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
- # Copyright:: Copyright (c) 2011 Farzad FARID
3
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
4
4
  # License:: Simplified BSD License
5
5
 
6
6
  # Configuration setting
7
7
  module Zabby
8
8
  class Config
9
9
  SETTING_LIST = %w{server user password proxy_host proxy_user proxy_password}
10
-
11
- def initialize &block
12
- setup(&block)
13
- end
14
10
 
15
- def setup &block
16
- instance_eval(&block) if block_given?
11
+ # Initialize Zabby configuration settings
12
+ # @todo Anything to configure here?
13
+ def initialize
17
14
  end
18
15
 
16
+ # Display configuration variables
19
17
  def list
18
+ puts "Zabby configuration"
19
+ puts "==================="
20
20
  SETTING_LIST.each do |k|
21
21
  puts "#{k} = #{instance_variable_get("@#{k}")}"
22
22
  end
23
+ nil
23
24
  end
24
25
 
26
+ # Dynamic setter and getter methods for the configuration variables.
27
+ # @param [String] name Setting name, ending with "=" in case we are setting a value
28
+ # @param [Array] args Setting value
29
+ # @param [Proc] block Unused
30
+ # @return [Object] Return the value set
25
31
  def method_missing(name, *args, &block)
26
32
  name = name.to_s.gsub(/=$/, '')
27
33
  raise ConfigurationError.new("Unknown setting '#{name}'") if !SETTING_LIST.include?(name.to_s)
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
- # Copyright:: Copyright (c) 2011 Farzad FARID
3
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
4
4
  # License:: Simplified BSD License
5
5
 
6
6
  module Zabby
@@ -71,6 +71,7 @@ module Zabby
71
71
  end
72
72
 
73
73
  # Perform an authenticated request
74
+ # @return [Object] The Zabbix response (Hash, Boolean, etc.) in JSON format.
74
75
  def perform_request(element, action, params)
75
76
  raise AuthenticationError.new("Not logged in") if !logged_in?
76
77
 
@@ -78,6 +79,9 @@ module Zabby
78
79
  query_zabbix_rpc(message)
79
80
  end
80
81
 
82
+ # Prepare a JSON request HTTP Post format
83
+ # @param [Hash] message A hash with all parameters for the Zabbix web service.
84
+ # @return [Net::HTTP::Post] Message ready to be POSTed.
81
85
  def request(message)
82
86
  req = Net::HTTP::Post.new(@request_path)
83
87
  req.add_field('Content-Type', 'application/json-rpc')
@@ -99,34 +103,41 @@ module Zabby
99
103
  http
100
104
  end
101
105
 
106
+ # Raise a Zabby exception
107
+ # @param [Hash] zabbix_response JSON formatted Zabbix response.
108
+ # @raise [Zabby::AuthenticationError] Authentication error.
109
+ # @raise [zabby::APIError] Generic Zabbix Web Services error.
110
+ def format_exception(zabbix_response)
111
+ error = zabbix_response['error']
112
+ error_message = error['message']
113
+ error_data = error['data']
114
+ error_code = error['code']
115
+
116
+ if error_data == "Login name or password is incorrect"
117
+ raise AuthenticationError.new(error_message, error_code, error_data)
118
+ else
119
+ raise APIError.new(error_message, error_code, error_data)
120
+ end
121
+ end
122
+
123
+ # Query the Zabbix Web Services and extract the JSON response.
124
+ # @param [Hash] message request in JSON format.
125
+ # @return [Object] The Zabbix response (Hash, Boolean, etc.) in JSON format.
126
+ # @raise [Zabby::ResponseCodeError] HTTP error.
102
127
  def query_zabbix_rpc(message)
103
128
  # Send the request!
104
- response = http.request(request(message))
129
+ http_response = http.request(request(message))
105
130
 
106
- if response.code != "200" then
107
- raise ResponseCodeError.new("Response code from [#{@uri}] is #{response.code}): #{response.body}")
131
+ # Check for HTTP errors.
132
+ if http_response.code != "200"
133
+ raise ResponseCodeError.new("Error from #{@uri}", http_response.code, http_response.body)
108
134
  end
109
135
 
110
- zabbix_response = JSON.parse(response.body)
111
-
112
- #if not ( responce_body_hash['id'] == id ) then
113
- # raise Zabbix::InvalidAnswerId.new("Wrong ID in zabbix answer")
114
- #end
115
-
116
- # Check errors in zabbix answer. If error exist - raise exception Zabbix::Error
117
- if (error = zabbix_response['error']) then
118
- error_message = error['message']
119
- error_data = error['data']
120
- error_code = error['code']
121
-
122
- e_message = "Code: [" + error_code.to_s + "]. Message: [" + error_message +
123
- "]. Data: [" + error_data + "]."
136
+ zabbix_response = JSON.parse(http_response.body)
124
137
 
125
- if error_data == "Login name or password is incorrect"
126
- raise AuthenticationError.new(e_message)
127
- else
128
- raise StandardError.new(e_message)
129
- end
138
+ # Check for Zabbix errors.
139
+ if zabbix_response['error']
140
+ format_exception(zabbix_response)
130
141
  end
131
142
 
132
143
  zabbix_response['result']
@@ -1,10 +1,26 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
- # Copyright:: Copyright (c) 2011 Farzad FARID
3
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
4
4
  # License:: Simplified BSD License
5
5
 
6
6
  module Zabby
7
- class ResponseCodeError < StandardError; end
8
- class AuthenticationError < StandardError; end
7
+ class APIError < StandardError
8
+ attr_reader :code, :msg, :data
9
+
10
+ def initialize(msg, code = nil, data = nil)
11
+ @msg = msg
12
+ @code = code
13
+ @data = data
14
+ end
15
+
16
+ def message
17
+ text = "#{msg}"
18
+ text += ": #{data}" if data
19
+ text += " (code: #{code})" if code
20
+ text
21
+ end
22
+ end
23
+ class ResponseCodeError < APIError; end
24
+ class AuthenticationError < APIError; end
9
25
  class ConfigurationError < StandardError; end
10
- end
26
+ end
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
- # Copyright:: Copyright (c) 2011 Farzad FARID
3
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
4
4
  # License:: Simplified BSD License
5
5
 
6
6
  require 'singleton'
@@ -12,72 +12,23 @@ end
12
12
 
13
13
 
14
14
  module Zabby
15
+ # This is the main interpreter.
16
+ # Additional shell commands are defined in the ShellHelpers module.
15
17
  class Runner
16
18
  include Singleton
19
+ include ShellHelpers
17
20
 
18
21
  attr_reader :config, :connection
19
22
 
20
- # Meta-create methods with the same name as the configuration settings.
21
- # This way we can write:
22
- # set host "http://my.zabbix.server"
23
- # instead of:
24
- # set :host => "http://my.zabbix.server"
25
- # or "set host" instead of "set :host"
26
- # All the created method does is return the second form which will be
27
- # used by "set".
28
- Zabby::Config::SETTING_LIST.each { |setting|
29
- # TODO.rdoc: Ruby 1.8 does not support default values for block arguments..
30
- # Writing "... do |value = nil|" would be more elegant.
31
- define_method(setting) do |*args|
32
- if args.empty?
33
- setting.intern
34
- else
35
- { setting.intern => args.first }
36
- end
37
- end
38
- }
39
-
40
- # Create a method mapping a Zabbix object.
41
- # @param [Symbol] name Zabbix Object name (:item, :host, etc.)
42
- # @param [Array] zmethods The list of supported verbs
43
- def self.create_zobject(name, zmethods)
44
- define_method(name) do
45
- @zobject[name] ||= Zabby::ZObject.new(name, zmethods)
46
- end
47
- end
48
-
49
- # Create all Zabbix object types and theirs verbs.
50
- create_zobject(:action, [ :create, :delete, :exists, :get, :update ])
51
- create_zobject(:alert, [ :create, :delete, :get ])
52
- create_zobject(:apiinfo, [ :version ])
53
- create_zobject(:application, [ :create, :delete, :exists, :get, :massAdd, :update ])
54
- create_zobject(:event, [ :acknowledge, :create, :delete, :get ])
55
- create_zobject(:graph, [ :create, :delete, :exists, :get, :update ])
56
- create_zobject(:graphitem, [ :get ])
57
- create_zobject(:history, [ :delete, :get ])
58
- create_zobject(:host, [ :create, :delete, :exists, :get, :update ])
59
- create_zobject(:hostgroup, [ :create, :delete, :exists, :get, :massAdd, :massRemove, :massUpdate, :update ])
60
- create_zobject(:image, [ :create, :delete, :exists, :get, :update ])
61
- create_zobject(:item, [ :create, :delete, :exists, :get, :update ])
62
- create_zobject(:maintenance, [ :create, :delete, :exists, :get, :update ])
63
- create_zobject(:map, [ :create, :delete, :exists, :get, :update ])
64
- create_zobject(:mediatype, [ :create, :delete, :get, :update ])
65
- create_zobject(:proxy, [ :get ])
66
- create_zobject(:screen, [ :create, :delete, :get, :update ])
67
- create_zobject(:script, [ :create, :delete, :execute, :get, :update ])
68
- create_zobject(:template, [ :create, :delete, :exists, :get, :massAdd, :massRemove, :massUpdate, :update ])
69
- create_zobject(:trigger, [ :addDependencies, :create, :delete, :deleteDependencies, :exists, :get, :update ])
70
- create_zobject(:user, [ :addMedia, :authenticate, :create, :delete, :deleteMedia, :get, :login, :logout, :update, :updateMedia, :updateProfile ])
71
- create_zobject(:usergroup, [ :create, :delete, :exists, :get, :massAdd, :massRemove, :massUpdate, :update ])
72
- create_zobject(:usermacro, [ :createGlobal, :deleteGlobal, :deleteHostMacro, :get, :massAdd, :massRemove, :massUpdate, :updateGlobal ])
73
- create_zobject(:usermedia, [ :get ])
74
-
75
23
  def initialize &block
76
- @config = Zabby::Config.new &block
24
+ @config = Zabby::Config.new
77
25
  @connection = Zabby::Connection.new
78
26
  @pure_binding = instance_eval "binding"
79
- @zobject = {} # List of Zabbix Object
80
27
 
28
+ # Configure the application
29
+ run(&block) if block_given?
30
+
31
+ # Configure Readline for the shell, if available
81
32
  if Object.const_defined?(:Readline)
82
33
  @readline = true
83
34
  Readline.basic_word_break_characters = ""
@@ -86,45 +37,14 @@ module Zabby
86
37
 
87
38
  $last_res = nil
88
39
  else
40
+ # Without Readline the Zabby shell is not available.
89
41
  @readline = false
90
42
  end
91
43
  end
92
44
 
93
- def setup &block
94
- @config.setup &block
95
- end
96
-
97
- def set(key_value = nil)
98
- if key_value.nil?
99
- @config.list
100
- elsif [ String, Symbol ].include?(key_value.class)
101
- puts "#{key_value} = #{@config.send(key_value)}"
102
- elsif key_value.instance_of? Hash
103
- key = key_value.keys.first
104
- value = key_value[key]
105
- @config.send(key, value)
106
- end
107
- end
108
-
109
- def login
110
- @connection.login(@config)
111
- end
112
-
113
- def logout
114
- @connection.logout
115
- end
116
-
117
- def logged_in?
118
- @connection.logged_in?
119
- end
120
- alias_method :loggedin?, :logged_in?
121
-
122
- def version
123
- Zabby::VERSION
124
- end
125
-
126
- # @param command_file [String] Filename containing commands to execute.
127
- # @param block [Proc] A block containing commands to execute.
45
+ # Execute script file and/or instruction block
46
+ # @param [String] command_file Filename containing commands to execute.
47
+ # @param [Proc] block A block containing commands to execute.
128
48
  def run(command_file = nil, &block)
129
49
  unless command_file.nil?
130
50
  commands = File.read(command_file)
@@ -137,9 +57,12 @@ module Zabby
137
57
  def shell
138
58
  raise RuntimeError.new("Shell cannot run because 'readline' is missing.") if !@readline
139
59
 
140
- puts "Zabby Shell #{Zabby::VERSION}"
141
- puts
142
- puts "** This is a simple irb like Zabbix Shell. Multiline commands do not work for e.g. **"
60
+ puts <<HEADER
61
+ Zabby Shell #{Zabby::VERSION}
62
+
63
+ ** This is a simple irb like Zabbix Shell. Multiline commands do not work for e.g. **
64
+ Type "help" for online documentation.
65
+ HEADER
143
66
  loop do
144
67
  cmd = Readline.readline('zabby> ')
145
68
 
@@ -154,7 +77,7 @@ module Zabby
154
77
  private
155
78
 
156
79
  # Run a single command.
157
- # @param cmd [String] A command to execute in the object's context.
80
+ # @param [String] cmd A command to execute in the object's context.
158
81
  def execute(cmd)
159
82
  res = eval(cmd, @pure_binding)
160
83
  $last_res = res
@@ -167,9 +90,13 @@ module Zabby
167
90
  end
168
91
  end
169
92
 
93
+ # Print a single command's output on the screen using "inspect" if necessary.
94
+ # @param [Object] res Result object to display
170
95
  def print_result(res)
171
96
  if res.kind_of? String
172
97
  puts res
98
+ elsif res.nil?
99
+ # Do not print nil values
173
100
  else
174
101
  puts "=> #{res.inspect}"
175
102
  end
@@ -0,0 +1,102 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
4
+ # License:: Simplified BSD License
5
+
6
+ module Zabby
7
+ # Useful helper methods for the Zabbix Shell. Methods added to this module
8
+ # are available in the scripting language and commande line.
9
+ # The following instance variable should be available to helper methods:
10
+ # - @config: Zabby::Config instance
11
+ # - @connection: Zabby::Connection instance
12
+ module ShellHelpers
13
+ # Documentation for helpers.
14
+ # Each helper method definition must be preceded by a call to "desc" and a short
15
+ # online help for the method.
16
+ @helpers_doc = {}
17
+ @last_doc = nil
18
+
19
+ # Save the documentation for a method about to be defined.
20
+ # @param text [String] Documentation of the method following the call to "desc"
21
+ def self.desc(text)
22
+ @last_doc = text
23
+ end
24
+
25
+ # Push helper documentation for the method just defined in a hash.
26
+ # @param [Symbol] method Helper method to document
27
+ # @todo Display functions in alphabetical or arbitrary order.
28
+ def self.method_added(method)
29
+ if @last_doc.nil?
30
+ @helpers_doc[method.id2name] = "** UNDOCUMENTED FUNCTION **"
31
+ else
32
+ @helpers_doc[method.id2name] = @last_doc
33
+ @last_doc = nil
34
+ end
35
+ end
36
+
37
+ # Show the Shell helpers documentation
38
+ def self.show_helpers_doc
39
+ help = <<EOT
40
+ Available commands:
41
+ ==================
42
+
43
+ EOT
44
+ @helpers_doc.each do |name, text|
45
+ help += name + ":\n"
46
+ help += '-' * name.size + "\n"
47
+ help += text + "\n\n"
48
+ end
49
+ help
50
+ end
51
+
52
+ desc %q{Set or query Zabby parameters.
53
+ - "set" without argument displays all parameters.
54
+ - "set <param>" shows the value of <param>
55
+ - "set <param> => <value>" set <param> to <value>}
56
+ def set(key_value = nil)
57
+ if key_value.nil?
58
+ @config.list
59
+ elsif [ String, Symbol ].include?(key_value.class)
60
+ puts "#{key_value} = #{@config.send(key_value)}"
61
+ elsif key_value.instance_of? Hash
62
+ key = key_value.keys.first
63
+ value = key_value[key]
64
+ @config.send(key, value)
65
+ end
66
+ end
67
+
68
+ desc %q{Login to the Zabbix server.
69
+ The parameters 'server', 'user' and 'password' must be defined.}
70
+ def login
71
+ @connection.login(@config)
72
+ end
73
+
74
+ desc 'Logout from the Zabbix server'
75
+ def logout
76
+ @connection.logout
77
+ end
78
+
79
+ desc 'Return true if we are connected to the Zabbix server, false otherwise.'
80
+ def logged_in?
81
+ @connection.logged_in?
82
+ end
83
+
84
+ desc 'Alias for "logged_in?".'
85
+ alias_method :loggedin?, :logged_in?
86
+
87
+ desc 'Show Zabby version.'
88
+ def version
89
+ Zabby::VERSION
90
+ end
91
+
92
+ desc 'Return the list of available Zabbix Classes (object types).'
93
+ def zabbix_classes
94
+ Zabby::ZClass.zabbix_classes
95
+ end
96
+
97
+ desc 'Show this help text.'
98
+ def help
99
+ puts Zabby::ShellHelpers.show_helpers_doc
100
+ end
101
+ end
102
+ end
@@ -1,8 +1,8 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
- # Copyright:: Copyright (c) 2011 Farzad FARID
3
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
4
4
  # License:: Simplified BSD License
5
5
 
6
6
  module Zabby
7
- VERSION = "0.0.5"
7
+ VERSION = "0.1.0"
8
8
  end
@@ -0,0 +1,193 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
4
+ # License:: Simplified BSD License
5
+
6
+ module Zabby
7
+ # Create Zabbix classes as provided by the Zabbix API
8
+ module ZClass
9
+ # List of available Zabbix classes
10
+ @zabbix_classes = []
11
+
12
+ def self.included(base)
13
+ base.extend(ClassMethods)
14
+ # Keep a list of Zabbix classes
15
+ @zabbix_classes << base.name.gsub(/^.*::/, '')
16
+ end
17
+
18
+ # Return the list of Zabbix classes
19
+ # @return [Array] List of Zabbix classes
20
+ def self.zabbix_classes
21
+ @zabbix_classes
22
+ end
23
+
24
+ module ClassMethods
25
+ # List of valid Web Service methods for the current Zabbix Object
26
+ attr_reader :zmethods
27
+
28
+ # Name of the current class without the namespace
29
+ # @return [String]
30
+ # @example
31
+ # Zabby::Host.object_name => "host"
32
+ def object_name
33
+ @object_name ||= self.name.gsub(/^.*::/, '').downcase
34
+ end
35
+
36
+ # Add the list of Web Service methods to the current class.
37
+ # @param [Array] zmethods Method names
38
+ # @example
39
+ # class Host
40
+ # include ZClass
41
+ # add_zmethods :create, :delete, :exists, :get, :update
42
+ # end
43
+ def add_zmethods(*zmethods)
44
+ @zmethods = zmethods.map { |f| f.to_sym }
45
+ end
46
+
47
+ # Simulate methods on the object and call the Zabbix Web Service ("host.get", "item.create", etc.).
48
+ # See http://www.zabbix.com/documentation/1.8/api for the API documentation.
49
+ # @param [String] zmethod Name of the Web Service methods
50
+ # @param [Array] args Method arguments
51
+ # @param [Proc] block Unused
52
+ # @raise [NoMethodError] Raised on invalid method names.
53
+ def method_missing(zmethod, *args, &block)
54
+ if @zmethods.include? zmethod
55
+ Zabby::Runner.instance.connection.perform_request(object_name, zmethod, args.first)
56
+ else
57
+ super
58
+ end
59
+ end
60
+
61
+ # Human representation of the Zabbix Class
62
+ # @return [String] Class representation
63
+ # @example
64
+ # Host.inspect => "<Zabbix Object 'host', methods: create, delete, exists, get, update>"
65
+ def inspect
66
+ "<Zabbix Object '#{object_name}', methods: #{@zmethods.join(', ')}>"
67
+ end
68
+ end
69
+ end
70
+
71
+ # Create all Zabbix object types and theirs methods.
72
+
73
+ class Action
74
+ include ZClass
75
+ add_zmethods :create, :delete, :exists, :get, :update
76
+ end
77
+
78
+ class Alert
79
+ include ZClass
80
+ add_zmethods :create, :delete, :get
81
+ end
82
+
83
+ class APIInfo
84
+ include ZClass
85
+ add_zmethods :version
86
+ end
87
+
88
+ class Application
89
+ include ZClass
90
+ add_zmethods :create, :delete, :exists, :get, :massAdd, :update
91
+ end
92
+
93
+ class Event
94
+ include ZClass
95
+ add_zmethods :acknowledge, :create, :delete, :get
96
+ end
97
+
98
+ class Graph
99
+ include ZClass
100
+ add_zmethods :create, :delete, :exists, :get, :update
101
+ end
102
+
103
+ class Graphitem
104
+ include ZClass
105
+ add_zmethods :get
106
+ end
107
+
108
+ class History
109
+ include ZClass
110
+ add_zmethods :delete, :get
111
+ end
112
+
113
+ class Host
114
+ include ZClass
115
+ add_zmethods :create, :delete, :exists, :get, :update
116
+ end
117
+
118
+ class Hostgroup
119
+ include ZClass
120
+ add_zmethods :create, :delete, :exists, :get, :massAdd, :massRemove, :massUpdate, :update
121
+ end
122
+
123
+ class Image
124
+ include ZClass
125
+ add_zmethods :create, :delete, :exists, :get, :update
126
+ end
127
+
128
+ class Item
129
+ include ZClass
130
+ add_zmethods :create, :delete, :exists, :get, :update
131
+ end
132
+
133
+ class Maintenance
134
+ include ZClass
135
+ add_zmethods :create, :delete, :exists, :get, :update
136
+ end
137
+
138
+ class Map
139
+ include ZClass
140
+ add_zmethods :create, :delete, :exists, :get, :update
141
+ end
142
+
143
+ class Mediatype
144
+ include ZClass
145
+ add_zmethods :create, :delete, :get, :update
146
+ end
147
+
148
+ class Proxy
149
+ include ZClass
150
+ add_zmethods :get
151
+ end
152
+
153
+ class Screen
154
+ include ZClass
155
+ add_zmethods :create, :delete, :get, :update
156
+ end
157
+
158
+ class Script
159
+ include ZClass
160
+ add_zmethods :create, :delete, :execute, :get, :update
161
+ end
162
+
163
+ class Template
164
+ include ZClass
165
+ add_zmethods :create, :delete, :exists, :get, :massAdd, :massRemove, :massUpdate, :update
166
+ end
167
+
168
+ class Trigger
169
+ include ZClass
170
+ add_zmethods :addDependencies, :create, :delete, :deleteDependencies, :exists, :get, :update
171
+ end
172
+
173
+ class User
174
+ include ZClass
175
+ add_zmethods :addMedia, :authenticate, :create, :delete, :deleteMedia, :get, :login, :logout, :update, :updateMedia, :updateProfile
176
+ end
177
+
178
+ class Usergroup
179
+ include ZClass
180
+ add_zmethods :create, :delete, :exists, :get, :massAdd, :massRemove, :massUpdate, :update
181
+ end
182
+
183
+ class Usermacro
184
+ include ZClass
185
+ add_zmethods :createGlobal, :deleteGlobal, :deleteHostMacro, :get, :massAdd, :massRemove, :massUpdate, :updateGlobal
186
+ end
187
+
188
+ class Usermedia
189
+ include ZClass
190
+ add_zmethods :get
191
+ end
192
+
193
+ end
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
- # Copyright:: Copyright (c) 2011 Farzad FARID
3
+ # Copyright:: Copyright (c) 2011-2012 Farzad FARID
4
4
  # License:: Simplified BSD License
5
5
 
6
6
  $:.push File.expand_path("../lib", __FILE__)
@@ -30,4 +30,5 @@ service.}
30
30
  s.add_development_dependency "bundler", ">= 1.0.0"
31
31
  s.add_development_dependency "rspec", ">= 2.0.0"
32
32
  s.add_development_dependency "rake", ">= 0.8.7"
33
+ s.add_development_dependency "yard"
33
34
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zabby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 5
10
- version: 0.0.5
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Farzad FARID
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-05 00:00:00 Z
18
+ date: 2012-03-14 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: json
@@ -79,6 +79,20 @@ dependencies:
79
79
  version: 0.8.7
80
80
  type: :development
81
81
  version_requirements: *id004
82
+ - !ruby/object:Gem::Dependency
83
+ name: yard
84
+ prerelease: false
85
+ requirement: &id005 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ type: :development
95
+ version_requirements: *id005
82
96
  description: |-
83
97
  Zabby is a Zabby API and CLI. It provides a provisioning tool for
84
98
  creating, updating and querying Zabbix objects (hosts, items, triggers, etc.) through the web
@@ -109,8 +123,9 @@ files:
109
123
  - lib/zabby/connection.rb
110
124
  - lib/zabby/exceptions.rb
111
125
  - lib/zabby/runner.rb
126
+ - lib/zabby/shell_helpers.rb
112
127
  - lib/zabby/version.rb
113
- - lib/zabby/zobject.rb
128
+ - lib/zabby/zclass.rb
114
129
  - spec/spec_helper.rb
115
130
  - zabby.gemspec
116
131
  homepage: http://zabby.org/
@@ -1,31 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
- # Copyright:: Copyright (c) 2011 Farzad FARID
4
- # License:: Simplified BSD License
5
-
6
- module Zabby
7
- # Definition of the Zabbix Objects as provided by the Zabbix API
8
- class ZObject
9
- attr_reader :zname, :zmethods
10
-
11
- # Define the Zabbix object name and associated methods
12
- #
13
- # @param [String] zname Zabbix Object name
14
- # @param [Array] zmethods List of associated methods
15
- def initialize(zname, zmethods)
16
- @zname = zname
17
- @zmethods = zmethods.map { |f| f.to_sym }
18
- end
19
-
20
- # Simulate methods on the object.
21
- # For example: "host.get", "item.create"..
22
- # The instance variable @zmethods is the list of valid methods.
23
- def method_missing(zmethod, *args, &block)
24
- if @zmethods.include? zmethod
25
- Zabby::Runner.instance.connection.perform_request(@zname, zmethod, args.first)
26
- else
27
- super
28
- end
29
- end
30
- end
31
- end