Skip to content

Commit d40ad6e

Browse files
bursztymamotl
authored andcommitted
Implement foundation for accessing the Alerting Provisioning API
1 parent 4c552a5 commit d40ad6e

File tree

5 files changed

+252
-0
lines changed

5 files changed

+252
-0
lines changed

grafana_client/api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from .client import GrafanaClient
1313
from .elements import (
1414
Admin,
15+
AlertingProvisioning,
1516
Annotations,
1617
Dashboard,
1718
DashboardVersions,
@@ -56,6 +57,7 @@ def __init__(
5657
)
5758
self.url = None
5859
self.admin = Admin(self.client)
60+
self.alertingprovisioning = AlertingProvisioning(self.client)
5961
self.dashboard = Dashboard(self.client)
6062
self.dashboard_versions = DashboardVersions(self.client)
6163
self.datasource = Datasource(self.client, self)

grafana_client/client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ def __request_runner(url, json=None, data=None, headers=None):
161161
# The "Tempo" data source responds with text/plain.
162162
if r.headers.get("Content-Type", "").startswith("text/"):
163163
return r.text
164+
elif not r.text: # Fix for alert rules
165+
return r.status_code
164166
else:
165167
return r.json()
166168

grafana_client/elements/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .admin import Admin
2+
from .alertingprovisioning import AlertingProvisioning
23
from .annotations import Annotations
34
from .base import Base
45
from .dashboard import Dashboard
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
from .base import Base
2+
3+
4+
class AlertingProvisioning(Base):
5+
def __init__(self, client):
6+
super(AlertingProvisioning, self).__init__(client)
7+
self.client = client
8+
9+
def get_alertrule(self, alertrule_uid):
10+
"""
11+
12+
:param alertrule_uid:
13+
:return:
14+
"""
15+
get_alertrule_path = "/v1/provisioning/alert-rules/%s" % alertrule_uid
16+
r = self.client.GET(get_alertrule_path)
17+
return r
18+
19+
def create_alertrule(self, alertrule):
20+
"""
21+
:param alertrule:
22+
:return:
23+
"""
24+
25+
create_alertrule_path = "/v1/provisioning/alert-rules"
26+
r = self.client.POST(create_alertrule_path, json=alertrule)
27+
return r
28+
29+
def update_alertrule(self, alertrule_uid, alertrule):
30+
"""
31+
@param alertrule_uid:
32+
@param alertrule:
33+
@return:
34+
"""
35+
36+
update_alertrule_path = "/v1/provisioning/alert-rules/%s" % alertrule_uid
37+
r = self.client.PUT(update_alertrule_path, json=alertrule)
38+
return r
39+
40+
def update_rule_group_interval(self, folder_uid, group_uid, alertrule_group):
41+
"""
42+
:param folder_uid:
43+
:param group_uid:
44+
:return:
45+
"""
46+
update_rule_group_interval_path = "/v1/provisioning/folder/%s/rule-groups/%s" % (folder_uid, group_uid)
47+
r = self.client.PUT(update_rule_group_interval_path, json=alertrule_group)
48+
return r
49+
50+
def delete_alertrule(self, alertrule_uid):
51+
"""
52+
@param alertrule_uid:
53+
@param alertrule:
54+
@return:
55+
"""
56+
57+
delete_alertrule_path = "/v1/provisioning/alert-rules/%s" % alertrule_uid
58+
r = self.client.DELETE(delete_alertrule_path)
59+
return r
60+
61+
def get_contactpoints(self):
62+
"""
63+
Gets all contact points
64+
@return:
65+
"""
66+
get_contactpoints_path = "/v1/provisioning/contact-points"
67+
return self.client.GET(get_contactpoints_path)
68+
69+
def create_contactpoint(self, contactpoint):
70+
"""
71+
Creates single contact point
72+
@param contactpoint:
73+
@return:
74+
"""
75+
create_contactpoint_path = "/v1/provisioning/contact-points"
76+
return self.client.POST(create_contactpoint_path, json=contactpoint)
77+
78+
def update_contactpoint(self, contactpoint_uid, contactpoint):
79+
"""
80+
Updates existing contact point
81+
@param contactpoint_uid:
82+
@param contactpoint:
83+
@return:
84+
"""
85+
update_contactpoint_path = "/v1/provisioning/contact-points/%s" % contactpoint_uid
86+
return self.client.PUT(update_contactpoint_path, json=contactpoint)
87+
88+
def delete_contactpoint(self, contactpoint_uid):
89+
"""
90+
Deletes existing contactpoint
91+
@param contactpoint_uid:
92+
@return:
93+
"""
94+
delete_contactpoint_path = "/v1/provisioning/contact-points/%s" % contactpoint_uid
95+
return self.client.DELETE(delete_contactpoint_path)
96+
97+
def get_notification_policy_tree(self):
98+
"""
99+
Gets notification policy tree
100+
@return:
101+
"""
102+
get_notification_policy_tree_path = "/v1/provisioning/policies"
103+
return self.client.GET(get_notification_policy_tree_path)
104+
105+
def set_notification_policy_tree(self, notification_policy_tree):
106+
"""
107+
Sets notification policy tree
108+
@param notification_policy_tree:
109+
@return:
110+
"""
111+
set_notification_policy_tree_path = "/v1/provisioning/policies"
112+
return self.client.PUT(set_notification_policy_tree_path, json=notification_policy_tree)
113+
114+
def get_mute_timings(self):
115+
"""
116+
Gets all mute timings
117+
@return:
118+
"""
119+
get_mute_timings_path = "/v1/provisioning/mute-timings"
120+
return self.client.GET(get_mute_timings_path)
121+
122+
def get_mute_timing(self, mutetiming_name):
123+
"""
124+
Gets single mute timing
125+
@return:
126+
"""
127+
get_mute_timing_path = "/v1/provisioning/mute-timings/%s" % mutetiming_name
128+
return self.client.GET(get_mute_timing_path)
129+
130+
def create_mute_timing(self, mutetiming):
131+
"""
132+
Creates single mute timing
133+
@return:
134+
"""
135+
create_mute_timing_path = "/v1/provisioning/mute-timings"
136+
return self.client.POST(create_mute_timing_path, json=mutetiming)
137+
138+
def update_mute_timing(self, mutetiming_name, mutetiming):
139+
"""
140+
Updates existing mute timing
141+
@return:
142+
"""
143+
update_mute_timing_path = "/v1/provisioning/mute-timings/%s" % mutetiming_name
144+
return self.client.PUT(update_mute_timing_path, json=mutetiming)
145+
146+
def delete_mute_timing(self, mutetiming_name):
147+
"""
148+
Deletes single mute timing
149+
@return:
150+
"""
151+
delete_mute_timing_path = "/v1/provisioning/mute-timings/%s" % mutetiming_name
152+
return self.client.GET(delete_mute_timing_path)
153+
154+
def get_templates(self):
155+
"""
156+
Gets all templates
157+
@return:
158+
"""
159+
get_templates_path = "/v1/provisioning/templates"
160+
return self.client.GET(get_templates_path)
161+
162+
def get_template(self, template_name):
163+
"""
164+
Gets single template
165+
@param template_name:
166+
@return:
167+
"""
168+
get_template_path = "/v1/provisioning/templates/%s" % template_name
169+
return self.client.GET(get_template_path)
170+
171+
def create_or_update_template(self, template_name, template):
172+
"""
173+
Creates or updates (if given template_name exists) template
174+
@param template_name:
175+
@param template:
176+
@return:
177+
"""
178+
create_template_path = "/v1/provisioning/templates/%s" % template_name
179+
return self.client.PUT(create_template_path, json=template)
180+
181+
def delete_template(self, template_name):
182+
"""
183+
Deletes template
184+
@param template_name:
185+
@param template:
186+
@return:
187+
"""
188+
create_template_path = "/v1/provisioning/templates/%s" % template_name
189+
return self.client.DELETE(create_template_path)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import unittest
2+
3+
import requests_mock
4+
5+
from grafana_client import GrafanaApi
6+
7+
ALERTRULE = {
8+
"id": 2,
9+
"uid": "bUUGqLiVk",
10+
"orgID": 1,
11+
"folderUID": "4",
12+
"ruleGroup": "Any",
13+
"title": "ApiAlerts",
14+
"condition": "B",
15+
"data": [],
16+
"updated": "2022-08-17T13:00:21Z",
17+
"noDataState": "NoData",
18+
"execErrState": "Alerting",
19+
"for": 300000000000,
20+
"labels": {"alertGroup": "any", "region": "eu-west-1"},
21+
}
22+
23+
24+
class AlertingProvisioningTestCase(unittest.TestCase):
25+
def setUp(self):
26+
self.grafana = GrafanaApi(("admin", "admin"), host="localhost", url_path_prefix="", protocol="http")
27+
28+
@requests_mock.Mocker()
29+
def test_get_alertrule(self, m):
30+
m.get("http://localhost/api/v1/provisioning/alert-rules/bUUGqLiVk", json=ALERTRULE)
31+
response = self.grafana.alertingprovisioning.get_alertrule("bUUGqLiVk")
32+
self.assertEqual(response["uid"], "bUUGqLiVk")
33+
34+
@requests_mock.Mocker()
35+
def test_delete_alertrule(self, m):
36+
m.delete("http://localhost/api/v1/provisioning/alert-rules/bUUGqLiVk", json={"uid": "bUUGqLiVk"})
37+
response = self.grafana.alertingprovisioning.delete_alertrule("bUUGqLiVk")
38+
self.assertEqual(response["uid"], "bUUGqLiVk")
39+
40+
@requests_mock.Mocker()
41+
def test_create_alertrule(self, m):
42+
m.post(
43+
"http://localhost/api/v1/provisioning/alert-rules",
44+
json=ALERTRULE,
45+
)
46+
47+
response = self.grafana.alertingprovisioning.create_alertrule(ALERTRULE)
48+
self.assertEqual(response["uid"], "bUUGqLiVk")
49+
50+
@requests_mock.Mocker()
51+
def test_update_alertrule(self, m):
52+
m.put(
53+
"http://localhost/api/v1/provisioning/alert-rules/bUUGqLiVk",
54+
json=ALERTRULE,
55+
)
56+
57+
response = self.grafana.alertingprovisioning.update_alertrule(alertrule_uid="bUUGqLiVk", alertrule=ALERTRULE)
58+
self.assertEqual(response["uid"], "bUUGqLiVk")

0 commit comments

Comments
 (0)