diff --git a/README.md b/README.md index 21ce4d90..b1404c93 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Click on the name of a plugin or module to view that content's documentation: - [grafana_datasource](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_datasource_module.html) - [grafana_folder](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_folder_module.html) - [grafana_notification_channel](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_notification_channel_module.html) + - [grafana_contact_point](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_contact_point_module.html) - [grafana_organization](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_organization_module.html) - [grafana_organization_user](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_organization_user_module.html) - [grafana_plugin](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_plugin_module.html) diff --git a/changelogs/fragments/352-module-contact-point.yml b/changelogs/fragments/352-module-contact-point.yml new file mode 100644 index 00000000..14915de6 --- /dev/null +++ b/changelogs/fragments/352-module-contact-point.yml @@ -0,0 +1,5 @@ +minor_changes: + - Add `grafana_contact_point` module + - Add support of `grafana_contact_point` in grafana role +trivial: + - Add tests for `grafana_contact_point` module diff --git a/meta/runtime.yml b/meta/runtime.yml index d29f1dda..71243ba1 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -6,6 +6,7 @@ action_groups: - grafana_datasource - grafana_folder - grafana_notification_channel + - grafana_contact_point - grafana_organization - grafana_organization_user - grafana_plugin diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py new file mode 100644 index 00000000..88a7a0c1 --- /dev/null +++ b/plugins/modules/grafana_contact_point.py @@ -0,0 +1,1354 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = """ +--- +module: grafana_contact_point +author: + - Moritz Pötschk (@nemental) +version_added: "1.9.0" +short_description: Manage Grafana Contact Points +description: + - Create/Update/Delete Grafana Contact Points via API. +options: + disable_resolve_message: + description: + - Disables the resolve message. + type: bool + default: false + include_image: + description: + - Whether to include an image in the notification. + type: bool + default: false + name: + description: + - The name of the contact point. + - Required when C(state) is C(present). + type: str + org_id: + description: + - The organization ID. + type: int + default: 1 + org_name: + description: + - The name of the organization. + type: str + provisioning: + description: + - Indicates if provisioning is enabled. + type: bool + default: true + state: + description: + - Status of the contact point. + type: str + default: present + choices: + - present + - absent + type: + description: + - The type of the contact point. + - Required when C(state) is C(present). + type: str + choices: + - alertmanager + - dingding + - discord + - email + - googlechat + - kafka + - line + - opsgenie + - pagerduty + - pushover + - sensugo + - slack + - teams + - telegram + - threema + - victorops + - webex + - webhook + - wecom + uid: + description: + - The unique ID of the contact point. + - Normally the uid is generated randomly, but it is required for handling the contact point via API. + type: str + required: true + alertmanager_password: + description: + - Password for accessing Alertmanager. + type: str + alertmanager_url: + description: + - URL for accessing Alertmanager. + - Required when C(type) is C(alertmanager). + type: str + alertmanager_username: + description: + - Username for accessing Alertmanager. + type: str + dingding_message: + description: + - The message to send via DingDing. + type: str + dingding_message_type: + description: + - The type of message to send via DingDing. + type: str + dingding_title: + description: + - The title of the DingDing message. + type: str + dingding_url: + description: + - The URL for DingDing webhook. + - Required when C(type) is C(dingding). + type: str + discord_avatar_url: + description: + - The avatar URL for Discord messages. + type: str + discord_message: + description: + - The message to send via Discord. + type: str + discord_title: + description: + - The title of the Discord message. + type: str + discord_url: + description: + - The URL for Discord webhook. + - Required when C(type) is C(discord). + type: str + discord_use_username: + description: + - Whether to use a custom username in Discord. + type: bool + default: false + email_addresses: + description: + - List of email addresses to send the message to. + - Required when C(type) is C(email). + type: list + elements: str + email_message: + description: + - The content of the email message. + type: str + email_single: + description: + - Whether to send a single email or individual emails. + type: bool + default: false + email_subject: + description: + - The subject of the email. + type: str + googlechat_url: + description: + - The URL for Google Chat webhook. + - Required when C(type) is C(webhook). + type: str + googlechat_message: + description: + - The message to send via Google Chat. + type: str + googlechat_title: + description: + - The title of the Google Chat message. + type: str + kafka_api_version: + description: + - The API version for Kafka. + type: str + default: v2 + kafka_cluster_id: + description: + - The cluster ID for Kafka. + type: str + kafka_description: + description: + - The description for the Kafka configuration. + type: str + kafka_details: + description: + - Additional details for Kafka. + type: str + kafka_password: + description: + - Password for accessing Kafka. + type: str + kafka_rest_proxy_url: + description: + - URL for Kafka REST Proxy. + - Required when C(type) is C(kafka). + type: str + kafka_topic: + description: + - Kafka topic to publish to. + - Required when C(type) is C(kafka). + type: str + kafka_username: + description: + - Username for accessing Kafka. + type: str + line_description: + description: + - Description for the Line message. + type: str + line_title: + description: + - Title of the Line message. + type: str + line_token: + description: + - Access token for Line. + - Required when C(type) is C(line). + type: str + opsgenie_api_key: + description: + - API key for OpsGenie. + - Required when C(type) is C(opsgenie). + type: str + opsgenie_auto_close: + description: + - Whether to enable auto-closing of alerts in OpsGenie. + type: bool + opsgenie_description: + description: + - Description of the OpsGenie alert. + type: str + opsgenie_message: + description: + - Message to send via OpsGenie. + type: str + opsgenie_override_priority: + description: + - Whether to override the priority in OpsGenie. + type: bool + opsgenie_responders: + description: + - List of responders for OpsGenie alerts. + type: list + elements: dict + opsgenie_send_tags_as: + description: + - Format for sending tags in OpsGenie. + type: str + opsgenie_url: + description: + - URL for OpsGenie webhook. + - Required when C(type) is C(pagerduty). + type: str + pagerduty_class: + description: + - Class of the PagerDuty alert. + type: str + pagerduty_client: + description: + - Client identifier for PagerDuty. + type: str + pagerduty_client_url: + description: + - Client URL for PagerDuty. + type: str + pagerduty_component: + description: + - Component involved in the PagerDuty alert. + type: str + pagerduty_details: + description: + - List of additional details for PagerDuty. + type: list + elements: dict + pagerduty_group: + description: + - Group associated with the PagerDuty alert. + type: str + pagerduty_integration_key: + description: + - Integration key for PagerDuty. + - Required when C(type) is C(pagerduty). + type: str + pagerduty_severity: + description: + - Severity level of the PagerDuty alert. + type: str + choices: + - critical + - error + - warning + - info + pagerduty_source: + description: + - Source of the PagerDuty alert. + type: str + pagerduty_summary: + description: + - Summary of the PagerDuty alert. + type: str + pushover_api_token: + description: + - API token for Pushover. + - Required when C(type) is C(pushover). + type: str + pushover_devices: + description: + - List of devices for Pushover notifications. + type: list + elements: str + pushover_expire: + description: + - Expiration time for Pushover notifications. + type: int + pushover_message: + description: + - Message to send via Pushover. + type: str + pushover_ok_priority: + description: + - Priority for OK messages in Pushover. + type: int + pushover_ok_sound: + description: + - Sound for OK messages in Pushover. + type: str + pushover_priority: + description: + - Priority for Pushover messages. + type: int + pushover_retry: + description: + - Retry interval for Pushover messages. + type: int + pushover_sound: + description: + - Sound for Pushover notifications. + type: str + pushover_title: + description: + - Title of the Pushover message. + type: str + pushover_upload_image: + description: + - Whether to upload an image with Pushover notification. + type: bool + default: true + pushover_user_key: + description: + - User key for Pushover. + - Required when C(type) is C(pushover). + type: str + sensugo_api_key: + description: + - API key for Sensu Go. + - Required when C(type) is C(pushover). + type: str + sensugo_url: + description: + - URL for Sensu Go. + - Required when C(type) is C(sensugo). + type: str + sensugo_check: + description: + - Check name for Sensu Go. + type: str + sensugo_entity: + description: + - Entity name for Sensu Go. + type: str + sensugo_handler: + description: + - Handler for Sensu Go. + type: str + sensugo_message: + description: + - Message to send via Sensu Go. + type: str + sensugo_namespace: + description: + - Namespace for Sensu Go. + type: str + slack_endpoint_url: + description: + - Endpoint URL for Slack webhook. + type: str + slack_icon_emoji: + description: + - Icon emoji for Slack messages. + type: str + slack_icon_url: + description: + - Icon URL for Slack messages. + type: str + slack_mention_channel: + description: + - Channel mention for Slack messages. + type: str + choices: + - here + - channel + slack_mention_groups: + description: + - List of groups to mention in Slack messages. + type: list + elements: str + slack_mention_users: + description: + - List of users to mention in Slack messages. + type: list + elements: str + slack_recipient: + description: + - Recipient for Slack messages. + - Required when C(type) is C(slack). + type: str + slack_text: + description: + - Text content for Slack messages. + type: str + slack_title: + description: + - Title of the Slack message. + type: str + slack_token: + description: + - Token for Slack authentication. + - Required when C(type) is C(slack). + type: str + slack_url: + description: + - URL for Slack webhook. + - Required when C(type) is C(slack). + type: str + slack_username: + description: + - Username to use in Slack messages. + type: str + teams_message: + description: + - Message to send via Microsoft Teams. + type: str + teams_section_title: + description: + - Section title for Microsoft Teams messages. + type: str + teams_title: + description: + - Title of the Microsoft Teams message. + type: str + teams_url: + description: + - URL for Microsoft Teams webhook. + - Required when C(type) is C(teams). + type: str + telegram_chat_id: + description: + - Chat ID for Telegram. + - Required when C(type) is C(telegram). + type: str + telegram_disable_notifications: + description: + - Whether to disable notifications for Telegram messages. + type: bool + telegram_message: + description: + - Message to send via Telegram. + type: str + telegram_parse_mode: + description: + - Parse mode for Telegram messages. + type: str + telegram_protect_content: + description: + - Whether to protect content in Telegram messages. + type: bool + telegram_token: + description: + - Token for Telegram authentication. + - Required when C(type) is C(telegram). + type: str + telegram_web_page_view: + description: + - Whether to enable web page preview in Telegram messages. + type: bool + threema_api_secret: + description: + - API secret for Threema. + - Required when C(type) is C(threema). + type: str + threema_description: + description: + - Description for Threema messages. + type: str + threema_gateway_id: + description: + - Gateway ID for Threema. + - Required when C(type) is C(threema). + type: str + threema_recipient_id: + description: + - Recipient ID for Threema messages. + - Required when C(type) is C(threema). + type: str + threema_title: + description: + - Title of the Threema message. + type: str + victorops_description: + description: + - Description for VictorOps messages. + type: str + victorops_message_type: + description: + - Message type for VictorOps. + type: str + choices: + - CRITICAL + - RECOVERY + victorops_title: + description: + - Title of the VictorOps message. + type: str + victorops_url: + description: + - URL for VictorOps webhook. + - Required when C(type) is C(victorops). + type: str + webex_api_url: + description: + - API URL for Webex. + type: str + webex_message: + description: + - Message to send via Webex. + type: str + webex_room_id: + description: + - Room ID for Webex messages. + - Required when C(type) is C(webex). + type: str + webex_token: + description: + - Token for Webex authentication. + - Required when C(type) is C(webex). + type: str + webhook_authorization_credentials: + description: + - Authorization credentials for webhook. + type: str + webhook_authorization_scheme: + description: + - Authorization scheme for webhook. + type: str + webhook_http_method: + description: + - HTTP method for webhook. + type: str + choices: + - POST + - PUT + webhook_max_alerts: + description: + - Maximum number of alerts for webhook. + type: int + webhook_message: + description: + - Message to send via webhook. + type: str + webhook_password: + description: + - Password for webhook authentication. + type: str + webhook_title: + description: + - Title of the webhook message. + type: str + webhook_url: + description: + - URL for webhook. + - Required when C(type) is C(webhook). + type: str + webhook_username: + description: + - Username for webhook authentication. + type: str + wecom_agent_id: + description: + - Agent ID for WeCom. + - Required when C(type) is C(wecom). + type: str + wecom_corp_id: + description: + - Corporate ID for WeCom. + - Required when C(type) is C(wecom). + type: str + wecom_message: + description: + - Message to send via WeCom. + type: str + wecom_msg_type: + description: + - Message type for WeCom. + type: str + wecom_secret: + description: + - Secret for WeCom authentication. + - Required when C(type) is C(wecom). + type: str + wecom_title: + description: + - Title of the WeCom message. + type: str + wecom_to_user: + description: + - List of users to send the WeCom message to. + type: list + elements: str + wecom_url: + description: + - URL for WeCom webhook. + - Required when C(type) is C(wecom). + type: str +extends_documentation_fragment: + - community.grafana.basic_auth + - community.grafana.api_key +""" + + +EXAMPLES = """ +- name: Create email contact point + community.grafana.grafana_contact_point: + grafana_url: "{{ grafana_url }}" + grafana_user: "{{ grafana_username }}" + grafana_password: "{{ grafana_password }}" + uid: email + name: E-Mail + type: email + email_addresses: + - example@example.com + +- name: Delete email contact point + community.grafana.grafana_contact_point: + grafana_url: "{{ grafana_url }}" + grafana_user: "{{ grafana_username }}" + grafana_password: "{{ grafana_password }}" + uid: email + state: absent +""" + +RETURN = """ +contact_point: + description: Contact point created or updated by the module. + returned: success + type: complex + contains: + uid: + description: The uid of the contact point. + returned: success + type: str + sample: + - ddmyrs0f74t8hc + name: + description: The name of the contact point. + returned: success + type: str + sample: + - supportmail + type: + description: The type of the contact point. + returned: success + type: str + sample: + - email + disableResolveMessage: + description: Is the resolve message of the contact point disabled. + returned: success + type: bool + sample: + - false + settings: + description: The type specific settings of the contact point. + returned: success + type: dict + sample: + - addresses: "support@example.com" + singleEmail: false + secureFields: + description: The secure fields config of the contact point. + returned: success + type: dict +diff: + description: Difference between previous and updated contact point. + returned: changed + type: complex + contains: + before: + description: Previous contact point. + returned: changed + type: dict + sample: + - uid: ddmyrs0f74t8hc + name: supportmail + type: email + disableResolveMessage: false + settings: + addresses: support@example.com + singleEmail: false + secureFields: {} + after: + description: Current contact point. + returned: changed + type: dict + sample: + - uid: ddmyrs0f74t8hc + name: supportmail + type: email + disableResolveMessage: true + settings: + addresses: support123@example.com + singleEmail: false + secureFields: {} +""" + +import json + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.urls import fetch_url +from ansible.module_utils._text import to_text +from ansible_collections.community.grafana.plugins.module_utils.base import ( + grafana_argument_spec, + clean_url, +) +from ansible.module_utils.urls import basic_auth_header + + +class GrafanaAPIException(Exception): + pass + + +def grafana_contact_point_payload(data): + payload = { + "uid": data["uid"], + "name": data["name"], + "type": data["type"], + "disableResolveMessage": data["disable_resolve_message"], + "settings": {}, + } + + if data["type"] == "alertmanager": + payload["type"] = "prometheus-alertmanager" + + type_settings_map = { + "alertmanager": { + "basicAuthPassword": "alertmanager_password", + "url": "alertmanager_url", + "basicAuthUser": "alertmanager_username", + }, + "dingding": { + "message": "dingding_message", + "msgType": "dingding_message_type", + "title": "dingding_title", + "url": "dingding_url", + }, + "discord": { + "avatar_url": "discord_avatar_url", + "message": "discord_message", + "title": "discord_title", + "url": "discord_url", + "use_discord_username": "discord_use_username", + }, + "email": { + "addresses": "email_addresses", + "message": "email_message", + "singleEmail": "email_single", + "subject": "email_subject", + }, + "googlechat": { + "url": "googlechat_url", + "message": "googlechat_message", + "title": "googlechat_title", + }, + "kafka": { + "apiVersion": "kafka_api_version", + "kafkaClusterId": "kafka_cluster_id", + "description": "kafka_description", + "details": "kafka_details", + "password": "kafka_password", + "kafkaRestProxy": "kafka_rest_proxy_url", + "kafkaTopic": "kafka_topic", + "username": "kafka_username", + }, + "line": { + "description": "line_description", + "title": "line_title", + "token": "line_token", + }, + "opsgenie": { + "apiKey": "opsgenie_api_key", + "autoClose": "opsgenie_auto_close", + "description": "opsgenie_description", + "message": "opsgenie_message", + "overridePriority": "opsgenie_override_priority", + "responders": "opsgenie_responders", + "sendTagsAs": "opsgenie_send_tags_as", + "apiUrl": "opsgenie_url", + }, + "pagerduty": { + "class": "pagerduty_class", + "client": "pagerduty_client", + "client_url": "pagerduty_client_url", + "component": "pagerduty_component", + "details": "pagerduty_details", + "group": "pagerduty_group", + "integrationKey": "pagerduty_integration_key", + "severity": "pagerduty_severity", + "source": "pagerduty_source", + "summary": "pagerduty_summary", + }, + "pushover": { + "apiToken": "pushover_api_token", + "device": "pushover_devices", + "expire": "pushover_expire", + "message": "pushover_message", + "okPriority": "pushover_ok_priority", + "okSound": "pushover_ok_sound", + "priority": "pushover_priority", + "retry": "pushover_retry", + "sound": "pushover_sound", + "title": "pushover_title", + "uploadImage": "pushover_upload_image", + "userKey": "pushover_user_key", + }, + "sensugo": { + "apiKey": "sensugo_api_key", + "url": "sensugo_url", + "check": "sensugo_check", + "entity": "sensugo_entity", + "handler": "sensugo_handler", + "message": "sensugo_message", + "namespace": "sensugo_namespace", + }, + "slack": { + "endpointUrl": "slack_endpoint_url", + "icon_emoji": "slack_icon_emoji", + "icon_url": "slack_icon_url", + "mentionChannel": "slack_mention_channel", + "mentionGroups": "slack_mention_groups", + "mentionUsers": "slack_mention_users", + "recipient": "slack_recipient", + "text": "slack_text", + "title": "slack_title", + "token": "slack_token", + "url": "slack_url", + "username": "slack_username", + }, + "teams": { + "message": "teams_message", + "sectiontitle": "teams_section_title", + "title": "teams_title", + "url": "teams_url", + }, + "telegram": { + "chatid": "telegram_chat_id", + "disable_notification": "telegram_disable_notifications", + "message": "telegram_message", + "parse_mode": "telegram_parse_mode", + "protect_content": "telegram_protect_content", + "bottoken": "telegram_token", + "disable_web_page_preview": "telegram_web_page_view", + }, + "threema": { + "api_secret": "threema_api_secret", + "description": "threema_description", + "gateway_id": "threema_gateway_id", + "recipient_id": "threema_recipient_id", + "title": "threema_title", + }, + "victorops": { + "description": "victorops_description", + "messageType": "victorops_message_type", + "title": "victorops_title", + "url": "victorops_url", + }, + "webex": { + "api_url": "webex_api_url", + "message": "webex_message", + "room_id": "webex_room_id", + "bot_token": "webex_token", + }, + "webhook": { + "authorization_credentials": "webhook_authorization_credentials", + "authorization_scheme": "webhook_authorization_scheme", + "httpMethod": "webhook_http_method", + "maxAlerts": "webhook_max_alerts", + "message": "webhook_message", + "password": "webhook_password", + "title": "webhook_title", + "url": "webhook_url", + "username": "webhook_username", + }, + "wecom": { + "agent_id": "wecom_agent_id", + "corp_id": "wecom_corp_id", + "message": "wecom_message", + "msgtype": "wecom_msg_type", + "secret": "wecom_secret", + "title": "wecom_title", + "touser": "wecom_to_user", + "url": "wecom_url", + }, + } + + type_settings = type_settings_map.get(data["type"]) + if type_settings: + for setting_key, data_key in type_settings.items(): + if data[data_key] is not None: + if data_key == "pushover_priority": + payload["settings"][setting_key] = { + "emergency": "2", + "high": "1", + "normal": "0", + "low": "-1", + "lowest": "-2", + }[data[data_key]] + elif data_key == "dingding_message_type": + payload["settings"][setting_key] = { + "link": "link", + "action_card": "actionCard", + }[data[data_key]] + elif data_key in ["email_addresses", "pushover_devices"]: + payload["settings"][setting_key] = ";".join(data[data_key]) + elif data_key in ["slack_mention_users", "slack_mention_groups"]: + payload["settings"][setting_key] = ",".join(data[data_key]) + elif data.get(data_key): + payload["settings"][setting_key] = data[data_key] + + return payload + + +class GrafanaContactPointInterface(object): + def __init__(self, module): + self._module = module + self.org_id = None + # {{{ Authentication header + self.headers = {"Content-Type": "application/json"} + if module.params.get("grafana_api_key", None): + self.headers["Authorization"] = ( + "Bearer %s" % module.params["grafana_api_key"] + ) + else: + self.headers["Authorization"] = basic_auth_header( + module.params["url_username"], module.params["url_password"] + ) + self.org_id = ( + self.grafana_organization_by_name(module.params["org_name"]) + if module.params["org_name"] + else module.params["org_id"] + ) + self.grafana_switch_organisation(module.params, self.org_id) + # }}} + self.contact_point = self.grafana_check_contact_point_match(module.params) + + def grafana_handle_api_provisioning(self, data): + if not self.contact_point or ( + not self.contact_point.get("provenance") and not data.get("provisioning") + ): + self.headers["X-Disable-Provenance"] = "true" + elif self.contact_point.get("provenance") and not data.get("provisioning"): + self._module.fail_json( + msg="Unable to update contact point '%s': provisioning cannot be disabled if it's already enabled" + % data["uid"] + ) + else: + pass + + def grafana_organization_by_name(self, data, org_name): + r, info = fetch_url( + self._module, + "%s/api/user/orgs" % data["url"], + headers=self.headers, + method="GET", + ) + organizations = json.loads(to_text(r.read())) + orga = next((org for org in organizations if org["name"] == org_name)) + if orga: + return orga["orgId"] + + raise GrafanaAPIException( + "Current user isn't member of organization: %s" % org_name + ) + + def grafana_switch_organisation(self, data, org_id): + r, info = fetch_url( + self._module, + "%s/api/user/using/%s" % (data["url"], org_id), + headers=self.headers, + method="POST", + ) + if info["status"] != 200: + raise GrafanaAPIException( + "Unable to switch to organization '%s': %s" % (org_id, info) + ) + + def grafana_check_contact_point_match(self, data): + r, info = fetch_url( + self._module, + "%s/api/v1/provisioning/contact-points" % data["url"], + headers=self.headers, + method="GET", + ) + + if info["status"] == 200: + contact_points = json.loads(to_text(r.read())) + contact_point = next( + (cp for cp in contact_points if cp["uid"] == data["uid"]), None + ) + return contact_point + elif info["status"] == 404: + self._module.fail_json( + msg="Unable to get contact point: API endpoint not found - please check your Grafana version" + ) + else: + raise GrafanaAPIException( + "Unable to get contact point '%s': %s" % (data["uid"], info) + ) + + def grafana_handle_contact_point(self, data): + payload = grafana_contact_point_payload(data) + + if data["state"] == "present": + self.grafana_handle_api_provisioning(data) + if self.contact_point: + return self.grafana_update_contact_point(data, payload) + else: + return self.grafana_create_contact_point(data, payload) + else: + if self.contact_point: + return self.grafana_delete_contact_point(data) + else: + return {"changed": False, "state": data["state"]} + + def grafana_create_contact_point(self, data, payload): + r, info = fetch_url( + self._module, + "%s/api/v1/provisioning/contact-points" % data["url"], + data=json.dumps(payload), + headers=self.headers, + method="POST", + ) + + if info["status"] == 202: + contact_point = json.loads(to_text(r.read())) + return { + "changed": True, + "contact_point": contact_point, + "state": data["state"], + } + else: + raise GrafanaAPIException("Unable to create contact point: %s" % info) + + def grafana_update_contact_point(self, data, payload): + r, info = fetch_url( + self._module, + "%s/api/v1/provisioning/contact-points/%s" % (data["url"], data["uid"]), + data=json.dumps(payload), + headers=self.headers, + method="PUT", + ) + + if info["status"] == 202: + contact_point = self.grafana_check_contact_point_match(data) + + if contact_point.get("provenance") and data.get("provisioning"): + del contact_point["provenance"] + + if self.contact_point == contact_point: + return { + "changed": False, + "contact_point": contact_point, + "state": data["state"], + } + else: + return { + "changed": True, + "diff": {"before": self.contact_point, "after": contact_point}, + "contact_point": contact_point, + "state": data["state"], + } + else: + raise GrafanaAPIException( + "Unable to update contact point '%s': %s" % (data["uid"], info) + ) + + def grafana_delete_contact_point(self, data): + r, info = fetch_url( + self._module, + "%s/api/v1/provisioning/contact-points/%s" % (data["url"], data["uid"]), + headers=self.headers, + method="DELETE", + ) + + if info["status"] == 202: + return { + "changed": True, + "contact_point": self.contact_point, + "state": data["state"], + } + elif info["status"] == 404: + return {"changed": False, "state": data["state"]} + else: + raise GrafanaAPIException( + "Unable to delete contact point '%s': %s" % (data["uid"], info) + ) + + +def main(): + argument_spec = grafana_argument_spec() + argument_spec.update( + # general arguments + disable_resolve_message=dict(type="bool", default=False), + include_image=dict(type="bool", default=False), + name=dict(type="str"), + org_id=dict(type="int", default=1), + org_name=dict(type="str"), + provisioning=dict(type="bool", default=True), + type=dict( + type="str", + choices=[ + "alertmanager", + "dingding", + "discord", + "email", + "googlechat", + "kafka", + "line", + "opsgenie", + "pagerduty", + "pushover", + "sensugo", + "slack", + "teams", + "telegram", + "threema", + "victorops", + "webex", + "webhook", + "wecom", + ], + ), + uid=dict(required=True, type="str"), + # alertmanager + alertmanager_password=dict(type="str", no_log=True), + alertmanager_url=dict(type="str"), + alertmanager_username=dict(type="str"), + # dingding + dingding_message=dict(type="str"), + dingding_message_type=dict(type="str"), + dingding_title=dict(type="str"), + dingding_url=dict(type="str"), + # discord + discord_avatar_url=dict(type="str"), + discord_message=dict(type="str"), + discord_title=dict(type="str"), + discord_url=dict(type="str", no_log=True), + discord_use_username=dict(type="bool", default=False), + # email + email_addresses=dict(type="list", elements="str"), + email_message=dict(type="str"), + email_single=dict(type="bool", default=False), + email_subject=dict(type="str"), + # googlechat + googlechat_url=dict(type="str", no_log=True), + googlechat_message=dict(type="str"), + googlechat_title=dict(type="str"), + # kafka + kafka_api_version=dict(type="str", default="v2"), + kafka_cluster_id=dict(type="str"), + kafka_description=dict(type="str"), + kafka_details=dict(type="str"), + kafka_password=dict(type="str", no_log=True), + kafka_rest_proxy_url=dict(type="str", no_log=True), + kafka_topic=dict(type="str"), + kafka_username=dict(type="str"), + # line + line_description=dict(type="str"), + line_title=dict(type="str"), + line_token=dict(type="str", no_log=True), + # opsgenie + opsgenie_api_key=dict(type="str", no_log=True), + opsgenie_auto_close=dict(type="bool"), + opsgenie_description=dict(type="str"), + opsgenie_message=dict(type="str"), + opsgenie_override_priority=dict(type="bool"), + opsgenie_responders=dict(type="list", elements="dict"), + opsgenie_send_tags_as=dict(type="str"), + opsgenie_url=dict(type="str"), + # pagerduty + pagerduty_class=dict(type="str"), + pagerduty_client=dict(type="str"), + pagerduty_client_url=dict(type="str"), + pagerduty_component=dict(type="str"), + pagerduty_details=dict(type="list", elements="dict"), + pagerduty_group=dict(type="str"), + pagerduty_integration_key=dict(type="str", no_log=True), + pagerduty_severity=dict( + type="str", choices=["critical", "error", "warning", "info"] + ), + pagerduty_source=dict(type="str"), + pagerduty_summary=dict(type="str"), + # pushover + pushover_api_token=dict(type="str", no_log=True), + pushover_devices=dict(type="list", elements="str"), + pushover_expire=dict(type="int"), + pushover_message=dict(type="str"), + pushover_ok_priority=dict(type="int"), + pushover_ok_sound=dict(type="str"), + pushover_priority=dict(type="int"), + pushover_retry=dict(type="int"), + pushover_sound=dict(type="str"), + pushover_title=dict(type="str"), + pushover_upload_image=dict(type="bool", default=True), + pushover_user_key=dict(type="str", no_log=True), + # sensugo + sensugo_api_key=dict(type="str", no_log=True), + sensugo_url=dict(type="str"), + sensugo_check=dict(type="str"), + sensugo_entity=dict(type="str"), + sensugo_handler=dict(type="str"), + sensugo_message=dict(type="str"), + sensugo_namespace=dict(type="str"), + # slack + slack_endpoint_url=dict(type="str"), + slack_icon_emoji=dict(type="str"), + slack_icon_url=dict(type="str"), + slack_mention_channel=dict(type="str", choices=["here", "channel"]), + slack_mention_groups=dict(type="list", elements="str"), + slack_mention_users=dict(type="list", elements="str"), + slack_recipient=dict(type="str"), + slack_text=dict(type="str"), + slack_title=dict(type="str"), + slack_token=dict(type="str", no_log=True), + slack_url=dict(type="str", no_log=True), + slack_username=dict(type="str"), + # teams + teams_message=dict(type="str"), + teams_section_title=dict(type="str"), + teams_title=dict(type="str"), + teams_url=dict(type="str", no_log=True), + # telegram + telegram_chat_id=dict(type="str"), + telegram_disable_notifications=dict(type="bool"), + telegram_message=dict(type="str"), + telegram_parse_mode=dict(type="str"), + telegram_protect_content=dict(type="bool"), + telegram_token=dict(type="str", no_log=True), + telegram_web_page_view=dict(type="bool"), + # threema + threema_api_secret=dict(type="str", no_log=True), + threema_description=dict(type="str"), + threema_gateway_id=dict(type="str"), + threema_recipient_id=dict(type="str"), + threema_title=dict(type="str"), + # victorops + victorops_description=dict(type="str"), + victorops_message_type=dict(type="str", choices=["CRITICAL", "RECOVERY"]), + victorops_title=dict(type="str"), + victorops_url=dict(type="str"), + # webex + webex_api_url=dict(type="str"), + webex_message=dict(type="str"), + webex_room_id=dict(type="str"), + webex_token=dict(type="str", no_log=True), + # webhook + webhook_authorization_credentials=dict(type="str", no_log=True), + webhook_authorization_scheme=dict(type="str"), + webhook_http_method=dict(type="str", choices=["POST", "PUT"]), + webhook_max_alerts=dict(type="int"), + webhook_message=dict(type="str"), + webhook_password=dict(type="str", no_log=True), + webhook_title=dict(type="str"), + webhook_url=dict(type="str"), + webhook_username=dict(type="str"), + # wecom + wecom_agent_id=dict(type="str"), + wecom_corp_id=dict(type="str"), + wecom_message=dict(type="str"), + wecom_msg_type=dict(type="str"), + wecom_secret=dict(type="str", no_log=True), + wecom_title=dict(type="str"), + wecom_to_user=dict(type="list", elements="str"), + wecom_url=dict(type="str", no_log=True), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=False, + required_together=[["url_username", "url_password", "org_id"]], + mutually_exclusive=[["url_username", "grafana_api_key"]], + required_if=[ + ["state", "present", ["name", "type"]], + ["type", "alertmanager", ["alertmanager_url"]], + ["type", "dingding", ["dingding_url"]], + ["type", "discord", ["discord_url"]], + ["type", "email", ["email_addresses"]], + ["type", "googlechat", ["googlechat_url"]], + ["type", "kafka", ["kafka_rest_proxy_url", "kafka_topic"]], + ["type", "line", ["line_token"]], + ["type", "opsgenie", ["opsgenie_api_key", "opsgenie_url"]], + ["type", "pagerduty", ["pagerduty_integration_key"]], + ["type", "pushover", ["pushover_api_token", "pushover_user_key"]], + ["type", "sensugo", ["sensugo_api_key", "sensugo_url"]], + ["type", "slack", ["slack_recipient", "slack_token", "slack_url"]], + ["type", "teams", ["teams_url"]], + ["type", "telegram", ["telegram_chat_id", "telegram_token"]], + [ + "type", + "threema", + ["threema_api_secret", "threema_gateway_id", "threema_recipient_id"], + ], + ["type", "victorops", ["victorops_url"]], + ["type", "webex", ["webex_token", "webex_room_id"]], + ["type", "webhook", ["webhook_url"]], + [ + "type", + "wecom", + ["wecom_url", "wecom_agent_id", "wecom_corp_id", "wecom_secret"], + ], + ], + ) + + module.params["url"] = clean_url(module.params["url"]) + grafana_iface = GrafanaContactPointInterface(module) + + result = grafana_iface.grafana_handle_contact_point(module.params) + module.exit_json(failed=False, **result) + + +if __name__ == "__main__": + main() +# TODO: check api messages diff --git a/roles/grafana/README.md b/roles/grafana/README.md index b26a9044..a6ce7507 100644 --- a/roles/grafana/README.md +++ b/roles/grafana/README.md @@ -172,6 +172,136 @@ Configure Grafana organizations, dashboards, folders, datasources, teams and use | org_name | no | | starts_at | yes | | state | no | +| [**grafana_contact_point**](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_contact_point_module.html) | +| disable_resolve_message | no | +| include_image | no | +| name | no | +| org_id | no | +| org_name | no | +| provisioning | no | +| state | no | +| type | no | +| uid | yes | +| alertmanager_password | no | +| alertmanager_url | no | +| alertmanager_username | no | +| dingding_message | no | +| dingding_message_type | no | +| dingding_title | no | +| dingding_url | no | +| discord_avatar_url | no | +| discord_message | no | +| discord_title | no | +| discord_url | no | +| discord_use_username | no | +| email_addresses | no | +| email_message | no | +| email_single | no | +| email_subject | no | +| googlechat_message | no | +| googlechat_title | no | +| googlechat_url | no | +| kafka_api_version | no | +| kafka_cluster_id | no | +| kafka_description | no | +| kafka_details | no | +| kafka_password | no | +| kafka_rest_proxy_url | no | +| kafka_topic | no | +| kafka_username | no | +| line_description | no | +| line_title | no | +| line_token | no | +| opsgenie_api_key | no | +| opsgenie_auto_close | no | +| opsgenie_description | no | +| opsgenie_message | no | +| opsgenie_override_priority | no | +| opsgenie_responders | no | +| opsgenie_send_tags_as | no | +| opsgenie_url | no | +| pagerduty_class | no | +| pagerduty_client | no | +| pagerduty_client_url | no | +| pagerduty_component | no | +| pagerduty_details | no | +| pagerduty_group | no | +| pagerduty_integration_key | no | +| pagerduty_severity | no | +| pagerduty_source | no | +| pagerduty_summary | no | +| pushover_api_token | no | +| pushover_devices | no | +| pushover_expire | no | +| pushover_message | no | +| pushover_ok_priority | no | +| pushover_ok_sound | no | +| pushover_priority | no | +| pushover_retry | no | +| pushover_sound | no | +| pushover_title | no | +| pushover_upload_image | no | +| pushover_user_key | no | +| sensugo_api_key | no | +| sensugo_check | no | +| sensugo_entity | no | +| sensugo_handler | no | +| sensugo_message | no | +| sensugo_namespace | no | +| sensugo_url | no | +| slack_endpoint_url | no | +| slack_icon_emoji | no | +| slack_icon_url | no | +| slack_mention_channel | no | +| slack_mention_groups | no | +| slack_mention_users | no | +| slack_recipient | no | +| slack_text | no | +| slack_title | no | +| slack_token | no | +| slack_url | no | +| slack_username | no | +| teams_message | no | +| teams_section_title | no | +| teams_title | no | +| teams_url | no | +| telegram_chat_id | no | +| telegram_disable_notifications | no | +| telegram_message | no | +| telegram_parse_mode | no | +| telegram_protect_content | no | +| telegram_token | no | +| telegram_web_page_view | no | +| threema_api_secret | no | +| threema_description | no | +| threema_gateway_id | no | +| threema_recipient_id | no | +| threema_title | no | +| victorops_description | no | +| victorops_message_type | no | +| victorops_title | no | +| victorops_url | no | +| webex_api_url | no | +| webex_message | no | +| webex_room_id | no | +| webex_token | no | +| webhook_authorization_credentials | no | +| webhook_authorization_scheme | no | +| webhook_http_method | no | +| webhook_max_alerts | no | +| webhook_message | no | +| webhook_password | no | +| webhook_title | no | +| webhook_url | no | +| webhook_username | no | +| wecom_agent_id | no | +| wecom_corp_id | no | +| wecom_message | no | +| wecom_msg_type | no | +| wecom_secret | no | +| wecom_title | no | +| wecom_to_user | no | +| wecom_url | no | ## Example Playbook diff --git a/roles/grafana/defaults/main.yml b/roles/grafana/defaults/main.yml index 9756a133..a3f90760 100644 --- a/roles/grafana/defaults/main.yml +++ b/roles/grafana/defaults/main.yml @@ -8,3 +8,4 @@ grafana_folders: [] grafana_dashboards: [] grafana_notification_channels: [] grafana_silences: [] +grafana_contact_points: [] diff --git a/roles/grafana/tasks/main.yml b/roles/grafana/tasks/main.yml index f5e41021..170d9337 100644 --- a/roles/grafana/tasks/main.yml +++ b/roles/grafana/tasks/main.yml @@ -89,6 +89,141 @@ loop_control: {loop_var: notification_channel} tags: notification_channel + - name: Manage contact point + community.grafana.grafana_contact_point: + disable_resolve_message: "{{ contact_point.disable_resolve_message | default(omit) }}" + include_image: "{{ contact_point.include_image | default(omit) }}" + name: "{{ contact_point.name | default(omit) }}" + org_id: "{{ contact_point.org_id | default(omit) }}" + org_name: "{{ contact_point.org_name | default(omit) }}" + provisioning: "{{ contact_point.provisioning | default(omit) }}" + state: "{{ contact_point.state | default(omit) }}" + type: "{{ contact_point.type | default(omit) }}" + uid: "{{ contact_point.uid }}" + alertmanager_password: "{{ contact_point.alertmanager_password | default(omit) }}" + alertmanager_url: "{{ contact_point.alertmanager_url | default(omit) }}" + alertmanager_username: "{{ contact_point.alertmanager_username | default(omit) }}" + dingding_message: "{{ contact_point.dingding_message | default(omit) }}" + dingding_message_type: "{{ contact_point.dingding_message_type | default(omit) }}" + dingding_title: "{{ contact_point.dingding_title | default(omit) }}" + dingding_url: "{{ contact_point.dingding_url | default(omit) }}" + discord_avatar_url: "{{ contact_point.discord_avatar_url | default(omit) }}" + discord_message: "{{ contact_point.discord_message | default(omit) }}" + discord_title: "{{ contact_point.discord_title | default(omit) }}" + discord_url: "{{ contact_point.discord_url | default(omit) }}" + discord_use_username: "{{ contact_point.discord_use_username | default(omit) }}" + email_addresses: "{{ contact_point.email_addresses | default(omit) }}" + email_message: "{{ contact_point.email_message | default(omit) }}" + email_single: "{{ contact_point.email_single | default(omit) }}" + email_subject: "{{ contact_point.email_subject | default(omit) }}" + googlechat_message: "{{ contact_point.googlechat_message | default(omit) }}" + googlechat_title: "{{ contact_point.googlechat_title | default(omit) }}" + googlechat_url: "{{ contact_point.googlechat_url | default(omit) }}" + kafka_api_version: "{{ contact_point.kafka_api_version | default(omit) }}" + kafka_cluster_id: "{{ contact_point.kafka_cluster_id | default(omit) }}" + kafka_description: "{{ contact_point.kafka_description | default(omit) }}" + kafka_details: "{{ contact_point.kafka_details | default(omit) }}" + kafka_password: "{{ contact_point.kafka_password | default(omit) }}" + kafka_rest_proxy_url: "{{ contact_point.kafka_rest_proxy_url | default(omit) }}" + kafka_topic: "{{ contact_point.kafka_topic | default(omit) }}" + kafka_username: "{{ contact_point.kafka_username | default(omit) }}" + line_description: "{{ contact_point.line_description | default(omit) }}" + line_title: "{{ contact_point.line_title | default(omit) }}" + line_token: "{{ contact_point.line_token | default(omit) }}" + opsgenie_api_key: "{{ contact_point.opsgenie_api_key | default(omit) }}" + opsgenie_auto_close: "{{ contact_point.opsgenie_auto_close | default(omit) }}" + opsgenie_description: "{{ contact_point.opsgenie_description | default(omit) }}" + opsgenie_message: "{{ contact_point.opsgenie_message | default(omit) }}" + opsgenie_override_priority: "{{ contact_point.opsgenie_override_priority | default(omit) }}" + opsgenie_responders: "{{ contact_point.opsgenie_responders | default(omit) }}" + opsgenie_send_tags_as: "{{ contact_point.opsgenie_send_tags_as | default(omit) }}" + opsgenie_url: "{{ contact_point.opsgenie_url | default(omit) }}" + pagerduty_class: "{{ contact_point.pagerduty_class | default(omit) }}" + pagerduty_client: "{{ contact_point.pagerduty_client | default(omit) }}" + pagerduty_client_url: "{{ contact_point.pagerduty_client_url | default(omit) }}" + pagerduty_component: "{{ contact_point.pagerduty_component | default(omit) }}" + pagerduty_details: "{{ contact_point.pagerduty_details | default(omit) }}" + pagerduty_group: "{{ contact_point.pagerduty_group | default(omit) }}" + pagerduty_integration_key: "{{ contact_point.pagerduty_integration_key | default(omit) }}" + pagerduty_severity: "{{ contact_point.pagerduty_severity | default(omit) }}" + pagerduty_source: "{{ contact_point.pagerduty_source | default(omit) }}" + pagerduty_summary: "{{ contact_point.pagerduty_summary | default(omit) }}" + pushover_api_token: "{{ contact_point.pushover_api_token | default(omit) }}" + pushover_devices: "{{ contact_point.pushover_devices | default(omit) }}" + pushover_expire: "{{ contact_point.pushover_expire | default(omit) }}" + pushover_message: "{{ contact_point.pushover_message | default(omit) }}" + pushover_ok_priority: "{{ contact_point.pushover_ok_priority | default(omit) }}" + pushover_ok_sound: "{{ contact_point.pushover_ok_sound | default(omit) }}" + pushover_priority: "{{ contact_point.pushover_priority | default(omit) }}" + pushover_retry: "{{ contact_point.pushover_retry | default(omit) }}" + pushover_sound: "{{ contact_point.pushover_sound | default(omit) }}" + pushover_title: "{{ contact_point.pushover_title | default(omit) }}" + pushover_upload_image: "{{ contact_point.pushover_upload_image | default(omit) }}" + pushover_user_key: "{{ contact_point.pushover_user_key | default(omit) }}" + sensugo_api_key: "{{ contact_point.sensugo_api_key | default(omit) }}" + sensugo_check: "{{ contact_point.sensugo_check | default(omit) }}" + sensugo_entity: "{{ contact_point.sensugo_entity | default(omit) }}" + sensugo_handler: "{{ contact_point.sensugo_handler | default(omit) }}" + sensugo_message: "{{ contact_point.sensugo_message | default(omit) }}" + sensugo_namespace: "{{ contact_point.sensugo_namespace | default(omit) }}" + sensugo_url: "{{ contact_point.sensugo_url | default(omit) }}" + slack_endpoint_url: "{{ contact_point.slack_endpoint_url | default(omit) }}" + slack_icon_emoji: "{{ contact_point.slack_icon_emoji | default(omit) }}" + slack_icon_url: "{{ contact_point.slack_icon_url | default(omit) }}" + slack_mention_channel: "{{ contact_point.slack_mention_channel | default(omit) }}" + slack_mention_groups: "{{ contact_point.slack_mention_groups | default(omit) }}" + slack_mention_users: "{{ contact_point.slack_mention_users | default(omit) }}" + slack_recipient: "{{ contact_point.slack_recipient | default(omit) }}" + slack_text: "{{ contact_point.slack_text | default(omit) }}" + slack_title: "{{ contact_point.slack_title | default(omit) }}" + slack_token: "{{ contact_point.slack_token | default(omit) }}" + slack_url: "{{ contact_point.slack_url | default(omit) }}" + slack_username: "{{ contact_point.slack_username | default(omit) }}" + teams_message: "{{ contact_point.teams_message | default(omit) }}" + teams_section_title: "{{ contact_point.teams_section_title | default(omit) }}" + teams_title: "{{ contact_point.teams_title | default(omit) }}" + teams_url: "{{ contact_point.teams_url | default(omit) }}" + telegram_chat_id: "{{ contact_point.telegram_chat_id | default(omit) }}" + telegram_disable_notifications: "{{ contact_point.telegram_disable_notifications | default(omit) }}" + telegram_message: "{{ contact_point.telegram_message | default(omit) }}" + telegram_parse_mode: "{{ contact_point.telegram_parse_mode | default(omit) }}" + telegram_protect_content: "{{ contact_point.telegram_protect_content | default(omit) }}" + telegram_token: "{{ contact_point.telegram_token | default(omit) }}" + telegram_web_page_view: "{{ contact_point.telegram_web_page_view | default(omit) }}" + threema_api_secret: "{{ contact_point.threema_api_secret | default(omit) }}" + threema_description: "{{ contact_point.threema_description | default(omit) }}" + threema_gateway_id: "{{ contact_point.threema_gateway_id | default(omit) }}" + threema_recipient_id: "{{ contact_point.threema_recipient_id | default(omit) }}" + threema_title: "{{ contact_point.threema_title | default(omit) }}" + victorops_description: "{{ contact_point.victorops_description | default(omit) }}" + victorops_message_type: "{{ contact_point.victorops_message_type | default(omit) }}" + victorops_title: "{{ contact_point.victorops_title | default(omit) }}" + victorops_url: "{{ contact_point.victorops_url | default(omit) }}" + webex_api_url: "{{ contact_point.webex_api_url | default(omit) }}" + webex_message: "{{ contact_point.webex_message | default(omit) }}" + webex_room_id: "{{ contact_point.webex_room_id | default(omit) }}" + webex_token: "{{ contact_point.webex_token | default(omit) }}" + webhook_authorization_credentials: "{{ contact_point.webhook_authorization_credentials | default(omit) }}" + webhook_authorization_scheme: "{{ contact_point.webhook_authorization_scheme | default(omit) }}" + webhook_http_method: "{{ contact_point.webhook_http_method | default(omit) }}" + webhook_max_alerts: "{{ contact_point.webhook_max_alerts | default(omit) }}" + webhook_message: "{{ contact_point.webhook_message | default(omit) }}" + webhook_password: "{{ contact_point.webhook_password | default(omit) }}" + webhook_title: "{{ contact_point.webhook_title | default(omit) }}" + webhook_url: "{{ contact_point.webhook_url | default(omit) }}" + webhook_username: "{{ contact_point.webhook_username | default(omit) }}" + wecom_agent_id: "{{ contact_point.wecom_agent_id | default(omit) }}" + wecom_corp_id: "{{ contact_point.wecom_corp_id | default(omit) }}" + wecom_message: "{{ contact_point.wecom_message | default(omit) }}" + wecom_msg_type: "{{ contact_point.wecom_msg_type | default(omit) }}" + wecom_secret: "{{ contact_point.wecom_secret | default(omit) }}" + wecom_title: "{{ contact_point.wecom_title | default(omit) }}" + wecom_to_user: "{{ contact_point.wecom_to_user | default(omit) }}" + wecom_url: "{{ contact_point.wecom_url | default(omit) }}" + loop: "{{ grafana_contact_points }}" + loop_control: {loop_var: contact_point} + tags: contact_point + - name: Manage datasource community.grafana.grafana_datasource: access: "{{ datasource.access | default(omit) }}" diff --git a/tests/integration/targets/grafana_contact_point/runme.sh b/tests/integration/targets/grafana_contact_point/runme.sh new file mode 100755 index 00000000..867afb0d --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/runme.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -eux + +ansible-playbook site.yml diff --git a/tests/integration/targets/grafana_contact_point/site.yml b/tests/integration/targets/grafana_contact_point/site.yml new file mode 100644 index 00000000..aeb027f0 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/site.yml @@ -0,0 +1,11 @@ +--- +- name: Run tests for grafana_contact_point + hosts: localhost + module_defaults: + community.grafana.grafana_contact_point: + grafana_url: http://grafana:3000 + grafana_user: admin + grafana_password: admin + tasks: + - ansible.builtin.include_role: + name: ../../grafana_contact_point diff --git a/tests/integration/targets/grafana_contact_point/tasks/alertmanager.yml b/tests/integration/targets/grafana_contact_point/tasks/alertmanager.yml new file mode 100644 index 00000000..9fd23797 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/alertmanager.yml @@ -0,0 +1,87 @@ +--- +- name: Create alertmanager contact point + register: result + community.grafana.grafana_contact_point: + uid: alertmanager + name: alertmanager + type: alertmanager + alertmanager_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "alertmanager" + - result.contact_point.name == "alertmanager" + - result.contact_point.type == "prometheus-alertmanager" + +- name: Create alertmanager contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: alertmanager + name: alertmanager + type: alertmanager + alertmanager_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "alertmanager" + - result.contact_point.name == "alertmanager" + - result.contact_point.type == "prometheus-alertmanager" + +- name: Update alertmanager contact point + register: result + community.grafana.grafana_contact_point: + uid: alertmanager + name: alertmanager + type: alertmanager + alertmanager_url: https://example-update.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "alertmanager" + - result.contact_point.name == "alertmanager" + - result.contact_point.type == "prometheus-alertmanager" + - result.diff is defined + +- name: Delete alertmanager contact point + register: result + community.grafana.grafana_contact_point: + uid: alertmanager + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "alertmanager" + +- name: Delete alertmanager contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: alertmanager + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/dingding.yml b/tests/integration/targets/grafana_contact_point/tasks/dingding.yml new file mode 100644 index 00000000..b2fee63c --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/dingding.yml @@ -0,0 +1,87 @@ +--- +- name: Create dingding contact point + register: result + community.grafana.grafana_contact_point: + uid: dingding + name: dingding + type: dingding + dingding_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "dingding" + - result.contact_point.name == "dingding" + - result.contact_point.type == "dingding" + +- name: Create dingding contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: dingding + name: dingding + type: dingding + dingding_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "dingding" + - result.contact_point.name == "dingding" + - result.contact_point.type == "dingding" + +- name: Update dingding contact point + register: result + community.grafana.grafana_contact_point: + uid: dingding + name: dingding + type: dingding + dingding_url: https://example-update.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "dingding" + - result.contact_point.name == "dingding" + - result.contact_point.type == "dingding" + - result.diff is defined + +- name: Delete dingding contact point + register: result + community.grafana.grafana_contact_point: + uid: dingding + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "dingding" + +- name: Delete dingding contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: dingding + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/discord.yml b/tests/integration/targets/grafana_contact_point/tasks/discord.yml new file mode 100644 index 00000000..a968d440 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/discord.yml @@ -0,0 +1,87 @@ +--- +- name: Create discord contact point + register: result + community.grafana.grafana_contact_point: + uid: discord + name: discord + type: discord + discord_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "discord" + - result.contact_point.name == "discord" + - result.contact_point.type == "discord" + +- name: Create discord contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: discord + name: discord + type: discord + discord_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "discord" + - result.contact_point.name == "discord" + - result.contact_point.type == "discord" + +- name: Update discord contact point + register: result + community.grafana.grafana_contact_point: + uid: discord + name: discord + type: discord + discord_url: https://example-update.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "discord" + - result.contact_point.name == "discord" + - result.contact_point.type == "discord" + - result.diff is defined + +- name: Delete discord contact point + register: result + community.grafana.grafana_contact_point: + uid: discord + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "discord" + +- name: Delete discord contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: discord + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/email.yml b/tests/integration/targets/grafana_contact_point/tasks/email.yml new file mode 100644 index 00000000..1d08ff03 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/email.yml @@ -0,0 +1,93 @@ +--- +- name: Create email contact point + register: result + community.grafana.grafana_contact_point: + uid: email + name: email + type: email + email_addresses: + - foo@example.org + - bar@example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "email" + - result.contact_point.name == "email" + - result.contact_point.type == "email" + +- name: Create email contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: email + name: email + type: email + email_addresses: + - foo@example.org + - bar@example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "email" + - result.contact_point.name == "email" + - result.contact_point.type == "email" + +- name: Update email contact point + register: result + community.grafana.grafana_contact_point: + uid: email + name: email + type: email + email_addresses: + - foo@example-update.org + - bar@example-update.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "email" + - result.contact_point.name == "email" + - result.contact_point.type == "email" + - result.diff is defined + +- name: Delete email contact point + register: result + community.grafana.grafana_contact_point: + uid: email + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "email" + +- name: Delete email contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: email + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/googlechat.yml b/tests/integration/targets/grafana_contact_point/tasks/googlechat.yml new file mode 100644 index 00000000..fdc13b96 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/googlechat.yml @@ -0,0 +1,87 @@ +--- +- name: Create googlechat contact point + register: result + community.grafana.grafana_contact_point: + uid: googlechat + name: googlechat + type: googlechat + googlechat_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "googlechat" + - result.contact_point.name == "googlechat" + - result.contact_point.type == "googlechat" + +- name: Create googlechat contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: googlechat + name: googlechat + type: googlechat + googlechat_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "googlechat" + - result.contact_point.name == "googlechat" + - result.contact_point.type == "googlechat" + +- name: Update googlechat contact point + register: result + community.grafana.grafana_contact_point: + uid: googlechat + name: googlechat + type: googlechat + googlechat_url: https://example-update.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "googlechat" + - result.contact_point.name == "googlechat" + - result.contact_point.type == "googlechat" + - result.diff is defined + +- name: Delete googlechat contact point + register: result + community.grafana.grafana_contact_point: + uid: googlechat + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "googlechat" + +- name: Delete googlechat contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: googlechat + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/kafka.yml b/tests/integration/targets/grafana_contact_point/tasks/kafka.yml new file mode 100644 index 00000000..3914b6a8 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/kafka.yml @@ -0,0 +1,90 @@ +--- +- name: Create kafka contact point + register: result + community.grafana.grafana_contact_point: + uid: kafka + name: kafka + type: kafka + kafka_rest_proxy_url: https://example.org + kafka_topic: test + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "kafka" + - result.contact_point.name == "kafka" + - result.contact_point.type == "kafka" + +- name: Create kafka contact point (idempotentcy) + register: result + community.grafana.grafana_contact_point: + uid: kafka + name: kafka + type: kafka + kafka_rest_proxy_url: https://example.org + kafka_topic: test + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "kafka" + - result.contact_point.name == "kafka" + - result.contact_point.type == "kafka" + +- name: Update kafka contact point + register: result + community.grafana.grafana_contact_point: + uid: kafka + name: kafka + type: kafka + kafka_rest_proxy_url: https://example-update.org + kafka_topic: test-update + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "kafka" + - result.contact_point.name == "kafka" + - result.contact_point.type == "kafka" + - result.diff is defined + +- name: Delete kafka contact point + register: result + community.grafana.grafana_contact_point: + uid: kafka + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "kafka" + +- name: Delete kafka contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: kafka + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/line.yml b/tests/integration/targets/grafana_contact_point/tasks/line.yml new file mode 100644 index 00000000..33c749e8 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/line.yml @@ -0,0 +1,87 @@ +--- +- name: Create line contact point + register: result + community.grafana.grafana_contact_point: + uid: line + name: line + type: line + line_token: xxx + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "line" + - result.contact_point.name == "line" + - result.contact_point.type == "line" + +- name: Create line contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: line + name: line + type: line + line_token: xxx + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "line" + - result.contact_point.name == "line" + - result.contact_point.type == "line" + +- name: Update line contact point + register: result + community.grafana.grafana_contact_point: + uid: line + name: line + type: line + line_token: xxx-update + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "line" + - result.contact_point.name == "line" + - result.contact_point.type == "line" + - result.diff is defined + +- name: Delete line contact point + register: result + community.grafana.grafana_contact_point: + uid: line + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "line" + +- name: Delete line contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: line + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/main.yml b/tests/integration/targets/grafana_contact_point/tasks/main.yml new file mode 100644 index 00000000..83a6dc67 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/main.yml @@ -0,0 +1,28 @@ +--- + +- name: Check for support of API endpoint + register: result + ignore_errors: true + community.grafana.grafana_contact_point: + uid: apitest + state: absent + +- name: Include contact point task files + ansible.builtin.include_tasks: "{{ item }}.yml" + when: "result.msg | default('') != 'Unable to get contact point: API endpoint not found - please check your Grafana version'" + loop: + - alertmanager + - dingding + - discord + - email + - googlechat + - kafka + - opsgenie + - pagerduty + - pushover + - sensugo + - slack + - teams + - telegram + - victorops + - webhook diff --git a/tests/integration/targets/grafana_contact_point/tasks/opsgenie.yml b/tests/integration/targets/grafana_contact_point/tasks/opsgenie.yml new file mode 100644 index 00000000..fef2813e --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/opsgenie.yml @@ -0,0 +1,90 @@ +--- +- name: Create opsgenie contact point + register: result + community.grafana.grafana_contact_point: + uid: opsgenie + name: opsgenie + type: opsgenie + opsgenie_url: https://example.org + opsgenie_api_key: xxx + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "opsgenie" + - result.contact_point.name == "opsgenie" + - result.contact_point.type == "opsgenie" + +- name: Create opsgenie contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: opsgenie + name: opsgenie + type: opsgenie + opsgenie_url: https://example.org + opsgenie_api_key: xxx + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "opsgenie" + - result.contact_point.name == "opsgenie" + - result.contact_point.type == "opsgenie" + +- name: Update opsgenie contact point + register: result + community.grafana.grafana_contact_point: + uid: opsgenie + name: opsgenie + type: opsgenie + opsgenie_url: https://example-update.org + opsgenie_api_key: xxx-update + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "opsgenie" + - result.contact_point.name == "opsgenie" + - result.contact_point.type == "opsgenie" + - result.diff is defined + +- name: Delete opsgenie contact point + register: result + community.grafana.grafana_contact_point: + uid: opsgenie + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "opsgenie" + +- name: Delete opsgenie contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: opsgenie + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/pagerduty.yml b/tests/integration/targets/grafana_contact_point/tasks/pagerduty.yml new file mode 100644 index 00000000..86c24a6f --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/pagerduty.yml @@ -0,0 +1,87 @@ +--- +- name: Create pagerduty contact point + register: result + community.grafana.grafana_contact_point: + uid: pagerduty + name: pagerduty + type: pagerduty + pagerduty_integration_key: xxx + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "pagerduty" + - result.contact_point.name == "pagerduty" + - result.contact_point.type == "pagerduty" + +- name: Create pagerduty contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: pagerduty + name: pagerduty + type: pagerduty + pagerduty_integration_key: xxx + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "pagerduty" + - result.contact_point.name == "pagerduty" + - result.contact_point.type == "pagerduty" + +- name: Update pagerduty contact point + register: result + community.grafana.grafana_contact_point: + uid: pagerduty + name: pagerduty + type: pagerduty + pagerduty_integration_key: xxx-update + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "pagerduty" + - result.contact_point.name == "pagerduty" + - result.contact_point.type == "pagerduty" + - result.diff is defined + +- name: Delete pagerduty contact point + register: result + community.grafana.grafana_contact_point: + uid: pagerduty + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "pagerduty" + +- name: Delete pagerduty contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: pagerduty + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/pushover.yml b/tests/integration/targets/grafana_contact_point/tasks/pushover.yml new file mode 100644 index 00000000..5a264838 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/pushover.yml @@ -0,0 +1,90 @@ +--- +- name: Create pushover contact point + register: result + community.grafana.grafana_contact_point: + uid: pushover + name: pushover + type: pushover + pushover_api_token: xxx + pushover_user_key: yyy + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "pushover" + - result.contact_point.name == "pushover" + - result.contact_point.type == "pushover" + +- name: Create pushover contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: pushover + name: pushover + type: pushover + pushover_api_token: xxx + pushover_user_key: yyy + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "pushover" + - result.contact_point.name == "pushover" + - result.contact_point.type == "pushover" + +- name: Update pushover contact point + register: result + community.grafana.grafana_contact_point: + uid: pushover + name: pushover + type: pushover + pushover_api_token: xxx-update + pushover_user_key: yyy-update + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "pushover" + - result.contact_point.name == "pushover" + - result.contact_point.type == "pushover" + - result.diff is defined + +- name: Delete pushover contact point + register: result + community.grafana.grafana_contact_point: + uid: pushover + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "pushover" + +- name: Delete pushover contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: pushover + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml b/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml new file mode 100644 index 00000000..16ffab43 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml @@ -0,0 +1,90 @@ +--- +- name: Create sensugo contact point + register: result + community.grafana.grafana_contact_point: + uid: sensugo + name: sensugo + type: sensugo + sensugo_url: https://example.org + sensugo_api_key: testapikey + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "sensugo" + - result.contact_point.name == "sensugo" + - result.contact_point.type == "sensugo" + +- name: Create sensugo contact point + register: result + community.grafana.grafana_contact_point: + uid: sensugo + name: sensugo + type: sensugo + sensugo_url: https://example.org + sensugo_api_key: testapikey + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "sensugo" + - result.contact_point.name == "sensugo" + - result.contact_point.type == "sensugo" + +- name: Update sensugo contact point + register: result + community.grafana.grafana_contact_point: + uid: sensugo + name: sensugo + type: sensugo + sensugo_url: https://example-update.org + sensugo_api_key: testapikey-update + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "sensugo" + - result.contact_point.name == "sensugo" + - result.contact_point.type == "sensugo" + - result.diff is defined + +- name: Delete sensugo contact point + register: result + community.grafana.grafana_contact_point: + uid: sensugo + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "sensugo" + +- name: Delete sensugo contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: sensugo + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/slack.yml b/tests/integration/targets/grafana_contact_point/tasks/slack.yml new file mode 100644 index 00000000..b803c041 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/slack.yml @@ -0,0 +1,93 @@ +--- +- name: Create slack contact point + register: result + community.grafana.grafana_contact_point: + uid: slack + name: slack + type: slack + slack_url: https://hooks.slack.com/services/xxx/yyy/zzz + slack_token: testapitoken + slack_recipient: foo + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "slack" + - result.contact_point.name == "slack" + - result.contact_point.type == "slack" + +- name: Check slack contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: slack + name: slack + type: slack + slack_url: https://hooks.slack.com/services/xxx/yyy/zzz + slack_token: testapitoken + slack_recipient: foo + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "slack" + - result.contact_point.name == "slack" + - result.contact_point.type == "slack" + +- name: Update slack contact point + register: result + community.grafana.grafana_contact_point: + uid: slack + name: slack + type: slack + slack_url: https://hooks.slack.com/services/xxx/yyy/update + slack_token: testapitoken-update + slack_recipient: foo-update + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "slack" + - result.contact_point.name == "slack" + - result.contact_point.type == "slack" + - result.diff is defined + +- name: Delete slack contact point + register: result + community.grafana.grafana_contact_point: + state: absent + uid: slack + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "slack" + +- name: Delete slack contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + state: absent + uid: slack + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/teams.yml b/tests/integration/targets/grafana_contact_point/tasks/teams.yml new file mode 100644 index 00000000..eb0d1e5d --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/teams.yml @@ -0,0 +1,87 @@ +--- +- name: Create teams contact point + register: result + community.grafana.grafana_contact_point: + uid: teams + name: teams + type: teams + teams_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "teams" + - result.contact_point.name == "teams" + - result.contact_point.type == "teams" + +- name: Create teams contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: teams + name: teams + type: teams + teams_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "teams" + - result.contact_point.name == "teams" + - result.contact_point.type == "teams" + +- name: Update teams contact point + register: result + community.grafana.grafana_contact_point: + uid: teams + name: teams + type: teams + teams_url: https://example-update.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "teams" + - result.contact_point.name == "teams" + - result.contact_point.type == "teams" + - result.diff is defined + +- name: Delete teams contact point + register: result + community.grafana.grafana_contact_point: + uid: teams + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "teams" + +- name: Delete teams contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: teams + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/telegram.yml b/tests/integration/targets/grafana_contact_point/tasks/telegram.yml new file mode 100644 index 00000000..1ff7191b --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/telegram.yml @@ -0,0 +1,90 @@ +--- +- name: Create telegram contact point + register: result + community.grafana.grafana_contact_point: + uid: telegram + name: telegram + type: telegram + telegram_token: xxx + telegram_chat_id: yyy + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "telegram" + - result.contact_point.name == "telegram" + - result.contact_point.type == "telegram" + +- name: Create telegram contact point + register: result + community.grafana.grafana_contact_point: + uid: telegram + name: telegram + type: telegram + telegram_token: xxx + telegram_chat_id: yyy + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "telegram" + - result.contact_point.name == "telegram" + - result.contact_point.type == "telegram" + +- name: Update telegram contact point + register: result + community.grafana.grafana_contact_point: + uid: telegram + name: telegram + type: telegram + telegram_token: xxx-update + telegram_chat_id: yyy-update + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "telegram" + - result.contact_point.name == "telegram" + - result.contact_point.type == "telegram" + - result.diff is defined + +- name: Delete telegram contact point + register: result + community.grafana.grafana_contact_point: + uid: telegram + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "telegram" + +- name: Delete telegram contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: telegram + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/threema.yml b/tests/integration/targets/grafana_contact_point/tasks/threema.yml new file mode 100644 index 00000000..ac406a4e --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/threema.yml @@ -0,0 +1,93 @@ +--- +- name: Create threema contact point + register: result + community.grafana.grafana_contact_point: + uid: threema + name: threema + type: threema + threema_gateway_id: "*xxxxxxx" + threema_recipient_id: yyyyyyyy + threema_api_secret: zzz + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "threema" + - result.contact_point.name == "threema" + - result.contact_point.type == "threema" + +- name: Create threema contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: threema + name: threema + type: threema + threema_gateway_id: xxx + threema_recepient_id: yyy + threema_api_secret: zzz + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "threema" + - result.contact_point.name == "threema" + - result.contact_point.type == "threema" + +- name: Update threema contact point + register: result + community.grafana.grafana_contact_point: + uid: threema + name: threema + type: threema + threema_gateway_id: "*xxxxxxx-update" + threema_recipient_id: yyyyyyyy-update + threema_api_secret: zzz-update + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "threema" + - result.contact_point.name == "threema" + - result.contact_point.type == "threema" + - result.diff is defined + +- name: Delete threema contact point + register: result + community.grafana.grafana_contact_point: + uid: threema + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "threema" + +- name: Delete threema contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: threema + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/victorops.yml b/tests/integration/targets/grafana_contact_point/tasks/victorops.yml new file mode 100644 index 00000000..1ee8c1fa --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/victorops.yml @@ -0,0 +1,87 @@ +--- +- name: Create victorops contact point + register: result + community.grafana.grafana_contact_point: + uid: victorops + name: victorops + type: victorops + victorops_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "victorops" + - result.contact_point.name == "victorops" + - result.contact_point.type == "victorops" + +- name: Create victorops contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: victorops + name: victorops + type: victorops + victorops_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "victorops" + - result.contact_point.name == "victorops" + - result.contact_point.type == "victorops" + +- name: Update victorops contact point + register: result + community.grafana.grafana_contact_point: + uid: victorops + name: victorops + type: victorops + victorops_url: https://example-update.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "victorops" + - result.contact_point.name == "victorops" + - result.contact_point.type == "victorops" + - result.diff is defined + +- name: Delete victorops contact point + register: result + community.grafana.grafana_contact_point: + uid: victorops + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "victorops" + +- name: Delete victorops contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: victorops + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent" diff --git a/tests/integration/targets/grafana_contact_point/tasks/webhook.yml b/tests/integration/targets/grafana_contact_point/tasks/webhook.yml new file mode 100644 index 00000000..29dbc246 --- /dev/null +++ b/tests/integration/targets/grafana_contact_point/tasks/webhook.yml @@ -0,0 +1,87 @@ +--- +- name: Create webhook contact point + register: result + community.grafana.grafana_contact_point: + uid: webhook + name: webhook + type: webhook + webhook_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "webhook" + - result.contact_point.name == "webhook" + - result.contact_point.type == "webhook" + +- name: Create webhook contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: webhook + name: webhook + type: webhook + webhook_url: https://example.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "present" + - result.contact_point.uid == "webhook" + - result.contact_point.name == "webhook" + - result.contact_point.type == "webhook" + +- name: Update webhook contact point + register: result + community.grafana.grafana_contact_point: + uid: webhook + name: webhook + type: webhook + webhook_url: https://example-update.org + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "present" + - result.contact_point.uid == "webhook" + - result.contact_point.name == "webhook" + - result.contact_point.type == "webhook" + - result.diff is defined + +- name: Delete webhook contact point + register: result + community.grafana.grafana_contact_point: + uid: webhook + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - result.changed + - result.state == "absent" + - result.contact_point.uid == "webhook" + +- name: Delete webhook contact point (idempotency) + register: result + community.grafana.grafana_contact_point: + uid: webhook + state: absent + +- ansible.builtin.debug: + var: result + +- ansible.builtin.assert: + that: + - not result.changed + - result.state == "absent"