icinga_api 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ac468fc80d13004bb9ec82f9617e6fde11b599c7
4
+ data.tar.gz: f6c892509cb27b488db7284523ce0607d4f3f445
5
+ SHA512:
6
+ metadata.gz: 969c5e36129e4b572b397fa8d1487c315a8b75e5bbb5544332de08451c2494512ae4ee083f60cf5c85caba8781d4188b2196853050dc54fc24e039776dd71961
7
+ data.tar.gz: c9d31d5e4f01d3e7764f1dd58a5061e7c6278a4e99ac3d59723ac38eb0a32d20412c0adf55cd69141e96a8af5c99d7116244f9c7850270d4a2b7ee52117c8bf0
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in icinga_api.gemspec
4
+ gemspec
5
+
6
+ gem 'ipaddress'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Sarah Diendorfer
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.
@@ -0,0 +1,82 @@
1
+ # IcingaApi
2
+
3
+ This is an still experimental gem to access the Icinga Web REST API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'icinga_api'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install icinga_api
20
+
21
+ ## Usage
22
+
23
+ ### create connection
24
+ ```ruby
25
+ require 'icinga_api'
26
+
27
+ icinga = IcingaApi.new(
28
+ url: "http://icinga-server/icinga-web",
29
+ authkey: "myauthkey"
30
+ )
31
+ ```
32
+
33
+ ### some sample host API calls
34
+ ```ruby
35
+ host = icinga.host("my-monitored-host")
36
+
37
+ # is the host up?
38
+ host.up?
39
+
40
+ # what is the state of the host?
41
+ host.current_state
42
+
43
+ # when was the last check of the host
44
+ host.last_check
45
+
46
+ # has the host problem been acknowledged?
47
+ host.problem_has_been_acknowledged
48
+
49
+ # get a list of services of the host
50
+ host.services
51
+
52
+ # get a specific service by name on a host
53
+ service = host.service("Time")
54
+
55
+ etc.
56
+ ```
57
+
58
+ ### some sample service API calls
59
+ ```ruby
60
+ # is the service ok?
61
+ service.ok?
62
+
63
+ # since when is the service in the current state?
64
+ service.last_state_change
65
+
66
+ # what is the display name of the service?
67
+ service.display_name
68
+
69
+ # when will the service be checked the next time?
70
+ service.next_check
71
+
72
+ etc.
73
+ ```
74
+
75
+
76
+ ## Contributing
77
+
78
+ 1. Fork it ( https://github.com/terracor/icinga_api/fork )
79
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
80
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
81
+ 4. Push to the branch (`git push origin my-new-feature`)
82
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'icinga_api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "icinga_api"
8
+ spec.version = IcingaApi::VERSION
9
+ spec.authors = ["Lothar Handl"]
10
+ spec.email = ["ranger@wizards.at"]
11
+ spec.summary = %q{A gem to access the Icinga Web API}
12
+ spec.description = %q{A gem to access the Icinga Web API}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
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_dependency "ipaddress"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ end
@@ -0,0 +1,26 @@
1
+ require 'pry'
2
+ require 'json'
3
+ require 'uri'
4
+ require 'net/http'
5
+ require 'time'
6
+ require 'ipaddress'
7
+
8
+ require "icinga_api/version"
9
+ require "icinga_api/request"
10
+ require "icinga_api/host"
11
+ require "icinga_api/service"
12
+
13
+ class IcingaApi
14
+ attr_reader :data
15
+
16
+ def initialize(options = {})
17
+ @data = options
18
+ @data[:url] += '/web/api/json'
19
+ end
20
+
21
+
22
+ def host(name)
23
+ Host.new(self, name)
24
+ end
25
+
26
+ end
@@ -0,0 +1,140 @@
1
+ class IcingaApi
2
+ class Host < Request
3
+ TARGET="host"
4
+ attr_reader :name, :host_filter
5
+
6
+ CHECKS = {
7
+ integer: %i(
8
+ HOST_ID
9
+ HOST_OBJECT_ID
10
+ HOST_INSTANCE_ID
11
+ HOST_PARENT_OBJECT_ID
12
+ HOST_CHILD_ID
13
+ HOST_CURRENT_CHECK_ATTEMPT
14
+ HOST_MAX_CHECK_ATTEMPTS
15
+ HOST_STATE_COUNT
16
+ ),
17
+ float: %i(
18
+ HOST_LATENCY
19
+ HOST_EXECUTION_TIME
20
+ ),
21
+ boolean: %i(
22
+ HOST_FLAP_DETECTION_ENABLED
23
+ HOST_ACTIVE_CHECKS_ENABLED
24
+ HOST_FLAP_DETECTION_ENABLED
25
+ HOST_FRESHNESS_CHECK_ENABLED
26
+ HOST_PASSIVE_CHECKS_ENABLED
27
+ HOST_EVENT_HANDLER_ENABLED
28
+ HOST_ACTIVE_CHECKS_ENABLED
29
+ HOST_NOTIFICATIONS_ENABLED
30
+ HOST_OBSESS_OVER_HOST
31
+ HOST_FAILURE_PREDICTION_ENABLED
32
+ HOST_IS_ACTIVE
33
+ HOST_HAS_BEEN_CHECKED
34
+ HOST_IS_FLAPPING
35
+ HOST_PROBLEM_HAS_BEEN_AKNOWLEDGED
36
+ HOST_IS_PENDING
37
+ HOST_SHOULD_BE_SCHEDULED
38
+ HOST_PROCESS_PERFORMANCE_DATA
39
+ ),
40
+ string: %i(
41
+ HOST_NAME
42
+ HOST_ALIAS
43
+ HOST_DISPLAY_NAME
44
+ HOST_NOTES
45
+ HOST_OUTPUT
46
+ HOST_LONG_OUTPUT
47
+ HOST_PARENT_NAME
48
+ HOST_CHILD_NAME
49
+ HOST_ICON_IMAGE
50
+ HOST_ICON_IMAGE_ALT
51
+ HOST_NOTES_URL
52
+ HOST_ACTION_URL
53
+ ),
54
+ time: %i(
55
+ HOST_LAST_CHECK
56
+ HOST_LAST_STATE_CHANGE
57
+ HOST_NEXT_CHECK
58
+ HOST_LAST_NOTIFICATION
59
+ HOST_STATUS_UPDATE_TIME
60
+ HOST_LAST_HARD_STATE_CHANGE
61
+ )
62
+ }
63
+
64
+ CHECKS.each do |check_type, arr|
65
+ request_name = "#{check_type.to_s}_request"
66
+ arr.each do |method_symbol|
67
+ method_name = method_symbol.to_s.gsub(/^\w+?_/, "").downcase
68
+ define_method(method_name) do
69
+ send(request_name, TARGET, @host_filter, method_symbol)
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+ def initialize(connection, name)
76
+ @connection = connection
77
+ @name = name
78
+ @host_filter = filter("HOST_NAME", "=", name)
79
+ end
80
+
81
+
82
+ def fetch(method)
83
+ string_request(TARGET, @host_filter, method)
84
+ end
85
+
86
+
87
+ def current_state
88
+ rc = request(TARGET, @host_filter, ["HOST_CURRENT_STATE"])
89
+ return :unknown unless rc[:success] == "true"
90
+ case rc[:result][0][:HOST_CURRENT_STATE].to_i
91
+ when 0
92
+ :up
93
+ when 1
94
+ :down
95
+ end
96
+ end
97
+
98
+
99
+ def up?
100
+ current_state == :up
101
+ end
102
+
103
+
104
+ def down?
105
+ current_state == :down
106
+ end
107
+
108
+
109
+ def unknown?
110
+ current_state == :unknown
111
+ end
112
+
113
+
114
+ def address
115
+ rc = request(TARGET, @host_filter, [:HOST_ADDRESS])
116
+ address = rc[:result][0][:HOST_ADDRESS]
117
+ begin
118
+ address = IPAddress(address)
119
+ rescue
120
+ address
121
+ end
122
+ end
123
+
124
+
125
+ def services
126
+ rc = request(Service::TARGET, @host_filter, [:SERVICE_NAME])
127
+ # TODO: langsam, und keine Ahnung, warum
128
+ rc[:result].map do |service_hash|
129
+ Service.new(@connection, self, service_hash[:SERVICE_NAME])
130
+ end
131
+ end
132
+
133
+
134
+ def service(name)
135
+ Service.new(@connection, self, name)
136
+ end
137
+
138
+ # TODO: implement further
139
+ end # of class Host
140
+ end
@@ -0,0 +1,66 @@
1
+ class IcingaApi
2
+ class Request
3
+ attr_accessor :connection
4
+
5
+ protected
6
+
7
+ def and_filters(a, b)
8
+ { type: "AND", field: [a, b] }
9
+ end
10
+
11
+
12
+ def or_filters(a, b)
13
+ { type: "OR", field: [a, b] }
14
+ end
15
+
16
+
17
+ def filter(field, operator, value)
18
+ { type: "atom", field: [ field ], method: [ operator ], value: [ value ] }
19
+ end
20
+
21
+
22
+ def request(target, filters, columns)
23
+ # prepare post data
24
+ data = Hash.new
25
+ data[:authkey] = @connection.data[:authkey]
26
+ data[:target] = target
27
+ filters = and_filters(filters, filters) # the hell knows why, but the api always wants an AND- or OR-construct on the top level
28
+ data[:filters_json] = filters.to_json if filters
29
+ columns.each_with_index do |col, i|
30
+ data["columns[#{i}]".to_sym] = col
31
+ end
32
+
33
+ # post data
34
+ uri = URI(@connection.data[:url])
35
+ res = Net::HTTP.post_form(uri, data)
36
+ raise "error on API query" unless res.code.to_i == 200
37
+ JSON.parse(res.body, { symbolize_names: true })
38
+ end
39
+
40
+
41
+ def string_request(target, filter, field)
42
+ rc = request(target, filter, [ field ])
43
+ rc[:result][0][field]
44
+ end
45
+
46
+
47
+ def integer_request(target, filter, field)
48
+ rc = string_request(target, filter, field).to_i
49
+ end
50
+
51
+
52
+ def float_request(target, filter, field)
53
+ rc = string_request(target, filter, field).to_f
54
+ end
55
+
56
+
57
+ def boolean_request(target, filter, field)
58
+ integer_request(target, filter, field) == 1
59
+ end
60
+
61
+
62
+ def time_request(target, filter, field)
63
+ Time.parse(string_request(target, filter, field))
64
+ end
65
+ end # of class Request
66
+ end
@@ -0,0 +1,126 @@
1
+ class IcingaApi
2
+ class Service < Request
3
+ TARGET = "service"
4
+ attr_reader :name, :service_filter
5
+
6
+ CHECKS = {
7
+ integer: %i(
8
+ SERVICE_ID
9
+ SERVICE_INSTANCE_ID
10
+ SERVICE_OBJECT_ID
11
+ SERVICE_CURRENT_CHECK_ATTEMPTS
12
+ SERVICE_MAX_CHECK_ATTEMPTS
13
+ SERVICE_STATE_COUNT
14
+ SERVICE_OBJECT_COUNT
15
+ ),
16
+ float: %i(
17
+ SERVICE_LATENCY
18
+ SERVICE_EXECUTION_TIME
19
+ ),
20
+ boolean: %i(
21
+ SERVICE_IS_ACTIVE
22
+ SERVICE_NOTIFICATIONS_ENABLED
23
+ SERVICE_FLAP_DETECTION_ENABLED
24
+ SERVICE_PASSIVE_CHECKS_ENABLED
25
+ SERVICE_EVENT_HANDLER_ENABLED
26
+ SERVICE_ACTIVE_CHECKS_ENABLED
27
+ SERVICE_RETAIN_STATUS_INFORMATION
28
+ SERVICE_RETAIN_NONSTATUS_INFORMATION
29
+ SERVICE_OBSESS_OVER_SERVICE
30
+ SERVICE_FAILURE_PREDICTION_ENABLED
31
+ SERVICE_PROCESS_PERFORMANCE_DATA
32
+ SERVICE_HAS_BEEN_CHECKED
33
+ SERVICE_IS_FLAPPING
34
+ SERVICE_PROBLEM_HAS_BEEN_ACKNOWLEDGED
35
+ SERVICE_SHOULD_BE_SCHEDULED
36
+ SERVICE_IS_PENDING
37
+ SERVICE_LAST_HARD_STATE
38
+ ),
39
+ string: %i(
40
+ SERVICE_NAME
41
+ SERVICE_DISPLAY_NAME
42
+ SERVICE_NOTES
43
+ SERVICE_OUTPUT
44
+ SERVICE_LONG_OUTPUT
45
+ SERVICE_ICON_IMAGE
46
+ SERVICE_ICON_IMAGE_ALT
47
+ SERVICE_NOTES_URL
48
+ SERVICE_ACTION_URL
49
+ ),
50
+ time: %i(
51
+ SERVICE_LAST_CHECK
52
+ SERVICE_LAST_STATE_CHANGE
53
+ SERVICE_NEXT_CHECK
54
+ SERVICE_LAST_HARD_STATE_CHANGE
55
+ SERVICE_LAST_NOTIFICATION
56
+ SERVICE_STATUS_UPDATE_TIME
57
+ )
58
+ }
59
+
60
+ CHECKS.each do |check_type, arr|
61
+ request_name = "#{check_type.to_s}_request"
62
+ arr.each do |method_symbol|
63
+ method_name = method_symbol.to_s.gsub(/^\w+?_/, "").downcase
64
+ define_method(method_name) do
65
+ send(request_name, TARGET, @service_filter, method_symbol)
66
+ end
67
+ end
68
+ end
69
+
70
+
71
+ def initialize(connection, host, name)
72
+ @connection = connection
73
+ @host = host
74
+ @name = name
75
+ @service_filter = and_filters(@host.host_filter, filter("SERVICE_NAME", "=", name))
76
+ end
77
+
78
+
79
+ def fetch(method)
80
+ string_request(TARGET, @service_filter, method)
81
+ end
82
+
83
+
84
+ def perfdata
85
+ rc = request(TARGET, @service_filter, [:SERVICE_PERFDATA])
86
+ # TODO: parsen
87
+ end
88
+
89
+
90
+ def current_state
91
+ rc = request(TARGET, @service_filter, ["SERVICE_CURRENT_STATE"])
92
+ case rc[:result][0][:SERVICE_CURRENT_STATE].to_i
93
+ when 0
94
+ :ok
95
+ when 1
96
+ :warning
97
+ when 2
98
+ :critical
99
+ when 4
100
+ :unknown
101
+ end
102
+ end
103
+
104
+
105
+ def ok?
106
+ current_state == :ok
107
+ end
108
+
109
+
110
+ def warning?
111
+ current_state == :warning
112
+ end
113
+
114
+
115
+ def critical?
116
+ current_state == :critical
117
+ end
118
+
119
+
120
+ def unknown?
121
+ current_state == :unknown
122
+ end
123
+
124
+ # TODO: implement further
125
+ end # of class Service
126
+ end
@@ -0,0 +1,3 @@
1
+ class IcingaApi
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: icinga_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Lothar Handl
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ipaddress
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ description: A gem to access the Icinga Web API
56
+ email:
57
+ - ranger@wizards.at
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - icinga_api.gemspec
68
+ - lib/icinga_api.rb
69
+ - lib/icinga_api/host.rb
70
+ - lib/icinga_api/request.rb
71
+ - lib/icinga_api/service.rb
72
+ - lib/icinga_api/version.rb
73
+ homepage: ''
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.4.1
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: A gem to access the Icinga Web API
97
+ test_files: []