-
Notifications
You must be signed in to change notification settings - Fork 66
Expand file tree
/
Copy pathgooddata_api.py
More file actions
323 lines (274 loc) · 11.2 KB
/
gooddata_api.py
File metadata and controls
323 lines (274 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# (C) 2025 GoodData Corporation
"""Interaction with GoodData Cloud via the direct API calls."""
import json
from typing import Any
import requests
TIMEOUT = 60
REQUEST_PAGE_SIZE = 250
API_VERSION = "v1"
class ApiMethods:
headers: dict[str, str]
base_url: str
@staticmethod
def _get_base_url(domain: str) -> str:
"""Returns the root endpoint for the GoodData Cloud API.
Args:
domain (str): The domain of the GoodData Cloud instance.
Returns:
str: The base URL for the GoodData Cloud API.
"""
return f"{domain}/api/{API_VERSION}"
def _get_url(self, endpoint: str) -> str:
"""Returns the full URL for a given API endpoint.
Args:
endpoint (str): The API endpoint to be appended to the base URL.
Returns:
str: The full URL for the API endpoint.
"""
return f"{self.base_url}{endpoint}"
def get_all_workspace_data_filters(
self, workspace_id: str
) -> requests.Response:
"""Gets all workspace data filters for a given workspace.
Args:
workspace_id (str): The ID of the workspace.
Returns:
requests.Response: The response from the server containing all
workspace data filters.
"""
url = f"/entities/workspaces/{workspace_id}/workspaceDataFilters"
return self._get(url)
def get_workspace_data_filter_settings(
self, workspace_id: str
) -> requests.Response:
"""Gets all workspace data filter settings for a given workspace.
Args:
workspace_id (str): The ID of the workspace.
Returns:
requests.Response: The response from the server containing all
workspace data filter settings.
"""
url = f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings?include=workspaceDataFilters"
return self._get(url)
def get_workspace_data_filter_setting(
self, workspace_id: str, wdf_id: str
) -> requests.Response:
"""Gets a specific workspace data filter setting.
Args:
workspace_id (str): The ID of the workspace.
wdf_id (str): The ID of the workspace data filter setting.
Returns:
requests.Response: The response from the server containing the
workspace data filter setting.
"""
url = f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings/{wdf_id}"
return self._get(url)
def put_workspace_data_filter_setting(
self,
workspace_id: str,
wdf_setting: dict[str, Any],
) -> requests.Response:
"""Updates a workspace data filter setting.
Args:
workspace_id (str): The ID of the workspace.
wdf_setting (dict[str, Any]): The workspace data filter setting to
update.
Returns:
requests.Response: The response from the server containing the
updated workspace data filter setting.
"""
wdf_setting_id = wdf_setting["data"]["id"]
endpoint = f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings/{wdf_setting_id}"
return self._put(
endpoint,
wdf_setting,
self.headers,
)
def post_workspace_data_filter_setting(
self,
workspace_id: str,
wdf_setting: dict[str, Any],
) -> requests.Response:
"""Creates a workspace data filter setting for a given workspace.
Args:
workspace_id (str): The ID of the workspace.
wdf_setting (dict[str, Any]): The workspace data filter setting to
create.
Returns:
requests.Response: The response from the server containing the
created workspace data filter setting.
"""
endpoint = (
f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings/"
)
return self._post(
endpoint,
wdf_setting,
self.headers,
)
def delete_workspace_data_filter_setting(
self,
workspace_id: str,
wdf_setting_id: str,
) -> requests.Response:
"""Deletes a workspace data filter setting.
Args:
workspace_id (str): The ID of the workspace.
wdf_setting_id (str): The ID of the workspace data filter setting
to delete.
Returns:
requests.Response: The response from the server confirming the
deletion of the workspace data filter setting.
"""
endpoint = f"/entities/workspaces/{workspace_id}/workspaceDataFilterSettings/{wdf_setting_id}"
return self._delete(
endpoint,
)
def get_user_data_filters(self, workspace_id: str) -> requests.Response:
"""Gets the user data filters for a given workspace."""
endpoint = f"/layout/workspaces/{workspace_id}/userDataFilters"
return self._get(endpoint)
def put_user_data_filters(
self, workspace_id: str, user_data_filters: dict[str, Any]
) -> requests.Response:
"""Puts the user data filters into GoodData workspace."""
headers = {**self.headers, "Content-Type": "application/json"}
return self._put(
f"/layout/workspaces/{workspace_id}/userDataFilters",
user_data_filters,
headers,
)
def get_automations(self, workspace_id: str) -> requests.Response:
"""Gets the automations for a given workspace."""
endpoint = (
f"/entities/workspaces/{workspace_id}/automations?include=ALL"
)
return self._get(endpoint)
def post_automation(
self, workspace_id: str, automation: dict[str, Any]
) -> requests.Response:
"""Posts an automation for a given workspace."""
endpoint = f"/entities/workspaces/{workspace_id}/automations"
return self._post(endpoint, automation)
def delete_automation(
self, workspace_id: str, automation_id: str
) -> requests.Response:
"""Deletes an automation for a given workspace."""
endpoint = (
f"/entities/workspaces/{workspace_id}/automations/{automation_id}"
)
return self._delete(endpoint)
def get_all_metrics(self, workspace_id: str) -> requests.Response:
"""Get all metrics from the specified workspace.
Args:
workspace_id (str): The ID of the workspace to retrieve metrics from.
Returns:
requests.Response: The response containing the metrics.
"""
endpoint = f"/entities/workspaces/{workspace_id}/metrics"
headers = {**self.headers, "X-GDC-VALIDATE-RELATIONS": "true"}
return self._get(endpoint, headers=headers)
def get_all_visualization_objects(
self, workspace_id: str
) -> requests.Response:
"""Get all visualizations from the specified workspace.
Args:
workspace_id (str): The ID of the workspace to retrieve visualizations from.
Returns:
requests.Response: The response containing the visualizations.
"""
endpoint = f"/entities/workspaces/{workspace_id}/visualizationObjects"
headers = {**self.headers, "X-GDC-VALIDATE-RELATIONS": "true"}
return self._get(endpoint, headers=headers)
def get_all_dashboards(self, workspace_id: str) -> requests.Response:
"""Get all dashboards from the specified workspace.
Args:
workspace_id (str): The ID of the workspace to retrieve dashboards from.
Returns:
requests.Response: The response containing the dashboards.
"""
endpoint = f"/entities/workspaces/{workspace_id}/analyticalDashboards"
headers = {**self.headers, "X-GDC-VALIDATE-RELATIONS": "true"}
return self._get(endpoint, headers=headers)
def get_profile(self) -> requests.Response:
"""Returns organization and current user information."""
endpoint = "/profile"
return self._get(endpoint)
def _get(
self, endpoint: str, headers: dict[str, str] | None = None
) -> requests.Response:
"""Sends a GET request to the server.
Args:
endpoint (str): The API endpoint to send the GET request to.
headers (dict[str, str] | None): Headers to include in the request.
If no headers are provided, the default headers will be used.
Returns:
requests.Response: The response from the server.
"""
url = self._get_url(endpoint)
request_headers = headers if headers else self.headers
return requests.get(url, headers=request_headers, timeout=TIMEOUT)
def _post(
self,
endpoint: str,
data: Any,
headers: dict | None = None,
) -> requests.Response:
"""Sends a POST request to the server with a given JSON object.
Args:
endpoint (str): The API endpoint to send the POST request to.
data (Any): The JSON data to send in the request body.
headers (dict | None): Headers to include in the request.
If no headers are provided, the default headers will be used.
Returns:
requests.Response: The response from the server.
"""
url = self._get_url(endpoint)
request_headers = headers if headers else self.headers
data_json = json.dumps(data)
return requests.post(
url, data=data_json, headers=request_headers, timeout=TIMEOUT
)
def _put(
self,
endpoint: str,
data: Any,
headers: dict | None = None,
) -> requests.Response:
"""Sends a PUT request to the server with a given JSON object.
Args:
endpoint (str): The API endpoint to send the PUT request to.
data (Any): The JSON data to send in the request body.
headers (dict | None): Headers to include in the request.
If no headers are provided, the default headers will be used.
Returns:
requests.Response: The response from the server.
"""
url = self._get_url(endpoint)
request_headers = headers if headers else self.headers
data_json = json.dumps(data)
return requests.put(
url, data=data_json, headers=request_headers, timeout=TIMEOUT
)
def _delete(
self,
endpoint: str,
) -> requests.Response:
"""Sends a DELETE request to the server.
Args:
endpoint (str): The API endpoint to send the DELETE request to.
Returns:
requests.Response: The response from the server.
"""
url = self._get_url(endpoint)
return requests.delete(url, headers=self.headers, timeout=TIMEOUT)
@staticmethod
def raise_if_response_not_ok(*responses: requests.Response) -> None:
"""Check if responses from API calls are OK.
Raises ValueError if any response is not OK (status code not 2xx).
"""
for response in responses:
if not response.ok:
raise ValueError(
f"Request to {response.url} failed with status code {response.status_code}: {response.text}"
)