Skip to content

Commit

Permalink
improve code quality and style guide
Browse files Browse the repository at this point in the history
  • Loading branch information
flkhndlr committed Jan 3, 2024
1 parent 5d8011b commit 06b7a89
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 138 deletions.
152 changes: 98 additions & 54 deletions plugins/modules/grafana_silence.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

from __future__ import absolute_import, division, print_function

DOCUMENTATION = '''
DOCUMENTATION = """
---
module: grafana_silence
author:
- flkhndlr (@flkhndlr)
version_added: "1.5.5"
version_added: "1.6.0"
short_description: Manage Grafana Silences
description:
- Create/delete Grafana Silences through the Alertmanager Silence API.
Expand All @@ -45,15 +45,18 @@
description:
- ISO 8601 Timestamp with milliseconds e.g. "2029-07-29T08:45:45.000Z" when the silence starts.
type: str
required: true
ends_at:
description:
- ISO 8601 Timestamp with milliseconds e.g. "2029-07-29T08:45:45.000Z" when the silence will end.
type: str
required: true
matchers:
description:
- List of matchers to select which alerts are affected by the silence.
type: list
elements: str
elements: dict
required: true
state:
description:
- Delete the first occurrence of a silence with the same settings.
Expand All @@ -67,13 +70,12 @@
required: False
type: bool
default: False
version_added: "1.2.0"
extends_documentation_fragment:
- community.grafana.basic_auth
- community.grafana.api_key
'''
"""

EXAMPLES = '''
EXAMPLES = """
---
- name: Create a silence
community.grafana.grafana_silence:
Expand Down Expand Up @@ -104,9 +106,9 @@
name: environment
value: test
state: absent
'''
"""

RETURN = '''
RETURN = """
---
silence:
description: Information about the Silence
Expand Down Expand Up @@ -152,7 +154,7 @@
status:
description: The status of the Silence
returned: success
type: object
type: dict
sample:
- {"state": "pending"}
updatedAt:
Expand All @@ -161,7 +163,7 @@
type: str
sample:
- "2023-07-27T13:27:33.042Z"
'''
"""

import json

Expand All @@ -178,25 +180,31 @@ class GrafanaError(Exception):


class GrafanaSilenceInterface(object):

def __init__(self, module):
self._module = module

Check warning on line 184 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L184

Added line #L184 was not covered by tests
# {{{ Authentication header
self.headers = {"Content-Type": "application/json"}
module.params['force_basic_auth'] = True
if module.params.get('grafana_api_key', None):
self.headers["Authorization"] = "Bearer %s" % module.params['grafana_api_key']
module.params["force_basic_auth"] = True

Check warning on line 187 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L186-L187

Added lines #L186 - L187 were not covered by tests
if module.params.get("grafana_api_key", None):
self.headers["Authorization"] = (

Check warning on line 189 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L189

Added line #L189 was not covered by tests
"Bearer %s" % module.params["grafana_api_key"]
)
else:
self.headers["Authorization"] = basic_auth_header(module.params['url_username'], module.params['url_password'])
self.headers["Authorization"] = basic_auth_header(

Check warning on line 193 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L193

Added line #L193 was not covered by tests
module.params["url_username"], module.params["url_password"]
)
# }}}
self.grafana_url = base.clean_url(module.params.get("url"))

Check warning on line 197 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L197

Added line #L197 was not covered by tests
if module.params.get("skip_version_check") is False:
try:
grafana_version = self.get_version()
except GrafanaError as e:
self._module.fail_json(failed=True, msg=to_text(e))

Check warning on line 202 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L199-L202

Added lines #L199 - L202 were not covered by tests
if grafana_version["major"] < 5:
self._module.fail_json(failed=True, msg="Silences API is available starting Grafana v8")
if grafana_version["major"] < 8:
self._module.fail_json(

Check warning on line 204 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L204

Added line #L204 was not covered by tests
failed=True,
msg="Silences API is available starting with Grafana v8",
)

def _send_request(self, url, data=None, headers=None, method="GET"):
if data is not None:
Expand All @@ -205,12 +213,17 @@ def _send_request(self, url, data=None, headers=None, method="GET"):
headers = []

Check warning on line 213 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L213

Added line #L213 was not covered by tests

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)
resp, info = fetch_url(

Check warning on line 216 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L215-L216

Added lines #L215 - L216 were not covered by tests
self._module, full_url, data=data, headers=headers, method=method
)
status_code = info["status"]

Check warning on line 219 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L219

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

Check warning on line 221 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L221

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

Check warning on line 223 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L223

Added line #L223 was not covered by tests
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")

Check warning on line 228 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L228

Added line #L228 was not covered by tests
elif status_code == 202:
Expand All @@ -219,11 +232,15 @@ def _send_request(self, url, data=None, headers=None, method="GET"):
return self._module.from_json(resp.read())

Check warning on line 232 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L232

Added line #L232 was not covered by tests
elif status_code == 400:
self._module.fail_json(failed=True, msg=info)
self._module.fail_json(failed=True, msg="Grafana Silences API answered with HTTP %d" % status_code)
self._module.fail_json(

Check warning on line 235 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L234-L235

Added lines #L234 - L235 were not covered by tests
failed=True, msg="Grafana Silences API answered with HTTP %d" % status_code
)

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

Check warning on line 241 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L240-L241

Added lines #L240 - L241 were not covered by tests
url, data=None, headers=self.headers, method="GET"
)
version = response.get("version")

Check warning on line 244 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L244

Added line #L244 was not covered by tests
if version is not None:
major, minor, rev = version.split(".")
Expand All @@ -232,8 +249,16 @@ def get_version(self):

def create_silence(self, comment, created_by, starts_at, ends_at, matchers):
url = "/api/alertmanager/grafana/api/v2/silences"
silence = dict(comment=comment, createdBy=created_by, startsAt=starts_at, endsAt=ends_at, matchers=matchers)
response = self._send_request(url, data=silence, headers=self.headers, method="POST")
silence = dict(

Check warning on line 252 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L251-L252

Added lines #L251 - L252 were not covered by tests
comment=comment,
createdBy=created_by,
startsAt=starts_at,
endsAt=ends_at,
matchers=matchers,
)
response = self._send_request(

Check warning on line 259 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L259

Added line #L259 was not covered by tests
url, data=silence, headers=self.headers, method="POST"
)
return response

Check warning on line 262 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L262

Added line #L262 was not covered by tests

def get_silence(self, comment, created_by, starts_at, ends_at, matchers):
Expand All @@ -242,16 +267,22 @@ def get_silence(self, comment, created_by, starts_at, ends_at, matchers):
responses = self._send_request(url, headers=self.headers, method="GET")

Check warning on line 267 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L267

Added line #L267 was not covered by tests

for response in responses:
if response["comment"] == comment and response["createdBy"] == created_by and \
response["startsAt"] == starts_at and response["endsAt"] == ends_at and \
response["matchers"] == matchers:
if (
response["comment"] == comment
and response["createdBy"] == created_by
and response["startsAt"] == starts_at
and response["endsAt"] == ends_at
and response["matchers"] == matchers
):
return response

Check warning on line 277 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L277

Added line #L277 was not covered by tests
else:
return None
return None

Check warning on line 280 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L279-L280

Added lines #L279 - L280 were not covered by tests

def get_silence_by_id(self, silence_id):
url = "/api/alertmanager/grafana/api/v2/silence/{SilenceId}".format(SilenceId=silence_id)
url = "/api/alertmanager/grafana/api/v2/silence/{SilenceId}".format(

Check warning on line 283 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L283

Added line #L283 was not covered by tests
SilenceId=silence_id
)
response = self._send_request(url, headers=self.headers, method="GET")
return response

Check warning on line 287 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L286-L287

Added lines #L286 - L287 were not covered by tests

Expand All @@ -261,7 +292,9 @@ def get_silences(self):
return response

Check warning on line 292 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L290-L292

Added lines #L290 - L292 were not covered by tests

def delete_silence(self, silence_id):
url = "/api/alertmanager/grafana/api/v2/silence/{SilenceId}".format(SilenceId=silence_id)
url = "/api/alertmanager/grafana/api/v2/silence/{SilenceId}".format(

Check warning on line 295 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L295

Added line #L295 was not covered by tests
SilenceId=silence_id
)
response = self._send_request(url, headers=self.headers, method="DELETE")
return response

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

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L298-L299

Added lines #L298 - L299 were not covered by tests

Expand All @@ -278,50 +311,61 @@ def setup_module_object():

argument_spec = base.grafana_argument_spec()
argument_spec.update(
comment=dict(type='str', required=True),
state=dict(type='str', required=True),
created_by=dict(type='str', required=True),
starts_at=dict(type='str', required=True),
ends_at=dict(type='str', required=True),
matchers=dict(type='list', elements='dict', required=True),
comment=dict(type="str", required=True),
state=dict(type="str", choices=["present", "absent"], default="present"),
created_by=dict(type="str", required=True),
starts_at=dict(type="str", required=True),
ends_at=dict(type="str", required=True),
matchers=dict(type="list", elements="dict", required=True),
skip_version_check=dict(type="bool", default=False),
)


def main():

module = setup_module_object()
comment = module.params['comment']
created_by = module.params['created_by']
starts_at = module.params['starts_at']
ends_at = module.params['ends_at']
matchers = module.params['matchers']
state = module.params['state']
comment = module.params["comment"]
created_by = module.params["created_by"]
starts_at = module.params["starts_at"]
ends_at = module.params["ends_at"]
matchers = module.params["matchers"]
state = module.params["state"]

Check warning on line 332 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L327-L332

Added lines #L327 - L332 were not covered by tests

changed = False
failed = False
silence = ""
grafana_iface = GrafanaSilenceInterface(module)

Check warning on line 336 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L334-L336

Added lines #L334 - L336 were not covered by tests

if state == 'present':
silence = grafana_iface.get_silence(comment, created_by, starts_at, ends_at, matchers)
if silence is None:
silence = grafana_iface.create_silence(comment, created_by, starts_at, ends_at, matchers)
silence = grafana_iface.get_silence(

Check warning on line 338 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L338

Added line #L338 was not covered by tests
comment, created_by, starts_at, ends_at, matchers
)

if state == "present":

if not silence:
silence = grafana_iface.create_silence(

Check warning on line 345 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L345

Added line #L345 was not covered by tests
comment, created_by, starts_at, ends_at, matchers
)
silence = grafana_iface.get_silence_by_id(silence["silenceID"])
changed = True

Check warning on line 349 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L348-L349

Added lines #L348 - L349 were not covered by tests
else:
module.exit_json(failed=failed, changed=changed,
msg="Silence with same parameters already exists! eg. '%s'" % silence["id"])
elif state == 'absent':
silence = grafana_iface.get_silence(comment, created_by, starts_at, ends_at, matchers)
if silence is not None:
module.exit_json(

Check warning on line 351 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L351

Added line #L351 was not covered by tests
failed=failed,
changed=changed,
msg="Silence with same parameters already exists! eg. '%s'"
% silence["id"],
)
elif state == "absent":
if silence:
grafana_iface.delete_silence(silence["id"])
changed = True

Check warning on line 360 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L359-L360

Added lines #L359 - L360 were not covered by tests
else:
failed = True
module.exit_json(failed=failed, changed=changed,
msg="No Silence with the same parameters found! Deletion not possible")
module.exit_json(

Check warning on line 362 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L362

Added line #L362 was not covered by tests
failed=failed,
changed=changed,
msg="No Silence with the same parameters found! Deletion not possible",
)
module.exit_json(failed=failed, changed=changed, silence=silence)

Check warning on line 367 in plugins/modules/grafana_silence.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/grafana_silence.py#L367

Added line #L367 was not covered by tests


if __name__ == '__main__':
if __name__ == "__main__":
main()
3 changes: 1 addition & 2 deletions tests/integration/targets/grafana_silence/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,4 @@
that:
- "result.changed == false"
- "result.failed == true"
- "result.msg == 'No Silence with the same parameters found! Deletion not possible'"

- "result.msg == 'No Silence with the same parameters found! Deletion not possible'"
Loading

0 comments on commit 06b7a89

Please sign in to comment.