1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-03-22 05:09:12 +00:00

New module icinga2_downtime (#11462)

* feat: Icinga 2 downtime module added allowing to schedule and remove downtimes through its REST API.

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* ensure compatibility with ModuleTestCase

feat: errors raised from MH now contain the changed flag
ref: move module exit out of the decorated run method

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* revised module

ref: module refactored using StateModuleHelper now
ref: suggested changes by reviewer added

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* revert change regarding changed flag in MH

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* refactoring and set changed flag explicitly on error

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* Check whether there was a state change on module failure removed.

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* ref: test cases migrated to the new feature that allows passing through exceptions

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* Update plugins/module_utils/icinga2.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/module_utils/icinga2.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/modules/icinga2_downtime.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* ref: make module helper private

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* fix: ensure that all non-null values are added to the request otherwise a `false` value is dropped

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* ref: module description extended with the note that check mode is not supported

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* Update plugins/modules/icinga2_downtime.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* fix: documentation updated

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* ref: documentation updated
ref: doc fragment added

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* Update plugins/doc_fragments/icinga2_api.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* ref: doc fragment renamed to `_icinga2_api.py`

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* ref: maintainer to doc fragment in BOTMETA.yml added

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>

* Update plugins/modules/icinga2_downtime.py

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>

* Update plugins/modules/icinga2_downtime.py

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>

* Update plugins/modules/icinga2_downtime.py

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>

---------

Signed-off-by: Fiehe Christoph  <c.fiehe@eurodata.de>
Co-authored-by: Fiehe Christoph <c.fiehe@eurodata.de>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
This commit is contained in:
Christoph Fiehe 2026-02-23 05:38:54 +01:00 committed by GitHub
parent cb91ff424f
commit ce7cb4e914
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 696 additions and 0 deletions

View file

@ -0,0 +1,127 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2026 Christoph Fiehe <christoph.fiehe@gmail.com>
# Note that this module util is **PRIVATE** to the collection. It can have breaking changes at any time.
# Do not use this from other collections or standalone plugins/modules!
from __future__ import annotations
import json
import typing as t
from ansible.module_utils.common.text.converters import to_bytes
from ansible.module_utils.urls import fetch_url, url_argument_spec
if t.TYPE_CHECKING:
from http.client import HTTPResponse
from urllib.error import HTTPError
from ansible.module_utils.basic import AnsibleModule
class Icinga2Client:
def __init__(
self,
module: AnsibleModule,
url: str,
ca_path: str | None = None,
timeout: int | float | None = None,
) -> None:
self.module = module
self.url = url.rstrip("/")
self.ca_path = ca_path
self.timeout = timeout
self.actions = Actions(client=self)
def send_request(
self, method: str, path: str, data: dict[str, t.Any] | None = None
) -> tuple[HTTPResponse | HTTPError, dict[str, t.Any]]:
url = f"{self.url}/{path}"
headers = {
"X-HTTP-Method-Override": method.upper(),
"Accept": "application/json",
}
return fetch_url(
module=self.module,
url=url,
ca_path=self.ca_path,
data=to_bytes(json.dumps(data)),
headers=headers,
timeout=self.timeout,
)
class Actions:
base_path = "v1/actions"
def __init__(self, client: Icinga2Client) -> None:
self.client = client
def schedule_downtime(
self,
object_type: str,
filter: str,
author: str,
comment: str,
start_time: int,
end_time: int,
duration: int,
filter_vars: dict[str, t.Any] | None = None,
fixed: bool | None = None,
all_services: bool | None = None,
trigger_name: str | None = None,
child_options: str | None = None,
) -> tuple[HTTPResponse | HTTPError, dict[str, t.Any]]:
path = f"{self.base_path}/schedule-downtime"
data: dict[str, t.Any] = {
"type": object_type,
"filter": filter,
"author": author,
"comment": comment,
"start_time": start_time,
"end_time": end_time,
"duration": duration,
}
if filter_vars is not None:
data["filter_vars"] = filter_vars
if fixed is not None:
data["fixed"] = fixed
if all_services is not None:
data["all_services"] = all_services
if trigger_name is not None:
data["trigger_name"] = trigger_name
if child_options is not None:
data["child_options"] = child_options
return self.client.send_request(method="POST", path=path, data=data)
def remove_downtime(
self,
object_type: str,
name: str | None = None,
filter: str | None = None,
filter_vars: dict[str, t.Any] | None = None,
) -> tuple[HTTPResponse | HTTPError, dict[str, t.Any]]:
path = f"{self.base_path}/remove-downtime"
data: dict[str, t.Any] = {"type": object_type}
if name is not None:
data[object_type.lower()] = name
if filter is not None:
data["filter"] = filter
if filter_vars is not None:
data["filter_vars"] = filter_vars
return self.client.send_request(method="POST", path=path, data=data)
def icinga2_argument_spec() -> dict[str, t.Any]:
argument_spec = url_argument_spec()
argument_spec.update(
url=dict(type="str", required=True),
ca_path=dict(type="path"),
timeout=dict(type="int", default=10),
)
return argument_spec