mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-03-22 13:19:13 +00:00
* 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>
127 lines
3.9 KiB
Python
127 lines
3.9 KiB
Python
# 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
|