├── .gitignore
├── .rspec
├── .rubocop.yml
├── .travis.yml
├── AUTHORS
├── CONTRIBUTING.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── config.reek
├── doc
├── downtimes.md
├── examples
├── hostgroups.md
├── hosts.md
├── notifications.md
├── servicegroups.md
├── services.md
├── statistics.md
├── usergroups.md
└── users.md
├── examples
├── _blank.rb
├── cert-manager.sh
├── config.rb
├── downtimes.rb
├── hostgroups.rb
├── hosts.rb
├── informations.rb
├── notifications.rb
├── servicegroups.rb
├── services.rb
├── statistics.rb
├── test.rb
├── usergroups.rb
└── users.rb
├── icinga2.gemspec
├── lib
├── icinga2.rb
├── icinga2
│ ├── actions.rb
│ ├── client.rb
│ ├── configuration_management.rb
│ ├── converts.rb
│ ├── downtimes.rb
│ ├── hostgroups.rb
│ ├── hosts.rb
│ ├── network.rb
│ ├── notifications.rb
│ ├── servicegroups.rb
│ ├── services.rb
│ ├── statistics.rb
│ ├── tools.rb
│ ├── usergroups.rb
│ ├── users.rb
│ ├── validator.rb
│ └── version.rb
├── logging.rb
└── monkey_patches.rb
└── spec
├── icinga2_spec.rb
└── spec_helper.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | *.rbc
3 | .bundle
4 | .config
5 | .yardoc
6 | Gemfile.lock
7 | InstalledFiles
8 | _yardoc
9 | coverage
10 | doc/
11 | lib/bundler/man
12 | pkg
13 | rdoc
14 | spec/reports
15 | test/tmp
16 | test/version_tmp
17 | tmp
18 |
19 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 |
3 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | TargetRubyVersion: 2.0
3 |
4 | AllCops:
5 | Exclude:
6 | - examples/*
7 | - spec/*
8 |
9 | # Disables "Use nested module/class definitions instead of compact style" warning
10 | ClassAndModuleChildren:
11 | Enabled: false
12 |
13 | # Increases "Class definition is too long" warning from 100 to 200
14 | Metrics/ClassLength:
15 | Max: 200
16 |
17 | # Increases "Method has too many lines" warning from 10 to 75
18 | Metrics/MethodLength:
19 | Max: 75
20 |
21 | # Increases "Module has too many lines" warning from 100 to 300
22 | Metrics/ModuleLength:
23 | Max: 300
24 |
25 | # Increases "Assignment Branch Condition size" warning from 15 to 80
26 | Metrics/AbcSize:
27 | Max: 80
28 |
29 | # Increases "Block has too many lines" warning from 25 to 190
30 | Metrics/BlockLength:
31 | Max: 190
32 |
33 | # Disables "Missing top-level class documentation comment" warning
34 | Documentation:
35 | Enabled: false
36 |
37 | # Increases "Line is too long" warning from 80 tp 200
38 | Metrics/LineLength:
39 | Max: 200
40 | Enabled: true
41 |
42 | CyclomaticComplexity:
43 | Enabled: false
44 |
45 | PerceivedComplexity:
46 | Enabled: false
47 |
48 | Style/Encoding:
49 | Enabled: false
50 |
51 | Style/RaiseArgs:
52 | EnforcedStyle: compact
53 |
54 | Layout:
55 | Enabled: False
56 |
57 | RescueWithoutErrorClass:
58 | Enabled: False
59 |
60 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # .travis.yml
2 | language: ruby
3 |
4 | sudo: required
5 | bundler_args: --retry=3 --jobs=3
6 |
7 | rvm:
8 | - 2.0
9 | - 2.1
10 | - 2.2
11 | - 2.3
12 | - 2.4
13 | - 2.5
14 |
15 | services:
16 | - docker
17 |
18 | before_install:
19 | - gem install bundler
20 | - gem update bundler
21 | - docker pull bodsch/docker-icinga2:2.8.1-master-r3
22 | - |
23 | docker run \
24 | --rm \
25 | --detach \
26 | --publish=5665:5665 \
27 | --env ICINGA_MASTER=icinga2 \
28 | --env ICINGA_CLUSTER=true \
29 | --env ICINGA_API_USERS=root:icinga \
30 | --env DEMO_DATA=true \
31 | --hostname=icinga2 \
32 | bodsch/docker-icinga2:2.8.1-master-r3
33 | - sleep 10s
34 | - |
35 | docker run \
36 | --rm \
37 | --detach \
38 | --env ICINGA2_MASTER=icinga2 \
39 | --env ICINGA2_PARENT=icinga2 \
40 | --env CERT_SERVICE_BA_USER=admin \
41 | --env CERT_SERVICE_BA_PASSWORD=admin \
42 | --env CERT_SERVICE_API_USER=root \
43 | --env CERT_SERVICE_API_PASSWORD=icinga \
44 | --env CERT_SERVICE_SERVER=icinga2 \
45 | --env CERT_SERVICE_PORT=8080 \
46 | --env CERT_SERVICE_PATH=/ \
47 | --hostname=icinga2-satellite \
48 | bodsch/docker-icinga2:2.8.1-satellite-r3
49 | - docker ps
50 | - sleep 25s
51 |
52 | script: bundle exec rspec spec
53 |
54 | fast_finish: true
55 |
56 | gemfile:
57 | - Gemfile
58 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | # Authors ordered by first contribution.
2 |
3 | Bodo Schulz - https://github.com/bodsch (bodo@boone-schulz.de)
4 | Andrei Skopenko - https://github.com/scopenco (andrei@skopenko.net)
5 | Shuliyey - https://github.com/Shuliyey ()
6 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing
2 | ============
3 | If you want to contribute to a project and make it better, your help is very welcome. Contributing is also a great way to learn more about social coding on Github, new technologies and and their ecosystems and how to make constructive, helpful bug reports, feature requests and the noblest of all contributions: a good, clean pull request.
4 |
5 | ### How to make a clean pull request
6 |
7 | Look for a project's contribution instructions. If there are any, follow them.
8 |
9 | - Create a personal fork of the project on Github.
10 | - Clone the fork on your local machine. Your remote repo on Github is called `origin`.
11 | - Add the original repository as a remote called `upstream`.
12 | - If you created your fork a while ago be sure to pull upstream changes into your local repository.
13 | - Create a new branch to work on! Branch from `develop` if it exists, else from `master`.
14 | - Implement/fix your feature, comment your code.
15 | - Follow the code style of the project, including indentation.
16 | - If the project has tests run them!
17 | - Write or adapt tests as needed.
18 | - Add or change the documentation as needed.
19 | - Squash your commits into a single commit with git's [interactive rebase](https://help.github.com/articles/interactive-rebase). Create a new branch if necessary.
20 | - Push your branch to your fork on Github, the remote `origin`.
21 | - From your fork open a pull request in the correct branch. Target the project's `develop` branch if there is one, else go for `master`!
22 | - If the maintainer requests further changes just push them to your branch. The PR will be updated automatically.
23 | - Once the pull request is approved and merged you can pull the changes from `upstream` to your local repo and delete
24 | your extra branch(es).
25 |
26 | And last but not least: Always write your commit messages in the present tense. Your commit message should describe what the commit, when applied, does to the code – not what you did to the code.
27 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Specify your gem's dependencies in icinga2.gemspec
4 | group :tools do
5 | gem 'rake'
6 | gem 'rake-notes'
7 | gem 'rspec'
8 | gem 'rspec_junit_formatter'
9 | gem 'rubocop'
10 | gem 'rubocop-checkstyle_formatter'
11 | gem 'rubycritic'
12 | end
13 |
14 | gemspec
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ruby-icinga2
2 |
3 | An enhanced ruby gem to communicate with Icinga2 API
4 |
5 | [](https://badge.fury.io/rb/icinga2)
6 |
7 | [][travis]
8 | [][gem-downloads]
9 | [][gem-downloads]
10 | [][gemnasium]
11 |
12 |
13 | [travis]: https://travis-ci.org/bodsch/ruby-icinga2
14 | [gem-downloads]: http://ruby-gem-downloads-badge.herokuapp.com/icinga2
15 | [gemnasium]: https://gemnasium.com/github.com/bodsch/ruby-icinga2
16 |
17 | ## Requirements
18 |
19 | * ruby version => 2.0
20 | * rest-client ~> 2.0
21 | * json ~> 2.1
22 | * openssl ~> 2.0 (only with ruby >= 2.3)
23 | * ruby_dig (only with ruby < 2.3)
24 |
25 | ## Install
26 |
27 | gem install icinga2
28 |
29 | ## Usage
30 |
31 | create an instance
32 |
33 | require 'icinga2'
34 |
35 | config = {
36 | icinga: {
37 | host: icinga_host,
38 | api: {
39 | port: icinga_api_port,
40 | username: icinga_api_user,
41 | password: icinga_api_pass
42 | }
43 | }
44 | }
45 |
46 | @icinga = Icinga2::Client.new( config )
47 |
48 | ### Use the examples
49 |
50 | You can use the [Icinga Vagrant-Box](https://github.com/Icinga/icinga-vagrant) from the Icinga Team or
51 | my own [Docker Container](https://hub.docker.com/r/bodsch/docker-icinga2/) as Datasource.
52 |
53 | **Remember** Change the exported Environment Variables to your choosed Datasource!
54 |
55 | you can find many examples under the directory `examples`:
56 |
57 | $ export ICINGA_HOST=localhost ; export ICINGA_API_USER=root ; export ICINGA_API_PASSWORD=icinga
58 | $ ruby examples/informations.rb
59 | $ ruby examples/statistics.rb
60 | $ ruby examples/users.rb
61 |
62 | and so on.
63 |
64 | ### Test via CLI
65 |
66 | $ irb
67 | irb(main):001:0> require 'icinga2'
68 | => true
69 | irb(main):002:0> config = { icinga: { host: 'localhost', api: { username: 'root', password: 'icinga' } } }
70 | => {:icinga=>{:host=>"localhost", :api=>{:username=>"root", :password=>"icinga"}}}
71 | irb(main):003:0> i = Icinga2::Client.new( config )
72 | irb(main):004:0> i.available?
73 | => true
74 | irb(main):005:0>
75 |
76 | ## Create a own gem file
77 |
78 | $ gem build icinga2.gemspec
79 | Successfully built RubyGem
80 | Name: icinga2
81 | Version: 0.9.2.7
82 | File: icinga2-0.9.2.7.gem
83 |
84 | ## Install local gem
85 |
86 | $ gem install icinga2
87 | Successfully installed icinga2-0.9.2.7
88 | 1 gem installed
89 |
90 |
91 | ## Status
92 |
93 | supports the following API Calls:
94 |
95 | - [Users](doc/users.md)
96 | * [add user](doc/users.md#add-user)
97 | * [delete user](doc/users.md#delete-dser)
98 | * [list users](doc/users.md#list-users)
99 | * [check if user exists](doc/users.md#user-exists)
100 |
101 | - [Usergroups](doc/usergroups.md)
102 | * [add usergroup](doc/usergroups.md#add-usergroup)
103 | * [delete usergroup](doc/usergroups.md#delete-usergroup)
104 | * [list usergroups](doc/usergroups.md#list-usergroups)
105 | * [check if usergroup exists](doc/usergroups.md#usergroup-exists)
106 |
107 | - [Hosts](doc/hosts.md)
108 | * [add host](doc/hosts.md#add-host)
109 | * [delete host](doc/hosts.md#delete-host)
110 | * [modify host](doc/hosts.md#modify-host)
111 | * [list hosts](doc/hosts.md#list-hosts)
112 | * [check if host exists](doc/hosts.md#host-exists)
113 | * [list host objects](doc/hosts.md#list-host-objects)
114 | * [count of hosts with problems](doc/hosts.md#count-hosts-with-problems)
115 | * [list of hosts with problems](doc/hosts.md#list-hosts-with-problems)
116 | * [count of all hosts](doc/hosts.md#count-all-hosts)
117 | * [count hosts with problems](doc/hosts.md#count-host-problems)
118 | * calculate host severity (protected)
119 |
120 | - [Hostgroups](doc/hostgroups.md)
121 | * [add hostgroup](doc/hostgroups.md#add-usergroup)
122 | * [delete hostgroup](doc/hostgroups.md#delete-usergroup)
123 | * [list hostgroups](doc/hostgroups.md#list-usergroups)
124 | * [check if hostgroup exists](doc/hostgroups.md#usergroup-exists)
125 |
126 | - [Services](doc/services.md)
127 | * [add service](doc/services.md#add-service)
128 | * [delete service](doc/services.md#delete-service)
129 | * [list unhandled services](doc/services.md#unhandled-services)
130 | * [list services](doc/services.md#list-services)
131 | * [check if service exists](doc/services.md#service-exists)
132 | * [list service objects](doc/services.md#list-service-objects)
133 | * [count services with problems](doc/services.md#count-services-with-problems)
134 | * [list of services with problems](doc/services.md#list-services-with-problems)
135 | * [count of all services](doc/services.md#count-all-services)
136 | * [count all services with handled problems](doc/services.md#count-all-services-handled)
137 | * calculate service severity (protected)
138 |
139 | - [Servicegroups](doc/servicegroups.md)
140 | * [add servicegroup](doc/servicegroups.md#add-servicegroup)
141 | * [delete servicegroup](doc/servicegroups.md#delete-servicegroup)
142 | * [list servicegroups](doc/servicegroups.md#list-servicegroup)
143 | * [check if servicegroup exists](doc/servicegroups.md#servicegroup-exists)
144 |
145 | - [Downtimes](doc/downtimes.md)
146 | * [add downtime](doc/downtimes.md#add-downtime)
147 | * [remove downtime](doc/downtimes.md#remove-downtime)
148 | * [list downtimes](doc/downtimes.md#list-downtimes)
149 |
150 | - [Notifications](doc/notifications.md)
151 | * [enable host notifications](doc/notifications.md#enable-host-notification)
152 | * [disable host notifications](doc/notifications.md#disable-host-notification)
153 | * [enable service notifications](doc/notifications.md#enable-service-notification)
154 | * [disable service notifications](doc/notifications.md#disable-service-notification)
155 | * [enable hostgroup notifications](doc/notifications.md#enable-hostgroup-notification)
156 | * [disable hostgroup notifications](doc/notifications.md#disable-hostgroup-notification)
157 | * [list all notifications](doc/notifications.md#list-notifications)
158 | * host notification (protected)
159 | * hostgroup notification (protected)
160 | * service notification (protected)
161 |
162 | - [Statistics](doc/statistics.md)
163 | * [statistic data for latence and execution time](doc/statistics.md#stats-avg)
164 | * [statistic data for interval data](doc/statistics.md#stats-interval)
165 | * [statistic data for services](doc/statistics.md#stats-services)
166 | * [statistic data for hosts](doc/statistics.md#stats-hosts)
167 | * [queue statistics from the api](doc/statistics.md#stats-work-queue)
168 |
169 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 |
2 | require 'bundler/gem_tasks'
3 | require 'rspec/core/rake_task'
4 | require 'bundler/gem_tasks'
5 | require 'rubocop/rake_task'
6 | require 'rake/testtask'
7 |
8 | # Default directory to look in is `/specs`
9 | # Run with `rake spec`
10 | RSpec::Core::RakeTask.new(:spec) do |task|
11 | task.rspec_opts = ['--color']
12 | end
13 |
14 | desc 'Run all style checks'
15 | task style: ['style:ruby']
16 |
17 | desc 'Run all regular tasks'
18 | task default: :spec
19 |
20 | desc 'Run all tests'
21 | task test: ['test']
22 |
23 | namespace :style do
24 | desc 'Run Ruby style checks'
25 | RuboCop::RakeTask.new(:ruby) do |task|
26 | task.patterns = ['**/*.rb']
27 | # don't abort rake on failure
28 | task.fail_on_error = false
29 | end
30 | end
31 |
32 |
33 | Rake::TestTask.new('test:all') do |t|
34 | t.libs = %w[lib spec]
35 | t.warning = true
36 | t.test_files = FileList['spec/**/*_spec.rb']
37 | end
38 |
--------------------------------------------------------------------------------
/config.reek:
--------------------------------------------------------------------------------
1 | ---
2 | UncommunicativeModuleName:
3 | accept:
4 | - Icinga2
5 |
6 | TooManyConstants:
7 | max_constants: 7
8 |
9 | TooManyStatements:
10 | enabled: true
11 | exclude:
12 | - initialize
13 | max_statements: 30
14 |
15 | LongParameterList:
16 | enabled: true
17 | max_params: 4
18 |
19 | UncommunicativeVariableName:
20 | enabled: false
21 |
--------------------------------------------------------------------------------
/doc/downtimes.md:
--------------------------------------------------------------------------------
1 | # Icinga2 - Downtimes
2 |
3 |
4 | ## add a downtime
5 | add_downtime( params )
6 |
7 | ### Example
8 |
9 | param = {
10 | name: 'test',
11 | type: 'service',
12 | host: 'icinga2',
13 | comment: 'test downtime',
14 | author: 'icingaadmin',
15 | start_time: Time.now.to_i,
16 | end_time: Time.now.to_i + 20
17 | }
18 | @icinga.add_downtime( param )
19 |
20 |
21 | ## remove a downtime
22 | remove_downtime( params )
23 |
24 | ### Example
25 |
26 | remove all downtimes from the user `icingaadmin` and the comment `test downtime`
27 |
28 | ```bash
29 | param = {
30 | comment: 'test downtime',
31 | author: 'icingaadmin'
32 | }
33 | @icinga.remove_downtime(param)
34 | ```
35 |
36 | remove a downtime from a host but not the services filtered by the author name.
37 | This example uses filter variables explained in the
38 | [advanced filters](https://github.com/Icinga/icinga2/blob/master/doc/12-icinga2-api.md#icinga2-api-advanced-filters)
39 | chapter from the official API documentation.
40 |
41 | ```bash
42 | param = {
43 | filter: '"host.name == filterHost && !service && downtime.author == filterAuthor"',
44 | filter_vars: { filterHost: 'c1-mysql-1', filterAuthor: 'icingaadmin' }
45 | )
46 | @icinga.remove_downtime(param)
47 | ```
48 |
49 | remove a downtime for service `ping4` and host `c1-mysql-1`
50 |
51 | ```bash
52 | param = {
53 | host_name: 'c1-mysql-1',
54 | service_name: 'ping4'
55 | }
56 | @icinga.remove_downtime(param)
57 | ```
58 |
59 |
60 | ## list all downtimes
61 | downtimes
62 |
63 | ### Example
64 | @icinga.downtimes
65 |
--------------------------------------------------------------------------------
/doc/examples:
--------------------------------------------------------------------------------
1 |
2 | To add hostgroup :
3 |
4 | curl -k -s -u icingaadmin:icinga 'https://localhost:5665/v1/objects/hostgroups/testgrp' \
5 | -X PUT -d '{ "attrs": { "name" : "testgrp" ,"display_name" : "testgrp" , "state_loaded" :true }}'
6 |
7 | To add host :
8 |
9 | curl -k -s -u icingaadmin:icinga 'https://localhost:5665/v1/objects/hosts/8.8.8.8' \
10 | -X PUT -d '{ "templates": [ "generic-host" ], "attrs": { "address": "8.8.8.8" , "groups" : [ "testgrp" ]} }'
11 |
12 |
13 | https://localhost:5665/v1/objects/users
14 | https://localhost:5665/v1/objects/usergroups
15 |
16 |
17 | https://localhost:5665/v1/objects/hostgroups
18 | https://localhost:5665/v1/objects/servicegroups
19 |
20 | https://localhost:5665/v1/objects/hosts
21 | https://localhost:5665/v1/objects/services
22 |
23 | # list service from host
24 | curl -k -u root:icinga -H 'Accept: application/json' -X GET 'https://localhost:5665/v1/objects/services/pandora-17-01!Runlevel-master-live-server'
25 |
26 |
27 | https://localhost:5665/v1/objects/notifications
28 |
29 | # get usergroups:
30 | curl -k -s -u root:icinga -H 'Accept: application/json' -X GET 'https://localhost:5665/v1/objects/usergroups'
31 |
32 | # add usergroup:
33 | curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/usergroups/foo' --data '{ "attrs": {"display_name": "Foo Bar" } }'
34 |
35 | # delete usergroup:
36 | curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: DELETE' -X POST 'https://localhost:5665/v1/objects/usergroups/foo'
37 |
38 |
39 | # delete user:
40 | curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: DELETE' -X POST 'https://localhost:5665/v1/objects/users/foo'
41 |
42 | # add user:
43 | curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/users/foo' --data '{ "attrs": {"display_name": "Foo Bar", "email": "foo.bar@coremedia.com","enable_notifications": false, "groups": [ "coreme
44 | dia" ] } }'
45 |
46 |
47 |
48 | # add notification
49 | curl -k -s -u root:icinga -H 'Accept: application/json' \
50 | -X PUT 'https://localhost:5665/v1/objects/notifications/debian7.example.com!jabber' -d '{
51 | "attrs": {
52 | "command":"mail-service-notification",
53 | "service_name":"apt",
54 | "user_groups": ["icingaadmins"] } }'
55 |
56 |
57 | # delete notification
58 | curl -k -s -u root:icinga -H 'Accept: application/json' \
59 | -H 'X-HTTP-Method-Override: DELETE' \
60 | -X POST 'https://localhost:5665/v1/objects/notifications/debian7.example.com!apt!jabber?cascade=1'
61 |
62 |
63 |
64 |
65 |
66 | # enable notification für host:
67 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/hosts/api_dummy_host_1' --data '{ "attrs": { "enable_notifications": true } }'
68 |
69 | # disable notification für host:
70 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/hosts/api_dummy_host_1' --data '{ "attrs": { "enable_notifications": false } }'
71 |
72 | # enable notification für service x von host:
73 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/services' --data '{ "filter": "host.name==\"api_dummy_host_1\"", "attrs": { "enable_notifications": true } }'
74 |
75 | # disable notification für service x von host:
76 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/services' --data '{ "filter": "host.name==\"api_dummy_host_1\"", "attrs": { "enable_notifications": false } }'
77 |
78 | # enable notification für hostgroup:
79 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/services' --data '{ "filter": "\"api_dummy_hostgroup\" in host.groups", "attrs": { "enable_notifications": true } }'
80 |
81 | # disable notification für hostgroup:
82 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/services' --data '{ "filter": "\"api_dummy_hostgroup\" in host.groups", "attrs": { "enable_notifications": false } }'
83 |
84 |
85 | # get downtimes
86 | curl -k -s -u root:icinga -H 'Accept: application/json' -X GET 'https://localhost:5665/v1/objects/downtimes'
87 |
88 | # delete named downtime
89 | curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: DELETE' -X POST 'https://localhost:5665/v1/objects/downtimes/icinga2-master!load!icinga2-master-1496045418-0'
90 |
91 |
92 | # schedule downtime for a host
93 |
94 | # current_time=$(date +%s)
95 | # 1449057010
96 | # current_time_add_30_second=$(date +%s --date="+30 seconds")
97 | # 1449057040
98 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/schedule-downtime' \
99 | --data '{ "type": "Host", "filter": "host.name==\"api_dummy_host_1\"", "start_time": 1449057685, "end_time": 1449057715, "author": "api_user", "comment": "api_comment", "fixed": true, "duration": 30 }'
100 |
101 | # schedule downtime for all services of a host - change the timestamps accordingly
102 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/schedule-downtime' \
103 | --data '{ "type": "Service", "filter": "host.name==\"api_dummy_host_1\"", "start_time": 1449064981, "end_time": 1449065129, "author": "api_user", "comment": "api_comment", "fixed": true, "duration": 30 }'
104 |
105 |
106 | # schedule downtime for all hosts and services in a hostgroup - change the timestamps accordingly
107 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/schedule-downtime' \
108 | --data '{ "type": "Host", "filter": "\"api_dummy_hostgroup\" in host.groups", "start_time": 1449065680, "end_time": 1449065823, "author": "api_user", "comment": "api_comment", "duration": 120, "fixed": true, "duration": 30 }'
109 |
110 | curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/schedule-downtime' \
111 | --data '{ "type": "Service", "filter": "\"api_dummy_hostgroup\" in host.groups)", "start_time": 1449065680, "end_time": 1449065823, "author": "api_user", "comment": "api_comment", "duration": 120, "fixed": true, "duration": 30 }'
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/doc/hostgroups.md:
--------------------------------------------------------------------------------
1 | # Icinga2 - Hostgroups
2 |
3 |
4 | ## add a hostgroup
5 | add_hostgroup( params )
6 |
7 | ### Example
8 | @icinga.add_hostgroup(host_group: 'foo', display_name: 'FOO')
9 |
10 |
11 | ## delete a hostgroup
12 | delete_hostgroup( params )
13 |
14 | ### Example
15 | @icinga.delete_hostgroup(host_group: 'foo')
16 |
17 |
18 | ## list hostgroups
19 |
20 | ### list named hostgroup
21 | hostgroups( params )
22 |
23 | #### Example
24 | @icinga.hostgroups(host_group: 'linux-servers')
25 |
26 | ### list all hostgroups
27 | hostgroups
28 |
29 | ### Example
30 | @icinga.hostgroups
31 |
32 |
33 | ## check if the hostgroup exists
34 | exists_hostgroup?( hostgroup )
35 |
36 | ### Example
37 | @icinga.exists_hostgroup?('linux-servers')
38 |
--------------------------------------------------------------------------------
/doc/hosts.md:
--------------------------------------------------------------------------------
1 | # Icinga2 - Hosts
2 |
3 | ## add a host
4 | add_host( params )
5 |
6 | ### Example
7 | param = {
8 | name: 'foo',
9 | address: 'foo.bar.com',
10 | display_name: 'test node',
11 | max_check_attempts: 5,
12 | notes: 'test node',
13 | vars: {
14 | description: 'host foo',
15 | os: 'Linux',
16 | partitions: {
17 | '/' => {
18 | crit: '95%',
19 | warn: '90%'
20 | }
21 | }
22 | }
23 | }
24 | @icinga.add_host(param)
25 |
26 |
27 | ## delete a host
28 | delete_host( params )
29 |
30 | ### Example
31 | @icinga.delete_host(name: 'foo')
32 |
33 |
34 | ## modify a host
35 | modify_host( params )
36 |
37 | ### Example
38 |
39 |
40 | param = {
41 | name: 'foo',
42 | address: 'foo.bar.com',
43 | display_name: 'Host for an example Problem',
44 | max_check_attempts: 10,
45 | }
46 |
47 | or
48 |
49 | param = {
50 | name: 'foo',
51 | address: 'foo.bar.com',
52 | notes: 'an demonstration object',
53 | vars: {
54 | description: 'schould be delete ASAP',
55 | os: 'Linux',
56 | partitions: {
57 | '/' => {
58 | crit: '98%',
59 | warn: '95%'
60 | }
61 | }
62 | },
63 | merge_vars: true
64 | }
65 |
66 | or
67 |
68 | param = {
69 | name: 'foo',
70 | address: 'foo.bar.com',
71 | vars: {
72 | description: 'removed all other custom vars',
73 | }
74 | }
75 |
76 | @icinga.modify_host( name: 'foo')
77 |
78 |
79 | ## list hosts
80 |
81 | ### list a named host
82 | hosts( params )
83 |
84 | #### Example
85 | @icinga.host(name: 'icinga2')
86 |
87 | ### list all hosts
88 | hosts
89 |
90 | #### Example
91 | @icinga.hosts
92 |
93 |
94 | ## check if the host exists
95 | exists_host?( host_name )
96 |
97 | ### Example
98 | @icinga.exists_host?('icinga2')
99 |
100 |
101 | ## get host objects
102 | host_objects( params )
103 |
104 | ### Example
105 | @icinga.host_objects(attrs: ['name', 'state'])
106 |
107 |
108 | ## count of hosts with problems
109 | count_hosts_with_problems
110 |
111 | ### Example
112 | @icinga.count_hosts_with_problems
113 |
114 |
115 | ## a hash of hosts with problems
116 | list_hosts_with_problems( max_items )
117 |
118 | ### Example
119 | @icinga.list_hosts_with_problems
120 | @icinga.list_hosts_with_problems( 10 )
121 |
122 |
123 | ## count of all hosts
124 | hosts_all
125 |
126 | ### Example
127 | @icinga.hosts_all
128 |
129 |
130 | ## count all hosts with problems (down, warning, unknown state)
131 | host_problems
132 |
133 | ### Example
134 | all, down, critical, unknown, handled, adjusted = @icinga.host_problems.values
135 |
136 | or
137 |
138 | p = @icinga.host_problems
139 | down = h.dig(:down)
140 |
141 |
142 | ## (protected) calculate a host severity
143 | host_severity( params )
144 |
145 | original code are from [Icinga Web2](/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php)
146 |
147 | ### Example
148 | host_severity( {'attrs' => { 'state' => 0.0, 'acknowledgement' => 0.0, 'downtime_depth' => 0.0 } } )
149 |
--------------------------------------------------------------------------------
/doc/notifications.md:
--------------------------------------------------------------------------------
1 | # Icinga2 - Notifications
2 |
3 |
4 | ## enable host notifications
5 | enable_host_notification( host )
6 |
7 | ### Example
8 | @icinga.enable_host_notification('icinga')
9 |
10 |
11 | ## disable host notifications
12 | disable_host_notification( host )
13 |
14 | ### Example
15 | @icinga.disable_host_notification('icinga')
16 |
17 |
18 | ## enable service notifications
19 | enable_service_notification( host )
20 |
21 | ### Example
22 | @icinga.enable_service_notification('icinga')
23 |
24 |
25 | ## disable service notifications
26 | disable_service_notification( host )
27 |
28 | ### Example
29 | @icinga.disable_service_notification('icinga')
30 |
31 |
32 | ## enable hostgroup notifications
33 | enable_hostgroup_notification( params )
34 |
35 | ### Example
36 | @icinga.enable_hostgroup_notification(host: 'icinga2', host_group: 'linux-servers')
37 |
38 |
39 | ## disable hostgroup notifications
40 | disable_hostgroup_notification( params )
41 |
42 | ### Example
43 | @icinga.disable_hostgroup_notification(host: 'icinga2', host_group: 'linux-servers')
44 |
45 |
46 | ## list all notifications
47 | notifications
48 |
49 | ### Example
50 | @icinga.notifications
51 |
52 |
53 | ## (protected) function for host notifications
54 | host_notification( params = {} )
55 |
56 | ## (protected) function for hostgroup notifications
57 | hostgroup_notification( params = {} )
58 |
59 | ## (protected) function for service notifications
60 | service_notification( params = {} )
61 |
--------------------------------------------------------------------------------
/doc/servicegroups.md:
--------------------------------------------------------------------------------
1 | # Icinga2 - Servicegroups
2 |
3 |
4 | ## add a servicegroup
5 | add_servicegroup( params )
6 |
7 | ### Example
8 | @icinga.add_servicegroup(service_group: 'foo', display_name: 'FOO')
9 |
10 | ## delete a servicegroup
11 | delete_servicegroup( params )
12 |
13 | ### Example
14 | @icinga.delete_servicegroup(service_group: 'foo')
15 |
16 | ## list servicegroups
17 |
18 | ### list a named servicegroup
19 | servicegroups( params )
20 |
21 | #### Example
22 | @icinga.servicegroups(service_group: 'disk')
23 |
24 | ### list all servicegroups
25 | servicegroups
26 |
27 | #### Example
28 | @icinga.servicegroups
29 |
30 |
31 | ## checks if the servicegroup exists
32 | exists_servicegroup?( service_group )
33 |
34 | ### Example
35 | @icinga.exists_servicegroup?('disk')
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/doc/services.md:
--------------------------------------------------------------------------------
1 | # Icinga2 - Services
2 |
3 |
4 | ## *add_services( params )*
5 |
6 | Add a Service to Icinga2
7 |
8 | `params` is an `Hash` with following Parameters:
9 |
10 | | Parameter | Type | Example | Description
11 | | :-------------------- | :-----: | :----- | :-----------
12 | | `host_name` | String | `foo` | existing Host for these Service
13 | | `name` | String | `ping4` | Service Name they will be create
14 | | `display_name` | String | `ping4 check` | displayed Name
15 | | `templates` | Array | `['own-service']` | (optional) a Array of templates (default: `['generic-service']`)
16 | | `check_command` | String | `ping4` | The Check Command to execute (**Importand** This Check-Comand must be exists! Otherwise an error will occur)
17 | | `check_interval` | Integer | `10` | The check Interval
18 | | `retry_interval` | Integer | `30` | The retry Interval
19 | | `notes` | String | `` |
20 | | `notes_url` | String | `` |
21 | | `action_url` | String | `` |
22 | | `check_period` | String | `` |
23 | | `check_timeout` | Integer | `` |
24 | | `command_endpoint` | String | `` |
25 | | `enable_active_checks` | Bool | `` |
26 | | `enable_event_handler` | Bool | `` |
27 | | `enable_flapping` | Bool | `` |
28 | | `enable_notifications` | Bool | `` |
29 | | `enable_passive_checks` | Bool | `` |
30 | | `enable_perfdata` | Bool | `` |
31 | | `event_command` | String | `` |
32 | | `flapping_threshold_high`| Integer | `` |
33 | | `flapping_threshold_low` | Integer | `` |
34 | | `flapping_threshold` | Integer | `` |
35 | | `icon_image_alt` | String | `` |
36 | | `icon_image` | String | `` |
37 | | `max_check_attempts` | Integer | `` |
38 | | `volatile` | Bool | `` |
39 | | `vars` | Hash | (see below) | optional config params for the `check_command`
40 |
41 | The result are an `Hash`
42 |
43 | ### Example
44 |
45 | @icinga.add_services(
46 | host_name: 'foo',
47 | name: 'ping4',
48 | check_command: 'ping4',
49 | check_interval: 10,
50 | retry_interval: 30
51 | )
52 |
53 | or
54 |
55 | @icinga.add_service(
56 | host_name: 'foo',
57 | name: 'http',
58 | check_command: 'http',
59 | check_interval: 10,
60 | retry_interval: 30,
61 | vars: {
62 | http_address: '127.0.0.1',
63 | http_url: '/access/index',
64 | http_port: 80
65 | }
66 | )
67 |
68 |
69 |
70 | ## *delete_service( params )*
71 |
72 | Delete an Service From Icinga2
73 |
74 | `params` is an `Hash` with following Parameters:
75 |
76 | | Parameter | Type | Example | Description
77 | | :-------------------- | :-----: | :----- | :-----------
78 | | `host` | String | `foo` | existing Host for these Service
79 | | `name` | String | `ping4` | Service Name they will be deleted
80 | | `cascade` | Bool | `true` | delete service also when other objects depend on it (default: `false`)
81 |
82 |
83 | The result are an `Hash`
84 |
85 | #### Example
86 |
87 | @icinga.delete_service(host_name: 'foo', name: 'ping4')
88 |
89 | or
90 |
91 | @icinga.delete_service(host_name: 'foo', name: 'new_ping4', cascade: true)
92 |
93 |
94 | ## *modify_service( params )*
95 |
96 | Modify an Service.
97 |
98 | `params` is an `Hash` with following Parameters:
99 |
100 | | Parameter | Type | Example | Description
101 | | :-------------------- | :-----: | :----- | :-----------
102 | | `name` | String | `ping4` | Service Name they will be deleted
103 | | `templates` | Array | `['own-service']` | (optional) a Array of templates (default: `['generic-service']`)
104 | | `vars` | Hash | (see below) | Hash with custom options (see `add_services()`)
105 |
106 | The result are an `Hash`
107 |
108 | #### Example
109 |
110 | @icinga.modify_service(
111 | name: 'http2',
112 | check_interval: 60,
113 | retry_interval: 10,
114 | vars: {
115 | http_url: '/access/login' ,
116 | http_address: '10.41.80.63'
117 | }
118 | )
119 |
120 |
121 | ## *unhandled_services*
122 |
123 | return all unhandled services
124 |
125 | The result are an `Hash`
126 |
127 | #### Example
128 | @icinga.unhandled_services
129 |
130 |
131 | ## *services* or *services( params )*
132 |
133 | returns all or a named service
134 |
135 | the optional `params` is an `Hash` with following Parameters:
136 |
137 | | Parameter | Type | Example | Description
138 | | :-------------------- | :-----: | :----- | :-----------
139 | | `host` | String | `foo` | Hostname
140 | | `service` | String | `ping4` | service to list
141 |
142 | The result are an `Hash`
143 |
144 | ### list all services
145 | services
146 |
147 | #### Example
148 | @icinga.services
149 |
150 |
151 | ### list named service
152 | services( params )
153 |
154 | #### Example
155 | @icinga.services( host_name: 'icinga2', service: 'ping4' )
156 |
157 |
158 | ## *exists_service?( params )*
159 |
160 | check if the service exists
161 |
162 | the optional `params` is an `Hash` with following Parameters:
163 |
164 | | Parameter | Type | Example | Description
165 | | :-------------------- | :-----: | :----- | :-----------
166 | | `host` | String | `foo` | Hostname
167 | | `service` | String | `ping4` | servicename
168 |
169 | The result are an `Hash`
170 |
171 | ### Example
172 | @icinga.exists_service?( host_name: 'icinga2', service: 'users' )
173 |
174 |
175 | ## *service_objects( params )*
176 |
177 | list service objects
178 |
179 | the optional `params` is an `Hash` with following Parameters:
180 |
181 | | Parameter | Type | Example | Description
182 | | :-------------------- | :-----: | :----- | :-----------
183 | | `attrs` | Array | `[]` | Array of `attrs`
184 | | `filter` | Array | `[]` | Array of `filter`
185 | | `joins` | Array | `[]` | Array of `joins`
186 |
187 | For more Examples for Quering Objects read the [Icinga2 Documentation](https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#querying-objects)
188 |
189 | - defaults for `attrs` are `['name', 'state', 'acknowledgement', 'downtime_depth', 'last_check']`
190 | - defaults for `filter` are `[]`
191 | - defaults for `joins` are `['host.name','host.state','host.acknowledgement','host.downtime_depth','host.last_check']`
192 |
193 | The result are an `Array`
194 |
195 | ### Example
196 | @icinga.service_objects(
197 | attrs: ['name', 'state'],
198 | joins: ['host.name','host.state']
199 | )
200 |
201 |
202 | ## *services_adjusted*
203 |
204 | returns adjusted service state
205 |
206 | The result are an `Hash`
207 |
208 | ### Example
209 |
210 | warning, critical, unknown = @icinga.services_adjusted.values
211 |
212 | or
213 |
214 | s = @icinga.services_adjusted
215 | unknown = s.dig(:unknown)
216 |
217 |
218 | ## *count_services_with_problems*
219 |
220 | count services with problems
221 |
222 | The result are an `Integer`
223 |
224 | ### Example
225 | @icinga.count_services_with_problems
226 |
227 |
228 | ## *list_services_with_problems( max_items )*
229 |
230 | list of services with problems
231 |
232 | The result are an `Hash`
233 |
234 | ### Example
235 |
236 | problems, problems_and_severity = @icinga.list_services_with_problems(10).values
237 |
238 | or
239 |
240 | l = @icinga.list_services_with_problems(10)
241 | problems_and_severity = l.dig(:services_with_problems_and_severity)
242 |
243 |
244 | ## *services_all*
245 |
246 | count all services
247 |
248 | The result are an `Integer`
249 |
250 | ### Example
251 |
252 | @icinga.services_all
253 |
254 |
255 | ## *service_problems*
256 |
257 | returns data with service problems
258 |
259 | The result are an `Hash`
260 |
261 | ### Example
262 |
263 | all, warning, critical, unknown, pending, in_downtime, acknowledged, adjusted_warning, adjusted_critical, adjusted_unknown = @icinga.service_problems.values
264 |
265 | or
266 |
267 | p = @icinga.service_problems
268 | warning = p.dig(:warning)
269 |
270 |
271 | ## *service_severity( params )* (protected)
272 |
273 | calculate a service severity
274 | (taken from the IcingaWeb2 Code)
275 |
276 | The result are an `Integer`
277 |
278 | ### Example
279 | service_severity( {'attrs' => { 'state' => 0.0, 'acknowledgement' => 0.0, 'downtime_depth' => 0.0 } } )
280 |
281 |
282 |
--------------------------------------------------------------------------------
/doc/statistics.md:
--------------------------------------------------------------------------------
1 | # Icinga2 - Statistics
2 |
3 |
4 | ## *average_statistics*
5 |
6 | statistic data for latency and execution_time
7 |
8 | The result are an `Hash`
9 |
10 | ### Example
11 | @icinga.cib_data
12 | latency, execution_time = @icinga.average_statistics.values
13 |
14 | or
15 |
16 | h = @icinga.average_statistics
17 | latency = h.dig(:latency)
18 |
19 | ## *interval_statistics*
20 |
21 | statistic data for intervall data
22 |
23 | The result are an `Hash`
24 |
25 | ### Example
26 | @icinga.cib_data
27 | hosts_active_checks, hosts_passive_checks, services_active_checks, services_passive_checks = @icinga.interval_statistics.values
28 |
29 | or
30 | i = @icinga.interval_statistics
31 | hosts_active_checks = i.dig(:hosts_active_checks)
32 |
33 |
34 | ## *service_statistics*
35 |
36 | statistic data for services
37 |
38 | The result are an `Hash`
39 |
40 | ### Example
41 | @icinga.cib_data
42 | ok, warning, critical, unknown, pending, in_downtime, ack = @icinga.service_statistics.values
43 |
44 | or
45 | s = @icinga.service_statistics
46 | critical = s.dig(:critical)
47 |
48 | ## *host_statistics*
49 |
50 | statistic data for hosts
51 |
52 | The result are an `Hash`
53 |
54 | ### Example
55 | @icinga.cib_data
56 | up, down, pending, unreachable, in_downtime, ack = @icinga.host_statistics.values
57 |
58 | or
59 |
60 | h = @icinga.host_statistics
61 | pending = h.dig(:pending)
62 |
63 |
64 | ## work_queue_statistics
65 |
66 | queue statistics from the api
67 |
68 | The result are an `Hash`
69 |
70 | ### Example
71 | @icinga.work_queue_statistics
72 |
73 |
--------------------------------------------------------------------------------
/doc/usergroups.md:
--------------------------------------------------------------------------------
1 | # Icinga2 - Usergroups
2 |
3 |
4 | ## *add_usergroup( params )*
5 |
6 | Creates an Icinga2 Usergroup.
7 |
8 | `params` are an `Hash` with following Parameters:
9 |
10 | | Parameter | Type | Example | Description
11 | | :-------------------- | :-----: | :----- | :-----------
12 | | `user_group` | String | `foo` | Usergroup they will be created
13 | | `display_name` | String | `User Foo` | the displayed Name
14 |
15 | The result are an `Hash`
16 |
17 | ### Example
18 | @icinga.add_usergroup(user_group: 'foo', display_name: 'FOO')
19 |
20 |
21 | ## *delete_usergroup( params )*
22 |
23 | Delete a Usergroup.
24 |
25 | `params` are an `Hash` with following Parameters:
26 |
27 | | Parameter | Type | Example | Description
28 | | :-------------------- | :-----: | :----- | :-----------
29 | | `user_group` | String | `foo` | Usergroup they will be deleted
30 |
31 | The result are an `Hash`
32 |
33 | ### Example
34 | @icinga.delete_usergroup(user_group: 'foo')
35 |
36 |
37 | ## *usergroups* or *usergroups( params )*
38 |
39 | returns all or a named usergroup.
40 |
41 | the optional `params` is an `Hash` with following Parameters:
42 |
43 | | Parameter | Type | Example | Description
44 | | :-------------------- | :-----: | :----- | :-----------
45 | | `user_group` | String | `foo` | Usergroup they will be listed
46 |
47 | The result are an `Hash`
48 |
49 |
50 | ### list all usergroups
51 | usergroups
52 |
53 | #### Example
54 | @icinga.usergroups
55 |
56 |
57 | ### list named usergroup
58 | usergroups( params )
59 |
60 | #### Example
61 | @icinga.usergroups(user_group: 'icingaadmins')
62 |
63 |
64 |
65 | ## *exists_usergroup?( user_group )*
66 |
67 | check if the Usergroup exists
68 |
69 | `params` is an `String` with the Usergroupname.
70 |
71 | The result are an `Boolean`
72 |
73 | ### Example
74 |
75 | @icinga.exists_usergroup?('icingaadmins')
76 |
--------------------------------------------------------------------------------
/doc/users.md:
--------------------------------------------------------------------------------
1 | # Icinga2 - Users
2 |
3 | ## *add_user( params )*
4 |
5 | creates an Icinga2 User.
6 |
7 | `params` are an `Hash` with following Parameters:
8 |
9 | | Parameter | Type | Example | Description
10 | | :-------------------- | :-----: | :----- | :-----------
11 | | `user_name` | String | `foo` | User they will be created
12 | | `display_name` | String | `User Foo` | the displayed Name
13 | | `email` | String | `foo@bar.tld` | the Email for this Users
14 | | `pager` | String | `+49 000 000000` | an optional Pager Number
15 | | `enable_notifications` | Bool | `true` | enable notifications for this user (default: **false**)
16 | | `groups` | Array | `['icingaadmins','dba']` | a hash with (existing!) groups
17 |
18 | The result are an `Hash`
19 |
20 | ### Example
21 |
22 | params = {
23 | user_name: 'foo',
24 | display_name: 'FOO',
25 | email: 'foo@bar.com',
26 | pager: '0000',
27 | groups: ['icingaadmins']
28 | }
29 | puts @icinga.add_user( params )
30 | {"code"=>200, "name"=>nil, "status"=>"Object was created"}
31 |
32 |
33 | ## *delete_user( params )*
34 |
35 | delete an Icinga2 User.
36 |
37 | `params` is an `Hash` with following Parameters:
38 |
39 | | Parameter | Type | Example | Description
40 | | :-------------------- | :-----: | :----- | :-----------
41 | | `user_name` | String | `foo` | User they will be deleted
42 |
43 | The result are an `Hash`
44 |
45 | ### Example
46 |
47 | puts @icinga.delete_user(user_name: 'foo')
48 | {"code"=>200, "name"=>"foo", "status"=>"Object was deleted."}
49 |
50 |
51 | ## *users* or *users( params )*
52 |
53 | returns all or a named user.
54 |
55 | the optional `params` is an `Hash` with following Parameters:
56 |
57 | | Parameter | Type | Example | Description
58 | | :-------------------- | :-----: | :----- | :-----------
59 | | `user_name` | String | `foo` | User they will be listed
60 |
61 | The result are an `Hash`
62 |
63 | ### list all users
64 | users
65 |
66 | #### Example
67 | @icinga.users
68 | {"attrs"=>{"__name"=>"icingaadmin", "active"=>true, "display_name"=>"Icinga 2 Admin", "email"=>"icinga@localhost", "enable_notifications"=>true, "groups"=>["icingaadmins"], "ha_mode"=>0.0, "last_notification"=>0.0, "name"=>"icingaadmin", "original_attributes"=>nil, "package"=>"_etc", "pager"=>"", "paused"=>false, "period"=>"", "source_location"=>{"first_column"=>1.0, "first_line"=>6.0, "last_column"=>25.0, "last_line"=>6.0, "path"=>"/etc/icinga2/conf.d/users.conf"}, "states"=>nil, "templates"=>["icingaadmin", "generic-user"], "type"=>"User", "types"=>nil, "vars"=>nil, "version"=>0.0, "zone"=>""}, "joins"=>{}, "meta"=>{}, "name"=>"icingaadmin", "type"=>"User"}
69 |
70 | ### list named user
71 | users( params )
72 |
73 | #### Example
74 | @icinga.users(user_name: 'foo')
75 | {"attrs"=>{"__name"=>"foo", "active"=>true, "display_name"=>"FOO", "email"=>"foo@bar.com", "enable_notifications"=>false, "groups"=>["icingaadmins"], "ha_mode"=>0.0, "last_notification"=>0.0, "name"=>"foo", "original_attributes"=>nil, "package"=>"_api", "pager"=>"0000", "paused"=>false, "period"=>"", "source_location"=>{"first_column"=>0.0, "first_line"=>1.0, "last_column"=>16.0, "last_line"=>1.0, "path"=>"/var/lib/icinga2/api/packages/_api/icinga2-master.matrix.lan-1507365860-1/conf.d/users/foo.conf"}, "states"=>nil, "templates"=>["foo"], "type"=>"User", "types"=>nil, "vars"=>nil, "version"=>1507609817.587105, "zone"=>"icinga2-master.matrix.lan"}, "joins"=>{}, "meta"=>{}, "name"=>"foo", "type"=>"User"}
76 |
77 |
78 |
79 | ## *exists_user?( params )*
80 |
81 | check if an User exists.
82 |
83 | `params` is an `String` with the Username.
84 |
85 | The result are an `Boolean`
86 |
87 | ### Example
88 |
89 | puts @icinga.exists_user?('icingaadmin')
90 | true
91 |
--------------------------------------------------------------------------------
/examples/_blank.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hostgroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 |
13 | # -----------------------------------------------------------------------------
14 |
15 | icinga_host = ENV.fetch( 'ICINGA_HOST' , 'icinga2' )
16 | icinga_api_port = ENV.fetch( 'ICINGA_API_PORT' , 5665 )
17 | icinga_api_user = ENV.fetch( 'ICINGA_API_USER' , 'admin' )
18 | icinga_api_pass = ENV.fetch( 'ICINGA_API_PASSWORD' , nil )
19 | icinga_api_pki_path = ENV.fetch( 'ICINGA_API_PKI_PATH' , '/etc/icinga2' )
20 | icinga_api_node_name = ENV.fetch( 'ICINGA_API_NODE_NAME' , nil )
21 | icinga_cluster = ENV.fetch( 'ICINGA_CLUSTER' , false )
22 | icinga_satellite = ENV.fetch( 'ICINGA_CLUSTER_SATELLITE', nil )
23 |
24 |
25 | # convert string to bool
26 | icinga_cluster = icinga_cluster.to_s.eql?('true') ? true : false
27 |
28 | config = {
29 | icinga: {
30 | host: icinga_host,
31 | api: {
32 | port: icinga_api_port,
33 | user: icinga_api_user,
34 | password: icinga_api_pass,
35 | pki_path: icinga_api_pki_path,
36 | node_name: icinga_api_node_name
37 | },
38 | cluster: icinga_cluster,
39 | satellite: icinga_satellite
40 | }
41 | }
42 |
43 | # ---------------------------------------------------------------------------------------
44 |
45 | i = Icinga2::Client.new( config )
46 |
47 | unless( i.nil? )
48 |
49 | # run tests ...
50 | #
51 | #
52 |
53 | begin
54 |
55 | puts ' ------------------------------------------------------------- '
56 | puts ''
57 |
58 |
59 |
60 | puts ' ------------------------------------------------------------- '
61 | puts ''
62 |
63 | rescue => e
64 | warn( e )
65 | warn( e.backtrace.join("\n") )
66 | end
67 | end
68 |
69 |
70 | # -----------------------------------------------------------------------------
71 |
72 | # EOF
73 |
--------------------------------------------------------------------------------
/examples/cert-manager.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Supported commands:
4 | # * pki new-ca (sets up a new CA)
5 | # * pki new-cert (creates a new CSR)
6 | # Command options:
7 | # --cn arg Common Name
8 | # --key arg Key file path (output
9 | # --csr arg CSR file path (optional, output)
10 | # --cert arg Certificate file path (optional, output)
11 | # * pki request (requests a certificate)
12 | # Command options:
13 | # --key arg Key file path (input)
14 | # --cert arg Certificate file path (input + output)
15 | # --ca arg CA file path (output)
16 | # --trustedcert arg Trusted certificate file path (input)
17 | # --host arg Icinga 2 host
18 | # --port arg Icinga 2 port
19 | # --ticket arg Icinga 2 PKI ticket
20 | # * pki save-cert (saves another Icinga 2 instance's certificate)
21 | # Command options:
22 | # --key arg Key file path (input), obsolete
23 | # --cert arg Certificate file path (input), obsolete
24 | # --trustedcert arg Trusted certificate file path (output)
25 | # --host arg Icinga 2 host
26 | # --port arg (=5665) Icinga 2 port
27 | # * pki sign-csr (signs a CSR)
28 | # Command options:
29 | # --csr arg CSR file path (input)
30 | # --cert arg Certificate file path (output)
31 | # * pki ticket (generates a ticket)
32 | # Command options:
33 | # --cn arg Certificate common name
34 | # --salt arg Ticket salt
35 |
36 | HOSTNAME="$(hostname -s)"
37 |
38 | PKI_KEY="/etc/icinga2/pki/${HOSTNAME}.key"
39 | PKI_CSR="/etc/icinga2/pki/${HOSTNAME}.csr"
40 | PKI_CRT="/etc/icinga2/pki/${HOSTNAME}.crt"
41 |
42 | ICINGA_MASTER="icinga2-core"
43 |
44 | PKI_CMD="icinga2 pki"
45 |
46 | # --------------------------------------------------------------------------------------------
47 |
48 | chown -R icinga: /var/lib/icinga2
49 |
50 | icinga2 api setup
51 | ${PKI_CMD} new-cert --cn ${HOSTNAME} --key ${PKI_KEY} --csr ${PKI_CSR}
52 | ${PKI_CMD} sign-csr --csr ${PKI_CSR} --cert ${PKI_CRT}
53 |
54 | # if [ $(icinga2 feature list | grep Enabled | grep api | wc -l) -eq 0 ]
55 | # then
56 | # icinga2 feature enable api
57 | # fi
58 |
59 | supervisorctl restart icinga2
60 |
61 | echo -e "\n\n"
62 |
63 |
64 | SATELLITES="icinga2-satellite-1 icinga2-satellite-2"
65 |
66 | for s in ${SATELLITES}
67 | do
68 | dir="/tmp/${s}"
69 |
70 | chown icinga: ${dir}
71 |
72 | salt=$(echo ${s} | sha256sum | cut -f 1 -d ' ')
73 |
74 | mkdir ${dir}
75 |
76 |
77 | ${PKI_CMD} new-cert --cn ${s} --key ${dir}/${s}.key --csr ${dir}/${s}.csr
78 | ${PKI_CMD} sign-csr --csr ${dir}/${s}.csr --cert ${dir}/${s}.crt
79 | ${PKI_CMD} save-cert --key ${dir}/${s}.key --cert ${dir}/${s}.crt --trustedcert ${dir}/trusted-master.crt --host ${ICINGA_MASTER}
80 | # Receive Ticket from master...
81 | pki_ticket=$(${PKI_CMD} ticket --cn ${HOSTNAME} --salt ${salt})
82 | ${PKI_CMD} request --host ${ICINGA_MASTER} --port 5665 --ticket ${pki_ticket} --key ${dir}/${s}.key --cert ${dir}/${s}.crt --trustedcert ${dir}/trusted-master.crt --ca /etc/icinga2/pki/ca.crt
83 |
84 | # openssl x509 -in ${dir}/${s}.crt -text -noout
85 | # openssl req -in ${dir}/${s}.csr -noout -text
86 |
87 | done
88 |
89 | exit 0
90 |
91 |
92 | #icinga2 pki new-cert --cn ${HOSTNAME} --key /etc/icinga2/pki/${HOSTNAME}.key --cert /etc/icinga2/pki/${HOSTNAME}.crt
93 | #
94 | ## Set trusted Cert
95 | #icinga2 pki save-cert --key /etc/icinga2/pki/${HOSTNAME}.key --cert /etc/icinga2/pki/${HOSTNAME}.crt --trustedcert /etc/icinga2/pki/trusted-master.crt --host ${ICINGA_MASTER}
96 | #
97 | #salt=$(echo $(hostname) | sha256sum | cut -f 1 -d ' ')
98 | ## Receive Ticket from master...
99 | #pki_ticket=$(icinga2 pki ticket --cn ${HOSTNAME} --salt ${salt})
100 | #echo " [i] PKI Ticket for '${HOSTNAME}' : '${pki_ticket}'" # => delegate_to: "${ICINGA_MASTER}"
101 | #
102 | ## Request PKI
103 | #icinga2 pki request --host ${ICINGA_MASTER} --port 5665 --ticket ${pki_ticket} --key /etc/icinga2/pki/${HOSTNAME}.key --cert /etc/icinga2/pki/${HOSTNAME}.crt --trustedcert /etc/icinga2/pki/trusted-master.crt --ca /etc/icinga2/pki/ca.crt
104 | #
105 | ## Set Master as Endpoint
106 | #icinga2 node setup --ticket ${pki_ticket} --endpoint ${ICINGA_MASTER} --zone ${HOSTNAME} --master_host ${ICINGA_MASTER} --trustedcert /etc/icinga2/pki/trusted-master.crt
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/examples/config.rb:
--------------------------------------------------------------------------------
1 |
2 | icinga_host = ENV.fetch( 'ICINGA_HOST' , 'icinga2' )
3 | icinga_api_port = ENV.fetch( 'ICINGA_API_PORT' , 5665 )
4 | icinga_api_user = ENV.fetch( 'ICINGA_API_USER' , 'admin' )
5 | icinga_api_pass = ENV.fetch( 'ICINGA_API_PASSWORD' , nil )
6 | icinga_api_pki_path = ENV.fetch( 'ICINGA_API_PKI_PATH' , '/etc/icinga2' )
7 | icinga_api_node_name = ENV.fetch( 'ICINGA_API_NODE_NAME' , nil )
8 |
9 | @config = {
10 | icinga: {
11 | host: icinga_host,
12 | api: {
13 | port: icinga_api_port,
14 | user: icinga_api_user,
15 | password: icinga_api_pass,
16 | pki_path: icinga_api_pki_path,
17 | node_name: icinga_api_node_name
18 | }
19 | }
20 | }
21 |
22 | # ---------------------------------------------------------------------------------------
23 |
24 |
--------------------------------------------------------------------------------
/examples/downtimes.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hostgroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | puts ' ------------------------------------------------------------- '
27 | puts ''
28 |
29 | # puts ' ==> DOWNTIMES'
30 | # puts ''
31 | # puts 'add Downtime \'test\''
32 | # puts i.add_downtime( name: 'test', type: 'service', host: 'foo', comment: 'test downtime', author: 'icingaadmin', start_time: Time.now.to_i, end_time: Time.now.to_i + 20 )
33 | # puts ''
34 | # puts 'list all Downtimes'
35 | # puts i.downtimes
36 | # puts ''
37 |
38 | puts ' ------------------------------------------------------------- '
39 | puts ''
40 |
41 | rescue => e
42 | warn( e )
43 | warn( e.backtrace.join("\n") )
44 | end
45 | end
46 |
47 |
48 | # -----------------------------------------------------------------------------
49 |
50 | # EOF
51 |
--------------------------------------------------------------------------------
/examples/hostgroups.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hostgroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | puts ' ------------------------------------------------------------- '
27 | puts ''
28 |
29 | puts '= check if Hostgroup \'linux-servers\' exists'
30 | puts i.exists_hostgroup?( 'linux-servers' ) ? 'true' : 'false'
31 | puts ''
32 | puts '= check if Hostgroup \'docker\' exists'
33 | puts i.exists_hostgroup?( 'docker' ) ? 'true' : 'false'
34 | puts ''
35 | puts '= list named Hostgroup \'linux-servers\''
36 | puts i.hostgroups( host_group: 'linux-servers' )
37 | puts ''
38 | puts '= list named Hostgroup \'foo\''
39 | puts i.hostgroups( host_group: 'foo' )
40 | puts ''
41 | puts '= list all Hostgroups'
42 | puts i.hostgroups
43 | puts ''
44 | puts '= add hostgroup \'foo\''
45 | puts i.add_hostgroup( host_group: 'foo', display_name: 'FOO' )
46 | puts ''
47 | puts '= delete Hostgroup \'foo\''
48 | puts i.delete_hostgroup( host_group: 'foo' )
49 |
50 | puts ' ------------------------------------------------------------- '
51 | puts ''
52 |
53 | rescue => e
54 | warn( e )
55 | warn( e.backtrace.join("\n") )
56 | end
57 | end
58 |
59 |
60 | # -----------------------------------------------------------------------------
61 |
62 | # EOF
63 |
--------------------------------------------------------------------------------
/examples/hosts.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hosts
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | puts ' ------------------------------------------------------------- '
27 | puts ''
28 | puts ' ==> HOSTS'
29 | puts ''
30 |
31 | puts format( '= count of all hosts : %d', i.hosts_all )
32 | puts format( '= count_hosts_with_problems: %d', i.count_hosts_with_problems)
33 | puts ''
34 |
35 | all, down, critical, unknown, handled, adjusted = i.host_problems.values
36 |
37 | puts '= hosts with problems'
38 | puts format( ' - all : %d', all )
39 | puts format( ' - down : %d', down )
40 | puts format( ' - critical: %d', critical )
41 | puts format( ' - unknown : %d', unknown )
42 | puts format( ' - handled : %d', handled )
43 | puts format( ' - adjusted: %d', adjusted )
44 | puts ''
45 |
46 | puts ''
47 | ['c1-mysql-1', 'bp-foo'].each do |h|
48 |
49 | e = i.exists_host?( h ) ? 'true' : 'false'
50 | puts format( '= check if Host \'%s\' exists : %s', h, e )
51 | end
52 |
53 | puts ''
54 |
55 | puts '= 5 Hosts with Problem '
56 | puts i.list_hosts_with_problems
57 | puts ''
58 |
59 | ['c1-mysql-1', 'bp-foo'].each do |h|
60 | puts format('= list named Hosts \'%s\'', h )
61 | puts i.hosts( name: h )
62 | puts ''
63 | end
64 |
65 | puts ' = add Host \'foo\''
66 |
67 | options = {
68 | name: 'foo',
69 | address: 'foo.bar.com',
70 | display_name: 'test node',
71 | max_check_attempts: 5,
72 | notes: 'test node',
73 | vars: {
74 | description: 'spec test',
75 | os: 'Docker',
76 | partitions: {
77 | '/' => {
78 | crit: '95%',
79 | warn: '90%'
80 | }
81 | }
82 | }
83 | }
84 |
85 | puts i.add_host(options)
86 | puts ''
87 |
88 | puts ' = add Host \'foo\' (again)'
89 | puts i.add_host(options)
90 | puts ''
91 |
92 | puts ' = modify Host \'foo\' with merge vars'
93 | options = {
94 | name: 'foo',
95 | display_name: 'test node (changed)',
96 | max_check_attempts: 10,
97 | notes: 'spec test',
98 | vars: {
99 | description: 'changed at ...'
100 | },
101 | merge_vars: true
102 | }
103 | puts i.modify_host(options)
104 | puts ''
105 |
106 | puts ' = modify Host \'foo\' with overwrite vars'
107 | options = {
108 | name: 'foo',
109 | display_name: 'test node (changed)',
110 | max_check_attempts: 10,
111 | notes: 'spec test',
112 | vars: {
113 | description: 'change and overwrite vars'
114 | }
115 | }
116 | puts i.modify_host(options)
117 | puts ''
118 |
119 | puts ' = delete Host \'test\''
120 | puts i.delete_host( name: 'test' )
121 | puts ''
122 |
123 | puts ' = delete Host \'foo\''
124 | puts i.delete_host( name: 'foo' )
125 | puts ''
126 |
127 | puts ' = delete Host \'foo\' (again)'
128 | puts i.delete_host( name: 'foo' )
129 | puts ''
130 |
131 | puts '= list all Hosts'
132 | puts i.hosts
133 | puts ''
134 |
135 | puts '= list named Hosts \'c1-mysql-1\''
136 | puts i.hosts(name: 'c1-mysql-1')
137 | puts ''
138 |
139 | puts '= list named Hosts \'c1-mysql-1\' (with attrs and filter)'
140 | puts i.hosts(
141 | name: 'c1-mysql-1',
142 | attrs: %w[display_name name address]
143 | )
144 | puts ''
145 |
146 | puts '= host object with attrs and filter'
147 | # Get host name, address of hosts belonging to a specific hostgroup
148 | puts i.host_objects(
149 | attrs: %w[display_name name address],
150 | filter: '"linux-servers" in host.groups'
151 | )
152 |
153 | puts ' ------------------------------------------------------------- '
154 | puts ''
155 |
156 | rescue => e
157 | warn( e )
158 | warn( e.backtrace.join("\n") )
159 | end
160 | end
161 |
162 |
163 | # -----------------------------------------------------------------------------
164 |
165 | # EOF
166 |
--------------------------------------------------------------------------------
/examples/informations.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hostgroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | i.cib_data
27 |
28 | puts ' ------------------------------------------------------------- '
29 | puts ''
30 |
31 | v, r = i.version.values
32 | l, e = i.average_statistics.values
33 | puts format( '= version: %s, revision %s', v, r )
34 | puts format( '= avg_latency: %s, avg_execution_time %s', l, e )
35 | puts format( '= start time: %s', i.start_time )
36 | puts format( '= uptime: %s', i.uptime )
37 | puts format( '= node name: %s', i.node_name )
38 | puts ''
39 |
40 | puts '= icinga2 status'
41 | puts i.status_data
42 | puts ''
43 |
44 | puts '= icinga2 application data'
45 | puts i.application_data
46 | puts ''
47 | puts '= CIB'
48 | puts i.cib_data
49 | puts ''
50 | puts '= API Listener'
51 | puts i.api_listener
52 | puts ''
53 |
54 | puts ' ------------------------------------------------------------- '
55 | puts ''
56 |
57 | rescue => e
58 | warn( e )
59 | warn( e.backtrace.join("\n") )
60 | end
61 | end
62 |
63 |
64 | # -----------------------------------------------------------------------------
65 |
66 | # EOF
67 |
--------------------------------------------------------------------------------
/examples/notifications.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hostgroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | puts ' ------------------------------------------------------------- '
27 | puts ''
28 |
29 | puts ' ==> NOTIFICATIONS'
30 | puts ''
31 | puts '= list all Notifications'
32 | puts i.notifications
33 | puts ''
34 |
35 | ['c1-mysql-1', 'bp-foo'].each do |h|
36 | puts format( '= enable Notifications for \'%s\'', h )
37 | puts i.enable_host_notification( h )
38 | end
39 | puts ''
40 |
41 | ['c1-mysql-1', 'bp-foo'].each do |h|
42 | puts format( '= disable Notifications for \'%s\'', h )
43 | puts i.disable_host_notification( h )
44 | end
45 | puts ''
46 |
47 | ['c1-mysql-1', 'bp-foo'].each do |h|
48 | puts format( '= enable Notifications for \'%s\' and they services', h )
49 | puts i.enable_service_notification( h )
50 | end
51 | puts ''
52 |
53 | ['c1-mysql-1', 'bp-foo'].each do |h|
54 | puts format( '= disable Notifications for \'%s\' and they services', h )
55 | puts i.disable_service_notification( h )
56 | end
57 | puts ''
58 |
59 | puts '= enable Notifications for hostgroup'
60 | puts i.enable_hostgroup_notification( host_group: 'linux-servers')
61 | puts ''
62 |
63 |
64 | puts '= disable Notifications for hostgroup'
65 | puts i.disable_hostgroup_notification( host_group: 'linux-servers')
66 | puts ''
67 |
68 | puts ' ------------------------------------------------------------- '
69 | puts ''
70 |
71 | rescue => e
72 | warn( e )
73 | warn( e.backtrace.join("\n") )
74 | end
75 | end
76 |
77 |
78 | # -----------------------------------------------------------------------------
79 |
80 | # EOF
81 |
--------------------------------------------------------------------------------
/examples/servicegroups.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Servicegroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | puts ' ------------------------------------------------------------- '
27 | puts ''
28 |
29 | puts ' ==> SERVICEGROUPS'
30 | puts ''
31 |
32 | %w[disk foo].each do |h|
33 |
34 | e = i.exists_servicegroup?( h ) ? 'true' : 'false'
35 | puts format( '= check if Servicegroup \'%s\' exists : %s', h, e )
36 | end
37 | puts ''
38 |
39 | %w[disk foo].each do |h|
40 | puts format( '= list named Servicegroup \'%s\':', h )
41 | puts i.servicegroups( service_group: h )
42 | end
43 | puts ''
44 |
45 | puts '= list all Servicegroup'
46 | puts i.servicegroups
47 | puts ''
48 |
49 | puts '= add Servicegroup \'foo\''
50 | puts i.add_servicegroup( service_group: 'foo', display_name: 'FOO' )
51 | puts ''
52 |
53 | puts '= add Servicegroup \'foo\' (again)'
54 | puts i.add_servicegroup( service_group: 'foo', display_name: 'FOO' )
55 | puts ''
56 |
57 | puts '= list named Servicegroup \'foo\''
58 | puts i.servicegroups( service_group: 'foo' )
59 | puts ''
60 |
61 | puts '= delete Servicegroup \'foo\''
62 | puts i.delete_servicegroup( service_group: 'foo' )
63 | puts ''
64 |
65 | puts '= delete Servicegroup \'foo\' (again)'
66 | puts i.delete_servicegroup( service_group: 'foo' )
67 | puts ''
68 |
69 | puts ' ------------------------------------------------------------- '
70 | puts ''
71 |
72 | rescue => e
73 | warn( e )
74 | warn( e.backtrace.join("\n") )
75 | end
76 | end
77 |
78 |
79 | # -----------------------------------------------------------------------------
80 |
81 | # EOF
82 |
--------------------------------------------------------------------------------
/examples/services.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hostgroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | puts ' ------------------------------------------------------------- '
27 | puts ''
28 |
29 | puts ' ==> SERVICES'
30 | puts ''
31 |
32 | puts '= service objects'
33 | puts i.service_objects
34 | puts ''
35 |
36 | puts '= service objects with \'attrs\' and \'joins\''
37 | puts i.service_objects(
38 | attrs: %w[name state],
39 | joins: ['host.name','host.state']
40 | )
41 | puts ''
42 |
43 | puts '= service objects with \'attrs\', \'filter\' and \'joins\''
44 | puts ' match host.address = 1.2.3.4'
45 | puts i.service_objects(
46 | attrs: %w[display_name check_command],
47 | filter: 'match("1.2.3.4", host.address)',
48 | joins: ['host.name','host.address']
49 | )
50 | puts ''
51 |
52 | # Get all services in critical state and filter out the ones for which active checks are disabled
53 | # service.states - 0 = OK, 1 = WARNING, 2 = CRITICAL
54 | #
55 | # { "joins": ["host.name", "host.address"], "filter": "service.state==2", "attrs": ["display_name", "check_command", "enable_active_checks"] }
56 | puts '= service objects with \'attrs\', \'filter\' and \'joins\''
57 | puts ' filter service.sate == 1'
58 | puts i.service_objects(
59 | attrs: %w[display_name check_command enable_active_checks],
60 | filter: 'service.state == 1' ,
61 | joins: ['host.name', 'host.address']
62 | )
63 | puts ''
64 |
65 | puts '= unhandled services'
66 | puts i.unhandled_services
67 | puts ''
68 |
69 | puts format( '= count of all services: %s', i.services_all )
70 | puts ''
71 |
72 | puts format( '= count of services with problems: %d', i.count_services_with_problems)
73 | puts ''
74 |
75 | all, warning, critical, unknown, pending, in_downtime, acknowledged,
76 | adjusted_warning, adjusted_critical, adjusted_unknown,
77 | handled_all, handled_warning, handled_critical, handled_unknown = i.service_problems.values
78 |
79 | puts '= services with problems'
80 | puts i.service_problems
81 | puts format( ' - all : %d', all )
82 | puts format( ' - warning : %d', warning )
83 | puts format( ' - critical : %d', critical )
84 | puts format( ' - unknown : %d', unknown )
85 | puts format( ' - pending : %d', pending )
86 | puts format( ' - in_downtime : %d', in_downtime )
87 | puts format( ' - acknowledged : %d', acknowledged )
88 | puts format( ' - adj. warning : %d', adjusted_warning )
89 | puts format( ' - adj. critical : %d', adjusted_critical )
90 | puts format( ' - adj. unknown : %d', adjusted_unknown )
91 | puts format( ' - handled all : %d', handled_all )
92 | puts format( ' - handled warning : %d', handled_warning )
93 | puts format( ' - handled critical: %d', handled_critical )
94 | puts format( ' - handled unknown : %d', handled_unknown )
95 | puts ''
96 |
97 | puts '= check if Service exists'
98 | ['c1-mysql-1', 'bp-foo'].each do |h|
99 | e = i.exists_service?( host_name: h, name: 'ssh' ) ? 'true' : 'false'
100 | puts format( ' - Service \'ssh\' for Host \'%s\' : %s', h, e )
101 | end
102 | puts ''
103 | ['c1-mysql-1', 'bp-foo'].each do |h|
104 | e = i.exists_service?( host_name: h, name: 'hdb' ) ? 'true' : 'false'
105 | puts format( ' - Service \'hdb\' for Host \'%s\' : %s', h, e )
106 | end
107 | puts ''
108 |
109 | puts '= 5 Services with Problems'
110 |
111 | problems, problems_and_severity = i.list_services_with_problems.values
112 |
113 | puts format( ' - problems: %s', problems )
114 | puts format( ' - problems and severity: %s', problems_and_severity )
115 | puts ''
116 |
117 | puts '= add service'
118 | puts i.add_service(
119 | host_name: 'c1-mysql-1',
120 | name: 'http2',
121 | check_command: 'http',
122 | check_interval: 10,
123 | retry_interval: 30,
124 | vars: {
125 | http_address: '127.0.0.1',
126 | http_url: '/access/index',
127 | http_port: 80
128 | }
129 | )
130 |
131 | puts '= add service (again)'
132 | puts i.add_service(
133 | host_name: 'c1-mysql-1',
134 | name: 'http2',
135 | check_command: 'http',
136 | check_interval: 10,
137 | retry_interval: 30,
138 | vars: {
139 | http_address: '127.0.0.1',
140 | http_url: '/access/index',
141 | http_port: 80
142 | }
143 | )
144 |
145 | puts '= modify service'
146 | puts i.modify_service(
147 | name: 'http2',
148 | check_interval: 60,
149 | retry_interval: 10,
150 | vars: {
151 | http_url: '/access/login' ,
152 | http_address: '10.41.80.63'
153 | }
154 | )
155 |
156 | puts '= delete service'
157 | puts i.delete_service(host_name: 'c1-mysql-1', name: 'http2' )
158 |
159 | puts '= delete service (again)'
160 | puts i.delete_service(host_name: 'c1-mysql-1', name: 'http2' )
161 |
162 | puts ''
163 | puts '= list named Service \'ping4\' from Host \'icinga2\''
164 | puts i.services( host_name: 'c1-mysql-1', service: 'ping4' )
165 | puts ''
166 | puts '= list all Services'
167 | puts i.services
168 |
169 | puts ' ------------------------------------------------------------- '
170 | puts ''
171 |
172 | rescue => e
173 | warn( e )
174 | warn( e.backtrace.join("\n") )
175 | end
176 | end
177 |
178 |
179 | # -----------------------------------------------------------------------------
180 |
181 | # EOF
182 |
--------------------------------------------------------------------------------
/examples/statistics.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hostgroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | i.cib_data
27 |
28 | puts ' ------------------------------------------------------------- '
29 | puts ''
30 |
31 | latency, execution_time = i.average_statistics.values
32 |
33 | puts format( '= latency: %s', latency )
34 | puts format( '= execution_time: %s', execution_time )
35 | puts ''
36 |
37 | interval_stats = i.interval_statistics
38 | host_stats = i.host_statistics
39 | service_stats = i.service_statistics
40 | work_queue_stats = i.work_queue_statistics
41 |
42 | hosts_active_checks = interval_stats.dig(:hosts_active_checks)
43 | hosts_passive_checks = interval_stats.dig(:hosts_passive_checks)
44 | services_active_checks = interval_stats.dig(:services_active_checks)
45 | services_passive_checks = interval_stats.dig(:services_passive_checks)
46 |
47 | host_stats_up = host_stats.dig(:up)
48 | host_stats_down = host_stats.dig(:down)
49 | host_stats_pending = host_stats.dig(:pending)
50 | host_stats_unreachable = host_stats.dig(:unreachable)
51 | host_stats_in_downtime = host_stats.dig(:in_downtime)
52 | host_stats_acknowledged = host_stats.dig(:acknowledged)
53 |
54 | service_stats_ok = service_stats.dig(:ok)
55 | service_stats_warning = service_stats.dig(:warning)
56 | service_stats_critical = service_stats.dig(:critical)
57 | service_stats_unknown = service_stats.dig(:unknown)
58 | service_stats_pending = service_stats.dig(:pending)
59 | service_stats_in_downtime = service_stats.dig(:in_downtime)
60 | service_stats_acknowledged = service_stats.dig(:acknowledged)
61 |
62 | puts format( '= hosts')
63 | puts format( ' active checks : %s', hosts_active_checks )
64 | puts format( ' passive checks: %s', hosts_passive_checks )
65 | puts ''
66 | puts format( '= host statistics')
67 | puts format( ' up : %s', host_stats_up )
68 | puts format( ' down : %s', host_stats_down )
69 | puts format( ' pending : %s', host_stats_pending )
70 | puts format( ' unreachable : %s', host_stats_unreachable )
71 | puts format( ' in downtime : %s', host_stats_in_downtime )
72 | puts format( ' acknowledged : %s', host_stats_acknowledged )
73 | puts ''
74 |
75 | puts format( '= services')
76 | puts format( ' active checks : %s', services_active_checks )
77 | puts format( ' passive checks: %s', services_passive_checks )
78 | puts ''
79 | puts format( '= service statistics')
80 | puts format( ' ok : %s', service_stats_ok )
81 | puts format( ' warning : %s', service_stats_warning )
82 | puts format( ' critical : %s', service_stats_critical )
83 | puts format( ' unknown : %s', service_stats_unknown )
84 | puts format( ' pending : %s', service_stats_pending )
85 | puts format( ' in downtime : %s', service_stats_in_downtime )
86 | puts format( ' acknowledged : %s', service_stats_acknowledged )
87 | puts ''
88 | puts format( '= workqueue statistics')
89 |
90 | work_queue_stats.each do |k,v|
91 | puts format(' %s : %s', k, v )
92 | end
93 | puts ''
94 |
95 | puts ' ------------------------------------------------------------- '
96 | puts ''
97 |
98 | rescue => e
99 | warn( e )
100 | warn( e.backtrace.join("\n") )
101 | end
102 | end
103 |
104 |
105 | # -----------------------------------------------------------------------------
106 |
107 | # EOF
108 |
109 |
--------------------------------------------------------------------------------
/examples/test.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 23.01.2017 - Bodo Schulz
5 | #
6 | #
7 | # v0.9.2
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 | begin
24 | # examples from: https://github.com/saurabh-hirani/icinga2-api-examples
25 | #
26 | # Get display_name, check_command attribute for services applied for filtered hosts matching host.address == 1.2.3.4.
27 | # Join the output with the hosts on which these checks run (services are applied to hosts)
28 | #
29 | puts i.service_objects(
30 | attrs: %w[display_name check_command],
31 | filter: 'match("1.2.3.4",host.address)' ,
32 | joins: ['host.name', 'host.address']
33 | )
34 | puts ''
35 | # Get all services in critical state and filter out the ones for which active checks are disabled
36 | # service.states - 0 = OK, 1 = WARNING, 2 = CRITICAL
37 | #
38 | # { "joins": ['host.name', 'host.address'], "filter": "service.state==2", "attrs": ['display_name', 'check_command', 'enable_active_checks'] }
39 | puts i.service_objects(
40 | attrs: %w[display_name check_command enable_active_checks],
41 | filter: 'service.state==1',
42 | joins: ['host.name', 'host.address']
43 | )
44 | puts ''
45 | # Get host name, address of hosts belonging to a specific hostgroup
46 | puts i.host_objects(
47 | attrs: %w[display_name name address],
48 | filter: '"windows-servers" in host.groups'
49 | )
50 |
51 | rescue => e
52 | warn( e )
53 | warn( e.backtrace.join("\n") )
54 | end
55 | end
56 |
57 |
58 | # -----------------------------------------------------------------------------
59 |
60 | # EOF
61 |
--------------------------------------------------------------------------------
/examples/usergroups.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hostgroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | puts ' ------------------------------------------------------------- '
27 | puts ''
28 |
29 | puts ' ==> USERGROUPS'
30 | puts ''
31 |
32 | ['icingaadmins', 'linux-admins'].each do |h|
33 | e = i.exists_usergroup?( h ) ? 'true' : 'false'
34 | puts format( '= check if Usergroup \'%s\' exists : %s', h, e )
35 | end
36 | puts ''
37 |
38 | puts '= add Usergroup \'foo\''
39 | puts i.add_usergroup( user_group: 'foo', display_name: 'FOO' )
40 | puts ''
41 |
42 | puts 'list named Usergroup \'foo\''
43 | puts i.usergroups( user_group: 'foo' )
44 | puts ''
45 |
46 | puts '= delete Usergroup \'foo\''
47 | puts i.delete_usergroup( user_group: 'foo' )
48 | puts ''
49 |
50 |
51 | puts 'list all Usergroup'
52 | puts i.usergroups
53 | puts ''
54 | puts ' ------------------------------------------------------------- '
55 | puts ''
56 |
57 | rescue => e
58 | warn( e )
59 | warn( e.backtrace.join("\n") )
60 | end
61 | end
62 |
63 |
64 | # -----------------------------------------------------------------------------
65 |
66 | # EOF
67 |
--------------------------------------------------------------------------------
/examples/users.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # 07.10.2017 - Bodo Schulz
5 | #
6 | #
7 | # Examples for Hostgroups
8 |
9 | # -----------------------------------------------------------------------------
10 |
11 | require_relative '../lib/icinga2'
12 | require_relative 'config'
13 |
14 | # -----------------------------------------------------------------------------
15 |
16 | i = Icinga2::Client.new( @config )
17 |
18 | unless( i.nil? )
19 |
20 | # run tests ...
21 | #
22 | #
23 |
24 | begin
25 |
26 | puts ' ------------------------------------------------------------- '
27 | puts ''
28 |
29 | puts ' ==> USERS'
30 | puts ''
31 |
32 | ['icingaadmin', 'icinga-admin'].each do |h|
33 | e = i.exists_user?( h ) ? 'true' : 'false'
34 | puts format( '= check if User \'%s\' exists : %s', h, e )
35 | end
36 | puts ''
37 |
38 | puts '= add User \'foo\''
39 | puts i.add_user( user_name: 'foo', display_name: 'FOO', email: 'foo@bar.com', pager: '0000', groups: ['icingaadmins'] )
40 | puts ''
41 | puts '= add User \'foo\' (again)'
42 | puts i.add_user( user_name: 'foo', display_name: 'FOO', email: 'foo@bar.com', pager: '0000', groups: ['icingaadmins'] )
43 | puts ''
44 |
45 | puts '= list named User \'foo\''
46 | puts i.users( user_name: 'foo' )
47 | puts ''
48 |
49 | puts '= delete User \'foo\''
50 | puts i.delete_user( user_name: 'foo' )
51 | puts ''
52 |
53 | puts '= list all User'
54 | puts i.users
55 | puts ''
56 |
57 | puts ' ------------------------------------------------------------- '
58 | puts ''
59 |
60 | rescue => e
61 | warn( e )
62 | warn( e.backtrace.join("\n") )
63 | end
64 | end
65 |
66 |
67 | # -----------------------------------------------------------------------------
68 |
69 | # EOF
70 |
--------------------------------------------------------------------------------
/icinga2.gemspec:
--------------------------------------------------------------------------------
1 |
2 | lib = File.expand_path('../lib', __FILE__)
3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 | require 'icinga2/version'
5 |
6 | Gem::Specification.new do |s|
7 |
8 | s.name = 'icinga2'
9 | s.version = Icinga2::VERSION
10 | s.date = '2018-03-29'
11 | s.summary = 'Ruby SDK for easly access to the Icinga2 API'
12 | s.description = 'An enhanced ruby gem to communicate with Icinga2 API.' +
13 | 'It\'s allowed create small applications to connect to Icinga2 to add Hosts, Services,' +
14 | 'User and so on.'
15 | s.authors = ['Bodo Schulz']
16 | s.email = 'bodo@boone-schulz.de'
17 |
18 | s.files = Dir[
19 | 'README.md',
20 | 'LICENSE',
21 | 'lib/**/*',
22 | 'spec/*',
23 | 'doc/*.md',
24 | 'examples/*.rb'
25 | ]
26 |
27 | s.homepage = 'https://github.com/bodsch/ruby-icinga2'
28 | s.license = 'LGPL-2.1+'
29 |
30 | begin
31 |
32 | if( RUBY_VERSION >= '2.0' )
33 | s.required_ruby_version = '~> 2.0'
34 | elsif( RUBY_VERSION <= '2.1' )
35 | s.required_ruby_version = '~> 2.1'
36 | elsif( RUBY_VERSION <= '2.2' )
37 | s.required_ruby_version = '~> 2.2'
38 | elsif( RUBY_VERSION <= '2.3' )
39 | s.required_ruby_version = '~> 2.3'
40 | end
41 |
42 | s.add_dependency('ruby_dig', '~> 0') if RUBY_VERSION < '2.3'
43 |
44 | s.add_dependency('openssl', '~> 2.0') if RUBY_VERSION >= '2.3'
45 | rescue => e
46 | warn "#{$PROGRAM_NAME}: #{e}"
47 | exit!
48 | end
49 |
50 | s.add_dependency('json', '~> 2.1')
51 | s.add_dependency('rest-client', '~> 2.0')
52 |
53 | s.add_development_dependency('rake', '~> 0')
54 | s.add_development_dependency('rake-notes', '~> 0')
55 | s.add_development_dependency('rubocop', '~> 0.49.0')
56 | s.add_development_dependency('rubocop-checkstyle_formatter', '~> 0')
57 | s.add_development_dependency('rspec', '~> 0')
58 | s.add_development_dependency('rspec_junit_formatter', '~> 0')
59 | s.add_development_dependency('rspec-nc', '~> 0')
60 | s.add_development_dependency('guard', '~> 0')
61 | s.add_development_dependency('guard-rspec', '~> 0')
62 | s.add_development_dependency('pry', '~> 0')
63 | s.add_development_dependency('pry-remote', '~> 0')
64 | s.add_development_dependency('pry-nav', '~> 0')
65 |
66 | end
67 |
--------------------------------------------------------------------------------
/lib/icinga2.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'ruby_dig' if RUBY_VERSION < '2.3'
4 |
5 | require 'rest-client'
6 | require 'openssl'
7 |
8 | require 'json'
9 | require 'net/http'
10 | require 'uri'
11 |
12 | require_relative 'logging'
13 | require_relative 'monkey_patches'
14 | require_relative 'icinga2/client'
15 |
16 | module Icinga2
17 | end
18 |
--------------------------------------------------------------------------------
/lib/icinga2/actions.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: false
3 |
4 | module Icinga2
5 |
6 | # namespace for action handling
7 | #
8 | # There are several actions available for Icinga 2 provided by the /v1/actions URL endpoint.
9 | #
10 | #
11 | # original API Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#actions
12 | #
13 | module Actions
14 |
15 | # Process a check result for a host or a service.
16 | #
17 | # FUNCTION IS NOT IMPLEMENTED YET
18 | #
19 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#process-check-result
20 | #
21 | # @param [Hash] params
22 | # @option params [Integer] exit_status For services: 0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN, for hosts: 0=OK, 1=CRITICAL.
23 | # @option params [String] plugin_output One or more lines of the plugin main output. Does not contain the performance data.
24 | # @option params [Array] performance_data The performance data.
25 | # @option params [Array] check_command The first entry should be the check commands path, then one entry for each command line option followed by an entry for each of its argument.
26 | # @option params [String] check_source Usually the name of the command_endpoint
27 | # @option params [Integer] execution_start The timestamp where a script/process started its execution.
28 | # @option params [Integer] execution_end The timestamp where a script/process ended its execution. This timestamp is used in features to determine e.g. the metric timestamp.
29 | # @option params [String] host_name
30 | # @option params [String] service_name
31 | # @option params [String] type
32 | # @option params [String] filter
33 | #
34 | # @example
35 | # params = {
36 | # host_name: 'example.localdomain',
37 | # service_name: 'passive-ping6',
38 | # exit_status: 2,
39 | # plugin_output: 'PING CRITICAL - Packet loss = 100%',
40 | # performance_data: [
41 | # 'rta=5000.000000ms;3000.000000;5000.000000;0.000000',
42 | # 'pl=100%;80;100;0'
43 | # ],
44 | # check_source: 'example.localdomain'
45 | # }
46 | # process_check_result(params)
47 | #
48 | # params = {
49 | # exit_status: 1,
50 | # plugin_output: 'Host is not available.',
51 | # type: 'Host',
52 | # filter: 'host.name == "example.localdomain"'
53 | # }
54 | # process_check_result(params)
55 | #
56 | # @return [Hash] result
57 | #
58 | # def process_check_result(params)
59 | #
60 | # raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
61 | # raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
62 | #
63 | # # exit_status = validate( params, required: true, var: 'exit_status', type: Integer )
64 | # # plugin_output = validate( params, required: true, var: 'plugin_output', type: String )
65 | # # performance_data = validate( params, required: false, var: 'performance_data', type: Array )
66 | # # check_command = validate( params, required: false, var: 'check_command', type: Array )
67 | # # check_source = validate( params, required: false, var: 'check_source', type: String )
68 | # # execution_start = validate( params, required: false, var: 'execution_start', type: Integer )
69 | # # execution_end = validate( params, required: false, var: 'execution_end', type: String )
70 | #
71 | # end
72 |
73 | #
74 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#reschedule-check
75 | # def reschedule_check(params)
76 | #
77 | # # $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/reschedule-check' \
78 | # # -d '{ "type": "Service", "filter": "service.name==\"ping6\"" }' | python -m json.tool
79 | # end
80 |
81 | #
82 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#send-custom-notification
83 | # def send_custom_notification
84 | # end
85 |
86 | #
87 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#delay-notification
88 | # def delay_notification
89 | # end
90 |
91 | #
92 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#acknowledge-problem
93 | # def acknowledge_problem
94 | # end
95 |
96 | #
97 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#remove-acknowledgement
98 | # def remove_acknowledgement
99 | # end
100 |
101 | #
102 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#add-comment
103 | # def add_comment
104 | # end
105 |
106 | #
107 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#remove-comment
108 | # def remove_comment
109 | # end
110 |
111 | #
112 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#schedule-downtime
113 | # def schedule_downtime
114 | # end
115 |
116 | # Shuts down Icinga2.
117 | #
118 | # @example
119 | # shutdown_process
120 | #
121 | # @return [Hash]
122 | #
123 | def shutdown_process
124 | post(
125 | url: format('%s/actions/shutdown-process', @icinga_api_url_base),
126 | headers: @headers,
127 | options: @options
128 | )
129 | end
130 |
131 | # Restarts Icinga2.
132 | #
133 | # @example
134 | # restart_process
135 | #
136 | # @return [Hash]
137 | #
138 | def restart_process
139 | post(
140 | url: format('%s/actions/restart-process', @icinga_api_url_base),
141 | headers: @headers,
142 | options: @options
143 | )
144 | end
145 |
146 | #
147 | # original Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#generate-ticket
148 | # def generate_ticket
149 | # end
150 |
151 | end
152 | end
153 |
--------------------------------------------------------------------------------
/lib/icinga2/client.rb:
--------------------------------------------------------------------------------
1 |
2 | require_relative 'version'
3 | require_relative 'validator'
4 | require_relative 'network'
5 | require_relative 'statistics'
6 | require_relative 'converts'
7 | require_relative 'tools'
8 | require_relative 'downtimes'
9 | require_relative 'notifications'
10 | require_relative 'hosts'
11 | require_relative 'hostgroups'
12 | require_relative 'services'
13 | require_relative 'servicegroups'
14 | require_relative 'users'
15 | require_relative 'usergroups'
16 | require_relative 'configuration_management'
17 | require_relative 'actions'
18 |
19 | # -------------------------------------------------------------------------------------------------------------------
20 | #
21 | # @abstract # Namespace for classes and modules that handle all Icinga2 API calls
22 | #
23 | # @author Bodo Schulz
24 | #
25 | #
26 | module Icinga2
27 |
28 | # static variable for hosts down
29 | HOSTS_DOWN = 1
30 | # static variable for hosts critical
31 | HOSTS_CRITICAL = 2
32 | # static variable for hosts unknown
33 | HOSTS_UNKNOWN = 3
34 |
35 | # static variables for handled warning
36 | SERVICE_STATE_WARNING = 1
37 | # static variables for handled critical
38 | SERVICE_STATE_CRITICAL = 2
39 | # static variables for handled unknown
40 | SERVICE_STATE_UNKNOWN = 3
41 |
42 | # Abstract base class for the API calls.
43 | # Provides some helper methods
44 | #
45 | # @author Bodo Schulz
46 | #
47 | class Client
48 |
49 | include Logging
50 |
51 | include Icinga2::Validator
52 | include Icinga2::Network
53 | include Icinga2::Statistics
54 | include Icinga2::Converts
55 | include Icinga2::Tools
56 | include Icinga2::Downtimes
57 | include Icinga2::Notifications
58 | include Icinga2::Hosts
59 | include Icinga2::Hostgroups
60 | include Icinga2::Services
61 | include Icinga2::Servicegroups
62 | include Icinga2::Users
63 | include Icinga2::Usergroups
64 | include Icinga2::ConfigurationManagement
65 | include Icinga2::Actions
66 |
67 | # Returns a new instance of Client
68 | #
69 | # @param [Hash, #read] settings the settings for Icinga2
70 | # @option settings [String] host the Icinga2 Hostname
71 | # @option settings [Integer] port (5665) the Icinga2 API Port
72 | # @option settings [String] username the Icinga2 API User
73 | # @option settings [String] password the Icinga2 API Password
74 | # @option settings [Integer] version (1) the Icinga2 API Version
75 | # @option settings [String] pki_path the location of the Certificate Files
76 | # @option settings [String] node_name overwrite the Icnag2 hostname for the PKI. if the node_name no set, we try to resolve with gethostbyname()
77 | #
78 | # @example to create an new Instance
79 | # config = {
80 | # icinga: {
81 | # host: '192.168.33.5',
82 | # api: {
83 | # username: 'root',
84 | # password: 'icinga',
85 | # version: 1
86 | # }
87 | # }
88 | # }
89 | # @icinga = Icinga2::Client.new(config)
90 | #
91 | # @return [instance, #read]
92 | #
93 | def initialize( settings )
94 |
95 | raise ArgumentError.new(format('wrong type. \'settings\' must be an Hash, given \'%s\'', settings.class.to_s)) unless( settings.is_a?(Hash) )
96 | raise ArgumentError.new('missing settings') if( settings.size.zero? )
97 |
98 | icinga_host = settings.dig(:icinga, :host)
99 | icinga_api_port = settings.dig(:icinga, :api, :port) || 5665
100 | icinga_api_user = settings.dig(:icinga, :api, :username)
101 | icinga_api_pass = settings.dig(:icinga, :api, :password)
102 | icinga_api_version = settings.dig(:icinga, :api, :version) || 1
103 | icinga_api_pki_path = settings.dig(:icinga, :api, :pki_path)
104 | icinga_api_node_name = settings.dig(:icinga, :api, :node_name)
105 |
106 | @last_call_timeout = 320
107 | @last_cib_data_called = 0
108 | @last_status_data_called = 0
109 | @last_application_data_called = 0
110 | @last_service_objects_called = 0
111 | @last_host_objects_called = 0
112 |
113 | @icinga_api_url_base = format( 'https://%s:%d/v%s', icinga_host, icinga_api_port, icinga_api_version )
114 |
115 | _has_cert, @options = cert?(
116 | pki_path: icinga_api_pki_path,
117 | node_name: icinga_api_node_name,
118 | username: icinga_api_user,
119 | password: icinga_api_pass
120 | )
121 |
122 | @headers = { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }
123 | end
124 |
125 | # create a HTTP Header based on a Icinga2 Certificate or an User API Login
126 | #
127 | # @param [Hash, #read] params
128 | # @option params [String] pki_path the location of the Certificate Files
129 | # @option params [String] node_name the Icinga2 Hostname
130 | # @option params [String] user the Icinga2 API User
131 | # @option params [String] password the Icinga2 API Password
132 | #
133 | # @example with Certificate
134 | # cert?(pki_path: '/etc/icinga2', node_name: 'icinga2-dashing')
135 | #
136 | # @example with User
137 | # cert?(username: 'root', password: 'icinga')
138 | #
139 | # @return [Array]
140 | #
141 | def cert?( params )
142 |
143 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
144 | raise ArgumentError.new('missing params') if( params.size.zero? )
145 |
146 | pki_path = params.dig(:pki_path)
147 | node_name = params.dig(:node_name)
148 | username = params.dig(:username)
149 | password = params.dig(:password)
150 |
151 | if( node_name.nil? )
152 | begin
153 | node_name = Socket.gethostbyname(Socket.gethostname).first
154 | logger.debug(format('node name: %s', node_name))
155 | rescue SocketError => e
156 | raise format("can't resolve hostname (%s)", e)
157 | end
158 | end
159 |
160 | ssl_cert_file = format( '%s/%s.crt', pki_path, node_name )
161 | ssl_key_file = format( '%s/%s.key', pki_path, node_name )
162 | ssl_ca_file = format( '%s/ca.crt', pki_path )
163 |
164 | if( File.file?( ssl_cert_file ) && File.file?( ssl_key_file ) && File.file?( ssl_ca_file ) )
165 |
166 | logger.debug( 'PKI found, using client certificates for connection to Icinga 2 API' )
167 |
168 | ssl_cert_file = File.read( ssl_cert_file )
169 | ssl_key_file = File.read( ssl_key_file )
170 | ssl_ca_file = File.read( ssl_ca_file )
171 |
172 | cert = OpenSSL::X509::Certificate.new( ssl_cert_file )
173 | key = OpenSSL::PKey::RSA.new( ssl_key_file )
174 |
175 | [true, {
176 | ssl_client_cert: cert,
177 | ssl_client_key: key,
178 | ssl_ca_file: ssl_ca_file,
179 | verify_ssl: OpenSSL::SSL::VERIFY_NONE
180 | } ]
181 |
182 | else
183 | logger.debug( 'PKI not found, using basic auth for connection to Icinga 2 API' )
184 |
185 | raise ArgumentError.new('Missing \'username\'') if( username.nil? )
186 | raise ArgumentError.new('Missing \'password\'') if( password.nil? )
187 |
188 | [false, {
189 | user: username,
190 | password: password,
191 | verify_ssl: OpenSSL::SSL::VERIFY_NONE
192 | } ]
193 | end
194 | end
195 |
196 | # return Icinga2 Application data
197 | #
198 | # @example
199 | # application_data
200 | #
201 | # @return [Hash]
202 | #
203 | def application_data
204 |
205 | data = icinga_application_data(
206 | url: format( '%s/status/IcingaApplication', @icinga_api_url_base ),
207 | headers: @headers,
208 | options: @options
209 | )
210 |
211 | return nil if( data.nil? )
212 | return nil unless(data.is_a?(Hash))
213 |
214 | app_data = data.dig('icingaapplication','app')
215 |
216 | # version and revision
217 | @version, @revision = parse_version(app_data.dig('version'))
218 | # - node_name
219 | @node_name = app_data.dig('node_name')
220 | # - start_time
221 | @start_time = Time.at(app_data.dig('program_start').to_f)
222 |
223 | data
224 | end
225 |
226 | # return Icinga2 CIB
227 | #
228 | # @example
229 | # cib_data
230 | #
231 | # @return [Hash]
232 | #
233 | def cib_data
234 |
235 | data = icinga_application_data(
236 | url: format( '%s/status/CIB', @icinga_api_url_base ),
237 | headers: @headers,
238 | options: @options
239 | )
240 |
241 | return nil if( data.nil? )
242 |
243 | @last_cib_data_called = 0 #Time.now.to_i
244 |
245 | if( data.is_a?(Hash))
246 |
247 | cib_data = data.clone
248 |
249 | # extract
250 | # - uptime
251 | uptime = cib_data.dig('uptime').round(2)
252 | @uptime = Time.at(uptime).utc.strftime('%H:%M:%S')
253 | # - avg_latency / avg_execution_time
254 | @avg_latency = cib_data.dig('avg_latency').round(2)
255 | @avg_execution_time = cib_data.dig('avg_execution_time').round(2)
256 |
257 | # - hosts
258 | @hosts_up = cib_data.dig('num_hosts_up').to_i
259 | @hosts_down = cib_data.dig('num_hosts_down').to_i
260 | @hosts_pending = cib_data.dig('num_hosts_pending').to_i
261 | @hosts_unreachable = cib_data.dig('num_hosts_unreachable').to_i
262 | @hosts_in_downtime = cib_data.dig('num_hosts_in_downtime').to_i
263 | @hosts_acknowledged = cib_data.dig('num_hosts_acknowledged').to_i
264 |
265 | # - services
266 | @services_ok = cib_data.dig('num_services_ok').to_i
267 | @services_warning = cib_data.dig('num_services_warning').to_i
268 | @services_critical = cib_data.dig('num_services_critical').to_i
269 | @services_unknown = cib_data.dig('num_services_unknown').to_i
270 | @services_pending = cib_data.dig('num_services_pending').to_i
271 | @services_in_downtime = cib_data.dig('num_services_in_downtime').to_i
272 | @services_acknowledged = cib_data.dig('num_services_acknowledged').to_i
273 |
274 | # - check stats
275 | @hosts_active_checks_1min = cib_data.dig('active_host_checks_1min')
276 | @hosts_passive_checks_1min = cib_data.dig('passive_host_checks_1min')
277 | @services_active_checks_1min = cib_data.dig('active_service_checks_1min')
278 | @services_passive_checks_1min = cib_data.dig('passive_service_checks_1min')
279 |
280 | end
281 |
282 | data
283 | end
284 |
285 | # return Icinga2 Status Data
286 | #
287 | # @example
288 | # status_data
289 | #
290 | # @return [Hash]
291 | #
292 | def status_data
293 |
294 | @last_status_data_called = Time.now.to_i
295 |
296 | icinga_application_data(
297 | url: format( '%s/status', @icinga_api_url_base ),
298 | headers: @headers,
299 | options: @options
300 | )
301 | end
302 |
303 | # return Icinga2 API Listener
304 | #
305 | # @example
306 | # api_listener
307 | #
308 | # @return [Hash]
309 | #
310 | def api_listener
311 |
312 | @last_application_data_called = Time.now.to_i
313 |
314 | icinga_application_data(
315 | url: format( '%s/status/ApiListener', @icinga_api_url_base ),
316 | headers: @headers,
317 | options: @options
318 | )
319 | end
320 |
321 | # check the availability of a Icinga network connect
322 | #
323 | # @example
324 | # available?
325 | #
326 | # @return [Bool]
327 | #
328 | def available?
329 |
330 | data = application_data
331 |
332 | return true unless( data.nil? )
333 |
334 | false
335 | end
336 |
337 | # return Icinga2 version and revision
338 | #
339 | # @example
340 | # version.values
341 | #
342 | # v = version
343 | # version = v.dig(:version)
344 | #
345 | # @return [Hash]
346 | # * version
347 | # * revision
348 | #
349 | def version
350 |
351 | application_data if((Time.now.to_i - @last_application_data_called).to_i > @last_call_timeout)
352 |
353 | version = @version.nil? ? 0 : @version
354 | revision = @revision.nil? ? 0 : @revision
355 |
356 | {
357 | version: version.to_s,
358 | revision: revision.to_s
359 | }
360 | end
361 |
362 | # return Icinga2 node_name
363 | #
364 | # @example
365 | # node_name
366 | #
367 | # @return [String]
368 | #
369 | def node_name
370 |
371 | application_data if((Time.now.to_i - @last_application_data_called).to_i > @last_call_timeout)
372 |
373 | return @node_name if( @node_name )
374 |
375 | nil
376 | end
377 |
378 | # return Icinga2 start time
379 | #
380 | # @example
381 | # start_time
382 | #
383 | # @return [String]
384 | #
385 | def start_time
386 |
387 | application_data if((Time.now.to_i - @last_application_data_called).to_i > @last_call_timeout)
388 |
389 | return @start_time if( @start_time )
390 |
391 | nil
392 | end
393 |
394 | # return Icinga2 uptime
395 | #
396 | # @example
397 | # cib_data
398 | # uptime
399 | #
400 | # @return [String]
401 | #
402 | def uptime
403 |
404 | cib_data if((Time.now.to_i - @last_cib_data_called).to_i > @last_call_timeout)
405 |
406 | return @uptime if( @uptime )
407 |
408 | nil
409 | end
410 |
411 | end
412 | end
413 |
--------------------------------------------------------------------------------
/lib/icinga2/configuration_management.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 |
4 | module Icinga2
5 |
6 | # namespace for config packages
7 | #
8 | # The main idea behind configuration management is to allow external applications creating configuration packages and stages based on configuration files and directory trees.
9 | #
10 | # This replaces any additional SSH connection and whatnot to dump configuration files to Icinga 2 directly.
11 | #
12 | # In case you are pushing a new configuration stage to a package, Icinga 2 will validate the configuration asynchronously and populate a status log which can be fetched in a separated request.
13 | #
14 | # original API Documentation: https://www.icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#configuration-management
15 | #
16 | module ConfigurationManagement
17 |
18 | # create a new empty configuration package.
19 | #
20 | # Package names starting with an underscore are reserved for internal packages and can not be used.
21 | #
22 | # @param [String] name the name for the new package.
23 | #
24 | # @example
25 | # create_config_package('cfg-package')
26 | #
27 | # @return [Hash]
28 | #
29 | def create_config_package(name)
30 |
31 | raise ArgumentError.new(format('wrong type. \'name\' must be an String, given \'%s\'', name.class.to_s)) unless( name.is_a?(String) )
32 | raise ArgumentError.new('missing \'name\'') if( name.size.zero? )
33 |
34 | return { 'code' => 404, 'name' => name, 'status' => 'Package names starting with an underscore are reserved for internal packages and can not be used.' } if( name.initial == '_' )
35 |
36 | post(
37 | url: format( '%s/config/packages/%s', @icinga_api_url_base, name ),
38 | headers: @headers,
39 | options: @options
40 | )
41 | end
42 |
43 | # Configuration files in packages are managed in stages.
44 | # Stages provide a way to maintain multiple configuration versions for a package.
45 | #
46 | # @param [Hash] params
47 | # @option params [String] package name of the package
48 | # @option params [String] name name for the package
49 | # @option params [Bool] cluser (false) package for an satellite
50 | # @option params [Bool] reload (true) reload icinga2 after upload
51 | # @option params [String] vars
52 | #
53 | # @example
54 | # params = {
55 | # package: 'cfg-package',
56 | # name: 'host1',
57 | # cluster: false,
58 | # vars: 'object Host "cmdb-host" { chec_command = "dummy" }',
59 | # reload: false
60 | # }
61 | # upload_config_package(params)
62 | #
63 | # @return [Hash]
64 | #
65 | def upload_config_package(params)
66 |
67 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
68 | raise ArgumentError.new('missing params') if( params.size.zero? )
69 |
70 | package = validate( params, required: true, var: 'package', type: String )
71 | name = validate( params, required: true, var: 'name', type: String )
72 | cluster = validate( params, required: false, var: 'cluster', type: Boolean ) || false
73 | vars = validate( params, required: false, var: 'vars', type: String )
74 | reload = validate( params, required: false, var: 'reload', type: Boolean ) || true
75 | name = name.gsub('.conf','')
76 |
77 | return { 'code' => 404, 'status' => format('no package \'%s\' exists', package) } unless(package_exists?(package))
78 |
79 | path = 'conf.d'
80 | path = 'zones.d/satellite' if(cluster)
81 | file = format( '%s/%s.conf', path, name )
82 |
83 | payload = {
84 | 'files' => {
85 | file.to_s => vars
86 | },
87 | 'reload' => reload
88 | }
89 |
90 | post(
91 | url: format( '%s/config/stages/%s', @icinga_api_url_base, package ),
92 | headers: @headers,
93 | options: @options,
94 | payload: payload
95 | )
96 | end
97 |
98 | # A list of packages.
99 | #
100 | # @example
101 | # list_config_packages
102 | #
103 | # @return [Hash]
104 | #
105 | def list_config_packages
106 |
107 | get(
108 | url: format( '%s/config/packages', @icinga_api_url_base ),
109 | headers: @headers,
110 | options: @options
111 | )
112 | end
113 |
114 | # A list of packages and their stages.
115 | #
116 | # @param [Hash] params
117 | # @option params [String] package
118 | # @option params [String] stage
119 | #
120 | # @example
121 | # params = {
122 | # package: 'cfg-package',
123 | # stage: 'example.localdomain-1441625839-0'
124 | # }
125 | # list_config_stages(params)
126 | #
127 | # @return [Hash]
128 | #
129 | def list_config_stages(params)
130 |
131 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
132 | raise ArgumentError.new('missing params') if( params.size.zero? )
133 |
134 | package = validate( params, required: true, var: 'package', type: String )
135 | stage = validate( params, required: true, var: 'stage', type: String )
136 |
137 | get(
138 | url: format( '%s/config/stages/%s/%s', @icinga_api_url_base, package, stage ),
139 | headers: @headers,
140 | options: @options
141 | )
142 | end
143 |
144 |
145 | # fetched the whole config package and return them as a String.
146 | #
147 | # @param [Hash] params
148 | # @option params [String] package
149 | # @option params [String] stage
150 | # @option params [Bool] cluser (false) package for an satellite
151 | # @option params [String] name
152 | #
153 | # @example
154 | # params = {
155 | # package: 'cfg-package',
156 | # stage: 'example.localdomain-1441625839-0',
157 | # name: 'host1',
158 | # cluster: false
159 | # }
160 | # fetch_config_stages(params)
161 | #
162 | # @return [String]
163 | #
164 | def fetch_config_stages(params)
165 |
166 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
167 | raise ArgumentError.new('missing params') if( params.size.zero? )
168 |
169 | package = validate( params, required: true, var: 'package', type: String )
170 | stage = validate( params, required: true, var: 'stage', type: String )
171 | name = validate( params, required: true, var: 'name', type: String )
172 | cluster = validate( params, required: false, var: 'cluster', type: Boolean ) || false
173 | name = name.gsub('.conf','')
174 |
175 | return { 'code' => 404, 'status' => format('no package \'%s\' exists', package) } unless(package_exists?(package))
176 |
177 | path = 'conf.d'
178 | path = 'zones.d/satellite' if(cluster)
179 | file = format( '%s/%s/%s/%s.conf', package, stage, path, name )
180 |
181 | get(
182 | url: format( '%s/config/files/%s', @icinga_api_url_base, file ),
183 | headers: {},
184 | options: @options
185 | )
186 | end
187 |
188 | # fetch the startup.log from the named packe / stage combination to see possible errors.
189 | #
190 | # @param [Hash] params
191 | # @option params [String] package
192 | # @option params [String] stage
193 | # @option params [Bool] cluser (false) package for an satellite
194 | #
195 | # @example
196 | # params = {
197 | # package: 'cfg-package',
198 | # stage: 'example.localdomain-1441625839-0',
199 | # cluster: false
200 | # }
201 | # package_stage_errors(params)
202 | #
203 | # @return [String]
204 | #
205 | def package_stage_errors(params)
206 |
207 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
208 | raise ArgumentError.new('missing params') if( params.size.zero? )
209 |
210 | package = validate( params, required: true, var: 'package', type: String )
211 | stage = validate( params, required: true, var: 'stage', type: String )
212 | # cluster = validate( params, required: false, var: 'cluster', type: Boolean ) || false
213 |
214 | return { 'code' => 404, 'status' => format('no package \'%s\' exists', package) } unless(package_exists?(package))
215 |
216 | file = format( '%s/%s/startup.log', package, stage )
217 |
218 | get(
219 | url: format( '%s/config/files/%s', @icinga_api_url_base, file ),
220 | headers: {},
221 | options: @options
222 | )
223 | end
224 |
225 | # Deleting Configuration Package Stage
226 | #
227 | # @param [Hash] params
228 | # @option params [String] package
229 | # @option params [String] stage
230 | #
231 | # @example
232 | # params = {
233 | # package: 'cfg-package',
234 | # stage: 'example.localdomain-1441625839-0',
235 | # cluster: false
236 | # }
237 | # remove_config_stage(params)
238 | #
239 | # @return [Hash]
240 | #
241 | def remove_config_stage(params)
242 |
243 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
244 | raise ArgumentError.new('missing params') if( params.size.zero? )
245 |
246 | package = validate( params, required: true, var: 'package', type: String )
247 | stage = validate( params, required: true, var: 'stage', type: String )
248 |
249 | return { 'code' => 404, 'name' => package, 'status' => 'Package names starting with an underscore are reserved for internal packages and can not be used.' } if( package.initial == '_' )
250 | return { 'code' => 404, 'status' => format('no package \'%s\' exists', name) } unless(package_exists?(package))
251 |
252 | delete(
253 | url: format( '%s/config/stages/%s/%s', @icinga_api_url_base, package, stage ),
254 | headers: @headers,
255 | options: @options
256 | )
257 | end
258 |
259 | # Deleting Configuration Package
260 | #
261 | # @param [String] name the name for the package.
262 | #
263 | # @example
264 | # remove_config_package('cfg-package')
265 | #
266 | # @return [Hash]
267 | #
268 | def remove_config_package(name)
269 |
270 | raise ArgumentError.new(format('wrong type. \'name\' must be an String, given \'%s\'', name.class.to_s)) unless( name.is_a?(String) )
271 | raise ArgumentError.new('missing \'name\'') if( name.size.zero? )
272 |
273 | return { 'code' => 404, 'name' => name, 'status' => 'Package names starting with an underscore are reserved for internal packages and can not be used.' } if( name.initial == '_' )
274 | return { 'code' => 404, 'status' => format('no package \'%s\' exists', name) } unless(package_exists?(name))
275 |
276 | delete(
277 | url: format( '%s/config/packages/%s', @icinga_api_url_base, name ),
278 | headers: @headers,
279 | options: @options
280 | )
281 | end
282 |
283 | # check if a package exists
284 | #
285 | # @param [String] name the name for the package.
286 | #
287 | # @example
288 | # package_exists?('cfg-package')
289 | #
290 | # @return [Bool]
291 | #
292 | def package_exists?(name)
293 |
294 | raise ArgumentError.new(format('wrong type. \'name\' must be an String, given \'%s\'', name.class.to_s)) unless( name.is_a?(String) )
295 | raise ArgumentError.new('missing \'name\'') if( name.size.zero? )
296 |
297 | current_packages = list_config_packages
298 |
299 | return { 'code' => 404, 'status' => 'error to get packages' } if( current_packages.nil? && current_packages.dig('code') != 200 )
300 |
301 | current_packages = current_packages.dig('results')
302 |
303 | data = current_packages.select { |k,_| k['name'] == name }
304 | data = data.first if( data )
305 |
306 | return false unless(data)
307 |
308 | true
309 | end
310 |
311 | end
312 | end
313 |
--------------------------------------------------------------------------------
/lib/icinga2/converts.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 |
4 | module Icinga2
5 |
6 | # many convert functions
7 | #
8 | #
9 | module Converts
10 |
11 | HOST_STATE_STRING = %w[Up Down].freeze
12 | SERVICE_STATE_STRING = %w[OK Warning Critical Unknown].freeze
13 |
14 | HOST_STATE_COLOR = %w[green red].freeze
15 | SERVICE_STATE_COLOR = %w[green yellow red purple].freeze
16 |
17 | # convert a Icinga2 state into a human readable state
18 | #
19 | # @param [String] state the Icinga2 State
20 | # @param [Bool] is_host (false) if this a Host or a Service Check
21 | #
22 | # @return [String]
23 | #
24 | def state_to_string( state, is_host = false )
25 | result = SERVICE_STATE_STRING[state] unless( is_host )
26 | result = HOST_STATE_STRING[state] if( is_host )
27 | result = 'Undefined' if( result.nil? )
28 | result
29 | end
30 |
31 | # convert a Icinga2 state into a named color
32 | #
33 | # @param [String] state the Icinga2 State
34 | # @param [Bool] is_host (false) if this a Host or a Service Check
35 | #
36 | # @return [String]
37 | #
38 | def state_to_color( state, is_host = false )
39 | result = SERVICE_STATE_COLOR[state] unless( is_host )
40 | result = HOST_STATE_COLOR[state] if( is_host )
41 | result = 'blue' if( result.nil? )
42 | result
43 | end
44 |
45 | # reformat a service check name
46 | #
47 | # @param [String] name
48 | #
49 | # @return [String]
50 | #
51 | def self.format_service( name )
52 | service_map = name.split('!', 2)
53 | service_map.join( ' - ' )
54 | end
55 |
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/lib/icinga2/downtimes.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 |
4 | module Icinga2
5 |
6 | # namespace for downtimes handling
7 | #
8 | # Schedule a downtime for hosts and services.
9 | #
10 | module Downtimes
11 |
12 | # add downtime
13 | #
14 | # @param [Hash] params
15 | # @option params [String] host_name
16 | # @option params [String] host_group
17 | # @option params [String] type 'host' or 'service' downtime
18 | # @option params [Integer] start_time (Time.new.to_i) Timestamp marking the beginning of the downtime. (required)
19 | # @option params [Integer] end_time Timestamp marking the end of the downtime. (required)
20 | # @option params [String] author Name of the author. (required)
21 | # @option params [String] comment Comment text. (required)
22 | # @option params [String] config_owner
23 | # @option params [Integer] duration Duration of the downtime in seconds if fixed is set to false. (Required for flexible downtimes.)
24 | # @option params [Integer] entry_time
25 | # @option params [Bool] fixed (true) Defaults to true. If true, the downtime is fixed otherwise flexible. See downtimes for more information.
26 | # @option params [String] scheduled_by
27 | # @option params [String] service_name
28 | # @option params [String] triggered_by Sets the trigger for a triggered downtime. See downtimes for more information on triggered downtimes.
29 | #
30 | # @example
31 | # param = {
32 | # name: 'test',
33 | # type: 'service',
34 | # host_name: 'icinga2',
35 | # comment: 'test downtime',
36 | # author: 'icingaadmin',
37 | # start_time: Time.now.to_i,
38 | # end_time: Time.now.to_i + 20
39 | # }
40 | # add_downtime(param)
41 | #
42 | # @return [Hash]
43 | #
44 | def add_downtime( params )
45 |
46 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
47 | raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
48 |
49 | host_name = validate( params, required: false, var: 'host_name', type: String )
50 | host_group = validate( params, required: false, var: 'host_group', type: String )
51 | start_time = validate( params, required: false, var: 'start_time', type: Integer ) || Time.now.to_i
52 | end_time = validate( params, required: false, var: 'end_time', type: Integer )
53 | author = validate( params, required: true, var: 'author', type: String )
54 | comment = validate( params, required: true, var: 'comment', type: String )
55 | type = validate( params, required: false, var: 'type', type: String )
56 | fixed = validate( params, required: false, var: 'fixed', type: Boolean ) || true
57 | duration_required = true if( fixed == false )
58 | duration = validate( params, required: duration_required, var: 'duration', type: Integer )
59 | entry_time = validate( params, required: false, var: 'entry_time', type: Integer )
60 | scheduled_by = validate( params, required: false, var: 'scheduled_by', type: String )
61 | service_name = validate( params, required: false, var: 'service_name', type: String )
62 | triggered_by = validate( params, required: false, var: 'triggered_by', type: String )
63 | config_owner = validate( params, required: false, var: 'config_owner', type: String )
64 | filter = nil
65 |
66 | # sanitychecks
67 | #
68 | raise ArgumentError.new(format('wrong downtype type. only \'host\' or \'service\' allowed, given \%s\'', type)) if( %w[host service].include?(type.downcase) == false )
69 | raise ArgumentError.new('choose \'host_name\' or \'host_group\', not both') unless( host_group.nil? || host_name.nil? )
70 | raise ArgumentError.new(format('these \'author\' are not exists: \'%s\'', author)) unless( exists_user?( author ) )
71 | raise ArgumentError.new('Missing downtime \'end_time\'') if( end_time.nil? )
72 | raise ArgumentError.new('\'end_time\' are equal or smaller then \'start_time\'') if( end_time.to_i <= start_time )
73 |
74 | # TODO
75 | # - more flexibility (e.g. support scheduled_by ...)
76 |
77 | unless( host_name.nil? )
78 | return { 'code' => 404, 'name' => host_name, 'status' => 'Object not Found' } unless( exists_host?( host_name ) )
79 | filter = format( 'host.name == "%s"', host_name )
80 | end
81 |
82 | unless( host_group.nil? )
83 | return { 'code' => 404, 'name' => host_group, 'status' => 'Object not Found' } unless( exists_hostgroup?( host_group ) )
84 | filter = format( '"%s" in host.groups', host_group )
85 | end
86 |
87 | payload = {
88 | type: type.capitalize, # we need the first char as Uppercase
89 | filter: filter,
90 | fixed: fixed,
91 | start_time: start_time,
92 | end_time: end_time,
93 | author: author,
94 | comment: comment,
95 | duration: duration,
96 | entry_time: entry_time,
97 | scheduled_by: scheduled_by,
98 | host_name: host_name,
99 | host_group: host_group,
100 | service_name: service_name,
101 | triggered_by: triggered_by,
102 | config_owner: config_owner
103 | }
104 |
105 | # remove all empty attrs
106 | payload.reject!{ |_k, v| v.nil? }
107 |
108 | post(
109 | url: format( '%s/actions/schedule-downtime', @icinga_api_url_base ),
110 | headers: @headers,
111 | options: @options,
112 | payload: payload
113 | )
114 | end
115 |
116 | # remove downtime
117 | #
118 | # @param [Hash] params
119 | # @option params [String] host_name
120 | # @option params [String] host_group
121 | # @option params [String] author Name of the author. (required)
122 | # @option params [String] comment Comment text. (required)
123 | # @option params [String] service_name
124 | # @option params [String] filter
125 | # @option params [Hash] filter_vars
126 | #
127 | #
128 | # @example
129 | # param = {
130 | # comment: 'test downtime',
131 | # author: 'icingaadmin'
132 | # }
133 | # remove_downtime(param)
134 | #
135 | # param = {
136 | # filter: '"host.name == filterHost && !service && downtime.author == filterAuthor"',
137 | # filter_vars: { filterHost: 'c1-mysql-1', filterAuthor: 'icingaadmin' }
138 | # )
139 | # remove_downtime(param)
140 | #
141 | # param = {
142 | # host_name: 'c1-mysql-1',
143 | # service_name: 'ping4'
144 | # }
145 | # remove_downtime(param)
146 | #
147 | # @return [Hash]
148 | #
149 | def remove_downtime( params )
150 |
151 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
152 | raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
153 |
154 | host_name = validate( params, required: false, var: 'host_name', type: String )
155 | host_group = validate( params, required: false, var: 'host_group', type: String )
156 | author = validate( params, required: false, var: 'author', type: String )
157 | comment = validate( params, required: false, var: 'comment', type: String )
158 | service_name = validate( params, required: false, var: 'service_name', type: String )
159 | filter = validate( params, required: false, var: 'filter', type: String )
160 | filter_vars = validate( params, required: false, var: 'filter_vars', type: Hash )
161 |
162 | payload = {
163 | type: 'Downtime',
164 | host_name: host_name,
165 | service_name: service_name,
166 | host_group: host_group,
167 | comment: comment,
168 | author: author,
169 | filter: filter,
170 | filter_vars: filter_vars
171 | }
172 |
173 | # remove all empty attrs
174 | payload.reject!{ |_k, v| v.nil? }
175 |
176 | post(
177 | url: format( '%s/actions/remove-downtime', @icinga_api_url_base ),
178 | headers: @headers,
179 | options: @options,
180 | payload: payload
181 | )
182 | end
183 |
184 | # return downtimes
185 | #
186 | # @example
187 | # downtimes
188 | #
189 | # @return [Array]
190 | #
191 | def downtimes
192 |
193 | api_data(
194 | url: format( '%s/objects/downtimes' , @icinga_api_url_base ),
195 | headers: @headers,
196 | options: @options
197 | )
198 | end
199 |
200 | end
201 | end
202 |
--------------------------------------------------------------------------------
/lib/icinga2/hostgroups.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: false
3 |
4 | module Icinga2
5 |
6 | # namespace for hostgroup handling
7 | module Hostgroups
8 |
9 | # add a hostgroup
10 | #
11 | # @param [Hash] params
12 | # @option params [String] host_group hostgroup to create
13 | # @option params [String] display_name the displayed name
14 | # @option params [String] notes
15 | # @option params [String] notes_url
16 | # @option params [String] action_url
17 | # @option params [Hash] vars ({})
18 | #
19 | # @example
20 | # add_hostgroup(host_group: 'foo', display_name: 'FOO')
21 | #
22 | # @return [Hash] result
23 | #
24 | def add_hostgroup( params )
25 |
26 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
27 | raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
28 |
29 | host_group = validate( params, required: true, var: 'host_group', type: String )
30 | display_name = validate( params, required: false, var: 'display_name', type: String )
31 | notes = validate( params, required: false, var: 'notes', type: String )
32 | notes_url = validate( params, required: false, var: 'notes_url', type: String )
33 | action_url = validate( params, required: false, var: 'action_url', type: String )
34 | vars = validate( params, required: false, var: 'vars', type: Hash ) || {}
35 |
36 | payload = {
37 | attrs: {
38 | display_name: display_name,
39 | notes: notes,
40 | notes_url: notes_url,
41 | action_url: action_url,
42 | vars: vars
43 | }
44 | }
45 |
46 | # remove all empty attrs
47 | payload.reject!{ |_k, v| v.nil? }
48 | payload[:attrs].reject!{ |_k, v| v.nil? }
49 |
50 | put(
51 | url: format('%s/objects/hostgroups/%s', @icinga_api_url_base, host_group),
52 | headers: @headers,
53 | options: @options,
54 | payload: payload
55 | )
56 | end
57 |
58 | # delete a hostgroup
59 | #
60 | # @param [Hash] params
61 | # @option params [String] name hostgroup to delete
62 | # @option params [Bool] cascade (false) delete hostgroup also when other objects depend on it
63 | #
64 | # @example
65 | # delete_hostgroup(name: 'foo')
66 | # delete_hostgroup(name: 'foo', cascade: true)
67 | #
68 | # @return [Hash] result
69 | #
70 | def delete_hostgroup( params )
71 |
72 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
73 | raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
74 |
75 | name = validate( params, required: true, var: 'name', type: String )
76 | cascade = validate( params, required: false, var: 'cascade', type: Boolean ) || false
77 |
78 | return { 'code' => 404, 'status' => 'Object not Found' } if( exists_hostgroup?( name ) == false )
79 |
80 | url = format( '%s/objects/hostgroups/%s%s', @icinga_api_url_base, name, cascade.is_a?(TrueClass) ? '?cascade=1' : nil )
81 |
82 | delete(
83 | url: url,
84 | headers: @headers,
85 | options: @options
86 | )
87 | end
88 |
89 | # returns all usersgroups
90 | #
91 | # @param [String] host_group (nil) optional for a single hostgroup
92 | #
93 | # @example to get all users
94 | # hostgroups
95 | #
96 | # @example to get one user
97 | # hostgroups(host_group: 'linux-servers')
98 | #
99 | # @return [Hash] returns a hash with all hostgroups
100 | #
101 | def hostgroups( host_group = nil )
102 |
103 | raise ArgumentError.new(format('wrong type. \'host_group\' must be an String, given \'%s\'', host_group.class.to_s)) unless( host_group.nil? || host_group.is_a?(String) )
104 |
105 | url = format( '%s/objects/hostgroups' , @icinga_api_url_base )
106 | url = format( '%s/objects/hostgroups/%s', @icinga_api_url_base, host_group ) unless( host_group.nil? )
107 |
108 | api_data(
109 | url: url,
110 | headers: @headers,
111 | options: @options
112 | )
113 | end
114 |
115 | # returns true if the hostgroup exists
116 | #
117 | # @param [String] host_group the name of the hostgroup
118 | #
119 | # @example
120 | # exists_hostgroup?('linux-servers')
121 | #
122 | # @return [Bool] returns true if the hostgroup exists
123 | #
124 | def exists_hostgroup?( host_group )
125 |
126 | raise ArgumentError.new(format('wrong type. \'host_group\' must be an String, given \'%s\'', host_group.class.to_s)) unless( host_group.is_a?(String) )
127 | raise ArgumentError.new('Missing \'host_group\'') if( host_group.size.zero? )
128 |
129 | result = hostgroups(host_group)
130 | result = JSON.parse( result ) if( result.is_a?(String) )
131 | result = result.first if( result.is_a?(Array) )
132 |
133 | return false if( result.is_a?(Hash) && result.dig('code') == 404 )
134 |
135 | true
136 | end
137 |
138 | end
139 | end
140 |
--------------------------------------------------------------------------------
/lib/icinga2/hosts.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 | module Icinga2
4 |
5 | # namespace for host handling
6 | module Hosts
7 |
8 | # add host
9 | #
10 | # @param [Hash] params
11 | # @option params [String] name
12 | # @option params [String] address
13 | # @option params [String] address6
14 | # @option params [String] display_name
15 | # @option params [Bool] enable_notifications (false)
16 | # @option params [Integer] max_check_attempts (3)
17 | # @option params [Integer] check_interval (60)
18 | # @option params [Integer] retry_interval (45)
19 | # @option params [String] notes
20 | # @option params [String] notes_url
21 | # @option params [String] action_url
22 | # @option params [String] check_command
23 | # @option params [Integer] check_interval
24 | # @option params [String] check_period
25 | # @option params [Integer] check_timeout
26 | # @option params [String] command_endpoint
27 | # @option params [Bool] enable_active_checks
28 | # @option params [Bool] enable_event_handler
29 | # @option params [Bool] enable_flapping
30 | # @option params [Bool] enable_passive_checks
31 | # @option params [Bool] enable_perfdata
32 | # @option params [String] event_command
33 | # @option params [Integer] flapping_threshold
34 | # @option params [Integer] flapping_threshold_high
35 | # @option params [Integer] flapping_threshold_low
36 | # @option params [String] icon_image
37 | # @option params [String] icon_image_alt
38 | # @option params [Integer] retry_interval
39 | # @option params [Bool] volatile
40 | # @option params [Hash] vars ({})
41 | #
42 | # @example
43 | # param = {
44 | # name: 'foo',
45 | # address: 'foo.bar.com',
46 | # display_name: 'test node',
47 | # max_check_attempts: 5,
48 | # notes: 'test node',
49 | # vars: {
50 | # description: 'host foo',
51 | # os: 'Linux',
52 | # partitions: {
53 | # '/' => {
54 | # crit: '95%',
55 | # warn: '90%'
56 | # }
57 | # }
58 | # }
59 | # }
60 | # add_host(param)
61 | #
62 | # @return [Hash]
63 | #
64 | def add_host( params )
65 |
66 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
67 | raise ArgumentError.new('missing params') if( params.size.zero? )
68 |
69 | name = validate( params, required: true, var: 'name', type: String )
70 | action_url = validate( params, required: false, var: 'action_url', type: String )
71 | address = validate( params, required: false, var: 'address', type: String )
72 | address6 = validate( params, required: false, var: 'address6', type: String )
73 | check_command = validate( params, required: false, var: 'check_command', type: String )
74 | check_interval = validate( params, required: false, var: 'check_interval', type: Integer ) || 60
75 | check_period = validate( params, required: false, var: 'check_period', type: Integer )
76 | check_timeout = validate( params, required: false, var: 'check_timeout', type: Integer )
77 | command_endpoint = validate( params, required: false, var: 'command_endpoint', type: String )
78 | display_name = validate( params, required: false, var: 'display_name', type: String )
79 | enable_active_checks = validate( params, required: false, var: 'enable_active_checks', type: Boolean )
80 | enable_event_handler = validate( params, required: false, var: 'enable_event_handler', type: Boolean )
81 | enable_flapping = validate( params, required: false, var: 'enable_flapping', type: Boolean )
82 | enable_notifications = validate( params, required: false, var: 'enable_notifications', type: Boolean ) || false
83 | enable_passive_checks = validate( params, required: false, var: 'enable_passive_checks', type: Boolean )
84 | volatile = validate( params, required: false, var: 'volatile', type: Boolean )
85 | enable_perfdata = validate( params, required: false, var: 'enable_perfdata', type: Boolean )
86 | event_command = validate( params, required: false, var: 'event_command', type: String )
87 | flapping_threshold = validate( params, required: false, var: 'flapping_threshold', type: Integer )
88 | groups = validate( params, required: false, var: 'groups', type: Array )
89 | icon_image = validate( params, required: false, var: 'icon_image', type: String )
90 | icon_image_alt = validate( params, required: false, var: 'icon_image_alt', type: String )
91 | notes = validate( params, required: false, var: 'notes', type: String )
92 | notes_url = validate( params, required: false, var: 'notes_url', type: String )
93 | max_check_attempts = validate( params, required: false, var: 'max_check_attempts', type: Integer ) || 3
94 | retry_interval = validate( params, required: false, var: 'retry_interval', type: Integer ) || 45
95 | templates = validate( params, required: false, var: 'templates', type: Array ) || [ 'generic-host' ]
96 | vars = validate( params, required: false, var: 'vars', type: Hash ) || {}
97 | zone = validate( params, required: false, var: 'zone', type: String )
98 |
99 | address = Socket.gethostbyname( name ).first if( address.nil? )
100 |
101 | payload = {
102 | templates: templates,
103 | attrs: {
104 | action_url: action_url,
105 | address: address,
106 | address6: address6,
107 | check_period: check_period,
108 | check_command: check_command,
109 | check_interval: check_interval,
110 | check_timeout: check_timeout,
111 | command_endpoint: command_endpoint,
112 | display_name: display_name,
113 | enable_active_checks: enable_active_checks,
114 | enable_event_handler: enable_event_handler,
115 | enable_flapping: enable_flapping,
116 | enable_notifications: enable_notifications,
117 | enable_passive_checks: enable_passive_checks,
118 | enable_perfdata: enable_perfdata,
119 | event_command: event_command,
120 | flapping_threshold: flapping_threshold,
121 | groups: groups,
122 | icon_image: icon_image,
123 | icon_image_alt: icon_image_alt,
124 | max_check_attempts: max_check_attempts,
125 | notes: notes,
126 | notes_url: notes_url,
127 | retry_interval: retry_interval,
128 | volatile: volatile,
129 | zone: zone,
130 | vars: vars
131 | }
132 | }
133 |
134 | # remove all empty attrs
135 | payload.reject!{ |_k, v| v.nil? }
136 | payload[:attrs].reject!{ |_k, v| v.nil? }
137 |
138 | # puts JSON.pretty_generate payload
139 |
140 | put(
141 | url: format( '%s/objects/hosts/%s', @icinga_api_url_base, name ),
142 | headers: @headers,
143 | options: @options,
144 | payload: payload
145 | )
146 | end
147 |
148 | # delete a host
149 | #
150 | # @param [Hash] params
151 | # @option params [String] name host to delete
152 | # @option params [Bool] cascade (false) delete host also when other objects depend on it
153 | #
154 | # @example
155 | # delete_host(name: 'foo')
156 | # delete_host(name: 'foo', cascade: true)
157 | #
158 | #
159 | # @return [Hash] result
160 | #
161 | def delete_host( params )
162 |
163 | raise ArgumentError.new('only Hash are allowed') unless( params.is_a?(Hash) )
164 | raise ArgumentError.new('missing params') if( params.size.zero? )
165 |
166 | name = validate( params, required: true, var: 'name', type: String )
167 | cascade = validate( params, required: false, var: 'cascade', type: Boolean ) || false
168 |
169 | url = format( '%s/objects/hosts/%s%s', @icinga_api_url_base, name, cascade.is_a?(TrueClass) ? '?cascade=1' : nil )
170 |
171 | delete(
172 | url: url,
173 | headers: @headers,
174 | options: @options
175 | )
176 | end
177 |
178 | # modify a host
179 | #
180 | # @param [Hash] params
181 | # @option params [String] name
182 | # @option params [String] name
183 | # @option params [String] address
184 | # @option params [String] address6
185 | # @option params [String] display_name
186 | # @option params [Bool] enable_notifications
187 | # @option params [Integer] max_check_attempts
188 | # @option params [Integer] check_interval
189 | # @option params [Integer] retry_interval
190 | # @option params [String] notes
191 | # @option params [String] notes_url
192 | # @option params [String] action_url
193 | # @option params [String] check_command
194 | # @option params [Integer] check_interval
195 | # @option params [String] check_period
196 | # @option params [Integer] check_timeout
197 | # @option params [String] command_endpoint
198 | # @option params [Bool] enable_active_checks
199 | # @option params [Bool] enable_event_handler
200 | # @option params [Bool] enable_flapping
201 | # @option params [Bool] enable_passive_checks
202 | # @option params [Bool] enable_perfdata
203 | # @option params [String] event_command
204 | # @option params [Integer] flapping_threshold
205 | # @option params [Integer] flapping_threshold_high
206 | # @option params [Integer] flapping_threshold_low
207 | # @option params [String] icon_image
208 | # @option params [String] icon_image_alt
209 | # @option params [Integer] retry_interval
210 | # @option params [Bool] volatile
211 | # @option params [Hash] vars ({})
212 | # @option params [Bool] merge_vars (false)
213 | #
214 | # @example
215 | # param = {
216 | # name: 'foo',
217 | # address: 'foo.bar.com',
218 | # display_name: 'Host for an example Problem',
219 | # max_check_attempts: 10,
220 | # }
221 | #
222 | # param = {
223 | # name: 'foo',
224 | # address: 'foo.bar.com',
225 | # notes: 'an demonstration object',
226 | # vars: {
227 | # description: 'schould be delete ASAP',
228 | # os: 'Linux',
229 | # partitions: {
230 | # '/' => {
231 | # crit: '98%',
232 | # warn: '95%'
233 | # }
234 | # }
235 | # },
236 | # merge_vars: true
237 | # }
238 | #
239 | # param = {
240 | # name: 'foo',
241 | # address: 'foo.bar.com',
242 | # vars: {
243 | # description: 'removed all other custom vars',
244 | # }
245 | # }
246 | #
247 | # add_host(param)
248 | #
249 | # @return [Hash]
250 | #
251 | def modify_host( params )
252 |
253 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
254 | raise ArgumentError.new('missing params') if( params.size.zero? )
255 |
256 | name = validate( params, required: true, var: 'name', type: String )
257 | action_url = validate( params, required: false, var: 'action_url', type: String )
258 | address = validate( params, required: false, var: 'address', type: String )
259 | address6 = validate( params, required: false, var: 'address6', type: String )
260 | check_command = validate( params, required: false, var: 'check_command', type: String )
261 | check_interval = validate( params, required: false, var: 'check_interval', type: Integer )
262 | check_period = validate( params, required: false, var: 'check_period', type: Integer )
263 | check_timeout = validate( params, required: false, var: 'check_timeout', type: Integer )
264 | command_endpoint = validate( params, required: false, var: 'command_endpoint', type: String )
265 | display_name = validate( params, required: false, var: 'display_name', type: String )
266 | enable_active_checks = validate( params, required: false, var: 'enable_active_checks', type: Boolean )
267 | enable_event_handler = validate( params, required: false, var: 'enable_event_handler', type: Boolean )
268 | enable_flapping = validate( params, required: false, var: 'enable_flapping', type: Boolean )
269 | enable_notifications = validate( params, required: false, var: 'enable_notifications', type: Boolean )
270 | enable_passive_checks = validate( params, required: false, var: 'enable_passive_checks', type: Boolean )
271 | volatile = validate( params, required: false, var: 'volatile', type: Boolean )
272 | enable_perfdata = validate( params, required: false, var: 'enable_perfdata', type: Boolean )
273 | event_command = validate( params, required: false, var: 'event_command', type: String )
274 | flapping_threshold = validate( params, required: false, var: 'flapping_threshold', type: Integer )
275 | groups = validate( params, required: false, var: 'groups', type: Array )
276 | icon_image = validate( params, required: false, var: 'icon_image', type: String )
277 | icon_image_alt = validate( params, required: false, var: 'icon_image_alt', type: String )
278 | notes = validate( params, required: false, var: 'notes', type: String )
279 | notes_url = validate( params, required: false, var: 'notes_url', type: String )
280 | max_check_attempts = validate( params, required: false, var: 'max_check_attempts', type: Integer )
281 | retry_interval = validate( params, required: false, var: 'retry_interval', type: Integer )
282 | templates = validate( params, required: false, var: 'templates', type: Array ) || [ 'generic-host' ]
283 | vars = validate( params, required: false, var: 'vars', type: Hash ) || {}
284 | zone = validate( params, required: false, var: 'zone', type: String )
285 | merge_vars = validate( params, required: false, var: 'merge_vars', type: Boolean ) || false
286 |
287 | # check if host exists
288 | return { 'code' => 404, 'name' => name, 'status' => 'Object not Found' } unless( exists_host?( name ) )
289 |
290 | # merge the new with the old vars
291 | if( merge_vars == true )
292 | current_host = hosts( name: name )
293 | current_host_vars = current_host.first
294 | current_host_vars = current_host_vars.dig('attrs','vars')
295 | current_host_vars = current_host_vars.deep_string_keys
296 | vars = vars.deep_string_keys unless( vars.empty? )
297 | vars = current_host_vars.merge( vars )
298 | end
299 |
300 | payload = {
301 | templates: templates,
302 | attrs: {
303 | action_url: action_url,
304 | address: address,
305 | address6: address6,
306 | check_period: check_period,
307 | check_command: check_command,
308 | check_interval: check_interval,
309 | check_timeout: check_timeout,
310 | command_endpoint: command_endpoint,
311 | display_name: display_name,
312 | enable_active_checks: enable_active_checks,
313 | enable_event_handler: enable_event_handler,
314 | enable_flapping: enable_flapping,
315 | enable_notifications: enable_notifications,
316 | enable_passive_checks: enable_passive_checks,
317 | enable_perfdata: enable_perfdata,
318 | event_command: event_command,
319 | flapping_threshold: flapping_threshold,
320 | groups: groups,
321 | icon_image: icon_image,
322 | icon_image_alt: icon_image_alt,
323 | max_check_attempts: max_check_attempts,
324 | notes: notes,
325 | notes_url: notes_url,
326 | retry_interval: retry_interval,
327 | volatile: volatile,
328 | zone: zone,
329 | vars: vars
330 | }
331 | }
332 |
333 | # remove all empty attrs
334 | payload.reject!{ |_k, v| v.nil? }
335 | payload[:attrs].reject!{ |_k, v| v.nil? }
336 |
337 | post(
338 | url: format( '%s/objects/hosts/%s', @icinga_api_url_base, name ),
339 | headers: @headers,
340 | options: @options,
341 | payload: payload
342 | )
343 | end
344 |
345 |
346 | # return hosts
347 | #
348 | # @param [Hash] params
349 | # @option params [String] name
350 | # @option params [Array] attrs
351 | # @option params [String] filter
352 | # @option params [Array] joins
353 | #
354 | # @example to get all hosts
355 | # hosts
356 | #
357 | # @example to get one host
358 | # hosts( name: 'icinga2')
359 | #
360 | # @return [Array]
361 | #
362 | def hosts( params = {} )
363 |
364 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
365 |
366 | name = validate( params, required: false, var: 'name', type: String )
367 | attrs = validate( params, required: false, var: 'attrs', type: Array )
368 | filter = validate( params, required: false, var: 'filter', type: String )
369 | joins = validate( params, required: false, var: 'joins', type: Array )
370 |
371 | payload = {
372 | attrs: attrs,
373 | filter: filter,
374 | joins: joins
375 | }
376 | payload.reject!{ |_k, v| v.nil? }
377 |
378 | api_data(
379 | url: format( '%s/objects/hosts/%s', @icinga_api_url_base, name ),
380 | headers: @headers,
381 | options: @options,
382 | payload: payload
383 | )
384 | end
385 |
386 | # returns true if the host exists
387 | #
388 | # @param [String] host_name
389 | #
390 | # @example
391 | # exists_host?('icinga2')
392 | #
393 | # @return [Bool]
394 | #
395 | def exists_host?( host_name )
396 |
397 | raise ArgumentError.new(format('wrong type. \'host_name\' must be an String, given \'%s\'',host_name.class.to_s)) unless( host_name.is_a?(String) )
398 | raise ArgumentError.new('Missing host_name') if( host_name.size.zero? )
399 |
400 | result = hosts( name: host_name )
401 | result = JSON.parse( result ) if( result.is_a?(String) )
402 | result = result.first if( result.is_a?(Array) )
403 |
404 | return false if( result.is_a?(Hash) && result.dig('code') == 404 )
405 |
406 | true
407 | end
408 |
409 | # returns host objects
410 | #
411 | # @param [Hash] params
412 | # @option params [Array] attrs (['name', 'state', 'acknowledgement', 'downtime_depth', 'last_check'])
413 | # @option params [String] filter ([])
414 | # @option params [Array] joins ([])
415 | #
416 | # @example with default attrs and joins
417 | # host_objects
418 | #
419 | # @example
420 | # host_objects(attrs: ['name', 'state'])
421 | #
422 | # @return [Hash]
423 | #
424 | def host_objects( params = {} )
425 |
426 | attrs = validate( params, required: false, var: 'attrs', type: Array ) || %w[name state acknowledgement downtime_depth last_check]
427 | filter = validate( params, required: false, var: 'filter', type: String )
428 | joins = validate( params, required: false, var: 'joins', type: Array )
429 |
430 | payload = {
431 | attrs: attrs,
432 | filter: filter,
433 | joins: joins
434 | }
435 | payload.reject!{ |_k, v| v.nil? }
436 |
437 | data = api_data(
438 | url: format( '%s/objects/hosts', @icinga_api_url_base ),
439 | headers: @headers,
440 | options: @options,
441 | payload: payload
442 | )
443 |
444 | @last_host_objects_called = Time.now.to_i
445 |
446 | if( !data.nil? && data.is_a?(Array) )
447 | all_hosts = data.clone
448 | unless( all_hosts.nil? )
449 | # global var for count of all hosts
450 | @hosts_all = all_hosts.size
451 | # global var for count of all host with a problem
452 | @hosts_problems = count_problems(all_hosts)
453 | # global var for count of all gost with state HOSTS_DOWN
454 | @hosts_problems_down = count_problems(all_hosts, Icinga2::HOSTS_DOWN)
455 | @hosts_problems_critical = count_problems(all_hosts, Icinga2::HOSTS_CRITICAL)
456 | @hosts_problems_unknown = count_problems(all_hosts, Icinga2::HOSTS_UNKNOWN)
457 | end
458 | end
459 |
460 | data
461 | end
462 |
463 | # returns adjusted hosts state
464 | # OBSOLETE
465 | #
466 | # @example
467 | # handled, down = hosts_adjusted.values
468 | #
469 | # h = hosts_adjusted
470 | # down = h.dig(:down_adjusted)
471 | #
472 | # @return [Hash]
473 | # * handled_problems
474 | # * down_adjusted
475 | #
476 | def hosts_adjusted
477 |
478 | puts 'function hosts_adjusted() is obsolete'
479 | puts 'Please use host_problems()'
480 |
481 | cib_data if((Time.now.to_i - @last_cib_data_called).to_i > @last_call_timeout)
482 | host_objects if((Time.now.to_i - @last_host_objects_called).to_i > @last_call_timeout)
483 |
484 | raise ArgumentError.new('Integer for @hosts_problems_down needed') unless( @hosts_problems_down.is_a?(Integer) )
485 | raise ArgumentError.new('Integer for @hosts_problems_critical needed') unless( @hosts_problems_critical.is_a?(Integer) )
486 | raise ArgumentError.new('Integer for @hosts_problems_unknown needed') unless( @hosts_problems_unknown.is_a?(Integer) )
487 | raise ArgumentError.new('Integer for @hosts_down needed') unless( @hosts_down.is_a?(Integer) )
488 |
489 | # calculate host problems adjusted by handled problems
490 | # count togther handled host problems
491 | handled_problems = @hosts_problems_down + @hosts_problems_critical + @hosts_problems_unknown
492 | down_adjusted = @hosts_down - handled_problems
493 |
494 | {
495 | handled_problems: handled_problems.to_i,
496 | down_adjusted: down_adjusted.to_i
497 | }
498 | end
499 |
500 | # return count of hosts with problems
501 | #
502 | # @example
503 | # count_hosts_with_problems
504 | #
505 | # @return [Integer]
506 | #
507 | def count_hosts_with_problems
508 |
509 | host_data = host_objects
510 | host_data = JSON.parse(host_data) if host_data.is_a?(String)
511 |
512 | f = host_data.select { |t| t.dig('attrs','state') != 0 && t.dig('attrs','downtime_depth').zero? && t.dig('attrs','acknowledgement').zero? }
513 |
514 | f.size
515 | end
516 |
517 | # return a list of hosts with problems
518 | #
519 | # @param [Integer] max_items numbers of list entries
520 | #
521 | # @example
522 | # list_hosts_with_problems
523 | #
524 | # @return [Hash]
525 | #
526 | def list_hosts_with_problems( max_items = 5 )
527 |
528 | raise ArgumentError.new(format('wrong type. \'max_items\' must be an Integer, given \'%s\'', max_items.class.to_s)) unless( max_items.is_a?(Integer) )
529 |
530 | host_problems = {}
531 | host_problems_severity = {}
532 |
533 | host_data = host_objects
534 | host_data = JSON.parse( host_data ) if host_data.is_a?(String)
535 |
536 | unless( host_data.nil? )
537 | host_data.each do |h,_v|
538 | name = h.dig('name')
539 | state = h.dig('attrs','state')
540 |
541 | next if state.to_i.zero?
542 |
543 | host_problems[name] = host_severity(h)
544 | end
545 | end
546 |
547 | # get the count of problems
548 | #
549 | host_problems.keys[1..max_items].each { |k| host_problems_severity[k] = host_problems[k] } if( host_problems.count != 0 )
550 |
551 | host_problems_severity
552 | end
553 |
554 | # returns a counter of all hosts
555 | #
556 | # @example
557 | # hosts_all
558 | #
559 | # @return [Integer]
560 | #
561 | def hosts_all
562 | host_objects if( @hosts_all.nil? || @hosts_all.zero? )
563 | @hosts_all
564 | end
565 |
566 | # returns data with host problems
567 | #
568 | # @example
569 | # host_objects
570 | # all, down, critical, unknown, handled, adjusted = host_problems.values
571 | #
572 | # p = host_problems
573 | # down = h.dig(:down)
574 | #
575 | # @return [Hash]
576 | # * all
577 | # * down
578 | # * critical
579 | # * unknown
580 | #
581 | def host_problems
582 |
583 | cib_data if((Time.now.to_i - @last_cib_data_called).to_i > @last_call_timeout)
584 | host_objects if((Time.now.to_i - @last_host_objects_called).to_i > @last_call_timeout)
585 |
586 | raise ArgumentError.new(format('wrong type. \'@hosts_problems_down\' must be an Integer, given \'%s\'', @hosts_problems_down.class.to_s)) unless( @hosts_problems_down.is_a?(Integer))
587 | raise ArgumentError.new(format('wrong type. \'@hosts_problems_critical\' must be an Integer, given \'%s\'', @hosts_problems_critical.class.to_s)) unless( @hosts_problems_critical.is_a?(Integer))
588 | raise ArgumentError.new(format('wrong type. \'@hosts_problems_critical\' must be an Integer, given \'%s\'', @hosts_problems_critical.class.to_s)) unless( @hosts_problems_critical.is_a?(Integer))
589 | raise ArgumentError.new(format('wrong type. \'@hosts_down\' must be an Integer, given \'%s\'', @hosts_down.class.to_s)) unless( @hosts_down.is_a?(Integer))
590 |
591 | problems_all = @hosts_problems.nil? ? 0 : @hosts_problems
592 | problems_down = @hosts_problems_down.nil? ? 0 : @hosts_problems_down
593 | problems_critical = @hosts_problems_critical.nil? ? 0 : @hosts_problems_critical
594 | problems_unknown = @hosts_problems_unknown.nil? ? 0 : @hosts_problems_unknown
595 |
596 | # calculate host problems adjusted by handled problems
597 | # count togther handled host problems
598 | problems_handled = @hosts_problems_down + @hosts_problems_critical + @hosts_problems_unknown
599 | problems_adjusted = @hosts_down - problems_handled
600 |
601 | {
602 | all: problems_all.to_i,
603 | down: problems_down.to_i,
604 | critical: problems_critical.to_i,
605 | unknown: problems_unknown.to_i,
606 | handled: problems_handled.to_i,
607 | adjusted: problems_adjusted.to_i
608 | }
609 | end
610 |
611 | protected
612 | # calculate a host severity
613 | #
614 | # stolen from Icinga Web 2
615 | # ./modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php
616 | #
617 | # @param [Hash] params
618 | # @option params [hash] attrs ()
619 | # * state [Float]
620 | # * acknowledgement [Float] (default: 0)
621 | # * downtime_depth [Float] (default: 0)
622 | #
623 | # @api protected
624 | #
625 | # @example
626 | # host_severity( {'attrs' => { 'state' => 0.0, 'acknowledgement' => 0.0, 'downtime_depth' => 0.0 } } )
627 | #
628 | # @return [Integer]
629 | #
630 | def host_severity( params )
631 |
632 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
633 | raise ArgumentError.new('missing params') if( params.size.zero? )
634 |
635 | attrs = params.dig('attrs')
636 |
637 | state = validate( attrs, required: true, var: 'state', type: Float )
638 | acknowledgement = validate( attrs, required: false, var: 'acknowledgement', type: Float ) || 0
639 | downtime_depth = validate( attrs, required: false, var: 'downtime_depth', type: Float ) || 0
640 |
641 | severity = 0
642 |
643 | severity +=
644 | if acknowledgement != 0
645 | 2
646 | elsif downtime_depth > 0
647 | 1
648 | else
649 | 4
650 | end
651 |
652 | severity += 16 if object_has_been_checked?(params)
653 |
654 | unless state.zero?
655 | severity +=
656 | if state == 1
657 | 32
658 | elsif state == 2
659 | 64
660 | else
661 | 256
662 | end
663 | end
664 |
665 | severity
666 | end
667 |
668 | end
669 | end
670 |
--------------------------------------------------------------------------------
/lib/icinga2/network.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 | module Icinga2
4 |
5 | # namespace for network handling
6 | module Network
7 |
8 | # static function for GET Requests
9 | #
10 | # @param [Hash] params
11 | # @option params [String] host
12 | # @option params [String] url
13 | # @option params [String] headers
14 | # @option params [String] options
15 | # @option params [Hash] payload
16 | #
17 | #
18 | # @return [Hash]
19 | #
20 | def api_data( params )
21 |
22 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
23 | raise ArgumentError.new('missing params') if( params.size.zero? )
24 |
25 | url = validate( params, required: true, var: 'url', type: String )
26 | headers = validate( params, required: true, var: 'headers', type: Hash )
27 | options = validate( params, required: true, var: 'options', type: Hash ).deep_symbolize_keys
28 | payload = validate( params, required: false, var: 'payload', type: Hash )
29 |
30 | rest_client = RestClient::Resource.new( URI.encode( url ), options )
31 |
32 | headers['X-HTTP-Method-Override'] = 'GET'
33 | method = 'GET'
34 | method = 'POST' if( payload )
35 |
36 | begin
37 | data = request( rest_client, method, headers, payload )
38 |
39 | data = JSON.parse( data ) if( data.is_a?(String) )
40 | data = data.deep_string_keys
41 | data = data.dig('results') if( data.is_a?(Hash) )
42 |
43 | return data
44 | rescue => e
45 | logger.error(e)
46 | logger.error(e.backtrace.join("\n"))
47 |
48 | return nil
49 | end
50 | end
51 |
52 | # static function for GET Requests without filters
53 | #
54 | # @param [Hash] params
55 | # @option params [String] host
56 | # @option params [String] url
57 | # @option params [String] headers
58 | # @option params [String] options
59 | # @option params [Hash] payload
60 | #
61 | #
62 | # @return [Hash]
63 | #
64 | def icinga_application_data( params )
65 |
66 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
67 | raise ArgumentError.new('missing params') if( params.size.zero? )
68 |
69 | url = validate( params, required: true, var: 'url', type: String )
70 | headers = validate( params, required: true, var: 'headers', type: Hash )
71 | options = validate( params, required: true, var: 'options', type: Hash ).deep_symbolize_keys
72 |
73 | begin
74 | data = api_data( url: url, headers: headers, options: options )
75 | data = data.first if( data.is_a?(Array) )
76 |
77 | return data.dig('status') unless( data.nil? )
78 | rescue => e
79 | logger.error(e)
80 | logger.error(e.backtrace.join("\n"))
81 |
82 | return nil
83 | end
84 |
85 | end
86 |
87 | # static function for POST Requests
88 | #
89 | # @param [Hash] params
90 | # @option params [String] url
91 | # @option params [String] headers
92 | # @option params [String] options
93 | # @option params [Hash] payload
94 | #
95 | #
96 | # @return [Hash]
97 | #
98 | def post( params )
99 |
100 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
101 | raise ArgumentError.new('missing params') if( params.size.zero? )
102 |
103 | url = validate( params, required: true, var: 'url', type: String )
104 | headers = validate( params, required: true, var: 'headers', type: Hash )
105 | options = validate( params, required: true, var: 'options', type: Hash ).deep_symbolize_keys
106 | payload = validate( params, required: false, var: 'payload', type: Hash )
107 |
108 | rest_client = RestClient::Resource.new( URI.encode( url ), options )
109 |
110 | headers['X-HTTP-Method-Override'] = 'POST'
111 |
112 | begin
113 | data = request( rest_client, 'POST', headers, payload )
114 | data = JSON.parse( data ) if( data.is_a?(String) )
115 | data = data.deep_string_keys
116 | data = data.dig('results') if( data.is_a?(Hash) )
117 |
118 | if( data.count.zero? )
119 | code = 404
120 | name = nil
121 | status = 'Object not found.'
122 | elsif( data.count == 1 )
123 | data = data.first
124 | code = data.dig('code').to_i
125 | name = data.dig('name')
126 | status = data.dig('status')
127 | else
128 | code = data.max_by{|k| k['code'] }.dig('code')
129 | status = data.map do |hash|
130 | hash['status']
131 | end
132 | end
133 |
134 | return { 'code' => code, 'name' => name, 'status' => status }
135 | rescue => e
136 | logger.error(e)
137 | logger.error(e.backtrace.join("\n"))
138 |
139 | puts e
140 | puts e.backtrace.join("\n")
141 |
142 | return nil
143 | end
144 | end
145 |
146 | # static function for PUT Requests
147 | #
148 | # @param [Hash] params
149 | # @option params [String] host
150 | # @option params [String] url
151 | # @option params [String] headers
152 | # @option params [String] options
153 | # @option params [Hash] payload
154 | #
155 | #
156 | # @return [Hash]
157 | #
158 | def put( params )
159 |
160 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
161 | raise ArgumentError.new('missing params') if( params.size.zero? )
162 |
163 | url = validate( params, required: true, var: 'url', type: String )
164 | headers = validate( params, required: true, var: 'headers', type: Hash )
165 | options = validate( params, required: true, var: 'options', type: Hash ).deep_symbolize_keys
166 | payload = validate( params, required: false, var: 'payload', type: Hash )
167 |
168 | rest_client = RestClient::Resource.new( URI.encode( url ), options )
169 |
170 | headers['X-HTTP-Method-Override'] = 'PUT'
171 |
172 | begin
173 | data = request( rest_client, 'PUT', headers, payload )
174 | data = JSON.parse( data ) if( data.is_a?(String) )
175 | data = data.deep_string_keys
176 |
177 | if( data.is_a?(Hash) )
178 | results = data.dig('results')
179 | results = results.first if( results.is_a?(Array) )
180 | else
181 | results = data
182 | end
183 |
184 | return { 'code' => results.dig('code').to_i, 'name' => results.dig('name'), 'status' => results.dig('status') } unless( results.nil? )
185 | rescue => e
186 | logger.error(e)
187 | logger.error(e.backtrace.join("\n"))
188 |
189 | return nil
190 | end
191 | end
192 |
193 | # static function for DELETE Requests
194 | #
195 | # @param [Hash] params
196 | # @option params [String] url
197 | # @option params [String] headers
198 | # @option params [String] options
199 | #
200 | #
201 | # @return [Hash]
202 | #
203 | def delete( params )
204 |
205 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
206 | raise ArgumentError.new('missing params') if( params.size.zero? )
207 |
208 | url = validate( params, required: true, var: 'url', type: String )
209 | headers = validate( params, required: true, var: 'headers', type: Hash )
210 | options = validate( params, required: true, var: 'options', type: Hash ).deep_symbolize_keys
211 |
212 | rest_client = RestClient::Resource.new( URI.encode( url ), options )
213 |
214 | headers['X-HTTP-Method-Override'] = 'DELETE'
215 |
216 | begin
217 | data = request( rest_client, 'DELETE', headers )
218 |
219 | data = JSON.parse( data ) if( data.is_a?(String) )
220 | data = data.deep_string_keys
221 |
222 | if( data.is_a?(Hash) )
223 | results = data.dig('results')
224 | results = results.first if( results.is_a?(Array) )
225 | else
226 | results = data
227 | end
228 |
229 | return { 'code' => results.dig('code').to_i, 'name' => results.dig('name'), 'status' => results.dig('status') } unless( results.nil? )
230 | rescue => e
231 | logger.error(e)
232 | logger.error(e.backtrace.join("\n"))
233 |
234 | return nil
235 | end
236 | end
237 |
238 | # static function for GET Requests
239 | #
240 | # @param [Hash] params
241 | # @option params [String] url
242 | # @option params [String] headers
243 | # @option params [String] options
244 | #
245 | #
246 | # @return [Hash]
247 | #
248 | def get(params)
249 |
250 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
251 | raise ArgumentError.new('missing params') if( params.size.zero? )
252 |
253 | url = validate( params, required: true, var: 'url', type: String )
254 | headers = validate( params, required: true, var: 'headers', type: Hash )
255 | options = validate( params, required: true, var: 'options', type: Hash ).deep_symbolize_keys
256 |
257 | rest_client = RestClient::Resource.new( URI.encode( url ), options )
258 |
259 | begin
260 | data = request( rest_client, 'GET', headers )
261 |
262 | # puts "data: #{data}"
263 |
264 | begin
265 | data = JSON.parse( data ) if( data.is_a?(String) )
266 | data = data.deep_string_keys
267 | data['code'] = 200
268 | rescue
269 | data
270 | end
271 |
272 | return data
273 | rescue => e
274 | logger.error(e)
275 | logger.error(e.backtrace.join("\n"))
276 |
277 | return nil
278 | end
279 | end
280 |
281 | private
282 | #
283 | # internal functionfor the Rest-Client Request
284 | #
285 | def request( client, method, headers, data = {} )
286 |
287 | # logger.debug( "request( #{client.to_s}, #{method}, #{headers}, #{data} )" )
288 |
289 | raise ArgumentError.new('client must be an RestClient::Resource') unless( client.is_a?(RestClient::Resource) )
290 | raise ArgumentError.new('method must be an \'GET\', \'POST\', \'PUT\' or \'DELETE\'') unless( %w[GET POST PUT DELETE].include?(method) )
291 | raise ArgumentError.new(format('data must be an Hash (%s)', data.class.to_s)) unless( data.nil? || data.is_a?(Hash) )
292 |
293 | max_retries = 3
294 | retried = 0
295 |
296 | begin
297 |
298 | case method.upcase
299 | when 'GET'
300 | response = client.get( headers )
301 | when 'POST'
302 | response = client.post( data.to_json, headers )
303 | when 'PATCH'
304 | response = client.patch( data, headers )
305 | when 'PUT'
306 | # response = @api_instance[endpoint].put( data, @headers )
307 | client.put( data.to_json, headers ) do |response, req, _result|
308 |
309 | @req = req
310 | @response_body = response.body
311 | @response_code = response.code.to_i
312 |
313 | case response.code
314 | when 200
315 | return @response_body
316 | when 400
317 | raise RestClient::BadRequest
318 | when 404
319 | raise RestClient::NotFound
320 | when 500
321 | raise RestClient::InternalServerError
322 | else
323 | response.return
324 | end
325 | end
326 |
327 | when 'DELETE'
328 | response = client.delete( @headers )
329 | else
330 | return false
331 | end
332 |
333 | response_body = response.body
334 | # response_headers = response.headers
335 |
336 | begin
337 | return JSON.parse( response_body ) if( response_body.is_a?(String) )
338 | rescue
339 | return response_body
340 | end
341 |
342 | rescue RestClient::BadRequest
343 |
344 | response_body = JSON.parse(response_body) if response_body.is_a?(String)
345 |
346 | return { 'results' => [{ 'code' => 400, 'status' => response_body.nil? ? 'Bad Request' : response_body }] }
347 |
348 | rescue RestClient::Unauthorized
349 |
350 | return { 'results' => [{ 'code' => 401, 'status' => format('Not authorized to connect \'%s\' - wrong username or password?', @icinga_api_url_base) }] }
351 |
352 | rescue RestClient::NotFound
353 |
354 | return { 'results' => [{ 'code' => 404, 'status' => 'Object not Found' }] }
355 |
356 | rescue RestClient::InternalServerError => error
357 |
358 | response_body = JSON.parse(@response_body) if @response_body.is_a?(String)
359 |
360 | # begin
361 | # puts '-------------------------------------'
362 | # puts response
363 | # puts response.class.to_s
364 | #
365 | # puts response.code.to_i
366 | # puts response_body
367 | # puts response_body.class.to_s
368 | # puts '-------------------------------------'
369 | # rescue
370 | #
371 | # end
372 |
373 | return { 'results' => [{ 'code' => 500, 'status' => error }] } if( response_body.nil? )
374 |
375 | results = response_body.dig('results')
376 | results = results.first if( results.is_a?(Array) )
377 | status = results.dig('status')
378 | errors = results.dig('errors')
379 | errors = errors.first if( errors.is_a?(Array) )
380 | errors = errors.sub(/ \'.*\'/,'')
381 |
382 | return { 'results' => [{ 'code' => 500, 'status' => format('%s (%s)', status, errors).delete('.') }] }
383 |
384 | rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
385 |
386 | # TODO
387 | # ist hier ein raise sinnvoll?
388 | raise format( "Maximum retries (%d) against '%s' reached. Giving up ...", max_retries, @icinga_api_url_base ) if( retried >= max_retries )
389 |
390 | retried += 1
391 | warn(format("Cannot execute request against '%s': '%s' (retry %d / %d)", @icinga_api_url_base, e, retried, max_retries))
392 | sleep(3)
393 | retry
394 |
395 | rescue RestClient::ExceptionWithResponse => e
396 |
397 | response = e.response
398 | response_body = response.body
399 | # response_code = response.code
400 |
401 | if( response_body =~ /{(.*)}{(.*)}/ )
402 | parts = response_body.match( /^{(?(.+))}{(.*)}/ )
403 | response_body = parts['regular'].to_s.strip
404 | response_body = format('{%s}', response_body )
405 | end
406 |
407 | begin
408 | response_body = JSON.parse(response_body) if response_body.is_a?(String)
409 | code = response.code.to_i
410 | status = response_body.dig('status')
411 |
412 | return { 'results' => [{ 'code' => code, 'status' => status }] }
413 |
414 | rescue => error
415 | puts(error)
416 | puts(error.backtrace.join("\n"))
417 |
418 | return { 'results' => [{ 'code' => 500, 'status' => error }] }
419 | end
420 |
421 | rescue RestClient::ExceptionWithResponse => e
422 |
423 | @logger.error( "Error: #{__method__} #{method_type.upcase} on #{endpoint} error: '#{e}'" )
424 | @logger.error( data )
425 | # @logger.error( @headers )
426 | # @logger.error( JSON.pretty_generate( response_headers ) )
427 |
428 | return { 'results' => [{ 'code' => 500, 'status' => e }] }
429 | end
430 |
431 | end
432 |
433 |
434 | end
435 | end
436 |
--------------------------------------------------------------------------------
/lib/icinga2/notifications.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 |
4 | module Icinga2
5 |
6 | # namespace for servicegroup handling
7 | module Notifications
8 |
9 | # enable host notifications
10 | #
11 | # @param [String] host
12 | #
13 | # @example
14 | # enable_host_notification('icinga')
15 | #
16 | # @return [Hash]
17 | #
18 | def enable_host_notification( host )
19 |
20 | raise ArgumentError.new(format('wrong type. \'host\' must be an String, given \'%s\'', host.class.to_s)) unless( host.is_a?(String) )
21 | raise ArgumentError.new('missing \'host\'') if( host.size.zero? )
22 |
23 | return { 'code' => 404, 'status' => 'Object not Found' } if( exists_host?( host ) == false )
24 |
25 | host_notification( name: host, enable_notifications: true )
26 | end
27 |
28 | # disable host notifications
29 | #
30 | # @param [String] host
31 | #
32 | # @example
33 | # disable_host_notification('icinga')
34 | #
35 | # @return [Hash]
36 | #
37 | def disable_host_notification( host )
38 |
39 | raise ArgumentError.new(format('wrong type. \'host\' must be an String, given \'%s\'', host.class.to_s)) unless( host.is_a?(String) )
40 | raise ArgumentError.new('missing \'host\'') if( host.size.zero? )
41 |
42 | return { 'code' => 404, 'status' => 'Object not Found' } if( exists_host?( host ) == false )
43 |
44 | host_notification( name: host, enable_notifications: false )
45 | end
46 |
47 | # enable service notifications
48 | #
49 | # @param [String] host
50 | #
51 | # @example
52 | # enable_service_notification('icinga')
53 | #
54 | # @return [Hash]
55 | #
56 | def enable_service_notification( host )
57 |
58 | raise ArgumentError.new(format('wrong type. \'host\' must be an String, given \'%s\'', host.class.to_s)) unless( host.is_a?(String) )
59 | raise ArgumentError.new('missing \'host\'') if( host.size.zero? )
60 |
61 | return { 'code' => 404, 'status' => 'Object not Found' } if( exists_host?( host ) == false )
62 |
63 | service_notification( name: host, enable_notifications: true )
64 | end
65 |
66 | # disable service notifications
67 | #
68 | # @param [String] host
69 | #
70 | # @example
71 | # disable_service_notification('icinga')
72 | #
73 | # @return [Hash]
74 | #
75 | def disable_service_notification( host )
76 |
77 | raise ArgumentError.new(format('wrong type. \'host\' must be an String, given \'%s\'', host.class.to_s)) unless( host.is_a?(String) )
78 | raise ArgumentError.new('missing \'host\'') if( host.size.zero? )
79 |
80 | return { 'code' => 404, 'status' => 'Object not Found' } if( exists_host?( host ) == false )
81 |
82 | service_notification( name: host, enable_notifications: false )
83 | end
84 |
85 | # enable hostgroup notifications
86 | #
87 | # @param [String] host_group
88 | #
89 | # @example
90 | # enable_hostgroup_notification('linux-servers')
91 | #
92 | # @return [Hash]
93 | #
94 | def enable_hostgroup_notification( host_group )
95 |
96 | raise ArgumentError.new(format('wrong type. \'host_group\' must be an String, given \'%s\'', host_group.class.to_s)) unless( host_group.is_a?(String) )
97 | raise ArgumentError.new('missing \'host_group\'') if( host_group.size.zero? )
98 |
99 | return { 'code' => 404, 'status' => 'Object not Found' } unless( exists_hostgroup?( host_group ) )
100 |
101 | hostgroup_notification( host_group: host_group, enable_notifications: true )
102 | end
103 |
104 | # disable hostgroup notifications
105 | #
106 | # @param [String] host_group
107 | #
108 | # @example
109 | # disable_hostgroup_notification('linux-servers')
110 | #
111 | # @return [Hash]
112 | #
113 | def disable_hostgroup_notification( host_group )
114 |
115 | raise ArgumentError.new(format('wrong type. \'host_group\' must be an String, given \'%s\'', host_group.class.to_s)) unless( host_group.is_a?(String) )
116 | raise ArgumentError.new('missing \'host_group\'') if( host_group.size.zero? )
117 |
118 | return { 'code' => 404, 'status' => 'Object not Found' } if( exists_hostgroup?( host_group ) == false )
119 |
120 | hostgroup_notification( host_group: host_group, enable_notifications: false )
121 | end
122 |
123 | # return all notifications
124 | #
125 | #
126 | # @return [Array]
127 | #
128 | def notifications
129 |
130 | api_data(
131 | url: format( '%s/objects/notifications', @icinga_api_url_base ),
132 | headers: @headers,
133 | options: @options
134 | )
135 | end
136 |
137 | protected
138 | # function for host notifications
139 | # @api protected
140 | #
141 | # @param [Hash] params
142 | # @option params [String] name
143 | # @option params [Bool] enable_notifications (false)
144 | #
145 | # @return [Hash]
146 | #
147 | def host_notification( params )
148 |
149 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
150 | raise ArgumentError.new('missing params') if( params.size.zero? )
151 |
152 | name = validate( params, required: true, var: 'name', type: String )
153 | notifications = validate( params, required: false, var: 'enable_notifications', type: Boolean ) || false
154 |
155 | payload = {
156 | attrs: {
157 | enable_notifications: notifications
158 | }
159 | }
160 |
161 | post(
162 | url: format( '%s/objects/hosts/%s', @icinga_api_url_base, name ),
163 | headers: @headers,
164 | options: @options,
165 | payload: payload
166 | )
167 | end
168 |
169 | # function for hostgroup notifications
170 | # @api protected
171 | #
172 | # @param [Hash] params
173 | # @option params [String] :host_group
174 | # @option params [Bool] :enable_notifications (false)
175 | #
176 | # @return [Hash]
177 | #
178 | def hostgroup_notification( params )
179 |
180 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
181 | raise ArgumentError.new('missing params') if( params.size.zero? )
182 |
183 | group = validate( params, required: true, var: 'host_group', type: String )
184 | notifications = validate( params, required: false, var: 'enable_notifications', type: Boolean ) || false
185 |
186 | payload = {
187 | filter: format( '"%s" in host.groups', group ),
188 | attrs: {
189 | enable_notifications: notifications
190 | }
191 | }
192 |
193 | post(
194 | url: format( '%s/objects/services', @icinga_api_url_base ),
195 | headers: @headers,
196 | options: @options,
197 | payload: payload
198 | )
199 | end
200 |
201 | # function for service notifications
202 | # @api protected
203 | #
204 | # @param [Hash] params
205 | # @option params [String] name
206 | # @option params [Bool] enable_notifications (false)
207 | #
208 | # @return [Hash]
209 | #
210 | def service_notification( params )
211 |
212 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
213 | raise ArgumentError.new('missing params') if( params.size.zero? )
214 |
215 | name = validate( params, required: true, var: 'name', type: String )
216 | notifications = validate( params, required: false, var: 'enable_notifications', type: Boolean ) || false
217 |
218 | payload = {
219 | filter: format( 'host.name=="%s"', name ),
220 | attrs: {
221 | enable_notifications: notifications
222 | }
223 | }
224 |
225 | post(
226 | url: format( '%s/objects/services', @icinga_api_url_base ),
227 | headers: @headers,
228 | options: @options,
229 | payload: payload
230 | )
231 | end
232 |
233 | end
234 | end
235 |
--------------------------------------------------------------------------------
/lib/icinga2/servicegroups.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 |
4 | module Icinga2
5 |
6 | # namespace for servicegroup handling
7 | module Servicegroups
8 |
9 | # add a servicegroup
10 | #
11 | # @param [Hash] params
12 | # @option params [String] service_group servicegroup to create
13 | # @option params [String] display_name the displayed name
14 | # @option params [String] notes
15 | # @option params [String] notes_url
16 | # @option params [String] action_url
17 | #
18 | # @example
19 | # add_servicegroup(service_group: 'foo', display_name: 'FOO')
20 | #
21 | # @return [Hash] result
22 | #
23 | def add_servicegroup( params )
24 |
25 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
26 | raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
27 |
28 | service_group = validate( params, required: true, var: 'service_group', type: String )
29 | display_name = validate( params, required: true, var: 'display_name', type: String )
30 | notes = validate( params, required: false, var: 'notes', type: String )
31 | notes_url = validate( params, required: false, var: 'notes_url', type: String )
32 | action_url = validate( params, required: false, var: 'action_url', type: String )
33 |
34 | payload = {
35 | attrs: {
36 | display_name: display_name,
37 | notes: notes,
38 | notes_url: notes_url,
39 | action_url: action_url
40 | }
41 | }
42 |
43 | # remove all empty attrs
44 | payload.reject!{ |_k, v| v.nil? }
45 | payload[:attrs].reject!{ |_k, v| v.nil? }
46 |
47 | put(
48 | url: format( '%s/objects/servicegroups/%s', @icinga_api_url_base, service_group ),
49 | headers: @headers,
50 | options: @options,
51 | payload: payload
52 | )
53 | end
54 |
55 | # delete a servicegroup
56 | #
57 | # @param [Hash] params
58 | # @option params [String] name servicegroup to delete
59 | # @option params [Bool] cascade (false) delete servicegroup also when other objects depend on it
60 | #
61 | # @example
62 | # delete_servicegroup('foo')
63 | #
64 | # @return [Array] result
65 | #
66 | def delete_servicegroup( params )
67 |
68 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
69 | raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
70 |
71 | name = validate( params, required: true, var: 'name', type: String )
72 | cascade = validate( params, required: false, var: 'cascade', type: Boolean ) || false
73 |
74 | return { 'code' => 404, 'status' => 'Object not Found' } if( exists_servicegroup?( name ) == false )
75 |
76 | url = format( '%s/objects/servicegroups/%s%s', @icinga_api_url_base, name, cascade.is_a?(TrueClass) ? '?cascade=1' : nil )
77 |
78 | delete(
79 | url: url,
80 | headers: @headers,
81 | options: @options
82 | )
83 | end
84 |
85 | # returns all servicegroups
86 | #
87 | # @param [String] service_group (nil) optional for a single servicegroup
88 | #
89 | # @example to get all users
90 | # servicegroups
91 | #
92 | # @example to get one user
93 | # servicegroups(service_group: 'disk')
94 | #
95 | # @return [Array] returns a hash with all servicegroups
96 | #
97 | def servicegroups( service_group = nil )
98 |
99 | raise ArgumentError.new(format('wrong type. \'service_group\' must be an String, given \'%s\'', service_group.class.to_s)) unless( service_group.nil? || service_group.is_a?(String) )
100 |
101 | url = format( '%s/objects/servicegroups' , @icinga_api_url_base )
102 | url = format( '%s/objects/servicegroups/%s', @icinga_api_url_base, service_group ) unless( service_group.nil? )
103 |
104 | api_data(
105 | url: url,
106 | headers: @headers,
107 | options: @options
108 | )
109 | end
110 |
111 | # checks if the servicegroup exists
112 | #
113 | # @param [String] service_group the name of the servicegroup
114 | #
115 | # @example
116 | # exists_servicegroup?('disk')
117 | #
118 | # @return [Bool] returns true if the servicegroup exists
119 | #
120 | def exists_servicegroup?( service_group )
121 |
122 | raise ArgumentError.new(format('wrong type. \'service_group\' must be an String, given \'%s\'', service_group.class.to_s)) unless( service_group.is_a?(String) )
123 | raise ArgumentError.new('Missing \'service_group\'') if( service_group.size.zero? )
124 |
125 | result = servicegroups(service_group)
126 | result = JSON.parse( result ) if result.is_a?( String )
127 | result = result.first if( result.is_a?(Array) )
128 |
129 | return false if( result.is_a?(Hash) && result.dig('code') == 404 )
130 |
131 | true
132 | end
133 |
134 | end
135 | end
136 |
--------------------------------------------------------------------------------
/lib/icinga2/statistics.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | #
3 |
4 | module Icinga2
5 |
6 | # namespace for icinga2 statistics
7 | module Statistics
8 |
9 |
10 | # return statistic data for latency and execution_time
11 | #
12 | # @example
13 | # latency, execution_time = average_statistics.values
14 | #
15 | # h = average_statistics
16 | # latency = h.dig(:latency)
17 | #
18 | # @return [Hash]
19 | # * latency (Float)
20 | # * execution_time (Float)
21 | #
22 | def average_statistics
23 |
24 | cib_data if((Time.now.to_i - @last_cib_data_called).to_i > @last_call_timeout)
25 |
26 | avg_latency = @avg_latency.nil? ? 0 : @avg_latency
27 | avg_execution_time = @avg_execution_time.nil? ? 0 : @avg_execution_time
28 |
29 | {
30 | latency: avg_latency.to_f,
31 | execution_time: avg_execution_time.to_f
32 | }
33 | end
34 |
35 | # return statistic data for intervall data
36 | #
37 | # @example
38 | # hosts_active_checks, hosts_passive_checks, services_active_checks, services_passive_checks = interval_statistics.values
39 | #
40 | # i = interval_statistics
41 | # hosts_active_checks = i.dig(:hosts_active_checks)
42 | #
43 | # @return [Hash]
44 | # * hosts_active_checks (Float)
45 | # * hosts_passive_checks (Float)
46 | # * services_active_checks (Float)
47 | # * services_passive_checks (Float)
48 | #
49 | def interval_statistics
50 |
51 | cib_data if((Time.now.to_i - @last_cib_data_called).to_i > @last_call_timeout)
52 |
53 | # take a look into https://github.com/Icinga/pkg-icinga2-debian/blob/master/lib/icinga/cib.cpp
54 |
55 | hosts_active_checks = @hosts_active_checks_1min.nil? ? 0 : @hosts_active_checks_1min
56 | hosts_passive_checks = @hosts_passive_checks_1min.nil? ? 0 : @hosts_passive_checks_1min
57 | services_active_checks = @services_active_checks_1min.nil? ? 0 : @services_active_checks_1min
58 | services_passive_checks = @services_passive_checks_1min.nil? ? 0 : @services_passive_checks_1min
59 |
60 | {
61 | hosts_active_checks: hosts_active_checks.to_f,
62 | hosts_passive_checks: hosts_passive_checks.to_f,
63 | services_active_checks: services_active_checks.to_f,
64 | services_passive_checks: services_passive_checks.to_f
65 | }
66 | end
67 |
68 | # return statistic data for services
69 | #
70 | # @example
71 | # ok, warning, critical, unknown, pending, in_downtime, ack = service_statistics.values
72 | #
73 | # s = service_statistics
74 | # critical = s.dig(:critical)
75 | #
76 | # @return [Hash]
77 | # * ok (Integer)
78 | # * warning (Integer)
79 | # * critical (Integer)
80 | # * unknown (Integer)
81 | # * pending (Integer)
82 | # * in_downtime (Integer)
83 | # * acknowledged (Integer)
84 | #
85 | def service_statistics
86 |
87 | cib_data if((Time.now.to_i - @last_cib_data_called).to_i > @last_call_timeout)
88 |
89 | services_ok = @services_ok.nil? ? 0 : @services_ok
90 | services_warning = @services_warning.nil? ? 0 : @services_warning
91 | services_critical = @services_critical.nil? ? 0 : @services_critical
92 | services_unknown = @services_unknown.nil? ? 0 : @services_unknown
93 | services_pending = @services_pending.nil? ? 0 : @services_pending
94 | services_in_downtime = @services_in_downtime.nil? ? 0 : @services_in_downtime
95 | services_acknowledged = @services_acknowledged.nil? ? 0 : @services_acknowledged
96 |
97 | {
98 | ok: services_ok.to_i,
99 | warning: services_warning.to_i,
100 | critical: services_critical.to_i,
101 | unknown: services_unknown.to_i,
102 | pending: services_pending.to_i,
103 | in_downtime: services_in_downtime.to_i,
104 | acknowledged: services_acknowledged.to_i
105 | }
106 | end
107 |
108 | # return statistic data for hosts
109 | #
110 | # @example
111 | # up, down, pending, unreachable, in_downtime, ack = host_statistics.values
112 | #
113 | # h = host_statistics
114 | # pending = h.dig(:pending)
115 | #
116 | # @return [Hash]
117 | # * up (Integer)
118 | # * down (Integer)
119 | # * pending (Integer)
120 | # * unreachable (Integer)
121 | # * in_downtime (Integer)
122 | # * acknowledged (Integer)
123 | #
124 | def host_statistics
125 |
126 | cib_data if((Time.now.to_i - @last_cib_data_called).to_i > @last_call_timeout)
127 |
128 | hosts_up = @hosts_up.nil? ? 0 : @hosts_up
129 | hosts_down = @hosts_down.nil? ? 0 : @hosts_down
130 | hosts_pending = @hosts_pending.nil? ? 0 : @hosts_pending
131 | hosts_unreachable = @hosts_unreachable.nil? ? 0 : @hosts_unreachable
132 | hosts_in_downtime = @hosts_in_downtime.nil? ? 0 : @hosts_in_downtime
133 | hosts_acknowledged = @hosts_acknowledged.nil? ? 0 : @hosts_acknowledged
134 |
135 | {
136 | up: hosts_up.to_i,
137 | down: hosts_down.to_i,
138 | pending: hosts_pending.to_i,
139 | unreachable: hosts_unreachable.to_i,
140 | in_downtime: hosts_in_downtime.to_i,
141 | acknowledged: hosts_acknowledged.to_i
142 | }
143 | end
144 |
145 |
146 | # return queue statistics from the api
147 | #
148 | # @example
149 | # work_queue_statistics
150 | #
151 | # @return [Hash]
152 | #
153 | def work_queue_statistics
154 |
155 | stats = {}
156 | data = api_data(
157 | url: format( '%s/status', @icinga_api_url_base ),
158 | headers: @headers,
159 | options: @options
160 | )
161 |
162 | return stats if data.nil?
163 |
164 | if( data.is_a?(Array) )
165 |
166 | json_rpc_data = data.find { |k| k['name'] == 'ApiListener' }
167 | graphite_data = data.find { |k| k['name'] == 'GraphiteWriter' }
168 | ido_mysql_data = data.find { |k| k['name'] == 'IdoMysqlConnection' }
169 |
170 | json_rpc_data = json_rpc_data.dig('status', 'api', 'json_rpc') unless( json_rpc_data.nil? )
171 | graphite_data = graphite_data.dig('status', 'graphitewriter', 'graphite') unless( graphite_data.nil? )
172 | ido_mysql_data = ido_mysql_data.dig('status', 'idomysqlconnection', 'ido-mysql') unless( ido_mysql_data.nil? )
173 |
174 | payload = {
175 | json_rpc: json_rpc_data,
176 | graphite: graphite_data,
177 | ido_mysql: ido_mysql_data
178 | }
179 |
180 | payload.reject!{ |_k, v| v.nil? }
181 |
182 | key_list = %w[work_queue_item_rate query_queue_item_rate]
183 |
184 | payload.each do |k,v|
185 | key_list.each do |key|
186 | if( v.include?( key ))
187 | attr_name = format('%s queue rate', k)
188 | stats[attr_name] = v[key].to_f.round(3)
189 | end
190 | end
191 | end
192 | end
193 |
194 | stats
195 | end
196 |
197 | end
198 | end
199 |
--------------------------------------------------------------------------------
/lib/icinga2/tools.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: false
3 |
4 | module Icinga2
5 |
6 | # namespache for tools
7 | module Tools
8 |
9 | # returns true for the last check
10 | # @private
11 | #
12 | # @param [Hash] object
13 | #
14 | # @return [Bool]
15 | #
16 | def object_has_been_checked?( object )
17 | object.dig('attrs', 'last_check') > 0
18 | end
19 |
20 | # parse version string and extract version and revision
21 | #
22 | # @param [String] version
23 | #
24 | # @return [String, String]
25 | #
26 | def parse_version( version )
27 |
28 | # version = "v2.4.10-504-gab4ba18"
29 | # version = "v2.4.10"
30 | version_map = version.split('-', 2)
31 | version_str = version_map.first
32 | # strip v2.4.10 (default) and r2.4.10 (Debian)
33 | version_str = version_str.scan(/^[vr]+(.*)/).last.first
34 |
35 | revision =
36 | if version_map.size > 1
37 | version_map.last
38 | else
39 | 'release'
40 | end
41 |
42 | [version_str, revision]
43 | end
44 |
45 |
46 | # return count of handled problems
47 | #
48 | # @param [Array] objects
49 | # @param [Integer] state (nil)
50 | #
51 | # @example for host objects
52 | # h_objects = host_objects
53 | # all = count_problems(h_objects)
54 | # down = count_problems(h_objects, Icinga2::HOSTS_DOWN)
55 | # critical = count_problems(h_objects, Icinga2::HOSTS_CRITICAL)
56 | # unknown = count_problems(h_objects, Icinga2::HOSTS_UNKNOWN)
57 | #
58 | # @example for service objects
59 | # s_objects = service_objects
60 | # all = count_problems(s_objects)
61 | # warning = count_problems(s_objects, Icinga2::SERVICE_STATE_WARNING)
62 | # critical = count_problems(s_objects, Icinga2::SERVICE_STATE_CRITICAL)
63 | # unknown = count_problems(s_objects, Icinga2::SERVICE_STATE_UNKNOWN)
64 | #
65 | # @return [Integer]
66 | #
67 | def count_problems( objects, state = nil )
68 |
69 | raise ArgumentError.new(format('wrong type. \'objects\' must be an Array, given \'%s\'', objects.class.to_s)) unless( objects.is_a?(Array) )
70 | #raise ArgumentError.new('missing objects') if( objects.size.zero? )
71 |
72 | raise ArgumentError.new(format('wrong type. \'state\' must be an Integer, given \'%s\'', state.class.to_s)) unless( state.nil? || state.is_a?(Integer) )
73 |
74 | # 0 = "Up" or "OK"
75 | # 1 = "Down" or "Warning"
76 | # 2 = "Critical"
77 | # 3 = "Unknown"
78 | compare_states = []
79 | compare_states = [1, 2, 3] unless( state.nil? )
80 |
81 | compare_states.push(state) if( state.is_a?(Integer) )
82 |
83 | objects = JSON.parse(objects) if objects.is_a?(String)
84 |
85 | f = objects.select do |t|
86 | t.dig('attrs','state') == state && \
87 | ( !t.dig('attrs','downtime_depth').nil? && t.dig('attrs','downtime_depth').zero?) && \
88 | ( !t.dig('attrs','acknowledgement').nil? && t.dig('attrs','acknowledgement').zero? )
89 | end
90 |
91 | f.size
92 | end
93 |
94 |
95 | # check, it an String a valid Json
96 | #
97 | # @param json [String] json
98 | #
99 | # @example
100 | # valid_json?( json )
101 | #
102 | # @return [Bool]
103 | #
104 | def valid_json?( json )
105 |
106 | begin
107 | JSON.parse( json )
108 | return true
109 | rescue JSON::ParserError => e
110 | @logger.error("json parse error: #{e}") if @debug
111 | return false
112 | end
113 |
114 | end
115 | end
116 | end
117 |
--------------------------------------------------------------------------------
/lib/icinga2/usergroups.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 |
4 | module Icinga2
5 |
6 | # namespace for usergroup handling
7 | module Usergroups
8 |
9 | # add a usergroup
10 | #
11 | # @param [Hash] params
12 | # @option params [String] user_group usergroup to create
13 | # @option params [String] display_name the displayed name
14 | #
15 | # @example
16 | # add_usergroup(user_group: 'foo', display_name: 'FOO')
17 | #
18 | # @return [Hash] result
19 | #
20 | def add_usergroup( params )
21 |
22 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
23 | raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
24 |
25 | user_group = validate( params, required: true, var: 'user_group', type: String )
26 | display_name = validate( params, required: false, var: 'display_name', type: String )
27 |
28 | payload = {
29 | attrs: {
30 | display_name: display_name
31 | }
32 | }
33 |
34 | # remove all empty attrs
35 | payload.reject!{ |_k, v| v.nil? }
36 | payload[:attrs].reject!{ |_k, v| v.nil? }
37 |
38 | put(
39 | url: format( '%s/objects/usergroups/%s', @icinga_api_url_base, user_group ),
40 | headers: @headers,
41 | options: @options,
42 | payload: payload
43 | )
44 | end
45 |
46 | # delete a usergroup
47 | #
48 | # @param [String] user_group usergroup to delete
49 | #
50 | # @example
51 | # delete_usergroup('foo')
52 | #
53 | # @return [Hash] result
54 | #
55 | def delete_usergroup( user_group )
56 |
57 | raise ArgumentError.new(format('wrong type. \'user_group\' must be an String, given \'%s\'', user_group.class.to_s)) unless( user_group.is_a?(String) )
58 | raise ArgumentError.new('missing \'user_group\'') if( user_group.size.zero? )
59 |
60 | delete(
61 | url: format( '%s/objects/usergroups/%s?cascade=1', @icinga_api_url_base, user_group ),
62 | headers: @headers,
63 | options: @options
64 | )
65 | end
66 |
67 | # returns all usersgroups
68 | #
69 | # @param [String] user_group (nil) optional for a single usergroup
70 | #
71 | # @example to get all users
72 | # usergroups
73 | #
74 | # @example to get one user
75 | # usergroups('icingaadmins')
76 | #
77 | # @return [Hash] returns a hash with all usergroups
78 | #
79 | def usergroups( user_group = nil )
80 |
81 | url = format( '%s/objects/usergroups' , @icinga_api_url_base )
82 | url = format( '%s/objects/usergroups/%s', @icinga_api_url_base, user_group ) unless( user_group.nil? )
83 |
84 | api_data(
85 | url: url,
86 | headers: @headers,
87 | options: @options
88 | )
89 | end
90 |
91 | # returns true if the usergroup exists
92 | #
93 | # @param [String] user_group the name of the usergroups
94 | #
95 | # @example
96 | # exists_usergroup?('icingaadmins')
97 | #
98 | # @return [Bool] returns true if the usergroup exists
99 | #
100 | def exists_usergroup?( user_group )
101 |
102 | raise ArgumentError.new(format('wrong type. \'user_group\' must be an String, given \'%s\'', user_group.class.to_s)) unless( user_group.is_a?(String) )
103 | raise ArgumentError.new('Missing \'user_group\'') if( user_group.size.zero? )
104 |
105 | result = usergroups( user_group )
106 | result = JSON.parse( result ) if result.is_a?( String )
107 | result = result.first if( result.is_a?(Array) )
108 |
109 | return false if( result.is_a?(Hash) && result.dig('code') == 404 )
110 |
111 | true
112 | end
113 |
114 | end
115 | end
116 |
--------------------------------------------------------------------------------
/lib/icinga2/users.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 |
4 | module Icinga2
5 |
6 | # namespace for User handling
7 | module Users
8 |
9 | # add a user
10 | #
11 | # @param [Hash] params
12 | # @option params [String] user_name user to create
13 | # @option params [String] display_name ('') the displayed name
14 | # @option params [String] email ('') the user email
15 | # @option params [String] pager ('') optional a pager
16 | # @option params [Bool] enable_notifications (false) enable notifications for this user
17 | # @option params [Array] groups ([]) a hash with groups
18 | # @option params [String] period
19 | # @option params [Array] states
20 | # @option params [Array] types
21 | # @option params [Hash] vars
22 | #
23 | # @example
24 | # param = {
25 | # user_name: 'foo',
26 | # display_name: 'FOO',
27 | # email: 'foo@bar.com',
28 | # pager: '0000',
29 | # groups: ['icingaadmins']
30 | # }
31 | # add_user(param)
32 | #
33 | # @return [Hash] result
34 | # * code [Integer]
35 | # * message [String]
36 | # * data (optional)
37 | #
38 | def add_user( params )
39 |
40 | raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
41 | raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
42 |
43 | user_name = validate( params, required: true, var: 'user_name', type: String )
44 | display_name = validate( params, required: false, var: 'display_name', type: String )
45 | email = validate( params, required: false, var: 'email', type: String )
46 | pager = validate( params, required: false, var: 'pager', type: String )
47 | notifications = validate( params, required: false, var: 'enable_notifications', type: Boolean ) || false
48 | groups = validate( params, required: false, var: 'groups', type: Array ) || []
49 | period = validate( params, required: false, var: 'period', type: String )
50 | states = validate( params, required: false, var: 'states', type: Array )
51 | types = validate( params, required: false, var: 'types', type: Array )
52 | vars = validate( params, required: false, var: 'vars', type: Hash ) || {}
53 |
54 | group_validate = []
55 |
56 | groups.each do |g|
57 | group_validate << g if exists_usergroup?( g ) == false
58 | end
59 |
60 | if( group_validate.count != 0 )
61 | return {
62 | 'code' => 404,
63 | 'message' => format('these groups are not exists: \'%s\'', group_validate.join(', ')),
64 | 'data' => params
65 | }
66 | end
67 |
68 | payload = {
69 | attrs: {
70 | display_name: display_name,
71 | email: email,
72 | pager: pager,
73 | enable_notifications: notifications,
74 | groups: groups,
75 | period: period,
76 | states: states,
77 | types: types,
78 | vars: vars
79 | }
80 | }
81 |
82 | # remove all empty attrs
83 | payload.reject!{ |_k, v| v.nil? }
84 | payload[:attrs].reject!{ |_k, v| v.nil? }
85 |
86 | put(
87 | url: format( '%s/objects/users/%s', @icinga_api_url_base, user_name ),
88 | headers: @headers,
89 | options: @options,
90 | payload: payload
91 | )
92 | end
93 |
94 | # delete a user
95 | #
96 | # @param [String] user_name user to delete
97 | #
98 | # @example
99 | # delete_user('foo')
100 | #
101 | # @return [Hash] result
102 | #
103 | def delete_user( user_name )
104 |
105 | raise ArgumentError.new(format('wrong type. \'user_name\' must be an String, given \'%s\'',user_name.class.to_s)) unless( user_name.is_a?(String) )
106 | raise ArgumentError.new('Missing user_name') if( user_name.size.zero? )
107 |
108 | delete(
109 | url: format( '%s/objects/users/%s?cascade=1', @icinga_api_url_base, user_name ),
110 | headers: @headers,
111 | options: @options
112 | )
113 | end
114 |
115 | # returns a named or all users
116 | #
117 | # @param [String] user_name ('') optional for a single user
118 | #
119 | # @example to get all users
120 | # users
121 | #
122 | # @example to get one user
123 | # users('icingaadmin')
124 | #
125 | # @return [Array]
126 | #
127 | def users( user_name = nil )
128 |
129 | url = format( '%s/objects/users' , @icinga_api_url_base )
130 | url = format( '%s/objects/users/%s', @icinga_api_url_base, user_name ) unless( user_name.nil? )
131 |
132 | api_data(
133 | url: url,
134 | headers: @headers,
135 | options: @options
136 | )
137 | end
138 |
139 | # checks if the user exists
140 | #
141 | # @param [String] user_name the name of the user
142 | #
143 | # @example
144 | # exists_user?('icingaadmin')
145 | #
146 | # @return [Bool] returns true if the user exists
147 | #
148 | def exists_user?( user_name )
149 |
150 | raise ArgumentError.new(format('wrong type. \'user_name\' must be an String, given \'%s\'', user_name.class.to_s)) unless( user_name.is_a?(String) )
151 | raise ArgumentError.new('Missing \'user_name\'') if( user_name.size.zero? )
152 |
153 | result = users( user_name )
154 | result = JSON.parse( result ) if result.is_a?( String )
155 | result = result.first if( result.is_a?(Array) )
156 |
157 | return false if( result.is_a?(Hash) && result.dig('code') == 404 )
158 |
159 | true
160 | end
161 |
162 | end
163 | end
164 |
--------------------------------------------------------------------------------
/lib/icinga2/validator.rb:
--------------------------------------------------------------------------------
1 |
2 | # class Hash
3 | # def assert_required_keys(*keys)
4 | # keys.flatten.each do |key|
5 | # raise ArgumentError.new("Required key: #{key.inspect}") unless key?(key)
6 | # end
7 | # end
8 | #
9 | # def assert_valid_keys(params, *valid_keys)
10 | # valid_keys.flatten!
11 | # params.each_key do |k|
12 | # unless valid_keys.include?(k)
13 | # raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
14 | # end
15 | # end
16 | # end
17 | # end
18 |
19 |
20 | module Icinga2
21 |
22 | # namespace for validate options
23 | module Validator
24 |
25 | # def validate_options!(params, options)
26 | # options[:optional] ||= []
27 | # options[:required] ||= []
28 | #
29 | # params = params.deep_symbolize_keys
30 | # params.assert_required_keys(options[:required])
31 | # params.assert_valid_keys(params, options[:required] + options[:optional])
32 | # end
33 |
34 | # function to validate function parameters
35 | #
36 | # @param [Hash] params
37 | # @param [Hash] options
38 | # @option options [Bool] requiered
39 | # @option options [String] vat
40 | # @option options [Object] type Ruby Object to check the valid type. e.g String, Ineger Hash, ...
41 | #
42 | # @example
43 | # name = validate( params, required: true, var: 'name', type: String )
44 | # vars = validate( params, required: false, var: 'vars', type: Hash )
45 | #
46 | # @return [Mixed] the variable from the parmas Hash or nil
47 | #
48 | def validate( params, options )
49 | required = options.dig(:required) || false
50 | var = options.dig(:var)
51 | type = options.dig(:type)
52 |
53 | params = params.deep_symbolize_keys
54 | variable = params.dig(var.to_sym)
55 |
56 | clazz = Object.const_get(type.to_s)
57 |
58 | raise ArgumentError.new(format('\'%s\' is requiered and missing!', var)) if(variable.nil? && required == true )
59 | raise ArgumentError.new(format('wrong type. \'%s\' must be an %s, given \'%s\'', var, type, variable.class.to_s)) unless( variable.nil? || variable.is_a?(clazz) )
60 |
61 | variable
62 | end
63 |
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/lib/icinga2/version.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 |
4 | module Icinga2
5 | # Current version of gem.
6 | VERSION = '1.0.0'.freeze
7 | end
8 |
--------------------------------------------------------------------------------
/lib/logging.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 |
4 | require 'logger'
5 |
6 | # taken from https://stackoverflow.com/questions/917566/ruby-share-logger-instance-among-module-classes
7 | #
8 | module Logging
9 |
10 | #
11 | #
12 | #
13 | def logger
14 | @logger ||= Logging.logger_for( self.class.name )
15 | end
16 |
17 | # Use a hash class-ivar to cache a unique Logger per class:
18 | @loggers = {}
19 |
20 | #
21 | #
22 | #
23 | class << self
24 | def logger_for( classname )
25 | @loggers[classname] ||= configure_logger_for( classname )
26 | end
27 |
28 | def configure_logger_for( classname )
29 |
30 | logger = Logger.new(STDOUT)
31 | logger.progname = classname
32 | logger.level = Logger::UNKNOWN
33 | logger.datetime_format = '%Y-%m-%d %H:%M:%S::%3N'
34 | logger.formatter = proc do |severity, datetime, progname, msg|
35 | "[#{datetime.strftime( logger.datetime_format )}] #{severity.ljust(5)} : #{progname} - #{msg}\n"
36 | end
37 |
38 | logger
39 | end
40 | end
41 |
42 | end
43 |
--------------------------------------------------------------------------------
/lib/monkey_patches.rb:
--------------------------------------------------------------------------------
1 |
2 | # -----------------------------------------------------------------------------
3 | # Monkey patches
4 |
5 | # Modify `Object`
6 | #
7 | # original from (https://gist.github.com/Integralist/9503099)
8 | #
9 | # None of the above solutions work with a multi-level hash
10 | # They only work on the first level: {:foo=>"bar", :level1=>{"level2"=>"baz"}}
11 | # The following two variations solve the problem in the same way
12 | # transform hash keys to symbols
13 | #
14 | # @example
15 | # multi_hash = { 'foo' => 'bar', 'level1' => { 'level2' => 'baz' } }
16 | # multi_hash = multi_hash.deep_string_keys
17 | #
18 | class Object
19 |
20 | def deep_symbolize_keys
21 | if( is_a?( Hash ) )
22 | return inject({}) do |memo, (k, v)|
23 | memo.tap { |m| m[k.to_sym] = v.deep_string_keys }
24 | end
25 | elsif( is_a?( Array ) )
26 | return map(&:deep_string_keys)
27 | end
28 |
29 | self
30 | end
31 |
32 | def deep_string_keys
33 | if( is_a?( Hash ) )
34 | return inject({}) do |memo, (k, v)|
35 | memo.tap { |m| m[k.to_s] = v.deep_string_keys }
36 | end
37 | elsif( is_a?( Array ) )
38 | return map(&:deep_string_keys)
39 | end
40 |
41 | self
42 | end
43 |
44 | end
45 |
46 | # -----------------------------------------------------------------------------
47 |
48 | # Monkey Patch for Array
49 | #
50 | class Array
51 |
52 | # add a compare function to Array class
53 | #
54 | # @example
55 | # a = ['aaa','bbb']
56 | # b = ['ccc','xxx']
57 | # a.compare(b)
58 | #
59 | # @return [Bool]
60 | #
61 | def compare( comparate )
62 | to_set == comparate.to_set
63 | end
64 | end
65 |
66 | # -----------------------------------------------------------------------------
67 |
68 | # Monkey Patch for Hash
69 | #
70 | class Hash
71 |
72 | # add a filter function to Hash Class
73 | #
74 | # @example
75 | # tags = [ 'foo', 'bar', 'fii' ]
76 | # useableTags = tags.filter( 'fii' )
77 | #
78 | # @return [Hash]
79 | #
80 | def filter( *args )
81 | if( args.size == 1 )
82 | args[0] = args[0].to_s if args[0].is_a?( Symbol )
83 | select { |key| key.to_s.match( args.first ) }
84 | else
85 | select { |key| args.include?( key ) }
86 | end
87 | end
88 | end
89 |
90 | # -----------------------------------------------------------------------------
91 |
92 | # Monkey Patch for Time
93 | #
94 | class Time
95 |
96 | # add function add_minutes to Time Class
97 | #
98 | # @example
99 | # time = Time.now
100 | # time = time.add_minutes(10)
101 | #
102 | # @return [Time]
103 | #
104 | def add_minutes(m)
105 | self + (60 * m)
106 | end
107 | end
108 |
109 | # -----------------------------------------------------------------------------
110 |
111 | # Monkey Patch to implement an Boolean Check
112 | # original from: https://stackoverflow.com/questions/3028243/check-if-ruby-object-is-a-boolean/3028378#3028378
113 | #
114 | #
115 | module Boolean; end
116 | class TrueClass; include Boolean; end
117 | class FalseClass; include Boolean; end
118 |
119 | true.is_a?(Boolean) #=> true
120 | false.is_a?(Boolean) #=> true
121 |
122 | # -----------------------------------------------------------------------------
123 |
124 | # Monkey Patch for String Class
125 | #
126 | class String
127 |
128 | # get the first character in a string
129 | #
130 | # original from https://stackoverflow.com/a/2730984
131 | #
132 | # @example
133 | # 'foo'.initial
134 | #
135 | # @return [String]
136 | #
137 | def initial
138 | self[0,1]
139 | end
140 | end
141 |
142 | # -----------------------------------------------------------------------------
143 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 |
2 | # frozen_string_literal: true
3 | # require 'pry'
4 | require 'rspec'
5 | require 'icinga2'
6 |
7 | # RSpec.configure do |config|
8 | # config.color_enabled = true
9 | # config.formatter = 'documentation'
10 | #
11 | # # Configure Timezone for proper tests
12 | # ENV['TZ'] = 'UTC'
13 | # end
14 |
--------------------------------------------------------------------------------