zapix 0.0.7
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 +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/zapix/proxies/basic.rb +5 -0
- data/lib/zapix/proxies/hostgroups.rb +98 -0
- data/lib/zapix/proxies/hosts.rb +73 -0
- data/lib/zapix/proxies/templates.rb +28 -0
- data/lib/zapix/version.rb +3 -0
- data/lib/zapix/zabbix_classes/host.rb +47 -0
- data/lib/zapix/zabbix_classes/interface.rb +42 -0
- data/lib/zapix/zabbix_rpc_client.rb +56 -0
- data/lib/zapix.rb +29 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/zapix_specs.rb +188 -0
- data/zapix.gemspec +27 -0
- metadata +152 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2013 stoyan
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Zapix
|
|
2
|
+
|
|
3
|
+
TODO: Write a gem description
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
gem 'zapix'
|
|
10
|
+
|
|
11
|
+
And then execute:
|
|
12
|
+
|
|
13
|
+
$ bundle
|
|
14
|
+
|
|
15
|
+
Or install it yourself as:
|
|
16
|
+
|
|
17
|
+
$ gem install zapix
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
TODO: Write usage instructions here
|
|
22
|
+
|
|
23
|
+
## Contributing
|
|
24
|
+
|
|
25
|
+
1. Fork it
|
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require_relative 'basic'
|
|
2
|
+
|
|
3
|
+
class HostGroups < Basic
|
|
4
|
+
|
|
5
|
+
def mass_create(*names)
|
|
6
|
+
names.each do |group_name|
|
|
7
|
+
create(group_name)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create(name)
|
|
12
|
+
@client.hostgroup_create({'name' => name}) unless exists?(name)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create_or_update(name)
|
|
16
|
+
if(exists?(name))
|
|
17
|
+
id = get_id(name)
|
|
18
|
+
@client.hostgroup_update({'groupid' => id,'name' => name})
|
|
19
|
+
else
|
|
20
|
+
create(name)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def exists?(name)
|
|
25
|
+
@client.hostgroup_exists({'name' => name})
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def get_id(name)
|
|
29
|
+
if(exists?(name))
|
|
30
|
+
result = @client.hostgroup_get({'filter' => {'name' => [name]}})
|
|
31
|
+
result[0]['groupid']
|
|
32
|
+
else
|
|
33
|
+
raise NonExistingHostgroup, "Hostgroup #{name} does not exist !"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def mass_delete(*names)
|
|
38
|
+
names.each do |group_name|
|
|
39
|
+
delete(group_name)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def get_host_ids_of(hostgroup)
|
|
44
|
+
result = @client.hostgroup_get('filter' => {'name' => [hostgroup]}, 'selectHosts' => 'refer')
|
|
45
|
+
extract_host_ids(result)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def any_hosts?(hostgroup)
|
|
49
|
+
raise NonExistingHostgroup, "Hostgroup #{hostgroup} does not exist !" unless exists?(hostgroup)
|
|
50
|
+
result = @client.hostgroup_get('filter' => {'name' => [hostgroup]}, 'selectHosts' => 'count').first['hosts'].to_i
|
|
51
|
+
if(result >= 1)
|
|
52
|
+
true
|
|
53
|
+
else
|
|
54
|
+
false
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def delete(name)
|
|
59
|
+
if(exists?(name))
|
|
60
|
+
# host cannot exist without a hostgroup, so we need to delete
|
|
61
|
+
# the attached hosts also
|
|
62
|
+
if(any_hosts?(name))
|
|
63
|
+
# delete all hosts attached to a hostgroup
|
|
64
|
+
host_ids = get_host_ids_of(name)
|
|
65
|
+
host_ids.each do |id|
|
|
66
|
+
@client.host_delete(['hostid' => id])
|
|
67
|
+
end
|
|
68
|
+
# now it is ok to delete the group
|
|
69
|
+
@client.hostgroup_delete([get_id(name)])
|
|
70
|
+
else
|
|
71
|
+
@client.hostgroup_delete([get_id(name)])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
else
|
|
75
|
+
raise NonExistingHostgroup, "Hostgroup #{name} does not exist !"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def get_all
|
|
80
|
+
# the fucking API also returns the ids and that's
|
|
81
|
+
# why we need to extract the names
|
|
82
|
+
host_groups_with_ids = @client.hostgroup_get({'output' => ['name']})
|
|
83
|
+
extract_host_groups(host_groups_with_ids)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def extract_host_ids(query_result)
|
|
87
|
+
query_result.first['hosts'].map { |host| host['hostid'] }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def extract_host_groups(group_names_and_ids)
|
|
91
|
+
group_names_and_ids.map do |hostgroup|
|
|
92
|
+
hostgroup['name']
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
class NonExistingHostgroup < StandardError; end
|
|
97
|
+
|
|
98
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require_relative 'basic'
|
|
2
|
+
class Hosts < Basic
|
|
3
|
+
|
|
4
|
+
def get_id(name)
|
|
5
|
+
if(exists?(name))
|
|
6
|
+
@client.host_get({'filter' => {'host' => name}}).first['hostid']
|
|
7
|
+
else
|
|
8
|
+
raise NonExistingHost, "Host #{name} does not exist !"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def create(options={})
|
|
13
|
+
@client.host_create(options) unless exists?(options["host"])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create_or_update(options={})
|
|
17
|
+
raise EmptyHostname, 'Host name cannot be empty !' if options['host'].nil?
|
|
18
|
+
if exists?(options['host'])
|
|
19
|
+
id = get_id(options['host'])
|
|
20
|
+
options.merge!('hostid' => id)
|
|
21
|
+
@client.host_update(options)
|
|
22
|
+
else
|
|
23
|
+
create(options)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def unlink_and_clear_templates(options={})
|
|
28
|
+
template_ids = options['template_ids'].map { |id| {'templateid' => id}}
|
|
29
|
+
@client.host_update({'hostid' => options['host_id'], 'templates_clear' => template_ids})
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def update_templates(options={})
|
|
33
|
+
template_ids = options['template_ids'].map { |id| {'templateid' => id}}
|
|
34
|
+
@client.host_update({'hostid' => options['host_id'], 'templates' => template_ids})
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def update_macros(options={})
|
|
38
|
+
@client.host_update('hostid' => options['host_id'], 'macros' => options['macros'])
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def exists?(name)
|
|
42
|
+
@client.host_exists({'host' => name})
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def get_all
|
|
46
|
+
host_names_and_ids = @client.host_get({'output' => ['name']})
|
|
47
|
+
|
|
48
|
+
# the fucking api ALWAYS returns the ids and that's
|
|
49
|
+
# why we need to extract the names separately
|
|
50
|
+
|
|
51
|
+
extract_host_names(host_names_and_ids)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def delete(name)
|
|
55
|
+
if exists?(name)
|
|
56
|
+
@client.host_delete(['hostid' => get_id(name)])
|
|
57
|
+
else
|
|
58
|
+
raise NonExistingHost, "Host #{name} cannot be deleted because it does not exist !"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def extract_host_names(hosts_and_ids)
|
|
65
|
+
hosts_and_ids.map do |current_host|
|
|
66
|
+
current_host['name']
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class NonExistingHost < StandardError; end
|
|
71
|
+
class EmptyHostname < StandardError; end
|
|
72
|
+
|
|
73
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require_relative 'basic'
|
|
2
|
+
class Templates < Basic
|
|
3
|
+
|
|
4
|
+
def exists?(name)
|
|
5
|
+
@client.template_exists({'name' => name})
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def create(name)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def delete(name)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def get_id(name)
|
|
15
|
+
if(exists?(name))
|
|
16
|
+
@client.template_get({'filter' => {'name' => name}}).first['templateid']
|
|
17
|
+
else
|
|
18
|
+
raise NonExistingTemplate, "Template #{name} does not exist !"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def get_templates_for_host(id)
|
|
23
|
+
@client.template_get({'hostids' => [id]}).map { |result_set| result_set['templateid'] }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class NonExistingTemplate < StandardError; end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
class Host
|
|
2
|
+
|
|
3
|
+
attr_accessor :group_ids, :template_ids, :interfaces, :macros
|
|
4
|
+
|
|
5
|
+
def initialize()
|
|
6
|
+
@group_ids = Array.new
|
|
7
|
+
@template_ids = Array.new
|
|
8
|
+
@interfaces = Array.new
|
|
9
|
+
@macros = Array.new
|
|
10
|
+
@properties = Hash.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add_name(name)
|
|
14
|
+
@properties.merge!('host' => name)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def add_group_ids(*ids)
|
|
18
|
+
ids.each do |id|
|
|
19
|
+
group_ids << {'groupid' => id}
|
|
20
|
+
end
|
|
21
|
+
@properties.merge!('groups' => group_ids)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def add_interfaces(*ifaces)
|
|
25
|
+
interfaces.concat(ifaces)
|
|
26
|
+
@properties.merge!('interfaces' => interfaces)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def add_template_ids(*ids)
|
|
30
|
+
ids.each do |id|
|
|
31
|
+
template_ids << {'templateid' => id}
|
|
32
|
+
end
|
|
33
|
+
@properties.merge!('templates' => template_ids)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def add_macros(*host_macros)
|
|
37
|
+
macros.concat(host_macros)
|
|
38
|
+
@properties.merge!('macros' => host_macros)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def to_hash
|
|
42
|
+
@properties
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'active_record'
|
|
2
|
+
|
|
3
|
+
class Interface
|
|
4
|
+
include ActiveModel::Validations
|
|
5
|
+
|
|
6
|
+
attr_reader :type, :main, :useip, :ip, :dns, :port
|
|
7
|
+
validates_presence_of :type, :main, :useip, :ip, :dns, :port
|
|
8
|
+
|
|
9
|
+
# for more info see
|
|
10
|
+
# https://www.zabbix.com/documentation/2.0/manual/appendix/api/hostinterface/definitions#host_interface
|
|
11
|
+
# we assume ip and dns shall always be set
|
|
12
|
+
|
|
13
|
+
validates_inclusion_of :type, :in => 1..4
|
|
14
|
+
validates_inclusion_of :main, :in => 0..1
|
|
15
|
+
validates_inclusion_of :useip, :in => 0..1
|
|
16
|
+
|
|
17
|
+
def initialize(attributes)
|
|
18
|
+
@type = attributes['type'] ||= 1
|
|
19
|
+
@main = attributes['main'] ||= 1
|
|
20
|
+
@useip = attributes['useip'] ||= 1
|
|
21
|
+
@ip = attributes['ip'] = attributes['ip']
|
|
22
|
+
@dns = attributes['dns'] = attributes['dns']
|
|
23
|
+
@port = attributes['port'] = attributes['port'] ||= 10050
|
|
24
|
+
@result = {
|
|
25
|
+
'type' => type,
|
|
26
|
+
'main' => main,
|
|
27
|
+
'useip' => useip,
|
|
28
|
+
'ip' => ip,
|
|
29
|
+
'dns' => dns,
|
|
30
|
+
'port' => port
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def read_attribute_for_validation(key)
|
|
35
|
+
send(key)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_hash
|
|
39
|
+
@result
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
class ZabbixRPCClient
|
|
6
|
+
|
|
7
|
+
attr_reader :uri, :debug
|
|
8
|
+
|
|
9
|
+
def initialize(options)
|
|
10
|
+
@uri = URI.parse(options[:service_url])
|
|
11
|
+
@username = options[:username]
|
|
12
|
+
@password = options[:password]
|
|
13
|
+
@debug = options[:debug]
|
|
14
|
+
@auth_token = authenticate
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def method_missing(name, *args)
|
|
18
|
+
method_name = map_name(name)
|
|
19
|
+
|
|
20
|
+
post_body = {
|
|
21
|
+
'method' => method_name,
|
|
22
|
+
'params' => args.first,
|
|
23
|
+
'id' => id,
|
|
24
|
+
'jsonrpc' => '2.0',
|
|
25
|
+
'auth' => @auth_token
|
|
26
|
+
}.to_json
|
|
27
|
+
|
|
28
|
+
resp = JSON.parse( http_post_request(post_body) )
|
|
29
|
+
raise JSONRPCError, resp['error'] if resp['error']
|
|
30
|
+
puts "[DEBUG] Get answer: #{resp}" if debug
|
|
31
|
+
resp["result"]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def http_post_request(post_body)
|
|
35
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
36
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
|
37
|
+
request.content_type = 'application/json'
|
|
38
|
+
request.body = post_body
|
|
39
|
+
puts "[DEBUG] Send request: #{request.body}" if debug
|
|
40
|
+
http.request(request).body
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def authenticate
|
|
44
|
+
user_login({'user' => @username, 'password' => @password})
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def id
|
|
48
|
+
rand(100000)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def map_name(name)
|
|
52
|
+
name.to_s.sub('_', '.')
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class JSONRPCError < RuntimeError; end
|
|
56
|
+
end
|
data/lib/zapix.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'zapix/version'
|
|
2
|
+
require_relative 'zapix/zabbix_rpc_client'
|
|
3
|
+
|
|
4
|
+
class ZabbixAPI
|
|
5
|
+
attr :client
|
|
6
|
+
|
|
7
|
+
def self.connect(options = {})
|
|
8
|
+
new(options)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def initialize(options = {})
|
|
12
|
+
@client = ZabbixRPCClient.new(options)
|
|
13
|
+
Dir["#{File.dirname(__FILE__)}/zapix/zabbix_classes/*.rb"].each { |f| load(f) }
|
|
14
|
+
Dir["#{File.dirname(__FILE__)}/zapix/proxies/*.rb"].each { |f| load(f) }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def hostgroups
|
|
18
|
+
@hostgroups ||= HostGroups.new(@client)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def hosts
|
|
22
|
+
@hosts ||= Hosts.new(@client)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def templates
|
|
26
|
+
@templates ||= Templates.new(@client)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
|
4
|
+
# loaded once.
|
|
5
|
+
#
|
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
|
7
|
+
require 'zapix'
|
|
8
|
+
RSpec.configure do |config|
|
|
9
|
+
|
|
10
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
|
11
|
+
config.run_all_when_everything_filtered = true
|
|
12
|
+
config.filter_run :focus
|
|
13
|
+
|
|
14
|
+
# Run specs in random order to surface order dependencies. If you find an
|
|
15
|
+
# order dependency and want to debug it, you can fix the order by providing
|
|
16
|
+
# the seed, which is printed after each run.
|
|
17
|
+
# --seed 1234
|
|
18
|
+
config.order = 'random'
|
|
19
|
+
end
|
data/spec/zapix_specs.rb
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
require_relative 'spec_helper'
|
|
2
|
+
|
|
3
|
+
zrc = ZabbixAPI.connect(
|
|
4
|
+
:service_url => ENV['ZABBIX_API_URL'],
|
|
5
|
+
:username => ENV['ZABBIX_API_LOGIN'],
|
|
6
|
+
:password => ENV['ZABBIX_API_PASSWORD'],
|
|
7
|
+
:debug => true
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
hostgroup = 'hostgroup'
|
|
11
|
+
another_hostgroup = 'anotherhostgroup'
|
|
12
|
+
hostgroup_with_hosts = 'withhosts'
|
|
13
|
+
template_1 = 'Template OS Linux'
|
|
14
|
+
template_2 = 'Template App MySQL'
|
|
15
|
+
application = 'application'
|
|
16
|
+
host = 'hostname'
|
|
17
|
+
|
|
18
|
+
describe ZabbixAPI do
|
|
19
|
+
|
|
20
|
+
context 'hostgroup' do
|
|
21
|
+
before(:all) do
|
|
22
|
+
zrc.hostgroups.create(hostgroup)
|
|
23
|
+
zrc.hostgroups.create(another_hostgroup)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
after(:all) do
|
|
27
|
+
zrc.hostgroups.delete(hostgroup)
|
|
28
|
+
zrc.hostgroups.delete(another_hostgroup)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'creates or updates a hostgroup' do
|
|
32
|
+
zrc.hostgroups.create_or_update(hostgroup)
|
|
33
|
+
result = zrc.hostgroups.create_or_update(hostgroup)
|
|
34
|
+
result.should include('groupids')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'returns false if hostgroup does not exist' do
|
|
38
|
+
result = zrc.hostgroups.exists?('nonexisting')
|
|
39
|
+
result.should be_false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'succeeds if a hostgroup exist' do
|
|
43
|
+
result = zrc.hostgroups.exists?(hostgroup)
|
|
44
|
+
result.should be_true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'returns hostgroup id' do
|
|
48
|
+
result = zrc.hostgroups.get_id(hostgroup)
|
|
49
|
+
(result.to_i).should >= 0
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'throws exception if hostgroup id does not exist' do
|
|
53
|
+
expect { zrc.hostgroups.get_id('nonexisting') }.to raise_error(HostGroups::NonExistingHostgroup)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'throws exception if someone checks for attached hosts of nonexisting group' do
|
|
57
|
+
expect { zrc.hostgroups.any_hosts?('nonexisting') }.to raise_error(HostGroups::NonExistingHostgroup)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'returns false if a hostgroup has no attached hosts' do
|
|
61
|
+
zrc.hostgroups.any_hosts?(hostgroup).should be_false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'returns all hostgroups' do
|
|
65
|
+
(zrc.hostgroups.get_all).should include(hostgroup, another_hostgroup)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context 'complex hostgroup consisting hosts' do
|
|
70
|
+
before(:each) do
|
|
71
|
+
zrc.hostgroups.create(hostgroup_with_hosts)
|
|
72
|
+
hostgroup_id = zrc.hostgroups.get_id(hostgroup_with_hosts)
|
|
73
|
+
example_host = Host.new
|
|
74
|
+
example_host.add_name(host)
|
|
75
|
+
example_host.add_interfaces(create_interface)
|
|
76
|
+
example_host.add_group_ids(hostgroup_id)
|
|
77
|
+
example_host.add_template_ids(zrc.templates.get_id(template_1), zrc.templates.get_id(template_2))
|
|
78
|
+
example_host.add_macros({'macro' => '{$TESTMACRO}', 'value' => 'test123'})
|
|
79
|
+
zrc.hosts.create_or_update(example_host.to_hash)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'deletes a hostgroup with attached hosts' do
|
|
83
|
+
zrc.hosts.exists?(host).should be_true
|
|
84
|
+
zrc.hostgroups.delete(hostgroup_with_hosts)
|
|
85
|
+
zrc.hostgroups.exists?(hostgroup_with_hosts).should be_false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'complex hostgroup should be easy to delete' do
|
|
91
|
+
before(:each) do
|
|
92
|
+
zrc.hostgroups.create(hostgroup_with_hosts)
|
|
93
|
+
hostgroup_id = zrc.hostgroups.get_id(hostgroup_with_hosts)
|
|
94
|
+
example_host = Host.new
|
|
95
|
+
example_host.add_name(host)
|
|
96
|
+
example_host.add_interfaces(create_interface)
|
|
97
|
+
example_host.add_macros({'macro' => '{$TESTMACRO}', 'value' => 'test123'})
|
|
98
|
+
example_host.add_group_ids(hostgroup_id)
|
|
99
|
+
example_host.add_template_ids(zrc.templates.get_id(template_1), zrc.templates.get_id(template_2))
|
|
100
|
+
zrc.hosts.create_or_update(example_host.to_hash)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
after(:each) do
|
|
104
|
+
zrc.hostgroups.delete(hostgroup_with_hosts)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'returns true if a hostgroup has attached hosts' do
|
|
108
|
+
zrc.hostgroups.any_hosts?(hostgroup_with_hosts).should be_true
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'returns all the host ids of a hosts belonging to a hostgroup' do
|
|
112
|
+
host_id = zrc.hosts.get_id(host)
|
|
113
|
+
zrc.hostgroups.get_host_ids_of(hostgroup_with_hosts).should include(host_id)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'gets the right template id for host' do
|
|
117
|
+
result = zrc.templates.get_templates_for_host(zrc.hosts.get_id(host))
|
|
118
|
+
result.should include(zrc.templates.get_id(template_1))
|
|
119
|
+
result.should include(zrc.templates.get_id(template_2))
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'unlinks all templates for host' do
|
|
123
|
+
host_id = zrc.hosts.get_id(host)
|
|
124
|
+
options = {}
|
|
125
|
+
options['template_ids'] = zrc.templates.get_templates_for_host(host_id)
|
|
126
|
+
options['host_id'] = host_id
|
|
127
|
+
result = zrc.hosts.unlink_and_clear_templates(options)
|
|
128
|
+
result.should_not include(zrc.templates.get_id(template_1))
|
|
129
|
+
result.should_not include(zrc.templates.get_id(template_2))
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'throws an exception if updating a host without specifying the hostname' do
|
|
133
|
+
example_host = Host.new
|
|
134
|
+
example_host.add_interfaces(create_interface)
|
|
135
|
+
expect { zrc.hosts.create_or_update(example_host.to_hash) }.to raise_error(Hosts::EmptyHostname)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "updates host's interface after unlinking all belonging templates" do
|
|
139
|
+
# unlinking all items
|
|
140
|
+
host_id = zrc.hosts.get_id(host)
|
|
141
|
+
options = {}
|
|
142
|
+
zrc.templates.get_templates_for_host(host_id)
|
|
143
|
+
options['template_ids'] = zrc.templates.get_templates_for_host(host_id)
|
|
144
|
+
options['host_id'] = host_id
|
|
145
|
+
result = zrc.hosts.unlink_and_clear_templates(options)
|
|
146
|
+
#result = zrc.hosts.update_templates(options)
|
|
147
|
+
# now it should be safe to update the interface of the host
|
|
148
|
+
example_host = Host.new
|
|
149
|
+
example_host.add_interfaces(create_interface)
|
|
150
|
+
example_host.add_name(host)
|
|
151
|
+
zrc.hosts.create_or_update(example_host.to_hash)
|
|
152
|
+
# check
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "updates host's templates" do
|
|
156
|
+
host_id = zrc.hosts.get_id(host)
|
|
157
|
+
options = {}
|
|
158
|
+
options['host_id'] = host_id
|
|
159
|
+
template_id = zrc.templates.get_id('Template App Agentless')
|
|
160
|
+
options['template_ids'] = [template_id]
|
|
161
|
+
zrc.hosts.update_templates(options)
|
|
162
|
+
zrc.templates.get_templates_for_host(host_id).should include(template_id)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "updates host's macro" do
|
|
166
|
+
host_id = zrc.hosts.get_id(host)
|
|
167
|
+
options = {}
|
|
168
|
+
options['host_id'] = host_id
|
|
169
|
+
options['macros'] = [{'macro' => '{$TESTMACRO}', 'value' => 'this is only a test macro'}]
|
|
170
|
+
zrc.hosts.update_macros(options)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def create_interface
|
|
175
|
+
Interface.new(
|
|
176
|
+
'ip' => "127.0.0.#{random_int}",
|
|
177
|
+
'dns' => "#{random_string}.our-cloud.de").to_hash
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def random_string
|
|
181
|
+
rand(36**7...36**8).to_s(36)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def random_int
|
|
185
|
+
rand(64)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
end
|
data/zapix.gemspec
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'zapix/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "zapix"
|
|
8
|
+
spec.version = Zapix::VERSION
|
|
9
|
+
spec.authors = ["stoyan"]
|
|
10
|
+
spec.email = ["stoyanoff.s@gmail.com"]
|
|
11
|
+
spec.description = %q{Communication with the Zabbix API made easy}
|
|
12
|
+
spec.summary = %q{A cool gem}
|
|
13
|
+
spec.homepage = "https://github.com/mrsn/zapix"
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
|
22
|
+
spec.add_development_dependency "rake"
|
|
23
|
+
spec.add_development_dependency "json"
|
|
24
|
+
spec.add_development_dependency "rspec"
|
|
25
|
+
spec.add_development_dependency "activerecord"
|
|
26
|
+
|
|
27
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: zapix
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.7
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- stoyan
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-06-26 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: bundler
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ~>
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '1.3'
|
|
22
|
+
type: :development
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ~>
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '1.3'
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
name: rake
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
33
|
+
none: false
|
|
34
|
+
requirements:
|
|
35
|
+
- - ! '>='
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
type: :development
|
|
39
|
+
prerelease: false
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ! '>='
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: json
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
none: false
|
|
50
|
+
requirements:
|
|
51
|
+
- - ! '>='
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
type: :development
|
|
55
|
+
prerelease: false
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ! '>='
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
- !ruby/object:Gem::Dependency
|
|
63
|
+
name: rspec
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
65
|
+
none: false
|
|
66
|
+
requirements:
|
|
67
|
+
- - ! '>='
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '0'
|
|
70
|
+
type: :development
|
|
71
|
+
prerelease: false
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ! '>='
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
- !ruby/object:Gem::Dependency
|
|
79
|
+
name: activerecord
|
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ! '>='
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: '0'
|
|
86
|
+
type: :development
|
|
87
|
+
prerelease: false
|
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
+
none: false
|
|
90
|
+
requirements:
|
|
91
|
+
- - ! '>='
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: '0'
|
|
94
|
+
description: Communication with the Zabbix API made easy
|
|
95
|
+
email:
|
|
96
|
+
- stoyanoff.s@gmail.com
|
|
97
|
+
executables: []
|
|
98
|
+
extensions: []
|
|
99
|
+
extra_rdoc_files: []
|
|
100
|
+
files:
|
|
101
|
+
- .gitignore
|
|
102
|
+
- .rspec
|
|
103
|
+
- Gemfile
|
|
104
|
+
- LICENSE.txt
|
|
105
|
+
- README.md
|
|
106
|
+
- Rakefile
|
|
107
|
+
- lib/zapix.rb
|
|
108
|
+
- lib/zapix/proxies/basic.rb
|
|
109
|
+
- lib/zapix/proxies/hostgroups.rb
|
|
110
|
+
- lib/zapix/proxies/hosts.rb
|
|
111
|
+
- lib/zapix/proxies/templates.rb
|
|
112
|
+
- lib/zapix/version.rb
|
|
113
|
+
- lib/zapix/zabbix_classes/host.rb
|
|
114
|
+
- lib/zapix/zabbix_classes/interface.rb
|
|
115
|
+
- lib/zapix/zabbix_rpc_client.rb
|
|
116
|
+
- spec/spec_helper.rb
|
|
117
|
+
- spec/zapix_specs.rb
|
|
118
|
+
- zapix.gemspec
|
|
119
|
+
homepage: https://github.com/mrsn/zapix
|
|
120
|
+
licenses:
|
|
121
|
+
- MIT
|
|
122
|
+
post_install_message:
|
|
123
|
+
rdoc_options: []
|
|
124
|
+
require_paths:
|
|
125
|
+
- lib
|
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
|
+
none: false
|
|
128
|
+
requirements:
|
|
129
|
+
- - ! '>='
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0'
|
|
132
|
+
segments:
|
|
133
|
+
- 0
|
|
134
|
+
hash: 1937690048835696292
|
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
|
+
none: false
|
|
137
|
+
requirements:
|
|
138
|
+
- - ! '>='
|
|
139
|
+
- !ruby/object:Gem::Version
|
|
140
|
+
version: '0'
|
|
141
|
+
segments:
|
|
142
|
+
- 0
|
|
143
|
+
hash: 1937690048835696292
|
|
144
|
+
requirements: []
|
|
145
|
+
rubyforge_project:
|
|
146
|
+
rubygems_version: 1.8.24
|
|
147
|
+
signing_key:
|
|
148
|
+
specification_version: 3
|
|
149
|
+
summary: A cool gem
|
|
150
|
+
test_files:
|
|
151
|
+
- spec/spec_helper.rb
|
|
152
|
+
- spec/zapix_specs.rb
|