mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-15 09:30:50 -07:00
Add downtime module (#1437)
* Add downtime module * review + tests * importorskip + review * py36 * make py3.6+ dep explicit
This commit is contained in:
parent
496be77a2b
commit
19a5975181
4 changed files with 536 additions and 0 deletions
1
plugins/modules/datadog_downtime.py
Symbolic link
1
plugins/modules/datadog_downtime.py
Symbolic link
|
@ -0,0 +1 @@
|
|||
./monitoring/datadog/datadog_downtime.py
|
308
plugins/modules/monitoring/datadog/datadog_downtime.py
Normal file
308
plugins/modules/monitoring/datadog/datadog_downtime.py
Normal file
|
@ -0,0 +1,308 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2020, Datadog, Inc
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = """
|
||||
---
|
||||
module: datadog_downtime
|
||||
short_description: Manages Datadog downtimes
|
||||
version_added: 2.0.0
|
||||
description:
|
||||
- Manages downtimes within Datadog.
|
||||
- Options as described on U(https://docs.datadoghq.com/api/v1/downtimes/s).
|
||||
author:
|
||||
- Datadog (@Datadog)
|
||||
requirements:
|
||||
- datadog-api-client
|
||||
- Python 3.6+
|
||||
options:
|
||||
api_key:
|
||||
description:
|
||||
- Your Datadog API key.
|
||||
required: true
|
||||
type: str
|
||||
api_host:
|
||||
description:
|
||||
- The URL to the Datadog API.
|
||||
- This value can also be set with the C(DATADOG_HOST) environment variable.
|
||||
required: false
|
||||
default: https://api.datadoghq.com
|
||||
type: str
|
||||
app_key:
|
||||
description:
|
||||
- Your Datadog app key.
|
||||
required: true
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- The designated state of the downtime.
|
||||
required: false
|
||||
choices: ["present", "absent"]
|
||||
default: present
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- The identifier of the downtime.
|
||||
- If empty, a new downtime gets created, otherwise it is either updated or deleted depending of the C(state).
|
||||
- To keep your playbook idempotent, you should save the identifier in a file and read it in a lookup.
|
||||
type: int
|
||||
monitor_tags:
|
||||
description:
|
||||
- A list of monitor tags to which the downtime applies.
|
||||
- The resulting downtime applies to monitors that match ALL provided monitor tags.
|
||||
type: list
|
||||
elements: str
|
||||
scope:
|
||||
description:
|
||||
- A list of scopes to which the downtime applies.
|
||||
- The resulting downtime applies to sources that matches ALL provided scopes.
|
||||
type: list
|
||||
elements: str
|
||||
monitor_id:
|
||||
description:
|
||||
- The ID of the monitor to mute. If not provided, the downtime applies to all monitors.
|
||||
type: int
|
||||
downtime_message:
|
||||
description:
|
||||
- A message to include with notifications for this downtime.
|
||||
- Email notifications can be sent to specific users by using the same "@username" notation as events.
|
||||
type: str
|
||||
start:
|
||||
type: int
|
||||
description:
|
||||
- POSIX timestamp to start the downtime. If not provided, the downtime starts the moment it is created.
|
||||
end:
|
||||
type: int
|
||||
description:
|
||||
- POSIX timestamp to end the downtime. If not provided, the downtime is in effect until you cancel it.
|
||||
timezone:
|
||||
description:
|
||||
- The timezone for the downtime.
|
||||
type: str
|
||||
rrule:
|
||||
description:
|
||||
- The C(RRULE) standard for defining recurring events.
|
||||
- For example, to have a recurring event on the first day of each month,
|
||||
select a type of rrule and set the C(FREQ) to C(MONTHLY) and C(BYMONTHDAY) to C(1).
|
||||
- Most common rrule options from the iCalendar Spec are supported.
|
||||
- Attributes specifying the duration in C(RRULE) are not supported (e.g. C(DTSTART), C(DTEND), C(DURATION)).
|
||||
type: str
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Create a downtime
|
||||
register: downtime_var
|
||||
community.general.datadog_downtime:
|
||||
state: present
|
||||
monitor_tags:
|
||||
- "foo:bar"
|
||||
downtime_message: "Downtime for foo:bar"
|
||||
scope: "test"
|
||||
api_key: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
app_key: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
# Lookup the id in the file and ignore errors if the file doesn't exits, so downtime gets created
|
||||
id: "{{ lookup('file', inventory_hostname ~ '_downtime_id.txt', errors='ignore') }}"
|
||||
- name: Save downtime id to file for later updates and idempotence
|
||||
delegate_to: localhost
|
||||
copy:
|
||||
content: "{{ downtime.downtime.id }}"
|
||||
dest: "{{ inventory_hostname ~ '_downtime_id.txt' }}"
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
# Returns the downtime JSON dictionary from the API response under the C(downtime) key.
|
||||
# See https://docs.datadoghq.com/api/v1/downtimes/#schedule-a-downtime for more details.
|
||||
downtime:
|
||||
description: The downtime returned by the API.
|
||||
type: dict
|
||||
returned: always
|
||||
sample: {
|
||||
"active": true,
|
||||
"canceled": null,
|
||||
"creator_id": 1445416,
|
||||
"disabled": false,
|
||||
"downtime_type": 2,
|
||||
"end": null,
|
||||
"id": 1055751000,
|
||||
"message": "Downtime for foo:bar",
|
||||
"monitor_id": null,
|
||||
"monitor_tags": [
|
||||
"foo:bar"
|
||||
],
|
||||
"parent_id": null,
|
||||
"recurrence": null,
|
||||
"scope": [
|
||||
"test"
|
||||
],
|
||||
"start": 1607015009,
|
||||
"timezone": "UTC",
|
||||
"updater_id": null
|
||||
}
|
||||
"""
|
||||
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
# Import Datadog
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
|
||||
DATADOG_IMP_ERR = None
|
||||
HAS_DATADOG = True
|
||||
try:
|
||||
from datadog_api_client.v1 import Configuration, ApiClient, ApiException
|
||||
from datadog_api_client.v1.api.downtimes_api import DowntimesApi
|
||||
from datadog_api_client.v1.model.downtime import Downtime
|
||||
from datadog_api_client.v1.model.downtime_recurrence import DowntimeRecurrence
|
||||
except ImportError:
|
||||
DATADOG_IMP_ERR = traceback.format_exc()
|
||||
HAS_DATADOG = False
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
api_key=dict(required=True, no_log=True),
|
||||
api_host=dict(required=False, default="https://api.datadoghq.com"),
|
||||
app_key=dict(required=True, no_log=True),
|
||||
state=dict(required=False, choices=["present", "absent"], default="present"),
|
||||
monitor_tags=dict(required=False, type="list", elements="str"),
|
||||
scope=dict(required=False, type="list", elements="str"),
|
||||
monitor_id=dict(required=False, type="int"),
|
||||
downtime_message=dict(required=False, no_log=True),
|
||||
start=dict(required=False, type="int"),
|
||||
end=dict(required=False, type="int"),
|
||||
timezone=dict(required=False, type="str"),
|
||||
rrule=dict(required=False, type="str"),
|
||||
id=dict(required=False, type="int"),
|
||||
)
|
||||
)
|
||||
|
||||
# Prepare Datadog
|
||||
if not HAS_DATADOG:
|
||||
module.fail_json(msg=missing_required_lib("datadog-api-client"), exception=DATADOG_IMP_ERR)
|
||||
|
||||
configuration = Configuration(
|
||||
host=module.params["api_host"],
|
||||
api_key={
|
||||
"apiKeyAuth": module.params["api_key"],
|
||||
"appKeyAuth": module.params["app_key"]
|
||||
}
|
||||
)
|
||||
with ApiClient(configuration) as api_client:
|
||||
api_client.user_agent = "ansible_collection/community_general (module_name datadog_downtime) {0}".format(
|
||||
api_client.user_agent
|
||||
)
|
||||
api_instance = DowntimesApi(api_client)
|
||||
|
||||
# Validate api and app keys
|
||||
try:
|
||||
api_instance.list_downtimes(current_only=True)
|
||||
except ApiException as e:
|
||||
module.fail_json(msg="Failed to connect Datadog server using given app_key and api_key: {0}".format(e))
|
||||
|
||||
if module.params["state"] == "present":
|
||||
schedule_downtime(module, api_client)
|
||||
elif module.params["state"] == "absent":
|
||||
cancel_downtime(module, api_client)
|
||||
|
||||
|
||||
def _get_downtime(module, api_client):
|
||||
api = DowntimesApi(api_client)
|
||||
downtime = None
|
||||
if module.params["id"]:
|
||||
try:
|
||||
downtime = api.get_downtime(module.params["id"])
|
||||
except ApiException as e:
|
||||
module.fail_json(msg="Failed to retrieve downtime with id {0}: {1}".format(module.params["id"], e))
|
||||
return downtime
|
||||
|
||||
|
||||
def build_downtime(module):
|
||||
downtime = Downtime()
|
||||
if module.params["monitor_tags"]:
|
||||
downtime.monitor_tags = module.params["monitor_tags"]
|
||||
if module.params["scope"]:
|
||||
downtime.scope = module.params["scope"]
|
||||
if module.params["monitor_id"]:
|
||||
downtime.monitor_id = module.params["monitor_id"]
|
||||
if module.params["downtime_message"]:
|
||||
downtime.message = module.params["downtime_message"]
|
||||
if module.params["start"]:
|
||||
downtime.start = module.params["start"]
|
||||
if module.params["end"]:
|
||||
downtime.end = module.params["end"]
|
||||
if module.params["timezone"]:
|
||||
downtime.timezone = module.params["timezone"]
|
||||
if module.params["rrule"]:
|
||||
downtime.recurrence = DowntimeRecurrence(
|
||||
rrule=module.params["rrule"]
|
||||
)
|
||||
return downtime
|
||||
|
||||
|
||||
def _post_downtime(module, api_client):
|
||||
api = DowntimesApi(api_client)
|
||||
downtime = build_downtime(module)
|
||||
try:
|
||||
resp = api.create_downtime(downtime)
|
||||
module.params["id"] = resp.id
|
||||
module.exit_json(changed=True, downtime=resp.to_dict())
|
||||
except ApiException as e:
|
||||
module.fail_json(msg="Failed to create downtime: {0}".format(e))
|
||||
|
||||
|
||||
def _equal_dicts(a, b, ignore_keys):
|
||||
ka = set(a).difference(ignore_keys)
|
||||
kb = set(b).difference(ignore_keys)
|
||||
return ka == kb and all(a[k] == b[k] for k in ka)
|
||||
|
||||
|
||||
def _update_downtime(module, current_downtime, api_client):
|
||||
api = DowntimesApi(api_client)
|
||||
downtime = build_downtime(module)
|
||||
try:
|
||||
if current_downtime.disabled:
|
||||
resp = api.create_downtime(downtime)
|
||||
else:
|
||||
resp = api.update_downtime(module.params["id"], downtime)
|
||||
if _equal_dicts(
|
||||
resp.to_dict(),
|
||||
current_downtime.to_dict(),
|
||||
["active", "creator_id", "updater_id"]
|
||||
):
|
||||
module.exit_json(changed=False, downtime=resp.to_dict())
|
||||
else:
|
||||
module.exit_json(changed=True, downtime=resp.to_dict())
|
||||
except ApiException as e:
|
||||
module.fail_json(msg="Failed to update downtime: {0}".format(e))
|
||||
|
||||
|
||||
def schedule_downtime(module, api_client):
|
||||
downtime = _get_downtime(module, api_client)
|
||||
if downtime is None:
|
||||
_post_downtime(module, api_client)
|
||||
else:
|
||||
_update_downtime(module, downtime, api_client)
|
||||
|
||||
|
||||
def cancel_downtime(module, api_client):
|
||||
downtime = _get_downtime(module, api_client)
|
||||
api = DowntimesApi(api_client)
|
||||
if downtime is None:
|
||||
module.exit_json(changed=False)
|
||||
try:
|
||||
api.cancel_downtime(downtime["id"])
|
||||
except ApiException as e:
|
||||
module.fail_json(msg="Failed to create downtime: {0}".format(e))
|
||||
|
||||
module.exit_json(changed=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue