Skip to content

Commit 42e6e14

Browse files
authored
Merge 4071e79 into ca148ea
2 parents ca148ea + 4071e79 commit 42e6e14

File tree

5 files changed

+239
-9
lines changed

5 files changed

+239
-9
lines changed

docs/content/grafana_api/folder.md

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* [get\_folder\_by\_id](#folder.Folder.get_folder_by_id)
88
* [create\_folder](#folder.Folder.create_folder)
99
* [update\_folder](#folder.Folder.update_folder)
10+
* [move\_folder](#folder.Folder.move_folder)
1011
* [delete\_folder](#folder.Folder.delete_folder)
1112
* [get\_folder\_permissions](#folder.Folder.get_folder_permissions)
1213
* [update\_folder\_permissions](#folder.Folder.update_folder_permissions)
@@ -46,6 +47,10 @@ def get_folders() -> list
4647

4748
The method includes a functionality to extract all folders inside the organization
4849

50+
Required Permissions:
51+
Action: folders:read
52+
Scope: folders:*
53+
4954
**Raises**:
5055

5156
- `Exception` - Unspecified error by executing the API call
@@ -69,6 +74,10 @@ The method includes a functionality to extract all folder information specified
6974

7075
- `uid` _str_ - Specify the uid of the folder
7176

77+
Required Permissions:
78+
- `Action` - folders:read
79+
- `Scope` - folders:*
80+
7281

7382
**Raises**:
7483

@@ -94,6 +103,10 @@ The method includes a functionality to extract all folder information specified
94103

95104
- `id` _int_ - Specify the id of the folder
96105

106+
Required Permissions:
107+
- `Action` - folders:read
108+
- `Scope` - folders:*
109+
97110

98111
**Raises**:
99112

@@ -110,7 +123,7 @@ The method includes a functionality to extract all folder information specified
110123
#### create\_folder
111124

112125
```python
113-
def create_folder(title: str, uid: str = None) -> dict
126+
def create_folder(title: str, uid: str = None, parent_uid: str = None) -> dict
114127
```
115128

116129
The method includes a functionality to create a new folder inside the organization specified by the defined title and the optional uid
@@ -119,6 +132,11 @@ The method includes a functionality to create a new folder inside the organizati
119132

120133
- `title` _str_ - Specify the title of the folder
121134
- `uid` _str_ - Specify the uid of the folder (default None)
135+
- `parent_uid` _str_ - Specify the parent_uid of the folder (default None)
136+
137+
Required Permissions:
138+
- `Action` - folders:create, folders:write
139+
- `Scope` - folders:*
122140

123141

124142
**Raises**:
@@ -151,6 +169,10 @@ The method includes a functionality to update a folder information inside the or
151169
- `version` _int_ - Specify the version of the folder (default 0)
152170
- `overwrite` _bool_ - Should the already existing folder information be overwritten (default False)
153171

172+
Required Permissions:
173+
- `Action` - folders:write
174+
- `Scope` - folders:*
175+
154176

155177
**Raises**:
156178

@@ -162,6 +184,36 @@ The method includes a functionality to update a folder information inside the or
162184

163185
- `api_call` _dict_ - Returns an updated folder
164186

187+
<a id="folder.Folder.move_folder"></a>
188+
189+
#### move\_folder
190+
191+
```python
192+
def move_folder(uid: str, parent_uid: str = None)
193+
```
194+
195+
The method includes a functionality to move a folder inside the organization specified by the defined uid. This feature is only relevant if nested folders are enabled
196+
197+
**Arguments**:
198+
199+
- `uid` _str_ - Specify the uid of the folder
200+
- `parent_uid` _str_ - Specify the parent_uid of the folder. If the value is None, then the folder is moved under the root (default None)
201+
202+
Required Permissions:
203+
- `Action` - folders:create, folders:write
204+
- `Scope` - folders:*, folders:uid:<destination folder UID>
205+
206+
207+
**Raises**:
208+
209+
- `ValueError` - Missed specifying a necessary value
210+
- `Exception` - Unspecified error by executing the API call
211+
212+
213+
**Returns**:
214+
215+
- `api_call` _dict_ - Returns the moved folder
216+
165217
<a id="folder.Folder.delete_folder"></a>
166218

167219
#### delete\_folder
@@ -176,6 +228,10 @@ The method includes a functionality to delete a folder inside the organization s
176228

177229
- `uid` _str_ - Specify the uid of the folder
178230

231+
Required Permissions:
232+
- `Action` - folders:delete
233+
- `Scope` - folders:*
234+
179235

180236
**Raises**:
181237

@@ -201,6 +257,10 @@ The method includes a functionality to extract the folder permissions inside the
201257

202258
- `uid` _str_ - Specify the uid of the folder
203259

260+
Required Permissions:
261+
- `Action` - folders.permissions:read
262+
- `Scope` - folders:*
263+
204264

205265
**Raises**:
206266

@@ -227,6 +287,10 @@ The method includes a functionality to update the folder permissions based on th
227287
- `uid` _str_ - Specify the uid of the folder
228288
- `permission_json` _dict_ - Specify the inserted permissions as dict
229289

290+
Required Permissions:
291+
- `Action` - folders.permissions:write
292+
- `Scope` - folders:*
293+
230294

231295
**Raises**:
232296

grafana_api/folder.py

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ def __init__(self, grafana_api_model: APIModel):
2323
def get_folders(self) -> list:
2424
"""The method includes a functionality to extract all folders inside the organization
2525
26+
Required Permissions:
27+
Action: folders:read
28+
Scope: folders:*
29+
2630
Raises:
2731
Exception: Unspecified error by executing the API call
2832
@@ -46,6 +50,10 @@ def get_folder_by_uid(self, uid: str) -> dict:
4650
Args:
4751
uid (str): Specify the uid of the folder
4852
53+
Required Permissions:
54+
Action: folders:read
55+
Scope: folders:*
56+
4957
Raises:
5058
ValueError: Missed specifying a necessary value
5159
Exception: Unspecified error by executing the API call
@@ -74,6 +82,10 @@ def get_folder_by_id(self, id: int) -> dict:
7482
Args:
7583
id (int): Specify the id of the folder
7684
85+
Required Permissions:
86+
Action: folders:read
87+
Scope: folders:*
88+
7789
Raises:
7890
ValueError: Missed specifying a necessary value
7991
Exception: Unspecified error by executing the API call
@@ -96,12 +108,17 @@ def get_folder_by_id(self, id: int) -> dict:
96108
logging.error("There is no folder id defined.")
97109
raise ValueError
98110

99-
def create_folder(self, title: str, uid: str = None) -> dict:
111+
def create_folder(self, title: str, uid: str = None, parent_uid: str = None) -> dict:
100112
"""The method includes a functionality to create a new folder inside the organization specified by the defined title and the optional uid
101113
102114
Args:
103115
title (str): Specify the title of the folder
104116
uid (str): Specify the uid of the folder (default None)
117+
parent_uid (str): Specify the parent_uid of the folder (default None)
118+
119+
Required Permissions:
120+
Action: folders:create, folders:write
121+
Scope: folders:*
105122
106123
Raises:
107124
ValueError: Missed specifying a necessary value
@@ -118,6 +135,9 @@ def create_folder(self, title: str, uid: str = None) -> dict:
118135
if uid is not None and len(uid) != 0:
119136
folder_information.update({"uid": uid})
120137

138+
if parent_uid is not None and len(parent_uid) != 0:
139+
folder_information.update({"parentUid": parent_uid})
140+
121141
api_call: dict = Api(self.grafana_api_model).call_the_api(
122142
APIEndpoints.FOLDERS.value,
123143
RequestsMethods.POST,
@@ -144,6 +164,10 @@ def update_folder(
144164
version (int): Specify the version of the folder (default 0)
145165
overwrite (bool): Should the already existing folder information be overwritten (default False)
146166
167+
Required Permissions:
168+
Action: folders:write
169+
Scope: folders:*
170+
147171
Raises:
148172
ValueError: Missed specifying a necessary value
149173
Exception: Unspecified error by executing the API call
@@ -179,12 +203,57 @@ def update_folder(
179203
logging.error("There is no folder title, version or uid defined.")
180204
raise ValueError
181205

206+
def move_folder(self, uid: str, parent_uid: str = None):
207+
"""The method includes a functionality to move a folder inside the organization specified by the defined uid. This feature is only relevant if nested folders are enabled
208+
209+
Args:
210+
uid (str): Specify the uid of the folder
211+
parent_uid (str): Specify the parent_uid of the folder. If the value is None, then the folder is moved under the root (default None)
212+
213+
Required Permissions:
214+
Action: folders:create, folders:write
215+
Scope: folders:*, folders:uid:<destination folder UID>
216+
217+
Raises:
218+
ValueError: Missed specifying a necessary value
219+
Exception: Unspecified error by executing the API call
220+
221+
Returns:
222+
api_call (dict): Returns the moved folder
223+
"""
224+
225+
if len(uid) != 0:
226+
folder_information: dict = dict()
227+
228+
if parent_uid is not None and len(parent_uid) != 0:
229+
folder_information.update({"parentUid": parent_uid})
230+
231+
api_call = Api(self.grafana_api_model).call_the_api(
232+
f"{APIEndpoints.FOLDERS.value}/{uid}/move",
233+
RequestsMethods.POST,
234+
json.dumps(folder_information),
235+
)
236+
237+
if api_call == dict() or api_call.get("id") is None:
238+
logging.error(f"Please, check the error: {api_call}.")
239+
raise Exception
240+
else:
241+
return api_call
242+
else:
243+
logging.error("There is no folder uid defined.")
244+
raise ValueError
245+
246+
182247
def delete_folder(self, uid: str):
183248
"""The method includes a functionality to delete a folder inside the organization specified by the defined uid
184249
185250
Args:
186251
uid (str): Specify the uid of the folder
187252
253+
Required Permissions:
254+
Action: folders:delete
255+
Scope: folders:*
256+
188257
Raises:
189258
ValueError: Missed specifying a necessary value
190259
Exception: Unspecified error by executing the API call
@@ -220,6 +289,10 @@ def get_folder_permissions(self, uid: str) -> list:
220289
Args:
221290
uid (str): Specify the uid of the folder
222291
292+
Required Permissions:
293+
Action: folders.permissions:read
294+
Scope: folders:*
295+
223296
Raises:
224297
ValueError: Missed specifying a necessary value
225298
Exception: Unspecified error by executing the API call
@@ -250,6 +323,10 @@ def update_folder_permissions(self, uid: str, permission_json: dict):
250323
uid (str): Specify the uid of the folder
251324
permission_json (dict): Specify the inserted permissions as dict
252325
326+
Required Permissions:
327+
Action: folders.permissions:write
328+
Scope: folders:*
329+
253330
Raises:
254331
ValueError: Missed specifying a necessary value
255332
Exception: Unspecified error by executing the API call

tests/integrationtest/test_folder.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,35 @@ def test_a_create_folder(self):
6969

7070
self.assertEqual("test1", self.folder.get_folders()[1].get("title"))
7171

72-
def test_b_update_folder(self):
72+
def test_b_subfolder(self):
73+
parent_uid = self.folder.get_folders()[1].get("uid")
74+
75+
subfolder: dict = self.folder.create_folder("test2", parent_uid=parent_uid)
76+
77+
self.assertEqual("test2", self.folder.get_folder_by_uid(subfolder["uid"]).get("title"))
78+
79+
def test_c_update_folder(self):
7380
self.folder.update_folder(
7481
"test2", self.folder.get_folders()[1].get("uid"), version=1
7582
)
7683

7784
self.assertEqual("test2", self.folder.get_folders()[1].get("title"))
7885

79-
def test_c_delete_folder(self):
86+
def test_d_move_folder(self):
87+
parent_uid = self.folder.get_folders()[1].get("uid")
88+
89+
folder_uid_a = self.folder.create_folder("test11", parent_uid=parent_uid)["uid"]
90+
folder_uid_b = self.folder.create_folder("test12")["uid"]
91+
92+
self.assertEqual("test12", self.folder.get_folder_by_uid(folder_uid_b)["title"])
93+
94+
moved_folder: dict = self.folder.move_folder(folder_uid_a, parent_uid=folder_uid_b)
95+
96+
self.assertEqual("test12", moved_folder["parents"][0]["title"])
97+
self.folder.delete_folder(moved_folder["parents"][0]["uid"])
98+
99+
100+
def test_e_delete_folder(self):
80101
self.folder.delete_folder(self.folder.get_folders()[1].get("uid"))
81102

82103
self.assertEqual(1, len(self.folder.get_folders()))
@@ -110,7 +131,7 @@ def test_get_folder_permissions(self):
110131
self.folder.get_folder_permissions("6U_QdWJnz"),
111132
)
112133

113-
def test_d_update_folder_permissions(self):
134+
def test_f_update_folder_permissions(self):
114135
permission_dict: dict = dict({"items": [{"role": "Viewer", "permission": 2}]})
115136

116137
self.folder.update_folder_permissions("6U_QdWJnz", permission_dict)

tests/unittests/test_alerting.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ def test_test_backtest_rule(self, call_the_api_mock):
738738
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
739739
alerting: Alerting = Alerting(grafana_api_model=model)
740740
datasource_rule_query: DatasourceRuleQuery = DatasourceRuleQuery(
741-
"test", {"test": "test"}, "test", "test", {"test": "test"}
741+
"test", {"test": "test"}, "datasourceUid", "test", {"test": "test"}
742742
)
743743

744744
call_the_api_mock.return_value = dict({"test": "test"})
@@ -756,17 +756,30 @@ def test_test_backtest_rule_no_condition(self):
756756
alerting.test_backtest_rule("", list())
757757

758758
@patch("grafana_api.api.Api.call_the_api")
759-
def test_test_recipient_rule_test_not_possible(self, call_the_api_mock):
759+
def test_test_backtest_rule_no_fields(self, call_the_api_mock):
760760
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
761761
alerting: Alerting = Alerting(grafana_api_model=model)
762762
datasource_rule_query: DatasourceRuleQuery = DatasourceRuleQuery(
763-
"test", {"test": "test"}, "test", "test", {"test": "test"}
763+
"test", {"test": "test"}, "datasourceUid", "test", {"test": "test"}
764+
)
765+
766+
call_the_api_mock.return_value = dict()
767+
768+
with self.assertRaises(Exception):
769+
alerting.test_backtest_rule("test", [datasource_rule_query])
770+
771+
@patch("grafana_api.api.Api.call_the_api")
772+
def test_test_datasource_uid_rule_test_not_possible(self, call_the_api_mock):
773+
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
774+
alerting: Alerting = Alerting(grafana_api_model=model)
775+
datasource_rule_query: DatasourceRuleQuery = DatasourceRuleQuery(
776+
"test", {"test": "test"}, "datasourceUid", "test", {"test": "test"}
764777
)
765778

766779
call_the_api_mock.return_value = dict()
767780

768781
with self.assertRaises(Exception):
769-
alerting.test_recipient_rule("test", "test", [datasource_rule_query])
782+
alerting.test_datasource_uid_rule("test", "test", [datasource_rule_query])
770783

771784
@patch("grafana_api.api.Api.call_the_api")
772785
def test_delete_ngalert_organization_configuration(self, call_the_api_mock):

0 commit comments

Comments
 (0)