Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle errors with negative return code better #359

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion plugins/module_utils/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
# Copyright: (c) 2019, Rémi REY (@rrey)

from __future__ import absolute_import, division, print_function
from ansible.module_utils.urls import url_argument_spec
from ansible.module_utils.urls import url_argument_spec, fetch_url

import json

__metaclass__ = type

Expand Down Expand Up @@ -52,3 +54,38 @@

def grafana_mutually_exclusive():
return [["url_username", "grafana_api_key"]]


def grafana_send_request(
self, module, url, grafana_url, data=None, headers=None, method="GET"
):
self.module = module

Check warning on line 62 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L62

Added line #L62 was not covered by tests
if data is not None:
data = json.dumps(data, sort_keys=True)

Check warning on line 64 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L64

Added line #L64 was not covered by tests
if not headers:
headers = []

Check warning on line 66 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L66

Added line #L66 was not covered by tests

full_url = "{grafana_url}{path}".format(grafana_url=grafana_url, path=url)
resp, info = fetch_url(

Check warning on line 69 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L68-L69

Added lines #L68 - L69 were not covered by tests
module=self.module, url=full_url, data=data, headers=headers, method=method
)
status_code = info["status"]

Check warning on line 72 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L72

Added line #L72 was not covered by tests
if status_code == 404:
return None

Check warning on line 74 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L74

Added line #L74 was not covered by tests
elif status_code == 401:
return self._module.fail_json(

Check warning on line 76 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L76

Added line #L76 was not covered by tests
failed=True,
msg="Unauthorized to perform action '%s' on '%s' header: %s"
% (method, full_url, self.headers),
)
elif status_code == 403:
self._module.fail_json(failed=True, msg="Permission Denied")

Check warning on line 82 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L82

Added line #L82 was not covered by tests
elif status_code < 0:
self._module.fail_json(failed=True, msg=info["msg"])

Check warning on line 84 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L84

Added line #L84 was not covered by tests
elif status_code in [200, 202]:
return self._module.from_json(resp.read())
self._module.fail_json(

Check warning on line 87 in plugins/module_utils/base.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/base.py#L86-L87

Added lines #L86 - L87 were not covered by tests
failed=True,
msg="Grafana API answered with HTTP %d" % status_code,
body=self._module.from_json(resp.read()),
)
88 changes: 51 additions & 37 deletions plugins/modules/grafana_datasource.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,11 +521,9 @@
"withCredentials": false }
"""

import json

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible.module_utils.urls import fetch_url, basic_auth_header
from ansible.module_utils.urls import basic_auth_header
from ansible_collections.community.grafana.plugins.module_utils import base


Expand Down Expand Up @@ -727,41 +725,27 @@
self.switch_organization(self.org_id)
# }}}

def _send_request(self, url, data=None, headers=None, method="GET"):
if data is not None:
data = json.dumps(data, sort_keys=True)
if not headers:
headers = []

full_url = "{grafana_url}{path}".format(grafana_url=self.grafana_url, path=url)
resp, info = fetch_url(
self._module, full_url, data=data, headers=headers, method=method
)
status_code = info["status"]
if status_code == 404:
return None
elif status_code == 401:
self._module.fail_json(
failed=True,
msg="Unauthorized to perform action '%s' on '%s'" % (method, full_url),
)
elif status_code == 403:
self._module.fail_json(failed=True, msg="Permission Denied")
elif status_code == 200:
return self._module.from_json(resp.read())
self._module.fail_json(
failed=True,
msg="Grafana API answered with HTTP %d for url %s and data %s"
% (status_code, url, data),
)

def switch_organization(self, org_id):
url = "/api/user/using/%d" % org_id
self._send_request(url, headers=self.headers, method="POST")
base.grafana_send_request(

Check warning on line 730 in plugins/modules/grafana_datasource.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_datasource.py#L730

Added line #L730 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="POST",
)

def organization_by_name(self, org_name):
url = "/api/user/orgs"
organizations = self._send_request(url, headers=self.headers, method="GET")
organizations = base.grafana_send_request(

Check warning on line 741 in plugins/modules/grafana_datasource.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_datasource.py#L741

Added line #L741 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="GET",
)
orga = next((org for org in organizations if org["name"] == org_name))
if orga:
return orga["orgId"]
Expand All @@ -772,19 +756,49 @@

def datasource_by_name(self, name):
url = "/api/datasources/name/%s" % quote(name, safe="")
return self._send_request(url, headers=self.headers, method="GET")
return base.grafana_send_request(

Check warning on line 759 in plugins/modules/grafana_datasource.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_datasource.py#L759

Added line #L759 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="GET",
)

def delete_datasource(self, name):
url = "/api/datasources/name/%s" % quote(name, safe="")
self._send_request(url, headers=self.headers, method="DELETE")
base.grafana_send_request(

Check warning on line 770 in plugins/modules/grafana_datasource.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_datasource.py#L770

Added line #L770 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="DELETE",
)

def update_datasource(self, ds_id, data):
url = "/api/datasources/%d" % ds_id
self._send_request(url, data=data, headers=self.headers, method="PUT")
base.grafana_send_request(

Check warning on line 781 in plugins/modules/grafana_datasource.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_datasource.py#L781

Added line #L781 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
data=data,
method="PUT",
)

def create_datasource(self, data):
url = "/api/datasources"
self._send_request(url, data=data, headers=self.headers, method="POST")
base.grafana_send_request(

Check warning on line 793 in plugins/modules/grafana_datasource.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_datasource.py#L793

Added line #L793 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
data=data,
method="POST",
)


def setup_module_object():
Expand Down
93 changes: 48 additions & 45 deletions plugins/modules/grafana_folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,8 @@
- 1
"""

import json

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.urls import fetch_url, basic_auth_header
from ansible.module_utils.urls import basic_auth_header
from ansible_collections.community.grafana.plugins.module_utils import base
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible.module_utils._text import to_text
Expand Down Expand Up @@ -223,45 +221,27 @@
failed=True, msg="Folders API is available starting Grafana v5"
)

def _send_request(self, url, data=None, headers=None, method="GET"):
if data is not None:
data = json.dumps(data, sort_keys=True)
if not headers:
headers = []

full_url = "{grafana_url}{path}".format(grafana_url=self.grafana_url, path=url)
resp, info = fetch_url(
self._module, full_url, data=data, headers=headers, method=method
)
status_code = info["status"]
if status_code == 404:
return None
elif status_code == 401:
self._module.fail_json(
failed=True,
msg="Unauthorized to perform action '%s' on '%s'" % (method, full_url),
)
elif status_code == 403:
self._module.fail_json(failed=True, msg="Permission Denied")
elif status_code == 412:
error_msg = resp.read()["message"]
self._module.fail_json(failed=True, msg=error_msg)
elif status_code == 200:
# XXX: Grafana folders endpoint stopped sending back json in response for delete operations
# see https://github.com/grafana/grafana/issues/77673
response = resp.read() or "{}"
return self._module.from_json(response)
self._module.fail_json(
failed=True, msg="Grafana Folders API answered with HTTP %d" % status_code
)

def switch_organization(self, org_id):
url = "/api/user/using/%d" % org_id
self._send_request(url, headers=self.headers, method="POST")
base.grafana_send_request(

Check warning on line 226 in plugins/modules/grafana_folder.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_folder.py#L226

Added line #L226 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="POST",
)

def organization_by_name(self, org_name):
url = "/api/user/orgs"
organizations = self._send_request(url, headers=self.headers, method="GET")
organizations = base.grafana_send_request(

Check warning on line 237 in plugins/modules/grafana_folder.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_folder.py#L237

Added line #L237 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="GET",
)
orga = next((org for org in organizations if org["name"] == org_name))
if orga:
return orga["orgId"]
Expand All @@ -272,8 +252,13 @@

def get_version(self):
url = "/api/health"
response = self._send_request(
url, data=None, headers=self.headers, method="GET"
response = base.grafana_send_request(

Check warning on line 255 in plugins/modules/grafana_folder.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_folder.py#L255

Added line #L255 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="GET",
)
version = response.get("version")
if version is not None:
Expand All @@ -284,23 +269,41 @@
def create_folder(self, title):
url = "/api/folders"
folder = dict(title=title)
response = self._send_request(
url, data=folder, headers=self.headers, method="POST"
return base.grafana_send_request(

Check warning on line 272 in plugins/modules/grafana_folder.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_folder.py#L272

Added line #L272 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
data=folder,
method="POST",
)
return response

def get_folder(self, title):
url = "/api/search?type=dash-folder&query={title}".format(title=quote(title))
response = self._send_request(url, headers=self.headers, method="GET")
response = base.grafana_send_request(

Check warning on line 284 in plugins/modules/grafana_folder.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_folder.py#L284

Added line #L284 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="GET",
)
for item in response:
if item.get("title") == to_text(title):
return item
return None

def delete_folder(self, folder_uid):
url = "/api/folders/{folder_uid}".format(folder_uid=folder_uid)
response = self._send_request(url, headers=self.headers, method="DELETE")
return response
return base.grafana_send_request(

Check warning on line 299 in plugins/modules/grafana_folder.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_folder.py#L299

Added line #L299 was not covered by tests
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="DELETE",
)


def main():
Expand Down
Loading
Loading