summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/grafana/tests/unit/modules
diff options
context:
space:
mode:
Diffstat (limited to 'ansible_collections/community/grafana/tests/unit/modules')
-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
4 files changed, 970 insertions, 0 deletions
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"})