summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/grafana/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
commit975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch)
tree89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/community/grafana/tests
parentInitial commit. (diff)
downloadansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz
ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/grafana/tests')
-rw-r--r--ansible_collections/community/grafana/tests/.gitignore1
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/aliases1
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/defaults/main.yml7
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/files/dashboard.json85
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-export.yml33
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-folder-destination.yml33
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-file.yml44
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-id.yml40
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-url.yml39
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/delete-dashboard.yml16
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/main.yml7
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/aliases1
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/defaults/main.yml7
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/azure.yml123
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/cloudwatch.yml111
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/elastic.yml313
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/errors.yml18
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/influx.yml88
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/issues.yml46
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/loki.yml82
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/main.yml16
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/postgres.yml93
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/redis.yml101
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/thruk.yml78
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/uid.yml253
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/zabbix.yml114
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_folder/defaults/main.yml7
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_folder/tasks/main.yml55
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/defaults/main.yml7
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/dingding.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/discord.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/email.yml79
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/googlechat.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/hipchat.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/kafka.yml76
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/line.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/main.yml20
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/opsgenie.yml77
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/pagerduty.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/prometheus.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/pushover.yml76
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/sensu.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/slack-and-beyond.yml110
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/teams.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/telegram.yml76
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/threema.yml78
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/victorops.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/webhook.yml74
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_organization/defaults/main.yml4
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_organization/tasks/main.yml57
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_team/defaults/main.yml7
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_team/tasks/create_user.yml29
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_team/tasks/main.yml187
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_user/defaults/main.yml4
-rw-r--r--ansible_collections/community/grafana/tests/integration/targets/grafana_user/tasks/main.yml237
-rw-r--r--ansible_collections/community/grafana/tests/sanity/ignore-2.10.txt4
-rw-r--r--ansible_collections/community/grafana/tests/sanity/ignore-2.11.txt6
-rw-r--r--ansible_collections/community/grafana/tests/sanity/ignore-2.12.txt4
-rw-r--r--ansible_collections/community/grafana/tests/sanity/ignore-2.13.txt4
-rw-r--r--ansible_collections/community/grafana/tests/sanity/ignore-2.14.txt4
-rw-r--r--ansible_collections/community/grafana/tests/sanity/ignore-2.15.txt4
-rw-r--r--ansible_collections/community/grafana/tests/sanity/ignore-2.9.txt3
-rw-r--r--ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_datasource/test_grafana_datasource.py212
-rw-r--r--ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py111
-rw-r--r--ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_team/test_grafana_team.py447
-rw-r--r--ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_user/test_grafana_user.py200
66 files changed, 4749 insertions, 0 deletions
diff --git a/ansible_collections/community/grafana/tests/.gitignore b/ansible_collections/community/grafana/tests/.gitignore
new file mode 100644
index 000000000..ea1472ec1
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/.gitignore
@@ -0,0 +1 @@
+output/
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/aliases b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/aliases
new file mode 100644
index 000000000..a6dafcf8c
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/aliases
@@ -0,0 +1 @@
+shippable/posix/group1
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/defaults/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/defaults/main.yml
new file mode 100644
index 000000000..8b9c9348a
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+
+grafana_url: "http://grafana:3000/"
+grafana_username: "admin"
+grafana_password: "admin"
+
+...
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/files/dashboard.json b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/files/dashboard.json
new file mode 100644
index 000000000..70287fa74
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/files/dashboard.json
@@ -0,0 +1,85 @@
+{
+ "annotations": {
+ "list": [
+ {
+ "builtIn": 1,
+ "datasource": "-- Grafana --",
+ "enable": true,
+ "hide": true,
+ "iconColor": "rgba(0, 211, 255, 1)",
+ "name": "Annotations & Alerts",
+ "type": "dashboard"
+ }
+ ]
+ },
+ "editable": true,
+ "gnetId": null,
+ "graphTooltip": 0,
+ "id": 11,
+ "links": [],
+ "panels": [
+ {
+ "content": "\n# Title\n\nFor markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)\n\n\n\n",
+ "gridPos": {
+ "h": 9,
+ "w": 12,
+ "x": 0,
+ "y": 0
+ },
+ "id": 2,
+ "mode": "markdown",
+ "options": {},
+ "targets": [
+ {
+ "expr": "",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "refId": "A"
+ }
+ ],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Panel Title",
+ "type": "text"
+ }
+ ],
+ "schemaVersion": 18,
+ "style": "dark",
+ "tags": [],
+ "templating": {
+ "list": []
+ },
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {
+ "refresh_intervals": [
+ "5s",
+ "10s",
+ "30s",
+ "1m",
+ "5m",
+ "15m",
+ "30m",
+ "1h",
+ "2h",
+ "1d"
+ ],
+ "time_options": [
+ "5m",
+ "15m",
+ "1h",
+ "6h",
+ "12h",
+ "24h",
+ "2d",
+ "7d",
+ "30d"
+ ]
+ },
+ "timezone": "",
+ "title": "test",
+ "uid": "9ZlJIhhWk",
+ "version": 7
+ } \ No newline at end of file
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-export.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-export.yml
new file mode 100644
index 000000000..04b17f727
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-export.yml
@@ -0,0 +1,33 @@
+---
+- set_fact:
+ dashboard_uid: "{{ result.uid }}"
+
+- name: Check export grafana dashboard to file
+ grafana_dashboard:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: export
+ path: /tmp/dashboard.json
+ overwrite: true
+ uid: "{{ dashboard_uid }}"
+ register: result
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.msg == 'Dashboard {{ dashboard_uid }} exported to /tmp/dashboard.json'"
+
+- name: Load /tmp/dashboard.json or fail if missing
+ set_fact:
+ exported_dashboard_lines: "{{ lookup('file', '/tmp/dashboard.json').splitlines() }}"
+
+- name: Assert that exported dashboard contains formatted JSON
+ assert:
+ that:
+ - "exported_dashboard_lines | length >= 2"
+ - "exported_dashboard_lines[0] == '{'"
+ - "exported_dashboard_lines[-1] == '}'"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-folder-destination.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-folder-destination.yml
new file mode 100644
index 000000000..f4f3d9f4d
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-folder-destination.yml
@@ -0,0 +1,33 @@
+---
+- name: copy dashboard file
+ copy:
+ src: "files/dashboard.json"
+ dest: "/tmp/dashboard.json"
+
+- block:
+ - name: Check import grafana dashboard from file to unknown folder fails
+ grafana_dashboard:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: present
+ commit_message: Updated by ansible
+ path: /tmp/dashboard.json
+ overwrite: true
+ folder: inexistent
+ register: result
+ ignore_errors: true
+
+- debug:
+ var: result
+
+- set_fact:
+ # XXX: Too many quotes of different types to do inline.
+ # I did not manage to find a good way of having it inline.
+ expected_error: "error : Dashboard folder 'inexistent' does not exist."
+
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.failed == true"
+ - "result.msg == expected_error"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-file.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-file.yml
new file mode 100644
index 000000000..93df1666a
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-file.yml
@@ -0,0 +1,44 @@
+---
+- name: copy dashboard file
+ copy:
+ src: "files/dashboard.json"
+ dest: "/tmp/dashboard.json"
+
+
+- name: Check import grafana dashboard from file
+ grafana_dashboard:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: present
+ commit_message: Updated by ansible
+ path: /tmp/dashboard.json
+ overwrite: true
+ register: result
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.msg == 'Dashboard test created'"
+
+- name: Check import grafana dashboard from file idempotency
+ grafana_dashboard:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: present
+ commit_message: Updated by ansible
+ path: /tmp/dashboard.json
+ overwrite: true
+ register: result
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.msg == 'Dashboard test unchanged.'"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-id.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-id.yml
new file mode 100644
index 000000000..3b81ebf71
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-id.yml
@@ -0,0 +1,40 @@
+---
+- name: Check import grafana dashboard from id
+ grafana_dashboard:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: present
+ commit_message: Updated by ansible
+ dashboard_id: "6098"
+ dashboard_revision: "1"
+ overwrite: true
+ register: result
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.msg == 'Dashboard Zabbix Host Status created'"
+
+- name: Check import grafana dashboard from id idempotency
+ grafana_dashboard:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: present
+ commit_message: Updated by ansible
+ dashboard_id: "6098"
+ dashboard_revision: "1"
+ overwrite: true
+ register: result
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.msg == 'Dashboard Zabbix Host Status unchanged.'"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-url.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-url.yml
new file mode 100644
index 000000000..5146fc9a0
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/dashboard-from-url.yml
@@ -0,0 +1,39 @@
+---
+
+- name: Check import grafana dashboard from url
+ grafana_dashboard:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: present
+ commit_message: Updated by ansible
+ dashboard_url: https://grafana.com/api/dashboards/6098/revisions/1/download
+ overwrite: true
+ register: result
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.msg == 'Dashboard Zabbix Host Status created'"
+
+- name: Check import grafana dashboard from url idempotency
+ grafana_dashboard:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: present
+ commit_message: Updated by ansible
+ dashboard_url: https://grafana.com/api/dashboards/6098/revisions/1/download
+ overwrite: true
+ register: result
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.msg == 'Dashboard Zabbix Host Status unchanged.'"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/delete-dashboard.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/delete-dashboard.yml
new file mode 100644
index 000000000..2013324fb
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/delete-dashboard.yml
@@ -0,0 +1,16 @@
+- name: Check delete dashboard is working
+ grafana_dashboard:
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+ uid: "{{ result.uid }}"
+ register: result
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.msg == 'Dashboard {{ result.uid }} deleted'"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/main.yml
new file mode 100644
index 000000000..4d9138fcf
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_dashboard/tasks/main.yml
@@ -0,0 +1,7 @@
+- block:
+ - include: dashboard-from-url.yml
+ - include: delete-dashboard.yml
+ - include: dashboard-from-id.yml
+ - include: dashboard-from-file.yml
+ - include: dashboard-export.yml
+ - include: dashboard-folder-destination.yml
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/aliases b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/aliases
new file mode 100644
index 000000000..a6dafcf8c
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/aliases
@@ -0,0 +1 @@
+shippable/posix/group1
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/defaults/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/defaults/main.yml
new file mode 100644
index 000000000..8b9c9348a
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+
+grafana_url: "http://grafana:3000/"
+grafana_username: "admin"
+grafana_password: "admin"
+
+...
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/azure.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/azure.yml
new file mode 100644
index 000000000..a96691893
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/azure.yml
@@ -0,0 +1,123 @@
+- name: Create azure datasource
+ register: result
+ grafana_datasource:
+ name: datasource-azure
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ org_id: '1'
+ ds_type: grafana-azure-monitor-datasource
+ ds_url: http://example.com
+ azure_client: client1
+ azure_tenant: tenant1
+ azure_secret: secret1
+ azure_cloud: azuremonitor
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-azure created'"
+ - result.datasource.access == 'proxy'
+ - result.datasource.basicAuth == false
+ - result.datasource.database == ''
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.clientId == 'client1'
+ - result.datasource.jsonData.cloudName == 'azuremonitor'
+ - result.datasource.jsonData.tenantId == 'tenant1'
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.jsonData.tlsAuthWithCACert == false
+ - result.datasource.name == 'datasource-azure'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'grafana-azure-monitor-datasource'
+ - result.datasource.url == 'http://example.com'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Check azure datasource creation idempotency
+ register: result
+ grafana_datasource:
+ name: datasource-azure
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ org_id: '1'
+ ds_type: grafana-azure-monitor-datasource
+ ds_url: http://example.com
+ azure_client: client1
+ azure_tenant: tenant1
+ azure_secret: secret1
+ azure_cloud: azuremonitor
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.access == 'proxy'
+ - result.datasource.basicAuth == false
+ - result.datasource.database == ''
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.clientId == 'client1'
+ - result.datasource.jsonData.cloudName == 'azuremonitor'
+ - result.datasource.jsonData.tenantId == 'tenant1'
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.jsonData.tlsAuthWithCACert == false
+ - result.datasource.name == 'datasource-azure'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'grafana-azure-monitor-datasource'
+ - result.datasource.url == 'http://example.com'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Delete azure datasource
+ register: result
+ grafana_datasource:
+ name: datasource-azure
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ org_id: '1'
+ ds_type: grafana-azure-monitor-datasource
+ ds_url: http://example.com
+ azure_client: client1
+ azure_tenant: tenant1
+ azure_secret: secret1
+ azure_cloud: azuremonitor
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-azure deleted.'"
+
+- name: Delete azure datasource (idempotency)
+ register: result
+ grafana_datasource:
+ name: datasource-azure
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ org_id: '1'
+ ds_type: grafana-azure-monitor-datasource
+ ds_url: http://example.com
+ azure_client: client1
+ azure_tenant: tenant1
+ azure_secret: secret1
+ azure_cloud: azuremonitor
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/cloudwatch.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/cloudwatch.yml
new file mode 100644
index 000000000..50268ea8f
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/cloudwatch.yml
@@ -0,0 +1,111 @@
+- name: Create cloudwatch datasource
+ register: result
+ grafana_datasource:
+ name: datasource-cloudwatch
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ org_id: '1'
+ ds_type: cloudwatch
+ ds_url: http://monitoring.us-west-1.amazonaws.com
+ aws_auth_type: keys
+ aws_default_region: us-west-1
+ aws_access_key: speakFriendAndEnter
+ aws_secret_key: mel10n
+ aws_custom_metrics_namespaces: n1,n2
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-cloudwatch created'"
+ - result.datasource.access == 'proxy'
+ - result.datasource.basicAuth == false
+ - result.datasource.database == ''
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.authType == 'keys'
+ - result.datasource.jsonData.customMetricsNamespaces == 'n1,n2'
+ - result.datasource.jsonData.defaultRegion == 'us-west-1'
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.jsonData.tlsAuthWithCACert == false
+ - result.datasource.name == 'datasource-cloudwatch'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'cloudwatch'
+ - result.datasource.url == 'http://monitoring.us-west-1.amazonaws.com'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Check cloudwatch datasource creation idempotency
+ register: result
+ grafana_datasource:
+ name: datasource-cloudwatch
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: cloudwatch
+ ds_url: http://monitoring.us-west-1.amazonaws.com
+ aws_auth_type: keys
+ aws_default_region: us-west-1
+ aws_access_key: speakFriendAndEnter
+ aws_secret_key: mel10n
+ aws_custom_metrics_namespaces: n1,n2
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.access == 'proxy'
+ - result.datasource.basicAuth == false
+ - result.datasource.database == ''
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.authType == 'keys'
+ - result.datasource.jsonData.customMetricsNamespaces == 'n1,n2'
+ - result.datasource.jsonData.defaultRegion == 'us-west-1'
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.jsonData.tlsAuthWithCACert == false
+ - result.datasource.name == 'datasource-cloudwatch'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'cloudwatch'
+ - result.datasource.url == 'http://monitoring.us-west-1.amazonaws.com'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Delete cloudwatch datasource
+ register: result
+ grafana_datasource:
+ name: datasource-cloudwatch
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-cloudwatch deleted.'"
+
+- name: Delete cloudwatch datasource (idempotency)
+ register: result
+ grafana_datasource:
+ name: datasource-cloudwatch
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/elastic.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/elastic.yml
new file mode 100644
index 000000000..73b258426
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/elastic.yml
@@ -0,0 +1,313 @@
+---
+- name: Create elasticsearch datasource with legacy elasticsearch format
+ register: result
+ grafana_datasource:
+ name: "datasource/elasticLegacy"
+ uid: "myuid"
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: elasticsearch
+ ds_url: https://elastic.company.com:9200
+ database: '[logstash_]YYYY.MM.DD'
+ basic_auth_user: grafana
+ basic_auth_password: '******'
+ time_field: '@timestamp'
+ time_interval: 1m
+ interval: Daily
+ es_version: 56
+ max_concurrent_shard_requests: 42
+ tls_ca_cert: /etc/ssl/certs/ca.pem
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.basicAuth
+ - result.datasource.basicAuthUser == 'grafana'
+ - result.datasource.access == 'proxy'
+ - result.datasource.database == '[logstash_]YYYY.MM.DD'
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.esVersion == 56
+ - result.datasource.jsonData.interval == 'Daily'
+ - result.datasource.jsonData.maxConcurrentShardRequests == 42
+ - result.datasource.jsonData.timeField == '@timestamp'
+ - not result.datasource.jsonData.tlsAuth
+ - result.datasource.jsonData.tlsAuthWithCACert
+ - result.datasource.name == 'datasource/elasticLegacy'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'elasticsearch'
+ - result.datasource.url == 'https://elastic.company.com:9200'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+ - "result.msg == 'Datasource datasource/elasticLegacy created'"
+
+- name: Create elasticsearch datasource with new elsaticsearch version format
+ register: result
+ grafana_datasource:
+ name: "datasource/elastic"
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: elasticsearch
+ ds_url: https://elastic.company.com:9200
+ database: '[logstash_]YYYY.MM.DD'
+ basic_auth_user: grafana
+ basic_auth_password: '******'
+ time_field: '@timestamp'
+ time_interval: 1m
+ interval: Daily
+ es_version: "7.10+"
+ max_concurrent_shard_requests: 42
+ tls_ca_cert: /etc/ssl/certs/ca.pem
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.basicAuth
+ - result.datasource.basicAuthUser == 'grafana'
+ - result.datasource.access == 'proxy'
+ - result.datasource.database == '[logstash_]YYYY.MM.DD'
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.esVersion == "7.10.0"
+ - result.datasource.jsonData.interval == 'Daily'
+ - result.datasource.jsonData.maxConcurrentShardRequests == 42
+ - result.datasource.jsonData.timeField == '@timestamp'
+ - not result.datasource.jsonData.tlsAuth
+ - result.datasource.jsonData.tlsAuthWithCACert
+ - result.datasource.name == 'datasource/elastic'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'elasticsearch'
+ - result.datasource.url == 'https://elastic.company.com:9200'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+ - "result.msg == 'Datasource datasource/elastic created'"
+
+- name: Check elasticsearch datasource creation idempotency
+ register: result
+ grafana_datasource:
+ name: "datasource/elastic"
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: elasticsearch
+ ds_url: https://elastic.company.com:9200
+ database: '[logstash_]YYYY.MM.DD'
+ basic_auth_user: grafana
+ basic_auth_password: '******'
+ time_field: '@timestamp'
+ time_interval: 1m
+ interval: Daily
+ es_version: "7.10+"
+ max_concurrent_shard_requests: 42
+ tls_ca_cert: /etc/ssl/certs/ca.pem
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.basicAuth
+ - result.datasource.basicAuthUser == 'grafana'
+ - result.datasource.access == 'proxy'
+ - result.datasource.database == '[logstash_]YYYY.MM.DD'
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.esVersion == '7.10.0'
+ - result.datasource.jsonData.interval == 'Daily'
+ - result.datasource.jsonData.maxConcurrentShardRequests == 42
+ - result.datasource.jsonData.timeField == '@timestamp'
+ - not result.datasource.jsonData.tlsAuth
+ - result.datasource.jsonData.tlsAuthWithCACert
+ - result.datasource.name == 'datasource/elastic'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'elasticsearch'
+ - result.datasource.url == 'https://elastic.company.com:9200'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+
+- name: update elasticsearch datasource creation
+ register: result
+ grafana_datasource:
+ name: "datasource/elastic"
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: elasticsearch
+ ds_url: https://elastic.example.com:9200
+ database: '[logstash_]YYYY.MM.DD'
+ basic_auth_user: grafana
+ basic_auth_password: '******'
+ time_field: '@timestamp'
+ time_interval: 1m
+ interval: Daily
+ es_version: "7.10+"
+ max_concurrent_shard_requests: 42
+ tls_ca_cert: /etc/ssl/certs/ca.pem
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.basicAuth
+ - result.datasource.basicAuthUser == 'grafana'
+ - result.datasource.access == 'proxy'
+ - result.datasource.database == '[logstash_]YYYY.MM.DD'
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.esVersion == '7.10.0'
+ - result.datasource.jsonData.interval == 'Daily'
+ - result.datasource.jsonData.maxConcurrentShardRequests == 42
+ - result.datasource.jsonData.timeField == '@timestamp'
+ - not result.datasource.jsonData.tlsAuth
+ - result.datasource.jsonData.tlsAuthWithCACert
+ - result.datasource.name == 'datasource/elastic'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'elasticsearch'
+ - result.datasource.url == 'https://elastic.example.com:9200'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+
+- name: update elasticsearch datasource (ignoring secureJsonData)
+ register: result
+ grafana_datasource:
+ name: "datasource/elastic"
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: elasticsearch
+ ds_url: https://elastic.example.com:9200
+ database: '[logstash_]YYYY.MM.DD'
+ basic_auth_user: grafana
+ basic_auth_password: '******'
+ time_field: '@timestamp'
+ time_interval: 1m
+ interval: Daily
+ es_version: "7.10+"
+ max_concurrent_shard_requests: 42
+ tls_ca_cert: /etc/ssl/certs/ca.pem
+ enforce_secure_data: false
+ additional_json_data:
+ nonSecureTest: "nonsecure"
+ additional_secure_json_data:
+ secureTest: "secure"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.basicAuth
+ - result.datasource.basicAuthUser == 'grafana'
+ - result.datasource.access == 'proxy'
+ - result.datasource.database == '[logstash_]YYYY.MM.DD'
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.esVersion == '7.10.0'
+ - result.datasource.jsonData.interval == 'Daily'
+ - result.datasource.jsonData.maxConcurrentShardRequests == 42
+ - result.datasource.jsonData.timeField == '@timestamp'
+ - not result.datasource.jsonData.tlsAuth
+ - result.datasource.jsonData.tlsAuthWithCACert
+ - result.datasource.name == 'datasource/elastic'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'elasticsearch'
+ - result.datasource.url == 'https://elastic.example.com:9200'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+ - result.datasource.jsonData.nonSecureTest == 'nonsecure'
+
+- name: update elasticsearch datasource (including secureJsonData)
+ register: result
+ grafana_datasource:
+ name: "datasource/elastic"
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: elasticsearch
+ ds_url: https://elastic.example.com:9200
+ database: '[logstash_]YYYY.MM.DD'
+ basic_auth_user: grafana
+ basic_auth_password: '******'
+ time_field: '@timestamp'
+ time_interval: 1m
+ interval: Daily
+ es_version: "7.10+"
+ max_concurrent_shard_requests: 42
+ tls_ca_cert: /etc/ssl/certs/ca.pem
+ enforce_secure_data: true
+ additional_json_data:
+ nonSecureTest: "nonsecure"
+ additional_secure_json_data:
+ secureTest: "secure"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.basicAuth
+ - result.datasource.basicAuthUser == 'grafana'
+ - result.datasource.access == 'proxy'
+ - result.datasource.database == '[logstash_]YYYY.MM.DD'
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.esVersion == '7.10.0'
+ - result.datasource.jsonData.interval == 'Daily'
+ - result.datasource.jsonData.maxConcurrentShardRequests == 42
+ - result.datasource.jsonData.timeField == '@timestamp'
+ - not result.datasource.jsonData.tlsAuth
+ - result.datasource.jsonData.tlsAuthWithCACert
+ - result.datasource.name == 'datasource/elastic'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'elasticsearch'
+ - result.datasource.url == 'https://elastic.example.com:9200'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+ - result.datasource.jsonData.nonSecureTest == 'nonsecure'
+ - result.datasource.secureJsonFields.secureTest == true
+ - result.diff.after.secureJsonData is defined
+
+- name: Delete elasticsearch datasource
+ register: result
+ grafana_datasource:
+ name: "datasource/elastic"
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- assert:
+ that:
+ - result.changed
+
+- name: Delete elasticsearch datasource (idempotency)
+ register: result
+ grafana_datasource:
+ name: "datasource/elastic"
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/errors.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/errors.yml
new file mode 100644
index 000000000..731a19d8f
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/errors.yml
@@ -0,0 +1,18 @@
+---
+- name: Create datasource without `ds_type` and `ds_url` (expect failure)
+ register: result
+ grafana_datasource:
+ name: datasource-postgres
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ ignore_errors: true
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.failed
+ - "result.msg == 'state is present but all of the following are missing: ds_type, ds_url'"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/influx.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/influx.yml
new file mode 100644
index 000000000..da61833f6
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/influx.yml
@@ -0,0 +1,88 @@
+- name: Create influxdb datasource
+ register: result
+ grafana_datasource:
+ name: datasource-influxdb
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: influxdb
+ ds_url: https://influx.company.com:8086
+ database: telegraf
+ time_interval: '>10s'
+ tls_ca_cert: /etc/ssl/certs/ca.pem
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-influxdb created'"
+
+- name: Check influxdb datasource creation idempotency
+ register: result
+ grafana_datasource:
+ name: datasource-influxdb
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: influxdb
+ ds_url: https://influx.company.com:8086
+ database: telegraf
+ time_interval: '>10s'
+ tls_ca_cert: /etc/ssl/certs/ca.pem
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.basicAuth == false
+ - result.datasource.access == 'proxy'
+ - result.datasource.database == 'telegraf'
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.timeInterval == '>10s'
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.jsonData.tlsAuthWithCACert
+ - result.datasource.name == 'datasource-influxdb'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'influxdb'
+ - result.datasource.url == 'https://influx.company.com:8086'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Delete influxdb datasource
+ register: result
+ grafana_datasource:
+ name: datasource-influxdb
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+
+- name: Delete influxdb datasource (idempotency)
+ register: result
+ grafana_datasource:
+ name: datasource-influxdb
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/issues.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/issues.yml
new file mode 100644
index 000000000..f80677d8d
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/issues.yml
@@ -0,0 +1,46 @@
+---
+
+- name: test datasource name with slash
+ register: result
+ grafana_datasource:
+ name: "datasource/elastic"
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: elasticsearch
+ ds_url: https://elastic.company.com:9200
+ database: '[logstash_]YYYY.MM.DD'
+ basic_auth_user: grafana
+ basic_auth_password: '******'
+ time_field: '@timestamp'
+ time_interval: 1m
+ interval: Daily
+ es_version: 56
+ max_concurrent_shard_requests: 42
+ tls_ca_cert: /etc/ssl/certs/ca.pem
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.basicAuth
+ - result.datasource.basicAuthUser == 'grafana'
+ - result.datasource.access == 'proxy'
+ - result.datasource.database == '[logstash_]YYYY.MM.DD'
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.esVersion == 56
+ - result.datasource.jsonData.interval == 'Daily'
+ - result.datasource.jsonData.maxConcurrentShardRequests == 42
+ - result.datasource.jsonData.timeField == '@timestamp'
+ - not result.datasource.jsonData.tlsAuth
+ - not result.datasource.jsonData.tlsAuthWithCACert
+ - result.datasource.name == 'datasource/elastic'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'elasticsearch'
+ - result.datasource.url == 'https://elastic.company.com:9200'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+ - "result.msg == 'Datasource datasource/elastic created'"
+
+...
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/loki.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/loki.yml
new file mode 100644
index 000000000..68eca9802
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/loki.yml
@@ -0,0 +1,82 @@
+- name: Create loki datasource
+ register: result
+ grafana_datasource:
+ name: datasource-loki
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ org_id: '1'
+ ds_type: loki
+ ds_url: https://loki.company.com:3100
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-loki created'"
+
+- name: Check loki datasource creation idempotency
+ register: result
+ grafana_datasource:
+ name: datasource-loki
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: loki
+ ds_url: https://loki.company.com:3100
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.basicAuth == false
+ - result.datasource.access == 'proxy'
+ - result.datasource.database == ''
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.jsonData.tlsAuthWithCACert == false
+ - result.datasource.name == 'datasource-loki'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'loki'
+ - result.datasource.url == 'https://loki.company.com:3100'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Delete loki datasource
+ register: result
+ grafana_datasource:
+ name: datasource-loki
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-loki deleted.'"
+
+- name: Delete loki datasource (idempotency)
+ register: result
+ grafana_datasource:
+ name: datasource-loki
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/main.yml
new file mode 100644
index 000000000..b5798e9a8
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+
+- block:
+ - include: errors.yml
+ - include: elastic.yml
+ - include: influx.yml
+ - include: postgres.yml
+ - include: cloudwatch.yml
+ - include: thruk.yml
+ - include: loki.yml
+ - include: zabbix.yml
+ - include: redis.yml
+ - include: azure.yml
+ - include: uid.yml
+
+...
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/postgres.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/postgres.yml
new file mode 100644
index 000000000..80221f012
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/postgres.yml
@@ -0,0 +1,93 @@
+- name: Create postgres datasource
+ register: result
+ grafana_datasource:
+ name: datasource-postgres
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: postgres
+ ds_url: postgres.company.com:5432
+ database: db
+ user: postgres
+ password: iampgroot
+ sslmode: verify-full
+ additional_json_data:
+ timescaledb: true
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-postgres created'"
+
+- name: Check postgres datasource creation idempotency
+ register: result
+ grafana_datasource:
+ name: datasource-postgres
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: postgres
+ ds_url: postgres.company.com:5432
+ database: db
+ user: postgres
+ password: iampgroot
+ sslmode: verify-full
+ additional_json_data:
+ timescaledb: true
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.basicAuth == false
+ - result.datasource.database == 'db'
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.sslmode == 'verify-full'
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.jsonData.tlsAuthWithCACert == false
+ - result.datasource.jsonData.timescaledb == true
+ - result.datasource.name == 'datasource-postgres'
+ - result.datasource.orgId == 1
+ - result.datasource.type == 'postgres'
+ - result.datasource.url == 'postgres.company.com:5432'
+ - result.datasource.user == 'postgres'
+ - result.datasource.withCredentials == false
+
+- name: Delete postgres datasource
+ register: result
+ grafana_datasource:
+ name: datasource-postgres
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+
+- name: Delete postgres datasource
+ register: result
+ grafana_datasource:
+ name: datasource-postgres
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/redis.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/redis.yml
new file mode 100644
index 000000000..933695354
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/redis.yml
@@ -0,0 +1,101 @@
+- name: Create redis datasource
+ register: result
+ grafana_datasource:
+ name: datasource-redis
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: redis-datasource
+ ds_url: https://redis.company.com:6379
+ time_interval: 1m
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.access == 'proxy'
+ - not result.datasource.isDefault
+ - result.datasource.name == 'datasource-redis'
+ - result.datasource.orgId == 1
+ - result.datasource.type == 'redis-datasource'
+ - result.datasource.url == 'https://redis.company.com:6379'
+ - "result.msg == 'Datasource datasource-redis created'"
+
+- name: Check redis-datasource datasource creation idempotency
+ register: result
+ grafana_datasource:
+ name: datasource-redis
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: redis-datasource
+ ds_url: https://redis.company.com:6379
+ time_interval: 1m
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.access == 'proxy'
+ - not result.datasource.isDefault
+ - result.datasource.name == 'datasource-redis'
+ - result.datasource.orgId == 1
+ - result.datasource.type == 'redis-datasource'
+ - result.datasource.url == 'https://redis.company.com:6379'
+
+- name: update redis-datasource datasource creation
+ register: result
+ grafana_datasource:
+ name: datasource-redis
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: redis-datasource
+ ds_url: https://redisnew.company.com:6379
+ time_interval: 1m
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.access == 'proxy'
+ - not result.datasource.isDefault
+ - result.datasource.name == 'datasource-redis'
+ - result.datasource.orgId == 1
+ - result.datasource.type == 'redis-datasource'
+ - result.datasource.url == 'https://redisnew.company.com:6379'
+
+- name: Delete redis-datasource datasource
+ register: result
+ grafana_datasource:
+ name: datasource-redis
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- assert:
+ that:
+ - result.changed
+
+- name: Delete redis-datasource datasource (idempotency)
+ register: result
+ grafana_datasource:
+ name: datasource-redis
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/thruk.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/thruk.yml
new file mode 100644
index 000000000..3ecc92d94
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/thruk.yml
@@ -0,0 +1,78 @@
+- name: Create thruk datasource
+ register: result
+ grafana_datasource:
+ name: datasource-thruk
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: "1"
+ ds_type: sni-thruk-datasource
+ ds_url: "https://thruk.company.com/sitename/thruk"
+ tls_skip_verify: yes
+ validate_certs: no
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-thruk created'"
+
+- name: Check thruk datasource creation idempotency
+ register: result
+ grafana_datasource:
+ name: datasource-thruk
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: sni-thruk-datasource
+ ds_url: "https://thruk.company.com/sitename/thruk"
+ tls_skip_verify: yes
+ validate_certs: no
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.basicAuth == false
+ - result.datasource.access == 'proxy'
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.jsonData.tlsAuthWithCACert == false
+ - result.datasource.name == 'datasource-thruk'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'sni-thruk-datasource'
+ - result.datasource.url == 'https://thruk.company.com/sitename/thruk'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Delete thruk datasource
+ register: result
+ grafana_datasource:
+ name: datasource-thruk
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+
+- name: Delete thruk datasource (idempotency)
+ register: result
+ grafana_datasource:
+ name: datasource-thruk
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/uid.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/uid.yml
new file mode 100644
index 000000000..71102a074
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/uid.yml
@@ -0,0 +1,253 @@
+- name: Create datasource with uid
+ register: result
+ grafana_datasource:
+ name: datasource-with-uid
+ uid: uid1
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: prometheus
+ ds_url: https://prometheus.company.com:8086
+ basic_auth_user: "admin"
+ basic_auth_password: "admin"
+ validate_certs: False
+ is_default: no
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-with-uid created'"
+
+- name: Create datasource without uid
+ register: result
+ grafana_datasource:
+ name: datasource-without-uid
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: prometheus
+ ds_url: https://prometheus.company.com:8086
+ basic_auth_user: "admin"
+ basic_auth_password: "admin"
+ validate_certs: False
+ is_default: no
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - "result.msg == 'Datasource datasource-without-uid created'"
+
+- name: Check datasource creation idempotency with uid
+ register: result
+ grafana_datasource:
+ name: datasource-with-uid
+ uid: uid1
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: prometheus
+ ds_url: https://prometheus.company.com:8086
+ basic_auth_user: "admin"
+ basic_auth_password: "admin"
+ validate_certs: False
+ is_default: no
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.access == 'proxy'
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.name == 'datasource-with-uid'
+ - result.datasource.uid == 'uid1'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'prometheus'
+ - result.datasource.url == 'https://prometheus.company.com:8086'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Check datasource creation idempotency without uid
+ register: result
+ grafana_datasource:
+ name: datasource-without-uid
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: prometheus
+ ds_url: https://prometheus.company.com:8086
+ basic_auth_user: "admin"
+ basic_auth_password: "admin"
+ validate_certs: False
+ is_default: no
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - result.datasource.access == 'proxy'
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.name == 'datasource-without-uid'
+ - result.datasource.uid
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'prometheus'
+ - result.datasource.url == 'https://prometheus.company.com:8086'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Set uid for datasource with random uid
+ register: result
+ grafana_datasource:
+ name: datasource-without-uid
+ uid: uid3
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: prometheus
+ ds_url: https://prometheus.company.com:8086
+ basic_auth_user: "admin"
+ basic_auth_password: "admin"
+ validate_certs: False
+ is_default: no
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.access == 'proxy'
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.name == 'datasource-without-uid'
+ - result.datasource.uid == 'uid3'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'prometheus'
+ - result.datasource.url == 'https://prometheus.company.com:8086'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Change uid for datasource
+ register: result
+ grafana_datasource:
+ name: datasource-with-uid
+ uid: uid2
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: prometheus
+ ds_url: https://prometheus.company.com:8086
+ basic_auth_user: "admin"
+ basic_auth_password: "admin"
+ validate_certs: False
+ is_default: no
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - result.datasource.access == 'proxy'
+ - result.datasource.isDefault == false
+ - result.datasource.jsonData.tlsAuth == false
+ - result.datasource.name == 'datasource-with-uid'
+ - result.datasource.uid == 'uid2'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'prometheus'
+ - result.datasource.url == 'https://prometheus.company.com:8086'
+ - result.datasource.user == ''
+ - result.datasource.withCredentials == false
+
+- name: Delete datasource-with-uid
+ register: result
+ grafana_datasource:
+ name: datasource-with-uid
+ uid: uid1
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: prometheus
+ ds_url: https://prometheus.company.com:8086
+ basic_auth_user: "admin"
+ basic_auth_password: "admin"
+ validate_certs: False
+ is_default: no
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+
+- name: Delete datasource-without-uid
+ register: result
+ grafana_datasource:
+ name: datasource-without-uid
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: prometheus
+ ds_url: https://prometheus.company.com:8086
+ basic_auth_user: "admin"
+ basic_auth_password: "admin"
+ validate_certs: False
+ is_default: no
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+
+- name: Delete datasource-with-uid (idempotency)
+ register: result
+ grafana_datasource:
+ name: datasource-with-uid
+ uid: uid1
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: prometheus
+ ds_url: https://prometheus.company.com:8086
+ basic_auth_user: "admin"
+ basic_auth_password: "admin"
+ validate_certs: False
+ is_default: no
+
+ state: absent
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/zabbix.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/zabbix.yml
new file mode 100644
index 000000000..c8a8236bf
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_datasource/tasks/zabbix.yml
@@ -0,0 +1,114 @@
+- name: Create zabbix datasource
+ register: result
+ grafana_datasource:
+ name: datasource-zabbix
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: alexanderzobnin-zabbix-datasource
+ ds_url: https://zabbix.company.com
+ zabbix_user: grafana
+ zabbix_password: '******'
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.username == 'grafana'
+ - result.datasource.name == 'datasource-zabbix'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'alexanderzobnin-zabbix-datasource'
+ - result.datasource.url == 'https://zabbix.company.com'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+ - "result.msg == 'Datasource datasource-zabbix created'"
+
+- name: Create zabbix datasource (idempotency)
+ register: result
+ grafana_datasource:
+ name: datasource-zabbix
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: alexanderzobnin-zabbix-datasource
+ ds_url: https://zabbix.company.com
+ zabbix_user: grafana
+ zabbix_password: '******'
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - not result.changed
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.username == 'grafana'
+ - result.datasource.name == 'datasource-zabbix'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'alexanderzobnin-zabbix-datasource'
+ - result.datasource.url == 'https://zabbix.company.com'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+
+- name: Update zabbix datasource
+ register: result
+ grafana_datasource:
+ name: datasource-zabbix
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ org_id: '1'
+ ds_type: alexanderzobnin-zabbix-datasource
+ ds_url: https://zabbix.example.com
+ zabbix_user: grafana
+ zabbix_password: '******'
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed
+ - not result.datasource.isDefault
+ - result.datasource.jsonData.username == 'grafana'
+ - result.datasource.name == 'datasource-zabbix'
+ - result.datasource.orgId == 1
+ - ('password' not in result.datasource) or (result.datasource.password == '')
+ - result.datasource.type == 'alexanderzobnin-zabbix-datasource'
+ - result.datasource.url == 'https://zabbix.example.com'
+ - result.datasource.user == ''
+ - not result.datasource.withCredentials
+ - "result.msg == 'Datasource datasource-zabbix updated'"
+
+- name: Delete zabbix datasource
+ register: result
+ grafana_datasource:
+ name: datasource-zabbix
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- assert:
+ that:
+ - result.changed
+
+- name: Delete zabbix datasource (idempotency)
+ register: result
+ grafana_datasource:
+ name: datasource-zabbix
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password }}"
+ state: absent
+
+- assert:
+ that:
+ - not result.changed
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_folder/defaults/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_folder/defaults/main.yml
new file mode 100644
index 000000000..8b9c9348a
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_folder/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+
+grafana_url: "http://grafana:3000/"
+grafana_username: "admin"
+grafana_password: "admin"
+
+...
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_folder/tasks/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_folder/tasks/main.yml
new file mode 100644
index 000000000..c6a520560
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_folder/tasks/main.yml
@@ -0,0 +1,55 @@
+---
+
+- name: Create a Folder
+ grafana_folder:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ title: "grafana_working_group"
+ state: present
+ register: result
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.folder.title == 'grafana_working_group'"
+
+- name: Test folder creation idempotency
+ grafana_folder:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ title: "grafana_working_group"
+ state: present
+ register: result
+
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.folder.title == 'grafana_working_group'"
+
+- name: Delete a Folder
+ grafana_folder:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ title: "grafana_working_group"
+ state: absent
+ register: result
+
+- assert:
+ that:
+ - "result.changed == true"
+
+- name: Test folder deletion idempotency
+ grafana_folder:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ title: "grafana_working_group"
+ state: absent
+ register: result
+
+- assert:
+ that:
+ - "result.changed == false"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/defaults/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/defaults/main.yml
new file mode 100644
index 000000000..8b9c9348a
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+
+grafana_url: "http://grafana:3000/"
+grafana_username: "admin"
+grafana_password: "admin"
+
+...
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/dingding.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/dingding.yml
new file mode 100644
index 000000000..7279e313b
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/dingding.yml
@@ -0,0 +1,74 @@
+---
+- name: Create dingding notification channel
+ register: result
+ grafana_notification_channel:
+ uid: dingding
+ name: dingding
+ type: dingding
+ dingding_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed == True
+ - result.channel.name == "dingding"
+ - result.channel.uid == "dingding"
+ - result.channel.type == "dingding"
+
+- name: Create dingding notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: dingding
+ name: dingding
+ type: dingding
+ dingding_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed == False
+ - result.channel.name == "dingding"
+ - result.channel.uid == "dingding"
+ - result.channel.type == "dingding"
+
+- name: Delete dingding notification channel
+ register: result
+ grafana_notification_channel:
+ uid: dingding
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed == True
+
+- name: Delete dingding notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: dingding
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed == False
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/discord.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/discord.yml
new file mode 100644
index 000000000..29cfece70
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/discord.yml
@@ -0,0 +1,74 @@
+---
+- name: Create discord notification channel
+ register: result
+ grafana_notification_channel:
+ uid: discord
+ name: discord
+ type: discord
+ discord_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed == True
+ - result.channel.name == "discord"
+ - result.channel.type == "discord"
+ - result.channel.uid == "discord"
+
+- name: Create discord notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: discord
+ name: discord
+ type: discord
+ discord_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed == False
+ - result.channel.name == "discord"
+ - result.channel.type == "discord"
+ - result.channel.uid == "discord"
+
+- name: Delete discord notification channel
+ register: result
+ grafana_notification_channel:
+ uid: discord
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed == True
+
+- name: Delete discord notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: discord
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - result.changed == False
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/email.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/email.yml
new file mode 100644
index 000000000..85a236c9e
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/email.yml
@@ -0,0 +1,79 @@
+---
+- name: Create email notification channel
+ register: result
+ grafana_notification_channel:
+ uid: email
+ name: email
+ type: email
+ email_addresses:
+ - foo@example.org
+ - bar@example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "email"
+ - result.channel.type == "email"
+ - result.channel.uid == "email"
+
+- name: Create email notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: email
+ name: email
+ type: email
+ email_addresses:
+ - foo@example.org
+ - bar@example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "email"
+ - result.channel.type == "email"
+ - result.channel.uid == "email"
+
+- name: Delete discord notification channel
+ register: result
+ grafana_notification_channel:
+ uid: email
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - "result.state == 'absent'"
+
+- name: Delete discord notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: email
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/googlechat.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/googlechat.yml
new file mode 100644
index 000000000..abc7db644
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/googlechat.yml
@@ -0,0 +1,74 @@
+---
+- name: Create googlechat notification channel
+ register: result
+ grafana_notification_channel:
+ uid: googlechat
+ name: googlechat
+ type: googlechat
+ googlechat_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "googlechat"
+ - result.channel.uid == "googlechat"
+ - result.channel.type == "googlechat"
+
+- name: Create googlechat notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: googlechat
+ name: googlechat
+ type: googlechat
+ googlechat_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "googlechat"
+ - result.channel.uid == "googlechat"
+ - result.channel.type == "googlechat"
+
+- name: Delete googlechat notification channel
+ register: result
+ grafana_notification_channel:
+ uid: googlechat
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete googlechat notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: googlechat
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/hipchat.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/hipchat.yml
new file mode 100644
index 000000000..4a9ec1704
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/hipchat.yml
@@ -0,0 +1,74 @@
+---
+- name: Create hipchat notification channel
+ register: result
+ grafana_notification_channel:
+ uid: hipchat
+ name: hipchat
+ type: hipchat
+ hipchat_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "hipchat"
+ - result.channel.type == "hipchat"
+ - result.channel.uid == "hipchat"
+
+- name: Create hipchat notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: hipchat
+ name: hipchat
+ type: hipchat
+ hipchat_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "hipchat"
+ - result.channel.type == "hipchat"
+ - result.channel.uid == "hipchat"
+
+- name: Delete hipchat notification channel
+ register: result
+ grafana_notification_channel:
+ uid: hipchat
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete hipchat notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: hipchat
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/kafka.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/kafka.yml
new file mode 100644
index 000000000..ffc208acb
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/kafka.yml
@@ -0,0 +1,76 @@
+---
+- name: Create kafka notification channel
+ register: result
+ grafana_notification_channel:
+ uid: kafka
+ name: kafka
+ type: kafka
+ kafka_url: https://example.org
+ kafka_topic: test
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "kafka"
+ - result.channel.uid == "kafka"
+ - result.channel.type == "kafka"
+
+- name: Create kafka notification channel (idempotentcy)
+ register: result
+ grafana_notification_channel:
+ uid: kafka
+ name: kafka
+ type: kafka
+ kafka_url: https://example.org
+ kafka_topic: test
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "kafka"
+ - result.channel.uid == "kafka"
+ - result.channel.type == "kafka"
+
+- name: Delete kafka notification channel
+ register: result
+ grafana_notification_channel:
+ uid: kafka
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete kafka notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: kafka
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/line.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/line.yml
new file mode 100644
index 000000000..83a1863ba
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/line.yml
@@ -0,0 +1,74 @@
+---
+- name: Create line notification channel
+ register: result
+ grafana_notification_channel:
+ uid: line
+ name: line
+ type: line
+ line_token: xxx
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.uid == "line"
+ - result.channel.name == "line"
+ - result.channel.type == "line"
+
+- name: Create line notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: line
+ name: line
+ type: line
+ line_token: xxx
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.uid == "line"
+ - result.channel.name == "line"
+ - result.channel.type == "line"
+
+- name: Delete line notification channel
+ register: result
+ grafana_notification_channel:
+ uid: line
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete line notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: line
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/main.yml
new file mode 100644
index 000000000..ada6338c7
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/main.yml
@@ -0,0 +1,20 @@
+---
+- block:
+ - include: dingding.yml
+ - include: discord.yml
+ - include: email.yml
+ - include: googlechat.yml
+ - include: hipchat.yml
+ - include: kafka.yml
+# - include: line.yml
+ - include: teams.yml
+ - include: opsgenie.yml
+ - include: pagerduty.yml
+ - include: prometheus.yml
+ - include: pushover.yml
+ - include: sensu.yml
+ - include: slack-and-beyond.yml
+ - include: telegram.yml
+# - include: threema.yml
+ - include: victorops.yml
+ - include: webhook.yml
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/opsgenie.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/opsgenie.yml
new file mode 100644
index 000000000..f871fe719
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/opsgenie.yml
@@ -0,0 +1,77 @@
+---
+- name: Create opsgenie notification channel
+ register: result
+ grafana_notification_channel:
+ uid: opsgenie
+ name: opsgenie
+ type: opsgenie
+ opsgenie_url: https://example.org
+ opsgenie_api_key: xxx
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "opsgenie"
+ - result.channel.type == "opsgenie"
+ - result.channel.uid == "opsgenie"
+
+- name: Create opsgenie notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: opsgenie
+ name: opsgenie
+ type: opsgenie
+ opsgenie_url: https://example.org
+ opsgenie_api_key: xxx
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "opsgenie"
+ - result.channel.type == "opsgenie"
+ - result.channel.uid == "opsgenie"
+
+- name: Delete opsgenie notification channel
+ register: result
+ grafana_notification_channel:
+ uid: opsgenie
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - "result.state == 'absent'"
+
+- name: Delete opsgenie notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: opsgenie
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/pagerduty.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/pagerduty.yml
new file mode 100644
index 000000000..a8fa940b0
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/pagerduty.yml
@@ -0,0 +1,74 @@
+---
+- name: Create pagerduty notification channel
+ register: result
+ grafana_notification_channel:
+ uid: pagerduty
+ name: pagerduty
+ type: pagerduty
+ pagerduty_integration_key: xxx
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "pagerduty"
+ - result.channel.type == "pagerduty"
+ - result.channel.uid == "pagerduty"
+
+- name: Create pagerduty notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: pagerduty
+ name: pagerduty
+ type: pagerduty
+ pagerduty_integration_key: xxx
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "pagerduty"
+ - result.channel.type == "pagerduty"
+ - result.channel.uid == "pagerduty"
+
+- name: Delete pagerduty notification channel
+ register: result
+ grafana_notification_channel:
+ uid: pagerduty
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete pagerduty notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: pagerduty
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/prometheus.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/prometheus.yml
new file mode 100644
index 000000000..40810eaf3
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/prometheus.yml
@@ -0,0 +1,74 @@
+---
+- name: Create prometheus notification channel
+ register: result
+ grafana_notification_channel:
+ uid: prometheus
+ name: prometheus
+ type: prometheus
+ prometheus_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "prometheus"
+ - result.channel.uid == "prometheus"
+ - result.channel.type == "prometheus-alertmanager"
+
+- name: Create prometheus notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: prometheus
+ name: prometheus
+ type: prometheus
+ prometheus_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "prometheus"
+ - result.channel.uid == "prometheus"
+ - result.channel.type == "prometheus-alertmanager"
+
+- name: Delete prometheus notification channel
+ register: result
+ grafana_notification_channel:
+ uid: prometheus
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete prometheus notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: prometheus
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/pushover.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/pushover.yml
new file mode 100644
index 000000000..894bd71e6
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/pushover.yml
@@ -0,0 +1,76 @@
+---
+- name: Create pushover notification channel
+ register: result
+ grafana_notification_channel:
+ uid: pushover
+ name: pushover
+ type: pushover
+ pushover_api_token: xxx
+ pushover_user_key: yyy
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "pushover"
+ - result.channel.uid == "pushover"
+ - result.channel.type == "pushover"
+
+- name: Create pushover notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: pushover
+ name: pushover
+ type: pushover
+ pushover_api_token: xxx
+ pushover_user_key: yyy
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "pushover"
+ - result.channel.uid == "pushover"
+ - result.channel.type == "pushover"
+
+- name: Delete pushover notification channel
+ register: result
+ grafana_notification_channel:
+ uid: pushover
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete pushover notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: pushover
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/sensu.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/sensu.yml
new file mode 100644
index 000000000..01619b719
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/sensu.yml
@@ -0,0 +1,74 @@
+---
+- name: Create sensu notification channel
+ register: result
+ grafana_notification_channel:
+ uid: sensu
+ name: sensu
+ type: sensu
+ sensu_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "sensu"
+ - result.channel.type == "sensu"
+ - result.channel.uid == "sensu"
+
+- name: Create sensu notification channel
+ register: result
+ grafana_notification_channel:
+ uid: sensu
+ name: sensu
+ type: sensu
+ sensu_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "sensu"
+ - result.channel.type == "sensu"
+ - result.channel.uid == "sensu"
+
+- name: Delete sensu notification channel
+ register: result
+ grafana_notification_channel:
+ uid: sensu
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete sensu notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: sensu
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/slack-and-beyond.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/slack-and-beyond.yml
new file mode 100644
index 000000000..0748c8bdb
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/slack-and-beyond.yml
@@ -0,0 +1,110 @@
+---
+- name: Create slack notification channel
+ register: result
+ grafana_notification_channel:
+ uid: slack
+ name: slack
+ type: slack
+ slack_url: https://hooks.slack.com/services/xxx/yyy/zzz
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "slack"
+ - result.channel.type == "slack"
+ - result.channel.uid == "slack"
+
+- name: Create slack notification channel
+ register: result
+ grafana_notification_channel:
+ uid: slack
+ name: slack
+ type: slack
+ slack_url: https://hooks.slack.com/services/xxx/yyy/zzz
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "slack"
+ - result.channel.type == "slack"
+ - result.channel.uid == "slack"
+
+- name: Check slack notification channel idempotency
+ register: result
+ grafana_notification_channel:
+ uid: slack
+ name: slack
+ type: slack
+ slack_url: https://hooks.slack.com/services/xxx/yyy/zzz
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+
+- name: Update slack notification channel
+ register: result
+ grafana_notification_channel:
+ uid: slack
+ name: slack
+ type: slack
+ slack_url: https://hooks.slack.com/services/xxx/yyy/fff
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete slack notification channel
+ register: result
+ grafana_notification_channel:
+ state: absent
+ uid: slack
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete slack notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ state: absent
+ uid: slack
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/teams.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/teams.yml
new file mode 100644
index 000000000..cfc44aef3
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/teams.yml
@@ -0,0 +1,74 @@
+---
+- name: Create teams notification channel
+ register: result
+ grafana_notification_channel:
+ uid: teams
+ name: teams
+ type: teams
+ teams_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "teams"
+ - result.channel.uid == "teams"
+ - result.channel.type == "teams"
+
+- name: Create teams notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: teams
+ name: teams
+ type: teams
+ teams_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "teams"
+ - result.channel.uid == "teams"
+ - result.channel.type == "teams"
+
+- name: Delete teams notification channel
+ register: result
+ grafana_notification_channel:
+ uid: teams
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete teams notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: teams
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/telegram.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/telegram.yml
new file mode 100644
index 000000000..98a7a3c6d
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/telegram.yml
@@ -0,0 +1,76 @@
+---
+- name: Create telegram notification channel
+ register: result
+ grafana_notification_channel:
+ uid: telegram
+ name: telegram
+ type: telegram
+ telegram_bot_token: xxx
+ telegram_chat_id: yyy
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "telegram"
+ - result.channel.type == "telegram"
+ - result.channel.uid == "telegram"
+
+- name: Create telegram notification channel
+ register: result
+ grafana_notification_channel:
+ uid: telegram
+ name: telegram
+ type: telegram
+ telegram_bot_token: xxx
+ telegram_chat_id: yyy
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "telegram"
+ - result.channel.type == "telegram"
+ - result.channel.uid == "telegram"
+
+- name: Delete telegram notification channel
+ register: result
+ grafana_notification_channel:
+ uid: telegram
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete telegram notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: telegram
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/threema.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/threema.yml
new file mode 100644
index 000000000..7858b6977
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/threema.yml
@@ -0,0 +1,78 @@
+---
+- name: Create threema notification channel
+ register: result
+ grafana_notification_channel:
+ uid: threema
+ name: threema
+ type: threema
+ threema_gateway_id: "*xxxxxxx"
+ threema_recipient_id: yyyyyyyy
+ threema_api_secret: zzz
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "threema"
+ - result.channel.type == "threema"
+ - result.channel.uid == "threema"
+
+- name: Create threema notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: threema
+ name: threema
+ type: threema
+ threema_gateway_id: xxx
+ threema_recepient_id: yyy
+ threema_api_secret: zzz
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "threema"
+ - result.channel.type == "threema"
+ - result.channel.uid == "threema"
+
+- name: Delete threema notification channel
+ register: result
+ grafana_notification_channel:
+ uid: threema
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete threema notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: threema
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/victorops.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/victorops.yml
new file mode 100644
index 000000000..3779e813a
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/victorops.yml
@@ -0,0 +1,74 @@
+---
+- name: Create victorops notification channel
+ register: result
+ grafana_notification_channel:
+ uid: victorops
+ name: victorops
+ type: victorops
+ victorops_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "victorops"
+ - result.channel.type == "victorops"
+ - result.channel.uid == "victorops"
+
+- name: Create victorops notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: victorops
+ name: victorops
+ type: victorops
+ victorops_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "victorops"
+ - result.channel.type == "victorops"
+ - result.channel.uid == "victorops"
+
+- name: Delete victorops notification channel
+ register: result
+ grafana_notification_channel:
+ uid: victorops
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete victorops notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: victorops
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/webhook.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/webhook.yml
new file mode 100644
index 000000000..c9efd9193
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_notification_channel/tasks/webhook.yml
@@ -0,0 +1,74 @@
+---
+- name: Create webhook notification channel
+ register: result
+ grafana_notification_channel:
+ uid: webhook
+ name: webhook
+ type: webhook
+ webhook_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+ - result.channel.name == "webhook"
+ - result.channel.uid == "webhook"
+ - result.channel.type == "webhook"
+
+- name: Create webhook notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: webhook
+ name: webhook
+ type: webhook
+ webhook_url: https://example.org
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
+ - result.channel.name == "webhook"
+ - result.channel.uid == "webhook"
+ - result.channel.type == "webhook"
+
+- name: Delete webhook notification channel
+ register: result
+ grafana_notification_channel:
+ uid: webhook
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == True"
+
+- name: Delete webhook notification channel (idempotency)
+ register: result
+ grafana_notification_channel:
+ uid: webhook
+ state: absent
+ grafana_url: "{{ grafana_url }}"
+ grafana_user: "{{ grafana_username }}"
+ grafana_password: "{{ grafana_password}}"
+
+- debug:
+ var: result
+
+- assert:
+ that:
+ - "result.changed == False"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_organization/defaults/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_organization/defaults/main.yml
new file mode 100644
index 000000000..7bb77ea3f
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_organization/defaults/main.yml
@@ -0,0 +1,4 @@
+---
+grafana_url: "http://grafana:3000/"
+grafana_username: "admin"
+grafana_password: "admin"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_organization/tasks/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_organization/tasks/main.yml
new file mode 100644
index 000000000..f8ccdf3bf
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_organization/tasks/main.yml
@@ -0,0 +1,57 @@
+---
+
+- name: Create a Grafana organization
+ community.grafana.grafana_organization:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: orgtest
+ state: present
+ register: result
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.failed == false"
+ - "result.org.name == 'orgtest'"
+
+- name: check idempotency Grafana organization
+ community.grafana.grafana_organization:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: orgtest
+ state: present
+ register: result
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.failed == false"
+ - "result.org.name == 'orgtest'"
+
+- name: Delete a Grafana organization
+ community.grafana.grafana_organization:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: orgtest
+ state: absent
+ register: result
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.failed == false"
+ - "result.msg |length > 0"
+
+- name: check idempotency delete a Grafana organization
+ community.grafana.grafana_organization:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: orgtest
+ state: absent
+ register: result
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.failed == false"
+ - "result.msg == 'No org found, nothing to do'"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_team/defaults/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_team/defaults/main.yml
new file mode 100644
index 000000000..8b9c9348a
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_team/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+
+grafana_url: "http://grafana:3000/"
+grafana_username: "admin"
+grafana_password: "admin"
+
+...
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_team/tasks/create_user.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_team/tasks/create_user.yml
new file mode 100644
index 000000000..6971d07b6
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_team/tasks/create_user.yml
@@ -0,0 +1,29 @@
+- name: Create John Doe for tests purpose through uri module
+ uri:
+ url: "{{ grafana_url }}api/admin/users"
+ method: POST
+ user: "{{ grafana_username }}"
+ password: "{{ grafana_password }}"
+ force_basic_auth: yes
+ body:
+ name: "John"
+ email: "john+doe@example.com"
+ login: "john"
+ password: "userpassword"
+ body_format: json
+ status_code: 200
+
+- name: Create Jane Doe for tests purpose through uri module
+ uri:
+ url: "{{ grafana_url }}api/admin/users"
+ method: POST
+ user: "{{ grafana_username }}"
+ password: "{{ grafana_password }}"
+ force_basic_auth: yes
+ body:
+ name: "Jane"
+ email: "jane.doe@example.com"
+ login: "jane"
+ password: "userpassword"
+ body_format: json
+ status_code: 200
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_team/tasks/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_team/tasks/main.yml
new file mode 100644
index 000000000..2d74581b7
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_team/tasks/main.yml
@@ -0,0 +1,187 @@
+---
+
+- name: Create a Team
+ grafana_team:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "grafana_working_group"
+ email: "foo.bar@example.com"
+ state: present
+ register: result
+
+- set_fact:
+ # From Grafana 9.0.0, the API user automatically becomes a member of the team
+ auto_member: "{{ result.team.memberCount == 1 }}"
+
+- set_fact:
+ expected_members: "{{ auto_member | ternary(['********@localhost'], []) }}"
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.team.name == 'grafana_working_group'"
+ - "result.team.email == 'foo.bar@example.com'"
+ - "result.team.memberCount == (expected_members|length)"
+ - "result.team.members == expected_members"
+
+- name: Check idempotency on team creation
+ grafana_team:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "grafana_working_group"
+ email: "foo.bar@example.com"
+ state: present
+ register: result
+
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.team.name == 'grafana_working_group'"
+ - "result.team.email == 'foo.bar@example.com'"
+ - "result.team.memberCount == (expected_members|length)"
+ - "result.team.members == expected_members"
+
+- name: Check a team can be deleted
+ grafana_team:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "grafana_working_group"
+ email: "foo.bar@example.com"
+ state: absent
+ register: result
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.message == 'Team deleted'"
+
+- name: Check idempotency on team deletion
+ grafana_team:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "grafana_working_group"
+ email: "foo.bar@example.com"
+ state: absent
+ register: result
+
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.message == 'No team found'"
+
+- name: Create users for tests purpose
+ import_tasks: create_user.yml
+
+- name: Create a Team with members
+ grafana_team:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "grafana_working_group"
+ email: "foo.bar@example.com"
+ members:
+ - "john+doe@example.com"
+ - "jane.doe@example.com"
+ state: present
+ register: result
+
+- set_fact:
+ expected_members: "{{ auto_member | ternary(['********@localhost', 'jane.doe@example.com', 'john+doe@example.com'], ['jane.doe@example.com', 'john+doe@example.com']) }}"
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.team.name == 'grafana_working_group'"
+ - "result.team.email == 'foo.bar@example.com'"
+ - "result.team.memberCount == (expected_members|length)"
+ - "result.team.members == expected_members"
+
+- name: Ensure a Team exists with member not enforced
+ grafana_team:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "grafana_working_group"
+ email: "foo.bar@example.com"
+ members:
+ - "john+doe@example.com"
+ state: present
+ register: result
+
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.team.name == 'grafana_working_group'"
+ - "result.team.email == 'foo.bar@example.com'"
+ - "result.team.memberCount == (expected_members|length)"
+ - "result.team.members == expected_members"
+
+- set_fact:
+ enforced_members: "{{ auto_member | ternary(['admin@localhost', 'john+doe@example.com'], ['john+doe@example.com']) }}"
+ expected_members: "{{ auto_member | ternary(['********@localhost', 'john+doe@example.com'], ['john+doe@example.com']) }}"
+
+- name: Ensure a Team exists with member enforced
+ grafana_team:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "grafana_working_group"
+ email: "foo.bar@example.com"
+ members: "{{ enforced_members }}"
+ enforce_members: true
+ state: present
+ register: result
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.team.name == 'grafana_working_group'"
+ - "result.team.email == 'foo.bar@example.com'"
+ - "result.team.memberCount == (expected_members|length)"
+ - "result.team.members == expected_members"
+
+- name: Ensure a Team exists with members omitted
+ grafana_team:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "grafana_working_group"
+ email: "foo.bar@example.com"
+ state: present
+ register: result
+
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.team.name == 'grafana_working_group'"
+ - "result.team.email == 'foo.bar@example.com'"
+ - "result.team.memberCount == (expected_members|length)"
+ - "result.team.members == expected_members"
+
+- name: Add new member to existing Team
+ grafana_team:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "grafana_working_group"
+ email: "foo.bar@example.com"
+ members:
+ - "john+doe@example.com"
+ - "jane.doe@example.com"
+ state: present
+ register: result
+
+- set_fact:
+ expected_members: "{{ auto_member | ternary(['********@localhost', 'jane.doe@example.com', 'john+doe@example.com'], ['jane.doe@example.com', 'john+doe@example.com']) }}"
+
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.team.name == 'grafana_working_group'"
+ - "result.team.email == 'foo.bar@example.com'"
+ - "result.team.memberCount == (expected_members|length)"
+ - "result.team.members == expected_members"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_user/defaults/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_user/defaults/main.yml
new file mode 100644
index 000000000..7bb77ea3f
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_user/defaults/main.yml
@@ -0,0 +1,4 @@
+---
+grafana_url: "http://grafana:3000/"
+grafana_username: "admin"
+grafana_password: "admin"
diff --git a/ansible_collections/community/grafana/tests/integration/targets/grafana_user/tasks/main.yml b/ansible_collections/community/grafana/tests/integration/targets/grafana_user/tasks/main.yml
new file mode 100644
index 000000000..c62801653
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/integration/targets/grafana_user/tasks/main.yml
@@ -0,0 +1,237 @@
+---
+- name: Create new admin
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "Harley Quinn"
+ email: harley.quinn@gotham.city
+ login: harley
+ password: Wy3ta6ob6M3wHELv58MPfqOe126RTnWpcYfEhyJm
+ is_admin: true
+ state: present
+ register: result
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.failed == false"
+ - "result.user.name == 'Harley Quinn'"
+ - "result.user.email == 'harley.quinn@gotham.city'"
+ - "result.user.isGrafanaAdmin == true"
+
+- name: Check idempotency on admin creation
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "Harley Quinn"
+ email: harley.quinn@gotham.city
+ login: harley
+ password: Wy3ta6ob6M3wHELv58MPfqOe126RTnWpcYfEhyJm
+ is_admin: true
+ state: present
+ register: result
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.user.name == 'Harley Quinn'"
+ - "result.user.email == 'harley.quinn@gotham.city'"
+ - "result.user.isGrafanaAdmin == true"
+
+- name: Check user creation with Grafana API
+ uri:
+ url: "{{ grafana_url }}api/users/lookup?loginOrEmail=harley"
+ user: "{{ grafana_username }}"
+ password: "{{ grafana_password }}"
+ force_basic_auth: yes
+ status_code: 200
+ headers:
+ Accept: application/json
+ Content-Type: application/json
+ register: result
+- assert:
+ that:
+ - "result.json.name == 'Harley Quinn'"
+ - "result.json.email == 'harley.quinn@gotham.city'"
+ - "result.json.isGrafanaAdmin == true"
+
+- name: Create a Grafana user without password (expect failure)
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "Bruce Wayne"
+ email: batman@gotham.city
+ login: batman
+ state: present
+ register: result
+ ignore_errors: yes
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.failed == true"
+ - "result.msg == 'missing required arguments: password'"
+
+- name: Create a Grafana user
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "Bruce Wayne"
+ email: batman@gotham.city
+ login: batman
+ password: robin
+ state: present
+ register: result
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.user.name == 'Bruce Wayne'"
+ - "result.user.email == 'batman@gotham.city'"
+ - "result.user.isGrafanaAdmin == false"
+
+- name: Check idempotency on user creation (password not requiered)
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "Bruce Wayne"
+ email: batman@gotham.city
+ login: batman
+ state: present
+ register: result
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.user.name == 'Bruce Wayne'"
+ - "result.user.email == 'batman@gotham.city'"
+ - "result.user.isGrafanaAdmin == false"
+
+- name: Check user creation with Grafana API
+ uri:
+ url: "{{ grafana_url }}api/users/lookup?loginOrEmail=batman"
+ user: "{{ grafana_username }}"
+ password: "{{ grafana_password }}"
+ force_basic_auth: yes
+ status_code: 200
+ headers:
+ Accept: application/json
+ Content-Type: application/json
+ register: result
+- assert:
+ that:
+ - "result.json.name == 'Bruce Wayne'"
+ - "result.json.email == 'batman@gotham.city'"
+ - "result.json.isGrafanaAdmin == false"
+
+- name: Update Grafana user
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "The Dark Knight"
+ email: thedarkknight@gotham.city
+ login: batman
+ password: robin
+ is_admin: true
+ state: present
+ register: result
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.user.name == 'The Dark Knight'"
+ - "result.user.email == 'thedarkknight@gotham.city'"
+ - "result.user.isGrafanaAdmin == true"
+
+- name: Check user update with Grafana API
+ uri:
+ url: "{{ grafana_url }}api/users/lookup?loginOrEmail=batman"
+ user: "{{ grafana_username }}"
+ password: "{{ grafana_password }}"
+ force_basic_auth: yes
+ status_code: 200
+ headers:
+ Accept: application/json
+ Content-Type: application/json
+ register: result
+- assert:
+ that:
+ - "result.json.name == 'The Dark Knight'"
+ - "result.json.email == 'thedarkknight@gotham.city'"
+ - "result.json.isGrafanaAdmin == true"
+
+- name: Delete a Grafana user
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ login: batman
+ state: absent
+ register: result
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.message == 'User deleted'"
+
+- name: Check idempotency on user deletion
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ login: batman
+ state: absent
+ register: result
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.message == 'No user found, nothing to do'"
+
+- name: Check user deletion with Grafana API (expect 404 Not Found)
+ uri:
+ url: "{{ grafana_url }}api/users/lookup?loginOrEmail=batman"
+ user: "{{ grafana_username }}"
+ password: "{{ grafana_password }}"
+ force_basic_auth: yes
+ status_code: 404
+ headers:
+ Accept: application/json
+ Content-Type: application/json
+ register: result
+- assert:
+ that:
+ - "result.json.message | lower == 'user not found'"
+
+- name: Create a Grafana user with character encoding
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "Bruce Wayne"
+ email: bruce+wayne@gotham.city
+ login: bruce+wayne@gotham.city
+ password: robin
+ state: present
+ register: result
+- assert:
+ that:
+ - "result.changed == true"
+ - "result.user.name == 'Bruce Wayne'"
+ - "result.user.email == 'bruce+wayne@gotham.city'"
+ - "result.user.isGrafanaAdmin == false"
+
+- name: Check idempotency on user creation (password not requiered)
+ grafana_user:
+ url: "{{ grafana_url }}"
+ url_username: "{{ grafana_username }}"
+ url_password: "{{ grafana_password }}"
+ name: "Bruce Wayne"
+ email: bruce+wayne@gotham.city
+ login: bruce+wayne@gotham.city
+ state: present
+ register: result
+- assert:
+ that:
+ - "result.changed == false"
+ - "result.user.name == 'Bruce Wayne'"
+ - "result.user.email == 'bruce+wayne@gotham.city'"
+ - "result.user.isGrafanaAdmin == false"
diff --git a/ansible_collections/community/grafana/tests/sanity/ignore-2.10.txt b/ansible_collections/community/grafana/tests/sanity/ignore-2.10.txt
new file mode 100644
index 000000000..5c82494f9
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/sanity/ignore-2.10.txt
@@ -0,0 +1,4 @@
+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/ansible_collections/community/grafana/tests/sanity/ignore-2.11.txt b/ansible_collections/community/grafana/tests/sanity/ignore-2.11.txt
new file mode 100644
index 000000000..68cb96ab4
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/sanity/ignore-2.11.txt
@@ -0,0 +1,6 @@
+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/ansible_collections/community/grafana/tests/sanity/ignore-2.12.txt b/ansible_collections/community/grafana/tests/sanity/ignore-2.12.txt
new file mode 100644
index 000000000..5c82494f9
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/sanity/ignore-2.12.txt
@@ -0,0 +1,4 @@
+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/ansible_collections/community/grafana/tests/sanity/ignore-2.13.txt b/ansible_collections/community/grafana/tests/sanity/ignore-2.13.txt
new file mode 100644
index 000000000..5c82494f9
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/sanity/ignore-2.13.txt
@@ -0,0 +1,4 @@
+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/ansible_collections/community/grafana/tests/sanity/ignore-2.14.txt b/ansible_collections/community/grafana/tests/sanity/ignore-2.14.txt
new file mode 100644
index 000000000..5c82494f9
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/sanity/ignore-2.14.txt
@@ -0,0 +1,4 @@
+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/ansible_collections/community/grafana/tests/sanity/ignore-2.15.txt b/ansible_collections/community/grafana/tests/sanity/ignore-2.15.txt
new file mode 100644
index 000000000..5c82494f9
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/sanity/ignore-2.15.txt
@@ -0,0 +1,4 @@
+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/ansible_collections/community/grafana/tests/sanity/ignore-2.9.txt b/ansible_collections/community/grafana/tests/sanity/ignore-2.9.txt
new file mode 100644
index 000000000..476a7a42e
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/sanity/ignore-2.9.txt
@@ -0,0 +1,3 @@
+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/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_datasource/test_grafana_datasource.py b/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_datasource/test_grafana_datasource.py
new file mode 100644
index 000000000..d2fba0fe1
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_datasource/test_grafana_datasource.py
@@ -0,0 +1,212 @@
+from __future__ import (absolute_import, division, print_function)
+
+from unittest import TestCase
+from unittest.mock import call, patch, MagicMock
+from ansible_collections.community.grafana.plugins.modules import grafana_datasource
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils import basic
+from ansible.module_utils.urls import basic_auth_header
+import json
+
+__metaclass__ = type
+
+
+def set_module_args(args):
+ """prepare arguments so that they will be picked up during module creation"""
+ args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
+ basic._ANSIBLE_ARGS = to_bytes(args)
+
+
+def exit_json(*args, **kwargs):
+ """function to patch over exit_json; package return data into an exception"""
+ if 'changed' not in kwargs:
+ kwargs['changed'] = False
+ raise AnsibleExitJson(kwargs)
+
+
+def fail_json(*args, **kwargs):
+ """function to patch over fail_json; package return data into an exception"""
+ kwargs['failed'] = True
+ raise AnsibleFailJson(kwargs)
+
+
+class AnsibleExitJson(Exception):
+ """Exception class to be raised by module.exit_json and caught by the test case"""
+ pass
+
+
+class AnsibleFailJson(Exception):
+ """Exception class to be raised by module.fail_json and caught by the test case"""
+ pass
+
+
+class GrafanaDatasource(TestCase):
+
+ def setUp(self):
+ self.authorization = basic_auth_header("admin", "admin")
+ self.mock_module_helper = patch.multiple(basic.AnsibleModule,
+ exit_json=exit_json,
+ fail_json=fail_json)
+ self.mock_module_helper.start()
+ self.addCleanup(self.mock_module_helper.stop)
+
+ def test_payload_prometheus(self):
+ expected_payload = {
+ 'access': 'proxy',
+ 'basicAuth': False,
+ 'database': '',
+ 'isDefault': False,
+ 'jsonData': {
+ 'tlsAuth': False,
+ 'tlsAuthWithCACert': False,
+ 'tlsSkipVerify': True
+ },
+ 'name': 'openshift_prometheus',
+ 'uid': 'xyz123',
+ 'orgId': 1,
+ 'secureJsonData': {},
+ 'type': 'prometheus',
+ 'url': 'https://openshift-monitoring.company.com',
+ 'user': '',
+ 'withCredentials': False
+ }
+ set_module_args({
+ 'url': 'https://grafana.example.com',
+ 'url_username': 'admin',
+ 'url_password': 'admin',
+ 'name': 'openshift_prometheus',
+ 'uid': 'xyz123',
+ 'ds_type': 'prometheus',
+ 'ds_url': 'https://openshift-monitoring.company.com',
+ 'access': 'proxy',
+ 'tls_skip_verify': 'true',
+ })
+ module = grafana_datasource.setup_module_object()
+ payload = grafana_datasource.get_datasource_payload(module.params)
+ self.assertEqual(payload, expected_payload)
+
+ def test_payload_prometheus_with_basic_auth(self):
+ expected_payload = {
+ 'access': 'proxy',
+ 'basicAuth': True,
+ 'basicAuthUser': 'admin',
+ 'database': '',
+ 'isDefault': False,
+ 'jsonData': {
+ 'tlsAuth': False,
+ 'tlsAuthWithCACert': False,
+ 'tlsSkipVerify': True
+ },
+ 'name': 'openshift_prometheus',
+ 'uid': 'xyz123',
+ 'orgId': 1,
+ 'secureJsonData': {'basicAuthPassword': 'admin'},
+ 'type': 'prometheus',
+ 'url': 'https://openshift-monitoring.company.com',
+ 'user': '',
+ 'withCredentials': False
+ }
+ set_module_args({
+ 'url': 'https://grafana.example.com',
+ 'url_username': 'admin',
+ 'url_password': 'admin',
+ 'name': 'openshift_prometheus',
+ 'uid': 'xyz123',
+ 'ds_type': 'prometheus',
+ 'ds_url': 'https://openshift-monitoring.company.com',
+ 'access': 'proxy',
+ 'basic_auth_user': 'admin',
+ 'basic_auth_password': 'admin',
+ 'tls_skip_verify': 'true',
+ })
+ module = grafana_datasource.setup_module_object()
+ payload = grafana_datasource.get_datasource_payload(module.params)
+ self.assertEqual(payload, expected_payload)
+
+ def test_payload_influxdb(self):
+ expected_payload = {
+ 'access': 'proxy',
+ 'basicAuth': False,
+ 'database': 'telegraf',
+ 'isDefault': False,
+ 'jsonData': {
+ 'timeInterval': '>10s',
+ 'tlsAuth': False,
+ 'tlsAuthWithCACert': True
+ },
+ 'name': 'datasource-influxdb',
+ 'uid': 'xyz123',
+ 'orgId': 1,
+ 'secureJsonData': {
+ 'tlsCACert': '/etc/ssl/certs/ca.pem'
+ },
+ 'type': 'influxdb',
+ 'url': 'https://influx.company.com:8086',
+ 'user': '',
+ 'withCredentials': False
+ }
+ set_module_args({
+ 'url': 'https://grafana.example.com',
+ 'url_username': 'admin',
+ 'url_password': 'admin',
+ 'name': 'datasource-influxdb',
+ 'uid': 'xyz123',
+ 'ds_type': 'influxdb',
+ 'ds_url': 'https://influx.company.com:8086',
+ 'database': 'telegraf',
+ 'time_interval': '>10s',
+ 'tls_ca_cert': '/etc/ssl/certs/ca.pem'
+ })
+ module = grafana_datasource.setup_module_object()
+ payload = grafana_datasource.get_datasource_payload(module.params)
+ self.assertEqual(payload, expected_payload)
+
+ def test_payload_elastic(self):
+ expected_payload = {
+ 'access': 'proxy',
+ 'basicAuth': True,
+ 'basicAuthUser': 'grafana',
+ 'database': '[logstash_]YYYY.MM.DD',
+ 'isDefault': False,
+ 'jsonData': {
+ 'esVersion': 56,
+ 'interval': 'Daily',
+ 'maxConcurrentShardRequests': 42,
+ 'timeField': '@timestamp',
+ 'timeInterval': '1m',
+ 'tlsAuth': False,
+ 'tlsAuthWithCACert': True
+ },
+ 'name': 'datasource-elastic',
+ 'uid': 'xyz123',
+ 'orgId': 1,
+ 'secureJsonData': {
+ 'basicAuthPassword': 'grafana',
+ 'tlsCACert': '/etc/ssl/certs/ca.pem'
+ },
+ 'type': 'elasticsearch',
+ 'url': 'https://elastic.company.com:9200',
+ 'user': '',
+ 'withCredentials': False
+ }
+ set_module_args({
+ 'url': 'https://grafana.example.com',
+ 'url_username': 'admin',
+ 'url_password': 'admin',
+ 'name': 'datasource-elastic',
+ 'uid': 'xyz123',
+ 'ds_type': 'elasticsearch',
+ 'ds_url': 'https://elastic.company.com:9200',
+ 'database': '[logstash_]YYYY.MM.DD',
+ 'basic_auth_user': 'grafana',
+ 'basic_auth_password': 'grafana',
+ 'time_field': '@timestamp',
+ 'time_interval': '1m',
+ 'interval': 'Daily',
+ 'es_version': 56,
+ 'max_concurrent_shard_requests': 42,
+ 'tls_ca_cert': '/etc/ssl/certs/ca.pem'
+ })
+ module = grafana_datasource.setup_module_object()
+ payload = grafana_datasource.get_datasource_payload(module.params)
+ self.assertEqual(payload, expected_payload)
diff --git a/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py b/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py
new file mode 100644
index 000000000..b3b025c4e
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_plugin/test_grafana_plugin.py
@@ -0,0 +1,111 @@
+from __future__ import (absolute_import, division, print_function)
+
+from unittest import TestCase
+from unittest.mock import patch, MagicMock
+from ansible_collections.community.grafana.plugins.modules import grafana_plugin
+
+__metaclass__ = type
+
+
+def run_command_ls():
+ STDERR = ""
+ STDOUT = """
+installed plugins:
+alexanderzobnin-zabbix-app @ 3.10.5
+
+Restart grafana after installing plugins . <service grafana-server restart>
+"""
+ return 0, STDOUT, STDERR
+
+
+def run_command_install_zip():
+ STDERR = ""
+ STDOUT = """
+installing alexanderzobnin-grafana-zabbix @
+from: /home/grafana//alexanderzobnin-grafana-zabbix-v3.10.5-1-g2219691.zip
+into: /var/lib/grafana/plugins
+
+... Installed alexanderzobnin-grafana-zabbix successfully
+
+Restart grafana after installing plugins . <service grafana-server restart>
+
+"""
+ return 0, STDOUT, STDERR
+
+
+def run_command_uninstall():
+ STDERR = ""
+ STDOUT = """
+Removing plugin: alexanderzobnin-zabbix-app
+
+Restart grafana after installing plugins . <service grafana-server restart>
+"""
+ return 0, STDOUT, STDERR
+
+
+def run_command_uninstall_again():
+ STDERR = ""
+ STDOUT = """
+Removing plugin: alexanderzobnin-zabbix-app
+Error: ✗ plugin does not exist
+"""
+ return 1, STDOUT, STDERR
+
+
+class GrafanaPlugin(TestCase):
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_plugin.grafana_cli_bin')
+ def test_plugin_install_zip(self, mock_grafana_cli_bin):
+ mock_grafana_cli_bin.return_value = "grafana-cli plugins"
+
+ params = {
+ "name": "alexanderzobnin-zabbix-app"
+ }
+
+ module = MagicMock()
+ module.run_command.return_value = run_command_install_zip()
+
+ result = grafana_plugin.get_grafana_plugin_version(module, params)
+ self.assertEqual(result, None)
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_plugin.grafana_cli_bin')
+ def test_plugin_ls(self, mock_grafana_cli_bin):
+ mock_grafana_cli_bin.return_value = "grafana-cli plugins"
+
+ params = {
+ "name": "alexanderzobnin-zabbix-app"
+ }
+
+ module = MagicMock()
+ module.run_command.return_value = run_command_ls()
+
+ result = grafana_plugin.get_grafana_plugin_version(module, params)
+ self.assertEqual(result, "3.10.5")
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_plugin.grafana_cli_bin')
+ def test_plugin_uninstall(self, mock_grafana_cli_bin):
+ mock_grafana_cli_bin.return_value = "grafana-cli plugins"
+
+ params = {
+ "name": "alexanderzobnin-zabbix-app"
+ }
+
+ module = MagicMock()
+ module.run_command.return_value = run_command_uninstall()
+
+ result = grafana_plugin.get_grafana_plugin_version(module, params)
+ self.assertEqual(result, None)
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_plugin.grafana_cli_bin')
+ def test_plugin_uninstall_again(self, mock_grafana_cli_bin):
+ mock_grafana_cli_bin.return_value = "grafana-cli plugins"
+
+ params = {
+ "name": "alexanderzobnin-zabbix-app"
+ }
+
+ module = MagicMock()
+ module.run_command.return_value = run_command_uninstall_again()
+
+ result = grafana_plugin.get_grafana_plugin_version(module, params)
+ self.assertEqual(result, None)
diff --git a/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_team/test_grafana_team.py b/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_team/test_grafana_team.py
new file mode 100644
index 000000000..c59953afa
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_team/test_grafana_team.py
@@ -0,0 +1,447 @@
+from __future__ import (absolute_import, division, print_function)
+
+from unittest import TestCase
+from unittest.mock import patch, MagicMock
+from ansible_collections.community.grafana.plugins.modules import grafana_team
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils import basic
+from ansible.module_utils.urls import basic_auth_header
+import json
+
+__metaclass__ = type
+
+
+class MockedReponse(object):
+ def __init__(self, data):
+ self.data = data
+
+ def read(self):
+ return self.data
+
+
+def exit_json(*args, **kwargs):
+ """function to patch over exit_json; package return data into an exception"""
+ if 'changed' not in kwargs:
+ kwargs['changed'] = False
+ raise AnsibleExitJson(kwargs)
+
+
+def fail_json(*args, **kwargs):
+ """function to patch over fail_json; package return data into an exception"""
+ kwargs['failed'] = True
+ raise AnsibleFailJson(kwargs)
+
+
+class AnsibleExitJson(Exception):
+ """Exception class to be raised by module.exit_json and caught by the test case"""
+ pass
+
+
+class AnsibleFailJson(Exception):
+ """Exception class to be raised by module.fail_json and caught by the test case"""
+ pass
+
+
+def set_module_args(args):
+ """prepare arguments so that they will be picked up during module creation"""
+ args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
+ basic._ANSIBLE_ARGS = to_bytes(args)
+
+
+def unauthorized_resp():
+ return (None, {"status": 401})
+
+
+def permission_denied_resp():
+ return (None, {"status": 403})
+
+
+def get_version_resp():
+ return {"major": 6, "minor": 0, "rev": 0}
+
+
+def get_low_version_resp():
+ return {"major": 4, "minor": 6, "rev": 0}
+
+
+def team_exists_resp():
+ server_response = json.dumps({"totalCount": 1, "teams": [{"name": "MyTestTeam", "email": "email@test.com"}]}, sort_keys=True)
+ return (MockedReponse(server_response), {"status": 200})
+
+
+def team_not_found_resp():
+ server_response = json.dumps({"totalCount": 0, "teams": []})
+ return (MockedReponse(server_response), {"status": 200})
+
+
+def team_created_resp():
+ server_response = json.dumps({"message": "Team created", "teamId": 2})
+ return (MockedReponse(server_response), {"status": 200})
+
+
+def team_updated_resp():
+ server_response = json.dumps({"message": "Team updated"})
+ return (MockedReponse(server_response), {"status": 200})
+
+
+def team_deleted_resp():
+ server_response = json.dumps({"message": "Team deleted"})
+ return (MockedReponse(server_response), {"status": 200})
+
+
+def team_members_resp():
+ server_response = json.dumps([{
+ "orgId": 1,
+ "teamId": 2,
+ "userId": 3,
+ "email": "user1@email.com",
+ "login": "user1",
+ "avatarUrl": r"\/avatar\/1b3c32f6386b0185c40d359cdc733a79"
+ }, {
+ "orgId": 1,
+ "teamId": 2,
+ "userId": 2,
+ "email": "user2@email.com",
+ "login": "user2",
+ "avatarUrl": r"\/avatar\/cad3c68da76e45d10269e8ef02f8e73e"
+ }])
+ return (MockedReponse(server_response), {"status": 200})
+
+
+def team_members_no_members_resp():
+ server_response = json.dumps([])
+ return (MockedReponse(server_response), {"status": 200})
+
+
+def add_team_member_resp():
+ server_response = json.dumps({"message": "Member added to Team"})
+ return (MockedReponse(server_response), {"status": 200})
+
+
+def delete_team_member_resp():
+ server_response = json.dumps({"message": "Team Member removed"})
+ return (MockedReponse(server_response), {"status": 200})
+
+
+class GrafanaTeamsTest(TestCase):
+
+ def setUp(self):
+ self.authorization = basic_auth_header("admin", "admin")
+ self.mock_module_helper = patch.multiple(basic.AnsibleModule,
+ exit_json=exit_json,
+ fail_json=fail_json)
+
+ self.mock_module_helper.start()
+ self.addCleanup(self.mock_module_helper.stop)
+
+ def test_module_setup_fails_without_params(self):
+ set_module_args({})
+
+ with self.assertRaises(AnsibleFailJson) as result:
+ grafana_team.main()
+ err, arg_list = result.exception.args[0]['msg'].split(':')
+ missing_args = [item.strip() for item in arg_list.split(',')]
+ self.assertEqual(err, 'missing required arguments')
+ self.assertEqual(arg_list, ["name", "email", "url"])
+
+ def test_module_setup_fails_without_name(self):
+ set_module_args({
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+
+ with self.assertRaises(AnsibleFailJson) as result:
+ grafana_team.main()
+ self.assertEqual(result.exception.args[0]['msg'], 'missing required arguments: name')
+
+ def test_module_setup_fails_without_email(self):
+ set_module_args({
+ 'name': 'MyTestTeam',
+ 'url': 'http://grafana.example.com'
+ })
+
+ with self.assertRaises(AnsibleFailJson) as result:
+ grafana_team.main()
+ self.assertEqual(result.exception.args[0]['msg'], 'missing required arguments: email')
+
+ def test_module_setup_fails_without_url(self):
+ set_module_args({
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ })
+
+ with self.assertRaises(AnsibleFailJson) as result:
+ grafana_team.main()
+ self.assertEqual(result.exception.args[0]['msg'], 'missing required arguments: url')
+
+ def test_module_setup_fails_with_mutually_exclusive_auth_methods(self):
+ set_module_args({
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com',
+ 'grafana_user': 'admin',
+ 'grafana_api_key': 'random_api_key',
+ })
+
+ with self.assertRaises(AnsibleFailJson) as result:
+ grafana_team.main()
+ self.assertEqual(result.exception.args[0]['msg'], 'parameters are mutually exclusive: url_username|grafana_api_key')
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ def test_module_fails_with_low_grafana_version(self, mock_get_version):
+ set_module_args({
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com',
+ 'grafana_user': 'admin',
+ 'grafana_password': 'admin',
+ })
+
+ module = grafana_team.setup_module_object()
+ mock_get_version.return_value = get_low_version_resp()
+
+ with self.assertRaises(AnsibleFailJson) as result:
+ grafana_team.main()
+ self.assertEqual(result.exception.args[0]['msg'], 'Teams API is available starting Grafana v5')
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_module_failure_with_unauthorized_resp(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com',
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = unauthorized_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ with self.assertRaises(AnsibleFailJson) as result:
+ grafana_team.main()
+ self.assertTrue(result.exception.args[0]['msg'].startswith('Unauthorized to perform action'))
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_module_failure_with_permission_denied_resp(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com',
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = permission_denied_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ with self.assertRaises(AnsibleFailJson) as result:
+ grafana_team.main()
+ self.assertTrue(result.exception.args[0]['msg'].startswith('Permission Denied'))
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_get_team_method_with_existing_team(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'state': 'present',
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = team_exists_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ grafana_iface = grafana_team.GrafanaTeamInterface(module)
+ res = grafana_iface.get_team("MyTestTeam")
+ mock_fetch_url.assert_called_once_with(
+ module, 'http://grafana.example.com/api/teams/search?name=MyTestTeam',
+ data=None,
+ headers={'Content-Type': 'application/json', 'Authorization': self.authorization},
+ method='GET')
+ self.assertEquals(res, {"email": "email@test.com", "name": "MyTestTeam"})
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_get_team_method_with_non_existing_team(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'state': 'present',
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = team_not_found_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ grafana_iface = grafana_team.GrafanaTeamInterface(module)
+ res = grafana_iface.get_team("MyTestTeam")
+ mock_fetch_url.assert_called_once_with(
+ module, 'http://grafana.example.com/api/teams/search?name=MyTestTeam',
+ data=None,
+ headers={'Content-Type': 'application/json', 'Authorization': self.authorization},
+ method='GET')
+ self.assertEquals(res, None)
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_create_team_method(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'state': 'present',
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = team_created_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ grafana_iface = grafana_team.GrafanaTeamInterface(module)
+
+ res = grafana_iface.create_team("MyTestTeam", "email@test.com")
+ mock_fetch_url.assert_called_once_with(
+ module, 'http://grafana.example.com/api/teams',
+ data=json.dumps({"email": "email@test.com", "name": "MyTestTeam"}, sort_keys=True),
+ headers={'Content-Type': 'application/json', 'Authorization': self.authorization},
+ method='POST')
+ self.assertEquals(res, {"message": "Team created", "teamId": 2})
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_update_team_method(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'state': 'present',
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = team_updated_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ grafana_iface = grafana_team.GrafanaTeamInterface(module)
+ res = grafana_iface.update_team(2, "MyTestTeam", "email@test.com")
+ mock_fetch_url.assert_called_once_with(
+ module, 'http://grafana.example.com/api/teams/2',
+ data=json.dumps({"email": "email@test.com", "name": "MyTestTeam"}, sort_keys=True),
+ headers={'Content-Type': 'application/json', 'Authorization': self.authorization},
+ method='PUT')
+ self.assertEquals(res, {"message": "Team updated"})
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_delete_team_method(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'state': 'absent',
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = team_deleted_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ grafana_iface = grafana_team.GrafanaTeamInterface(module)
+ res = grafana_iface.delete_team(2)
+ mock_fetch_url.assert_called_once_with(
+ module, 'http://grafana.example.com/api/teams/2',
+ data=None,
+ headers={'Content-Type': 'application/json', 'Authorization': self.authorization},
+ method='DELETE')
+ self.assertEquals(res, {"message": "Team deleted"})
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_get_team_members_method(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'state': 'present',
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = team_members_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ grafana_iface = grafana_team.GrafanaTeamInterface(module)
+ res = grafana_iface.get_team_members(2)
+ mock_fetch_url.assert_called_once_with(
+ module, 'http://grafana.example.com/api/teams/2/members',
+ data=None,
+ headers={'Content-Type': 'application/json', 'Authorization': self.authorization},
+ method='GET')
+ self.assertEquals(res, ["user1@email.com", "user2@email.com"])
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_get_team_members_method_no_members_returned(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'state': 'present',
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = team_members_no_members_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ grafana_iface = grafana_team.GrafanaTeamInterface(module)
+ res = grafana_iface.get_team_members(2)
+ mock_fetch_url.assert_called_once_with(
+ module, 'http://grafana.example.com/api/teams/2/members',
+ data=None,
+ headers={'Content-Type': 'application/json', 'Authorization': self.authorization},
+ method='GET')
+ self.assertEquals(res, [])
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_add_team_member_method(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'state': 'present',
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = add_team_member_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ grafana_iface = grafana_team.GrafanaTeamInterface(module)
+ with patch.object(grafana_team.GrafanaTeamInterface, 'get_user_id_from_mail') as mock_get_user_id_from_mail:
+ mock_get_user_id_from_mail.return_value = 42
+ res = grafana_iface.add_team_member(2, "another@test.com")
+ mock_fetch_url.assert_called_once_with(
+ module, 'http://grafana.example.com/api/teams/2/members',
+ data=json.dumps({'userId': 42}),
+ headers={'Content-Type': 'application/json', 'Authorization': self.authorization},
+ method='POST')
+ self.assertEquals(res, None)
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.GrafanaTeamInterface.get_version')
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_team.fetch_url')
+ def test_delete_team_member_method(self, mock_fetch_url, mock_get_version):
+ set_module_args({
+ 'state': 'present',
+ 'name': 'MyTestTeam',
+ 'email': 'email@test.com',
+ 'url': 'http://grafana.example.com'
+ })
+ module = grafana_team.setup_module_object()
+ mock_fetch_url.return_value = delete_team_member_resp()
+ mock_get_version.return_value = get_version_resp()
+
+ grafana_iface = grafana_team.GrafanaTeamInterface(module)
+ with patch.object(grafana_team.GrafanaTeamInterface, 'get_user_id_from_mail') as mock_get_user_id_from_mail:
+ mock_get_user_id_from_mail.return_value = 42
+ res = grafana_iface.delete_team_member(2, "another@test.com")
+ mock_fetch_url.assert_called_once_with(
+ module, 'http://grafana.example.com/api/teams/2/members/42',
+ data=None,
+ headers={'Content-Type': 'application/json', 'Authorization': self.authorization},
+ method='DELETE')
+ self.assertEquals(res, None)
+
+ def test_diff_members_function(self):
+ list1 = ["foo@example.com", "bar@example.com"]
+ list2 = ["bar@example.com", "random@example.com"]
+
+ res = grafana_team.diff_members(list1, list2)
+ self.assertEquals(res, {"to_del": ["random@example.com"], "to_add": ["foo@example.com"]})
diff --git a/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_user/test_grafana_user.py b/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_user/test_grafana_user.py
new file mode 100644
index 000000000..925c01655
--- /dev/null
+++ b/ansible_collections/community/grafana/tests/unit/modules/grafana/grafana_user/test_grafana_user.py
@@ -0,0 +1,200 @@
+from __future__ import (absolute_import, division, print_function)
+
+from unittest import TestCase
+from unittest.mock import call, patch, MagicMock
+from ansible_collections.community.grafana.plugins.modules import grafana_user
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils import basic
+from ansible.module_utils.urls import basic_auth_header
+import json
+
+__metaclass__ = type
+
+
+class MockedReponse(object):
+ def __init__(self, data):
+ self.data = data
+
+ def read(self):
+ return self.data
+
+
+def exit_json(*args, **kwargs):
+ """function to patch over exit_json; package return data into an exception"""
+ if 'changed' not in kwargs:
+ kwargs['changed'] = False
+ raise AnsibleExitJson(kwargs)
+
+
+def fail_json(*args, **kwargs):
+ """function to patch over fail_json; package return data into an exception"""
+ kwargs['failed'] = True
+ raise AnsibleFailJson(kwargs)
+
+
+class AnsibleExitJson(Exception):
+ """Exception class to be raised by module.exit_json and caught by the test case"""
+ pass
+
+
+class AnsibleFailJson(Exception):
+ """Exception class to be raised by module.fail_json and caught by the test case"""
+ pass
+
+
+def set_module_args(args):
+ """prepare arguments so that they will be picked up during module creation"""
+ args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
+ basic._ANSIBLE_ARGS = to_bytes(args)
+
+
+def user_deleted_resp():
+ server_response = json.dumps({"message": "User deleted"})
+ return (MockedReponse(server_response), {"status": 200})
+
+
+def user_already_exists_resp():
+ server_response = json.dumps({"message": "failed to create user"})
+ return (MockedReponse(server_response), {"status": 500})
+
+
+def user_created_resp():
+ server_response = json.dumps({
+ "id": 2,
+ "email": "robin@gotham.com",
+ "name": "Robin",
+ "login": "adrobinmin",
+ "theme": "light",
+ "orgId": 1,
+ "isGrafanaAdmin": False,
+ "isDisabled": False,
+ "isExternal": False,
+ "authLabels": None,
+ "updatedAt": "2019-09-25T14:44:37+01:00",
+ "createdAt": "2019-09-25T14:44:37+01:00"
+ }, sort_keys=True)
+ return (MockedReponse(server_response), {"status": 200})
+
+
+class GrafanaUserTest(TestCase):
+
+ def setUp(self):
+ self.authorization = basic_auth_header("admin", "changeme")
+ self.mock_module_helper = patch.multiple(basic.AnsibleModule,
+ exit_json=exit_json,
+ fail_json=fail_json)
+ self.mock_module_helper.start()
+ self.addCleanup(self.mock_module_helper.stop)
+
+ # create an already existing user
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_user.fetch_url')
+ def test_create_user_existing_user(self, mock_fetch_url):
+ set_module_args({
+ 'url': 'https://grafana.example.com',
+ 'url_username': 'admin',
+ 'url_password': 'changeme',
+ 'name': 'Joker',
+ 'email': 'joker@gotham.com',
+ 'login': 'joker',
+ 'password': 'oups',
+ 'state': 'present'
+ })
+ module = grafana_user.setup_module_object()
+ mock_fetch_url.return_value = user_already_exists_resp()
+
+ grafana_iface = grafana_user.GrafanaUserInterface(module)
+ with self.assertRaises(AnsibleFailJson):
+ grafana_iface.create_user(
+ 'Joker', 'joker@gotham.com', 'joker', 'oups')
+ mock_fetch_url.assert_called_once_with(
+ module,
+ 'https://grafana.example.com/api/admin/users',
+ data=json.dumps({'name': 'Joker', 'email': 'joker@gotham.com',
+ 'login': 'joker', 'password': 'oups'}, sort_keys=True),
+ headers={'Content-Type': 'application/json',
+ 'Authorization': self.authorization},
+ method='POST')
+
+ # create a new user
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_user.fetch_url')
+ def test_create_user_new_user(self, mock_fetch_url):
+ set_module_args({
+ 'url': 'https://grafana.example.com',
+ 'url_username': 'admin',
+ 'url_password': 'changeme',
+ 'name': 'Robin',
+ 'email': 'robin@gotham.com',
+ 'login': 'robin',
+ 'password': 'oups',
+ 'state': 'present'
+ })
+ module = grafana_user.setup_module_object()
+
+ mock_fetch_url.return_value = user_created_resp()
+
+ expected_fetch_url_calls = [
+ # first call to create user
+ call(
+ module,
+ 'https://grafana.example.com/api/admin/users',
+ data=json.dumps({'name': 'Robin', 'email': 'robin@gotham.com',
+ 'login': 'robin', 'password': 'oups'}, sort_keys=True),
+ headers={'Content-Type': 'application/json',
+ 'Authorization': self.authorization},
+ method='POST'),
+
+ # second call to return created user
+ call(
+ module,
+ 'https://grafana.example.com/api/users/lookup?loginOrEmail=robin',
+ data=None,
+ headers={'Content-Type': 'application/json',
+ 'Authorization': self.authorization},
+ method='GET'),
+ ]
+
+ grafana_iface = grafana_user.GrafanaUserInterface(module)
+ result = grafana_iface.create_user(
+ 'Robin', 'robin@gotham.com', 'robin', 'oups')
+
+ mock_fetch_url.assert_has_calls(
+ expected_fetch_url_calls, any_order=False)
+
+ self.assertEquals(result, {
+ "id": 2,
+ "email": "robin@gotham.com",
+ "name": "Robin",
+ "login": "adrobinmin",
+ "theme": "light",
+ "orgId": 1,
+ "isGrafanaAdmin": False,
+ "isDisabled": False,
+ "isExternal": False,
+ "authLabels": None,
+ "updatedAt": "2019-09-25T14:44:37+01:00",
+ "createdAt": "2019-09-25T14:44:37+01:00"
+ })
+
+ @patch('ansible_collections.community.grafana.plugins.modules.grafana_user.fetch_url')
+ def test_delete_user(self, mock_fetch_url):
+ set_module_args({
+ 'url': 'https://grafana.example.com',
+ 'url_username': 'admin',
+ 'url_password': 'changeme',
+ 'login': 'batman',
+ 'state': 'absent'
+ })
+ module = grafana_user.setup_module_object()
+ mock_fetch_url.return_value = user_deleted_resp()
+
+ grafana_iface = grafana_user.GrafanaUserInterface(module)
+ user_id = 42
+ result = grafana_iface.delete_user(user_id)
+ mock_fetch_url.assert_called_once_with(
+ module,
+ 'https://grafana.example.com/api/admin/users/42',
+ data=None,
+ headers={'Content-Type': 'application/json',
+ 'Authorization': self.authorization},
+ method='DELETE')
+ self.assertEquals(result, {"message": "User deleted"})