icinga_api 0.0.1

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