From 7547432236c77088fb04db1d24e1dab973e88483 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 09:47:23 +0200
Subject: [PATCH 001/120] docs: role readme org_id and org_name
---
roles/grafana/README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/roles/grafana/README.md b/roles/grafana/README.md
index f76e687f..b26a9044 100644
--- a/roles/grafana/README.md
+++ b/roles/grafana/README.md
@@ -168,6 +168,8 @@ Configure Grafana organizations, dashboards, folders, datasources, teams and use
| created_by | yes |
| ends_at | yes |
| matchers | yes |
+| org_id | no |
+| org_name | no |
| starts_at | yes |
| state | no |
From 8ce66da0e0d5e455bdeac5428df9e3c804ab1fda Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 09:48:06 +0200
Subject: [PATCH 002/120] feat: role task org_id and org_name
---
roles/grafana/tasks/main.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/roles/grafana/tasks/main.yml b/roles/grafana/tasks/main.yml
index 1665a856..f5e41021 100644
--- a/roles/grafana/tasks/main.yml
+++ b/roles/grafana/tasks/main.yml
@@ -206,9 +206,11 @@
community.grafana.grafana_silence:
comment: "{{ silence.comment }}"
created_by: "{{ silence.created_by }}"
- starts_at: "{{ silence.starts_at }}"
ends_at: "{{ silence.ends_at }}"
matchers: "{{ silence.matchers }}"
+ org_id: "{{ datasource.org_id | default(omit) }}"
+ org_name: "{{ datasource.org_name | default(omit) }}"
+ starts_at: "{{ silence.starts_at }}"
state: "{{ silence.state | default(omit) }}"
loop: "{{ grafana_silences }}"
loop_control: {loop_var: silence}
From 9d88bb0df548d1843670fe59651e578bdf57ccea Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 09:48:41 +0200
Subject: [PATCH 003/120] docs: module args org_id and org_name
---
plugins/modules/grafana_silence.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/plugins/modules/grafana_silence.py b/plugins/modules/grafana_silence.py
index 35f54a3d..2b2897cb 100644
--- a/plugins/modules/grafana_silence.py
+++ b/plugins/modules/grafana_silence.py
@@ -30,6 +30,18 @@
requirements:
- The Alertmanager API is only available starting Grafana 8 and the module will fail if the server version is lower than version 8.
options:
+ org_id:
+ description:
+ - The Grafana organization ID where the silence will be created or deleted.
+ - Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organization.
+ - Mutually exclusive with C(org_name).
+ default: 1
+ type: int
+ org_name:
+ description:
+ - The Grafana organization name where the silence will be created or deleted.
+ - Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organization.
+ - Mutually exclusive with C(org_id).
comment:
description:
- The comment that describes the silence.
From 213f3fd6343db811b449a2c8092ca48d4a6bae9f Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 09:49:56 +0200
Subject: [PATCH 004/120] feat: class init switch org
---
plugins/modules/grafana_silence.py | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/plugins/modules/grafana_silence.py b/plugins/modules/grafana_silence.py
index 2b2897cb..19932be9 100644
--- a/plugins/modules/grafana_silence.py
+++ b/plugins/modules/grafana_silence.py
@@ -193,9 +193,10 @@ class GrafanaError(Exception):
class GrafanaSilenceInterface(object):
def __init__(self, module):
self._module = module
+ self.grafana_url = base.clean_url(module.params.get("url"))
+ self.org_id = None
# {{{ Authentication header
self.headers = {"Content-Type": "application/json"}
- module.params["force_basic_auth"] = True
if module.params.get("grafana_api_key", None):
self.headers["Authorization"] = (
"Bearer %s" % module.params["grafana_api_key"]
@@ -204,8 +205,14 @@ def __init__(self, module):
self.headers["Authorization"] = basic_auth_header(
module.params["url_username"], module.params["url_password"]
)
+ self.org_id = (
+ self.organization_by_name(module.params["org_name"])
+ if module.params["org_name"]
+ else module.params["org_id"]
+ )
+ self.switch_organization(self.org_id)
# }}}
- self.grafana_url = base.clean_url(module.params.get("url"))
+
if module.params.get("skip_version_check") is False:
try:
grafana_version = self.get_version()
From d59bec9153b526dea83a492804ef70e1f83b9689 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 09:50:27 +0200
Subject: [PATCH 005/120] feat: switch org and get org functions
---
plugins/modules/grafana_silence.py | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/plugins/modules/grafana_silence.py b/plugins/modules/grafana_silence.py
index 19932be9..fd8d1701 100644
--- a/plugins/modules/grafana_silence.py
+++ b/plugins/modules/grafana_silence.py
@@ -252,6 +252,21 @@ def _send_request(self, url, data=None, headers=None, method="GET"):
failed=True, msg="Grafana Silences API answered with HTTP %d" % status_code
)
+ def switch_organization(self, org_id):
+ url = "/api/user/using/%d" % org_id
+ self._send_request(url, headers=self.headers, method="POST")
+
+ def organization_by_name(self, org_name):
+ url = "/api/user/orgs"
+ organizations = self._send_request(url, headers=self.headers, method="GET")
+ orga = next((org for org in organizations if org["name"] == org_name))
+ if orga:
+ return orga["orgId"]
+
+ return self._module.fail_json(
+ failed=True, msg="Current user isn't member of organization: %s" % org_name
+ )
+
def get_version(self):
url = "/api/health"
response = self._send_request(
From 0eb1ea58a18351c1654b6636823a14654ca02da8 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 09:50:46 +0200
Subject: [PATCH 006/120] feat: module args
---
plugins/modules/grafana_silence.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/plugins/modules/grafana_silence.py b/plugins/modules/grafana_silence.py
index fd8d1701..53dea9cc 100644
--- a/plugins/modules/grafana_silence.py
+++ b/plugins/modules/grafana_silence.py
@@ -344,23 +344,24 @@ def setup_module_object():
argument_spec = base.grafana_argument_spec()
argument_spec.update(
comment=dict(type="str", required=True),
- state=dict(type="str", choices=["present", "absent"], default="present"),
created_by=dict(type="str", required=True),
- starts_at=dict(type="str", required=True),
ends_at=dict(type="str", required=True),
matchers=dict(type="list", elements="dict", required=True),
+ org_id=dict(default=1, type="int"),
+ org_name=dict(type="str"),
skip_version_check=dict(type="bool", default=False),
+ starts_at=dict(type="str", required=True),
+ state=dict(type="str", choices=["present", "absent"], default="present"),
)
def main():
-
module = setup_module_object()
comment = module.params["comment"]
created_by = module.params["created_by"]
- starts_at = module.params["starts_at"]
ends_at = module.params["ends_at"]
matchers = module.params["matchers"]
+ starts_at = module.params["starts_at"]
state = module.params["state"]
changed = False
@@ -372,7 +373,6 @@ def main():
)
if state == "present":
-
if not silence:
silence = grafana_iface.create_silence(
comment, created_by, starts_at, ends_at, matchers
@@ -396,6 +396,7 @@ def main():
changed=changed,
msg="Silence does not exist",
)
+
module.exit_json(failed=failed, changed=changed, silence=silence)
From f5d059313672c3abab68e83f6119fdf5f769db7e Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 09:53:41 +0200
Subject: [PATCH 007/120] docs: changelog fragment
---
changelogs/fragments/371-silence-org-switch.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 changelogs/fragments/371-silence-org-switch.yml
diff --git a/changelogs/fragments/371-silence-org-switch.yml b/changelogs/fragments/371-silence-org-switch.yml
new file mode 100644
index 00000000..140237ad
--- /dev/null
+++ b/changelogs/fragments/371-silence-org-switch.yml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - add org switch by `org_id` and `org_name` in `grafana_silence`
From c1946f9076b8a9be38f4d6c537accb96fd2344e4 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 10:03:04 +0200
Subject: [PATCH 008/120] test: recode silence tests and add org tests
---
.../grafana_silence/tasks/create-delete.yml | 83 +++++++++++++++++
.../targets/grafana_silence/tasks/main.yml | 91 +------------------
.../targets/grafana_silence/tasks/org.yml | 7 ++
3 files changed, 94 insertions(+), 87 deletions(-)
create mode 100644 tests/integration/targets/grafana_silence/tasks/create-delete.yml
create mode 100644 tests/integration/targets/grafana_silence/tasks/org.yml
diff --git a/tests/integration/targets/grafana_silence/tasks/create-delete.yml b/tests/integration/targets/grafana_silence/tasks/create-delete.yml
new file mode 100644
index 00000000..1561eb59
--- /dev/null
+++ b/tests/integration/targets/grafana_silence/tasks/create-delete.yml
@@ -0,0 +1,83 @@
+---
+- module_defaults:
+ community.grafana.grafana_silence:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ block:
+ - name: Create new silence
+ community.grafana.grafana_silence:
+ comment: "a testcomment"
+ created_by: "me"
+ starts_at: "2029-07-29T08:45:45.000Z"
+ ends_at: "2029-07-29T08:55:45.000Z"
+ matchers:
+ - isEqual: true
+ isRegex: true
+ name: environment
+ value: test
+ state: present
+ register: result
+ - assert:
+ that:
+ - "result.changed == true"
+ - "result.failed == false"
+ - "result.silence.id != ''"
+
+ - name: Check idempotency on silence creation
+ community.grafana.grafana_silence:
+ comment: "a testcomment"
+ created_by: "me"
+ starts_at: "2029-07-29T08:45:45.000Z"
+ ends_at: "2029-07-29T08:55:45.000Z"
+ matchers:
+ - isEqual: true
+ isRegex: true
+ name: environment
+ value: test
+ state: present
+ register: result
+ - assert:
+ that:
+ - "result.changed == false"
+ - "result.msg != ''"
+
+ - name: Delete the silence
+ community.grafana.grafana_silence:
+ comment: "a testcomment"
+ created_by: "me"
+ starts_at: "2029-07-29T08:45:45.000Z"
+ ends_at: "2029-07-29T08:55:45.000Z"
+ matchers:
+ - isEqual: true
+ isRegex: true
+ name: environment
+ value: test
+ state: absent
+ register: result
+ - assert:
+ that:
+ - "result.changed == true"
+ - "result.failed == false"
+ - "result.silence.id != ''"
+ - - "result.silence.createdBy != 'me'"
+
+ - name: Check idempotency on silence deletion
+ community.grafana.grafana_silence:
+ comment: "a testcomment"
+ created_by: "me"
+ starts_at: "2029-07-29T08:45:45.000Z"
+ ends_at: "2029-07-29T08:55:45.000Z"
+ matchers:
+ - isEqual: true
+ isRegex: true
+ name: environment
+ value: test
+ state: absent
+ register: result
+ ignore_errors: yes
+ - assert:
+ that:
+ - "result.changed == false"
+ - "result.failed == false"
+ - "result.msg == 'Silence does not exist'"
diff --git a/tests/integration/targets/grafana_silence/tasks/main.yml b/tests/integration/targets/grafana_silence/tasks/main.yml
index ad4cfa25..f8756077 100644
--- a/tests/integration/targets/grafana_silence/tasks/main.yml
+++ b/tests/integration/targets/grafana_silence/tasks/main.yml
@@ -1,89 +1,6 @@
---
-- name: Create new silence
- community.grafana.grafana_silence:
- url: "{{ grafana_url }}"
- url_username: "{{ grafana_username }}"
- url_password: "{{ grafana_password }}"
- comment: "a testcomment"
- created_by: "me"
- starts_at: "2029-07-29T08:45:45.000Z"
- ends_at: "2029-07-29T08:55:45.000Z"
- matchers:
- - isEqual: true
- isRegex: true
- name: environment
- value: test
- state: present
- register: result
-- assert:
- that:
- - "result.changed == true"
- - "result.failed == false"
- - "result.silence.id != ''"
+- name: Silence creation and deletion
+ ansible.builtin.include_tasks: create-delete.yml
-- name: Check idempotency on silence creation
- community.grafana.grafana_silence:
- url: "{{ grafana_url }}"
- url_username: "{{ grafana_username }}"
- url_password: "{{ grafana_password }}"
- comment: "a testcomment"
- created_by: "me"
- starts_at: "2029-07-29T08:45:45.000Z"
- ends_at: "2029-07-29T08:55:45.000Z"
- matchers:
- - isEqual: true
- isRegex: true
- name: environment
- value: test
- state: present
- register: result
-- assert:
- that:
- - "result.changed == false"
- - "result.msg != ''"
-
-- name: Delete the silence
- community.grafana.grafana_silence:
- url: "{{ grafana_url }}"
- url_username: "{{ grafana_username }}"
- url_password: "{{ grafana_password }}"
- comment: "a testcomment"
- created_by: "me"
- starts_at: "2029-07-29T08:45:45.000Z"
- ends_at: "2029-07-29T08:55:45.000Z"
- matchers:
- - isEqual: true
- isRegex: true
- name: environment
- value: test
- state: absent
- register: result
-- assert:
- that:
- - "result.changed == true"
- - "result.failed == false"
- - "result.silence.id != ''"
- - - "result.silence.createdBy != 'me'"
-
-- name: Check idempotency on silence deletion
- community.grafana.grafana_silence:
- url: "{{ grafana_url }}"
- url_username: "{{ grafana_username }}"
- url_password: "{{ grafana_password }}"
- comment: "a testcomment"
- created_by: "me"
- starts_at: "2029-07-29T08:45:45.000Z"
- ends_at: "2029-07-29T08:55:45.000Z"
- matchers:
- - isEqual: true
- isRegex: true
- name: environment
- value: test
- state: absent
- register: result
- ignore_errors: yes
-- assert:
- that:
- - "result.changed == false"
- - "result.failed == false"
- - "result.msg == 'Silence does not exist'"
\ No newline at end of file
+- name: Silence creation and deletion for organization
+ ansible.builtin.include_tasks: org.yml
diff --git a/tests/integration/targets/grafana_silence/tasks/org.yml b/tests/integration/targets/grafana_silence/tasks/org.yml
new file mode 100644
index 00000000..514232f9
--- /dev/null
+++ b/tests/integration/targets/grafana_silence/tasks/org.yml
@@ -0,0 +1,7 @@
+---
+- module_defaults:
+ community.grafana.grafana_silence:
+ org_name: Main Org.
+ block:
+ - name: Silence creation and deletion
+ ansible.builtin.include_tasks: create-delete.yml
From 747034109bd0a6853331c604875c708c794ec42b Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 10:09:09 +0200
Subject: [PATCH 009/120] docs: org name type
---
plugins/modules/grafana_silence.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/plugins/modules/grafana_silence.py b/plugins/modules/grafana_silence.py
index 53dea9cc..7d0421ec 100644
--- a/plugins/modules/grafana_silence.py
+++ b/plugins/modules/grafana_silence.py
@@ -42,6 +42,7 @@
- The Grafana organization name where the silence will be created or deleted.
- Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organization.
- Mutually exclusive with C(org_id).
+ type: str
comment:
description:
- The comment that describes the silence.
From 2a031d0e91dd2403fb5b63addee0fa8926ae704d Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 10:24:45 +0200
Subject: [PATCH 010/120] test: mock test called once with to with
---
.../modules/grafana/grafana_silence/test_grafana_silence.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/unit/modules/grafana/grafana_silence/test_grafana_silence.py b/tests/unit/modules/grafana/grafana_silence/test_grafana_silence.py
index 96522c2a..c2bb1df3 100644
--- a/tests/unit/modules/grafana/grafana_silence/test_grafana_silence.py
+++ b/tests/unit/modules/grafana/grafana_silence/test_grafana_silence.py
@@ -136,7 +136,7 @@ def test_create_silence_new_silence(
}
],
)
- mock_fetch_url.assert_called_once_with(
+ mock_fetch_url.assert_called_with(
module,
"https://grafana.example.com/api/alertmanager/grafana/api/v2/silences",
data=json.dumps(
@@ -198,7 +198,7 @@ def test_delete_silence(self, mock_fetch_url, mock_get_version):
grafana_iface = grafana_silence.GrafanaSilenceInterface(module)
silence_id = "470b7116-8f06-4bb6-9e6c-6258aa92218e"
result = grafana_iface.delete_silence(silence_id)
- mock_fetch_url.assert_called_once_with(
+ mock_fetch_url.assert_called_with(
module,
"https://grafana.example.com/api/alertmanager/grafana/api/v2/silence/470b7116-8f06-4bb6-9e6c-6258aa92218e",
data=None,
From 1aca3d8159aa8e7ebc10f903fbd9b81361cbab0d Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 11 Apr 2024 10:32:30 +0200
Subject: [PATCH 011/120] fix: remove message argument
---
plugins/modules/grafana_dashboard.py | 17 +----------------
1 file changed, 1 insertion(+), 16 deletions(-)
diff --git a/plugins/modules/grafana_dashboard.py b/plugins/modules/grafana_dashboard.py
index 77a5a756..60cd5b86 100644
--- a/plugins/modules/grafana_dashboard.py
+++ b/plugins/modules/grafana_dashboard.py
@@ -81,8 +81,6 @@
description:
- Set a commit message for the version history.
- Only used when C(state) is C(present).
- - C(message) alias is deprecated in Ansible 2.10, since it is used internally by Ansible Core Engine.
- aliases: [ 'message' ]
type: str
extends_documentation_fragment:
- community.grafana.basic_auth
@@ -620,15 +618,7 @@ def main():
dashboard_id=dict(type="str"),
dashboard_revision=dict(type="str", default="1"),
overwrite=dict(type="bool", default=False),
- commit_message=dict(
- type="str",
- aliases=["message"],
- deprecated_aliases=[
- dict(
- name="message", version="2.0.0", collection_name="community.grafana"
- )
- ],
- ),
+ commit_message=dict(type="str"),
)
module = AnsibleModule(
argument_spec=argument_spec,
@@ -647,11 +637,6 @@ def main():
module.params["url"] = clean_url(module.params["url"])
- if "message" in module.params:
- module.fail_json(
- msg="'message' is reserved keyword, please change this parameter to 'commit_message'"
- )
-
try:
if module.params["state"] == "present":
result = grafana_create_dashboard(module, module.params)
From 3ea35d0de8358216f181322fda61760a17d4029a Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 13:01:06 +0200
Subject: [PATCH 012/120] docs: changelog fragment
---
changelogs/fragments/372-rm-dashboard-message-argument.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 changelogs/fragments/372-rm-dashboard-message-argument.yml
diff --git a/changelogs/fragments/372-rm-dashboard-message-argument.yml b/changelogs/fragments/372-rm-dashboard-message-argument.yml
new file mode 100644
index 00000000..3f54afa5
--- /dev/null
+++ b/changelogs/fragments/372-rm-dashboard-message-argument.yml
@@ -0,0 +1,3 @@
+---
+removed_features:
+ - removed deprecated `message` argument in `grafana_dashboard`
From 9874869c6ae126829b02b5a06ee4583df052f512 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 13:21:17 +0200
Subject: [PATCH 013/120] ci: remove sanity ignore files active tested versions
---
tests/sanity/ignore-2.15.txt | 1 -
tests/sanity/ignore-2.16.txt | 1 -
tests/sanity/ignore-2.17.txt | 4 ----
3 files changed, 6 deletions(-)
delete mode 100644 tests/sanity/ignore-2.15.txt
delete mode 100644 tests/sanity/ignore-2.16.txt
delete mode 100644 tests/sanity/ignore-2.17.txt
diff --git a/tests/sanity/ignore-2.15.txt b/tests/sanity/ignore-2.15.txt
deleted file mode 100644
index 0a40a23d..00000000
--- a/tests/sanity/ignore-2.15.txt
+++ /dev/null
@@ -1 +0,0 @@
-plugins/modules/grafana_dashboard.py validate-modules:invalid-argument-name
diff --git a/tests/sanity/ignore-2.16.txt b/tests/sanity/ignore-2.16.txt
deleted file mode 100644
index 0a40a23d..00000000
--- a/tests/sanity/ignore-2.16.txt
+++ /dev/null
@@ -1 +0,0 @@
-plugins/modules/grafana_dashboard.py validate-modules:invalid-argument-name
diff --git a/tests/sanity/ignore-2.17.txt b/tests/sanity/ignore-2.17.txt
deleted file mode 100644
index 5c82494f..00000000
--- a/tests/sanity/ignore-2.17.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-plugins/modules/grafana_dashboard.py validate-modules:invalid-argument-name
-tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py pep8:W291
-hacking/check_fragment.sh shebang
-hacking/find_grafana_versions.py shebang
From 125308ef45f5998633364c19e84cbf628b7403b5 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 13:25:55 +0200
Subject: [PATCH 014/120] ci: remove sanity ignore files active tested versions
---
tests/sanity/ignore-2.18.txt | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 tests/sanity/ignore-2.18.txt
diff --git a/tests/sanity/ignore-2.18.txt b/tests/sanity/ignore-2.18.txt
deleted file mode 100644
index 0a40a23d..00000000
--- a/tests/sanity/ignore-2.18.txt
+++ /dev/null
@@ -1 +0,0 @@
-plugins/modules/grafana_dashboard.py validate-modules:invalid-argument-name
From 31876c1c0a16f0f5cd65925d811689841f5016fb Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 13:22:40 +0200
Subject: [PATCH 015/120] test: remove all sanity ignore files
---
tests/sanity/ignore-2.10.txt | 4 ----
tests/sanity/ignore-2.11.txt | 6 ------
tests/sanity/ignore-2.12.txt | 4 ----
tests/sanity/ignore-2.13.txt | 4 ----
tests/sanity/ignore-2.14.txt | 4 ----
tests/sanity/ignore-2.9.txt | 3 ---
6 files changed, 25 deletions(-)
delete mode 100644 tests/sanity/ignore-2.10.txt
delete mode 100644 tests/sanity/ignore-2.11.txt
delete mode 100644 tests/sanity/ignore-2.12.txt
delete mode 100644 tests/sanity/ignore-2.13.txt
delete mode 100644 tests/sanity/ignore-2.14.txt
delete mode 100644 tests/sanity/ignore-2.9.txt
diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt
deleted file mode 100644
index 5c82494f..00000000
--- a/tests/sanity/ignore-2.10.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-plugins/modules/grafana_dashboard.py validate-modules:invalid-argument-name
-tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py pep8:W291
-hacking/check_fragment.sh shebang
-hacking/find_grafana_versions.py shebang
diff --git a/tests/sanity/ignore-2.11.txt b/tests/sanity/ignore-2.11.txt
deleted file mode 100644
index 68cb96ab..00000000
--- a/tests/sanity/ignore-2.11.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-plugins/modules/grafana_dashboard.py validate-modules:invalid-argument-name
-tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py pep8:W291
-hacking/check_fragment.sh shebang
-hacking/find_grafana_versions.py shebang
-hacking/find_grafana_versions.py future-import-boilerplate!skip
-hacking/find_grafana_versions.py metaclass-boilerplate!skip
diff --git a/tests/sanity/ignore-2.12.txt b/tests/sanity/ignore-2.12.txt
deleted file mode 100644
index 5c82494f..00000000
--- a/tests/sanity/ignore-2.12.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-plugins/modules/grafana_dashboard.py validate-modules:invalid-argument-name
-tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py pep8:W291
-hacking/check_fragment.sh shebang
-hacking/find_grafana_versions.py shebang
diff --git a/tests/sanity/ignore-2.13.txt b/tests/sanity/ignore-2.13.txt
deleted file mode 100644
index 5c82494f..00000000
--- a/tests/sanity/ignore-2.13.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-plugins/modules/grafana_dashboard.py validate-modules:invalid-argument-name
-tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py pep8:W291
-hacking/check_fragment.sh shebang
-hacking/find_grafana_versions.py shebang
diff --git a/tests/sanity/ignore-2.14.txt b/tests/sanity/ignore-2.14.txt
deleted file mode 100644
index 5c82494f..00000000
--- a/tests/sanity/ignore-2.14.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-plugins/modules/grafana_dashboard.py validate-modules:invalid-argument-name
-tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py pep8:W291
-hacking/check_fragment.sh shebang
-hacking/find_grafana_versions.py shebang
diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt
deleted file mode 100644
index 476a7a42..00000000
--- a/tests/sanity/ignore-2.9.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py pep8:W291
-hacking/check_fragment.sh shebang
-hacking/find_grafana_versions.py shebang
From 3a2f6de470d3f80887141745e73772a9cd332eae Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 13:23:48 +0200
Subject: [PATCH 016/120] ci: bump python to 3.12
---
.github/workflows/ansible-test.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml
index f32caf98..acf315dc 100644
--- a/.github/workflows/ansible-test.yml
+++ b/.github/workflows/ansible-test.yml
@@ -12,7 +12,7 @@ jobs:
timeout-minutes: 30
strategy:
matrix:
- python_version: ["3.10"]
+ python_version: ["3.12"]
ansible_version: ["stable-2.15", "stable-2.16", "devel"]
steps:
- name: Perform testing
@@ -29,7 +29,7 @@ jobs:
timeout-minutes: 30
strategy:
matrix:
- python_version: ["3.10"]
+ python_version: ["3.12"]
ansible_version: ["stable-2.15", "stable-2.16", "devel"]
steps:
- name: Perform testing
@@ -47,7 +47,7 @@ jobs:
matrix:
grafana_version: ["8.5.27", "9.5.19", "10.4.3"]
ansible_version: ["stable-2.15", "stable-2.16", "devel"]
- python_version: ["3.10"]
+ python_version: ["3.12"]
services:
grafana:
image: grafana/grafana:${{ matrix.grafana_version }}
@@ -69,7 +69,7 @@ jobs:
matrix:
grafana_version: ["8.5.27", "9.5.19", "10.4.3"]
ansible_version: ["stable-2.15", "stable-2.16", "devel"]
- python_version: ["3.10"]
+ python_version: ["3.12"]
services:
grafana:
image: grafana/grafana:${{ matrix.grafana_version }}
From 211d32474e9cbe3fc6d143db153fd08dde24e1fa Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 13:28:35 +0200
Subject: [PATCH 017/120] docs: changelog fragment
---
changelogs/fragments/373-cleanup-and-update-sanity.yml | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 changelogs/fragments/373-cleanup-and-update-sanity.yml
diff --git a/changelogs/fragments/373-cleanup-and-update-sanity.yml b/changelogs/fragments/373-cleanup-and-update-sanity.yml
new file mode 100644
index 00000000..c20a1253
--- /dev/null
+++ b/changelogs/fragments/373-cleanup-and-update-sanity.yml
@@ -0,0 +1,4 @@
+---
+trivial:
+ - bump python to 3.12 in ansible tests
+ - remove sanity ignore files
From 0498790af53fe658943d1d9c9a5fbfe990a3537d Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 13:39:43 +0200
Subject: [PATCH 018/120] ci: python to 3.11
---
.github/workflows/ansible-test.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml
index acf315dc..58405817 100644
--- a/.github/workflows/ansible-test.yml
+++ b/.github/workflows/ansible-test.yml
@@ -12,7 +12,7 @@ jobs:
timeout-minutes: 30
strategy:
matrix:
- python_version: ["3.12"]
+ python_version: ["3.11"]
ansible_version: ["stable-2.15", "stable-2.16", "devel"]
steps:
- name: Perform testing
@@ -29,7 +29,7 @@ jobs:
timeout-minutes: 30
strategy:
matrix:
- python_version: ["3.12"]
+ python_version: ["3.11"]
ansible_version: ["stable-2.15", "stable-2.16", "devel"]
steps:
- name: Perform testing
@@ -47,7 +47,7 @@ jobs:
matrix:
grafana_version: ["8.5.27", "9.5.19", "10.4.3"]
ansible_version: ["stable-2.15", "stable-2.16", "devel"]
- python_version: ["3.12"]
+ python_version: ["3.11"]
services:
grafana:
image: grafana/grafana:${{ matrix.grafana_version }}
@@ -69,7 +69,7 @@ jobs:
matrix:
grafana_version: ["8.5.27", "9.5.19", "10.4.3"]
ansible_version: ["stable-2.15", "stable-2.16", "devel"]
- python_version: ["3.12"]
+ python_version: ["3.11"]
services:
grafana:
image: grafana/grafana:${{ matrix.grafana_version }}
From 849f4dfc448f5b837e512077bce7e14cbf4bb62e Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 13:40:05 +0200
Subject: [PATCH 019/120] docs: update fragment
---
changelogs/fragments/373-cleanup-and-update-sanity.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/changelogs/fragments/373-cleanup-and-update-sanity.yml b/changelogs/fragments/373-cleanup-and-update-sanity.yml
index c20a1253..e5236485 100644
--- a/changelogs/fragments/373-cleanup-and-update-sanity.yml
+++ b/changelogs/fragments/373-cleanup-and-update-sanity.yml
@@ -1,4 +1,4 @@
---
trivial:
- - bump python to 3.12 in ansible tests
+ - bump python to 3.11 in ansible tests
- remove sanity ignore files
From 3f91a7e81a57e7e4e39c362c371176d8db740372 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 26 Feb 2024 13:45:58 +0100
Subject: [PATCH 020/120] feat: switc org by name
---
.../modules/grafana_notification_channel.py | 34 ++++++++++++++++---
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index 30b5b112..4fcf646c 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -611,6 +611,7 @@ def grafana_notification_channel_payload(data):
class GrafanaNotificationChannelInterface(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):
@@ -621,13 +622,18 @@ def __init__(self, module):
self.headers["Authorization"] = basic_auth_header(
module.params["url_username"], module.params["url_password"]
)
+ self.org_id = (
+ self.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.grafana_url = clean_url(module.params.get("url"))
- def grafana_switch_organisation(self, grafana_url, org_id):
+ def grafana_switch_organisation(self, data, org_id):
r, info = fetch_url(
self._module,
- "%s/api/user/using/%s" % (grafana_url, org_id),
+ "%s/api/user/using/%s" % (data["url"], org_id),
headers=self.headers,
method="POST",
)
@@ -636,6 +642,22 @@ def grafana_switch_organisation(self, grafana_url, org_id):
"Unable to switch to organization %s : %s" % (org_id, info)
)
+ def 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_create_notification_channel(self, data, payload):
r, info = fetch_url(
self._module,
@@ -729,6 +751,7 @@ def main():
argument_spec = grafana_argument_spec()
argument_spec.update(
org_id=dict(type="int", default=1),
+ org_name=dict(type="str"),
uid=dict(type="str"),
name=dict(type="str"),
type=dict(
@@ -797,8 +820,8 @@ def main():
elements="str",
choices=["emergency", "high", "normal", "low", "lowest"],
),
- pushover_retry=dict(type="int"), # TODO: only when priority==emergency
- pushover_expire=dict(type="int"), # TODO: only when priority==emergency
+ pushover_retry=dict(type="int"),
+ pushover_expire=dict(type="int"),
pushover_alert_sound=dict(type="str"), # TODO: add sound choices
pushover_ok_sound=dict(type="str"), # TODO: add sound choices
sensu_url=dict(type="str"),
@@ -863,6 +886,7 @@ def main():
],
["type", "victorops", ["victorops_url"]],
["type", "webhook", ["webhook_url"]],
+ ["pushover_priority", "emergency", ["pushover_retry", "pushover_expire"]],
],
)
From a393b26ffd6b6cdc921a5de9b6d23e615c6b87d9 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 26 Feb 2024 13:49:24 +0100
Subject: [PATCH 021/120] feat: check if unified grafana is enabled
---
.../modules/grafana_notification_channel.py | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index 4fcf646c..8faf2d6b 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -629,6 +629,26 @@ def __init__(self, module):
)
self.grafana_switch_organisation(module.params, self.org_id)
# }}}
+ self.grafana_check_unified_alerting(module.params)
+
+ def grafana_check_unified_alerting(self, data):
+ self.grafana_unified_alerting = None
+ r, info = fetch_url(
+ self._module,
+ "%s/api/frontend/settings" % data["url"],
+ headers=self.headers,
+ method="GET",
+ )
+ if info["status"] == 200:
+ try:
+ settings = json.loads(to_text(r.read()))
+ self.grafana_unified_alerting = settings["unifiedAlertingEnabled"]
+ except UnicodeError:
+ raise GrafanaAPIException("Unable to decode version string to Unicode")
+ except Exception as e:
+ raise GrafanaAPIException(e)
+ else:
+ raise GrafanaAPIException("Unable to get grafana version: %s" % info)
def grafana_switch_organisation(self, data, org_id):
r, info = fetch_url(
From e5de86a4c55282a16cc4ebbe2e53a71fc1cbde9e Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 26 Feb 2024 13:53:05 +0100
Subject: [PATCH 022/120] docs: org id description
---
plugins/modules/grafana_notification_channel.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index 8faf2d6b..d30069c4 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -36,7 +36,7 @@
options:
org_id:
description:
- - The Grafana Organisation ID where the dashboard will be imported / exported.
+ - The Grafana Organisation ID where the notification channel will be handled.
- Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organisation..
default: 1
type: int
From 37db4425bc8f70dc7201fee63f5ef355e71d812c Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 26 Feb 2024 13:56:36 +0100
Subject: [PATCH 023/120] docs: added org_name description
---
plugins/modules/grafana_notification_channel.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index d30069c4..504b9ac2 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -38,8 +38,15 @@
description:
- The Grafana Organisation ID where the notification channel will be handled.
- Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organisation..
+ - Mutually exclusive with C(org_name).
default: 1
type: int
+ org_name:
+ description:
+ - The Grafana Organisation name where the notification channel will be handled.
+ - Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organisation..
+ - Mutually exclusive with C(org_id).
+ type: str
state:
type: str
default: present
From 56d38490a8fc970d3c8753c22695d616fb9d8796 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 26 Feb 2024 15:05:06 +0100
Subject: [PATCH 024/120] feat: url and exception toggle for api handling
---
.../modules/grafana_notification_channel.py | 62 ++++++++++++++-----
1 file changed, 47 insertions(+), 15 deletions(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index 504b9ac2..e7098d9b 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -630,13 +630,16 @@ def __init__(self, module):
module.params["url_username"], module.params["url_password"]
)
self.org_id = (
- self.organization_by_name(module.params["org_name"])
+ 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.grafana_check_unified_alerting(module.params)
+ self.endpoint_type = (
+ "contact point" if self.grafana_unified_alerting else "notification channel"
+ )
def grafana_check_unified_alerting(self, data):
self.grafana_unified_alerting = None
@@ -669,7 +672,7 @@ def grafana_switch_organisation(self, data, org_id):
"Unable to switch to organization %s : %s" % (org_id, info)
)
- def organization_by_name(self, data, org_name):
+ def grafana_organization_by_name(self, data, org_name):
r, info = fetch_url(
self._module,
"%s/api/user/orgs" % data["url"],
@@ -686,28 +689,45 @@ def organization_by_name(self, data, org_name):
)
def grafana_create_notification_channel(self, data, payload):
+ url = (
+ "%s/api/v1/provisioning/contact-points"
+ if self.grafana_unified_alerting
+ else "%s/api/alert-notifications"
+ )
r, info = fetch_url(
self._module,
- "%s/api/alert-notifications" % data["url"],
+ url % data["url"],
data=json.dumps(payload),
headers=self.headers,
method="POST",
)
if info["status"] == 200:
- return {
- "state": "present",
- "changed": True,
- "channel": json.loads(to_text(r.read())),
- }
+ if self.grafana_unified_alerting:
+ return {
+ "state": "present",
+ "changed": True,
+ "contact-point": json.loads(to_text(r.read())),
+ }
+ else:
+ return {
+ "state": "present",
+ "changed": True,
+ "channel": json.loads(to_text(r.read())),
+ }
else:
raise GrafanaAPIException(
- "Unable to create notification channel: %s" % info
+ "Unable to create %s: %s" % (self.endpoint_type, info)
)
def grafana_update_notification_channel(self, data, payload, before):
+ url = (
+ "%s/api/v1/provisioning/contact-points/%s"
+ if self.grafana_unified_alerting
+ else "%s/api/alert-notifications/uid/%s"
+ )
r, info = fetch_url(
self._module,
- "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"]),
+ url % (data["url"], data["uid"]),
data=json.dumps(payload),
headers=self.headers,
method="PUT",
@@ -737,15 +757,22 @@ def grafana_update_notification_channel(self, data, payload, before):
}
else:
raise GrafanaAPIException(
- "Unable to update notification channel %s : %s" % (data["uid"], info)
+ "Unable to update %s %s : %s" % (self.endpoint_type, data["uid"], info)
)
def grafana_create_or_update_notification_channel(self, data):
payload = grafana_notification_channel_payload(data)
+ url = (
+ "%s/api/v1/provisioning/contact-points" % data["url"]
+ if self.grafana_unified_alerting
+ else "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"])
+ )
r, info = fetch_url(
self._module,
- "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"]),
+ url,
+ data=json.dumps(payload),
headers=self.headers,
+ method="GET",
)
if info["status"] == 200:
before = json.loads(to_text(r.read()))
@@ -754,13 +781,18 @@ def grafana_create_or_update_notification_channel(self, data):
return self.grafana_create_notification_channel(data, payload)
else:
raise GrafanaAPIException(
- "Unable to get notification channel %s : %s" % (data["uid"], info)
+ "Unable to get %s %s : %s" % (self.endpoint_type, data["uid"], info)
)
def grafana_delete_notification_channel(self, data):
+ url = (
+ "%s/api/v1/provisioning/contact-points/%s"
+ if self.grafana_unified_alerting
+ else "%s/api/alert-notifications/uid/%s"
+ )
r, info = fetch_url(
self._module,
- "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"]),
+ url % (data["url"], data["uid"]),
headers=self.headers,
method="DELETE",
)
@@ -770,7 +802,7 @@ def grafana_delete_notification_channel(self, data):
return {"changed": False}
else:
raise GrafanaAPIException(
- "Unable to delete notification channel %s : %s" % (data["uid"], info)
+ "Unable to delete %s %s : %s" % (self.endpoint_type, data["uid"], info)
)
From 2fcd37608809358a60e9e56a20db945b509b5ecb Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 27 Feb 2024 16:18:18 +0100
Subject: [PATCH 025/120] fix: create or update function
---
plugins/modules/grafana_notification_channel.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index e7098d9b..e1f7c44e 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -431,6 +431,7 @@
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.module_utils.six.moves.urllib.parse import quote
from ansible_collections.community.grafana.plugins.module_utils.base import (
grafana_argument_spec,
clean_url,
@@ -763,7 +764,7 @@ def grafana_update_notification_channel(self, data, payload, before):
def grafana_create_or_update_notification_channel(self, data):
payload = grafana_notification_channel_payload(data)
url = (
- "%s/api/v1/provisioning/contact-points" % data["url"]
+ "%s/api/v1/provisioning/contact-points?name=%s" % (data["url"], quote(data["name"]))
if self.grafana_unified_alerting
else "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"])
)
@@ -774,10 +775,10 @@ def grafana_create_or_update_notification_channel(self, data):
headers=self.headers,
method="GET",
)
- if info["status"] == 200:
- before = json.loads(to_text(r.read()))
+ before = json.loads(to_text(r.read()))
+ if info["status"] == 200 and before != None:
return self.grafana_update_notification_channel(data, payload, before)
- elif info["status"] == 404:
+ elif info["status"] == 404 or before == None:
return self.grafana_create_notification_channel(data, payload)
else:
raise GrafanaAPIException(
From 792e07008927780c975d7bdb6f3ed8f4b416d9ba Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 27 Feb 2024 17:01:13 +0100
Subject: [PATCH 026/120] fix: delete contact points logic
---
.../modules/grafana_notification_channel.py | 28 ++++++++++---------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index e1f7c44e..9d6c4515 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -764,7 +764,8 @@ def grafana_update_notification_channel(self, data, payload, before):
def grafana_create_or_update_notification_channel(self, data):
payload = grafana_notification_channel_payload(data)
url = (
- "%s/api/v1/provisioning/contact-points?name=%s" % (data["url"], quote(data["name"]))
+ "%s/api/v1/provisioning/contact-points?name=%s"
+ % (data["url"], quote(data["name"]))
if self.grafana_unified_alerting
else "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"])
)
@@ -777,9 +778,14 @@ def grafana_create_or_update_notification_channel(self, data):
)
before = json.loads(to_text(r.read()))
if info["status"] == 200 and before != None:
- return self.grafana_update_notification_channel(data, payload, before)
- elif info["status"] == 404 or before == None:
+ if data["state"] == "present":
+ return self.grafana_update_notification_channel(data, payload, before)
+ else:
+ return self.grafana_delete_notification_channel(data)
+ elif info["status"] == 404 or (before == None and data["state"] == "present"):
return self.grafana_create_notification_channel(data, payload)
+ elif info["status"] == 200 and before == None and data["state"] == "absent":
+ return {"changed": False}
else:
raise GrafanaAPIException(
"Unable to get %s %s : %s" % (self.endpoint_type, data["uid"], info)
@@ -797,7 +803,7 @@ def grafana_delete_notification_channel(self, data):
headers=self.headers,
method="DELETE",
)
- if info["status"] == 200:
+ if info["status"] == 200 or info["status"] == 202:
return {"state": "absent", "changed": True}
elif info["status"] == 404:
return {"changed": False}
@@ -951,16 +957,12 @@ def main():
)
module.params["url"] = clean_url(module.params["url"])
- alert_channel_iface = GrafanaNotificationChannelInterface(module)
- if module.params["state"] == "present":
- result = alert_channel_iface.grafana_create_or_update_notification_channel(
- module.params
- )
- module.exit_json(failed=False, **result)
- else:
- result = alert_channel_iface.grafana_delete_notification_channel(module.params)
- module.exit_json(failed=False, **result)
+ alert_channel_iface = GrafanaNotificationChannelInterface(module)
+ result = alert_channel_iface.grafana_create_or_update_notification_channel(
+ module.params
+ )
+ module.exit_json(failed=False, **result)
if __name__ == "__main__":
From 7a9bfd5ea406af20b9ad14cde4fdf51edcce86da Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 27 Feb 2024 17:10:14 +0100
Subject: [PATCH 027/120] chore: format
---
.../modules/grafana_notification_channel.py | 34 ++++++++++---------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index 9d6c4515..c6d3287b 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -721,18 +721,21 @@ def grafana_create_notification_channel(self, data, payload):
)
def grafana_update_notification_channel(self, data, payload, before):
- url = (
+ url_template = (
"%s/api/v1/provisioning/contact-points/%s"
if self.grafana_unified_alerting
else "%s/api/alert-notifications/uid/%s"
)
+ url = url_template % (data["url"], data["uid"])
+
r, info = fetch_url(
self._module,
- url % (data["url"], data["uid"]),
+ url,
data=json.dumps(payload),
headers=self.headers,
method="PUT",
)
+
if info["status"] == 200:
del before["created"]
del before["updated"]
@@ -742,18 +745,12 @@ def grafana_update_notification_channel(self, data, payload, before):
del after["created"]
del after["updated"]
- if before == after:
- return {
- "changed": False,
- "channel": channel,
- }
+ if before == channel:
+ return {"changed": False, "channel": channel}
else:
return {
"changed": True,
- "diff": {
- "before": before,
- "after": after,
- },
+ "diff": {"before": before, "after": after},
"channel": channel,
}
else:
@@ -769,6 +766,7 @@ def grafana_create_or_update_notification_channel(self, data):
if self.grafana_unified_alerting
else "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"])
)
+
r, info = fetch_url(
self._module,
url,
@@ -776,15 +774,16 @@ def grafana_create_or_update_notification_channel(self, data):
headers=self.headers,
method="GET",
)
+
before = json.loads(to_text(r.read()))
- if info["status"] == 200 and before != None:
+ if info["status"] == 200 and before is not None:
if data["state"] == "present":
return self.grafana_update_notification_channel(data, payload, before)
else:
return self.grafana_delete_notification_channel(data)
- elif info["status"] == 404 or (before == None and data["state"] == "present"):
+ elif info["status"] == 404 or (before is None and data["state"] == "present"):
return self.grafana_create_notification_channel(data, payload)
- elif info["status"] == 200 and before == None and data["state"] == "absent":
+ elif info["status"] == 200 and before is None and data["state"] == "absent":
return {"changed": False}
else:
raise GrafanaAPIException(
@@ -792,17 +791,20 @@ def grafana_create_or_update_notification_channel(self, data):
)
def grafana_delete_notification_channel(self, data):
- url = (
+ url_template = (
"%s/api/v1/provisioning/contact-points/%s"
if self.grafana_unified_alerting
else "%s/api/alert-notifications/uid/%s"
)
+ url = url_template % (data["url"], data["uid"])
+
r, info = fetch_url(
self._module,
- url % (data["url"], data["uid"]),
+ url,
headers=self.headers,
method="DELETE",
)
+
if info["status"] == 200 or info["status"] == 202:
return {"state": "absent", "changed": True}
elif info["status"] == 404:
From 4d9e165d144e758e1ba35cab2257871f989ec855 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 28 Feb 2024 14:45:09 +0100
Subject: [PATCH 028/120] refactor: handling of get response
---
.../modules/grafana_notification_channel.py | 63 ++++++++++++-------
1 file changed, 40 insertions(+), 23 deletions(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index c6d3287b..c62c42f7 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -690,31 +690,31 @@ def grafana_organization_by_name(self, data, org_name):
)
def grafana_create_notification_channel(self, data, payload):
- url = (
+ url_template = (
"%s/api/v1/provisioning/contact-points"
if self.grafana_unified_alerting
else "%s/api/alert-notifications"
)
+ url = url_template % data["url"]
+
r, info = fetch_url(
self._module,
- url % data["url"],
+ url,
data=json.dumps(payload),
headers=self.headers,
method="POST",
)
- if info["status"] == 200:
- if self.grafana_unified_alerting:
- return {
- "state": "present",
- "changed": True,
- "contact-point": json.loads(to_text(r.read())),
- }
- else:
- return {
- "state": "present",
- "changed": True,
- "channel": json.loads(to_text(r.read())),
- }
+
+ status = info["status"]
+ channel = json.loads(to_text(r.read()))
+
+ if status in [200, 202]:
+ type_key = "contact-point" if self.grafana_unified_alerting else "channel"
+ return {
+ "state": "present",
+ "changed": True,
+ type_key: channel,
+ }
else:
raise GrafanaAPIException(
"Unable to create %s: %s" % (self.endpoint_type, info)
@@ -736,7 +736,9 @@ def grafana_update_notification_channel(self, data, payload, before):
method="PUT",
)
- if info["status"] == 200:
+ status = info["status"]
+
+ if status == 200:
del before["created"]
del before["updated"]
@@ -753,6 +755,12 @@ def grafana_update_notification_channel(self, data, payload, before):
"diff": {"before": before, "after": after},
"channel": channel,
}
+ elif status == 202:
+ contact_point = json.loads(to_text(r.read()))
+ return {
+ "changed": True,
+ "contact-point": contact_point,
+ }
else:
raise GrafanaAPIException(
"Unable to update %s %s : %s" % (self.endpoint_type, data["uid"], info)
@@ -776,15 +784,24 @@ def grafana_create_or_update_notification_channel(self, data):
)
before = json.loads(to_text(r.read()))
- if info["status"] == 200 and before is not None:
- if data["state"] == "present":
- return self.grafana_update_notification_channel(data, payload, before)
+ status = info.get("status")
+ state = data["state"]
+
+ if status == 200:
+ if state == "present":
+ if before is None:
+ return self.grafana_create_notification_channel(data, payload)
+ else:
+ return self.grafana_update_notification_channel(
+ data, payload, before
+ )
else:
- return self.grafana_delete_notification_channel(data)
- elif info["status"] == 404 or (before is None and data["state"] == "present"):
+ if before is None:
+ return {"changed": False}
+ else:
+ return self.grafana_delete_notification_channel(data)
+ elif status == 404:
return self.grafana_create_notification_channel(data, payload)
- elif info["status"] == 200 and before is None and data["state"] == "absent":
- return {"changed": False}
else:
raise GrafanaAPIException(
"Unable to get %s %s : %s" % (self.endpoint_type, data["uid"], info)
From 3b4f04f4047c0492bc4a72f59b9d09292ff8b901 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 28 Feb 2024 18:35:43 +0100
Subject: [PATCH 029/120] fix: reset notification channel
---
.../modules/grafana_notification_channel.py | 185 ++++--------------
1 file changed, 40 insertions(+), 145 deletions(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index c62c42f7..30b5b112 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -36,17 +36,10 @@
options:
org_id:
description:
- - The Grafana Organisation ID where the notification channel will be handled.
+ - The Grafana Organisation ID where the dashboard will be imported / exported.
- Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organisation..
- - Mutually exclusive with C(org_name).
default: 1
type: int
- org_name:
- description:
- - The Grafana Organisation name where the notification channel will be handled.
- - Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organisation..
- - Mutually exclusive with C(org_id).
- type: str
state:
type: str
default: present
@@ -431,7 +424,6 @@
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.module_utils.six.moves.urllib.parse import quote
from ansible_collections.community.grafana.plugins.module_utils.base import (
grafana_argument_spec,
clean_url,
@@ -619,7 +611,6 @@ def grafana_notification_channel_payload(data):
class GrafanaNotificationChannelInterface(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):
@@ -630,41 +621,13 @@ def __init__(self, module):
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.grafana_check_unified_alerting(module.params)
- self.endpoint_type = (
- "contact point" if self.grafana_unified_alerting else "notification channel"
- )
+ self.grafana_url = clean_url(module.params.get("url"))
- def grafana_check_unified_alerting(self, data):
- self.grafana_unified_alerting = None
+ def grafana_switch_organisation(self, grafana_url, org_id):
r, info = fetch_url(
self._module,
- "%s/api/frontend/settings" % data["url"],
- headers=self.headers,
- method="GET",
- )
- if info["status"] == 200:
- try:
- settings = json.loads(to_text(r.read()))
- self.grafana_unified_alerting = settings["unifiedAlertingEnabled"]
- except UnicodeError:
- raise GrafanaAPIException("Unable to decode version string to Unicode")
- except Exception as e:
- raise GrafanaAPIException(e)
- else:
- raise GrafanaAPIException("Unable to get grafana version: %s" % info)
-
- def grafana_switch_organisation(self, data, org_id):
- r, info = fetch_url(
- self._module,
- "%s/api/user/using/%s" % (data["url"], org_id),
+ "%s/api/user/using/%s" % (grafana_url, org_id),
headers=self.headers,
method="POST",
)
@@ -673,72 +636,34 @@ def grafana_switch_organisation(self, data, org_id):
"Unable to switch to organization %s : %s" % (org_id, info)
)
- 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_create_notification_channel(self, data, payload):
- url_template = (
- "%s/api/v1/provisioning/contact-points"
- if self.grafana_unified_alerting
- else "%s/api/alert-notifications"
- )
- url = url_template % data["url"]
-
r, info = fetch_url(
self._module,
- url,
+ "%s/api/alert-notifications" % data["url"],
data=json.dumps(payload),
headers=self.headers,
method="POST",
)
-
- status = info["status"]
- channel = json.loads(to_text(r.read()))
-
- if status in [200, 202]:
- type_key = "contact-point" if self.grafana_unified_alerting else "channel"
+ if info["status"] == 200:
return {
"state": "present",
"changed": True,
- type_key: channel,
+ "channel": json.loads(to_text(r.read())),
}
else:
raise GrafanaAPIException(
- "Unable to create %s: %s" % (self.endpoint_type, info)
+ "Unable to create notification channel: %s" % info
)
def grafana_update_notification_channel(self, data, payload, before):
- url_template = (
- "%s/api/v1/provisioning/contact-points/%s"
- if self.grafana_unified_alerting
- else "%s/api/alert-notifications/uid/%s"
- )
- url = url_template % (data["url"], data["uid"])
-
r, info = fetch_url(
self._module,
- url,
+ "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"]),
data=json.dumps(payload),
headers=self.headers,
method="PUT",
)
-
- status = info["status"]
-
- if status == 200:
+ if info["status"] == 200:
del before["created"]
del before["updated"]
@@ -747,88 +672,56 @@ def grafana_update_notification_channel(self, data, payload, before):
del after["created"]
del after["updated"]
- if before == channel:
- return {"changed": False, "channel": channel}
+ if before == after:
+ return {
+ "changed": False,
+ "channel": channel,
+ }
else:
return {
"changed": True,
- "diff": {"before": before, "after": after},
+ "diff": {
+ "before": before,
+ "after": after,
+ },
"channel": channel,
}
- elif status == 202:
- contact_point = json.loads(to_text(r.read()))
- return {
- "changed": True,
- "contact-point": contact_point,
- }
else:
raise GrafanaAPIException(
- "Unable to update %s %s : %s" % (self.endpoint_type, data["uid"], info)
+ "Unable to update notification channel %s : %s" % (data["uid"], info)
)
def grafana_create_or_update_notification_channel(self, data):
payload = grafana_notification_channel_payload(data)
- url = (
- "%s/api/v1/provisioning/contact-points?name=%s"
- % (data["url"], quote(data["name"]))
- if self.grafana_unified_alerting
- else "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"])
- )
-
r, info = fetch_url(
self._module,
- url,
- data=json.dumps(payload),
+ "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"]),
headers=self.headers,
- method="GET",
)
-
- before = json.loads(to_text(r.read()))
- status = info.get("status")
- state = data["state"]
-
- if status == 200:
- if state == "present":
- if before is None:
- return self.grafana_create_notification_channel(data, payload)
- else:
- return self.grafana_update_notification_channel(
- data, payload, before
- )
- else:
- if before is None:
- return {"changed": False}
- else:
- return self.grafana_delete_notification_channel(data)
- elif status == 404:
+ if info["status"] == 200:
+ before = json.loads(to_text(r.read()))
+ return self.grafana_update_notification_channel(data, payload, before)
+ elif info["status"] == 404:
return self.grafana_create_notification_channel(data, payload)
else:
raise GrafanaAPIException(
- "Unable to get %s %s : %s" % (self.endpoint_type, data["uid"], info)
+ "Unable to get notification channel %s : %s" % (data["uid"], info)
)
def grafana_delete_notification_channel(self, data):
- url_template = (
- "%s/api/v1/provisioning/contact-points/%s"
- if self.grafana_unified_alerting
- else "%s/api/alert-notifications/uid/%s"
- )
- url = url_template % (data["url"], data["uid"])
-
r, info = fetch_url(
self._module,
- url,
+ "%s/api/alert-notifications/uid/%s" % (data["url"], data["uid"]),
headers=self.headers,
method="DELETE",
)
-
- if info["status"] == 200 or info["status"] == 202:
+ if info["status"] == 200:
return {"state": "absent", "changed": True}
elif info["status"] == 404:
return {"changed": False}
else:
raise GrafanaAPIException(
- "Unable to delete %s %s : %s" % (self.endpoint_type, data["uid"], info)
+ "Unable to delete notification channel %s : %s" % (data["uid"], info)
)
@@ -836,7 +729,6 @@ def main():
argument_spec = grafana_argument_spec()
argument_spec.update(
org_id=dict(type="int", default=1),
- org_name=dict(type="str"),
uid=dict(type="str"),
name=dict(type="str"),
type=dict(
@@ -905,8 +797,8 @@ def main():
elements="str",
choices=["emergency", "high", "normal", "low", "lowest"],
),
- pushover_retry=dict(type="int"),
- pushover_expire=dict(type="int"),
+ pushover_retry=dict(type="int"), # TODO: only when priority==emergency
+ pushover_expire=dict(type="int"), # TODO: only when priority==emergency
pushover_alert_sound=dict(type="str"), # TODO: add sound choices
pushover_ok_sound=dict(type="str"), # TODO: add sound choices
sensu_url=dict(type="str"),
@@ -971,17 +863,20 @@ def main():
],
["type", "victorops", ["victorops_url"]],
["type", "webhook", ["webhook_url"]],
- ["pushover_priority", "emergency", ["pushover_retry", "pushover_expire"]],
],
)
module.params["url"] = clean_url(module.params["url"])
-
alert_channel_iface = GrafanaNotificationChannelInterface(module)
- result = alert_channel_iface.grafana_create_or_update_notification_channel(
- module.params
- )
- module.exit_json(failed=False, **result)
+
+ if module.params["state"] == "present":
+ result = alert_channel_iface.grafana_create_or_update_notification_channel(
+ module.params
+ )
+ module.exit_json(failed=False, **result)
+ else:
+ result = alert_channel_iface.grafana_delete_notification_channel(module.params)
+ module.exit_json(failed=False, **result)
if __name__ == "__main__":
From a1310ea2e1fae2e25c276132b99b582b8ecb4ab3 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 28 Feb 2024 18:37:21 +0100
Subject: [PATCH 030/120] feat: intial add working contact point module
---
plugins/modules/grafana_contact_point.yml | 277 ++++++++++++++++++++++
1 file changed, 277 insertions(+)
create mode 100644 plugins/modules/grafana_contact_point.yml
diff --git a/plugins/modules/grafana_contact_point.yml b/plugins/modules/grafana_contact_point.yml
new file mode 100644
index 00000000..a4b4e8f7
--- /dev/null
+++ b/plugins/modules/grafana_contact_point.yml
@@ -0,0 +1,277 @@
+#!/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.
+
+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: changed
+"""
+
+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.module_utils.six.moves.urllib.parse import quote
+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_email(data, payload):
+ payload["settings"]["addresses"] = ";".join(data["email_addresses"])
+ if data.get("email_single"):
+ payload["settings"]["singleEmail"] = data["email_single"]
+
+
+def grafana_contact_point_payload(data):
+ payload = {
+ "uid": data["uid"],
+ "name": data["name"],
+ "type": data["type"],
+ "isDefault": data["is_default"],
+ "disableResolveMessage": data["disable_resolve_message"],
+ "settings": {"uploadImage": data["include_image"]},
+ }
+
+ if data["type"] == "email":
+ grafana_contact_point_payload_email(data, payload)
+
+ 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)
+ # }}}
+
+ 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()))
+ before = next(
+ (cp for cp in contact_points if cp["uid"] == data["uid"]), None
+ )
+ return self.grafana_handle_contact_point(data, before)
+ else:
+ raise GrafanaAPIException(
+ "Unable to get contact point %s : %s" % (data["uid"], info)
+ )
+
+ def grafana_handle_contact_point(self, data, before):
+ payload = grafana_contact_point_payload(data)
+
+ if data["state"] == "present":
+ if before:
+ return self.grafana_update_contact_point(data, payload, before)
+ else:
+ return self.grafana_create_contact_point(data, payload)
+ else:
+ if before:
+ return self.grafana_delete_contact_point(data)
+ else:
+ return {"changed": False}
+
+ 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, "state": data["state"], "contact_point": contact_point}
+ else:
+ raise GrafanaAPIException(
+ "Unable to create contact point: %s" % info
+ )
+
+ def grafana_update_contact_point(self, data, payload, before):
+ 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 = json.loads(to_text(r.read()))
+
+ if before == contact_point:
+ return {"changed": False}
+ else:
+ return {"changed": True, "diff": {"before": before, "after": payload}, "contact_point": contact_point}
+ 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 {"state": "absent", "changed": True}
+ elif info["status"] == 404:
+ return {"changed": False}
+ else:
+ raise GrafanaAPIException(
+ "Unable to delete contact point %s : %s" % (data["uid"], info)
+ )
+
+
+def main():
+ argument_spec = grafana_argument_spec()
+ argument_spec.update(
+ org_id=dict(type="int", default=1),
+ org_name=dict(type="str"),
+ uid=dict(type="str"),
+ name=dict(type="str"),
+ type=dict(type="str", choices=["email"]),
+ is_default=dict(type="bool", default=False),
+ include_image=dict(type="bool", default=False),
+ disable_resolve_message=dict(type="bool", default=False),
+ email_addresses=dict(type="list", elements="str"),
+ email_single=dict(type="bool"),
+ )
+
+ 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", "email", ["email_addresses"]],
+ ],
+ )
+
+ module.params["url"] = clean_url(module.params["url"])
+ grafana_iface = GrafanaContactPointInterface(module)
+
+ result = grafana_iface.grafana_check_contact_point_match(module.params)
+ module.exit_json(failed=False, **result)
+
+
+if __name__ == "__main__":
+ main()
From 0e260fafdd2eb32173fe2409113ead6a06d51038 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 28 Feb 2024 18:44:35 +0100
Subject: [PATCH 031/120] chore: format
---
plugins/modules/grafana_contact_point.yml | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.yml b/plugins/modules/grafana_contact_point.yml
index a4b4e8f7..9858782e 100644
--- a/plugins/modules/grafana_contact_point.yml
+++ b/plugins/modules/grafana_contact_point.yml
@@ -195,11 +195,13 @@ class GrafanaContactPointInterface(object):
if info["status"] == 202:
contact_point = json.loads(to_text(r.read()))
- return {"changed": True, "state": data["state"], "contact_point": contact_point}
+ return {
+ "changed": True,
+ "state": data["state"],
+ "contact_point": contact_point,
+ }
else:
- raise GrafanaAPIException(
- "Unable to create contact point: %s" % info
- )
+ raise GrafanaAPIException("Unable to create contact point: %s" % info)
def grafana_update_contact_point(self, data, payload, before):
r, info = fetch_url(
@@ -216,7 +218,11 @@ class GrafanaContactPointInterface(object):
if before == contact_point:
return {"changed": False}
else:
- return {"changed": True, "diff": {"before": before, "after": payload}, "contact_point": contact_point}
+ return {
+ "changed": True,
+ "diff": {"before": before, "after": payload},
+ "contact_point": contact_point,
+ }
else:
raise GrafanaAPIException(
"Unable to update contact point %s : %s" % (data["uid"], info)
From e6168f0ca55d0cd7eb651d403bf3fdcd1693e9f3 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 28 Feb 2024 20:17:00 +0100
Subject: [PATCH 032/120] chore: wtf i named it yml
---
.../{grafana_contact_point.yml => grafana_contact_point.py} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename plugins/modules/{grafana_contact_point.yml => grafana_contact_point.py} (100%)
diff --git a/plugins/modules/grafana_contact_point.yml b/plugins/modules/grafana_contact_point.py
similarity index 100%
rename from plugins/modules/grafana_contact_point.yml
rename to plugins/modules/grafana_contact_point.py
From e3bb6048c6450576963ad54d7320c88264f45153 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 29 Feb 2024 08:11:01 +0100
Subject: [PATCH 033/120] chore: remove unused import
---
plugins/modules/grafana_contact_point.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 9858782e..a447d768 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -67,7 +67,6 @@
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.module_utils.six.moves.urllib.parse import quote
from ansible_collections.community.grafana.plugins.module_utils.base import (
grafana_argument_spec,
clean_url,
From 45a2170755b6c7377ec206c320a0c68aadebaf2b Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 29 Feb 2024 08:35:13 +0100
Subject: [PATCH 034/120] docs: changelog fragment
---
changelogs/fragments/352-module-contact-point.yml | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 changelogs/fragments/352-module-contact-point.yml
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
From 65e92b5245daeb44fed9c7efd9abbd34cc38ef04 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 29 Feb 2024 09:10:41 +0100
Subject: [PATCH 035/120] feat: initial support of contact point module in
grafana role
---
meta/runtime.yml | 1 +
roles/grafana/README.md | 10 ++++++++++
roles/grafana/defaults/main.yml | 1 +
roles/grafana/tasks/main.yml | 15 +++++++++++++++
4 files changed, 27 insertions(+)
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/roles/grafana/README.md b/roles/grafana/README.md
index b26a9044..61de4fc5 100644
--- a/roles/grafana/README.md
+++ b/roles/grafana/README.md
@@ -172,6 +172,16 @@ 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) |
+| email_addresses | no |
+| email_single | no |
+| is_default | no |
+| name | yes |
+| org_id | no |
+| org_name | no |
+| state | no |
+| type | yes |
+| uid | 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..347ef1c6 100644
--- a/roles/grafana/tasks/main.yml
+++ b/roles/grafana/tasks/main.yml
@@ -89,6 +89,21 @@
loop_control: {loop_var: notification_channel}
tags: notification_channel
+ - name: Manage contact point
+ community.grafana.grafana_contact_point:
+ email_addresses: "{{ contact_point.email_addresses | default(omit) }}"
+ email_single: "{{ contact_point.email_single | default(omit) }}"
+ is_default: "{{ contact_point.is_default | default(omit) }}"
+ name: "{{ contact_point.name }}"
+ org_id: "{{ contact_point.org_id | default(omit) }}"
+ org_name: "{{ contact_point.org_id | default(omit) }}"
+ state: "{{ contact_point.state | default(omit) }}"
+ type: "{{ contact_point.type }}"
+ uid: "{{ contact_point.uid | 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) }}"
From 75167fc6186b4c1ec6a6a939fe10fe92d3c72ab0 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 29 Feb 2024 11:36:08 +0100
Subject: [PATCH 036/120] docs: add module to readme
---
README.md | 1 +
1 file changed, 1 insertion(+)
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)
From fbca2c4b656db2838fb2f430297291238a1000b0 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 4 Mar 2024 10:27:59 +0100
Subject: [PATCH 037/120] chore: arguments for all contact points
---
plugins/modules/grafana_contact_point.py | 204 ++++++++++++++++++++++-
1 file changed, 198 insertions(+), 6 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index a447d768..81dd8f75 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -78,6 +78,18 @@ class GrafanaAPIException(Exception):
pass
+def grafana_contact_point_payload(data):
+ payload = {
+ "uid": data["uid"],
+ "name": data["name"],
+ "type": data["type"],
+ "isDefault": data["is_default"],
+ "disableResolveMessage": data["disable_resolve_message"],
+ }
+
+ return payload
+
+
def grafana_contact_point_payload_email(data, payload):
payload["settings"]["addresses"] = ";".join(data["email_addresses"])
if data.get("email_single"):
@@ -248,16 +260,177 @@ def grafana_delete_contact_point(self, data):
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),
+ is_default=dict(type="bool", default=False),
+ name=dict(type="str"),
org_id=dict(type="int", default=1),
org_name=dict(type="str"),
+ type=dict(
+ type="str",
+ choices=[
+ "alertmanager",
+ "dingding",
+ "discord",
+ "email",
+ "googlechat",
+ "kaska",
+ "line",
+ "opsgenie",
+ "pagerduty",
+ "pushover",
+ "sensugo",
+ "slack",
+ "teams",
+ "telegram",
+ "threema",
+ "victorops",
+ "webex",
+ "webhook",
+ "wecom",
+ ],
+ ),
uid=dict(type="str"),
- name=dict(type="str"),
- type=dict(type="str", choices=["email"]),
- is_default=dict(type="bool", default=False),
- include_image=dict(type="bool", default=False),
- disable_resolve_message=dict(type="bool", default=False),
+ # type: alertmanager
+ alertmanager_password=dict(type="str", no_log=True),
+ alertmanager_url=dict(type="str"),
+ alertmanager_username=dict(type="str"),
+ # type: dingding
+ dingding_message=dict(type="str"),
+ dingding_message_type=dict(type="str"),
+ dingding_title=dict(type="str"),
+ dingding_url=dict(type="str"),
+ # type: 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),
+ # type: email
email_addresses=dict(type="list", elements="str"),
- email_single=dict(type="bool"),
+ email_message=dict(type="str"),
+ email_single=dict(type="bool", default=False),
+ email_subject=dict(type="str"),
+ # type: googlechat
+ googlechat_url=dict(type="str", no_log=True),
+ googlechat_message=dict(type="str"),
+ googlechat_title=dict(type="str"),
+ # type: 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"),
+ # type: line
+ line_description=dict(type="str"),
+ line_title=dict(type="str"),
+ line_token=dict(type="str", no_log=True),
+ # type: 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"),
+ # type: 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"),
+ # type: 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),
+ # type: 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"),
+ # type: 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"),
+ slack_mention_users=dict(type="list"),
+ 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"),
+ # type: 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),
+ # type: 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"),
+ # type: 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"),
+ # type: 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"),
+ # type: 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),
+ # type: 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"),
+ # type: 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"),
+ wecom_url=dict(type="str", no_log=True),
)
module = AnsibleModule(
@@ -267,7 +440,26 @@ def main():
mutually_exclusive=[["url_username", "grafana_api_key"]],
required_if=[
["state", "present", ["name", "type"]],
+ ["state", "absent", ["uid"]],
+ ["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"]],
+ ["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"]],
],
)
From 8672a474b6d86e833959ed67154c4ac440cfebef Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 4 Mar 2024 10:32:03 +0100
Subject: [PATCH 038/120] chore: format
---
plugins/modules/grafana_contact_point.py | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 81dd8f75..38f8e1b7 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -346,7 +346,9 @@ def main():
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_severity=dict(
+ type="str", choices=["critical", "error", "warning", "info"]
+ ),
pagerduty_source=dict(type="str"),
pagerduty_summary=dict(type="str"),
# type: pushover
@@ -455,11 +457,19 @@ def main():
["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",
+ "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"]],
+ [
+ "type",
+ "wecom",
+ ["wecom_url", "wecom_agent_id", "wecom_corp_id", "wecom_secret"],
+ ],
],
)
From cdbe594071f79ece8b22cff8a98571f58b7e59f3 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 4 Mar 2024 13:55:45 +0100
Subject: [PATCH 039/120] chore: handle provisioning
---
plugins/modules/grafana_contact_point.py | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 38f8e1b7..cc3467e8 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -78,24 +78,11 @@ class GrafanaAPIException(Exception):
pass
-def grafana_contact_point_payload(data):
- payload = {
- "uid": data["uid"],
- "name": data["name"],
- "type": data["type"],
- "isDefault": data["is_default"],
- "disableResolveMessage": data["disable_resolve_message"],
- }
-
- return payload
-
-
def grafana_contact_point_payload_email(data, payload):
payload["settings"]["addresses"] = ";".join(data["email_addresses"])
if data.get("email_single"):
payload["settings"]["singleEmail"] = data["email_single"]
-
def grafana_contact_point_payload(data):
payload = {
"uid": data["uid"],
@@ -103,7 +90,7 @@ def grafana_contact_point_payload(data):
"type": data["type"],
"isDefault": data["is_default"],
"disableResolveMessage": data["disable_resolve_message"],
- "settings": {"uploadImage": data["include_image"]},
+ "settings": {},
}
if data["type"] == "email":
@@ -134,6 +121,10 @@ def __init__(self, module):
self.grafana_switch_organisation(module.params, self.org_id)
# }}}
+ def grafana_api_provisioning(self, data):
+ if not data["provisioning"]:
+ self.headers["X-Disable-Provenance"] = "true"
+
def grafana_organization_by_name(self, data, org_name):
r, info = fetch_url(
self._module,
@@ -188,6 +179,7 @@ def grafana_handle_contact_point(self, data, before):
if before:
return self.grafana_update_contact_point(data, payload, before)
else:
+ self.grafana_api_provisioning(data)
return self.grafana_create_contact_point(data, payload)
else:
if before:
@@ -267,6 +259,7 @@ def main():
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=[
From 8a9234dfcff10363f959146dadfd4d4260bed09a Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 4 Mar 2024 16:16:29 +0100
Subject: [PATCH 040/120] chore: payload with type settings map and for loop
---
plugins/modules/grafana_contact_point.py | 190 ++++++++++++++++++++++-
1 file changed, 183 insertions(+), 7 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index cc3467e8..c81c2be4 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -78,11 +78,6 @@ class GrafanaAPIException(Exception):
pass
-def grafana_contact_point_payload_email(data, payload):
- payload["settings"]["addresses"] = ";".join(data["email_addresses"])
- if data.get("email_single"):
- payload["settings"]["singleEmail"] = data["email_single"]
-
def grafana_contact_point_payload(data):
payload = {
"uid": data["uid"],
@@ -93,8 +88,189 @@ def grafana_contact_point_payload(data):
"settings": {},
}
- if data["type"] == "email":
- grafana_contact_point_payload_email(data, payload)
+ 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_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
From bd48aabce275d12cd84862c75aae654ca006ae32 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 4 Mar 2024 20:16:47 +0100
Subject: [PATCH 041/120] fix: alertmanager type
---
plugins/modules/grafana_contact_point.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index c81c2be4..583a7978 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -88,6 +88,9 @@ def grafana_contact_point_payload(data):
"settings": {},
}
+ if data["type"] == "alertmanager":
+ payload["type"] = "prometheus-alertmanager"
+
type_settings_map = {
"alertmanager": {
"basicAuthPassword": "alertmanager_password",
From c3352e8582d2748de2dc28d4ba4da01819f94591 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 4 Mar 2024 20:18:10 +0100
Subject: [PATCH 042/120] test: initial add contact point integration tests
---
.../targets/grafana_contact_point/runme.sh | 5 ++
.../targets/grafana_contact_point/site.yml | 11 +++
.../tasks/alertmanager.yml | 56 ++++++++++++
.../grafana_contact_point/tasks/dingding.yml | 56 ++++++++++++
.../grafana_contact_point/tasks/discord.yml | 56 ++++++++++++
.../grafana_contact_point/tasks/email.yml | 61 +++++++++++++
.../tasks/googlechat.yml | 56 ++++++++++++
.../grafana_contact_point/tasks/kafka.yml | 58 +++++++++++++
.../grafana_contact_point/tasks/line.yml | 56 ++++++++++++
.../grafana_contact_point/tasks/main.yml | 16 ++++
.../grafana_contact_point/tasks/opsgenie.yml | 59 +++++++++++++
.../grafana_contact_point/tasks/pagerduty.yml | 56 ++++++++++++
.../grafana_contact_point/tasks/pushover.yml | 58 +++++++++++++
.../grafana_contact_point/tasks/sensugo.yml | 56 ++++++++++++
.../grafana_contact_point/tasks/slack.yml | 86 +++++++++++++++++++
.../grafana_contact_point/tasks/teams.yml | 56 ++++++++++++
.../grafana_contact_point/tasks/telegram.yml | 58 +++++++++++++
.../grafana_contact_point/tasks/threema.yml | 60 +++++++++++++
.../grafana_contact_point/tasks/victorops.yml | 56 ++++++++++++
.../grafana_contact_point/tasks/webhook.yml | 56 ++++++++++++
20 files changed, 1032 insertions(+)
create mode 100755 tests/integration/targets/grafana_contact_point/runme.sh
create mode 100644 tests/integration/targets/grafana_contact_point/site.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/alertmanager.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/dingding.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/discord.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/email.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/googlechat.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/kafka.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/line.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/main.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/opsgenie.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/pagerduty.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/pushover.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/sensugo.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/slack.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/teams.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/telegram.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/threema.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/victorops.yml
create mode 100644 tests/integration/targets/grafana_contact_point/tasks/webhook.yml
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..6ca4b934
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/alertmanager.yml
@@ -0,0 +1,56 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..5b14a909
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/dingding.yml
@@ -0,0 +1,56 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..89e62daa
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/discord.yml
@@ -0,0 +1,56 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..91aeba8b
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/email.yml
@@ -0,0 +1,61 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- name: Delete discord contact point
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: email
+ state: absent
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == True
+ - result.state == 'absent'
+
+- name: Delete discord contact point (idempotency)
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: email
+ state: absent
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == False
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..1243ca04
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/googlechat.yml
@@ -0,0 +1,56 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..bef1106c
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/kafka.yml
@@ -0,0 +1,58 @@
+---
+- name: Create kafka contact point
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: kafka
+ name: kafka
+ type: kafka
+ kafka_url: https://example.org
+ kafka_topic: test
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == True
+
+- name: Create kafka contact point (idempotentcy)
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: kafka
+ name: kafka
+ type: kafka
+ kafka_url: https://example.org
+ kafka_topic: test
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..f1f88de9
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/line.yml
@@ -0,0 +1,56 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..bb94793c
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+- ansible.builtin.include_tasks: alertmanager.yml
+- ansible.builtin.include_tasks: dingding.yml
+- ansible.builtin.include_tasks: discord.yml
+- ansible.builtin.include_tasks: email.yml
+- ansible.builtin.include_tasks: googlechat.yml
+- ansible.builtin.include_tasks: kafka.yml
+- ansible.builtin.include_tasks: opsgenie.yml
+- ansible.builtin.include_tasks: pagerduty.yml
+- ansible.builtin.include_tasks: pushover.yml
+- ansible.builtin.include_tasks: sensugo.yml
+- ansible.builtin.include_tasks: slack.yml
+- ansible.builtin.include_tasks: teams.yml
+- ansible.builtin.include_tasks: telegram.yml
+- ansible.builtin.include_tasks: victorops.yml
+- ansible.builtin.include_tasks: webhook.yml
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..6e810e2a
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/opsgenie.yml
@@ -0,0 +1,59 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+ - result.state == 'absent'
+
+- 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:
+ - result.changed == False
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..3c5e65a9
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/pagerduty.yml
@@ -0,0 +1,56 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..27ed69be
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/pushover.yml
@@ -0,0 +1,58 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..902034e4
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml
@@ -0,0 +1,56 @@
+---
+- name: Create sensu contact point
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: sensu
+ name: sensu
+ type: sensu
+ sensu_url: https://example.org
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == True
+
+- name: Create sensu contact point
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: sensu
+ name: sensu
+ type: sensu
+ sensu_url: https://example.org
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == False
+
+- name: Delete sensu contact point
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: sensu
+ state: absent
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == True
+
+- name: Delete sensu contact point (idempotency)
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: sensu
+ state: absent
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == False
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..19c50d21
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/slack.yml
@@ -0,0 +1,86 @@
+---
+- 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
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == True
+
+- 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
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == False
+
+- 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
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == False
+
+- 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/fff
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == True
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..019b407e
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/teams.yml
@@ -0,0 +1,56 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..fbe207e7
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/telegram.yml
@@ -0,0 +1,58 @@
+---
+- name: Create telegram contact point
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: telegram
+ name: telegram
+ type: telegram
+ telegram_bot_token: xxx
+ telegram_chat_id: yyy
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == True
+
+- name: Create telegram contact point
+ register: result
+ community.grafana.grafana_contact_point:
+ uid: telegram
+ name: telegram
+ type: telegram
+ telegram_bot_token: xxx
+ telegram_chat_id: yyy
+
+- ansible.builtin.debug:
+ var: result
+
+- ansible.builtin.assert:
+ that:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..6e17aa51
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/threema.yml
@@ -0,0 +1,60 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == True
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..8ab40387
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/victorops.yml
@@ -0,0 +1,56 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
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..8ff8ba4c
--- /dev/null
+++ b/tests/integration/targets/grafana_contact_point/tasks/webhook.yml
@@ -0,0 +1,56 @@
+---
+- 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 == True
+
+- 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:
+ - result.changed == False
+
+- 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 == True
+
+- 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:
+ - result.changed == False
From 3345e9a060a11270efe765873bd3c6658585e893 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 4 Mar 2024 22:24:56 +0100
Subject: [PATCH 043/120] fix: provisioning handling
---
plugins/modules/grafana_contact_point.py | 30 ++++++++++++++----------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 583a7978..4b41fd69 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -83,7 +83,6 @@ def grafana_contact_point_payload(data):
"uid": data["uid"],
"name": data["name"],
"type": data["type"],
- "isDefault": data["is_default"],
"disableResolveMessage": data["disable_resolve_message"],
"settings": {},
}
@@ -300,9 +299,16 @@ def __init__(self, module):
self.grafana_switch_organisation(module.params, self.org_id)
# }}}
- def grafana_api_provisioning(self, data):
- if not data["provisioning"]:
+ def grafana_api_provisioning(self, data, before):
+ if not before or (
+ not before.get("provenance") and not data.get("provisioning")
+ ):
self.headers["X-Disable-Provenance"] = "true"
+ elif before.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"]
+ )
def grafana_organization_by_name(self, data, org_name):
r, info = fetch_url(
@@ -329,7 +335,7 @@ def grafana_switch_organisation(self, data, org_id):
)
if info["status"] != 200:
raise GrafanaAPIException(
- "Unable to switch to organization %s : %s" % (org_id, info)
+ "Unable to switch to organization '%s': %s" % (org_id, info)
)
def grafana_check_contact_point_match(self, data):
@@ -348,17 +354,17 @@ def grafana_check_contact_point_match(self, data):
return self.grafana_handle_contact_point(data, before)
else:
raise GrafanaAPIException(
- "Unable to get contact point %s : %s" % (data["uid"], info)
+ "Unable to get contact point '%s': %s" % (data["uid"], info)
)
def grafana_handle_contact_point(self, data, before):
payload = grafana_contact_point_payload(data)
if data["state"] == "present":
+ self.grafana_api_provisioning(data, before)
if before:
return self.grafana_update_contact_point(data, payload, before)
else:
- self.grafana_api_provisioning(data)
return self.grafana_create_contact_point(data, payload)
else:
if before:
@@ -395,19 +401,20 @@ def grafana_update_contact_point(self, data, payload, before):
)
if info["status"] == 202:
- contact_point = json.loads(to_text(r.read()))
+ if before.get("provenance") and data.get("provisioning"):
+ del before["provenance"]
- if before == contact_point:
+ if before == payload:
return {"changed": False}
else:
return {
"changed": True,
"diff": {"before": before, "after": payload},
- "contact_point": contact_point,
+ "contact_point": payload,
}
else:
raise GrafanaAPIException(
- "Unable to update contact point %s : %s" % (data["uid"], info)
+ "Unable to update contact point '%s': %s" % (data["uid"], info)
)
def grafana_delete_contact_point(self, data):
@@ -424,7 +431,7 @@ def grafana_delete_contact_point(self, data):
return {"changed": False}
else:
raise GrafanaAPIException(
- "Unable to delete contact point %s : %s" % (data["uid"], info)
+ "Unable to delete contact point '%s': %s" % (data["uid"], info)
)
@@ -434,7 +441,6 @@ def main():
# general arguments
disable_resolve_message=dict(type="bool", default=False),
include_image=dict(type="bool", default=False),
- is_default=dict(type="bool", default=False),
name=dict(type="str"),
org_id=dict(type="int", default=1),
org_name=dict(type="str"),
From fc12309b43f929181ca49e222c4d02f7b455450f Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 20 Mar 2024 13:09:24 +0100
Subject: [PATCH 044/120] chore: rename before to contact_point
---
plugins/modules/grafana_contact_point.py | 32 ++++++++++++------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 4b41fd69..7f71c7df 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -299,12 +299,12 @@ def __init__(self, module):
self.grafana_switch_organisation(module.params, self.org_id)
# }}}
- def grafana_api_provisioning(self, data, before):
- if not before or (
- not before.get("provenance") and not data.get("provisioning")
+ def grafana_api_provisioning(self, data, contact_point):
+ if not contact_point or (
+ not contact_point.get("provenance") and not data.get("provisioning")
):
self.headers["X-Disable-Provenance"] = "true"
- elif before.get("provenance") and not data.get("provisioning"):
+ elif 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"]
@@ -348,26 +348,26 @@ def grafana_check_contact_point_match(self, data):
if info["status"] == 200:
contact_points = json.loads(to_text(r.read()))
- before = next(
+ contact_point = next(
(cp for cp in contact_points if cp["uid"] == data["uid"]), None
)
- return self.grafana_handle_contact_point(data, before)
+ return self.grafana_handle_contact_point(data, contact_point)
else:
raise GrafanaAPIException(
"Unable to get contact point '%s': %s" % (data["uid"], info)
)
- def grafana_handle_contact_point(self, data, before):
+ def grafana_handle_contact_point(self, data, contact_point):
payload = grafana_contact_point_payload(data)
if data["state"] == "present":
- self.grafana_api_provisioning(data, before)
- if before:
- return self.grafana_update_contact_point(data, payload, before)
+ self.grafana_api_provisioning(data, contact_point)
+ if contact_point:
+ return self.grafana_update_contact_point(data, payload, contact_point)
else:
return self.grafana_create_contact_point(data, payload)
else:
- if before:
+ if contact_point:
return self.grafana_delete_contact_point(data)
else:
return {"changed": False}
@@ -391,7 +391,7 @@ def grafana_create_contact_point(self, data, payload):
else:
raise GrafanaAPIException("Unable to create contact point: %s" % info)
- def grafana_update_contact_point(self, data, payload, before):
+ def grafana_update_contact_point(self, data, payload, contact_point):
r, info = fetch_url(
self._module,
"%s/api/v1/provisioning/contact-points/%s" % (data["url"], data["uid"]),
@@ -401,15 +401,15 @@ def grafana_update_contact_point(self, data, payload, before):
)
if info["status"] == 202:
- if before.get("provenance") and data.get("provisioning"):
- del before["provenance"]
+ if contact_point.get("provenance") and data.get("provisioning"):
+ del contact_point["provenance"]
- if before == payload:
+ if contact_point == payload:
return {"changed": False}
else:
return {
"changed": True,
- "diff": {"before": before, "after": payload},
+ "diff": {"before": contact_point, "after": payload},
"contact_point": payload,
}
else:
From 8fe1aa7776bf69715f3c65dc4d222ad9755eef39 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 20 Mar 2024 13:34:46 +0100
Subject: [PATCH 045/120] chore: switch entry func and define contact point as
self var
---
plugins/modules/grafana_contact_point.py | 33 ++++++++++++------------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 7f71c7df..bcf3dc81 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -298,13 +298,14 @@ def __init__(self, module):
)
self.grafana_switch_organisation(module.params, self.org_id)
# }}}
+ self.contact_point = self.grafana_check_contact_point_match(module.params)
- def grafana_api_provisioning(self, data, contact_point):
- if not contact_point or (
- not contact_point.get("provenance") and not data.get("provisioning")
+ def grafana_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 contact_point.get("provenance") and not data.get("provisioning"):
+ 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"]
@@ -351,23 +352,23 @@ def grafana_check_contact_point_match(self, data):
contact_point = next(
(cp for cp in contact_points if cp["uid"] == data["uid"]), None
)
- return self.grafana_handle_contact_point(data, contact_point)
+ return contact_point
else:
raise GrafanaAPIException(
"Unable to get contact point '%s': %s" % (data["uid"], info)
)
- def grafana_handle_contact_point(self, data, contact_point):
+ def grafana_handle_contact_point(self, data):
payload = grafana_contact_point_payload(data)
if data["state"] == "present":
- self.grafana_api_provisioning(data, contact_point)
- if contact_point:
- return self.grafana_update_contact_point(data, payload, contact_point)
+ self.grafana_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 contact_point:
+ if self.contact_point:
return self.grafana_delete_contact_point(data)
else:
return {"changed": False}
@@ -391,7 +392,7 @@ def grafana_create_contact_point(self, data, payload):
else:
raise GrafanaAPIException("Unable to create contact point: %s" % info)
- def grafana_update_contact_point(self, data, payload, contact_point):
+ 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"]),
@@ -401,15 +402,15 @@ def grafana_update_contact_point(self, data, payload, contact_point):
)
if info["status"] == 202:
- if contact_point.get("provenance") and data.get("provisioning"):
- del contact_point["provenance"]
+ if self.contact_point.get("provenance") and data.get("provisioning"):
+ del self.contact_point["provenance"]
- if contact_point == payload:
+ if self.contact_point == payload:
return {"changed": False}
else:
return {
"changed": True,
- "diff": {"before": contact_point, "after": payload},
+ "diff": {"before": self.contact_point, "after": payload},
"contact_point": payload,
}
else:
@@ -654,7 +655,7 @@ def main():
module.params["url"] = clean_url(module.params["url"])
grafana_iface = GrafanaContactPointInterface(module)
- result = grafana_iface.grafana_check_contact_point_match(module.params)
+ result = grafana_iface.grafana_handle_contact_point(module.params)
module.exit_json(failed=False, **result)
From 2801a5733ccb89be76c383386f8425f8d1ad1717 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 20 Mar 2024 15:38:35 +0100
Subject: [PATCH 046/120] fix: change update diff check
---
plugins/modules/grafana_contact_point.py | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index bcf3dc81..0816cf6d 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -402,16 +402,14 @@ def grafana_update_contact_point(self, data, payload):
)
if info["status"] == 202:
- if self.contact_point.get("provenance") and data.get("provisioning"):
- del self.contact_point["provenance"]
-
- if self.contact_point == payload:
+ contact_point = self.grafana_check_contact_point_match(data)
+ if self.contact_point == contact_point:
return {"changed": False}
else:
return {
"changed": True,
- "diff": {"before": self.contact_point, "after": payload},
- "contact_point": payload,
+ "diff": {"before": self.contact_point, "after": contact_point},
+ "contact_point": contact_point,
}
else:
raise GrafanaAPIException(
From 483edd7de6d95063f2d1e76b60b200ebf0fc03e3 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 20 Mar 2024 16:59:09 +0100
Subject: [PATCH 047/120] fix: payload data handling and update diff check
---
plugins/modules/grafana_contact_point.py | 45 +++++++++++++-----------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 0816cf6d..990a4338 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -254,25 +254,26 @@ def grafana_contact_point_payload(data):
type_settings = type_settings_map.get(data["type"])
if type_settings:
for setting_key, data_key in type_settings.items():
- 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]
+ 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
@@ -403,6 +404,10 @@ def grafana_update_contact_point(self, data, payload):
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}
else:
@@ -452,7 +457,7 @@ def main():
"discord",
"email",
"googlechat",
- "kaska",
+ "kafka",
"line",
"opsgenie",
"pagerduty",
From e55a7395f7a0ea8e71c1d47ca1206c849016be36 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 20 Mar 2024 17:00:20 +0100
Subject: [PATCH 048/120] test: all basic tests successful
---
.../grafana_contact_point/tasks/kafka.yml | 4 +--
.../grafana_contact_point/tasks/sensugo.yml | 30 ++++++++++---------
.../grafana_contact_point/tasks/slack.yml | 23 +++++---------
.../grafana_contact_point/tasks/telegram.yml | 4 +--
4 files changed, 27 insertions(+), 34 deletions(-)
diff --git a/tests/integration/targets/grafana_contact_point/tasks/kafka.yml b/tests/integration/targets/grafana_contact_point/tasks/kafka.yml
index bef1106c..2503bbdd 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/kafka.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/kafka.yml
@@ -5,7 +5,7 @@
uid: kafka
name: kafka
type: kafka
- kafka_url: https://example.org
+ kafka_rest_proxy_url: https://example.org
kafka_topic: test
- ansible.builtin.debug:
@@ -21,7 +21,7 @@
uid: kafka
name: kafka
type: kafka
- kafka_url: https://example.org
+ kafka_rest_proxy_url: https://example.org
kafka_topic: test
- ansible.builtin.debug:
diff --git a/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml b/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml
index 902034e4..6cdf0478 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml
@@ -1,11 +1,12 @@
---
-- name: Create sensu contact point
+- name: Create sensugo contact point
register: result
community.grafana.grafana_contact_point:
- uid: sensu
- name: sensu
- type: sensu
- sensu_url: https://example.org
+ uid: sensugo
+ name: sensugo
+ type: sensugo
+ sensugo_url: https://example.org
+ sensugo_api_key: testapikey
- ansible.builtin.debug:
var: result
@@ -14,13 +15,14 @@
that:
- result.changed == True
-- name: Create sensu contact point
+- name: Create sensugo contact point
register: result
community.grafana.grafana_contact_point:
- uid: sensu
- name: sensu
- type: sensu
- sensu_url: https://example.org
+ uid: sensugo
+ name: sensugo
+ type: sensugo
+ sensugo_url: https://example.org
+ sensugo_api_key: testapikey
- ansible.builtin.debug:
var: result
@@ -29,10 +31,10 @@
that:
- result.changed == False
-- name: Delete sensu contact point
+- name: Delete sensugo contact point
register: result
community.grafana.grafana_contact_point:
- uid: sensu
+ uid: sensugo
state: absent
- ansible.builtin.debug:
@@ -42,10 +44,10 @@
that:
- result.changed == True
-- name: Delete sensu contact point (idempotency)
+- name: Delete sensugo contact point (idempotency)
register: result
community.grafana.grafana_contact_point:
- uid: sensu
+ uid: sensugo
state: absent
- ansible.builtin.debug:
diff --git a/tests/integration/targets/grafana_contact_point/tasks/slack.yml b/tests/integration/targets/grafana_contact_point/tasks/slack.yml
index 19c50d21..110ec963 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/slack.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/slack.yml
@@ -6,6 +6,8 @@
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
@@ -14,28 +16,15 @@
that:
- result.changed == True
-- 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
-
-- ansible.builtin.debug:
- var: result
-
-- ansible.builtin.assert:
- that:
- - result.changed == False
-
-- name: Check slack contact point idempotency
+- 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
@@ -51,6 +40,8 @@
name: slack
type: slack
slack_url: https://hooks.slack.com/services/xxx/yyy/fff
+ slack_token: testapitoken
+ slack_recipient: foo
- ansible.builtin.debug:
var: result
diff --git a/tests/integration/targets/grafana_contact_point/tasks/telegram.yml b/tests/integration/targets/grafana_contact_point/tasks/telegram.yml
index fbe207e7..2fd38a5a 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/telegram.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/telegram.yml
@@ -5,7 +5,7 @@
uid: telegram
name: telegram
type: telegram
- telegram_bot_token: xxx
+ telegram_token: xxx
telegram_chat_id: yyy
- ansible.builtin.debug:
@@ -21,7 +21,7 @@
uid: telegram
name: telegram
type: telegram
- telegram_bot_token: xxx
+ telegram_token: xxx
telegram_chat_id: yyy
- ansible.builtin.debug:
From 8835e888ba06afc78845c7c8a42487cbc0ddab80 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 21 Mar 2024 13:34:39 +0100
Subject: [PATCH 049/120] fix: fail definition for grafana < 9
---
plugins/modules/grafana_contact_point.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 990a4338..352dcf8b 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -354,6 +354,10 @@ def grafana_check_contact_point_match(self, data):
(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"
+ )
else:
raise GrafanaAPIException(
"Unable to get contact point '%s': %s" % (data["uid"], info)
From c57708622f520dd3be4174fd8d00d21ca6ba1441 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 21 Mar 2024 13:38:20 +0100
Subject: [PATCH 050/120] test: loop cp task files
---
.../grafana_contact_point/tasks/main.yml | 34 +++++++++++--------
1 file changed, 19 insertions(+), 15 deletions(-)
diff --git a/tests/integration/targets/grafana_contact_point/tasks/main.yml b/tests/integration/targets/grafana_contact_point/tasks/main.yml
index bb94793c..32a2eb15 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/main.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/main.yml
@@ -1,16 +1,20 @@
---
-- ansible.builtin.include_tasks: alertmanager.yml
-- ansible.builtin.include_tasks: dingding.yml
-- ansible.builtin.include_tasks: discord.yml
-- ansible.builtin.include_tasks: email.yml
-- ansible.builtin.include_tasks: googlechat.yml
-- ansible.builtin.include_tasks: kafka.yml
-- ansible.builtin.include_tasks: opsgenie.yml
-- ansible.builtin.include_tasks: pagerduty.yml
-- ansible.builtin.include_tasks: pushover.yml
-- ansible.builtin.include_tasks: sensugo.yml
-- ansible.builtin.include_tasks: slack.yml
-- ansible.builtin.include_tasks: teams.yml
-- ansible.builtin.include_tasks: telegram.yml
-- ansible.builtin.include_tasks: victorops.yml
-- ansible.builtin.include_tasks: webhook.yml
+
+- name: Include contact point task files
+ ansible.builtin.include_tasks: "{{ item }}.yml"
+ loop:
+ - alertmanager
+ - dingding
+ - discord
+ - email
+ - googlechat
+ - kafka
+ - opsgenie
+ - pagerduty
+ - pushover
+ - sensugo
+ - slack
+ - teams
+ - telegram
+ - victorops
+ - webhook
From 5f00dd781e3b14e21406e4abbcc30163e5b55763 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 21 Mar 2024 15:52:19 +0100
Subject: [PATCH 051/120] test: add api endpoint check
---
.../targets/grafana_contact_point/tasks/main.yml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tests/integration/targets/grafana_contact_point/tasks/main.yml b/tests/integration/targets/grafana_contact_point/tasks/main.yml
index 32a2eb15..060ceab8 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/main.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/main.yml
@@ -1,7 +1,15 @@
---
+- 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'"
loop:
- alertmanager
- dingding
From cb5cc0b52f18d878a394030c10b55c26b7c59295 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 5 Apr 2024 11:10:13 +0200
Subject: [PATCH 052/120] chore: todos and rename function
---
plugins/modules/grafana_contact_point.py | 8 +++++---
roles/grafana/README.md | 2 +-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 352dcf8b..bd115459 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -301,7 +301,7 @@ def __init__(self, module):
# }}}
self.contact_point = self.grafana_check_contact_point_match(module.params)
- def grafana_api_provisioning(self, data):
+ def grafana_handle_api_provisioning(self, data):
if not self.contact_point or (
not self.contact_point.get("provenance") and not data.get("provisioning")
):
@@ -311,6 +311,7 @@ def grafana_api_provisioning(self, data):
msg="Unable to update contact point '%s': provisioning cannot be disabled if it's already enabled"
% data["uid"]
)
+ # TODO: else
def grafana_organization_by_name(self, data, org_name):
r, info = fetch_url(
@@ -356,7 +357,7 @@ def grafana_check_contact_point_match(self, data):
return contact_point
elif info["status"] == 404:
self._module.fail_json(
- msg="Unable to get contact point: API endpoint not found"
+ msg="Unable to get contact point: API endpoint not found" # TODO: versionshinweis?!
)
else:
raise GrafanaAPIException(
@@ -367,7 +368,7 @@ def grafana_handle_contact_point(self, data):
payload = grafana_contact_point_payload(data)
if data["state"] == "present":
- self.grafana_api_provisioning(data)
+ self.grafana_handle_api_provisioning(data)
if self.contact_point:
return self.grafana_update_contact_point(data, payload)
else:
@@ -668,3 +669,4 @@ def main():
if __name__ == "__main__":
main()
+# TODO: check api messages
diff --git a/roles/grafana/README.md b/roles/grafana/README.md
index 61de4fc5..6baa5b37 100644
--- a/roles/grafana/README.md
+++ b/roles/grafana/README.md
@@ -172,7 +172,7 @@ 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) |
+| [**grafana_contact_point**](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_contact_point_module.html) | # TODO: parameter
| email_addresses | no |
| email_single | no |
| is_default | no |
From 55ded9129b07bb3b8209d4447399dda4def14020 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 11 Apr 2024 13:28:35 +0200
Subject: [PATCH 053/120] docs: ansible argument docs without desc
---
plugins/modules/grafana_contact_point.py | 560 ++++++++++++++++++++++-
1 file changed, 559 insertions(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index bd115459..dc86a55c 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -28,7 +28,565 @@
short_description: Manage Grafana Contact Points
description:
- Create/Update/Delete Grafana Contact Points via API.
-
+options:
+ disable_resolve_message:
+ description:
+ - desc_text
+ type: bool
+ default: false
+ include_image:
+ description:
+ - desc_text
+ type: bool
+ default: false
+ name:
+ description:
+ - desc_text
+ type: str
+ org_id:
+ description:
+ - desc_text
+ type: int
+ default: 1
+ org_name:
+ description:
+ - desc_text
+ type: str
+ provisioning:
+ description:
+ - desc_text
+ type: bool
+ default: true
+ type:
+ description:
+ - desc_text
+ type: str
+ choices:
+ - alertmanager
+ - dingding
+ - discord
+ - email
+ - googlechat
+ - kafka
+ - line
+ - opsgenie
+ - pagerduty
+ - pushover
+ - sensugo
+ - slack
+ - teams
+ - telegram
+ - threema
+ - victorops
+ - webex
+ - webhook
+ - wecom
+ uid:
+ description:
+ - desc_text
+ type: str
+ alertmanager_password:
+ description:
+ - desc_text
+ type: str
+ alertmanager_url:
+ description:
+ - desc_text
+ type: str
+ alertmanager_username:
+ description:
+ - desc_text
+ type: str
+ dingding_message:
+ description:
+ - desc_text
+ type: str
+ dingding_message_type:
+ description:
+ - desc_text
+ type: str
+ dingding_title:
+ description:
+ - desc_text
+ type: str
+ dingding_url:
+ description:
+ - desc_text
+ type: str
+ discord_avatar_url:
+ description:
+ - desc_text
+ type: str
+ discord_message:
+ description:
+ - desc_text
+ type: str
+ discord_title:
+ description:
+ - desc_text
+ type: str
+ discord_url:
+ description:
+ - desc_text
+ type: str
+ discord_use_username:
+ description:
+ - desc_text
+ type: bool
+ default: false
+ email_addresses:
+ description:
+ - desc_text
+ type: list
+ elements: str
+ email_message:
+ description:
+ - desc_text
+ type: str
+ email_single:
+ description:
+ - desc_text
+ type: bool
+ default: false
+ email_subject:
+ description:
+ - desc_text
+ type: str
+ googlechat_url:
+ description:
+ - desc_text
+ type: str
+ googlechat_message:
+ description:
+ - desc_text
+ type: str
+ googlechat_title:
+ description:
+ - desc_text
+ type: str
+ kafka_api_version:
+ description:
+ - desc_text
+ type: str
+ default: v2
+ kafka_cluster_id:
+ description:
+ - desc_text
+ type: str
+ kafka_description:
+ description:
+ - desc_text
+ type: str
+ kafka_details:
+ description:
+ - desc_text
+ type: str
+ kafka_password:
+ description:
+ - desc_text
+ type: str
+ kafka_rest_proxy_url:
+ description:
+ - desc_text
+ type: str
+ kafka_topic:
+ description:
+ - desc_text
+ type: str
+ kafka_username:
+ description:
+ - desc_text
+ type: str
+ line_description:
+ description:
+ - desc_text
+ type: str
+ line_title:
+ description:
+ - desc_text
+ type: str
+ line_token:
+ description:
+ - desc_text
+ type: str
+ opsgenie_api_key:
+ description:
+ - desc_text
+ type: str
+ opsgenie_auto_close:
+ description:
+ - desc_text
+ type: bool
+ opsgenie_description:
+ description:
+ - desc_text
+ type: str
+ opsgenie_message:
+ description:
+ - desc_text
+ type: str
+ opsgenie_override_priority:
+ description:
+ - desc_text
+ type: bool
+ opsgenie_responders:
+ description:
+ - desc_text
+ type: list
+ elements: dict
+ opsgenie_send_tags_as:
+ description:
+ - desc_text
+ type: str
+ opsgenie_url:
+ description:
+ - desc_text
+ type: str
+ pagerduty_class:
+ description:
+ - desc_text
+ type: str
+ pagerduty_client:
+ description:
+ - desc_text
+ type: str
+ pagerduty_client_url:
+ description:
+ - desc_text
+ type: str
+ pagerduty_component:
+ description:
+ - desc_text
+ type: str
+ pagerduty_details:
+ description:
+ - desc_text
+ type: list
+ elements: dict
+ pagerduty_group:
+ description:
+ - desc_text
+ type: str
+ pagerduty_integration_key:
+ description:
+ - desc_text
+ type: str
+ pagerduty_severity:
+ description:
+ - desc_text
+ type: str
+ choices:
+ - critical
+ - error
+ - warning
+ - info
+ pagerduty_source:
+ description:
+ - desc_text
+ type: str
+ pagerduty_summary:
+ description:
+ - desc_text
+ type: str
+ pushover_api_token:
+ description:
+ - desc_text
+ type: str
+ pushover_devices:
+ description:
+ - desc_text
+ type: list
+ elements: str
+ pushover_expire:
+ description:
+ - desc_text
+ type: int
+ pushover_message:
+ description:
+ - desc_text
+ type: str
+ pushover_ok_priority:
+ description:
+ - desc_text
+ type: int
+ pushover_ok_sound:
+ description:
+ - desc_text
+ type: str
+ pushover_priority:
+ description:
+ - desc_text
+ type: int
+ pushover_retry:
+ description:
+ - desc_text
+ type: int
+ pushover_sound:
+ description:
+ - desc_text
+ type: str
+ pushover_title:
+ description:
+ - desc_text
+ type: str
+ pushover_upload_image:
+ description:
+ - desc_text
+ type: bool
+ default: true
+ pushover_user_key:
+ description:
+ - desc_text
+ type: str
+ sensugo_api_key:
+ description:
+ - desc_text
+ type: str
+ sensugo_url:
+ description:
+ - desc_text
+ type: str
+ sensugo_check:
+ description:
+ - desc_text
+ type: str
+ sensugo_entity:
+ description:
+ - desc_text
+ type: str
+ sensugo_handler:
+ description:
+ - desc_text
+ type: str
+ sensugo_message:
+ description:
+ - desc_text
+ type: str
+ sensugo_namespace:
+ description:
+ - desc_text
+ type: str
+ slack_endpoint_url:
+ description:
+ - desc_text
+ type: str
+ slack_icon_emoji:
+ description:
+ - desc_text
+ type: str
+ slack_icon_url:
+ description:
+ - desc_text
+ type: str
+ slack_mention_channel:
+ description:
+ - desc_text
+ type: str
+ choices:
+ - here
+ - channel
+ slack_mention_groups:
+ description:
+ - desc_text
+ type: list
+ slack_mention_users:
+ description:
+ - desc_text
+ type: list
+ slack_recipient:
+ description:
+ - desc_text
+ type: str
+ slack_text:
+ description:
+ - desc_text
+ type: str
+ slack_title:
+ description:
+ - desc_text
+ type: str
+ slack_token:
+ description:
+ - desc_text
+ type: str
+ slack_url:
+ description:
+ - desc_text
+ type: str
+ slack_username:
+ description:
+ - desc_text
+ type: str
+ teams_message:
+ description:
+ - desc_text
+ type: str
+ teams_section_title:
+ description:
+ - desc_text
+ type: str
+ teams_title:
+ description:
+ - desc_text
+ type: str
+ teams_url:
+ description:
+ - desc_text
+ type: str
+ telegram_chat_id:
+ description:
+ - desc_text
+ type: str
+ telegram_disable_notifications:
+ description:
+ - desc_text
+ type: bool
+ telegram_message:
+ description:
+ - desc_text
+ type: str
+ telegram_parse_mode:
+ description:
+ - desc_text
+ type: str
+ telegram_protect_content:
+ description:
+ - desc_text
+ type: bool
+ telegram_token:
+ description:
+ - desc_text
+ type: str
+ telegram_web_page_view:
+ description:
+ - desc_text
+ type: bool
+ threema_api_secret:
+ description:
+ - desc_text
+ type: str
+ threema_description:
+ description:
+ - desc_text
+ type: str
+ threema_gateway_id:
+ description:
+ - desc_text
+ type: str
+ threema_recipient_id:
+ description:
+ - desc_text
+ type: str
+ threema_title:
+ description:
+ - desc_text
+ type: str
+ victorops_description:
+ description:
+ - desc_text
+ type: str
+ victorops_message_type:
+ description:
+ - desc_text
+ type: str
+ choices:
+ - CRITICAL
+ - RECOVERY
+ victorops_title:
+ description:
+ - desc_text
+ type: str
+ victorops_url:
+ description:
+ - desc_text
+ type: str
+ webex_api_url:
+ description:
+ - desc_text
+ type: str
+ webex_message:
+ description:
+ - desc_text
+ type: str
+ webex_room_id:
+ description:
+ - desc_text
+ type: str
+ webex_token:
+ description:
+ - desc_text
+ type: str
+ webhook_authorization_credentials:
+ description:
+ - desc_text
+ type: str
+ webhook_authorization_scheme:
+ description:
+ - desc_text
+ type: str
+ webhook_http_method:
+ description:
+ - desc_text
+ type: str
+ choices:
+ - POST
+ - PUT
+ webhook_max_alerts:
+ description:
+ - desc_text
+ type: int
+ webhook_message:
+ description:
+ - desc_text
+ type: str
+ webhook_password:
+ description:
+ - desc_text
+ type: str
+ webhook_title:
+ description:
+ - desc_text
+ type: str
+ webhook_url:
+ description:
+ - desc_text
+ type: str
+ webhook_username:
+ description:
+ - desc_text
+ type: str
+ wecom_agent_id:
+ description:
+ - desc_text
+ type: str
+ wecom_corp_id:
+ description:
+ - desc_text
+ type: str
+ wecom_message:
+ description:
+ - desc_text
+ type: str
+ wecom_msg_type:
+ description:
+ - desc_text
+ type: str
+ wecom_secret:
+ description:
+ - desc_text
+ type: str
+ wecom_title:
+ description:
+ - desc_text
+ type: str
+ wecom_to_user:
+ description:
+ - desc_text
+ type: list
+ wecom_url:
+ description:
+ - desc_text
+ type: str
extends_documentation_fragment:
- community.grafana.basic_auth
- community.grafana.api_key
From d229b0103023335f4adf4dbb2ee5ad4e9c984e4c Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 11 Apr 2024 13:39:21 +0200
Subject: [PATCH 054/120] chore: added else for provisioning handling and api
version error message
---
plugins/modules/grafana_contact_point.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index dc86a55c..e679086d 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -869,7 +869,11 @@ def grafana_handle_api_provisioning(self, data):
msg="Unable to update contact point '%s': provisioning cannot be disabled if it's already enabled"
% data["uid"]
)
- # TODO: else
+ else:
+ self._module.fail_json(
+ msg="Unable to update contact point '%s': error while handling provisioning"
+ % data["uid"]
+ )
def grafana_organization_by_name(self, data, org_name):
r, info = fetch_url(
@@ -915,7 +919,7 @@ def grafana_check_contact_point_match(self, data):
return contact_point
elif info["status"] == 404:
self._module.fail_json(
- msg="Unable to get contact point: API endpoint not found" # TODO: versionshinweis?!
+ msg="Unable to get contact point: API endpoint not found - please check your Grafana version"
)
else:
raise GrafanaAPIException(
From fb996b754bd744aae342d3e3503c58fb9b02c7ed Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 11 Apr 2024 13:49:55 +0200
Subject: [PATCH 055/120] fix: pass if provisioning is else
---
plugins/modules/grafana_contact_point.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index e679086d..573908b0 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -870,10 +870,7 @@ def grafana_handle_api_provisioning(self, data):
% data["uid"]
)
else:
- self._module.fail_json(
- msg="Unable to update contact point '%s': error while handling provisioning"
- % data["uid"]
- )
+ pass
def grafana_organization_by_name(self, data, org_name):
r, info = fetch_url(
From 5ea99a50ca089e1cf2e8beb0b0368408994778b5 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 11 Apr 2024 14:04:10 +0200
Subject: [PATCH 056/120] test: fix grafana version check
---
tests/integration/targets/grafana_contact_point/tasks/main.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/integration/targets/grafana_contact_point/tasks/main.yml b/tests/integration/targets/grafana_contact_point/tasks/main.yml
index 060ceab8..83a6dc67 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/main.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/main.yml
@@ -9,7 +9,7 @@
- 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'"
+ when: "result.msg | default('') != 'Unable to get contact point: API endpoint not found - please check your Grafana version'"
loop:
- alertmanager
- dingding
From 8a00cd0d43538dee8f34755d1b300fbfffa41992 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 11 Apr 2024 14:13:15 +0200
Subject: [PATCH 057/120] chore: argument section comments
---
plugins/modules/grafana_contact_point.py | 38 ++++++++++++------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 573908b0..f191cb84 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -1038,31 +1038,31 @@ def main():
],
),
uid=dict(type="str"),
- # type: alertmanager
+ # alertmanager
alertmanager_password=dict(type="str", no_log=True),
alertmanager_url=dict(type="str"),
alertmanager_username=dict(type="str"),
- # type: dingding
+ # dingding
dingding_message=dict(type="str"),
dingding_message_type=dict(type="str"),
dingding_title=dict(type="str"),
dingding_url=dict(type="str"),
- # type: discord
+ # 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),
- # type: email
+ # 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"),
- # type: googlechat
+ # googlechat
googlechat_url=dict(type="str", no_log=True),
googlechat_message=dict(type="str"),
googlechat_title=dict(type="str"),
- # type: kafka
+ # kafka
kafka_api_version=dict(type="str", default="v2"),
kafka_cluster_id=dict(type="str"),
kafka_description=dict(type="str"),
@@ -1071,11 +1071,11 @@ def main():
kafka_rest_proxy_url=dict(type="str", no_log=True),
kafka_topic=dict(type="str"),
kafka_username=dict(type="str"),
- # type: line
+ # line
line_description=dict(type="str"),
line_title=dict(type="str"),
line_token=dict(type="str", no_log=True),
- # type: opsgenie
+ # opsgenie
opsgenie_api_key=dict(type="str", no_log=True),
opsgenie_auto_close=dict(type="bool"),
opsgenie_description=dict(type="str"),
@@ -1084,7 +1084,7 @@ def main():
opsgenie_responders=dict(type="list", elements="dict"),
opsgenie_send_tags_as=dict(type="str"),
opsgenie_url=dict(type="str"),
- # type: pagerduty
+ # pagerduty
pagerduty_class=dict(type="str"),
pagerduty_client=dict(type="str"),
pagerduty_client_url=dict(type="str"),
@@ -1097,7 +1097,7 @@ def main():
),
pagerduty_source=dict(type="str"),
pagerduty_summary=dict(type="str"),
- # type: pushover
+ # pushover
pushover_api_token=dict(type="str", no_log=True),
pushover_devices=dict(type="list", elements="str"),
pushover_expire=dict(type="int"),
@@ -1110,7 +1110,7 @@ def main():
pushover_title=dict(type="str"),
pushover_upload_image=dict(type="bool", default=True),
pushover_user_key=dict(type="str", no_log=True),
- # type: sensugo
+ # sensugo
sensugo_api_key=dict(type="str", no_log=True),
sensugo_url=dict(type="str"),
sensugo_check=dict(type="str"),
@@ -1118,7 +1118,7 @@ def main():
sensugo_handler=dict(type="str"),
sensugo_message=dict(type="str"),
sensugo_namespace=dict(type="str"),
- # type: slack
+ # slack
slack_endpoint_url=dict(type="str"),
slack_icon_emoji=dict(type="str"),
slack_icon_url=dict(type="str"),
@@ -1131,12 +1131,12 @@ def main():
slack_token=dict(type="str", no_log=True),
slack_url=dict(type="str", no_log=True),
slack_username=dict(type="str"),
- # type: teams
+ # 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),
- # type: telegram
+ # telegram
telegram_chat_id=dict(type="str"),
telegram_disable_notifications=dict(type="bool"),
telegram_message=dict(type="str"),
@@ -1144,23 +1144,23 @@ def main():
telegram_protect_content=dict(type="bool"),
telegram_token=dict(type="str", no_log=True),
telegram_web_page_view=dict(type="bool"),
- # type: threema
+ # 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"),
- # type: victorops
+ # 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"),
- # type: webex
+ # 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),
- # type: webhook
+ # 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"]),
@@ -1170,7 +1170,7 @@ def main():
webhook_title=dict(type="str"),
webhook_url=dict(type="str"),
webhook_username=dict(type="str"),
- # type: wecom
+ # wecom
wecom_agent_id=dict(type="str"),
wecom_corp_id=dict(type="str"),
wecom_message=dict(type="str"),
From 3f29357542efafd5c3ccb84be68f5560a7903fa1 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 11 Apr 2024 14:23:15 +0200
Subject: [PATCH 058/120] docs: module docs sanity findings
---
plugins/modules/grafana_contact_point.py | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index f191cb84..26bbf3db 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -57,6 +57,14 @@
- desc_text
type: bool
default: true
+ state:
+ description:
+ - Status of the contact point
+ type: str
+ default: present
+ choices:
+ - present
+ - absent
type:
description:
- desc_text
@@ -389,10 +397,12 @@
description:
- desc_text
type: list
+ elements: str
slack_mention_users:
description:
- desc_text
type: list
+ elements: str
slack_recipient:
description:
- desc_text
@@ -583,6 +593,7 @@
description:
- desc_text
type: list
+ elements: str
wecom_url:
description:
- desc_text
@@ -618,6 +629,7 @@
contact_point:
description: Contact point created or updated by the module.
returned: changed
+ type: dict
"""
import json
@@ -1123,8 +1135,8 @@ def main():
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"),
- slack_mention_users=dict(type="list"),
+ 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"),
@@ -1177,7 +1189,7 @@ def main():
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"),
+ wecom_to_user=dict(type="list", elements="str"),
wecom_url=dict(type="str", no_log=True),
)
From dfd918d6c28257be59d4cbff3e9b100355d3a1cb Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 11:05:07 +0200
Subject: [PATCH 059/120] docs: role parameters
---
roles/grafana/README.md | 130 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 125 insertions(+), 5 deletions(-)
diff --git a/roles/grafana/README.md b/roles/grafana/README.md
index 6baa5b37..09901eff 100644
--- a/roles/grafana/README.md
+++ b/roles/grafana/README.md
@@ -172,16 +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) | # TODO: parameter
-| email_addresses | no |
-| email_single | no |
-| is_default | no |
-| name | yes |
+| [**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 | yes |
| uid | no |
+| 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_url | no |
+| googlechat_message | no |
+| googlechat_title | 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_url | no |
+| sensugo_check | no |
+| sensugo_entity | no |
+| sensugo_handler | no |
+| sensugo_message | no |
+| sensugo_namespace | 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
From 242aa554e13dcc6279ce517a5e25ad9a29713d22 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 11:18:47 +0200
Subject: [PATCH 060/120] docs: module args description texts (thanks chatgpt)
---
plugins/modules/grafana_contact_point.py | 258 +++++++++++------------
1 file changed, 129 insertions(+), 129 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 26bbf3db..2bdb3dea 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -31,35 +31,35 @@
options:
disable_resolve_message:
description:
- - desc_text
+ - Disables the resolve message.
type: bool
default: false
include_image:
description:
- - desc_text
+ - Whether to include an image in the notification.
type: bool
default: false
name:
description:
- - desc_text
+ - The name of the contact point.
type: str
org_id:
description:
- - desc_text
+ - The organization ID.
type: int
default: 1
org_name:
description:
- - desc_text
+ - The name of the organization.
type: str
provisioning:
description:
- - desc_text
+ - Indicates if provisioning is enabled.
type: bool
default: true
state:
description:
- - Status of the contact point
+ - Status of the contact point.
type: str
default: present
choices:
@@ -67,7 +67,7 @@
- absent
type:
description:
- - desc_text
+ - The type of the contact point.
type: str
choices:
- alertmanager
@@ -91,197 +91,197 @@
- wecom
uid:
description:
- - desc_text
+ - The unique ID of the contact point.
type: str
alertmanager_password:
description:
- - desc_text
+ - Password for accessing Alertmanager.
type: str
alertmanager_url:
description:
- - desc_text
+ - URL for accessing Alertmanager.
type: str
alertmanager_username:
description:
- - desc_text
+ - Username for accessing Alertmanager.
type: str
dingding_message:
description:
- - desc_text
+ - The message to send via DingDing.
type: str
dingding_message_type:
description:
- - desc_text
+ - The type of message to send via DingDing.
type: str
dingding_title:
description:
- - desc_text
+ - The title of the DingDing message.
type: str
dingding_url:
description:
- - desc_text
+ - The URL for DingDing webhook.
type: str
discord_avatar_url:
description:
- - desc_text
+ - The avatar URL for Discord messages.
type: str
discord_message:
description:
- - desc_text
+ - The message to send via Discord.
type: str
discord_title:
description:
- - desc_text
+ - The title of the Discord message.
type: str
discord_url:
description:
- - desc_text
+ - The URL for Discord webhook.
type: str
discord_use_username:
description:
- - desc_text
+ - Whether to use a custom username in Discord.
type: bool
default: false
email_addresses:
description:
- - desc_text
+ - List of email addresses to send the message to.
type: list
elements: str
email_message:
description:
- - desc_text
+ - The content of the email message.
type: str
email_single:
description:
- - desc_text
+ - Whether to send a single email or individual emails.
type: bool
default: false
email_subject:
description:
- - desc_text
+ - The subject of the email.
type: str
googlechat_url:
description:
- - desc_text
+ - The URL for Google Chat webhook.
type: str
googlechat_message:
description:
- - desc_text
+ - The message to send via Google Chat.
type: str
googlechat_title:
description:
- - desc_text
+ - The title of the Google Chat message.
type: str
kafka_api_version:
description:
- - desc_text
+ - The API version for Kafka.
type: str
default: v2
kafka_cluster_id:
description:
- - desc_text
+ - The cluster ID for Kafka.
type: str
kafka_description:
description:
- - desc_text
+ - The description for the Kafka configuration.
type: str
kafka_details:
description:
- - desc_text
+ - Additional details for Kafka.
type: str
kafka_password:
description:
- - desc_text
+ - Password for accessing Kafka.
type: str
kafka_rest_proxy_url:
description:
- - desc_text
+ - URL for Kafka REST Proxy.
type: str
kafka_topic:
description:
- - desc_text
+ - Kafka topic to publish to.
type: str
kafka_username:
description:
- - desc_text
+ - Username for accessing Kafka.
type: str
line_description:
description:
- - desc_text
+ - Description for the Line message.
type: str
line_title:
description:
- - desc_text
+ - Title of the Line message.
type: str
line_token:
description:
- - desc_text
+ - Access token for Line.
type: str
opsgenie_api_key:
description:
- - desc_text
+ - API key for OpsGenie.
type: str
opsgenie_auto_close:
description:
- - desc_text
+ - Whether to enable auto-closing of alerts in OpsGenie.
type: bool
opsgenie_description:
description:
- - desc_text
+ - Description of the OpsGenie alert.
type: str
opsgenie_message:
description:
- - desc_text
+ - Message to send via OpsGenie.
type: str
opsgenie_override_priority:
description:
- - desc_text
+ - Whether to override the priority in OpsGenie.
type: bool
opsgenie_responders:
description:
- - desc_text
+ - List of responders for OpsGenie alerts.
type: list
elements: dict
opsgenie_send_tags_as:
description:
- - desc_text
+ - Format for sending tags in OpsGenie.
type: str
opsgenie_url:
description:
- - desc_text
+ - URL for OpsGenie webhook.
type: str
pagerduty_class:
description:
- - desc_text
+ - Class of the PagerDuty alert.
type: str
pagerduty_client:
description:
- - desc_text
+ - Client identifier for PagerDuty.
type: str
pagerduty_client_url:
description:
- - desc_text
+ - Client URL for PagerDuty.
type: str
pagerduty_component:
description:
- - desc_text
+ - Component involved in the PagerDuty alert.
type: str
pagerduty_details:
description:
- - desc_text
+ - List of additional details for PagerDuty.
type: list
elements: dict
pagerduty_group:
description:
- - desc_text
+ - Group associated with the PagerDuty alert.
type: str
pagerduty_integration_key:
description:
- - desc_text
+ - Integration key for PagerDuty.
type: str
pagerduty_severity:
description:
- - desc_text
+ - Severity level of the PagerDuty alert.
type: str
choices:
- critical
@@ -290,313 +290,313 @@
- info
pagerduty_source:
description:
- - desc_text
+ - Source of the PagerDuty alert.
type: str
pagerduty_summary:
description:
- - desc_text
+ - Summary of the PagerDuty alert.
type: str
pushover_api_token:
description:
- - desc_text
+ - API token for Pushover.
type: str
pushover_devices:
description:
- - desc_text
+ - List of devices for Pushover notifications.
type: list
elements: str
pushover_expire:
description:
- - desc_text
+ - Expiration time for Pushover notifications.
type: int
pushover_message:
description:
- - desc_text
+ - Message to send via Pushover.
type: str
pushover_ok_priority:
description:
- - desc_text
+ - Priority for OK messages in Pushover.
type: int
pushover_ok_sound:
description:
- - desc_text
+ - Sound for OK messages in Pushover.
type: str
pushover_priority:
description:
- - desc_text
+ - Priority for Pushover messages.
type: int
pushover_retry:
description:
- - desc_text
+ - Retry interval for Pushover messages.
type: int
pushover_sound:
description:
- - desc_text
+ - Sound for Pushover notifications.
type: str
pushover_title:
description:
- - desc_text
+ - Title of the Pushover message.
type: str
pushover_upload_image:
description:
- - desc_text
+ - Whether to upload an image with Pushover notification.
type: bool
default: true
pushover_user_key:
description:
- - desc_text
+ - User key for Pushover.
type: str
sensugo_api_key:
description:
- - desc_text
+ - API key for Sensu Go.
type: str
sensugo_url:
description:
- - desc_text
+ - URL for Sensu Go.
type: str
sensugo_check:
description:
- - desc_text
+ - Check name for Sensu Go.
type: str
sensugo_entity:
description:
- - desc_text
+ - Entity name for Sensu Go.
type: str
sensugo_handler:
description:
- - desc_text
+ - Handler for Sensu Go.
type: str
sensugo_message:
description:
- - desc_text
+ - Message to send via Sensu Go.
type: str
sensugo_namespace:
description:
- - desc_text
+ - Namespace for Sensu Go.
type: str
slack_endpoint_url:
description:
- - desc_text
+ - Endpoint URL for Slack webhook.
type: str
slack_icon_emoji:
description:
- - desc_text
+ - Icon emoji for Slack messages.
type: str
slack_icon_url:
description:
- - desc_text
+ - Icon URL for Slack messages.
type: str
slack_mention_channel:
description:
- - desc_text
+ - Channel mention for Slack messages.
type: str
choices:
- here
- channel
slack_mention_groups:
description:
- - desc_text
+ - List of groups to mention in Slack messages.
type: list
elements: str
slack_mention_users:
description:
- - desc_text
+ - List of users to mention in Slack messages.
type: list
elements: str
slack_recipient:
description:
- - desc_text
+ - Recipient for Slack messages.
type: str
slack_text:
description:
- - desc_text
+ - Text content for Slack messages.
type: str
slack_title:
description:
- - desc_text
+ - Title of the Slack message.
type: str
slack_token:
description:
- - desc_text
+ - Token for Slack authentication.
type: str
slack_url:
description:
- - desc_text
+ - URL for Slack webhook.
type: str
slack_username:
description:
- - desc_text
+ - Username to use in Slack messages.
type: str
teams_message:
description:
- - desc_text
+ - Message to send via Microsoft Teams.
type: str
teams_section_title:
description:
- - desc_text
+ - Section title for Microsoft Teams messages.
type: str
teams_title:
description:
- - desc_text
+ - Title of the Microsoft Teams message.
type: str
teams_url:
description:
- - desc_text
+ - URL for Microsoft Teams webhook.
type: str
telegram_chat_id:
description:
- - desc_text
+ - Chat ID for Telegram.
type: str
telegram_disable_notifications:
description:
- - desc_text
+ - Whether to disable notifications for Telegram messages.
type: bool
telegram_message:
description:
- - desc_text
+ - Message to send via Telegram.
type: str
telegram_parse_mode:
description:
- - desc_text
+ - Parse mode for Telegram messages.
type: str
telegram_protect_content:
description:
- - desc_text
+ - Whether to protect content in Telegram messages.
type: bool
telegram_token:
description:
- - desc_text
+ - Token for Telegram authentication.
type: str
telegram_web_page_view:
description:
- - desc_text
+ - Whether to enable web page preview in Telegram messages.
type: bool
threema_api_secret:
description:
- - desc_text
+ - API secret for Threema.
type: str
threema_description:
description:
- - desc_text
+ - Description for Threema messages.
type: str
threema_gateway_id:
description:
- - desc_text
+ - Gateway ID for Threema.
type: str
threema_recipient_id:
description:
- - desc_text
+ - Recipient ID for Threema messages.
type: str
threema_title:
description:
- - desc_text
+ - Title of the Threema message.
type: str
victorops_description:
description:
- - desc_text
+ - Description for VictorOps messages.
type: str
victorops_message_type:
description:
- - desc_text
+ - Message type for VictorOps.
type: str
choices:
- CRITICAL
- RECOVERY
victorops_title:
description:
- - desc_text
+ - Title of the VictorOps message.
type: str
victorops_url:
description:
- - desc_text
+ - URL for VictorOps webhook.
type: str
webex_api_url:
description:
- - desc_text
+ - API URL for Webex.
type: str
webex_message:
description:
- - desc_text
+ - Message to send via Webex.
type: str
webex_room_id:
description:
- - desc_text
+ - Room ID for Webex messages.
type: str
webex_token:
description:
- - desc_text
+ - Token for Webex authentication.
type: str
webhook_authorization_credentials:
description:
- - desc_text
+ - Authorization credentials for webhook.
type: str
webhook_authorization_scheme:
description:
- - desc_text
+ - Authorization scheme for webhook.
type: str
webhook_http_method:
description:
- - desc_text
+ - HTTP method for webhook.
type: str
choices:
- POST
- PUT
webhook_max_alerts:
description:
- - desc_text
+ - Maximum number of alerts for webhook.
type: int
webhook_message:
description:
- - desc_text
+ - Message to send via webhook.
type: str
webhook_password:
description:
- - desc_text
+ - Password for webhook authentication.
type: str
webhook_title:
description:
- - desc_text
+ - Title of the webhook message.
type: str
webhook_url:
description:
- - desc_text
+ - URL for webhook.
type: str
webhook_username:
description:
- - desc_text
+ - Username for webhook authentication.
type: str
wecom_agent_id:
description:
- - desc_text
+ - Agent ID for WeCom.
type: str
wecom_corp_id:
description:
- - desc_text
+ - Corporate ID for WeCom.
type: str
wecom_message:
description:
- - desc_text
+ - Message to send via WeCom.
type: str
wecom_msg_type:
description:
- - desc_text
+ - Message type for WeCom.
type: str
wecom_secret:
description:
- - desc_text
+ - Secret for WeCom authentication.
type: str
wecom_title:
description:
- - desc_text
+ - Title of the WeCom message.
type: str
wecom_to_user:
description:
- - desc_text
+ - List of users to send the WeCom message to.
type: list
elements: str
wecom_url:
description:
- - desc_text
+ - URL for WeCom webhook.
type: str
extends_documentation_fragment:
- community.grafana.basic_auth
From d1e9674e4ce565d36e452d2c1488eb40ebef4d9a Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 13:23:43 +0200
Subject: [PATCH 061/120] docs: module return values
---
plugins/modules/grafana_contact_point.py | 74 ++++++++++++++++++++++--
1 file changed, 70 insertions(+), 4 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 2bdb3dea..5ec00561 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -628,8 +628,75 @@
RETURN = """
contact_point:
description: Contact point created or updated by the module.
- returned: changed
+ 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.
+ return: changed
type: dict
+ contains:
+ before:
+ description: Previous contact point.
+ return: changed
+ type: complex
+ sample:
+ - uid: ddmyrs0f74t8hc
+ name: supportmail
+ type: email
+ disableResolveMessage: false
+ settings:
+ addresses: support@example.com
+ singleEmail: false
+ secureFields: {}
+ after:
+ description: Current contact point.
+ return: changed
+ type: complex
+ sample:
+ - uid: ddmyrs0f74t8hc
+ name: supportmail
+ type: email
+ disableResolveMessage: true
+ settings:
+ addresses: support123@example.com
+ singleEmail: false
+ secureFields: {}
"""
import json
@@ -963,7 +1030,6 @@ def grafana_create_contact_point(self, data, payload):
contact_point = json.loads(to_text(r.read()))
return {
"changed": True,
- "state": data["state"],
"contact_point": contact_point,
}
else:
@@ -985,7 +1051,7 @@ def grafana_update_contact_point(self, data, payload):
del contact_point["provenance"]
if self.contact_point == contact_point:
- return {"changed": False}
+ return {"changed": False, "contact_point": contact_point}
else:
return {
"changed": True,
@@ -1006,7 +1072,7 @@ def grafana_delete_contact_point(self, data):
)
if info["status"] == 202:
- return {"state": "absent", "changed": True}
+ return {"changed": True, "contact_point": contact_point}
elif info["status"] == 404:
return {"changed": False}
else:
From 6fc012f7b5086fb8e294135041d759c087c3ce9c Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 14:08:56 +0200
Subject: [PATCH 062/120] fix: contact point var ref
---
plugins/modules/grafana_contact_point.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 5ec00561..fc0a2ad9 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -1072,7 +1072,7 @@ def grafana_delete_contact_point(self, data):
)
if info["status"] == 202:
- return {"changed": True, "contact_point": contact_point}
+ return {"changed": True, "contact_point": self.contact_point}
elif info["status"] == 404:
return {"changed": False}
else:
From 45e7798f29f3ea99bad53712eb8ebcc34881b735 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Mon, 27 May 2024 14:16:17 +0200
Subject: [PATCH 063/120] docs: return returned type
---
plugins/modules/grafana_contact_point.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index fc0a2ad9..62d58767 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -668,12 +668,12 @@
type: dict
diff:
description: Difference between previous and updated contact point.
- return: changed
+ returned: changed
type: dict
contains:
before:
description: Previous contact point.
- return: changed
+ returned: changed
type: complex
sample:
- uid: ddmyrs0f74t8hc
@@ -686,7 +686,7 @@
secureFields: {}
after:
description: Current contact point.
- return: changed
+ returned: changed
type: complex
sample:
- uid: ddmyrs0f74t8hc
From b11720cab21ddd87820e2d94037296e817388c40 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 09:37:48 +0200
Subject: [PATCH 064/120] docs: return values
---
plugins/modules/grafana_contact_point.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 62d58767..464ccd78 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -669,12 +669,12 @@
diff:
description: Difference between previous and updated contact point.
returned: changed
- type: dict
+ type: complex
contains:
before:
description: Previous contact point.
returned: changed
- type: complex
+ type: dict
sample:
- uid: ddmyrs0f74t8hc
name: supportmail
@@ -687,7 +687,7 @@
after:
description: Current contact point.
returned: changed
- type: complex
+ type: dict
sample:
- uid: ddmyrs0f74t8hc
name: supportmail
From 2a393b629832ca806521055b48c7f0d50343eb05 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 09:38:09 +0200
Subject: [PATCH 065/120] chore: add state to return
---
plugins/modules/grafana_contact_point.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 464ccd78..3a85207e 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -1015,7 +1015,7 @@ def grafana_handle_contact_point(self, data):
if self.contact_point:
return self.grafana_delete_contact_point(data)
else:
- return {"changed": False}
+ return {"changed": False, "state": data["state"]}
def grafana_create_contact_point(self, data, payload):
r, info = fetch_url(
@@ -1031,6 +1031,7 @@ def grafana_create_contact_point(self, data, payload):
return {
"changed": True,
"contact_point": contact_point,
+ "state": data["state"],
}
else:
raise GrafanaAPIException("Unable to create contact point: %s" % info)
@@ -1051,12 +1052,13 @@ def grafana_update_contact_point(self, data, payload):
del contact_point["provenance"]
if self.contact_point == contact_point:
- return {"changed": False, "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(
@@ -1072,9 +1074,9 @@ def grafana_delete_contact_point(self, data):
)
if info["status"] == 202:
- return {"changed": True, "contact_point": self.contact_point}
+ return {"changed": True, "contact_point": self.contact_point, "state": data["state"]}
elif info["status"] == 404:
- return {"changed": False}
+ return {"changed": False, "state": data["state"]}
else:
raise GrafanaAPIException(
"Unable to delete contact point '%s': %s" % (data["uid"], info)
From c4510df0b851a7410914a16632cd2fbc40b27b46 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 09:39:41 +0200
Subject: [PATCH 066/120] style: formatting black
---
plugins/modules/grafana_contact_point.py | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 3a85207e..a8e86dbf 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -1052,7 +1052,11 @@ def grafana_update_contact_point(self, data, payload):
del contact_point["provenance"]
if self.contact_point == contact_point:
- return {"changed": False, "contact_point": contact_point, "state": data["state"]}
+ return {
+ "changed": False,
+ "contact_point": contact_point,
+ "state": data["state"],
+ }
else:
return {
"changed": True,
@@ -1074,7 +1078,11 @@ def grafana_delete_contact_point(self, data):
)
if info["status"] == 202:
- return {"changed": True, "contact_point": self.contact_point, "state": data["state"]}
+ return {
+ "changed": True,
+ "contact_point": self.contact_point,
+ "state": data["state"],
+ }
elif info["status"] == 404:
return {"changed": False, "state": data["state"]}
else:
From 11a3f75c15e9be76ce94e0654df8fedd279402f0 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 10:33:38 +0200
Subject: [PATCH 067/120] docs: required if references
---
plugins/modules/grafana_contact_point.py | 34 +++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index a8e86dbf..368d1e85 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -100,6 +100,7 @@
alertmanager_url:
description:
- URL for accessing Alertmanager.
+ - Required when C(type) is C(alertmanager).
type: str
alertmanager_username:
description:
@@ -120,6 +121,7 @@
dingding_url:
description:
- The URL for DingDing webhook.
+ - Required when C(type) is C(dingding).
type: str
discord_avatar_url:
description:
@@ -136,6 +138,7 @@
discord_url:
description:
- The URL for Discord webhook.
+ - Required when C(type) is C(discord).
type: str
discord_use_username:
description:
@@ -145,6 +148,7 @@
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:
@@ -163,6 +167,7 @@
googlechat_url:
description:
- The URL for Google Chat webhook.
+ - Required when C(type) is C(webhook).
type: str
googlechat_message:
description:
@@ -196,10 +201,12 @@
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:
@@ -216,10 +223,12 @@
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:
@@ -249,6 +258,7 @@
opsgenie_url:
description:
- URL for OpsGenie webhook.
+ - Required when C(type) is C(pagerduty).
type: str
pagerduty_class:
description:
@@ -278,6 +288,7 @@
pagerduty_integration_key:
description:
- Integration key for PagerDuty.
+ - Required when C(type) is C(pagerduty).
type: str
pagerduty_severity:
description:
@@ -299,6 +310,7 @@
pushover_api_token:
description:
- API token for Pushover.
+ - Required when C(type) is C(pushover).
type: str
pushover_devices:
description:
@@ -345,14 +357,17 @@
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:
@@ -406,6 +421,7 @@
slack_recipient:
description:
- Recipient for Slack messages.
+ - Required when C(type) is C(slack).
type: str
slack_text:
description:
@@ -418,10 +434,12 @@
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:
@@ -442,10 +460,12 @@
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:
@@ -466,6 +486,7 @@
telegram_token:
description:
- Token for Telegram authentication.
+ - Required when C(type) is C(telegram).
type: str
telegram_web_page_view:
description:
@@ -474,6 +495,7 @@
threema_api_secret:
description:
- API secret for Threema.
+ - Required when C(type) is C(threema).
type: str
threema_description:
description:
@@ -482,10 +504,12 @@
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:
@@ -509,6 +533,7 @@
victorops_url:
description:
- URL for VictorOps webhook.
+ - Required when C(type) is C(victorops).
type: str
webex_api_url:
description:
@@ -521,10 +546,12 @@
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:
@@ -560,6 +587,7 @@
webhook_url:
description:
- URL for webhook.
+ - Required when C(type) is C(webhook).
type: str
webhook_username:
description:
@@ -568,10 +596,12 @@
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:
@@ -584,6 +614,7 @@
wecom_secret:
description:
- Secret for WeCom authentication.
+ - Required when C(type) is C(wecom).
type: str
wecom_title:
description:
@@ -597,6 +628,7 @@
wecom_url:
description:
- URL for WeCom webhook.
+ - Required when C(type) is C(wecom).
type: str
extends_documentation_fragment:
- community.grafana.basic_auth
@@ -1284,7 +1316,7 @@ def main():
["type", "googlechat", ["googlechat_url"]],
["type", "kafka", ["kafka_rest_proxy_url", "kafka_topic"]],
["type", "line", ["line_token"]],
- ["type", "opsgenie", ["opsgenie_api_key"]],
+ ["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"]],
From 2d552cb953ae09c6024817902a4d787cc8f2073c Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 11:55:22 +0200
Subject: [PATCH 068/120] fix: uid required
---
plugins/modules/grafana_contact_point.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 368d1e85..ef574642 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -42,6 +42,7 @@
name:
description:
- The name of the contact point.
+ - Required when C(state) is C(present).
type: str
org_id:
description:
@@ -68,6 +69,7 @@
type:
description:
- The type of the contact point.
+ - Required when C(state) is C(present).
type: str
choices:
- alertmanager
@@ -92,7 +94,9 @@
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.
@@ -1307,7 +1311,7 @@ def main():
required_together=[["url_username", "url_password", "org_id"]],
mutually_exclusive=[["url_username", "grafana_api_key"]],
required_if=[
- ["state", "present", ["name", "type"]],
+ ["state", "present", ["uid", "name", "type"]],
["state", "absent", ["uid"]],
["type", "alertmanager", ["alertmanager_url"]],
["type", "dingding", ["dingding_url"]],
From 8f6e14d9e73e03f078b849ed781d8d0fbbbc541e Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 11:56:05 +0200
Subject: [PATCH 069/120] test: add update task and extend asserts
---
.../tasks/alertmanager.yml | 39 ++++++++++++++--
.../grafana_contact_point/tasks/dingding.yml | 39 ++++++++++++++--
.../grafana_contact_point/tasks/discord.yml | 39 ++++++++++++++--
.../grafana_contact_point/tasks/email.yml | 46 ++++++++++++++++---
.../tasks/googlechat.yml | 39 ++++++++++++++--
.../grafana_contact_point/tasks/kafka.yml | 40 ++++++++++++++--
.../grafana_contact_point/tasks/line.yml | 39 ++++++++++++++--
.../grafana_contact_point/tasks/opsgenie.yml | 41 +++++++++++++++--
.../grafana_contact_point/tasks/pagerduty.yml | 39 ++++++++++++++--
.../grafana_contact_point/tasks/pushover.yml | 40 ++++++++++++++--
.../grafana_contact_point/tasks/sensugo.yml | 40 ++++++++++++++--
.../grafana_contact_point/tasks/slack.yml | 32 +++++++++----
.../grafana_contact_point/tasks/teams.yml | 39 ++++++++++++++--
.../grafana_contact_point/tasks/telegram.yml | 40 ++++++++++++++--
.../grafana_contact_point/tasks/threema.yml | 41 +++++++++++++++--
.../grafana_contact_point/tasks/victorops.yml | 39 ++++++++++++++--
.../grafana_contact_point/tasks/webhook.yml | 39 ++++++++++++++--
17 files changed, 595 insertions(+), 76 deletions(-)
diff --git a/tests/integration/targets/grafana_contact_point/tasks/alertmanager.yml b/tests/integration/targets/grafana_contact_point/tasks/alertmanager.yml
index 6ca4b934..9fd23797 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/alertmanager.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/alertmanager.yml
@@ -12,7 +12,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -27,7 +31,31 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -40,7 +68,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "alertmanager"
- name: Delete alertmanager contact point (idempotency)
register: result
@@ -53,4 +83,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 5b14a909..b2fee63c 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/dingding.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/dingding.yml
@@ -12,7 +12,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -27,7 +31,31 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -40,7 +68,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "dingding"
- name: Delete dingding contact point (idempotency)
register: result
@@ -53,4 +83,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 89e62daa..a968d440 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/discord.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/discord.yml
@@ -12,7 +12,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -27,7 +31,31 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -40,7 +68,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "discord"
- name: Delete discord contact point (idempotency)
register: result
@@ -53,4 +83,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 91aeba8b..1d08ff03 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/email.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/email.yml
@@ -14,7 +14,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -31,9 +35,35 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - not result.changed
+ - result.state == "present"
+ - result.contact_point.uid == "email"
+ - result.contact_point.name == "email"
+ - result.contact_point.type == "email"
-- name: Delete discord contact point
+- 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
@@ -44,10 +74,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
- - result.state == 'absent'
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "email"
-- name: Delete discord contact point (idempotency)
+- name: Delete email contact point (idempotency)
register: result
community.grafana.grafana_contact_point:
uid: email
@@ -58,4 +89,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 1243ca04..fdc13b96 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/googlechat.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/googlechat.yml
@@ -12,7 +12,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -27,7 +31,31 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -40,7 +68,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "googlechat"
- name: Delete googlechat contact point (idempotency)
register: result
@@ -53,4 +83,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 2503bbdd..3914b6a8 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/kafka.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/kafka.yml
@@ -13,7 +13,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -29,7 +33,32 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -42,7 +71,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "kafka"
- name: Delete kafka contact point (idempotency)
register: result
@@ -55,4 +86,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index f1f88de9..33c749e8 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/line.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/line.yml
@@ -12,7 +12,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -27,7 +31,31 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -40,7 +68,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "line"
- name: Delete line contact point (idempotency)
register: result
@@ -53,4 +83,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - not result.changed
+ - result.state == "absent"
diff --git a/tests/integration/targets/grafana_contact_point/tasks/opsgenie.yml b/tests/integration/targets/grafana_contact_point/tasks/opsgenie.yml
index 6e810e2a..fef2813e 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/opsgenie.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/opsgenie.yml
@@ -13,7 +13,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -29,7 +33,32 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -42,8 +71,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
- - result.state == 'absent'
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "opsgenie"
- name: Delete opsgenie contact point (idempotency)
register: result
@@ -56,4 +86,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 3c5e65a9..86c24a6f 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/pagerduty.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/pagerduty.yml
@@ -12,7 +12,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -27,7 +31,31 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -40,7 +68,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "pagerduty"
- name: Delete pagerduty contact point (idempotency)
register: result
@@ -53,4 +83,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 27ed69be..5a264838 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/pushover.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/pushover.yml
@@ -13,7 +13,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -29,7 +33,32 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -42,7 +71,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "pushover"
- name: Delete pushover contact point (idempotency)
register: result
@@ -55,4 +86,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 6cdf0478..16ffab43 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/sensugo.yml
@@ -13,7 +13,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -29,7 +33,32 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -42,7 +71,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "sensugo"
- name: Delete sensugo contact point (idempotency)
register: result
@@ -55,4 +86,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 110ec963..b803c041 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/slack.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/slack.yml
@@ -14,7 +14,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -31,7 +35,11 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -39,16 +47,21 @@
uid: slack
name: slack
type: slack
- slack_url: https://hooks.slack.com/services/xxx/yyy/fff
- slack_token: testapitoken
- slack_recipient: foo
+ 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 == True
+ - 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
@@ -61,7 +74,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "slack"
- name: Delete slack contact point (idempotency)
register: result
@@ -74,4 +89,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 019b407e..eb0d1e5d 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/teams.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/teams.yml
@@ -12,7 +12,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -27,7 +31,31 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -40,7 +68,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "teams"
- name: Delete teams contact point (idempotency)
register: result
@@ -53,4 +83,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 2fd38a5a..1ff7191b 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/telegram.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/telegram.yml
@@ -13,7 +13,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -29,7 +33,32 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -42,7 +71,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "telegram"
- name: Delete telegram contact point (idempotency)
register: result
@@ -55,4 +86,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 6e17aa51..ac406a4e 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/threema.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/threema.yml
@@ -14,7 +14,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -31,7 +35,33 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -44,7 +74,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "threema"
- name: Delete threema contact point (idempotency)
register: result
@@ -57,4 +89,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 8ab40387..1ee8c1fa 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/victorops.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/victorops.yml
@@ -12,7 +12,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -27,7 +31,31 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -40,7 +68,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "victorops"
- name: Delete victorops contact point (idempotency)
register: result
@@ -53,4 +83,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
index 8ff8ba4c..29dbc246 100644
--- a/tests/integration/targets/grafana_contact_point/tasks/webhook.yml
+++ b/tests/integration/targets/grafana_contact_point/tasks/webhook.yml
@@ -12,7 +12,11 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - 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
@@ -27,7 +31,31 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - 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
@@ -40,7 +68,9 @@
- ansible.builtin.assert:
that:
- - result.changed == True
+ - result.changed
+ - result.state == "absent"
+ - result.contact_point.uid == "webhook"
- name: Delete webhook contact point (idempotency)
register: result
@@ -53,4 +83,5 @@
- ansible.builtin.assert:
that:
- - result.changed == False
+ - not result.changed
+ - result.state == "absent"
From d0044e2bcb9c0254af5d88307d94d3f6ed6b09fd Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 12:03:03 +0200
Subject: [PATCH 070/120] fix: uid required
---
plugins/modules/grafana_contact_point.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index ef574642..88a7a0c1 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -1161,7 +1161,7 @@ def main():
"wecom",
],
),
- uid=dict(type="str"),
+ uid=dict(required=True, type="str"),
# alertmanager
alertmanager_password=dict(type="str", no_log=True),
alertmanager_url=dict(type="str"),
@@ -1311,8 +1311,7 @@ def main():
required_together=[["url_username", "url_password", "org_id"]],
mutually_exclusive=[["url_username", "grafana_api_key"]],
required_if=[
- ["state", "present", ["uid", "name", "type"]],
- ["state", "absent", ["uid"]],
+ ["state", "present", ["name", "type"]],
["type", "alertmanager", ["alertmanager_url"]],
["type", "dingding", ["dingding_url"]],
["type", "discord", ["discord_url"]],
From fff95583bda563ae4356900d888b07d491d454c6 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Tue, 28 May 2024 13:50:16 +0200
Subject: [PATCH 071/120] feat: role task arguments
---
roles/grafana/README.md | 8 +--
roles/grafana/tasks/main.yml | 134 +++++++++++++++++++++++++++++++++--
2 files changed, 131 insertions(+), 11 deletions(-)
diff --git a/roles/grafana/README.md b/roles/grafana/README.md
index 09901eff..a6ce7507 100644
--- a/roles/grafana/README.md
+++ b/roles/grafana/README.md
@@ -180,8 +180,8 @@ Configure Grafana organizations, dashboards, folders, datasources, teams and use
| org_name | no |
| provisioning | no |
| state | no |
-| type | yes |
-| uid | no |
+| type | no |
+| uid | yes |
| alertmanager_password | no |
| alertmanager_url | no |
| alertmanager_username | no |
@@ -198,9 +198,9 @@ Configure Grafana organizations, dashboards, folders, datasources, teams and use
| email_message | no |
| email_single | no |
| email_subject | no |
-| googlechat_url | no |
| googlechat_message | no |
| googlechat_title | no |
+| googlechat_url | no |
| kafka_api_version | no |
| kafka_cluster_id | no |
| kafka_description | no |
@@ -243,12 +243,12 @@ Configure Grafana organizations, dashboards, folders, datasources, teams and use
| pushover_upload_image | no |
| pushover_user_key | no |
| sensugo_api_key | no |
-| sensugo_url | 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 |
diff --git a/roles/grafana/tasks/main.yml b/roles/grafana/tasks/main.yml
index 347ef1c6..170d9337 100644
--- a/roles/grafana/tasks/main.yml
+++ b/roles/grafana/tasks/main.yml
@@ -91,15 +91,135 @@
- name: Manage contact point
community.grafana.grafana_contact_point:
- email_addresses: "{{ contact_point.email_addresses | default(omit) }}"
- email_single: "{{ contact_point.email_single | default(omit) }}"
- is_default: "{{ contact_point.is_default | default(omit) }}"
- name: "{{ contact_point.name }}"
+ 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_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 }}"
- uid: "{{ contact_point.uid | 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
From bffae2a6d485e314699369dcc8f9db4b5d3ab46f Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 31 May 2024 09:34:49 +0200
Subject: [PATCH 072/120] fix: bump required ansible version
---
meta/runtime.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meta/runtime.yml b/meta/runtime.yml
index 71243ba1..529b9ea0 100644
--- a/meta/runtime.yml
+++ b/meta/runtime.yml
@@ -1,5 +1,5 @@
---
-requires_ansible: ">=2.14.0"
+requires_ansible: ">=2.15.0"
action_groups:
grafana:
- grafana_dashboard
From 224d306d12a39d976b591b6a25f8bcecfd0bed05 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 31 May 2024 09:35:05 +0200
Subject: [PATCH 073/120] docs: changelog fragment
---
changelogs/fragments/374-ansible-required-version.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 changelogs/fragments/374-ansible-required-version.yml
diff --git a/changelogs/fragments/374-ansible-required-version.yml b/changelogs/fragments/374-ansible-required-version.yml
new file mode 100644
index 00000000..b3ea6347
--- /dev/null
+++ b/changelogs/fragments/374-ansible-required-version.yml
@@ -0,0 +1,3 @@
+---
+trivial:
+ - bump required ansible version to 2.15.0
From 3bdd20a51d96315a676c3ffeb04698b8dce25dfc Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 31 May 2024 10:01:25 +0200
Subject: [PATCH 074/120] fix: bump required ansible version in role
---
roles/grafana/meta/main.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/roles/grafana/meta/main.yml b/roles/grafana/meta/main.yml
index b5df4219..a9a4ae36 100644
--- a/roles/grafana/meta/main.yml
+++ b/roles/grafana/meta/main.yml
@@ -4,7 +4,7 @@ galaxy_info:
author: community
description: Configure Grafana organizations, dashboards, folders, datasources, silences, teams and users
license: GPLv3
- min_ansible_version: "2.14"
+ min_ansible_version: "2.15"
galaxy_tags: [grafana, monitoring]
platforms:
- {name: EL, versions: [all]}
From a9f4b80022f9bf04888b1a8ce4d1b548ca21aa06 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 31 May 2024 11:29:00 +0200
Subject: [PATCH 075/120] fix: remove deprecation check for api_key version
---
plugins/lookup/grafana_dashboard.py | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/plugins/lookup/grafana_dashboard.py b/plugins/lookup/grafana_dashboard.py
index 83ee250f..0a1baa43 100644
--- a/plugins/lookup/grafana_dashboard.py
+++ b/plugins/lookup/grafana_dashboard.py
@@ -152,16 +152,10 @@ def grafana_switch_organisation(self, headers):
def grafana_headers(self):
headers = {"content-type": "application/json; charset=utf8"}
- if self.grafana_api_key:
- api_key = self.grafana_api_key
- if len(api_key) % 4 == 2:
- display.deprecated(
- "Passing a mangled version of the API key to the grafana_dashboard lookup is no longer necessary and should not be done.",
- "2.0.0",
- collection_name="community.grafana",
- )
- api_key += "=="
- headers["Authorization"] = "Bearer %s" % api_key
+ if module.params.get("grafana_api_key", None):
+ self.headers["Authorization"] = (
+ "Bearer %s" % module.params["grafana_api_key"]
+ )
else:
headers["Authorization"] = basic_auth_header(
self.grafana_user, self.grafana_password
From 74495f3af99c869f3350e8df8d92342920f01cad Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 31 May 2024 11:31:37 +0200
Subject: [PATCH 076/120] docs: changelog fragment
---
.../fragments/376-dashboard-lookup-api-key-deprecation.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 changelogs/fragments/376-dashboard-lookup-api-key-deprecation.yml
diff --git a/changelogs/fragments/376-dashboard-lookup-api-key-deprecation.yml b/changelogs/fragments/376-dashboard-lookup-api-key-deprecation.yml
new file mode 100644
index 00000000..a462ffd3
--- /dev/null
+++ b/changelogs/fragments/376-dashboard-lookup-api-key-deprecation.yml
@@ -0,0 +1,3 @@
+---
+removed_features:
+ - removed check and handling of mangled api key in `grafana_dashboard` lookup
From 5e76ab7fcea23b181bacb343f8824eba868aca1d Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 31 May 2024 11:37:09 +0200
Subject: [PATCH 077/120] fix: grafana api key variable ref
---
plugins/lookup/grafana_dashboard.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/plugins/lookup/grafana_dashboard.py b/plugins/lookup/grafana_dashboard.py
index 0a1baa43..514d4fd5 100644
--- a/plugins/lookup/grafana_dashboard.py
+++ b/plugins/lookup/grafana_dashboard.py
@@ -152,10 +152,8 @@ def grafana_switch_organisation(self, headers):
def grafana_headers(self):
headers = {"content-type": "application/json; charset=utf8"}
- if module.params.get("grafana_api_key", None):
- self.headers["Authorization"] = (
- "Bearer %s" % module.params["grafana_api_key"]
- )
+ if self.grafana_api_key.get("grafana_api_key", None):
+ headers["Authorization"] = "Bearer %s" % self.grafana_api_key
else:
headers["Authorization"] = basic_auth_header(
self.grafana_user, self.grafana_password
From 3f9bcae6341b12d32dbe63438da5654644b692e3 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 31 May 2024 09:23:50 +0200
Subject: [PATCH 078/120] build(2.0.0): release version
---
CHANGELOG.rst | 15 +++++++++++++++
changelogs/changelog.yaml | 14 ++++++++++++++
galaxy.yml | 2 +-
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 9449bdc5..57dae08c 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -4,6 +4,21 @@ Grafana Collection Release Notes
.. contents:: Topics
+v2.0.0
+======
+
+Minor Changes
+-------------
+
+- Add `grafana_contact_point` module
+- Add support of `grafana_contact_point` in grafana role
+- add org switch by `org_id` and `org_name` in `grafana_silence`
+
+Removed Features (previously deprecated)
+----------------------------------------
+
+- removed deprecated `message` argument in `grafana_dashboard`
+
v1.9.1
======
diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml
index f8d3f898..2b78d2c9 100644
--- a/changelogs/changelog.yaml
+++ b/changelogs/changelog.yaml
@@ -312,3 +312,17 @@ releases:
- 367-dashboard-undo-breaing-change-message.yml
- 368-molecule-pin-requests.yml
release_date: '2024-05-21'
+ 2.0.0:
+ changes:
+ minor_changes:
+ - Add `grafana_contact_point` module
+ - Add support of `grafana_contact_point` in grafana role
+ - add org switch by `org_id` and `org_name` in `grafana_silence`
+ removed_features:
+ - removed deprecated `message` argument in `grafana_dashboard`
+ fragments:
+ - 352-module-contact-point.yml
+ - 371-silence-org-switch.yml
+ - 372-rm-dashboard-message-argument.yml
+ - 373-cleanup-and-update-sanity.yml
+ release_date: '2024-05-31'
diff --git a/galaxy.yml b/galaxy.yml
index 83df2d7d..0577f6c2 100644
--- a/galaxy.yml
+++ b/galaxy.yml
@@ -1,7 +1,7 @@
---
namespace: community
name: grafana
-version: 1.9.1
+version: 2.0.0
readme: README.md
authors:
- Rémi REY (@rrey)
From f7207b9e64c79ca004c770c3da74991c936aed4f Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 31 May 2024 09:59:34 +0200
Subject: [PATCH 079/120] docs: fix some version_added values
---
plugins/modules/grafana_contact_point.py | 2 +-
plugins/modules/grafana_silence.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 88a7a0c1..500c64f6 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -24,7 +24,7 @@
module: grafana_contact_point
author:
- Moritz Pötschk (@nemental)
-version_added: "1.9.0"
+version_added: "2.0.0"
short_description: Manage Grafana Contact Points
description:
- Create/Update/Delete Grafana Contact Points via API.
diff --git a/plugins/modules/grafana_silence.py b/plugins/modules/grafana_silence.py
index 7d0421ec..1b2b7091 100644
--- a/plugins/modules/grafana_silence.py
+++ b/plugins/modules/grafana_silence.py
@@ -23,7 +23,7 @@
module: grafana_silence
author:
- flkhndlr (@flkhndlr)
-version_added: "1.8.0"
+version_added: "1.9.0"
short_description: Manage Grafana Silences
description:
- Create/delete Grafana Silences through the Alertmanager Silence API.
From f16555e84535b93a55777253ea7f267503b0d57c Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 31 May 2024 12:24:26 +0200
Subject: [PATCH 080/120] docs: update changelog
---
CHANGELOG.rst | 6 ++++++
changelogs/changelog.yaml | 7 +++++++
2 files changed, 13 insertions(+)
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 57dae08c..bf836e6e 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -17,8 +17,14 @@ Minor Changes
Removed Features (previously deprecated)
----------------------------------------
+- removed check and handling of mangled api key in `grafana_dashboard` lookup
- removed deprecated `message` argument in `grafana_dashboard`
+New Modules
+-----------
+
+- community.grafana.grafana_contact_point - Manage Grafana Contact Points
+
v1.9.1
======
diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml
index 2b78d2c9..d9be1049 100644
--- a/changelogs/changelog.yaml
+++ b/changelogs/changelog.yaml
@@ -319,10 +319,17 @@ releases:
- Add support of `grafana_contact_point` in grafana role
- add org switch by `org_id` and `org_name` in `grafana_silence`
removed_features:
+ - removed check and handling of mangled api key in `grafana_dashboard` lookup
- removed deprecated `message` argument in `grafana_dashboard`
fragments:
- 352-module-contact-point.yml
- 371-silence-org-switch.yml
- 372-rm-dashboard-message-argument.yml
- 373-cleanup-and-update-sanity.yml
+ - 374-ansible-required-version.yml
+ - 376-dashboard-lookup-api-key-deprecation.yml
+ modules:
+ - description: Manage Grafana Contact Points
+ name: grafana_contact_point
+ namespace: ''
release_date: '2024-05-31'
From c30717b3fa3a593fede31366c04eb86b033e5465 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Sun, 16 Jun 2024 11:23:40 +0200
Subject: [PATCH 081/120] fix: grafana version sorting
---
hacking/find_grafana_versions.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hacking/find_grafana_versions.py b/hacking/find_grafana_versions.py
index 716f877a..c54f18ca 100644
--- a/hacking/find_grafana_versions.py
+++ b/hacking/find_grafana_versions.py
@@ -33,7 +33,7 @@ def get_grafana_releases():
if major not in by_major.keys() or by_major[major]["as_tuple"] < as_tuple:
by_major[major] = {"version": version, "as_tuple": as_tuple}
- latest_3_majors = sorted(list(by_major.keys()))[:3]
+ latest_3_majors = sorted(list(by_major.keys()), reverse=True)[:3]
latest_releases = [by_major[idx]["version"] for idx in latest_3_majors]
print(json.dumps(latest_releases))
From 793df2c59a69f766ff3582cabbe6763889efd185 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Sun, 16 Jun 2024 13:04:04 +0200
Subject: [PATCH 082/120] docs: chabgelog fragment
---
changelogs/fragments/378-grafana-version-sorting.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 changelogs/fragments/378-grafana-version-sorting.yml
diff --git a/changelogs/fragments/378-grafana-version-sorting.yml b/changelogs/fragments/378-grafana-version-sorting.yml
new file mode 100644
index 00000000..46c74655
--- /dev/null
+++ b/changelogs/fragments/378-grafana-version-sorting.yml
@@ -0,0 +1,3 @@
+---
+trivial:
+ - Fix grafana version sorting
From 8f1eefa1c07d2dc1be2670fa19b0bc1b1e94109b Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 19 Jun 2024 09:55:14 +0200
Subject: [PATCH 083/120] fix(grafana_contact_point): get org by name func args
---
plugins/modules/grafana_contact_point.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_contact_point.py b/plugins/modules/grafana_contact_point.py
index 500c64f6..b7633f3d 100644
--- a/plugins/modules/grafana_contact_point.py
+++ b/plugins/modules/grafana_contact_point.py
@@ -966,7 +966,9 @@ def __init__(self, module):
module.params["url_username"], module.params["url_password"]
)
self.org_id = (
- self.grafana_organization_by_name(module.params["org_name"])
+ self.grafana_organization_by_name(
+ module.params, module.params["org_name"]
+ )
if module.params["org_name"]
else module.params["org_id"]
)
From 5339481cc962356a4a709611e5503ac8e968d5c5 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 19 Jun 2024 09:58:54 +0200
Subject: [PATCH 084/120] docs: changelog fragment
---
changelogs/fragments/379-contact-points-org-name-func-args.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 changelogs/fragments/379-contact-points-org-name-func-args.yml
diff --git a/changelogs/fragments/379-contact-points-org-name-func-args.yml b/changelogs/fragments/379-contact-points-org-name-func-args.yml
new file mode 100644
index 00000000..5e8eea45
--- /dev/null
+++ b/changelogs/fragments/379-contact-points-org-name-func-args.yml
@@ -0,0 +1,3 @@
+---
+bugfixes:
+ - Add missing function argument in `grafana_contact_point` for org handling
From eeeba8ec39146a529c0d2eda5adc168925b764e9 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 10:44:12 +0200
Subject: [PATCH 085/120] docs: meta runtime deprecation notification channel
---
meta/runtime.yml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/meta/runtime.yml b/meta/runtime.yml
index 529b9ea0..7f45047b 100644
--- a/meta/runtime.yml
+++ b/meta/runtime.yml
@@ -13,3 +13,9 @@ action_groups:
- grafana_team
- grafana_user
- grafana_silence
+plugin_routing:
+ modules:
+ grafana_notification_channel:
+ deprecation:
+ removal_version: 3.0.0
+ warning_text: Legacy alerting is removed in Grafana version 11, use community.grafana.grafana_contact_point instead.
From 729f2f231a387458d9efcc92e7e9232d4da07654 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 10:44:41 +0200
Subject: [PATCH 086/120] docs: plugin module deprecation notification_channel
---
plugins/modules/grafana_notification_channel.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index 30b5b112..42ea442d 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -33,6 +33,10 @@
short_description: Manage Grafana Notification Channels
description:
- Create/Update/Delete Grafana Notification Channels via API.
+deprecated:
+ removed_in: "3.0.0"
+ why: Legacy alerting is removed in Grafana version 11.
+ alternative: Use M(community.grafana.grafana_contact_point) instead.
options:
org_id:
description:
From 3c2cad9fc75b47d7afd50ef79b1da39aa60c0465 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 10:48:43 +0200
Subject: [PATCH 087/120] docs: changelog fragment
---
changelogs/fragments/382-notification-channel-deprecation.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 changelogs/fragments/382-notification-channel-deprecation.yml
diff --git a/changelogs/fragments/382-notification-channel-deprecation.yml b/changelogs/fragments/382-notification-channel-deprecation.yml
new file mode 100644
index 00000000..3410b084
--- /dev/null
+++ b/changelogs/fragments/382-notification-channel-deprecation.yml
@@ -0,0 +1,3 @@
+---
+deprecated_features:
+ - Deprecate `grafana_notification_channel` with removal in version 3.0.0
From 260a4f361aac5e8ebbfb470bfba8feb805c8e875 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 14:21:15 +0200
Subject: [PATCH 088/120] feat: notification channel get version with skip
version check
---
.../modules/grafana_notification_channel.py | 29 +++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index 42ea442d..324836ed 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -100,6 +100,11 @@
default: false
description:
- Disable the resolve message.
+ skip_version_check:
+ description:
+ - Skip Grafana version check and try to reach api endpoint anyway.
+ type: bool
+ default: false
reminder_frequency:
type: str
description:
@@ -627,6 +632,29 @@ def __init__(self, module):
)
# }}}
self.grafana_url = clean_url(module.params.get("url"))
+ if module.params.get("skip_version_check") is False:
+ try:
+ grafana_version = self.get_version()
+ except GrafanaAPIException as e:
+ self._module.fail_json(failed=True, msg=to_text(e))
+ if grafana_version["major"] >= 11:
+ self._module.fail_json(
+ failed=True,
+ msg="Legacy Alerting API is available up to Grafana v11",
+ )
+
+ def get_version(self):
+ r, info = fetch_url(
+ self._module,
+ "%s/api/health" % self.grafana_url,
+ headers=self.headers,
+ method="GET",
+ )
+ version = r.get("version")
+ if version is not None:
+ major, minor, rev = version.split(".")
+ return {"major": int(major), "minor": int(minor), "rev": int(rev)}
+ raise GrafanaAPIException("Failed to retrieve version: %s" % info)
def grafana_switch_organisation(self, grafana_url, org_id):
r, info = fetch_url(
@@ -761,6 +789,7 @@ def main():
is_default=dict(type="bool", default=False),
include_image=dict(type="bool", default=False),
disable_resolve_message=dict(type="bool", default=False),
+ skip_version_check=dict(type="bool", default=False),
reminder_frequency=dict(type="str"),
dingding_url=dict(type="str"),
dingding_message_type=dict(
From bd719fa8a62abef3157d6838d5cf7d08a3df221e Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 14:28:23 +0200
Subject: [PATCH 089/120] chore: version ref
---
plugins/modules/grafana_notification_channel.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index 324836ed..c092e9cf 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -640,7 +640,7 @@ def __init__(self, module):
if grafana_version["major"] >= 11:
self._module.fail_json(
failed=True,
- msg="Legacy Alerting API is available up to Grafana v11",
+ msg="Legacy Alerting API is available up to Grafana v10",
)
def get_version(self):
From 95ea959d93aa3eb60160f6bcc7a1495587741b87 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 14:28:51 +0200
Subject: [PATCH 090/120] test: notification channel check for legacy api
---
.../tasks/main.yml | 61 +++++++++----------
1 file changed, 28 insertions(+), 33 deletions(-)
diff --git a/tests/integration/targets/grafana_notification_channel/tasks/main.yml b/tests/integration/targets/grafana_notification_channel/tasks/main.yml
index af0b2f86..4684926a 100644
--- a/tests/integration/targets/grafana_notification_channel/tasks/main.yml
+++ b/tests/integration/targets/grafana_notification_channel/tasks/main.yml
@@ -1,34 +1,29 @@
---
-- block:
- - ansible.builtin.include_tasks:
- file: dingding.yml
- - ansible.builtin.include_tasks:
- file: discord.yml
- - ansible.builtin.include_tasks:
- file: email.yml
- - ansible.builtin.include_tasks:
- file: googlechat.yml
- - ansible.builtin.include_tasks:
- file: hipchat.yml
- - ansible.builtin.include_tasks:
- file: kafka.yml
- - ansible.builtin.include_tasks:
- file: teams.yml
- - ansible.builtin.include_tasks:
- file: opsgenie.yml
- - ansible.builtin.include_tasks:
- file: pagerduty.yml
- - ansible.builtin.include_tasks:
- file: prometheus.yml
- - ansible.builtin.include_tasks:
- file: pushover.yml
- - ansible.builtin.include_tasks:
- file: sensu.yml
- - ansible.builtin.include_tasks:
- file: slack-and-beyond.yml
- - ansible.builtin.include_tasks:
- file: telegram.yml
- - ansible.builtin.include_tasks:
- file: victorops.yml
- - ansible.builtin.include_tasks:
- file: webhook.yml
+
+- name: Check for support of API endpoint
+ register: result
+ ignore_errors: true
+ community.grafana.grafana_notification_channel:
+ title: apitest
+ state: absent
+
+- name: Include notification channel task files
+ ansible.builtin.include_tasks: "{{ item }}.yml"
+ when: "result.msg | default('') != 'Legacy Alerting API is available up to Grafana v10'"
+ loop:
+ - dingding
+ - discord
+ - email
+ - googlechat
+ - hipchat
+ - kafka
+ - teams
+ - opsgenie
+ - pagerduty
+ - prometheus
+ - pushover
+ - sensu
+ - slack-and-beyond
+ - telegram
+ - victorops
+ - webhook
From 48810322a0303435fa80ae536207ad6f49140ff0 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 14:33:19 +0200
Subject: [PATCH 091/120] test: grafana attributes
---
.../targets/grafana_notification_channel/tasks/main.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/integration/targets/grafana_notification_channel/tasks/main.yml b/tests/integration/targets/grafana_notification_channel/tasks/main.yml
index 4684926a..7161088b 100644
--- a/tests/integration/targets/grafana_notification_channel/tasks/main.yml
+++ b/tests/integration/targets/grafana_notification_channel/tasks/main.yml
@@ -4,6 +4,9 @@
register: result
ignore_errors: true
community.grafana.grafana_notification_channel:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
title: apitest
state: absent
From 6b6d955c01386711a46a0906efd85631715cfdd8 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 28 Jun 2024 12:19:55 +0200
Subject: [PATCH 092/120] fix: read output of health api if ok
---
plugins/modules/grafana_notification_channel.py | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/plugins/modules/grafana_notification_channel.py b/plugins/modules/grafana_notification_channel.py
index c092e9cf..24e4e3c0 100644
--- a/plugins/modules/grafana_notification_channel.py
+++ b/plugins/modules/grafana_notification_channel.py
@@ -650,11 +650,13 @@ def get_version(self):
headers=self.headers,
method="GET",
)
- version = r.get("version")
- if version is not None:
- major, minor, rev = version.split(".")
- return {"major": int(major), "minor": int(minor), "rev": int(rev)}
- raise GrafanaAPIException("Failed to retrieve version: %s" % info)
+ if info["status"] == 200:
+ version = json.loads(to_text(r.read())).get("version")
+ if version is not None:
+ major, minor, rev = version.split(".")
+ return {"major": int(major), "minor": int(minor), "rev": int(rev)}
+ else:
+ raise GrafanaAPIException("Failed to retrieve version: %s" % info)
def grafana_switch_organisation(self, grafana_url, org_id):
r, info = fetch_url(
From 11ae84f1527362c2f5394fa3852510f868e66692 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 28 Jun 2024 12:20:31 +0200
Subject: [PATCH 093/120] test: wrong arg
---
.../targets/grafana_notification_channel/tasks/main.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/integration/targets/grafana_notification_channel/tasks/main.yml b/tests/integration/targets/grafana_notification_channel/tasks/main.yml
index 7161088b..7d1dec69 100644
--- a/tests/integration/targets/grafana_notification_channel/tasks/main.yml
+++ b/tests/integration/targets/grafana_notification_channel/tasks/main.yml
@@ -7,7 +7,7 @@
grafana_url: "{{ grafana_url }}"
grafana_user: "{{ grafana_username }}"
grafana_password: "{{ grafana_password }}"
- title: apitest
+ name: apitest
state: absent
- name: Include notification channel task files
From 6bb5266a69e404c9a8fdbea9e7ba17a7556d5692 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 28 Jun 2024 12:23:37 +0200
Subject: [PATCH 094/120] docs: changelog fragment
---
changelogs/fragments/382-notification-channel-deprecation.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/changelogs/fragments/382-notification-channel-deprecation.yml b/changelogs/fragments/382-notification-channel-deprecation.yml
index 3410b084..9af1cf01 100644
--- a/changelogs/fragments/382-notification-channel-deprecation.yml
+++ b/changelogs/fragments/382-notification-channel-deprecation.yml
@@ -1,3 +1,5 @@
---
deprecated_features:
- Deprecate `grafana_notification_channel` with removal in version 3.0.0
+trivial:
+ - Check Grafana version for `grafana_notification_channel` integration tests
From 7c1d1e7fe7251ada5cd7f840efc58a99b4b650a8 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 26 Jun 2024 13:38:11 +0200
Subject: [PATCH 095/120] refactor: folder finding loop
---
plugins/modules/grafana_folder.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index 73c437db..a6372fad 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -290,15 +290,16 @@ def create_folder(self, title):
return response
def get_folder(self, title):
- url = "/api/search?type=dash-folder&query={title}".format(title=quote(title))
+ url = "/api/search?type=dash-folder&query=%s" % quote(title)
response = self._send_request(url, headers=self.headers, method="GET")
- for item in response:
- if item.get("title") == to_text(title):
- return item
+ folder = next((item for item in response if item["title"] == title))
+ if folder:
+ return folder
+
return None
def delete_folder(self, folder_uid):
- url = "/api/folders/{folder_uid}".format(folder_uid=folder_uid)
+ url = "/api/folders/%s" % folder_uid
response = self._send_request(url, headers=self.headers, method="DELETE")
return response
From 4ea2afbeb379f8ad0c0e9b5b99fded159ea7ce31 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 26 Jun 2024 13:38:31 +0200
Subject: [PATCH 096/120] chore: add uid and parent_uid arg
---
plugins/modules/grafana_folder.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index a6372fad..9f34ed8d 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -308,10 +308,12 @@ def main():
argument_spec = base.grafana_argument_spec()
argument_spec.update(
name=dict(type="str", aliases=["title"], required=True),
- state=dict(type="str", default="present", choices=["present", "absent"]),
- skip_version_check=dict(type="bool", default=False),
org_id=dict(default=1, type="int"),
org_name=dict(type="str"),
+ parent_uid=dict(type="str"),
+ skip_version_check=dict(type="bool", default=False),
+ state=dict(type="str", default="present", choices=["present", "absent"]),
+ uid=dict(type="str"),
)
module = AnsibleModule(
argument_spec=argument_spec,
From b2d155fd72d1581cc91b234cb51a1ca66ef384a0 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 26 Jun 2024 14:16:22 +0200
Subject: [PATCH 097/120] fix: check if multiple folder found by name
---
plugins/modules/grafana_folder.py | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index 9f34ed8d..4af28c0e 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -292,9 +292,14 @@ def create_folder(self, title):
def get_folder(self, title):
url = "/api/search?type=dash-folder&query=%s" % quote(title)
response = self._send_request(url, headers=self.headers, method="GET")
- folder = next((item for item in response if item["title"] == title))
- if folder:
- return folder
+ folders = [item for item in response if item.get("title") == to_text(title)]
+
+ if len(folders) == 1:
+ return folders[0]
+ elif len(folders) > 1:
+ raise GrafanaError(
+ f"Multiple folders found for name {title}. Please use uid."
+ )
return None
From 2729a74beafea93fa32722b36231add73a9fe81c Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 26 Jun 2024 15:00:04 +0200
Subject: [PATCH 098/120] feat: change get folder api and use parent_uid if
defined and check against uid first
---
plugins/modules/grafana_folder.py | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index 4af28c0e..978c8bd1 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -289,17 +289,16 @@ def create_folder(self, title):
)
return response
- def get_folder(self, title):
- url = "/api/search?type=dash-folder&query=%s" % quote(title)
+ def get_folder(self, title, uid=None, parent_uid=None):
+ url = "/api/folders%s" % ("?parentUid=%s" % parent_uid if parent_uid else "")
response = self._send_request(url, headers=self.headers, method="GET")
- folders = [item for item in response if item.get("title") == to_text(title)]
+ if uid:
+ folders = [item for item in response if item.get("uid") == uid]
+ else:
+ folders = [item for item in response if item.get("title") == to_text(title)]
- if len(folders) == 1:
+ if folders:
return folders[0]
- elif len(folders) > 1:
- raise GrafanaError(
- f"Multiple folders found for name {title}. Please use uid."
- )
return None
From 34ae5b9a0f0ad2dc760c25e6225929b88b73195f Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 26 Jun 2024 15:00:29 +0200
Subject: [PATCH 099/120] feat: get folders by uid and parent_uid if defined
---
plugins/modules/grafana_folder.py | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index 978c8bd1..33ad4fcc 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -331,13 +331,24 @@ def main():
)
state = module.params["state"]
title = module.params["name"]
+ parent_uid = module.params["parent_uid"]
+ uid = module.params["uid"]
module.params["url"] = base.clean_url(module.params["url"])
grafana_iface = GrafanaFolderInterface(module)
changed = False
- if state == "present":
+
+ if uid and parent_uid:
+ folder = grafana_iface.get_folder(title, uid, parent_uid)
+ elif uid:
+ folder = grafana_iface.get_folder(title, uid)
+ elif parent_uid:
+ folder = grafana_iface.get_folder(title, parent_uid=parent_uid)
+ else:
folder = grafana_iface.get_folder(title)
+
+ if state == "present":
if folder is None:
grafana_iface.create_folder(title)
folder = grafana_iface.get_folder(title)
@@ -345,7 +356,6 @@ def main():
folder = grafana_iface.get_folder(title)
module.exit_json(changed=changed, folder=folder)
elif state == "absent":
- folder = grafana_iface.get_folder(title)
if folder is None:
module.exit_json(changed=False, message="No folder found")
result = grafana_iface.delete_folder(folder.get("uid"))
From 8743bd9ace19a6e6de17ef64765239640a37f0d5 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 26 Jun 2024 15:12:16 +0200
Subject: [PATCH 100/120] chore: simplify
---
plugins/modules/grafana_folder.py | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index 33ad4fcc..8f190a38 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -339,14 +339,7 @@ def main():
changed = False
- if uid and parent_uid:
- folder = grafana_iface.get_folder(title, uid, parent_uid)
- elif uid:
- folder = grafana_iface.get_folder(title, uid)
- elif parent_uid:
- folder = grafana_iface.get_folder(title, parent_uid=parent_uid)
- else:
- folder = grafana_iface.get_folder(title)
+ folder = grafana_iface.get_folder(title, uid, parent_uid)
if state == "present":
if folder is None:
From a73039057f9b8d4850f0eaf0d179c1475c19f19c Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 26 Jun 2024 15:19:31 +0200
Subject: [PATCH 101/120] feat: create folder with uid and parent_uid
---
plugins/modules/grafana_folder.py | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index 8f190a38..44142078 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -281,9 +281,9 @@ def get_version(self):
return {"major": int(major), "minor": int(minor), "rev": int(rev)}
raise GrafanaError("Failed to retrieve version from '%s'" % url)
- def create_folder(self, title):
+ def create_folder(self, title, uid=None, parent_uid=None):
url = "/api/folders"
- folder = dict(title=title)
+ folder = dict(title=title, uid=uid, parentUid=parent_uid)
response = self._send_request(
url, data=folder, headers=self.headers, method="POST"
)
@@ -343,10 +343,9 @@ def main():
if state == "present":
if folder is None:
- grafana_iface.create_folder(title)
- folder = grafana_iface.get_folder(title)
+ grafana_iface.create_folder(title, uid, parent_uid)
+ folder = grafana_iface.get_folder(title, uid, parent_uid)
changed = True
- folder = grafana_iface.get_folder(title)
module.exit_json(changed=changed, folder=folder)
elif state == "absent":
if folder is None:
From 453b68ac366fd0fc3c4e29f93803314c3ee24a5e Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Wed, 26 Jun 2024 15:23:06 +0200
Subject: [PATCH 102/120] docs: parent_uid and uid
---
plugins/modules/grafana_folder.py | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index 44142078..db5d9e90 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -37,10 +37,18 @@
required: true
type: str
aliases: [ title ]
+ uid:
+ description:
+ - The folder UID.
+ type: str
+ parent_uid:
+ description:
+ - The parent folder UID.
+ type: str
state:
description:
- Delete the members not found in the C(members) parameters from the
- - list of members found on the Folder.
+ - list of members found on the folder.
default: present
type: str
choices: ["present", "absent"]
From dfca09b1abcd863e9429ab25dee54ba102a32999 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 09:45:02 +0200
Subject: [PATCH 103/120] docs: module return values
---
plugins/modules/grafana_folder.py | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index db5d9e90..61f9f4a9 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -116,6 +116,12 @@
type: str
sample:
- "nErXDvCkzz"
+ orgId:
+ description: The organization id
+ returned: always
+ type: int
+ sample:
+ - 1
title:
description: The Folder title
returned: always
@@ -182,6 +188,12 @@
type: int
sample:
- 1
+ parentUid:
+ description: The parent folders uid
+ returned: always as subfolder
+ type: str
+ sample:
+ - "76HjcBH2"
"""
import json
@@ -189,7 +201,6 @@
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.urls import fetch_url, basic_auth_header
from ansible_collections.community.grafana.plugins.module_utils import base
-from ansible.module_utils.six.moves.urllib.parse import quote
from ansible.module_utils._text import to_text
__metaclass__ = type
From ca04523caaec602a43e22a08df621c0c4560df41 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 09:45:44 +0200
Subject: [PATCH 104/120] test: use module defaults
---
.../grafana_folder/tasks/create-delete.yml | 94 +++++++++----------
1 file changed, 44 insertions(+), 50 deletions(-)
diff --git a/tests/integration/targets/grafana_folder/tasks/create-delete.yml b/tests/integration/targets/grafana_folder/tasks/create-delete.yml
index c818c2ef..e1ee756c 100644
--- a/tests/integration/targets/grafana_folder/tasks/create-delete.yml
+++ b/tests/integration/targets/grafana_folder/tasks/create-delete.yml
@@ -1,58 +1,52 @@
---
-- name: Create a Folder
- community.grafana.grafana_folder:
- url: "{{ grafana_url }}"
- url_username: "{{ grafana_username }}"
- url_password: "{{ grafana_password }}"
- title: grafana_working_group
- state: present
- register: result
+- module_defaults:
+ community.grafana.grafana_folder:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ block:
+ - name: Create a Folder
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: present
+ register: result
-- ansible.builtin.assert:
- that:
- - result.changed == true
- - result.folder.title == 'grafana_working_group'
- when: not ansible_check_mode
+ - ansible.builtin.assert:
+ that:
+ - result.changed == true
+ - result.folder.title == 'grafana_working_group'
+ when: not ansible_check_mode
-- name: Test folder creation idempotency
- community.grafana.grafana_folder:
- url: "{{ grafana_url }}"
- url_username: "{{ grafana_username }}"
- url_password: "{{ grafana_password }}"
- title: grafana_working_group
- state: present
- register: result
+ - name: Test folder creation idempotency
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: present
+ register: result
-- ansible.builtin.assert:
- that:
- - result.changed == false
- - result.folder.title == 'grafana_working_group'
- when: not ansible_check_mode
+ - ansible.builtin.assert:
+ that:
+ - result.changed == false
+ - result.folder.title == 'grafana_working_group'
+ when: not ansible_check_mode
-- name: Delete a Folder
- community.grafana.grafana_folder:
- url: "{{ grafana_url }}"
- url_username: "{{ grafana_username }}"
- url_password: "{{ grafana_password }}"
- title: grafana_working_group
- state: absent
- register: result
+ - name: Delete a Folder
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: absent
+ register: result
-- ansible.builtin.assert:
- that:
- - result.changed == true
- when: not ansible_check_mode
+ - ansible.builtin.assert:
+ that:
+ - result.changed == true
+ when: not ansible_check_mode
-- name: Test folder deletion idempotency
- community.grafana.grafana_folder:
- url: "{{ grafana_url }}"
- url_username: "{{ grafana_username }}"
- url_password: "{{ grafana_password }}"
- title: grafana_working_group
- state: absent
- register: result
+ - name: Test folder deletion idempotency
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: absent
+ register: result
-- ansible.builtin.assert:
- that:
- - result.changed == false
- when: not ansible_check_mode
+ - ansible.builtin.assert:
+ that:
+ - result.changed == false
+ when: not ansible_check_mode
From bca4d7d10d9152014c85a29db6420cfa53714cc0 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 09:46:00 +0200
Subject: [PATCH 105/120] test: add sub folder tests
---
.../targets/grafana_folder/tasks/sub.yml | 110 ++++++++++++++++++
1 file changed, 110 insertions(+)
create mode 100644 tests/integration/targets/grafana_folder/tasks/sub.yml
diff --git a/tests/integration/targets/grafana_folder/tasks/sub.yml b/tests/integration/targets/grafana_folder/tasks/sub.yml
new file mode 100644
index 00000000..d9f95ac5
--- /dev/null
+++ b/tests/integration/targets/grafana_folder/tasks/sub.yml
@@ -0,0 +1,110 @@
+---
+- module_defaults:
+ community.grafana.grafana_folder:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ uid: "parent"
+ block:
+ - name: Create a parent Folder
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: present
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == true
+ - result.folder.title == 'grafana_working_group'
+ - result.folder.uid == 'parent'
+ when: not ansible_check_mode
+
+ - name: Test folder parent creation idempotency
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: present
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == false
+ - result.folder.title == 'grafana_working_group'
+ - result.folder.uid == 'parent'
+ when: not ansible_check_mode
+
+ - module_defaults:
+ community.grafana.grafana_folder:
+ uid: "sub"
+ parent_uid: "parent"
+ block:
+ - name: Create a sub Folder
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: present
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == true
+ - result.folder.title == 'grafana_working_group'
+ - result.folder.uid == 'sub'
+ - result.folder.parentUid == 'parent'
+ when: not ansible_check_mode
+
+ - name: Test sub folder creation idempotency
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: present
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == false
+ - result.folder.title == 'grafana_working_group'
+ - result.folder.uid == 'sub'
+ - result.folder.parentUid == 'parent'
+ when: not ansible_check_mode
+
+ - name: Delete sub Folder
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: absent
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == true
+ when: not ansible_check_mode
+
+ - name: Test sub folder deletion idempotency
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: absent
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == false
+ when: not ansible_check_mode
+
+ - name: Delete a Folder
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: absent
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == true
+ when: not ansible_check_mode
+
+ - name: Test folder deletion idempotency
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: absent
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == false
+ when: not ansible_check_mode
From 2f1d435948cbbab40b8d7a6f3cacfc400e9670e2 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 09:54:28 +0200
Subject: [PATCH 106/120] test: add sub folder tests to main
---
tests/integration/targets/grafana_folder/tasks/main.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/integration/targets/grafana_folder/tasks/main.yml b/tests/integration/targets/grafana_folder/tasks/main.yml
index 0ac91f37..7880e8dc 100644
--- a/tests/integration/targets/grafana_folder/tasks/main.yml
+++ b/tests/integration/targets/grafana_folder/tasks/main.yml
@@ -4,3 +4,6 @@
- name: Folder creation and deletion for organization
ansible.builtin.include_tasks: org.yml
+
+- name: Folder creation and deletion for subfolders
+ ansible.builtin.include_tasks: sub.yml
From d09dd8da4a33a0da811164118c9f44b9ad711244 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 09:54:56 +0200
Subject: [PATCH 107/120] test: fix org name test
---
.../targets/grafana_folder/tasks/org.yml | 52 +++++++++++++++++--
1 file changed, 49 insertions(+), 3 deletions(-)
diff --git a/tests/integration/targets/grafana_folder/tasks/org.yml b/tests/integration/targets/grafana_folder/tasks/org.yml
index f30d48c1..7a628914 100644
--- a/tests/integration/targets/grafana_folder/tasks/org.yml
+++ b/tests/integration/targets/grafana_folder/tasks/org.yml
@@ -1,7 +1,53 @@
---
- module_defaults:
community.grafana.grafana_folder:
- org_name: Main Org.
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ org_name: "Main Org."
block:
- - name: Folder creation and deletion
- ansible.builtin.include_tasks: create-delete.yml
+ - name: Create a Folder
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: present
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == true
+ - result.folder.title == 'grafana_working_group'
+ when: not ansible_check_mode
+
+ - name: Test folder creation idempotency
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: present
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == false
+ - result.folder.title == 'grafana_working_group'
+ when: not ansible_check_mode
+
+ - name: Delete a Folder
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: absent
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == true
+ when: not ansible_check_mode
+
+ - name: Test folder deletion idempotency
+ community.grafana.grafana_folder:
+ title: grafana_working_group
+ state: absent
+ register: result
+
+ - ansible.builtin.assert:
+ that:
+ - result.changed == false
+ when: not ansible_check_mode
From 2bc3d8f423e0e63d3589d14371f913f40eaa3ffb Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 09:55:11 +0200
Subject: [PATCH 108/120] test: sub folder tests module defaults
---
tests/integration/targets/grafana_folder/tasks/sub.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/integration/targets/grafana_folder/tasks/sub.yml b/tests/integration/targets/grafana_folder/tasks/sub.yml
index d9f95ac5..21adb236 100644
--- a/tests/integration/targets/grafana_folder/tasks/sub.yml
+++ b/tests/integration/targets/grafana_folder/tasks/sub.yml
@@ -34,6 +34,9 @@
- module_defaults:
community.grafana.grafana_folder:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
uid: "sub"
parent_uid: "parent"
block:
From 0cffd21140c04620f23a20153440bd167735c612 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 10:00:06 +0200
Subject: [PATCH 109/120] docs: changelog fragment
---
changelogs/fragments/381-sub-folders.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 changelogs/fragments/381-sub-folders.yml
diff --git a/changelogs/fragments/381-sub-folders.yml b/changelogs/fragments/381-sub-folders.yml
new file mode 100644
index 00000000..36e46667
--- /dev/null
+++ b/changelogs/fragments/381-sub-folders.yml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - `grafana_folder` manage subfolders and specify uid
From 46d21d996f92a421511025f7d64b74b64d1db0c6 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 10:04:34 +0200
Subject: [PATCH 110/120] feat: role uid and parent_uid
---
roles/grafana/tasks/main.yml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/roles/grafana/tasks/main.yml b/roles/grafana/tasks/main.yml
index 170d9337..d0ddab40 100644
--- a/roles/grafana/tasks/main.yml
+++ b/roles/grafana/tasks/main.yml
@@ -277,10 +277,12 @@
- name: Manage folder # noqa: args[module]
community.grafana.grafana_folder:
name: "{{ folder.name }}"
- skip_version_check: "{{ folder.skip_version_check | default(omit) }}"
- state: "{{ folder.state | default(omit) }}"
org_id: "{{ folder.org_id | default(omit) }}"
org_name: "{{ folder.org_name | default(omit) }}"
+ parent_uid: "{{ folder.parent_uid | default(omit) }}"
+ skip_version_check: "{{ folder.skip_version_check | default(omit) }}"
+ state: "{{ folder.state | default(omit) }}"
+ uid: "{{ folder.uid | default(omit) }}"
loop: "{{ grafana_folders }}"
loop_control: {loop_var: folder}
tags: folder
From b6160be362252300476c06e265067b82aa62404b Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Thu, 27 Jun 2024 10:04:50 +0200
Subject: [PATCH 111/120] docs: role new subfolder parameters
---
roles/grafana/README.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/roles/grafana/README.md b/roles/grafana/README.md
index a6ce7507..5c76497c 100644
--- a/roles/grafana/README.md
+++ b/roles/grafana/README.md
@@ -73,10 +73,12 @@ Configure Grafana organizations, dashboards, folders, datasources, teams and use
| zabbix_user | no |
| [**grafana_folders**](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_folder_module.html) |
| name | yes |
-| skip_version_check | no |
-| state | no |
| org_id | no |
| org_name | no |
+| parent_uid | no |
+| skip_version_check | no |
+| state | no |
+| uid | no |
| [**grafana_dashboards**](https://docs.ansible.com/ansible/latest/collections/community/grafana/grafana_dashboard_module.html) |
| commit_message | no |
| dashboard_id | no |
From 196cb0925e4822b7f47658dd5ce6053535a4c9ce Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 28 Jun 2024 13:00:58 +0200
Subject: [PATCH 112/120] fix: check for api support
---
plugins/modules/grafana_folder.py | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index 61f9f4a9..c9fa2364 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -241,6 +241,10 @@ def __init__(self, module):
self._module.fail_json(
failed=True, msg="Folders API is available starting Grafana v5"
)
+ if grafana_version["major"] < 11 and module.params["parent_uid"]:
+ self._module.fail_json(
+ failed=True, msg="Subfolder API is available starting Grafana v11"
+ )
def _send_request(self, url, data=None, headers=None, method="GET"):
if data is not None:
@@ -311,13 +315,16 @@ def create_folder(self, title, uid=None, parent_uid=None):
def get_folder(self, title, uid=None, parent_uid=None):
url = "/api/folders%s" % ("?parentUid=%s" % parent_uid if parent_uid else "")
response = self._send_request(url, headers=self.headers, method="GET")
- if uid:
- folders = [item for item in response if item.get("uid") == uid]
- else:
- folders = [item for item in response if item.get("title") == to_text(title)]
+ if response is not None:
+ if uid:
+ folders = [item for item in response if item.get("uid") == uid]
+ else:
+ folders = [
+ item for item in response if item.get("title") == to_text(title)
+ ]
- if folders:
- return folders[0]
+ if folders:
+ return folders[0]
return None
From 6decf1c990ee8f36c00d9a66555ffa96c90f819e Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 28 Jun 2024 13:01:28 +0200
Subject: [PATCH 113/120] test: separate sub folder test file
---
.../targets/grafana_folder/tasks/main.yml | 22 ++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/tests/integration/targets/grafana_folder/tasks/main.yml b/tests/integration/targets/grafana_folder/tasks/main.yml
index 7880e8dc..ca3bd168 100644
--- a/tests/integration/targets/grafana_folder/tasks/main.yml
+++ b/tests/integration/targets/grafana_folder/tasks/main.yml
@@ -1,9 +1,21 @@
---
-- name: Folder creation and deletion
- ansible.builtin.include_tasks: create-delete.yml
+- name: Include folder task files
+ ansible.builtin.include_tasks: "{{ item }}.yml"
+ loop:
+ - create-delete
+ - org
-- name: Folder creation and deletion for organization
- ansible.builtin.include_tasks: org.yml
+- name: Check for support of API endpoint
+ register: result
+ ignore_errors: true
+ community.grafana.grafana_folder:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ title: apitest
+ parent_uid: "parent"
+ state: absent
-- name: Folder creation and deletion for subfolders
+- name: Include folder task file for subfolders
ansible.builtin.include_tasks: sub.yml
+ when: "result.msg | default('') != 'Subfolder API is available starting Grafana v11'"
From 57fc59268da2b1bd6ba27addce21f433c20c7a75 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 28 Jun 2024 13:04:21 +0200
Subject: [PATCH 114/120] docs: version notice for parent_uid arg
---
plugins/modules/grafana_folder.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index c9fa2364..054386d2 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -44,6 +44,7 @@
parent_uid:
description:
- The parent folder UID.
+ - Available with subfolder feature of Grafana 11.
type: str
state:
description:
From 23ff04f28abc8905e89eadd3b2c590390b29d4e2 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 28 Jun 2024 13:05:27 +0200
Subject: [PATCH 115/120] docs: changelog fragment format fix
---
changelogs/fragments/381-sub-folders.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/changelogs/fragments/381-sub-folders.yml b/changelogs/fragments/381-sub-folders.yml
index 36e46667..bb6f2506 100644
--- a/changelogs/fragments/381-sub-folders.yml
+++ b/changelogs/fragments/381-sub-folders.yml
@@ -1,3 +1,3 @@
---
minor_changes:
- - `grafana_folder` manage subfolders and specify uid
+ - Manage subfolders for `grafana_folder` and specify uid
From 89e5cfa37322d1af54ec4e4a3fcf417ebed489c4 Mon Sep 17 00:00:00 2001
From: Nemental <15136847+Nemental@users.noreply.github.com>
Date: Fri, 28 Jun 2024 13:11:19 +0200
Subject: [PATCH 116/120] chore: lower folder
---
plugins/modules/grafana_folder.py | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index 054386d2..dc7e1b6d 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -25,15 +25,15 @@
author:
- Rémi REY (@rrey)
version_added: "1.0.0"
-short_description: Manage Grafana Folders
+short_description: Manage Grafana folders
description:
- - Create/update/delete Grafana Folders through the Folders API.
+ - Create/update/delete Grafana folders through the folders API.
requirements:
- - The Folders API is only available starting Grafana 5 and the module will fail if the server version is lower than version 5.
+ - The folders API is only available starting Grafana 5 and the module will fail if the server version is lower than version 5.
options:
name:
description:
- - The title of the Grafana Folder.
+ - The title of the Grafana folder.
required: true
type: str
aliases: [ title ]
@@ -101,18 +101,18 @@
RETURN = """
---
folder:
- description: Information about the Folder
+ description: Information about the folder
returned: On success
type: complex
contains:
id:
- description: The Folder identifier
+ description: The folder identifier
returned: always
type: int
sample:
- 42
uid:
- description: The Folder uid
+ description: The folder uid
returned: always
type: str
sample:
@@ -124,13 +124,13 @@
sample:
- 1
title:
- description: The Folder title
+ description: The folder title
returned: always
type: str
sample:
- "Department ABC"
url:
- description: The Folder url
+ description: The folder url
returned: always
type: str
sample:
@@ -240,7 +240,7 @@ def __init__(self, module):
self._module.fail_json(failed=True, msg=to_text(e))
if grafana_version["major"] < 5:
self._module.fail_json(
- failed=True, msg="Folders API is available starting Grafana v5"
+ failed=True, msg="folders API is available starting Grafana v5"
)
if grafana_version["major"] < 11 and module.params["parent_uid"]:
self._module.fail_json(
@@ -276,7 +276,7 @@ def _send_request(self, url, data=None, headers=None, method="GET"):
response = resp.read() or "{}"
return self._module.from_json(response)
self._module.fail_json(
- failed=True, msg="Grafana Folders API answered with HTTP %d" % status_code
+ failed=True, msg="Grafana folders API answered with HTTP %d" % status_code
)
def switch_organization(self, org_id):
From 19218c4bfb201b6b6b2e3727fffa9eab84ca6be8 Mon Sep 17 00:00:00 2001
From: Moritz <15136847+Nemental@users.noreply.github.com>
Date: Wed, 3 Jul 2024 10:32:14 +0200
Subject: [PATCH 117/120] chore: simplify if statement
Co-authored-by: Sebastian Gumprich
---
plugins/modules/grafana_folder.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/modules/grafana_folder.py b/plugins/modules/grafana_folder.py
index dc7e1b6d..9e7cea92 100644
--- a/plugins/modules/grafana_folder.py
+++ b/plugins/modules/grafana_folder.py
@@ -316,7 +316,7 @@ def create_folder(self, title, uid=None, parent_uid=None):
def get_folder(self, title, uid=None, parent_uid=None):
url = "/api/folders%s" % ("?parentUid=%s" % parent_uid if parent_uid else "")
response = self._send_request(url, headers=self.headers, method="GET")
- if response is not None:
+ if response:
if uid:
folders = [item for item in response if item.get("uid") == uid]
else:
From 2e15a7ebf04889a52d1ceaee20e859b29f7bed8b Mon Sep 17 00:00:00 2001
From: sfhl <59044937+sfhl@users.noreply.github.com>
Date: Tue, 9 Jul 2024 13:22:49 +0200
Subject: [PATCH 118/120] fix wrong vars
---
roles/grafana/tasks/main.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/roles/grafana/tasks/main.yml b/roles/grafana/tasks/main.yml
index d0ddab40..80704fa7 100644
--- a/roles/grafana/tasks/main.yml
+++ b/roles/grafana/tasks/main.yml
@@ -345,8 +345,8 @@
created_by: "{{ silence.created_by }}"
ends_at: "{{ silence.ends_at }}"
matchers: "{{ silence.matchers }}"
- org_id: "{{ datasource.org_id | default(omit) }}"
- org_name: "{{ datasource.org_name | default(omit) }}"
+ org_id: "{{ silence.org_id | default(omit) }}"
+ org_name: "{{ silence.org_name | default(omit) }}"
starts_at: "{{ silence.starts_at }}"
state: "{{ silence.state | default(omit) }}"
loop: "{{ grafana_silences }}"
From 9bc0280a75644b3877f3cf259af99f5eb90699cc Mon Sep 17 00:00:00 2001
From: sfhl <59044937+sfhl@users.noreply.github.com>
Date: Tue, 9 Jul 2024 13:58:48 +0200
Subject: [PATCH 119/120] Create patch-1.yaml
---
changelogs/fragments/patch-1.yaml | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 changelogs/fragments/patch-1.yaml
diff --git a/changelogs/fragments/patch-1.yaml b/changelogs/fragments/patch-1.yaml
new file mode 100644
index 00000000..1b2c3d60
--- /dev/null
+++ b/changelogs/fragments/patch-1.yaml
@@ -0,0 +1,2 @@
+bugfixes:
+ - Fix var prefixes
From 0f3ed379c2bac3c3322501baf33b4f17ec18853a Mon Sep 17 00:00:00 2001
From: Sebastian Gumprich
Date: Tue, 9 Jul 2024 14:38:16 +0200
Subject: [PATCH 120/120] Update patch-1.yaml
---
changelogs/fragments/patch-1.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/changelogs/fragments/patch-1.yaml b/changelogs/fragments/patch-1.yaml
index 1b2c3d60..84e78c92 100644
--- a/changelogs/fragments/patch-1.yaml
+++ b/changelogs/fragments/patch-1.yaml
@@ -1,2 +1,2 @@
bugfixes:
- - Fix var prefixes
+ - Fix var prefixes in silence-task in role