From 82541f87741ccaf7d9e845605905a649ebc4c027 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Wed, 13 Nov 2019 13:22:25 +0100 Subject: [PATCH 01/34] Add missing dict2items filter --- templates/object-template.conf.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/object-template.conf.j2 b/templates/object-template.conf.j2 index 868fae7..ac44bd5 100644 --- a/templates/object-template.conf.j2 +++ b/templates/object-template.conf.j2 @@ -1,7 +1,7 @@ // {{ ansible_managed }} {% import 'item_definitions.j2' as definitions %} {% if hostvars[item].i2_objects is defined -%} -{% for item in hostvars[item].i2_objects -%} +{% for item in hostvars[item].i2_objects|dict2items -%} {{ definitions.object(item) }} {% endfor %} {% endif %} From 540086ada96ff1affecf1eea959e3e5832f2f17d Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 14 Nov 2019 12:07:58 +0100 Subject: [PATCH 02/34] Also install php-curl for API access and php-imagick for reports --- tasks/icinga2-web2-Debian.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/icinga2-web2-Debian.yml b/tasks/icinga2-web2-Debian.yml index dcf9914..0830036 100644 --- a/tasks/icinga2-web2-Debian.yml +++ b/tasks/icinga2-web2-Debian.yml @@ -4,6 +4,8 @@ name: - php - php-gd + - php-curl + - php-imagick - libapache2-mod-php state: present From a99cea3797772eb93a4085b0c37dc9ddedca763b Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Mon, 18 Nov 2019 14:13:35 +0100 Subject: [PATCH 03/34] Make sure apache is restarted when new PHP modules are installed/enabled --- tasks/icinga2-web2-Debian.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/icinga2-web2-Debian.yml b/tasks/icinga2-web2-Debian.yml index 0830036..a7ddbc0 100644 --- a/tasks/icinga2-web2-Debian.yml +++ b/tasks/icinga2-web2-Debian.yml @@ -8,6 +8,7 @@ - php-imagick - libapache2-mod-php state: present + notify: restart apache2 - name: IcingaWeb2 – Get PHP version command: php --version @@ -21,6 +22,7 @@ - name: IcingaWeb2 – Enable PHP apache module apache2_module: name: "php{{ php_version }}" + notify: restart apache2 - name: Debian – IcingaWeb2 – Set timezone in php.ini lineinfile: From 7f09da378a5de9a1f49e0fbe7c63ecfcb4375246 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Mon, 18 Nov 2019 14:16:46 +0100 Subject: [PATCH 04/34] Generate configuration files for IcingaWeb2 based on variables --- defaults/main.yml | 75 +++++++++++++++++++++++++++++- tasks/icinga2-web2-Debian.yml | 28 +++++------ tasks/icinga2-web2.yml | 38 +++++++++++++++ templates/icingaweb2-config.ini.j2 | 6 +++ 4 files changed, 129 insertions(+), 18 deletions(-) create mode 100644 templates/icingaweb2-config.ini.j2 diff --git a/defaults/main.yml b/defaults/main.yml index 7214432..f61d619 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -84,5 +84,76 @@ i2_webui_params: # {{ ansible_facts.default_ipv4.address }} i2_webui_connectfrom: - localhost - - +i2_webui_default_authentication: + icingaweb2: + backend: db + resource: icingaweb_db +i2_webui_default_config: + global: + show_stacktraces: "0" + show_application_state_messages: "1" + config_backend: db + config_resource: incingaweb_db + logging: + log: syslog + level: ERROR + application: icingaweb2 + facility: user +i2_webui_default_groups: + icingaweb2: + backend: db + resource: icingaweb_db +i2_webui_default_resources: + icingaweb_db: + type: db + db: mysql + host: "{{ i2_webui_params.host|default('localhost') }}" + port: "" + dbname: "{{ i2_webui_params.database }}" + username: "{{ i2_webui_params.user }}" + password: "{{ i2_webui_params.password }}" + charset: utf8 + use_ssl: "0" + icinga_ido: + type: db + db: mysql + host: "{{ i2_ido_params.host|default('localhost') }}" + port: "" + dbname: "{{ i2_ido_params.database }}" + username: "{{ i2_ido_params.user }}" + password: "{{ i2_ido_params.password }}" + charset: utf8 + use_ssl: "0" +i2_webui_default_roles: + Administrators: + users: "{{ i2_webui_admins|join(',') }}" + permissions: "*" + groups: Administrators + #i2_webui_module_monitoring_commandtransports: +i2_webui_modules_monitoring_backends: + icinga: + type: ido + resource: icinga_ido +i2_webui_modules_monitoring_commandtransports: + icinga2: + transport: api + host: "{{ i2_api_host }}" + port: "{{ i2_api_port }}" + username: icingaweb2 # TODO + password: "{{ vault_icinga_api_icingaweb_password }}" # TODO +i2_webui_modules_monitoring_config: + security: + protected_customvars: "*pw*,*pass*,community" +i2_webui_custom_authentication: {} +i2_webui_custom_config: {} +i2_webui_custom_groups: {} +i2_webui_custom_resources: {} +i2_webui_custom_roles: {} +i2_webui_authentication: "{{ i2_webui_default_authentication|combine(i2_webui_custom_authentication) }}" +i2_webui_config: "{{ i2_webui_default_config|combine(i2_webui_custom_config) }}" +i2_webui_groups: "{{ i2_webui_default_groups|combine(i2_webui_custom_groups) }}" +i2_webui_resources: "{{ i2_webui_default_resources|combine(i2_webui_custom_resources) }}" +i2_webui_roles: "{{ i2_webui_default_roles|combine(i2_webui_custom_roles) }}" +i2_webui_user: "www-data" # fixme this is httpd on RedHat +i2_webui_group: icingaweb2 +i2_webui_admins: [] diff --git a/tasks/icinga2-web2-Debian.yml b/tasks/icinga2-web2-Debian.yml index 0830036..7959002 100644 --- a/tasks/icinga2-web2-Debian.yml +++ b/tasks/icinga2-web2-Debian.yml @@ -36,28 +36,24 @@ - git state: latest tags: icinga2-ansible-web2-ui-install + notify: restart apache2 - name: IcingaWeb2 – Add user www-data to group icingaweb2 user: name: www-data groups: icingaweb2 -- name: IcingaWeb2 – Adjust Directory Owner and Group - file: - path: "/etc/icingaweb2/modules" - owner: www-data - group: icingaweb2 - mode: 0755 - state: directory - recurse: yes - -- name: IcingaWeb2 – Create Directory Owner and Group +- name: IcingaWeb2 – Create configutation directories file: - path: "/etc/icingaweb2/modules/{{ item }}" - owner: www-data - group: icingaweb2 - mode: 0755 + path: "/etc/icingaweb2/{{ item }}" + owner: "{{ i2_webui_user }}" + group: "{{ i2_webui_group }}" + mode: 02770 state: directory loop: - - monitoring - - translation + - "" + - "modules" + - "modules/monitoring" + - "modules/translation" + - "modules/director" + - "enabledModules" diff --git a/tasks/icinga2-web2.yml b/tasks/icinga2-web2.yml index 2afa51e..501205e 100644 --- a/tasks/icinga2-web2.yml +++ b/tasks/icinga2-web2.yml @@ -5,6 +5,44 @@ - include_tasks: icinga2-web2-Debian.yml when: ansible_os_family == 'Debian' +- name: IcingaWeb2 - Create configuration files + become: true + template: + src: "icingaweb2-config.ini.j2" + dest: "/{{ item.dest }}" + mode: 0660 + owner: "{{ i2_webui_user }}" + group: "{{ i2_webui_group }}" + loop: + - dest: /etc/icingaweb2/config.ini + sections: "{{ i2_webui_config }}" + - dest: /etc/icingaweb2/roles.ini + sections: "{{ i2_webui_roles }}" + - dest: /etc/icingaweb2/authentication.ini + sections: "{{ i2_webui_authentication }}" + - dest: /etc/icingaweb2/resources.ini + sections: "{{ i2_webui_resources }}" + - dest: /etc/icingaweb2/groups.ini + sections: "{{ i2_webui_groups }}" + - dest: /etc/icingaweb2/modules/monitoring/backends.ini + sections: "{{ i2_webui_modules_monitoring_backends }}" + - dest: /etc/icingaweb2/modules/monitoring/commandtransports.ini + sections: "{{ i2_webui_modules_monitoring_commandtransports }}" + - dest: /etc/icingaweb2/modules/monitoring/config.ini + sections: "{{ i2_webui_modules_monitoring_config }}" + +- name: IcingaWeb2 - Enable modules + become: true + file: + src: '/usr/share/icingaweb2/modules/{{ item }}' + dest: '/etc/icingaweb2/enabledModules/{{ item }}' + owner: "{{ i2_webui_user }}" + group: "{{ i2_webui_group }}" + state: link + loop: + - doc + - monitoring + - name: Check if IcingaWeb2 configuration is in place become: yes stat: diff --git a/templates/icingaweb2-config.ini.j2 b/templates/icingaweb2-config.ini.j2 new file mode 100644 index 0000000..c610356 --- /dev/null +++ b/templates/icingaweb2-config.ini.j2 @@ -0,0 +1,6 @@ +{% for section, options in item.sections.items() %} +[{{ section }}] +{% for option, value in options.items() %} +{{ option }} = "{{ value }}" +{% endfor %} +{% endfor %} From a820dd73e5edc3ec792028b8d98b2fab6ac1b35e Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 28 Nov 2019 14:39:52 +0100 Subject: [PATCH 05/34] Quote zone names --- tasks/icinga2-node-config.yml | 4 ++-- templates/item_definitions.j2 | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tasks/icinga2-node-config.yml b/tasks/icinga2-node-config.yml index 8258275..7628a8b 100644 --- a/tasks/icinga2-node-config.yml +++ b/tasks/icinga2-node-config.yml @@ -49,8 +49,8 @@ --ticket {{ pki_ticket.stdout }} --endpoint {{ hostvars[i2_parent_nodes[0]]['i2_hostname'] }} --trustedcert {{ i2_pki_path }}/trusted_parent.crt - --zone {{ i2_zonename }} - --parent_zone {{ i2_parent_zone }} + --zone '{{ i2_zonename }}' + --parent_zone '{{ i2_parent_zone }}' --parent_host {{ hostvars[i2_parent_nodes[0]]['i2_api_host'] }} --accept-commands --accept-config diff --git a/templates/item_definitions.j2 b/templates/item_definitions.j2 index 93e67c8..70ffe60 100644 --- a/templates/item_definitions.j2 +++ b/templates/item_definitions.j2 @@ -1,6 +1,5 @@ {% import 'object_attributes.j2' as attributes %} {% macro object(item) -%} - {# No longer required since icinga 2.9 ? #} {% set library = item.value.pop('library', None) %} {%- if library is defined and library is not none %} From 5728fd4ca330b33dd5ef89ffbf6b0eff87e4f59a Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 28 Nov 2019 17:10:57 +0100 Subject: [PATCH 06/34] Use the i2_api_host and i2_api_port to connect to parent --- tasks/icinga2-node-config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/icinga2-node-config.yml b/tasks/icinga2-node-config.yml index 7628a8b..52ba792 100644 --- a/tasks/icinga2-node-config.yml +++ b/tasks/icinga2-node-config.yml @@ -38,7 +38,8 @@ --key {{ i2_pki_path }}/{{ i2_hostname }}.key --cert {{ i2_pki_file }} --trustedcert {{ i2_pki_path }}/trusted_parent.crt - --host {{ hostvars[i2_parent_nodes[0]]['i2_hostname'] }} + --host {{ hostvars[i2_parent_nodes[0]]['i2_api_host'] }} + --port {{ hostvars[i2_parent_nodes[0]]['i2_api_port'] }} when: trusted_authority.stat.exists is sameas false - name: Nodes - Retrieve signed certificate and set-up agent (Top-Down) From 22aea82b84fdcbe13527ff0bd943f79afd27cf78 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Wed, 4 Dec 2019 17:07:51 +0100 Subject: [PATCH 07/34] Adjust the way we handle the configuration files so we can reuse it for the additional modules as well --- defaults/main.yml | 176 +++++++++++++++++------------ tasks/icinga2-web2.yml | 29 ++--- templates/icingaweb2-config.ini.j2 | 2 +- 3 files changed, 118 insertions(+), 89 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index f61d619..dd4666f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -84,76 +84,112 @@ i2_webui_params: # {{ ansible_facts.default_ipv4.address }} i2_webui_connectfrom: - localhost -i2_webui_default_authentication: - icingaweb2: - backend: db - resource: icingaweb_db -i2_webui_default_config: - global: - show_stacktraces: "0" - show_application_state_messages: "1" - config_backend: db - config_resource: incingaweb_db - logging: - log: syslog - level: ERROR - application: icingaweb2 - facility: user -i2_webui_default_groups: - icingaweb2: - backend: db - resource: icingaweb_db -i2_webui_default_resources: - icingaweb_db: - type: db - db: mysql - host: "{{ i2_webui_params.host|default('localhost') }}" - port: "" - dbname: "{{ i2_webui_params.database }}" - username: "{{ i2_webui_params.user }}" - password: "{{ i2_webui_params.password }}" - charset: utf8 - use_ssl: "0" - icinga_ido: - type: db - db: mysql - host: "{{ i2_ido_params.host|default('localhost') }}" - port: "" - dbname: "{{ i2_ido_params.database }}" - username: "{{ i2_ido_params.user }}" - password: "{{ i2_ido_params.password }}" - charset: utf8 - use_ssl: "0" -i2_webui_default_roles: - Administrators: - users: "{{ i2_webui_admins|join(',') }}" - permissions: "*" - groups: Administrators - #i2_webui_module_monitoring_commandtransports: -i2_webui_modules_monitoring_backends: - icinga: - type: ido - resource: icinga_ido -i2_webui_modules_monitoring_commandtransports: - icinga2: - transport: api - host: "{{ i2_api_host }}" - port: "{{ i2_api_port }}" - username: icingaweb2 # TODO - password: "{{ vault_icinga_api_icingaweb_password }}" # TODO -i2_webui_modules_monitoring_config: - security: - protected_customvars: "*pw*,*pass*,community" -i2_webui_custom_authentication: {} -i2_webui_custom_config: {} -i2_webui_custom_groups: {} -i2_webui_custom_resources: {} -i2_webui_custom_roles: {} -i2_webui_authentication: "{{ i2_webui_default_authentication|combine(i2_webui_custom_authentication) }}" -i2_webui_config: "{{ i2_webui_default_config|combine(i2_webui_custom_config) }}" -i2_webui_groups: "{{ i2_webui_default_groups|combine(i2_webui_custom_groups) }}" -i2_webui_resources: "{{ i2_webui_default_resources|combine(i2_webui_custom_resources) }}" -i2_webui_roles: "{{ i2_webui_default_roles|combine(i2_webui_custom_roles) }}" i2_webui_user: "www-data" # fixme this is httpd on RedHat i2_webui_group: icingaweb2 i2_webui_admins: [] + +i2_webui_default_config: + authenticate: + file: authentication.ini + sections: + icingaweb2: + backend: db + resource: icingaweb_db + config: + file: config.ini + sections: + global: + show_stacktraces: "0" + show_application_state_messages: "1" + config_backend: db + config_resource: icingaweb_db + logging: + log: syslog + level: ERROR + application: icingaweb2 + facility: user + groups: + file: groups.ini + sections: + icingaweb2: + backend: db + resource: icingaweb_db + resources: + file: resources.ini + sections: + icingaweb_db: + type: db + db: mysql + host: "{{ i2_webui_params.host|default('localhost') }}" + port: "{{ i2_webui_params.port|default(omit) }}" + dbname: "{{ i2_webui_params.database }}" + username: "{{ i2_webui_params.user }}" + password: "{{ i2_webui_params.password }}" + charset: utf8 + use_ssl: "0" + icinga_ido: + type: db + db: mysql + host: "{{ i2_ido_params.host|default('localhost') }}" + port: "{{ i2_ido_params.port|default(omit) }}" + dbname: "{{ i2_ido_params.database }}" + username: "{{ i2_ido_params.user }}" + password: "{{ i2_ido_params.password }}" + charset: utf8 + use_ssl: "0" + roles: + file: roles.ini + sections: + Administrators: + users: "{{ i2_webui_admins|join(',') }}" + permissions: "*" + groups: Administrators + modules_monitoring_backends: + file: modules/monitoring/backends.ini + sections: + icinga: + type: ido + resource: icinga_ido + modules_monitoring_commandtransports: + file: modules/monitoring/commandtransports.ini + sections: + icinga2: + transport: api + host: "{{ i2_api_host }}" + port: "{{ i2_api_port }}" + username: "{{ i2_api_webui_user }}" + password: "{{ i2_api_webui_password }}" + modules_monitoring_config: + file: modules/monitoring/config.ini + sections: + security: + protected_customvars: "*pw*,*pass*,community" +i2_webui_default_module_config: + director: + resources: + sections: + director_db: + type: db + db: mysql + host: "{{ i2_director_params.host|default('localhost') }}" + port: "" + dbname: "{{ i2_director_params.database }}" + username: "{{ i2_director_params.user }}" + password: "{{ i2_director_params.password }}" + charset: utf8 + use_ssl: "0" + modules_director_config: + file: modules/director/config.ini + sections: + db: + resource: director_db + modules_director_kickstart: + file: modules/director/kickstart.ini + sections: + config: + endpoint: "{{ i2_hostname }}" + username: director + password: "{{ i2_api_director_password }}" +i2_webui_custom_config: {} +i2_webui_config: "{{ i2_webui_default_config|combine(i2_webui_custom_config, recursive=True) }}" + diff --git a/tasks/icinga2-web2.yml b/tasks/icinga2-web2.yml index 501205e..13b1d1a 100644 --- a/tasks/icinga2-web2.yml +++ b/tasks/icinga2-web2.yml @@ -5,31 +5,24 @@ - include_tasks: icinga2-web2-Debian.yml when: ansible_os_family == 'Debian' +- name: IcingaWeb2 - Include default config for module + set_fact: + i2_webui_default_config: "{{ i2_webui_default_config|combine( + i2_webui_default_module_config[item]|default({}), recursive=True) + }}" + loop: "{{ i2_webui_modules | map(attribute='name') | list }}" + - name: IcingaWeb2 - Create configuration files become: true template: src: "icingaweb2-config.ini.j2" - dest: "/{{ item.dest }}" + dest: "/etc/icingaweb2/{{ item.value.file }}" mode: 0660 owner: "{{ i2_webui_user }}" group: "{{ i2_webui_group }}" - loop: - - dest: /etc/icingaweb2/config.ini - sections: "{{ i2_webui_config }}" - - dest: /etc/icingaweb2/roles.ini - sections: "{{ i2_webui_roles }}" - - dest: /etc/icingaweb2/authentication.ini - sections: "{{ i2_webui_authentication }}" - - dest: /etc/icingaweb2/resources.ini - sections: "{{ i2_webui_resources }}" - - dest: /etc/icingaweb2/groups.ini - sections: "{{ i2_webui_groups }}" - - dest: /etc/icingaweb2/modules/monitoring/backends.ini - sections: "{{ i2_webui_modules_monitoring_backends }}" - - dest: /etc/icingaweb2/modules/monitoring/commandtransports.ini - sections: "{{ i2_webui_modules_monitoring_commandtransports }}" - - dest: /etc/icingaweb2/modules/monitoring/config.ini - sections: "{{ i2_webui_modules_monitoring_config }}" + loop: "{{ i2_webui_config | dict2items }}" + loop_control: + label: "{{ item.key }}" - name: IcingaWeb2 - Enable modules become: true diff --git a/templates/icingaweb2-config.ini.j2 b/templates/icingaweb2-config.ini.j2 index c610356..cdbce4e 100644 --- a/templates/icingaweb2-config.ini.j2 +++ b/templates/icingaweb2-config.ini.j2 @@ -1,4 +1,4 @@ -{% for section, options in item.sections.items() %} +{% for section, options in item.value.sections.items() %} [{{ section }}] {% for option, value in options.items() %} {{ option }} = "{{ value }}" From 7ae7149431b83cb957392c419563cbf2ac050e18 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Wed, 4 Dec 2019 17:10:14 +0100 Subject: [PATCH 08/34] Adjust the installation of modules to include an version and repo Handle additional actions for director module --- defaults/main.yml | 15 ++++++++---- tasks/icinga2-web2-modules.yml | 42 +++++++++++++++++++++++++++++++--- tasks/icinga2-web2.yml | 6 ++--- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index dd4666f..47ecf28 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -68,10 +68,17 @@ i2_webui_php_all: no i2_webui_modules_dir: "/usr/share/icingaweb2/modules" i2_timezone: "UTC" i2_webui_modules: - - map - - cube - - toplevelview - - businessprocess + - name: cube + version: v1.1.0 + - name: map + version: v1.1.0 + repo: https://github.com/nbuchwitz/icingaweb2-module-map.git + - name: toplevelview + version: v0.3.1 + - name: ipl + version: v0.4.0 + - name: businessprocess + version: v2.2.0 i2_webui_params: database: icingaweb user: icingaweb diff --git a/tasks/icinga2-web2-modules.yml b/tasks/icinga2-web2-modules.yml index 3218adf..848611f 100644 --- a/tasks/icinga2-web2-modules.yml +++ b/tasks/icinga2-web2-modules.yml @@ -1,9 +1,45 @@ --- -- name: Icingaweb2 – Download modules from github +- name: IcingaWeb2 – Download modules from github become: yes git: - repo: "https://github.com/Icinga/icingaweb2-module-{{ item }}.git" - dest: "{{ i2_webui_modules_dir }}/{{ item}}" + repo: "{{ item.repo|default('https://github.com/Icinga/icingaweb2-module-' + item.name +'.git') }}" + dest: "{{ i2_webui_modules_dir }}/{{ item.name }}" update: no + version: "{{ item.version }}" loop: "{{ i2_webui_modules }}" ignore_errors: yes + +- name: IcingaWeb2 - Enable modules + become: true + file: + src: "{{ i2_webui_modules_dir }}/{{ item.name }}" + dest: '/etc/icingaweb2/enabledModules/{{ item.name }}' + owner: "{{ i2_webui_user }}" + group: "{{ i2_webui_group }}" + state: link + loop: "{{ i2_webui_modules }}" + +- name: IcingaWeb2 - Director + when: i2_webui_modules | json_query('[?name==`director`]') | length > 0 + block: + - name: IcingaWeb2 - Director - Check if migration is pending + command: icingacli director migration pending + register: directormigrationpending + check_mode: false + changed_when: false + failed_when: false + + - name: IcingaWeb2 - Director - Run migration + command: icingacli director migration run + when: directormigrationpending.rc == 0 + + - name: IcingaWeb2 - Director - Check if kickstart is required + command: icingacli director kickstart required + register: directorkickstartrequired + check_mode: false + changed_when: false + failed_when: false + + - name: IcingaWeb2 - Director - Run kickstart + command: icingacli director kickstart run + when: directorkickstartrequired.rc == 0 diff --git a/tasks/icinga2-web2.yml b/tasks/icinga2-web2.yml index 13b1d1a..e6a0b59 100644 --- a/tasks/icinga2-web2.yml +++ b/tasks/icinga2-web2.yml @@ -67,7 +67,5 @@ ({{ ansible_facts.default_ipv4.address }}) to continue the installation tags: icinga2-ansible-web2-ui-install -# Something here doesn't work but I don't know what… looks -# like this will need to time out. -# - name: IcingaWeb2 – Install additional modules -# import_tasks: icinga2-web2-modules.yml +- name: IcingaWeb2 – Install additional modules + import_tasks: icinga2-web2-modules.yml From 2fe356a2266c1793b64a2a5fa83b42e34227ca2f Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Tue, 4 Feb 2020 11:49:55 +0100 Subject: [PATCH 09/34] Fixes in the node hierachy detection --- tasks/icinga2-bootstrap.yml | 60 ++++++++++++++++++++++++++------- templates/host_template.conf.j2 | 8 +++-- templates/zones.conf.j2 | 2 ++ 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/tasks/icinga2-bootstrap.yml b/tasks/icinga2-bootstrap.yml index a1d4e27..58a211b 100644 --- a/tasks/icinga2-bootstrap.yml +++ b/tasks/icinga2-bootstrap.yml @@ -69,34 +69,68 @@ + groups[i2_satellite_group]|default([]) + groups[i2_agent_group]|default([]) }} -- name: Determine child nodes +- name: Determine peer nodes set_fact: i2_peer_nodes: >- {{ hostvars | dict2items - | json_query("[?value.i2_zonename==" + "'" + i2_zonename + "'].key") + | json_query("[?value.i2_zonename==" + "'" + hostvars[item].i2_zonename + "'].key") | sort }} + run_once: True + delegate_facts: True + delegate_to: "{{ item }}" + loop: >- + {{ groups[i2_master_group]|default([]) + + groups[i2_satellite_group]|default([]) + + groups[i2_agent_group]|default([]) }} - name: Determine parent and child nodes set_fact: i2_child_nodes: >- {{ hostvars | dict2items - | json_query("[?value.i2_parent_zone==" + "'" + i2_zonename + "'].key") - | difference(i2_peer_nodes) - | sort }} - i2_child_zones: >- - {{ hostvars | dict2items | map(attribute='value') | list - | json_query("[?i2_parent_zone==" + "'" + i2_zonename + "'].i2_zonename") - | unique - | difference([i2_zonename]) + | json_query("[?value.i2_parent_zone==" + "'" + hostvars[item].i2_zonename + "'].key") + | difference(hostvars[item].i2_peer_nodes) | sort }} i2_parent_nodes: >- - {%- if i2_parent_zone is defined -%} + {%- if hostvars[item].i2_parent_zone is defined -%} {{ hostvars | dict2items - | json_query("[?value.i2_zonename==" + "'" + i2_parent_zone + "'].key") - | difference(i2_peer_nodes) + | json_query("[?value.i2_zonename==" + "'" + hostvars[item].i2_parent_zone + "'].key") + | difference(hostvars[item].i2_peer_nodes) | sort }} {%- else %}[]{% endif -%} + run_once: True + delegate_facts: True + delegate_to: "{{ item }}" + loop: >- + {{ groups[i2_master_group]|default([]) + + groups[i2_satellite_group]|default([]) + + groups[i2_agent_group]|default([]) }} + +- name: Determine satellite zones + set_fact: + i2_satellite_zones: >- + {{ groups[i2_satellite_group]|default([]) | map('extract', hostvars, 'i2_zonename' ) + | unique + | sort }} + +- name: Determine child zones + set_fact: + i2_child_zones: >- + {{ hostvars[item].i2_child_nodes | map('extract', hostvars, 'i2_zonename' ) + | unique + | sort }} + i2_child_satellite_zones: >- + {{ hostvars[item].i2_child_nodes | map('extract', hostvars, 'i2_zonename' ) + | unique + | intersect(i2_satellite_zones) + | sort }} + run_once: True + delegate_facts: True + delegate_to: "{{ item }}" + loop: >- + {{ groups[i2_master_group]|default([]) + + groups[i2_satellite_group]|default([]) + + groups[i2_agent_group]|default([]) }} - name: Check if Client Certificates exist become: yes diff --git a/templates/host_template.conf.j2 b/templates/host_template.conf.j2 index 90b9b9e..d37d828 100644 --- a/templates/host_template.conf.j2 +++ b/templates/host_template.conf.j2 @@ -9,13 +9,17 @@ object Host "{{ hostvars[item].i2_hostname }}" { {% endif -%} address = "{{ hostvars[item].i2_address }}" + {% if item not in groups[i2_master_group] and item not in groups[i2_satellite_group] -%} vars.agent_endpoint = name // Follows the convention that host name == endpoint name + {% endif %} vars.os = "{{ hostvars[item].ansible_system }}" vars.os_family = "{{ hostvars[item].ansible_os_family }}" - {% if hostvars[item].i2_master is defined and hostvars[item].i2_master -%} + {% if hostvars[item].i2_child_satellite_zones is defined and + hostvars[item].i2_child_satellite_zones|length > 0 + -%} // Satellite zones controlled by this master. - {{ attributes.eval_value('zones', i2_child_zones, 'vars.') }} + {{ attributes.eval_value('zones', hostvars[item].i2_child_satellite_zones, 'vars.') }} {% endif %} {% if hostvars[item].i2_host_attributes is defined -%} diff --git a/templates/zones.conf.j2 b/templates/zones.conf.j2 index c0c949d..1d1d155 100644 --- a/templates/zones.conf.j2 +++ b/templates/zones.conf.j2 @@ -62,6 +62,7 @@ object Endpoint "{{ hostvars[item].i2_hostname }}" { # Create Endpoints for all the nodes in child Zones #} {% for item in i2_child_nodes -%} +{% if hostvars[item].i2_hostname is defined -%} object Endpoint "{{ hostvars[item].i2_hostname }}" { {% if i2_connection_direction == 'top-down' %} host = "{{ hostvars[item].i2_api_host }}" // Actively connect to child node. @@ -70,6 +71,7 @@ object Endpoint "{{ hostvars[item].i2_hostname }}" { // Child node will connect to us. {% endif %} } +{% endif %} {% endfor -%} From 1643840bf09f6aa6651c0bf00eba1532f50e21ac Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Tue, 4 Feb 2020 11:59:06 +0100 Subject: [PATCH 10/34] Fix name of default config and order options in generated files --- defaults/main.yml | 2 +- templates/icingaweb2-config.ini.j2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 47ecf28..6a6d0c9 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -96,7 +96,7 @@ i2_webui_group: icingaweb2 i2_webui_admins: [] i2_webui_default_config: - authenticate: + authentication: file: authentication.ini sections: icingaweb2: diff --git a/templates/icingaweb2-config.ini.j2 b/templates/icingaweb2-config.ini.j2 index cdbce4e..7956e7b 100644 --- a/templates/icingaweb2-config.ini.j2 +++ b/templates/icingaweb2-config.ini.j2 @@ -1,6 +1,6 @@ {% for section, options in item.value.sections.items() %} [{{ section }}] -{% for option, value in options.items() %} +{% for option, value in options|dictsort %} {{ option }} = "{{ value }}" {% endfor %} {% endfor %} From 4aa1b34463e601931db4bbde4cc3c4303b9784a9 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Tue, 4 Feb 2020 16:01:11 +0100 Subject: [PATCH 11/34] Use template instead of blockinfile for the api-users.conf file --- tasks/icinga2-api.yml | 8 ++------ tasks/icinga2-objects.yml | 8 ++++++++ ...{api_users_fragment.j2 => api-users.conf.j2} | 7 +++++-- templates/zone_fragment.conf.j2 | 17 ----------------- templates/zones.conf.j2 | 2 +- 5 files changed, 16 insertions(+), 26 deletions(-) rename templates/{api_users_fragment.j2 => api-users.conf.j2} (51%) delete mode 100644 templates/zone_fragment.conf.j2 diff --git a/tasks/icinga2-api.yml b/tasks/icinga2-api.yml index f427192..17fdf31 100644 --- a/tasks/icinga2-api.yml +++ b/tasks/icinga2-api.yml @@ -152,16 +152,12 @@ # Blerim made i2_confd an array of locations to be included. - name: Master - Create Api-Users config file become: yes - blockinfile: - create: yes + template: + src: api-users.conf.j2 dest: "{{ i2_zones_dir }}/{{ i2_zonename }}/api-users.conf" - marker: "// {mark} Ansible managed block for {{ item.key }}" - content: "{{ lookup('template', 'api_users_fragment.j2') }}" owner: "{{ i2_user }}" group: "{{ i2_group }}" mode: 0644 - directory_mode: 0755 - with_dict: "{{ i2_api_users }}" when: - inventory_hostname == i2_configuration_master - i2_api_users is defined diff --git a/tasks/icinga2-objects.yml b/tasks/icinga2-objects.yml index 33a2124..737e5e8 100644 --- a/tasks/icinga2-objects.yml +++ b/tasks/icinga2-objects.yml @@ -167,6 +167,14 @@ - i2_remove_unmanaged_objects - item.dest is defined +- name: Add api-users.conf to the managed object files + set_fact: + managed_object_files: "{{ managed_object_files+[i2_zones_dir+'/'+i2_zonename+'/api-users.conf'] }}" + when: + - i2_remove_unmanaged_objects + - inventory_hostname == i2_configuration_master + - i2_api_users is defined + - name: Removing unmanaged object files become: yes file: diff --git a/templates/api_users_fragment.j2 b/templates/api-users.conf.j2 similarity index 51% rename from templates/api_users_fragment.j2 rename to templates/api-users.conf.j2 index 44fd83d..e53374f 100644 --- a/templates/api_users_fragment.j2 +++ b/templates/api-users.conf.j2 @@ -1,6 +1,9 @@ +// {{ ansible_managed }} +{% for item in i2_api_users|dict2items %} object ApiUser "{{ item.key }}" { password = "{{ item.value.password }}" - {% if item.value.permissions is defined %} +{% if item.value.permissions is defined %} permissions = [ "{{ item.value.permissions | join('", "') }}" ] - {% endif %} +{% endif %} } +{% endfor %} diff --git a/templates/zone_fragment.conf.j2 b/templates/zone_fragment.conf.j2 deleted file mode 100644 index 3488ba2..0000000 --- a/templates/zone_fragment.conf.j2 +++ /dev/null @@ -1,17 +0,0 @@ -object Endpoint "{{ hostvars[item].i2_hostname }}" { -{# - Masters don't connect to satellites or agents in a bottom-up set-up, - only in a top-down scenario. -#} -{% if i2_connection_direction == 'top-down' %} - host = "{{ hostvars[item].i2_api_host }}" - port = "{{ i2_api_port }}" -{% endif %} -} - -object Zone "{{ hostvars[item].i2_zonename }}" { -{% if hostvars[item].i2_parent_zone is defined and hostvars[item].i2_parent_zone != item %} - parent = "{{ hostvars[item].i2_zone }}" -{% endif %} - endpoints = [ "{{ hostvars[item].i2_hostname }}" ] -} diff --git a/templates/zones.conf.j2 b/templates/zones.conf.j2 index 1d1d155..70e42a3 100644 --- a/templates/zones.conf.j2 +++ b/templates/zones.conf.j2 @@ -1,4 +1,4 @@ -// Ansible managed +// {{ ansible_managed }} /* * Defines a global zone for distributed setups with masters, From 9624d2a9f581254187eeac7d14157fdd2aef42e8 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Tue, 4 Feb 2020 16:02:13 +0100 Subject: [PATCH 12/34] Cleanup unused code --- tasks/icinga2-config.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/tasks/icinga2-config.yml b/tasks/icinga2-config.yml index c895ebb..0353bbe 100644 --- a/tasks/icinga2-config.yml +++ b/tasks/icinga2-config.yml @@ -73,37 +73,3 @@ backup: "{{ i2_keep_backups }}" when: i2_master or i2_certificate_signed_by_ca notify: reload icinga2 - -#- name: Set-up remote Zones and Endpoints for Satellites - #become: yes - #blockinfile: - #create: yes - #owner: "{{ i2_user }}" - #group: "{{ i2_group }}" - #dest: "{{ i2_zones_dir }}/{{ hostvars[item].i2_parent_zone }}/endpoints.conf" - #marker: "// {mark} Ansible managed block for {{ item }} (client)" - #content: "{{ lookup('template', 'templates/zone_fragment.conf.j2') }}" - #loop: "{{ groups[i2_agent_group]|default([]) }}" - #when: - #- i2_config_master - #- hostvars[item].i2_hostname is defined - #notify: reload icinga2 - -## This isn't very elegant but the only way I could -## think of to make this work in the short term. -#- name: Set fact for managed endpoint files - #set_fact: - #managed_object_files: "{{ - #( - #managed_object_files|default([]) - #+ [ - #i2_zones_dir - #+ '/' - #+ hostvars[item].i2_parent_zone - #+ '/endpoints.conf' - #] - #) - #| unique - #}}" - #loop: "{{ groups[i2_agent_group]|default([]) }}" - #when: i2_remove_unmanaged_objects From 99737e558f11fb77bf72f17c9229aa954a780f24 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Tue, 4 Feb 2020 16:08:32 +0100 Subject: [PATCH 13/34] use openssl_certificate_info --- .travis.yml | 6 ++---- tasks/icinga2-bootstrap.yml | 12 ++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index a0bdb41..87d4fb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,10 +12,8 @@ script: - molecule test matrix: include: - - env: ANSIBLE_VERSION="2.5.9" - - env: ANSIBLE_VERSION="2.6.5" - - env: ANSIBLE_VERSION="2.7.0" - - env: ANSIBLE_VERSION="2.7.5" + - env: ANSIBLE_VERSION="2.9.2" + - env: ANSIBLE_VERSION="2.8.7" branches: only: - master diff --git a/tasks/icinga2-bootstrap.yml b/tasks/icinga2-bootstrap.yml index 58a211b..d5a01e7 100644 --- a/tasks/icinga2-bootstrap.yml +++ b/tasks/icinga2-bootstrap.yml @@ -140,18 +140,18 @@ - name: Check if Client Certificate is signed by our CA become: yes - shell: >- - openssl x509 -in {{ i2_pki_file }} -noout -text | grep Issuer - register: certificate_authority - ignore_errors: yes + openssl_certificate_info: + path: "{{ i2_pki_file }}" + register: client_certificate when: not i2_master and client_certificate.stat.exists - name: Set certificate authority fact set_fact: i2_certificate_signed_by_ca: yes when: - - certificate_authority.changed - - "'Icinga CA' in certificate_authority.stdout" + - client_certificate.issuer is defined + - "'Icinga CA' == client_certificate.issuer.commonName" + - "i2_hostname == client_certificate.subject.commonName" - name: Icingaweb2 (Redhat) - Check if SELinux is enabled command: /usr/sbin/getenforce From 421436cd20219a99718e6b033d2e229072d1f487 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 13 Feb 2020 17:49:36 +0100 Subject: [PATCH 14/34] Install icinga-director service, create Director database and create all configuration directories --- files/icinga-director.service | 21 ++++++++++++++++ handlers/main.yml | 11 +++++++++ tasks/icinga2-web2-Debian.yml | 17 +------------ tasks/icinga2-web2-modules.yml | 44 +++++++++++++++++++++++++++++++++- tasks/icinga2-web2.yml | 18 ++++++++++++++ 5 files changed, 94 insertions(+), 17 deletions(-) create mode 100644 files/icinga-director.service diff --git a/files/icinga-director.service b/files/icinga-director.service new file mode 100644 index 0000000..f96f1d7 --- /dev/null +++ b/files/icinga-director.service @@ -0,0 +1,21 @@ +[Unit] +Description=Icinga Director - Monitoring Configuration +Documentation=https://icinga.com/docs/director/latest/ +Wants=network.target + +[Service] +EnvironmentFile=-/etc/default/icinga-director +EnvironmentFile=-/etc/sysconfig/icinga-director +ExecStart=/usr/bin/icingacli director daemon run +ExecReload=/bin/kill -HUP ${MAINPID} +User=icingadirector +SyslogIdentifier=icingadirector +Type=notify + +NotifyAccess=main +WatchdogSec=10 +RestartSec=30 +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/handlers/main.yml b/handlers/main.yml index 7fa1a48..3f0d3f0 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,4 +1,9 @@ --- +- name: reload systemd + become: yes + systemd: + daemon_reload: yes + - name: start icinga2 become: yes service: @@ -44,6 +49,12 @@ state: restarted when: i2_manage_service +- name: restart icinga-director + become: yes + service: + name: icinga-director + state: restarted + - name: restart php-fpm become: yes service: diff --git a/tasks/icinga2-web2-Debian.yml b/tasks/icinga2-web2-Debian.yml index d9c2a64..cf89ba1 100644 --- a/tasks/icinga2-web2-Debian.yml +++ b/tasks/icinga2-web2-Debian.yml @@ -43,19 +43,4 @@ - name: IcingaWeb2 – Add user www-data to group icingaweb2 user: name: www-data - groups: icingaweb2 - -- name: IcingaWeb2 – Create configutation directories - file: - path: "/etc/icingaweb2/{{ item }}" - owner: "{{ i2_webui_user }}" - group: "{{ i2_webui_group }}" - mode: 02770 - state: directory - loop: - - "" - - "modules" - - "modules/monitoring" - - "modules/translation" - - "modules/director" - - "enabledModules" + groups: "{{ i2_webui_group }}" diff --git a/tasks/icinga2-web2-modules.yml b/tasks/icinga2-web2-modules.yml index 848611f..93da551 100644 --- a/tasks/icinga2-web2-modules.yml +++ b/tasks/icinga2-web2-modules.yml @@ -22,16 +22,25 @@ - name: IcingaWeb2 - Director when: i2_webui_modules | json_query('[?name==`director`]') | length > 0 block: + - name: IcingaWeb2 - Director - Create database + mysql_db: + login_host: "{{ i2_director_params.host }}" + login_user: "{{ i2_director_params.user }}" + login_password: "{{ i2_director_params.password }}" + name: "{{ i2_director_params.database }}" + state: present + - name: IcingaWeb2 - Director - Check if migration is pending command: icingacli director migration pending register: directormigrationpending check_mode: false changed_when: false - failed_when: false + failed_when: directormigrationpending.stdout is match('ERROR:') - name: IcingaWeb2 - Director - Run migration command: icingacli director migration run when: directormigrationpending.rc == 0 + notify: restart icinga-director - name: IcingaWeb2 - Director - Check if kickstart is required command: icingacli director kickstart required @@ -43,3 +52,36 @@ - name: IcingaWeb2 - Director - Run kickstart command: icingacli director kickstart run when: directorkickstartrequired.rc == 0 + notify: restart icinga-director + + - name: IcingaWeb2 - Director - Add system user + user: + name: icingadirector + group: "{{ i2_webui_group }}" + shell: /bin/false + home: /var/lib/icingadirector + system: yes + become: yes + + - name: IcingaWeb2 - Director - Create home directory + file: + path: /var/lib/icingadirector + owner: icingadirector + group: "{{ i2_webui_group }}" + mode: 0750 + become: yes + + - name: IcingaWeb2 - Director - Install unit file + copy: + src: icinga-director.service + dest: /etc/systemd/system/icinga-director.service + become: yes + notify: reload systemd + + - meta: flush_handlers + + - name: IcingaWeb2 - Director - Enable and start Background Daemon + systemd: + name: icinga-director + enabled: yes + state: started diff --git a/tasks/icinga2-web2.yml b/tasks/icinga2-web2.yml index e6a0b59..1c3202b 100644 --- a/tasks/icinga2-web2.yml +++ b/tasks/icinga2-web2.yml @@ -12,6 +12,24 @@ }}" loop: "{{ i2_webui_modules | map(attribute='name') | list }}" +- name: IcingaWeb2 – Create configuration directories + file: + path: "/etc/icingaweb2/{{ item }}" + owner: "{{ i2_webui_user }}" + group: "{{ i2_webui_group }}" + mode: 02770 + state: directory + loop: "{{ default | union(additional) }}" + vars: + default: + - "" + - "modules" + - "modules/monitoring" + - "modules/translation" + - "modules/director" + - "enabledModules" + additional: "{{ i2_webui_config | json_query('*.file') | map('dirname') | list | unique }}" + - name: IcingaWeb2 - Create configuration files become: true template: From 047f4e53f11d1dcef09c074c6b493b9f7b973200 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Tue, 25 Feb 2020 15:25:29 +0100 Subject: [PATCH 15/34] Simple label for loop and set managed_object_files without loop --- tasks/icinga2-objects.yml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tasks/icinga2-objects.yml b/tasks/icinga2-objects.yml index 737e5e8..d8d2bcc 100644 --- a/tasks/icinga2-objects.yml +++ b/tasks/icinga2-objects.yml @@ -35,6 +35,8 @@ set_fact: existing_files: "{{ existing_files|default([]) + [ item.path ] }}" loop: "{{ existing_objects.files }}" + loop_control: + label: "{{ item.path }}" when: - i2_remove_unmanaged_objects @@ -148,25 +150,20 @@ - name: Set fact Managed Objects set_fact: - managed_objects: "{{ - managed_global_templates.results + managed_object_files: "{{ + ( managed_global_templates.results + managed_global_objects.results + managed_global_apply_rules.results + managed_zone_templates.results + managed_zone_objects.results + managed_zone_apply_rules.results - + managed_zone_hosts.results + + managed_zone_hosts.results ) + | selectattr('dest', 'defined') + | map(attribute='dest') + | list }}" when: i2_remove_unmanaged_objects -- name: Set fact for managed object files - set_fact: - managed_object_files: "{{ managed_object_files|default([]) + [item.dest] }}" - loop: "{{ managed_objects }}" - when: - - i2_remove_unmanaged_objects - - item.dest is defined - - name: Add api-users.conf to the managed object files set_fact: managed_object_files: "{{ managed_object_files+[i2_zones_dir+'/'+i2_zonename+'/api-users.conf'] }}" From f2bcaab9601afa8e1f4e58adf86292655635fcc6 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 27 Feb 2020 16:19:57 +0100 Subject: [PATCH 16/34] Setup the icinga nodes in layers, first masters, then satellites, then the agents --- tasks/icinga2-api.yml | 10 -------- tasks/icinga2-layer.yml | 36 ++++++++++++++++++++++++++ tasks/main.yml | 57 +++++++++++++++++++---------------------- 3 files changed, 62 insertions(+), 41 deletions(-) create mode 100644 tasks/icinga2-layer.yml diff --git a/tasks/icinga2-api.yml b/tasks/icinga2-api.yml index 17fdf31..40d74b3 100644 --- a/tasks/icinga2-api.yml +++ b/tasks/icinga2-api.yml @@ -163,13 +163,3 @@ - i2_api_users is defined notify: - reload icinga2 - -- name: Master – Restart Icinga2 Service on Config Master - service: - name: icinga2 - state: started - enabled: yes - when: - - inventory_hostname == i2_configuration_master - - i2_manage_service - diff --git a/tasks/icinga2-layer.yml b/tasks/icinga2-layer.yml new file mode 100644 index 0000000..47dce87 --- /dev/null +++ b/tasks/icinga2-layer.yml @@ -0,0 +1,36 @@ +--- +- name: Create basic Icinga2 configuration + import_tasks: icinga2-config.yml + tags: + - config + +- name: Set up Icinga2 IDO + import_tasks: icinga2-ido-mysql.yml + when: i2_master and i2_setup_ido + tags: + - ido + +- name: Set up Icinga2 API and PKI + import_tasks: icinga2-api.yml + when: i2_master + tags: + - api + +- name: Set up Icinga2 Nodes + import_tasks: icinga2-node-config.yml + when: not i2_master and groups[i2_master_group] is defined + tags: + - nodes + +- name: Enable Icinga2 features + import_tasks: icinga2-features.yml + when: i2_features|flatten|length > 0 + tags: + - features + +- name: Make sure Icinga 2 is started + service: + name: icinga2 + state: started + enabled: yes + when: i2_manage_service diff --git a/tasks/main.yml b/tasks/main.yml index 1a8e3b6..109c05e 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -14,42 +14,29 @@ tags: - install -- name: Create basic Icinga2 configuration - import_tasks: icinga2-config.yml - tags: - - config +- name: Set up Icinga2 masters + when: i2_master + block: + - name: Setup distibuted layer + import_tasks: icinga2-layer.yml -- name: Set up Icinga2 IDO - import_tasks: icinga2-ido-mysql.yml - when: i2_master and i2_setup_ido - tags: - - ido +- meta: flush_handlers -- name: Enable Icinga2 features - import_tasks: icinga2-features.yml - when: i2_features|flatten|length > 0 - tags: - - features +- name: Set up Icinga2 satellites + when: i2_satellite + block: + - name: Setup distibuted layer + import_tasks: icinga2-layer.yml -- name: Set up Icingaweb2 - import_tasks: icinga2-web2.yml - when: - - inventory_hostname == i2_configuration_master - - i2_setup_webui - tags: - - webui +- meta: flush_handlers -- name: Set up Icinga2 API and PKI - import_tasks: icinga2-api.yml - when: i2_master - tags: - - api +- name: Set up Icinga2 agents + when: not i2_master and not i2_satellite + block: + - name: Setup distibuted layer + import_tasks: icinga2-layer.yml -- name: Set up Icinga2 Nodes - import_tasks: icinga2-node-config.yml - when: not i2_master and groups[i2_master_group] is defined - tags: - - nodes +- meta: flush_handlers - name: Set up Icinga Templates, Objects and Apply Rules import_tasks: icinga2-objects.yml @@ -69,3 +56,11 @@ state: started enabled: yes when: i2_manage_service + +- name: Set up Icingaweb2 + import_tasks: icinga2-web2.yml + when: + - inventory_hostname == i2_configuration_master + - i2_setup_webui + tags: + - webui From bd623e10b6a492111831557348fc65e5ae08da0d Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Mon, 23 Mar 2020 13:52:05 +0100 Subject: [PATCH 17/34] Fix the layout of the feature configuration, which fixes IDO cleanup configuration generation --- templates/object_attributes.j2 | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/templates/object_attributes.j2 b/templates/object_attributes.j2 index 40f56aa..75f0fd5 100644 --- a/templates/object_attributes.j2 +++ b/templates/object_attributes.j2 @@ -1,31 +1,31 @@ -{%- macro attrs(map, prefix="", operator="=", iterator=None) %} - {%- for k, v in map.items() %} - {%- if v is mapping %} - {{ mapdict(k, v, prefix, operator, iterator) | indent(width=2)}} - {%- else %} +{% macro attrs(map, prefix="", operator="=", iterator=None) %} +{% for k, v in map.items() %} +{% if v is mapping %} + {{ mapdict(k, v, prefix, operator, iterator) | indent(width=2)}} +{% else %} {{ eval_value(k, v, prefix, operator, iterator) }} - {%- endif %} - {%- endfor %} -{%- endmacro %} +{%- endif %} +{% endfor %} +{% endmacro %} {% macro mapdict(key, dictionary, prefix="", operator="=", iterator=None) %} {{ key|icingakey(prefix) }} {{ operator }} { -{% for subkey, value in dictionary.items() -%} -{% if value is mapping -%} -{{ mapdict(subkey, value, "", operator, iterator) | indent(width=2) }} -{% else -%} -{{ eval_value(subkey, value, "", operator, iterator) }} -{% endif -%} -{% endfor -%} +{% for subkey, value in dictionary.items() %} +{% if value is mapping %} + {{ mapdict(subkey, value, "", operator, iterator) | indent(width=2) }} +{% else %} + {{ eval_value(subkey, value, "", operator, iterator) }} +{%- endif %} +{% endfor %} } {% endmacro %} -{% macro eval_value(orig_key, val, prefix="", operator="=", iterator=None) -%} +{% macro eval_value(orig_key, val, prefix="", operator="=", iterator=None) %} {% set key = prefix + orig_key if prefix is defined %} -{% if val is iterable and val is not string and orig_key in ['command'] -%} +{% if val is iterable and val is not string and orig_key in ['command'] %} {{ key }} = [ {{ val | map('icinga_vars') | join(' + ') }} ] {% elif orig_key in ['import'] -%} - {% for template in val if val is not string -%} + {% for template in val if val is not string %} {{ key }} "{{ template }}" {% endfor %} {% elif val is iterable and orig_key in ['assign', 'ignore'] -%} @@ -38,5 +38,5 @@ {{ key }} = true {% else -%} {{ key }} {{ operator }} {{ val|icinga_vars(iterator) }} -{% endif -%} -{% endmacro -%} +{% endif %} +{% endmacro %} From 7dbe5cbcec621ba91ed4011aec6df2ae1f025993 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Tue, 24 Mar 2020 11:34:05 +0100 Subject: [PATCH 18/34] Fix layout of generated configuration --- templates/host_template.conf.j2 | 33 +++++++++----------- templates/item_definitions.j2 | 47 +++++++++++++++-------------- templates/object_attributes.j2 | 26 ++++++++-------- templates/template_template.conf.j2 | 39 +++++++++++++----------- 4 files changed, 72 insertions(+), 73 deletions(-) diff --git a/templates/host_template.conf.j2 b/templates/host_template.conf.j2 index d37d828..97f3e6f 100644 --- a/templates/host_template.conf.j2 +++ b/templates/host_template.conf.j2 @@ -2,32 +2,27 @@ {% import 'object_attributes.j2' as attributes %} object Host "{{ hostvars[item].i2_hostname }}" { - {% if hostvars[item].i2_host_template is defined -%} - import "{{ hostvars[item].i2_host_template }}" - {% else -%} - import "generic-host" - {% endif -%} + import "{{ hostvars[item].get('i2_host_template', 'generic-host') }}" address = "{{ hostvars[item].i2_address }}" - {% if item not in groups[i2_master_group] and item not in groups[i2_satellite_group] -%} +{% if item not in groups[i2_master_group] and item not in groups[i2_satellite_group] %} vars.agent_endpoint = name // Follows the convention that host name == endpoint name - {% endif %} +{% endif %} vars.os = "{{ hostvars[item].ansible_system }}" vars.os_family = "{{ hostvars[item].ansible_os_family }}" - - {% if hostvars[item].i2_child_satellite_zones is defined and +{% if hostvars[item].i2_child_satellite_zones is defined and hostvars[item].i2_child_satellite_zones|length > 0 - -%} +%} // Satellite zones controlled by this master. {{ attributes.eval_value('zones', hostvars[item].i2_child_satellite_zones, 'vars.') }} - {% endif %} +{%- endif %} - {% if hostvars[item].i2_host_attributes is defined -%} - {% set host_attributes = hostvars[item].i2_host_attributes %} - {{ attributes.attrs(host_attributes) -}} - {% endif -%} - {% if hostvars[item].i2_host_variables is defined -%} - {% set host_variables = hostvars[item].i2_host_variables %} - {{ attributes.attrs(host_variables, 'vars.') -}} - {% endif -%} +{%- if hostvars[item].i2_host_attributes is defined %} +{% set host_attributes = hostvars[item].i2_host_attributes %} +{{ attributes.attrs(host_attributes) }} +{%- endif %} +{% if hostvars[item].i2_host_variables is defined %} +{% set host_variables = hostvars[item].i2_host_variables %} +{{ attributes.attrs(host_variables, 'vars.') }} +{%- endif %} } diff --git a/templates/item_definitions.j2 b/templates/item_definitions.j2 index 70ffe60..de975b1 100644 --- a/templates/item_definitions.j2 +++ b/templates/item_definitions.j2 @@ -10,44 +10,45 @@ library "{{ library }}" object {{ item.key }} "{{ object_name }}" { {% set vars = params.pop('variables', None) %} {{ attributes.attrs(params) }} -{% if vars is defined and vars is not none %} +{%- if vars is defined and vars is not none -%} {{ attributes.attrs(vars, 'vars.') }} {% endif -%} } +{% if not loop.last %} + +{% endif %} {% endfor %} {% endmacro %} -{% macro apply_rule(item) -%} +{% macro apply_rule(item) %} {% for rule_name, params in item.value.items() %} - {% set target = params.pop('target', None) %} +{% set target = target if target in ['Host', 'Service'] else 'Host' %} {% set iterator = params.pop('iterator', None) %} -{% set operators = params.pop('var_operators', None) %} - -apply {{ item.key }} "{{ rule_name }}{% if iterator is defined and iterator is not none -%} --" for ({% if iterator is string %}{{ iterator }}{% else %}{{ iterator.key }}{%- if iterator.value is defined %} => {{ iterator.value }}{% endif %} in {{ iterator.in }}{% endif %}) -{%- else -%}"{%- endif %} to{% if target in ['Host', 'Service'] %} {{ target }} {% else %} Host {% endif -%} -{ +{% set operators = params.pop('var_operators', None) -%} +apply {{ item.key }} "{{ rule_name }}{% if iterator is not none -%} +-" for ({% if iterator is string %}{{ iterator }}{% else %}{{ iterator.key }}{{ " => {}".format(iterator.value) if iterator.value }} in {{ iterator.in }}{% endif %}) +{%- else -%}"{%- endif %} to {{ target }} { {% if (params.attributes is not defined) and (params.variables is not defined) %} {{ attributes.attrs(params) }} -{% endif %} +{%- endif %} {% if params.variables is defined -%} {{ attributes.attrs(params.variables, 'vars.', '=', iterator) }} -{% endif %} +{%- endif %} -{% if params.conditionals is defined %} +{%- if params.conditionals is defined %} {% for conditional in params.conditionals %} {% set condition = conditional.pop('condition') %} if ({{ condition }}) { {{ attributes.attrs(conditional) }} } {% endfor %} -{% endif %} +{%- endif %} -{% if operators is defined and operators is not none and operators|length -%} +{%- if operators is defined and operators is not none and operators|length -%} {%- for operator, params in operators.items() %} {% if params is iterable and params is not string -%} {{ attributes.attrs({ 'vars': params }, '', operator, iterator) }} @@ -55,27 +56,27 @@ if ({{ condition }}) { {{ attributes.eval_value('vars', params, '', operator, iterator) }} {% endif -%} {% endfor -%} -{% endif -%} +{%- endif %} -{% if params.custom is defined %} +{%- if params.custom is defined %} {{ params.custom }} -{% endif %} +{%- endif %} -{% if params.attributes is defined %} +{%- if params.attributes is defined %} {{ attributes.attrs(params.attributes) }} -{% endif %} - +{%- endif %} } +{% if not loop.last %} + +{% endif %} {% endfor %} {% endmacro %} {% macro template(item) -%} - -{% for object_name, params in item.value.items() %} - +{% for object_name, params in item.value.items() -%} {% set operators = params.pop('var_operators', None) %} template {{ item.key }} "{{ object_name }}" { diff --git a/templates/object_attributes.j2 b/templates/object_attributes.j2 index 75f0fd5..d390007 100644 --- a/templates/object_attributes.j2 +++ b/templates/object_attributes.j2 @@ -3,8 +3,8 @@ {% if v is mapping %} {{ mapdict(k, v, prefix, operator, iterator) | indent(width=2)}} {% else %} - {{ eval_value(k, v, prefix, operator, iterator) }} -{%- endif %} + {{ eval_value(k, v, prefix, operator, iterator) | indent(width=2) }} +{% endif %} {% endfor %} {% endmacro %} @@ -14,8 +14,8 @@ {% if value is mapping %} {{ mapdict(subkey, value, "", operator, iterator) | indent(width=2) }} {% else %} - {{ eval_value(subkey, value, "", operator, iterator) }} -{%- endif %} + {{ eval_value(subkey, value, "", operator, iterator) | indent(width=2) }} +{% endif %} {% endfor %} } {% endmacro %} @@ -23,20 +23,20 @@ {% macro eval_value(orig_key, val, prefix="", operator="=", iterator=None) %} {% set key = prefix + orig_key if prefix is defined %} {% if val is iterable and val is not string and orig_key in ['command'] %} - {{ key }} = [ {{ val | map('icinga_vars') | join(' + ') }} ] +{{ key }} = [ {{ val | map('icinga_vars') | join(' + ') }} ] {% elif orig_key in ['import'] -%} - {% for template in val if val is not string %} - {{ key }} "{{ template }}" - {% endfor %} +{% for template in val if val is not string %} +{{ key }} "{{ template }}" +{% endfor %} {% elif val is iterable and orig_key in ['assign', 'ignore'] -%} - {{ key }} where {{ val | join(' && ') }} +{{ key }} where {{ val | join(' && ') }} {% elif val is iterable and val is not string -%} - {{ key }} = [ {{ val | map('icinga_vars') | join(', ') }} ] +{{ key }} = [ {{ val | map('icinga_vars') | join(', ') }} ] {% elif (val | bool is sameas false) and (val | string | lower == "false") -%} - {{ key }} = false +{{ key }} = false {% elif (val is defined) and (val | bool is sameas true) -%} - {{ key }} = true +{{ key }} = true {% else -%} - {{ key }} {{ operator }} {{ val|icinga_vars(iterator) }} +{{ key }} {{ operator }} {{ val|icinga_vars(iterator) }} {% endif %} {% endmacro %} diff --git a/templates/template_template.conf.j2 b/templates/template_template.conf.j2 index 535c6ed..c763017 100644 --- a/templates/template_template.conf.j2 +++ b/templates/template_template.conf.j2 @@ -1,32 +1,35 @@ // {{ ansible_managed }} {% import 'object_attributes.j2' as attributes %} - {% for object_name, params in item.value.items() %} - -{% set operators = params.pop('var_operators', None) %} +{% set operators = params.pop('var_operators', None) -%} template {{ item.key }} "{{ object_name }}" { -{% if params.attributes is defined -%} -{{ attributes.attrs(params.attributes) -}} -{% endif -%} -{% if params.variables is defined -%} -{{ attributes.attrs(params.variables, 'vars.') -}} -{% endif -%} -{% if params.attributes is not defined and params.variables is not defined %} -{{ attributes.attrs(params) -}} -{% endif %} -{% if params.conditionals is defined -%} +{% if params.attributes is defined %} +{{ attributes.attrs(params.attributes) }} +{%- elif params.variables is not defined %} +{{ attributes.attrs(params) }} +{%- endif %} + +{%- if params.variables is defined %} +{{ attributes.attrs(params.variables, 'vars.') }} +{%- endif %} + +{%- if params.conditionals is defined %} {% for conditional in params.conditionals %} {% set condition = conditional.pop('condition') %} if ({{ condition }}) { {{ attributes.attrs(conditional) -}} } {% endfor %} -{% endif -%} -{% if operators is defined and operators is not none and operators|length -%} -{%- for operator, params in operators.items() %} +{% endif %} + +{%- if operators is defined and operators is not none and operators|length %} +{% for operator, params in operators.items() %} {{ attributes.attrs({ 'vars': params }, '', operator) }} -{% endfor -%} -{% endif -%} +{% endfor %} +{% endif %} } +{% if not loop.last %} + +{% endif %} {% endfor %} From 3308e02cd5d7d43555f49a1c82207637d71f9dc2 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 14 May 2020 12:14:10 +0200 Subject: [PATCH 19/34] Configure the satellites via "Top Down Config Sync" --- tasks/icinga2-bootstrap.yml | 2 ++ templates/host_template.conf.j2 | 11 +++++++ templates/item_definitions.j2 | 42 +++++++++++++++++++++++++ templates/zones.conf.j2 | 56 +++++++-------------------------- 4 files changed, 66 insertions(+), 45 deletions(-) diff --git a/tasks/icinga2-bootstrap.yml b/tasks/icinga2-bootstrap.yml index d5a01e7..268a397 100644 --- a/tasks/icinga2-bootstrap.yml +++ b/tasks/icinga2-bootstrap.yml @@ -61,6 +61,8 @@ {{ hostvars[item].i2_custom_objects|default({}) }} i2_apply_rules: >- {{ hostvars[item].i2_custom_apply_rules|default({}) }} + i2_connection_direction: >- + {{ hostvars[item].i2_connection_directorion|default(i2_connection_direction) }} run_once: True delegate_facts: True delegate_to: "{{ item }}" diff --git a/templates/host_template.conf.j2 b/templates/host_template.conf.j2 index 97f3e6f..90eb821 100644 --- a/templates/host_template.conf.j2 +++ b/templates/host_template.conf.j2 @@ -1,6 +1,17 @@ // {{ ansible_managed }} +{% import 'item_definitions.j2' as definitions %} {% import 'object_attributes.j2' as attributes %} +{# + # When the item is an agent include the Endpoint and Zone for the this agent + # in the generates host configuration. + #} +{% if item not in groups[i2_master_group]|union(groups[i2_satellite_group]) %} +{% set item_parent = hostvars[item].i2_parent_nodes[0] %} +{{ definitions.endpoint(item, item_parent, hostvars) }} +{{ definitions.zone(hostvars[item].i2_zonename, hostvars[item_parent].i2_zonename, hostvars) }} + +{% endif %} object Host "{{ hostvars[item].i2_hostname }}" { import "{{ hostvars[item].get('i2_host_template', 'generic-host') }}" address = "{{ hostvars[item].i2_address }}" diff --git a/templates/item_definitions.j2 b/templates/item_definitions.j2 index de975b1..5d2dffe 100644 --- a/templates/item_definitions.j2 +++ b/templates/item_definitions.j2 @@ -105,3 +105,45 @@ if ({{ condition }}) { } {% endfor %} {% endmacro %} + +{% macro endpoint(item, current, hostvars) -%} +object Endpoint "{{ hostvars[item].i2_hostname }}" { +{% if item == current %} + // That's us +{% elif item in hostvars[current].i2_parent_nodes %} +{% if hostvars[current].i2_connection_direction == 'top-down' %} + // Parent already connects to us. +{% else %} + host = "{{ hostvars[item].i2_api_host }}" // Actively connect to parent. + port = "{{ hostvars[item].i2_api_port }}" +{% endif -%} +{% elif item in hostvars[current].i2_peer_nodes %} +{% if (current == hostvars[current].i2_peer_nodes[0] and hostvars[item].i2_connection_direction == 'top-down') + or (current != hostvars[current].i2_peer_nodes[0] and hostvars[item].i2_connection_direction != 'top-down' ) %} + host = "{{ hostvars[item].i2_api_host }}" // Actively connect to peer. + port = "{{ hostvars[item].i2_api_port }}" +{% else %} + // Peer already connects to us. +{% endif -%} +{% elif item in hostvars[current].i2_child_nodes %} +{% if hostvars[item].i2_connection_direction == 'top-down' %} + host = "{{ hostvars[item].i2_api_host }}" // Actively connect to child node. + port = "{{ hostvars[item].i2_api_port }}" +{% else %} + // Child node will connect to us. +{% endif -%} +{% endif %} +{% if not hostvars[item].i2_master|default(False) and not hostvars[item].i2_satellite|default(False) %} + log_duration = 0 +{% endif %} +} +{%- endmacro %} + +{% macro zone(item, parent, hostvars) -%} +{% set endpointvars = hostvars | dict2items | json_query("[?value.i2_zonename=='" + item + "'].value") %} +object Zone "{{ item }}" { + endpoints = [ {{ endpointvars | map(attribute='i2_hostname') | sort | map('icinga_vars') | join(', ') }} ] +{% if parent %} parent = {{ parent | icinga_vars }} +{% endif %} +} +{%- endmacro %} diff --git a/templates/zones.conf.j2 b/templates/zones.conf.j2 index 70e42a3..6519391 100644 --- a/templates/zones.conf.j2 +++ b/templates/zones.conf.j2 @@ -1,4 +1,5 @@ // {{ ansible_managed }} +{% import 'item_definitions.j2' as definitions %} /* * Defines a global zone for distributed setups with masters, @@ -29,14 +30,7 @@ object Zone "director-global" { # Create Endpoints for all the nodes in our parent Zone #} {% for item in i2_parent_nodes -%} -object Endpoint "{{ hostvars[item].i2_hostname }}" { -{% if i2_connection_direction == 'top-down' %} - // Parent already connects to us. -{% else %} - host = "{{ hostvars[item].i2_api_host }}" // Actively connect to parent. - port = "{{ hostvars[item].i2_api_port }}" -{% endif -%} -} +{{ definitions.endpoint(item, inventory_hostname, hostvars) }} {% endfor -%} @@ -44,65 +38,37 @@ object Endpoint "{{ hostvars[item].i2_hostname }}" { # Create Endpoints for all the nodes in our Zone #} {% for item in i2_peer_nodes -%} -object Endpoint "{{ hostvars[item].i2_hostname }}" { -{% if inventory_hostname == item %} - // That's us -{% elif (inventory_hostname == i2_peer_nodes[0] and i2_connection_direction == 'top-down') - or (inventory_hostname != i2_peer_nodes[0] and i2_connection_direction != 'top-down' ) %} - host = "{{ hostvars[item].i2_api_host }}" // Actively connect to peer. - port = "{{ hostvars[item].i2_api_port }}" -{% else %} - // Peer already connects to us. -{% endif -%} -} +{{ definitions.endpoint(item, inventory_hostname, hostvars) }} {% endfor -%} +{% if inventory_hostname in groups[i2_master_group] %} {# # Create Endpoints for all the nodes in child Zones #} {% for item in i2_child_nodes -%} -{% if hostvars[item].i2_hostname is defined -%} -object Endpoint "{{ hostvars[item].i2_hostname }}" { -{% if i2_connection_direction == 'top-down' %} - host = "{{ hostvars[item].i2_api_host }}" // Actively connect to child node. - port = "{{ hostvars[item].i2_api_port }}" -{% else %} - // Child node will connect to us. -{% endif %} -} -{% endif %} +{{ definitions.endpoint(item, inventory_hostname, hostvars) }} {% endfor -%} +{% endif -%} {# # The parent Zone of the current node #} {% if i2_parent_zone is defined -%} -object Zone "{{ i2_parent_zone }}" { - endpoints = [ {{ hostvars|dict2items - | json_query("[?value.i2_zonename==" + "'" + i2_parent_zone + "'].key") - | sort|map('icinga_vars')|join(', ') }} ] -} +{{ definitions.zone(i2_parent_zone, '', hostvars) }} {% endif -%}{# # The Zone of the current node #} -object Zone "{{ i2_zonename }}" { - endpoints = [ {{ i2_peer_nodes|map('extract', hostvars, 'i2_hostname')|map('icinga_vars')|join(', ') }} ] -{% if i2_parent_zone is defined %} parent = {{ i2_parent_zone|icinga_vars }} -{% endif %} -} +{{ definitions.zone(i2_zonename, i2_parent_zone|default(''), hostvars) }} +{% if inventory_hostname in groups[i2_master_group] %} {# # The child Zones of the current node #} {% for child_zone in i2_child_zones -%} -object Zone "{{ child_zone }}" { - endpoints = [ {{ hostvars|dict2items - | json_query("[?value.i2_zonename==" + "'" + child_zone + "'].key") - | sort|map('icinga_vars')|join(', ') }} ] - parent = "{{ i2_zonename }}" -} +{{ definitions.zone(child_zone, i2_zonename, hostvars) }} {% endfor -%} +{% endif %} From 0da7e099fcecb91b9286ff33aa628f574e0b5cda Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Wed, 22 Jul 2020 14:57:54 +0200 Subject: [PATCH 20/34] Mark commands tags which don't change the system --- tasks/icinga2-bootstrap.yml | 2 ++ tasks/icinga2-web2-Debian.yml | 1 + 2 files changed, 3 insertions(+) diff --git a/tasks/icinga2-bootstrap.yml b/tasks/icinga2-bootstrap.yml index 268a397..eb058c2 100644 --- a/tasks/icinga2-bootstrap.yml +++ b/tasks/icinga2-bootstrap.yml @@ -159,3 +159,5 @@ command: /usr/sbin/getenforce register: selinux when: ansible_os_family == 'RedHat' + changed_when: false + check_mode: false diff --git a/tasks/icinga2-web2-Debian.yml b/tasks/icinga2-web2-Debian.yml index a7ddbc0..ff04f0c 100644 --- a/tasks/icinga2-web2-Debian.yml +++ b/tasks/icinga2-web2-Debian.yml @@ -14,6 +14,7 @@ command: php --version register: php_version changed_when: false + check_mode: false - name: IcingaWeb2 – Set PHP version set_fact: From f1b010e8add6696c4dcb8927a92abfe42cff148b Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Wed, 22 Jul 2020 14:58:54 +0200 Subject: [PATCH 21/34] Make the state of the icinga packages a variable so we can use this role to upgrade the packages as well --- tasks/icinga2-Debian.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/icinga2-Debian.yml b/tasks/icinga2-Debian.yml index acccb80..b48e7c8 100644 --- a/tasks/icinga2-Debian.yml +++ b/tasks/icinga2-Debian.yml @@ -24,7 +24,7 @@ become: yes apt: name: icinga2 - state: present + state: "{{ i2_package_state|default('present') }}" notify: start icinga2 when: i2_manage_package @@ -32,7 +32,7 @@ become: yes apt: name: "icinga2-ido-{{ i2_ido_backend }}" - state: present + state: "{{ i2_package_state|default('present') }}" notify: start icinga2 when: - i2_manage_package From 2933b2863edc0f2936b1ca23b441ae60be0fb05a Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Wed, 26 Aug 2020 08:57:34 +0200 Subject: [PATCH 22/34] Use the i2_package_state for Red Hat as well and use the restart icinga2 handler so icinga2 will be restarted on upgrades --- tasks/icinga2-Debian.yml | 4 ++-- tasks/icinga2-RedHat.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tasks/icinga2-Debian.yml b/tasks/icinga2-Debian.yml index b48e7c8..fedaba5 100644 --- a/tasks/icinga2-Debian.yml +++ b/tasks/icinga2-Debian.yml @@ -25,7 +25,7 @@ apt: name: icinga2 state: "{{ i2_package_state|default('present') }}" - notify: start icinga2 + notify: restart icinga2 when: i2_manage_package - name: Debian - Ensure IDO is installed on the masters @@ -33,7 +33,7 @@ apt: name: "icinga2-ido-{{ i2_ido_backend }}" state: "{{ i2_package_state|default('present') }}" - notify: start icinga2 + notify: retart icinga2 when: - i2_manage_package - i2_ido_backend is defined diff --git a/tasks/icinga2-RedHat.yml b/tasks/icinga2-RedHat.yml index 732b1be..d4b65c0 100644 --- a/tasks/icinga2-RedHat.yml +++ b/tasks/icinga2-RedHat.yml @@ -20,9 +20,9 @@ become: yes yum: name: icinga2 - state: present + state: "{{ i2_package_state|default('present') }}" update_cache: yes - notify: start icinga2 + notify: restart icinga2 when: i2_manage_package - name: RedHat - Ensure IDO is installed on the masters @@ -30,7 +30,7 @@ yum: name: "icinga2-ido-{{ i2_ido_backend }}" state: present - notify: start icinga2 + notify: restart icinga2 when: - i2_manage_package - i2_ido_backend is defined From 93c25eef58de763a8a6f2b7af0909d121059225b Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 27 Aug 2020 14:14:42 +0200 Subject: [PATCH 23/34] Specify default more clearly --- defaults/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 7214432..811537d 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -33,8 +33,8 @@ i2_remove_unmanaged_features: no i2_remove_unmanaged_objects: no i2_remove_unmanaged_objects_in_zone: no -i2_master: no -i2_satellite: no +i2_master: "{{ inventory_hostname in groups[i2_master_group] }}" +i2_satellite: "{{ inventory_hostname in groups[i2_satellite_group] }}" i2_api_port: 5665 i2_connection_direction: 'top-down' From 75a44743ea30b3fc1c8e0aa6f990229e5ea159d4 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 27 Aug 2020 14:16:04 +0200 Subject: [PATCH 24/34] Support install icingaweb on additional hosts --- defaults/main.yml | 1 + tasks/icinga2-web2-Debian.yml | 6 ++++++ tasks/main.yml | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 8e8e321..7570a56 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -33,6 +33,7 @@ i2_remove_unmanaged_features: no i2_remove_unmanaged_objects: no i2_remove_unmanaged_objects_in_zone: no +i2_webui: "{{ inventory_hostname == i2_configuration_master }}" i2_master: "{{ inventory_hostname in groups[i2_master_group] }}" i2_satellite: "{{ inventory_hostname in groups[i2_satellite_group] }}" i2_api_port: 5665 diff --git a/tasks/icinga2-web2-Debian.yml b/tasks/icinga2-web2-Debian.yml index 10af9e9..916722e 100644 --- a/tasks/icinga2-web2-Debian.yml +++ b/tasks/icinga2-web2-Debian.yml @@ -1,4 +1,10 @@ --- +- name: IcingaWeb2 - Install dependencies + apt: + name: + - "python{% if ansible_python['version']['major'] == 3 %}3{% endif %}-pymysql" + state: present + - name: IcingaWeb2 – Install PHP requirements apt: name: diff --git a/tasks/main.yml b/tasks/main.yml index 109c05e..6e5f89e 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -60,7 +60,7 @@ - name: Set up Icingaweb2 import_tasks: icinga2-web2.yml when: - - inventory_hostname == i2_configuration_master + - i2_webui - i2_setup_webui tags: - webui From 16c1acff1a55c7552802ca6f7a4d24b89f9d022e Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 10 Sep 2020 16:22:04 +0200 Subject: [PATCH 25/34] handle lists --- templates/icingaweb2-config.ini.j2 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/icingaweb2-config.ini.j2 b/templates/icingaweb2-config.ini.j2 index 7956e7b..056a688 100644 --- a/templates/icingaweb2-config.ini.j2 +++ b/templates/icingaweb2-config.ini.j2 @@ -1,6 +1,10 @@ {% for section, options in item.value.sections.items() %} [{{ section }}] {% for option, value in options|dictsort %} +{% if value is string %} {{ option }} = "{{ value }}" +{% elif value is iterable %} +{{ option }} = "{{ value|join(', ') }}" +{% endif %} {% endfor %} {% endfor %} From e270edadf462a9e2c4550468ef17d9fb994acec1 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 18 Feb 2021 13:55:31 +0100 Subject: [PATCH 26/34] Use complete path to binary --- tasks/icinga2-api.yml | 6 ++-- tasks/icinga2-node-config.yml | 62 +++++++++++++++++------------------ 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/tasks/icinga2-api.yml b/tasks/icinga2-api.yml index 40d74b3..9550a2c 100644 --- a/tasks/icinga2-api.yml +++ b/tasks/icinga2-api.yml @@ -10,7 +10,7 @@ - name: Master - Create Certificate Authority become: yes - command: icinga2 pki new-ca + command: /usr/sbin/icinga2 pki new-ca args: creates: "{{ i2_ca_file }}" when: inventory_hostname == i2_configuration_master @@ -97,7 +97,7 @@ - name: Master - Create Host Certificate become: yes command: > - icinga2 pki new-cert + /usr/sbin/icinga2 pki new-cert --cn {{ i2_hostname }} --key {{ i2_pki_path }}/{{ i2_hostname }}.key --csr {{ i2_pki_path }}/{{ i2_hostname }}.csr @@ -107,7 +107,7 @@ - name: Master - Sign Host Certificate become: yes command: > - icinga2 pki sign-csr + /usr/sbin/icinga2 pki sign-csr --csr {{ i2_pki_path }}/{{ i2_hostname }}.csr --cert {{ i2_pki_path }}/{{ i2_hostname }}.crt args: diff --git a/tasks/icinga2-node-config.yml b/tasks/icinga2-node-config.yml index 52ba792..8668e65 100644 --- a/tasks/icinga2-node-config.yml +++ b/tasks/icinga2-node-config.yml @@ -18,7 +18,7 @@ # This command must be run as privileged user or the icinga user - name: Nodes - Generate Client Ticket on Master become: yes - command: icinga2 pki ticket --cn {{ i2_hostname }} + command: /usr/sbin/icinga2 pki ticket --cn {{ i2_hostname }} register: pki_ticket delegate_to: "{{ i2_configuration_master }}" when: i2_certificate_signed_by_ca is sameas false @@ -26,36 +26,36 @@ - name: Nodes - Generate self-signed certificate for first-contact with parent become: yes command: > - icinga2 pki new-cert --cn {{ i2_hostname }} - --key {{ i2_pki_path }}/{{ i2_hostname }}.key - --cert {{ i2_pki_file }} + /usr/sbin/icinga2 pki new-cert --cn {{ i2_hostname }} + --key {{ i2_pki_path }}/{{ i2_hostname }}.key + --cert {{ i2_pki_file }} when: trusted_authority.stat.exists is sameas false - name: Nodes - Retrieve Public Certificate from Parent Node become: yes command: > - icinga2 pki save-cert - --key {{ i2_pki_path }}/{{ i2_hostname }}.key - --cert {{ i2_pki_file }} - --trustedcert {{ i2_pki_path }}/trusted_parent.crt - --host {{ hostvars[i2_parent_nodes[0]]['i2_api_host'] }} - --port {{ hostvars[i2_parent_nodes[0]]['i2_api_port'] }} + /usr/sbin/icinga2 pki save-cert + --key {{ i2_pki_path }}/{{ i2_hostname }}.key + --cert {{ i2_pki_file }} + --trustedcert {{ i2_pki_path }}/trusted_parent.crt + --host {{ hostvars[i2_parent_nodes[0]]['i2_api_host'] }} + --port {{ hostvars[i2_parent_nodes[0]]['i2_api_port'] }} when: trusted_authority.stat.exists is sameas false - name: Nodes - Retrieve signed certificate and set-up agent (Top-Down) become: yes command: > - icinga2 node setup - --cn {{ i2_hostname }} - --ticket {{ pki_ticket.stdout }} - --endpoint {{ hostvars[i2_parent_nodes[0]]['i2_hostname'] }} - --trustedcert {{ i2_pki_path }}/trusted_parent.crt - --zone '{{ i2_zonename }}' - --parent_zone '{{ i2_parent_zone }}' - --parent_host {{ hostvars[i2_parent_nodes[0]]['i2_api_host'] }} - --accept-commands - --accept-config - --disable-confd + /usr/sbin/icinga2 node setup + --cn {{ i2_hostname }} + --ticket {{ pki_ticket.stdout }} + --endpoint {{ hostvars[i2_parent_nodes[0]]['i2_hostname'] }} + --trustedcert {{ i2_pki_path }}/trusted_parent.crt + --zone '{{ i2_zonename }}' + --parent_zone '{{ i2_parent_zone }}' + --parent_host {{ hostvars[i2_parent_nodes[0]]['i2_api_host'] }} + --accept-commands + --accept-config + --disable-confd when: i2_connection_direction == 'top-down' and not i2_certificate_signed_by_ca notify: restart icinga2 @@ -69,16 +69,16 @@ - name: Nodes - Retrieve signed certificate and set-up agent (Bottom-Up) become: yes command: >- - icinga2 node setup - --cn {{ i2_hostname }} - --ticket {{ pki_ticket.stdout }} {{ endpoints }} - --trustedcert {{ i2_pki_path }}/trusted_parent.crt - --zone '{{ i2_zonename }}' - --parent_zone '{{ i2_parent_zone }}' - --parent_host {{ hostvars[i2_parent_nodes[0]]['i2_api_host'] }},{{ hostvars[i2_parent_nodes[0]]['i2_api_port'] }} - --accept-commands - --accept-config - --disable-confd + /usr/sbin/icinga2 node setup + --cn {{ i2_hostname }} + --ticket {{ pki_ticket.stdout }} {{ endpoints }} + --trustedcert {{ i2_pki_path }}/trusted_parent.crt + --zone '{{ i2_zonename }}' + --parent_zone '{{ i2_parent_zone }}' + --parent_host {{ hostvars[i2_parent_nodes[0]]['i2_api_host'] }},{{ hostvars[i2_parent_nodes[0]]['i2_api_port'] }} + --accept-commands + --accept-config + --disable-confd when: - i2_connection_direction == 'bottom-up' - not i2_certificate_signed_by_ca From 70aa2fa803e00124e40b1a5471aea8662a810d8f Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Fri, 26 Feb 2021 08:40:40 +0100 Subject: [PATCH 27/34] Only do set_fact if the hostvar is not set yet or incorrect and add an option (i2_bootstrap_cacheable) to cache the values. This will help with hosts which are temporarily down --- defaults/main.yml | 2 +- tasks/icinga2-bootstrap.yml | 113 ++++++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 19 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 811537d..63f2b37 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -85,4 +85,4 @@ i2_webui_params: i2_webui_connectfrom: - localhost - +i2_bootstrap_cacheable: False diff --git a/tasks/icinga2-bootstrap.yml b/tasks/icinga2-bootstrap.yml index eb058c2..a72bce8 100644 --- a/tasks/icinga2-bootstrap.yml +++ b/tasks/icinga2-bootstrap.yml @@ -13,7 +13,13 @@ {{ groups[i2_master_group]|default([]) + groups[i2_satellite_group]|default([]) + groups[i2_agent_group]|default([]) }} - when: hostvars[item].ansible_fqdn is not defined + when: + - hostvars[item].ansible_fqdn is not defined or + hostvars[item].ansible_facts.default_ipv4.address is not defined + - hostvars[item].i2_address is not defined or + hostvars[item].i2_api_host is not defined or + hostvars[item].i2_hostname is not defined or + hostvars[item].i2_zonename is not defined # Copying role-vars to host-vars # We do this in a loop over all the nodes as we @@ -21,6 +27,7 @@ # which we don't get if a --limit is in place - name: Set default hostvars for Icinga masters set_fact: + cacheable: "{{ i2_bootstrap_cacheable }}" i2_master: >- {{ hostvars[item].i2_master|default(True) }} i2_satellite: >- @@ -29,9 +36,12 @@ delegate_facts: True delegate_to: "{{ item }}" loop: "{{ groups[i2_master_group]|default([]) }}" + when: hostvars[item].i2_master is not defined or + hostvars[item].i2_satellite is not defined - name: Set default hostvars for Icinga satellites set_fact: + cacheable: "{{ i2_bootstrap_cacheable }}" i2_master: >- {{ hostvars[item].i2_master|default(False) }} i2_satellite: >- @@ -42,9 +52,30 @@ delegate_facts: True delegate_to: "{{ item }}" loop: "{{ groups[i2_satellite_group]|default([]) }}" + when: hostvars[item].i2_master is not defined or + hostvars[item].i2_satellite is not defined or + hostvars[item].i2_parent_zone is not defined + +- name: Set default hostvars for Icinga agents + set_fact: + cacheable: "{{ i2_bootstrap_cacheable }}" + i2_master: >- + {{ hostvars[item].i2_master|default(False) }} + i2_satellite: >- + {{ hostvars[item].i2_satellite|default(False) }} + i2_parent_zone: >- + {{ hostvars[item].i2_parent_zone|default('master') }} + run_once: True + delegate_facts: True + delegate_to: "{{ item }}" + loop: "{{ groups[i2_agent_group]|default([]) }}" + when: hostvars[item].i2_master is not defined or + hostvars[item].i2_satellite is not defined or + hostvars[item].i2_parent_zone is not defined - name: Set default hostvars for all Icinga nodes set_fact: + cacheable: "{{ i2_bootstrap_cacheable }}" i2_address: >- {{ hostvars[item].i2_address|default(hostvars[item].ansible_facts.default_ipv4.address) }} i2_api_port: >- @@ -55,14 +86,30 @@ {{ hostvars[item].i2_hostname|default(hostvars[item].ansible_fqdn) }} i2_zonename: >- {{ hostvars[item].i2_zonename|default(hostvars[item].ansible_fqdn) }} + i2_connection_direction: >- + {{ hostvars[item].i2_connection_directorion|default(i2_connection_direction) }} + run_once: True + delegate_facts: True + delegate_to: "{{ item }}" + loop: >- + {{ groups[i2_master_group]|default([]) + + groups[i2_satellite_group]|default([]) + + groups[i2_agent_group]|default([]) }} + when: hostvars[item].i2_address is not defined or + hostvars[item].i2_api_port is not defined or + hostvars[item].i2_api_host is not defined or + hostvars[item].i2_hostname is not defined or + hostvars[item].i2_zonename is not defined or + hostvars[item].i2_connection_direction is not defined + +- name: Set additional hostvars needed for configuration master + set_fact: i2_templates: >- {{ hostvars[item].i2_custom_templates|default({}) }} i2_objects: >- {{ hostvars[item].i2_custom_objects|default({}) }} i2_apply_rules: >- {{ hostvars[item].i2_custom_apply_rules|default({}) }} - i2_connection_direction: >- - {{ hostvars[item].i2_connection_directorion|default(i2_connection_direction) }} run_once: True delegate_facts: True delegate_to: "{{ item }}" @@ -70,13 +117,12 @@ {{ groups[i2_master_group]|default([]) + groups[i2_satellite_group]|default([]) + groups[i2_agent_group]|default([]) }} + when: inventory_hostname == i2_configuration_master - name: Determine peer nodes set_fact: - i2_peer_nodes: >- - {{ hostvars | dict2items - | json_query("[?value.i2_zonename==" + "'" + hostvars[item].i2_zonename + "'].key") - | sort }} + cacheable: "{{ i2_bootstrap_cacheable }}" + i2_peer_nodes: "{{ peers }}" run_once: True delegate_facts: True delegate_to: "{{ item }}" @@ -84,29 +130,45 @@ {{ groups[i2_master_group]|default([]) + groups[i2_satellite_group]|default([]) + groups[i2_agent_group]|default([]) }} + vars: + x: "{{ [hostvars[item].i2_peer_nodes, i2_peer_nodes] }}" + peers: >- + {{ hostvars | dict2items + | json_query("[?value.i2_zonename=='" + hostvars[item].i2_zonename + "'].key") + | sort }} + when: hostvars[item].i2_peer_nodes is not defined or + hostvars[item].i2_peer_nodes != peers - name: Determine parent and child nodes set_fact: - i2_child_nodes: >- + cacheable: "{{ i2_bootstrap_cacheable }}" + i2_child_nodes: "{{ childs }}" + i2_parent_nodes: "{{ parents }}" + run_once: True + delegate_facts: True + delegate_to: "{{ item }}" + loop: >- + {{ groups[i2_master_group]|default([]) + + groups[i2_satellite_group]|default([]) + + groups[i2_agent_group]|default([]) }} + vars: + childs: >- {{ hostvars | dict2items - | json_query("[?value.i2_parent_zone==" + "'" + hostvars[item].i2_zonename + "'].key") + | json_query("[?value.i2_parent_zone=='" + hostvars[item].i2_zonename + "'].key") | difference(hostvars[item].i2_peer_nodes) | sort }} - i2_parent_nodes: >- + parents: >- {%- if hostvars[item].i2_parent_zone is defined -%} {{ hostvars | dict2items - | json_query("[?value.i2_zonename==" + "'" + hostvars[item].i2_parent_zone + "'].key") + | json_query("[?value.i2_zonename=='" + hostvars[item].i2_parent_zone + "'].key") | difference(hostvars[item].i2_peer_nodes) | sort }} {%- else %}[]{% endif -%} - run_once: True - delegate_facts: True - delegate_to: "{{ item }}" - loop: >- - {{ groups[i2_master_group]|default([]) - + groups[i2_satellite_group]|default([]) - + groups[i2_agent_group]|default([]) }} + when: hostvars[item].i2_child_nodes is not defined or + hostvars[item].i2_parent_nodes is not defined or + hostvars[item].i2_child_nodes != childs or + hostvars[item].i2_parent_nodes != parents - name: Determine satellite zones set_fact: @@ -117,6 +179,7 @@ - name: Determine child zones set_fact: + cacheable: "{{ i2_bootstrap_cacheable }}" i2_child_zones: >- {{ hostvars[item].i2_child_nodes | map('extract', hostvars, 'i2_zonename' ) | unique @@ -133,6 +196,20 @@ {{ groups[i2_master_group]|default([]) + groups[i2_satellite_group]|default([]) + groups[i2_agent_group]|default([]) }} + vars: + child_zones: >- + {{ hostvars[item].i2_child_nodes | map('extract', hostvars, 'i2_zonename' ) + | unique + | sort }} + child_satellite_zones: >- + {{ hostvars[item].i2_child_nodes | map('extract', hostvars, 'i2_zonename' ) + | unique + | intersect(i2_satellite_zones) + | sort }} + when: hostvars[item].i2_child_zones is not defined or + hostvars[item].i2_child_satellite_zones is not defined or + hostvars[item].i2_child_zones != child_zones or + hostvars[item].i2_child_satellite_zones != child_satellite_zones - name: Check if Client Certificates exist become: yes From fddb44a8a4ff08e7cdf32b0146035ee3fcf0aa65 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Fri, 26 Feb 2021 08:48:26 +0100 Subject: [PATCH 28/34] Remove space after comma in lists --- templates/icingaweb2-config.ini.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/icingaweb2-config.ini.j2 b/templates/icingaweb2-config.ini.j2 index 056a688..0dd2806 100644 --- a/templates/icingaweb2-config.ini.j2 +++ b/templates/icingaweb2-config.ini.j2 @@ -4,7 +4,7 @@ {% if value is string %} {{ option }} = "{{ value }}" {% elif value is iterable %} -{{ option }} = "{{ value|join(', ') }}" +{{ option }} = "{{ value|join(',') }}" {% endif %} {% endfor %} {% endfor %} From 3b99aa2ea36f8d3b69dc3e222baac387f79dbd7a Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 11 Mar 2021 09:15:41 +0100 Subject: [PATCH 29/34] Fix removal of unmanaged files which sometimes removed to much --- tasks/icinga2-objects.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasks/icinga2-objects.yml b/tasks/icinga2-objects.yml index d8d2bcc..01cba33 100644 --- a/tasks/icinga2-objects.yml +++ b/tasks/icinga2-objects.yml @@ -158,7 +158,9 @@ + managed_zone_objects.results + managed_zone_apply_rules.results + managed_zone_hosts.results ) - | selectattr('dest', 'defined') + | selectattr('invocation', 'defined') + | map(attribute='invocation') + | map(attribute='module_args') | map(attribute='dest') | list }}" @@ -177,7 +179,5 @@ file: path: "{{ item }}" state: absent - with_items: "{{ existing_files|default([]) }}" - when: - - item not in managed_object_files - - i2_remove_unmanaged_objects + with_items: "{{ existing_files|default([])|difference(managed_object_files) }}" + when: i2_remove_unmanaged_objects From 885793404bfd3da124000679fdd56940153a844e Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Thu, 11 Mar 2021 14:09:04 +0100 Subject: [PATCH 30/34] Remove when clause which causes configuration to be lost --- tasks/icinga2-bootstrap.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/tasks/icinga2-bootstrap.yml b/tasks/icinga2-bootstrap.yml index a72bce8..684be23 100644 --- a/tasks/icinga2-bootstrap.yml +++ b/tasks/icinga2-bootstrap.yml @@ -117,7 +117,6 @@ {{ groups[i2_master_group]|default([]) + groups[i2_satellite_group]|default([]) + groups[i2_agent_group]|default([]) }} - when: inventory_hostname == i2_configuration_master - name: Determine peer nodes set_fact: From 86e9f93781af61c90454f26ba2a79248944dcf90 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Wed, 7 Apr 2021 10:27:41 +0200 Subject: [PATCH 31/34] Handle hosts in the all group --- tasks/icinga2-bootstrap.yml | 65 +++++++++++++++++---------------- tasks/icinga2-objects.yml | 8 ++-- templates/host_template.conf.j2 | 6 ++- 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/tasks/icinga2-bootstrap.yml b/tasks/icinga2-bootstrap.yml index 684be23..9c08494 100644 --- a/tasks/icinga2-bootstrap.yml +++ b/tasks/icinga2-bootstrap.yml @@ -125,37 +125,28 @@ run_once: True delegate_facts: True delegate_to: "{{ item }}" - loop: >- - {{ groups[i2_master_group]|default([]) - + groups[i2_satellite_group]|default([]) - + groups[i2_agent_group]|default([]) }} + loop: "{{ groups['all' ] }}" vars: - x: "{{ [hostvars[item].i2_peer_nodes, i2_peer_nodes] }}" peers: >- + {%- if hostvars[item].i2_zonename is defined -%} {{ hostvars | dict2items | json_query("[?value.i2_zonename=='" + hostvars[item].i2_zonename + "'].key") | sort }} + {%- else -%} + {{ [ inventory_hostname ] }} + {%- endif -%} when: hostvars[item].i2_peer_nodes is not defined or hostvars[item].i2_peer_nodes != peers -- name: Determine parent and child nodes +- name: Determine parent nodes set_fact: cacheable: "{{ i2_bootstrap_cacheable }}" - i2_child_nodes: "{{ childs }}" i2_parent_nodes: "{{ parents }}" run_once: True delegate_facts: True delegate_to: "{{ item }}" - loop: >- - {{ groups[i2_master_group]|default([]) - + groups[i2_satellite_group]|default([]) - + groups[i2_agent_group]|default([]) }} + loop: "{{ groups['all' ] }}" vars: - childs: >- - {{ hostvars | dict2items - | json_query("[?value.i2_parent_zone=='" + hostvars[item].i2_zonename + "'].key") - | difference(hostvars[item].i2_peer_nodes) - | sort }} parents: >- {%- if hostvars[item].i2_parent_zone is defined -%} {{ hostvars | dict2items @@ -164,10 +155,28 @@ | sort }} {%- else %}[]{% endif -%} - when: hostvars[item].i2_child_nodes is not defined or - hostvars[item].i2_parent_nodes is not defined or - hostvars[item].i2_child_nodes != childs or - hostvars[item].i2_parent_nodes != parents + when: + - hostvars[item].i2_parent_nodes is not defined or hostvars[item].i2_parent_nodes != parents + +- name: Determine child nodes + set_fact: + cacheable: "{{ i2_bootstrap_cacheable }}" + i2_child_nodes: "{{ childs }}" + run_once: True + delegate_facts: True + delegate_to: "{{ item }}" + loop: >- + {{ groups[i2_master_group]|default([]) + + groups[i2_satellite_group]|default([]) }} + vars: + childs: >- + {{ hostvars | dict2items + | json_query("[?value.i2_parent_zone=='" + hostvars[item].i2_zonename + "'].key") + | difference(hostvars[item].i2_peer_nodes) + | sort }} + when: + - hostvars[item].i2_zonename is defined + - hostvars[item].i2_child_nodes is not defined or hostvars[item].i2_child_nodes != childs - name: Determine satellite zones set_fact: @@ -179,29 +188,23 @@ - name: Determine child zones set_fact: cacheable: "{{ i2_bootstrap_cacheable }}" - i2_child_zones: >- - {{ hostvars[item].i2_child_nodes | map('extract', hostvars, 'i2_zonename' ) - | unique - | sort }} - i2_child_satellite_zones: >- - {{ hostvars[item].i2_child_nodes | map('extract', hostvars, 'i2_zonename' ) - | unique - | intersect(i2_satellite_zones) - | sort }} + i2_child_zones: "{{ child_zones }}" + i2_child_satellite_zones: "{{ child_satellite_zones }}" run_once: True delegate_facts: True delegate_to: "{{ item }}" loop: >- {{ groups[i2_master_group]|default([]) - + groups[i2_satellite_group]|default([]) - + groups[i2_agent_group]|default([]) }} + + groups[i2_satellite_group]|default([]) }} vars: child_zones: >- {{ hostvars[item].i2_child_nodes | map('extract', hostvars, 'i2_zonename' ) + | select('string') | unique | sort }} child_satellite_zones: >- {{ hostvars[item].i2_child_nodes | map('extract', hostvars, 'i2_zonename' ) + | select('string') | unique | intersect(i2_satellite_zones) | sort }} diff --git a/tasks/icinga2-objects.yml b/tasks/icinga2-objects.yml index 01cba33..0c017ce 100644 --- a/tasks/icinga2-objects.yml +++ b/tasks/icinga2-objects.yml @@ -133,17 +133,17 @@ become: yes template: src: host_template.conf.j2 - dest: "{{ i2_zones_dir }}/{{ - hostvars[item]['i2_parent_zone']|default(hostvars[item]['i2_zonename']) + dest: "{{ i2_zones_dir }}/{{ zone }}/hosts/{{ hostvars[item]['i2_hostname'] }}.conf" owner: "{{ i2_user }}" group: "{{ i2_group }}" mode: 0644 loop: "{{ groups['all'] }}" register: managed_zone_hosts + vars: + zone: "{{ hostvars[item]['i2_parent_zone'] | default(hostvars[item]['i2_zonename'] | default( None )) }}" when: - - hostvars[item].i2_parent_zone is defined or - (hostvars[item].i2_master is defined and hostvars[item].i2_master) + - zone is defined - hostvars[item].i2_hostname is defined notify: - reload icinga2 diff --git a/templates/host_template.conf.j2 b/templates/host_template.conf.j2 index 90eb821..5ae5e8e 100644 --- a/templates/host_template.conf.j2 +++ b/templates/host_template.conf.j2 @@ -5,7 +5,7 @@ # When the item is an agent include the Endpoint and Zone for the this agent # in the generates host configuration. #} -{% if item not in groups[i2_master_group]|union(groups[i2_satellite_group]) %} +{% if item in groups[i2_agent_group] %} {% set item_parent = hostvars[item].i2_parent_nodes[0] %} {{ definitions.endpoint(item, item_parent, hostvars) }} @@ -16,11 +16,13 @@ object Host "{{ hostvars[item].i2_hostname }}" { import "{{ hostvars[item].get('i2_host_template', 'generic-host') }}" address = "{{ hostvars[item].i2_address }}" -{% if item not in groups[i2_master_group] and item not in groups[i2_satellite_group] %} +{% if item in groups[i2_agent_group] %} vars.agent_endpoint = name // Follows the convention that host name == endpoint name {% endif %} +{% if hostvars[item].ansible_system is defined %} vars.os = "{{ hostvars[item].ansible_system }}" vars.os_family = "{{ hostvars[item].ansible_os_family }}" +{% endif %} {% if hostvars[item].i2_child_satellite_zones is defined and hostvars[item].i2_child_satellite_zones|length > 0 %} From 5c7b72cfc8f70213fa3a543e838c5f4410cd1d20 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Wed, 7 Apr 2021 15:23:31 +0200 Subject: [PATCH 32/34] Another fix to handle hosts in the all group --- tasks/icinga2-bootstrap.yml | 8 +++++++- templates/zones.conf.j2 | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tasks/icinga2-bootstrap.yml b/tasks/icinga2-bootstrap.yml index 9c08494..555622f 100644 --- a/tasks/icinga2-bootstrap.yml +++ b/tasks/icinga2-bootstrap.yml @@ -162,6 +162,7 @@ set_fact: cacheable: "{{ i2_bootstrap_cacheable }}" i2_child_nodes: "{{ childs }}" + i2_child_satellite_nodes: "{{ satellites }}" run_once: True delegate_facts: True delegate_to: "{{ item }}" @@ -174,9 +175,14 @@ | json_query("[?value.i2_parent_zone=='" + hostvars[item].i2_zonename + "'].key") | difference(hostvars[item].i2_peer_nodes) | sort }} + satellites: >- + {{ childs | intersect(groups[i2_satellite_group]|default([])) }} when: - hostvars[item].i2_zonename is defined - - hostvars[item].i2_child_nodes is not defined or hostvars[item].i2_child_nodes != childs + - hostvars[item].i2_child_nodes is not defined or + hostvars[item].i2_child_nodes != childs or + hostvars[item].i2_child_satellite_nodes is not defined or + hostvars[item].i2_child_satellite_nodes != satellites - name: Determine satellite zones set_fact: diff --git a/templates/zones.conf.j2 b/templates/zones.conf.j2 index 6519391..5b2ca9e 100644 --- a/templates/zones.conf.j2 +++ b/templates/zones.conf.j2 @@ -46,7 +46,7 @@ object Zone "director-global" { {# # Create Endpoints for all the nodes in child Zones #} -{% for item in i2_child_nodes -%} +{% for item in i2_child_satellite_nodes -%} {{ definitions.endpoint(item, inventory_hostname, hostvars) }} {% endfor -%} @@ -67,7 +67,7 @@ object Zone "director-global" { {# # The child Zones of the current node #} -{% for child_zone in i2_child_zones -%} +{% for child_zone in i2_child_satellite_zones -%} {{ definitions.zone(child_zone, i2_zonename, hostvars) }} {% endfor -%} From 31dd9be8b9e8c228b13c2d6ec6c73a762c5ccdd7 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Mon, 14 Feb 2022 15:47:32 +0100 Subject: [PATCH 33/34] icinga_ido should use latin1. See discussion https://community.icinga.com/t/umlauts-and-special-characters-in-icingaweb2/6415/6 --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 46b2883..322c12c 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -143,7 +143,7 @@ i2_webui_default_config: dbname: "{{ i2_ido_params.database }}" username: "{{ i2_ido_params.user }}" password: "{{ i2_ido_params.password }}" - charset: utf8 + charset: latin1 use_ssl: "0" roles: file: roles.ini From b70be1fcfb6ef3f4795110008dadbc2e0d3885c3 Mon Sep 17 00:00:00 2001 From: Arjan Oosting Date: Mon, 29 Aug 2022 15:21:27 +0200 Subject: [PATCH 34/34] Only install apt-transport-https when we are on an apt version which doesn't support https out of the box --- tasks/icinga2-Debian.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tasks/icinga2-Debian.yml b/tasks/icinga2-Debian.yml index fedaba5..dd3b6c4 100644 --- a/tasks/icinga2-Debian.yml +++ b/tasks/icinga2-Debian.yml @@ -1,10 +1,15 @@ --- +- name: Debian - Determine apt version + package_facts: + - name: Debian - Install apt-transport-https become: yes apt: name: apt-transport-https state: present - when: i2_manage_repository + when: + - i2_manage_repository + - ansible_facts.packages['apt'] | map(attribute='version') | first is version('1.5', '<') - name: Debian - Add Icinga 2 repository key become: yes