Vendor Galaxy Roles and Collections

This commit is contained in:
Stefan Bethke 2026-02-06 22:07:16 +01:00
commit 2aed20393f
3553 changed files with 387444 additions and 2 deletions

View file

@ -0,0 +1,19 @@
debops.icinga - Manage Icinga 2 Agent using Ansible
Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
Copyright (C) 2018 DebOps <https://debops.org/>
SPDX-License-Identifier: GPL-3.0-only
This Ansible role is part of DebOps.
DebOps is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3, as
published by the Free Software Foundation.
DebOps is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DebOps. If not, see https://www.gnu.org/licenses/.

View file

@ -0,0 +1,904 @@
---
# .. vim: foldmarker=[[[,]]]:foldmethod=marker
# .. Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# .. Copyright (C) 2018 DebOps <https://debops.org/>
# .. SPDX-License-Identifier: GPL-3.0-only
# .. _icinga__ref_defaults:
# debops.icinga default variables
# ===============================
# .. contents:: Sections
# :local:
#
# .. include:: ../../../../includes/global.rst
# Upstream configuration, APT packages [[[
# ----------------------------------------
# .. envvar:: icinga__upstream [[[
#
# Enable or disable support for Icinga 2 upstream packages instead of the ones
# included in a given OS release.
icinga__upstream: '{{ True
if (ansible_distribution_release in ["trusty"])
else False }}'
# ]]]
# .. envvar:: icinga__upstream_apt_key_id [[[
#
# The GPG key id of the upstream Icinga 2 APT repository.
icinga__upstream_apt_key_id: 'DD3A F619 8ED0 00B4 C0B7 3956 CC11 6F55 AA7F 2382'
# ]]]
# .. envvar:: icinga__upstream_apt_repo [[[
#
# The :file:`sources.list` entry of the upstream Icinga 2 APT repository.
icinga__upstream_apt_repo: 'deb https://packages.icinga.com/{{ icinga__distribution | lower }} icinga-{{ icinga__distribution_release | lower }} main'
# ]]]
# .. envvar:: icinga__distribution [[[
#
# Name of the OS distribution used to select the correct upstream APT
# repository.
icinga__distribution: '{{ ansible_local.core.distribution | d(ansible_distribution) }}'
# ]]]
# .. envvar:: icinga__distribution_release [[[
#
# Name of the OS release used to select the correct upstream APT repository.
icinga__distribution_release: '{{ ansible_local.core.distribution_release | d(ansible_distribution_release) }}'
# ]]]
# .. envvar:: icinga__version [[[
#
# The version of the installed Icinga 2 package, detected by the Ansible local
# fact script. This variable can be used in conditional Icinga 2 configuration.
icinga__version: '{{ ansible_local.icinga.version | d("0.0.0") }}'
# ]]]
# .. envvar:: icinga__base_packages [[[
#
# List of APT packages to install for Icinga 2 support.
icinga__base_packages:
- 'icinga2'
- 'ssl-cert'
- 'monitoring-plugins'
- 'nagios-plugins-contrib'
# ]]]
# .. envvar:: icinga__packages [[[
#
# List of additional APT packages to install with Icinga 2.
icinga__packages: []
# ]]]
# ]]]
# User and group configuration [[[
# --------------------------------
# .. envvar:: icinga__user [[[
#
# Name of the UNIX system account which is used to run Icinga 2. This account
# is created by the APT package and you shouldn't change it here.
icinga__user: 'nagios'
# ]]]
# .. envvar:: icinga__group [[[
#
# Name of the UNIX system group which is used to run Icinga 2. This group is
# created by the APT package and you shouldn't change it here.
icinga__group: 'nagios'
# ]]]
# .. envvar:: icinga__additional_groups [[[
#
# List of additional UNIX groups which the Icinga 2 user should be a member of.
icinga__additional_groups:
- 'ssl-cert'
- '{{ ansible_local.proc_hidepid.group
if (ansible_local.proc_hidepid.group | d() and
(ansible_local.proc_hidepid.enabled | d()) | bool)
else [] }}'
# ]]]
# ]]]
# Network, DNS configuration, API configuration [[[
# -------------------------------------------------
# .. envvar:: icinga__fqdn [[[
#
# The Fully Qualified Domain Name of this Icinga 2 node. This variable is used
# during the node registration in the Icinga 2 Director and in the zone
# configuration.
icinga__fqdn: '{{ ansible_fqdn }}'
# ]]]
# .. envvar:: icinga__display_name [[[
#
# The short display name of this Icinga 2 node. This variable is used during
# the node registration in the Icinga 2 Director and in the zone configuration.
icinga__display_name: '{{ (inventory_hostname_short | d(inventory_hostname.split(".")[0]))
if (inventory_hostname_short | d(inventory_hostname.split(".")[0]) != "localhost")
else ansible_hostname }}'
# ]]]
# .. envvar:: icinga__ipv4_address [[[
#
# The IPv4 address (or FQDN used to lookup the IPv4 address) of this Icinga 2
# node. This variable is used during the node registration in the Icinga 2
# Director (and will be used to contact the node for monitoring purposes).
icinga__ipv4_address: '{{ ansible_default_ipv4.address
| d(ansible_all_ipv4_addresses | d([]) | first)
| d(icinga_fqdn) }}'
# ]]]
# .. envvar:: icinga__ipv6_address [[[
#
# The IPv6 address (or FQDN used to lookup the IPv4 address) of this Icinga 2
# node. This variable is used during the node registration in the Icinga 2
# Director (and will be used to contact the node for monitoring purposes).
icinga__ipv6_address: '{{ ansible_default_ipv6.address
| d(ansible_all_ipv6_addresses | d([]) | first)
| d(omit, true) }}'
# ]]]
# .. envvar:: icinga__domain [[[
#
# The main DNS domain used by the role to configure Icinga 2.
icinga__domain: '{{ ansible_domain }}'
# ]]]
# .. envvar:: icinga__master_nodes [[[
#
# List which contains the result of the DNS query for Icinga 2 master node
# ``SRV`` resource records in the host's domain. This is a DebOps-specific
# feature, which does not have a corresponding RFC.
#
# See :ref:`icinga__ref_dns_config` for details if you want to specify this
# list manually.
icinga__master_nodes: '{{ q("debops.debops.dig_srv", "_icinga-master._tcp." + icinga__domain,
"icinga-master." + icinga__domain, icinga__api_port) }}'
# ]]]
# .. envvar:: icinga__master_delegate_to [[[
#
# The host to which tasks that must execute on the master node will be delegated.
# It's used when ``icinga__master_*_configuration`` is set and configuration
# files are written on the master node.
icinga__master_delegate_to: '{{ icinga__master_nodes[0]["target"] }}'
# ]]]
# .. envvar:: icinga__director_nodes [[[
#
# List which contains the result of the DNS query for Icinga 2 director node
# ``SRV`` resource records in the host's domain. This is a DebOps-specific
# feature, which does not have a corresponding RFC.
#
# Only the first entry in the list will be used to register a node.
#
# See :ref:`icinga__ref_dns_config` for details if you want to specify this
# list manually.
icinga__director_nodes: '{{ q("debops.debops.dig_srv", "_icinga-director._tcp." + icinga__domain,
"icinga-director." + icinga__domain, 443) }}'
# ]]]
# .. envvar:: icinga__node_type [[[
#
# Specify the type of this Icinga 2 node, either ``master`` or ``client``.
#
# Master nodes are not registered automatically in the Icinga 2 Director, and
# have the default API user configured automatically.
#
# Client nodes are registered in the Icinga 2 Director if one is available.
icinga__node_type: '{{ "master"
if (icinga__fqdn in
(icinga__master_nodes | map(attribute="target")) or
not icinga__director_enabled | bool)
else "client" }}'
# ]]]
# .. envvar:: icinga__allow [[[
#
# List of IP addresses or subnets that are allowed to talk to the Icinga
# 2 Agent over the network, configured on all hosts in the Ansible inventory.
# If no entries are specified, access through the firewall is disabled.
icinga__allow: []
# ]]]
# .. envvar:: icinga__group_allow [[[
#
# List of IP addresses or subnets that are allowed to talk to the Icinga
# 2 Agent over the network, configured on hosts in a specific Ansible inventory
# group. If no entries are specified, access through the firewall is disabled.
icinga__group_allow: []
# ]]]
# .. envvar:: icinga__host_allow [[[
#
# List of IP addresses or subnets that are allowed to talk to the Icinga
# 2 Agent over the network, configured on specific hosts in the Ansible
# inventory. If no entries are specified, access through the firewall is
# disabled.
icinga__host_allow: []
# ]]]
# .. envvar:: icinga__api_listen [[[
#
# IP address on which the Icinga 2 REST API should listen. Defaults to all IPv4
# and IPv6 addresses.
icinga__api_listen: '::'
# ]]]
# .. envvar:: icinga__api_port [[[
#
# The TCP port on which the Icinga 2 REST API should listen.
icinga__api_port: '5665'
# ]]]
# .. envvar:: icinga__api_user [[[
#
# The default user account for the REST API with superuser privileges. This
# account will be defined only on the master Icinga 2 nodes.
#
# This account is used by the :ref:`debops.icinga_web` Ansible role to perform
# the configuration kickstart and to access the Icinga REST API. It should be
# synchronized with the corresponding :envvar:`icinga_web__icinga_api_user`
# variable.
icinga__api_user: 'root'
# ]]]
# .. envvar:: icinga__api_password [[[
#
# The password for the Icinga 2 REST API "root" account. It will be generated
# only on the master Icinga 2 nodes. It should be synchronized with the
# corresponding :envvar:`icinga_web__icinga_api_password` variable.
icinga__api_password: '{{ lookup("password", secret + "/icinga/api/"
+ icinga__fqdn + "/credentials/"
+ icinga__api_user + "/password")
if (icinga__node_type == "master")
else "" }}'
# ]]]
# .. envvar:: icinga__api_permissions [[[
#
# List of the default permissions for the "root" account accessible via the
# REST API.
icinga__api_permissions: [ '*' ]
# ]]]
# ]]]
# Icinga 2 Director options [[[
# -----------------------------
# .. envvar:: icinga__director_enabled [[[
#
# Enable or disable support for the Icinga 2 Director configuration. Support
# will be automatically enabled if DNS ``SRV`` records exist for the Icinga 2
# master and director nodes.
#
# See :ref:`icinga__ref_dns_config` for more details.
icinga__director_enabled: '{{ True
if (icinga__master_nodes[0]["dig_srv_src"] | d("") != "fallback" and
icinga__director_nodes[0]["dig_srv_src"] | d("") != "fallback")
else False }}'
# ]]]
# .. envvar:: icinga__director_register [[[
#
# Enable or disable automatic registration of configured hosts in Icinga 2
# Director.
icinga__director_register: '{{ True
if (icinga__director_enabled | bool)
else False }}'
# ]]]
# .. envvar:: icinga__director_register_api_fqdn [[[
#
# The Fully Qualified Domain Name of the Icinga 2 Director host where a given
# host will be registered. The address will be found using DNS ``SRV`` records
# by default. See :ref:`icinga__ref_dns_config` for more details.
icinga__director_register_api_fqdn: '{{ icinga__director_nodes[0]["target"] }}'
# ]]]
# .. envvar:: icinga__director_register_api_url [[[
#
# The URL of the Icinga 2 Director REST API which will be used to register the
# host in Icinga 2 Director.
icinga__director_register_api_url: 'https://{{ icinga__director_register_api_fqdn }}/director/host'
# ]]]
# .. envvar:: icinga__director_register_api_user [[[
#
# The user account in the Icinga 2 Director REST API which will be used for
# host registration. This variable corresponds to the
# :envvar:`icinga_web__director_api_user` variable.
icinga__director_register_api_user: 'director-api'
# ]]]
# .. envvar:: icinga__director_register_api_password [[[
#
# The password of the Icinga 2 Director REST API user used to register the host
# in Icinga. This variable corresponds to the
# :envvar:`icinga_web__director_api_password` variable.
icinga__director_register_api_password: '{{ lookup("password", secret + "/icinga_web/api/"
+ icinga__director_register_api_fqdn + "/credentials/"
+ icinga__director_register_api_user + "/password") }}'
# ]]]
# .. envvar:: icinga__director_register_default_templates [[[
#
# List of default host templates to use for a given host during registration.
# The templates need to be prepared beforehand in the Icinga 2 Director.
icinga__director_register_default_templates:
- 'icinga-agent-host'
# ]]]
# .. envvar:: icinga__director_register_templates [[[
#
# List of host templates to use for a given host during registration. These
# templates are used for all hosts in the Ansible inventory. The templates
# need to be prepared beforehand in the Icinga 2 Director.
icinga__director_register_templates: []
# ]]]
# .. envvar:: icinga__director_register_group_templates [[[
#
# List of host templates to use for a given host during registration. These
# templates are used for hosts in a specific Ansible inventory group.
# The templates need to be prepared beforehand in the Icinga 2 Director.
icinga__director_register_group_templates: []
# ]]]
# .. envvar:: icinga__director_register_host_templates [[[
#
# List of host templates to use for a given host during registration. These
# templates are used for specific hosts in the Ansible inventory.
# The templates need to be prepared beforehand in the Icinga 2 Director.
icinga__director_register_host_templates: []
# ]]]
# .. envvar:: icinga__director_register_default_vars [[[
#
# YAML dictionary that contains default environment variables defined for
# a given host during registration. The key is the variable name, and the value
# is the variable value.
icinga__director_register_default_vars:
'ansible_managed': True
# ]]]
# .. envvar:: icinga__director_register_vars [[[
#
# YAML dictionary that contains environment variables defined for a given host
# during registration. These variables will be set for all hosts in the Ansible
# inventory. The key is the variable name, and the value is the variable value.
icinga__director_register_vars: {}
# ]]]
# .. envvar:: icinga__director_register_group_vars [[[
#
# YAML dictionary that contains environment variables defined for a given host
# during registration. These variables will be set for hosts in a specific
# Ansible inventory group. The key is the variable name, and the value is the
# variable value.
icinga__director_register_group_vars: {}
# ]]]
# .. envvar:: icinga__director_register_host_vars [[[
#
# YAML dictionary that contains environment variables defined for a given host
# during registration. These variables will be set for specific hosts in the
# Ansible inventory. The key is the variable name, and the value is the
# variable value.
icinga__director_register_host_vars: {}
# ]]]
# .. envvar:: icinga__director_register_host_object [[[
#
# The host object data passed to the Icinga 2 Director via the REST API during
# host registration.
icinga__director_register_host_object:
object_type: 'object'
object_name: '{{ icinga__fqdn }}'
display_name: '{{ icinga__display_name }}'
address: '{{ icinga__ipv4_address }}'
address6: '{{ icinga__ipv6_address }}'
imports: '{{ q("flattened",
(icinga__director_register_default_templates
+ icinga__director_register_templates
+ icinga__director_register_group_templates
+ icinga__director_register_host_templates)) }}'
vars: '{{ icinga__director_register_default_vars
| combine(icinga__director_register_vars,
icinga__director_register_group_vars,
icinga__director_register_host_vars) }}'
# ]]]
# .. envvar:: icinga__director_deploy [[[
#
# Enable or disable automatic deployment of new Icinga configuration via Icinga
# 2 Director. The deployment will be triggered only once if any host on the
# current run is registered in Icinga.
icinga__director_deploy: '{{ True
if (icinga__director_register | bool)
else False }}'
# ]]]
# .. envvar:: icinga__director_deploy_api_fqdn [[[
#
# The Fully Qualified Domain Name of the Icinga 2 Director host where the
# deployment will be performed. The address will be found using DNS SRV records
# by default. See :ref:`icinga__ref_dns_config` for more details.
icinga__director_deploy_api_fqdn: '{{ icinga__director_nodes[0]["target"] }}'
# ]]]
# .. envvar:: icinga__director_deploy_api_url [[[
#
# The REST API URL used to execute new configuration deployment.
icinga__director_deploy_api_url: 'https://{{ icinga__director_deploy_api_fqdn }}/director/config/deploy'
# ]]]
# .. envvar:: icinga__director_deploy_api_user [[[
#
# The user account in the Icinga 2 Director REST API which will be used for
# configuration deployment. This variable corresponds to the
# :envvar:`icinga_web__director_api_user` variable.
icinga__director_deploy_api_user: 'director-api'
# ]]]
# .. envvar:: icinga__director_deploy_api_password [[[
#
# The password of the Icinga 2 Director REST API user used to perform the
# configuration deployment. This variable corresponds to the
# :envvar:`icinga_web__director_api_password` variable.
icinga__director_deploy_api_password: '{{ lookup("password", secret + "/icinga_web/api/"
+ icinga__director_deploy_api_fqdn + "/credentials/"
+ icinga__director_deploy_api_user + "/password") }}'
# ]]]
# ]]]
# DebOps PKI support [[[
# ----------------------
# .. envvar:: icinga__pki_enabled [[[
#
# Enable or disable support for DebOps PKI. If disabled, Icinga will be
# configured with the default certificate and key paths, but no further
# configuration will be done to create the internal PKI.
icinga__pki_enabled: '{{ True
if (ansible_local | d() and ansible_local.pki | d() and
(ansible_local.pki.enabled | d()) | bool)
else False }}'
# ]]]
# .. envvar:: icinga__pki_path [[[
#
# The base path where the PKI realms are located.
icinga__pki_path: '{{ ansible_local.pki.path | d("/etc/pki/realms") }}'
# ]]]
# .. envvar:: icinga__pki_realm [[[
#
# Name of the PKI realm to use for Icinga REST API.
icinga__pki_realm: '{{ ansible_local.pki.realm | d("domain") }}'
# ]]]
# .. envvar:: icinga__pki_ca [[[
#
# Name of the file which contains the Root Certificate Authority certificate.
icinga__pki_ca: '{{ ansible_local.pki.ca | d("CA.crt") }}'
# ]]]
# .. envvar:: icinga__pki_crt [[[
#
# Name of the file which contains the server certificate.
icinga__pki_crt: '{{ ansible_local.pki.crt | d("default.crt") }}'
# ]]]
# .. envvar:: icinga__pki_key [[[
#
# Name of the file which contains the private key.
icinga__pki_key: '{{ ansible_local.pki.key | d("default.key") }}'
# ]]]
# .. envvar:: icinga__pki_cert_path [[[
#
# Absolute path of the X.509 server certificate used by Icinga.
icinga__pki_cert_path: '{{ icinga__pki_path + "/" + icinga__pki_realm
+ "/" + icinga__pki_crt }}'
# ]]]
# .. envvar:: icinga__pki_key_path [[[
#
# Absolute path of the X.509 private key used by Icinga.
icinga__pki_key_path: '{{ icinga__pki_path + "/" + icinga__pki_realm
+ "/" + icinga__pki_key }}'
# ]]]
# .. envvar:: icinga__pki_ca_path [[[
#
# Absolute path of the Root Certificate Authority used by Icinga.
icinga__pki_ca_path: '{{ icinga__pki_path + "/" + icinga__pki_realm
+ "/" + icinga__pki_ca }}'
# ]]]
# ]]]
# Icinga configuration files [[[
# ------------------------------
# These lists manage the files and directories stored in the
# :file:`/etc/icinga2/` directory. See the :ref:`icinga__ref_configuration` for
# more details.
# .. envvar:: icinga__default_configuration [[[
#
# The default Icinga configuration files defined by the role.
icinga__default_configuration:
- name: 'icinga2.conf'
divert: True
comment: |
Icinga 2 configuration file
- this is where you define settings for the Icinga application including
which hosts/services to check.
For an overview of all available configuration options please refer
to the documentation that is distributed as part of Icinga 2.
options:
- name: 'constants'
comment: 'The constant.conf defines global constants.'
value: |
include "constants.conf"
state: 'present'
- name: 'zones'
comment: |
The zones.conf defines zones for a cluster setup.
Not required for single instance setups.
value: |
include "zones.conf"
state: 'present'
- name: 'itl'
comment: |
The Icinga Template Library (ITL) provides a number of useful templates
and command definitions.
Common monitoring plugin command definitions are included separately.
value: |
include <itl>
include <plugins>
include <plugins-contrib>
include <manubulon>
state: 'present'
- name: 'windows_plugins'
comment: |
This includes the Icinga 2 Windows plugins. These command definitions
are required on a master node when a client is used as command endpoint.
value: |
include <windows-plugins>
state: 'present'
- name: 'nscp'
comment: |
This includes the NSClient++ check commands. These command definitions
are required on a master node when a client is used as command endpoint.
value: |
include <nscp>
state: 'present'
- name: 'features_enabled'
comment: |
The features-available directory contains a number of configuration
files for features which can be enabled and disabled using the
icinga2 feature enable / icinga2 feature disable CLI commands.
These commands work by creating and removing symbolic links in
the features-enabled directory.
value: |
include "features-enabled/*.conf"
state: 'present'
- name: 'repository.d'
comment: |
The repository.d directory contains all configuration objects
managed by the 'icinga2 repository' CLI commands.
value: |
include_recursive "repository.d"
state: '{{ "absent"
if (icinga__version is version("2.8.0", ">="))
else "present" }}'
- name: 'conf.d'
comment: |
Although in theory you could define all your objects in this file
the preferred way is to create separate directories and files in the conf.d
directory. Each of these files must have the file extension ".conf".
value: |
include_recursive "conf.d"
state: '{{ "absent" if (icinga__director_enabled | bool) else "present" }}'
- name: 'api_users'
comment: |
Read the API User objects on master node.
value: |
include "conf.d/api-users.conf"
state: '{{ "present"
if (icinga__director_enabled | bool and
icinga__node_type == "master")
else "absent" }}'
- name: 'zones.conf'
divert: True
comment: |
Endpoint and Zone configuration for a cluster setup
This local example requires 'NodeName' defined in
constants.conf
options:
- name: 'object_master'
value: |
{% for record in icinga__master_nodes %}
{% if record.target | d() %}
object Endpoint "{{ record.target | regex_replace('\.$', '') }}" {
host = "{{ record.target | regex_replace('\.$', '') }}"
port = "{{ record.port }}"
}
{% endif %}
{% endfor %}
object Zone "master" {
endpoints = [ "{{ icinga__master_nodes | map(attribute='target') | join('", "') }}" ]
}
state: '{{ "present"
if (icinga__node_type != "master" and
icinga__master_nodes[0]["dig_srv_src"] | d("") != "fallback")
else "absent" }}'
- name: 'object_node'
value: |
object Endpoint NodeName {
host = NodeName
}
object Zone ZoneName {
endpoints = [ NodeName ]
{% if (icinga__director_enabled | bool and icinga__node_type != 'master') %}
parent = "master"
{% endif %}
}
state: 'present'
- name: 'object_global_templates'
value: |
object Zone "global-templates" {
global = true
}
state: 'present'
- name: 'object_director_global'
value: |
object Zone "director-global" {
global = true
}
state: '{{ "present" if (icinga__director_enabled | bool) else "absent" }}'
- name: 'conf.d/api-users.conf'
comment: 'The APIUser objects are used for authentication against the API.'
group: '{{ icinga__group }}'
mode: '0640'
no_log: '{{ debops__no_log | d(True) }}'
state: '{{ "present"
if (icinga__node_type == "master")
else "absent" }}'
options:
- name: 'api_user_root'
value: |
object ApiUser "{{ icinga__api_user }}" {
password = "{{ icinga__api_password }}"
permissions = [ "{{ icinga__api_permissions | join('", "') }}" ]
}
state: 'present'
- name: 'features-available/api.conf'
divert: True
comment: 'The API listener is used for distributed monitoring setups.'
value: |
object ApiListener "api" {
bind_host = "{{ icinga__api_listen }}"
bind_port = {{ icinga__api_port }}
{% if icinga__pki_enabled | bool %}
cert_path = "{{ icinga__pki_cert_path }}"
key_path = "{{ icinga__pki_key_path }}"
ca_path = "{{ icinga__pki_ca_path }}"
{% else %}
cert_path = SysconfDir + "/icinga2/pki/" + NodeName + ".crt"
key_path = SysconfDir + "/icinga2/pki/" + NodeName + ".key"
ca_path = SysconfDir + "/icinga2/pki/ca.crt"
{% endif %}
accept_config = {{ 'false' if (icinga__director_enabled | bool and icinga__node_type == 'master') else 'true' }}
accept_commands = {{ 'false' if (icinga__director_enabled | bool and icinga__node_type == 'master') else 'true' }}
ticket_salt = TicketSalt
}
state: 'present'
feature_name: 'api'
feature_state: 'present'
- name: 'features-available/notification.conf'
divert: True
state: '{{ "init" if (icinga__node_type == "master") else "feature" }}'
feature_name: 'notification'
feature_state: '{{ "present" if (icinga__node_type == "master") else "absent" }}'
- name: 'features-available/checker.conf'
divert: True
state: '{{ "init" if (icinga__node_type == "master") else "feature" }}'
feature_name: 'checker'
feature_state: '{{ "present" if (icinga__node_type == "master") else "absent" }}'
# ]]]
# .. envvar:: icinga__configuration [[[
#
# List of the Icinga configuration files managed on all hosts in the Ansible
# inventory.
icinga__configuration: []
# ]]]
# .. envvar:: icinga__group_configuration [[[
#
# List of the Icinga configuration files managed on hosts in a specific Ansible
# inventory group.
icinga__group_configuration: []
# ]]]
# .. envvar:: icinga__host_configuration [[[
#
# List of the Icinga configuration files managed on specific hosts in the
# Ansible inventory.
icinga__host_configuration: []
# ]]]
# .. envvar:: icinga__dependent_configuration [[[
#
# List of the Icinga configuration files defined by other Ansible roles using
# role-dependent variables. See :ref:`icinga__ref_dependency` for more details
# about the usage.
icinga__dependent_configuration: []
# ]]]
# .. envvar:: icinga__dependent_configuration_filter [[[
#
# Variable which contains the parsed list of Icinga configuration files defined
# by other Ansible roles.
icinga__dependent_configuration_filter: '{{ lookup("template",
"lookup/icinga__dependent_configuration_filter.j2")
| from_yaml }}'
# ]]]
# .. envvar:: icinga__combined_configuration [[[
#
# Variable which combines all of the other Icinga configuration lists and is
# used in the role tasks.
icinga__combined_configuration: '{{ icinga__default_configuration
+ icinga__dependent_configuration_filter
+ icinga__configuration
+ icinga__group_configuration
+ icinga__host_configuration }}'
# ]]]
# ]]]
# Icinga master node's configuration files [[[
# --------------------------------------------
# These lists manage the files and directories stored in the
# :file:`/etc/icinga2/zones.d/` directory on the Icinga master node.
# It may be used when the setup of an Icinga agent needs to add config files
# to the master node. It's useful when Director module is not used and
# Icinga objects (Zone, Endpoint, Host, ...) need to be defined both
# on the agent and the master nodes.
# The syntax for ``icinga__master_*_configuration`` variables is the
# same as :ref:`icinga__ref_configuration`.
# .. envvar:: icinga__master_configuration [[[
#
# List of the Icinga configuration files defined on the master node for
# every host.
icinga__master_configuration: []
# ]]]
# .. envvar:: icinga__master_group_configuration [[[
#
# List of the Icinga configuration files defined on the master node for
# hosts in a specific Ansible inventory group.
icinga__master_group_configuration: []
# ]]]
# .. envvar:: icinga__master_host_configuration [[[
#
# List of the Icinga configuration files defined on the master node for
# specific hosts in the Ansible inventory.
icinga__master_host_configuration: []
# ]]]
# .. envvar:: icinga__master_combined_configuration [[[
#
# Variable which combines Icinga master node configuration from previous
# variables.
icinga__master_combined_configuration: '{{ icinga__master_configuration
+ icinga__master_group_configuration
+ icinga__master_host_configuration }}'
# ]]]
# ]]]
# Custom files managed with Icinga [[[
# ------------------------------------
# These lists can be used to manage custom files (by default scripts) on the
# hosts along with Icinga. See :ref:`icinga__ref_custom_files` for more
# details.
# .. envvar:: icinga__custom_files [[[
#
# List of custom files managed on all hosts in the Ansible inventory.
icinga__custom_files: []
# ]]]
# .. envvar:: icinga__group_custom_files [[[
#
# List of custom files managed on hosts in a specific Ansible inventory group.
icinga__group_custom_files: []
# ]]]
# .. envvar:: icinga__host_custom_files [[[
#
# List of custom files managed on specific hosts in the Ansible inventory.
icinga__host_custom_files: []
# ]]]
# ]]]
# Configuration for other Ansible roles [[[
# -----------------------------------------
# .. envvar:: icinga__etc_services__dependent_list [[[
#
# Configuration for the :ref:`debops.etc_services` Ansible role.
icinga__etc_services__dependent_list:
- name: 'icinga-api'
port: '{{ icinga__api_port }}'
comment: 'Icinga 2 REST API'
# ]]]
# .. envvar:: icinga__keyring__dependent_apt_keys [[[
#
# Configuration for the :ref:`debops.keyring` Ansible role.
icinga__keyring__dependent_apt_keys:
- id: '{{ icinga__upstream_apt_key_id }}'
repo: '{{ icinga__upstream_apt_repo }}'
state: '{{ "present" if icinga__upstream | bool else "absent" }}'
# ]]]
# .. envvar:: icinga__ferm__dependent_rules [[[
#
# Configuration for the :ref:`debops.ferm` Ansible role.
icinga__ferm__dependent_rules:
- type: 'accept'
dport: [ 'icinga-api' ]
saddr: '{{ icinga__allow + icinga__group_allow + icinga__host_allow }}'
accept_any: False
weight: '40'
by_role: 'icinga'
name: 'icinga_api'
# ]]]
# .. envvar:: icinga__unattended_upgrades__dependent_origins [[[
#
# List of origin patterns managed by the :ref:`debops.unattended_upgrades` role.
icinga__unattended_upgrades__dependent_origins:
- origin: 'site=packages.icinga.com'
by_role: 'debops.icinga'
state: '{{ "present" if icinga__upstream | bool else "absent" }}'
# ]]]
# ]]]

View file

@ -0,0 +1,30 @@
---
# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
- name: Check icinga2 configuration and restart it on the master node
ansible.builtin.command: icinga2 daemon -C
register: icinga__register_check_config
changed_when: icinga__register_check_config.changed | bool
notify: [ 'Restart icinga2 on the master node' ]
delegate_to: '{{ icinga__master_delegate_to }}'
- name: Restart icinga2 on the master node
ansible.builtin.service:
name: 'icinga2'
state: 'restarted'
delegate_to: '{{ icinga__master_delegate_to }}'
- name: Trigger Icinga Director configuration deployment
ansible.builtin.uri:
body_format: 'json'
headers:
Accept: 'application/json'
method: 'POST'
url: '{{ icinga__director_deploy_api_url }}'
user: '{{ icinga__director_deploy_api_user }}'
password: '{{ icinga__director_deploy_api_password }}'
run_once: True
when: icinga__director_deploy | bool
no_log: '{{ debops__no_log | d(True) }}'

View file

@ -0,0 +1,31 @@
---
# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018-2022 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
# Ensure that custom Ansible plugins and modules included in the main DebOps
# collection are available to roles in other collections.
collections: [ 'debops.debops' ]
dependencies: []
galaxy_info:
author: 'Maciej Delmanowski'
description: 'Manage Icinga 2 installation'
company: 'DebOps'
license: 'GPL-3.0-only'
min_ansible_version: '2.4.0'
platforms:
- name: 'Ubuntu'
versions: [ 'all' ]
- name: 'Debian'
versions: [ 'all' ]
galaxy_tags:
- monitoring
- icinga
- nagios

View file

@ -0,0 +1,197 @@
---
# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
- name: Import Custom Ansible plugins
ansible.builtin.import_role:
name: 'ansible_plugins'
- name: Import DebOps global handlers
ansible.builtin.import_role:
name: 'global_handlers'
- name: Import DebOps secret role
ansible.builtin.import_role:
name: 'secret'
- name: Install required Icinga packages
ansible.builtin.package:
name: '{{ lookup("flattened",
(icinga__base_packages + icinga__packages),
wantlist=True) }}'
state: 'present'
register: icinga__register_packages
until: icinga__register_packages is succeeded
- name: Add Icinga user to system UNIX groups
ansible.builtin.user:
name: '{{ icinga__user }}'
groups: '{{ lookup("flattened", icinga__additional_groups, wantlist=True) | join(",") }}'
append: True
notify: [ 'Check icinga2 configuration and restart' ]
- name: Load dependent configuration variables
ansible.builtin.include_vars:
dir: '{{ secret + "/icinga/dependent_config/" + inventory_hostname }}'
depth: 1
name: 'icinga__vars_dependent_configuration'
when: (ansible_local | d() and ansible_local.icinga | d() and
(ansible_local.icinga.configured | d()) | bool)
- name: Make sure that Ansible local facts directory exists
ansible.builtin.file:
path: '/etc/ansible/facts.d'
state: 'directory'
owner: 'root'
group: 'root'
mode: '0755'
- name: Save Icinga local facts
ansible.builtin.template:
src: 'etc/ansible/facts.d/icinga.fact.j2'
dest: '/etc/ansible/facts.d/icinga.fact'
owner: 'root'
group: 'root'
mode: '0755'
notify: [ 'Refresh host facts' ]
tags: [ 'meta::facts' ]
- name: Update Ansible facts if they were modified
ansible.builtin.meta: 'flush_handlers'
- name: Add/remove diversion of Icinga configuration files
debops.debops.dpkg_divert:
path: '{{ "/etc/icinga2/" + item.filename | d(item.name | regex_replace(".conf$", "") + ".conf") }}'
state: '{{ item.state | d("present") }}'
delete: True
loop: '{{ icinga__combined_configuration | debops.debops.parse_kv_items }}'
loop_control:
label: '{{ {"name": item.name, "state": item.state | d("present")} }}'
notify: [ 'Check icinga2 configuration and restart' ]
when: (item.name | d() and
item.state | d('present') in ['absent', 'present'] and
item.divert | d(False) | bool)
- name: Ensure that configuration directories exist
ansible.builtin.file:
path: '/etc/icinga2/{{ (item.filename | d(item.name | regex_replace(".conf$", "") + ".conf")) | dirname }}'
state: 'directory'
owner: 'root'
group: 'root'
mode: '0755'
with_items: '{{ icinga__combined_configuration | debops.debops.parse_kv_items }}'
when: (item.name | d() and item.state | d('present') not in ['absent', 'ignore', 'init', 'feature'] and
((item.filename | d(item.name | regex_replace(".conf$", "") + ".conf")) | dirname | d()))
- name: Remove Icinga configuration files
ansible.builtin.file:
path: '/etc/icinga2/{{ item.filename | d(item.name | regex_replace(".conf$", "") + ".conf") }}'
state: 'absent'
with_items: '{{ icinga__combined_configuration | debops.debops.parse_kv_items }}'
notify: [ 'Check icinga2 configuration and restart' ]
when: (item.name | d() and item.state | d('present') == 'absent' and
not item.divert | d(False) | bool)
- name: Generate Icinga configuration files
ansible.builtin.template:
src: 'etc/icinga2/template.conf.j2'
dest: '/etc/icinga2/{{ item.filename | d(item.name | regex_replace(".conf$", "") + ".conf") }}'
owner: '{{ item.owner | d("root") }}'
group: '{{ item.group | d("root") }}'
mode: '{{ item.mode | d("0644") }}'
with_items: '{{ icinga__combined_configuration | debops.debops.parse_kv_items }}'
notify: [ 'Check icinga2 configuration and restart' ]
when: (item.name | d() and item.state | d('present') not in ['absent', 'ignore', 'init', 'divert', 'feature'])
no_log: '{{ debops__no_log | d(item.no_log) | d(False) }}'
- name: Ensure that configuration directories exist on the master node
ansible.builtin.file:
path: '/etc/icinga2/zones.d/{{ (item.filename | d(item.name | regex_replace(".conf$", "") + ".conf")) | dirname }}'
state: 'directory'
recurse: true
owner: 'root'
group: 'root'
mode: '0755'
with_items: '{{ icinga__master_combined_configuration | debops.debops.parse_kv_items }}'
delegate_to: '{{ icinga__master_delegate_to }}'
when: (item.name | d() and item.state | d('present') not in ['absent', 'ignore', 'init', 'feature'] and
((item.filename | d(item.name | regex_replace(".conf$", "") + ".conf")) | dirname | d()))
- name: Remove Icinga configuration on the master node if requested
ansible.builtin.file:
path: '/etc/icinga2/zones.d/{{ item.filename | d(item.name | regex_replace(".conf$", "") + ".conf") }}'
state: 'absent'
with_items: '{{ icinga__master_combined_configuration | debops.debops.parse_kv_items }}'
delegate_to: '{{ icinga__master_delegate_to }}'
notify: [ 'Check icinga2 configuration and restart it on the master node' ]
when: (item.name | d() and item.state | d('present') == 'absent')
- name: Generate Icinga configuration files on the master node
ansible.builtin.template:
src: 'etc/icinga2/template.conf.j2'
dest: '/etc/icinga2/zones.d/{{ item.filename | d(item.name | regex_replace(".conf$", "") + ".conf") }}'
owner: '{{ item.owner | d("root") }}'
group: '{{ item.group | d("root") }}'
mode: '{{ item.mode | d("0644") }}'
with_items: '{{ icinga__master_combined_configuration | debops.debops.parse_kv_items }}'
delegate_to: '{{ icinga__master_delegate_to }}'
notify: [ 'Check icinga2 configuration and restart it on the master node' ]
when: (item.name | d() and item.state | d('present') not in ['absent', 'ignore', 'init', 'divert', 'feature'])
no_log: '{{ debops__no_log | d(item.no_log) | d(False) }}'
- name: Configure state of Icinga features
ansible.builtin.file:
path: '/etc/icinga2/features-enabled/{{ item.feature_name }}.conf'
src: '{{ ("../features-available/" + item.feature_name + ".conf")
if (item.feature_state | d("present") == "present") else omit }}'
state: '{{ "link" if item.feature_state | d("present") == "present" else "absent" }}'
mode: '0644'
force: '{{ True if ansible_check_mode | bool else omit }}'
with_items: '{{ icinga__combined_configuration | debops.debops.parse_kv_items }}'
notify: [ 'Check icinga2 configuration and restart' ]
when: (item.name | d() and item.state | d('present') not in ['absent', 'ignore', 'init', 'divert'] and
item.feature_name | d() and item.feature_state | d())
- name: Copy custom files for Icinga
ansible.builtin.copy:
content: '{{ item.content | d(omit) }}'
src: '{{ item.src | d(omit) }}'
dest: '{{ item.dest | d(omit) }}'
force: '{{ item.force | d(omit) }}'
owner: '{{ item.owner | d("root") }}'
group: '{{ item.group | d("root") }}'
mode: '{{ item.mode | d("0755") }}'
loop: '{{ q("flattened", icinga__custom_files
+ icinga__group_custom_files
+ icinga__host_custom_files) }}'
when: ((item.src | d() or item.content | d()) and
item.dest | d() and item.state | d("present") != "absent")
- name: Save dependent configuration on Ansible Controller
ansible.builtin.template:
src: 'secret/icinga/dependent_config/inventory_hostname/configuration.json.j2'
dest: '{{ secret + "/icinga/dependent_config/" + inventory_hostname + "/configuration.json" }}'
mode: '0644'
become: False
delegate_to: 'localhost'
- name: Register Icinga node in Icinga Director
ansible.builtin.uri:
body_format: 'json'
headers:
Accept: 'application/json'
method: 'POST'
body: '{{ icinga__director_register_host_object }}'
url: '{{ icinga__director_register_api_url }}'
user: '{{ icinga__director_register_api_user }}'
password: '{{ icinga__director_register_api_password }}'
status_code: [ 201, 422, 500 ]
force_basic_auth: True
register: icinga__register_director_host
notify: [ 'Trigger Icinga Director configuration deployment' ]
when: (icinga__director_enabled | bool and icinga__director_register | bool and
(icinga__node_type != 'master' or (ansible_local.icinga_web.installed | d()) | bool))
changed_when: icinga__register_director_host.status == 201
tags: [ 'role::icinga:register' ]
no_log: '{{ debops__no_log | d(True) }}'

View file

@ -0,0 +1,8 @@
---
# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
- name: Prepare Icinga environment
ansible.builtin.set_fact:
icinga__secret__directories: '{{ lookup("template", "lookup/icinga__secret__directories.j2") | from_yaml }}'

View file

@ -0,0 +1,39 @@
#!{{ ansible_python['executable'] }}
# -*- coding: utf-8 -*-
# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
# {{ ansible_managed }}
from __future__ import print_function
from json import loads, dumps
from sys import exit
import subprocess
import os
def cmd_exists(cmd):
return any(
os.access(os.path.join(path, cmd), os.X_OK)
for path in os.environ["PATH"].split(os.pathsep)
)
output = loads('''{{ {"installed": False,
"configured": True}
| to_nice_json }}''')
output['installed'] = cmd_exists('icinga2')
try:
icinga_version_stdout = subprocess.check_output(
["dpkg-query", "-W", "-f=${Version}",
"icinga2"]).decode('utf-8').split('-')[0]
output['version'] = icinga_version_stdout
except Exception:
pass
print(dumps(output, sort_keys=True, indent=4))

View file

@ -0,0 +1,43 @@
{# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
#}
{% macro print_comment(comment) %}
{% if (comment | regex_replace('\n$','')).split('\n') | count == 1 %}
{{ comment | regex_replace('\n$','') | comment('plain', decoration='// ', prefix='', postfix='') -}}
{% else %}
{{ comment | regex_replace('\n$','') | comment('plain', decoration=' * ', prefix='/**', postfix=' */\n') -}}
{% endif %}
{% endmacro %}
{{ print_comment(ansible_managed) }}
{% if item.comment | d() %}
{{ print_comment(item.comment) -}}
{% endif %}
{% if item.options | d() %}
{% for element in item.options %}
{% if element.value | d() and element.state | d('present') not in [ 'absent', 'ignore' ] %}
{% if (not loop.first or (loop.first and item.comment | d())) %}
{% endif %}
{% if element.comment | d() %}
{{ print_comment(element.comment) -}}
{% endif %}
{% if element.state | d('present') == 'comment' %}
/*
{% endif %}
{{ element.value | regex_replace('\n$','') }}
{% if element.state | d('present') == 'comment' %}
*/
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if item.value | d() %}
{% if item.state | d('present') == 'comment' %}
/*
{% endif %}
{{ item.value | regex_replace('\n$','') }}
{% if item.state | d('present') == 'comment' %}
*/
{% endif %}
{% endif %}

View file

@ -0,0 +1,35 @@
{# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
#}
{% set icinga__tpl_dependent_configuration = {} %}
{% if icinga__vars_dependent_configuration | d() %}
{% set _ = icinga__tpl_dependent_configuration.update(icinga__vars_dependent_configuration) %}
{% endif %}
{% if icinga__dependent_configuration %}
{% set icinga__tpl_flattened_configuration = lookup('flattened', icinga__dependent_configuration) %}
{% for element in ([ icinga__tpl_flattened_configuration ] if icinga__tpl_flattened_configuration is mapping else icinga__tpl_flattened_configuration) %}
{% if element.role | d() and element.config | d() %}
{% if element.state | d('present') not in [ 'ignore', 'absent' ] %}
{% set flattened_config = lookup('flattened', element.config) %}
{% set _ = icinga__tpl_dependent_configuration.update({
element.role: ([ flattened_config ] if flattened_config is mapping else flattened_config)
}) %}
{% elif element.state | d('present') == 'absent' %}
{% set _ = icinga__tpl_dependent_configuration.pop(element.role, None) %}
{% endif %}
{% elif element is mapping and 'role' not in element.keys() and 'config' not in element.keys() %}
{% for role, config in element.items() %}
{% set flattened_config = lookup('flattened', config) %}
{% set _ = icinga__tpl_dependent_configuration.update({
role: ([ flattened_config ] if flattened_config is mapping else flattened_config)
}) %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% set icinga__tpl_output_configuration = [] %}
{% for key, value in icinga__tpl_dependent_configuration.items() %}
{% set _ = icinga__tpl_output_configuration.extend(value) %}
{% endfor %}
{{ icinga__tpl_output_configuration | to_yaml }}

View file

@ -0,0 +1,7 @@
{# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
#}
{% for host in play_hosts %}
- 'icinga/dependent_config/{{ host }}'
{% endfor %}

View file

@ -0,0 +1,31 @@
{# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
#}
{% set icinga__tpl_dependent_configuration = {} %}
{% if icinga__vars_dependent_configuration | d() %}
{% set _ = icinga__tpl_dependent_configuration.update(icinga__vars_dependent_configuration) %}
{% endif %}
{% if icinga__dependent_configuration %}
{% set icinga__tpl_flattened_configuration = lookup('flattened', icinga__dependent_configuration) %}
{% for element in ([ icinga__tpl_flattened_configuration ] if icinga__tpl_flattened_configuration is mapping else icinga__tpl_flattened_configuration) %}
{% if element.role | d() and element.config | d() %}
{% if element.state | d('present') not in [ 'ignore', 'absent' ] %}
{% set flattened_config = lookup('flattened', element.config) %}
{% set _ = icinga__tpl_dependent_configuration.update({
element.role: ([ flattened_config ] if flattened_config is mapping else flattened_config)
}) %}
{% elif element.state | d('present') == 'absent' %}
{% set _ = icinga__tpl_dependent_configuration.pop(element.role, None) %}
{% endif %}
{% elif element is mapping and 'role' not in element.keys() and 'config' not in element.keys() %}
{% for role, config in element.items() %}
{% set flattened_config = lookup('flattened', config) %}
{% set _ = icinga__tpl_dependent_configuration.update({
role: ([ flattened_config ] if flattened_config is mapping else flattened_config)
}) %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{{ icinga__tpl_dependent_configuration | to_nice_json }}