Skip to content

Commit

Permalink
handle errors with negative return code better
Browse files Browse the repository at this point in the history
  • Loading branch information
rndmh3ro committed Apr 26, 2024
1 parent fc4f19a commit bb25a66
Show file tree
Hide file tree
Showing 7 changed files with 326 additions and 252 deletions.
38 changes: 37 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,37 @@ def grafana_required_together():

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
if data is not None:
data = json.dumps(data, sort_keys=True)
if not headers:
headers = []

full_url = "{grafana_url}{path}".format(grafana_url=grafana_url, path=url)
resp, info = fetch_url(
module=self.module, url=full_url, data=data, headers=headers, method=method
)
status_code = info["status"]
if status_code == 404:
return None
elif status_code == 401:
return self._module.fail_json(
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")
elif status_code < 0:
self._module.fail_json(failed=True, msg=info["msg"])
elif status_code == 200:
return self._module.from_json(resp.read())
self._module.fail_json(
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 @@ -724,41 +722,27 @@ def __init__(self, module):
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(
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(
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 @@ -769,19 +753,49 @@ def organization_by_name(self, org_name):

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(
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(
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(
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(
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 @@ def __init__(self, module):
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(
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(
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 organization_by_name(self, org_name):

def get_version(self):
url = "/api/health"
response = self._send_request(
url, data=None, headers=self.headers, method="GET"
response = base.grafana_send_request(
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 get_version(self):
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(
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(
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(
self,
module=self._module,
url=url,
grafana_url=self.grafana_url,
headers=self.headers,
method="DELETE",
)


def main():
Expand Down
Loading

0 comments on commit bb25a66

Please sign in to comment.