peak-sdk 1.4.0__py3-none-any.whl → 1.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. peak/_metadata.py +58 -3
  2. peak/_version.py +1 -1
  3. peak/cli/cli.py +4 -2
  4. peak/cli/helpers.py +2 -0
  5. peak/cli/press/blocks/specs.py +2 -2
  6. peak/cli/press/specs.py +4 -2
  7. peak/cli/resources/alerts/__init__.py +35 -0
  8. peak/cli/resources/alerts/emails.py +360 -0
  9. peak/cli/resources/images.py +1 -1
  10. peak/cli/resources/services.py +23 -0
  11. peak/cli/resources/users.py +71 -0
  12. peak/cli/resources/workflows.py +77 -15
  13. peak/cli/ruff.toml +5 -3
  14. peak/compression.py +2 -2
  15. peak/exceptions.py +4 -6
  16. peak/handler.py +3 -5
  17. peak/helpers.py +35 -9
  18. peak/output.py +2 -2
  19. peak/press/apps.py +8 -16
  20. peak/press/blocks.py +8 -16
  21. peak/press/deployments.py +2 -4
  22. peak/press/specs.py +12 -14
  23. peak/resources/__init__.py +3 -2
  24. peak/resources/alerts.py +309 -0
  25. peak/resources/artifacts.py +2 -4
  26. peak/resources/images.py +8 -14
  27. peak/resources/services.py +7 -6
  28. peak/resources/users.py +93 -0
  29. peak/resources/webapps.py +3 -5
  30. peak/resources/workflows.py +106 -16
  31. peak/sample_yaml/resources/emails/send_email.yaml +15 -0
  32. peak/sample_yaml/resources/services/create_or_update_service.yaml +1 -0
  33. peak/sample_yaml/resources/services/create_service.yaml +1 -0
  34. peak/sample_yaml/resources/services/update_service.yaml +1 -0
  35. peak/sample_yaml/resources/workflows/create_or_update_workflow.yaml +28 -0
  36. peak/sample_yaml/resources/workflows/create_workflow.yaml +10 -0
  37. peak/sample_yaml/resources/workflows/patch_workflow.yaml +28 -0
  38. peak/sample_yaml/resources/workflows/update_workflow.yaml +28 -0
  39. peak/session.py +7 -4
  40. peak/telemetry.py +1 -1
  41. peak/template.py +6 -4
  42. peak/tools/logging/__init__.py +26 -268
  43. peak/tools/logging/log_level.py +35 -3
  44. peak/tools/logging/logger.py +389 -0
  45. peak/validators.py +34 -2
  46. {peak_sdk-1.4.0.dist-info → peak_sdk-1.6.0.dist-info}/METADATA +11 -12
  47. {peak_sdk-1.4.0.dist-info → peak_sdk-1.6.0.dist-info}/RECORD +50 -43
  48. {peak_sdk-1.4.0.dist-info → peak_sdk-1.6.0.dist-info}/WHEEL +1 -1
  49. {peak_sdk-1.4.0.dist-info → peak_sdk-1.6.0.dist-info}/LICENSE +0 -0
  50. {peak_sdk-1.4.0.dist-info → peak_sdk-1.6.0.dist-info}/entry_points.txt +0 -0
peak/press/specs.py CHANGED
@@ -19,6 +19,7 @@
19
19
  # # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
20
20
  #
21
21
  """Specs client module."""
22
+
22
23
  from __future__ import annotations
23
24
 
24
25
  from typing import Any, Dict, Iterator, List, Literal, Optional, overload
@@ -46,8 +47,7 @@ class Spec(BaseClient):
46
47
  page_number: Optional[int] = None,
47
48
  *,
48
49
  return_iterator: Literal[False],
49
- ) -> Dict[str, Any]:
50
- ...
50
+ ) -> Dict[str, Any]: ...
51
51
 
52
52
  @overload
53
53
  def list_specs(
@@ -62,8 +62,7 @@ class Spec(BaseClient):
62
62
  page_number: Optional[int] = None,
63
63
  *,
64
64
  return_iterator: Literal[True] = True,
65
- ) -> Iterator[Dict[str, Any]]:
66
- ...
65
+ ) -> Iterator[Dict[str, Any]]: ...
67
66
 
68
67
  def list_specs(
69
68
  self,
@@ -144,7 +143,7 @@ class Spec(BaseClient):
144
143
  def list_spec_release_deployments(
145
144
  self,
146
145
  spec_id: str,
147
- version: str,
146
+ version: Optional[str],
148
147
  status: Optional[List[str]] = None,
149
148
  name: Optional[str] = None,
150
149
  title: Optional[str] = None,
@@ -153,14 +152,13 @@ class Spec(BaseClient):
153
152
  page_number: Optional[int] = None,
154
153
  *,
155
154
  return_iterator: Literal[False],
156
- ) -> Dict[str, Any]:
157
- ...
155
+ ) -> Dict[str, Any]: ...
158
156
 
159
157
  @overload
160
158
  def list_spec_release_deployments(
161
159
  self,
162
160
  spec_id: str,
163
- version: str,
161
+ version: Optional[str],
164
162
  status: Optional[List[str]] = None,
165
163
  name: Optional[str] = None,
166
164
  title: Optional[str] = None,
@@ -169,13 +167,12 @@ class Spec(BaseClient):
169
167
  page_number: Optional[int] = None,
170
168
  *,
171
169
  return_iterator: Literal[True] = True,
172
- ) -> Iterator[Dict[str, Any]]:
173
- ...
170
+ ) -> Iterator[Dict[str, Any]]: ...
174
171
 
175
172
  def list_spec_release_deployments(
176
173
  self,
177
174
  spec_id: str,
178
- version: str,
175
+ version: Optional[str],
179
176
  status: Optional[List[str]] = None,
180
177
  name: Optional[str] = None,
181
178
  title: Optional[str] = None,
@@ -188,11 +185,11 @@ class Spec(BaseClient):
188
185
  """Get all deployments of a App or Block spec release (ordered by most recently created to oldest).
189
186
 
190
187
  REFERENCE:
191
- 🔗 `API Documentation <https://press.peak.ai/api-docs/index.htm#/Specs/get_v1_specs__specId__releases__version__deployments>`__
188
+ 🔗 `API Documentation <https://press.peak.ai/api-docs/index.htm#/Specs/get_v1_specs__specId__releases_deployments>`__
192
189
 
193
190
  Args:
194
191
  spec_id (str): The ID of the App or Block spec.
195
- version (str): The release version of the spec in valid semantic versioning format.
192
+ version (str | None): The release version of the spec in valid semantic versioning format. If not provided, all deployments are returned.
196
193
  status (List[str] | None): List of statuses to filter deployments.
197
194
  Valid values are `deleting`, `delete_failed`, `deployed`, `deploying`, `failed`, `platform_resource_error`, `redeploying`, `rollback`, `rollback_complete`, `rollback_failed` and `warning`.
198
195
  name (str | None): String to filter deployments by name.
@@ -218,13 +215,14 @@ class Spec(BaseClient):
218
215
  InternalServerErrorException: the server encountered an unexpected condition that
219
216
  prevented it from fulfilling the request.
220
217
  """
221
- method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/{spec_id}/releases/{version}/deployments"
218
+ method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/{spec_id}/releases/deployments"
222
219
 
223
220
  params: Dict[str, Any] = {
224
221
  "status": status,
225
222
  "name": name,
226
223
  "title": title,
227
224
  "sort": sort,
225
+ "version": version,
228
226
  "pageSize": page_size,
229
227
  }
230
228
 
@@ -19,10 +19,11 @@
19
19
  # # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
20
20
  #
21
21
  """This module exports all platform resources from the `Peak-Platform`."""
22
+
22
23
  from __future__ import annotations
23
24
 
24
25
  from typing import List
25
26
 
26
- from peak.resources import artifacts, images, services, tenants, webapps, workflows
27
+ from peak.resources import alerts, artifacts, images, services, tenants, users, webapps, workflows
27
28
 
28
- __all__: List[str] = ["workflows", "images", "artifacts", "webapps", "tenants", "services"]
29
+ __all__: List[str] = ["alerts", "artifacts", "images", "services", "tenants", "users", "webapps", "workflows"]
@@ -0,0 +1,309 @@
1
+ #
2
+ # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
3
+ # #
4
+ # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # # may not use this file except in compliance with the License. A copy of
6
+ # # the License is located at:
7
+ # #
8
+ # # https://github.com/PeakBI/peak-sdk/blob/main/LICENSE
9
+ # #
10
+ # # or in the "license" file accompanying this file. This file is
11
+ # # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # # ANY KIND, either express or implied. See the License for the specific
13
+ # # language governing permissions and limitations under the License.
14
+ # #
15
+ # # This file is part of the peak-sdk.
16
+ # # see (https://github.com/PeakBI/peak-sdk)
17
+ # #
18
+ # # You should have received a copy of the APACHE LICENSE, VERSION 2.0
19
+ # # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
20
+ #
21
+
22
+ """Alerts client module."""
23
+
24
+ from __future__ import annotations
25
+
26
+ from typing import Any, Dict, Iterator, List, Literal, Optional, overload
27
+
28
+ from peak.base_client import BaseClient
29
+ from peak.constants import ContentType, HttpMethods
30
+ from peak.session import Session
31
+
32
+
33
+ class Alert(BaseClient):
34
+ """Client class for interacting with alerts resource."""
35
+
36
+ BASE_ENDPOINT = "notifications/api/v1"
37
+
38
+ @overload
39
+ def list_emails(
40
+ self,
41
+ date_from: Optional[str] = None,
42
+ date_to: Optional[str] = None,
43
+ page_size: Optional[int] = None,
44
+ page_number: Optional[int] = None,
45
+ count: Optional[int] = None,
46
+ *,
47
+ return_iterator: Literal[False],
48
+ ) -> Dict[str, Any]: ...
49
+
50
+ @overload
51
+ def list_emails(
52
+ self,
53
+ date_from: Optional[str] = None,
54
+ date_to: Optional[str] = None,
55
+ page_size: Optional[int] = None,
56
+ page_number: Optional[int] = None,
57
+ count: Optional[int] = None,
58
+ *,
59
+ return_iterator: Literal[True] = True,
60
+ ) -> Iterator[Dict[str, Any]]: ...
61
+
62
+ def list_emails(
63
+ self,
64
+ date_from: Optional[str] = None,
65
+ date_to: Optional[str] = None,
66
+ page_size: Optional[int] = None,
67
+ page_number: Optional[int] = None,
68
+ count: Optional[int] = None,
69
+ *,
70
+ return_iterator: bool = True,
71
+ ) -> Iterator[Dict[str, Any]] | Dict[str, Any]:
72
+ """Retrieve the history of emails sent.
73
+
74
+ REFERENCE:
75
+ 🔗 `API Documentation <https://service.peak.ai/notifications/api-docs/index.htm#/emails/get_api_v1_emails>`__
76
+
77
+ Args:
78
+ date_from (str | None): The date after which the emails should be included (in ISO format).
79
+ It is 90 days from current date by default.
80
+ date_to (str | None): The date till which the emails should be included (in ISO format).
81
+ It is current date by default.
82
+ page_size (int | None): Number of emails to retrieve per page. It is 25 by default.
83
+ page_number (int | None): Page number to retrieve. Only used when return_iterator is False.
84
+ count (int | None): Number of emails required (Ordered by latest to earliest).
85
+ For example, if 5 is provided, it will return last 5 emails.
86
+ It is -1 by default which means it will return all the available emails within the given dates.
87
+ return_iterator (bool): Whether to return an iterator object or list of emails for a specified page number, defaults to True.
88
+
89
+ Returns:
90
+ Iterator[Dict[str, Any]] | Dict[str, Any]: an iterator object which returns an element per iteration, until there are no more elements to return.
91
+ If `return_iterator` is set to False, a dictionary containing the list and pagination details is returned instead.
92
+
93
+ Set `return_iterator` to True if you want automatic client-side pagination, or False if you want server-side pagination.
94
+
95
+ Raises:
96
+ BadRequestException: The given request parameters are invalid.
97
+ UnauthorizedException: The credentials are invalid.
98
+ ForbiddenException: The user does not have permission to perform the operation.
99
+ InternalServerErrorException: The server failed to process the request.
100
+ """
101
+ method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/emails"
102
+
103
+ params: Dict[str, Any] = {
104
+ "dateTo": date_to,
105
+ "dateFrom": date_from,
106
+ "pageSize": page_size,
107
+ "count": -1 if count is None else count,
108
+ }
109
+
110
+ if return_iterator:
111
+ return self.session.create_generator_request(
112
+ endpoint,
113
+ method,
114
+ content_type=ContentType.APPLICATION_JSON,
115
+ response_key="emails",
116
+ params=params,
117
+ )
118
+
119
+ return self.session.create_request( # type: ignore[no-any-return]
120
+ endpoint,
121
+ method,
122
+ content_type=ContentType.APPLICATION_JSON,
123
+ params={**params, "pageNumber": page_number},
124
+ )
125
+
126
+ def send_email(
127
+ self,
128
+ body: Dict[str, Any],
129
+ ) -> Dict[str, Any]:
130
+ """Send an email to the specified recipients using the specified template.
131
+
132
+ REFERENCE:
133
+ 🔗 `API Documentation <https://service.peak.ai/notifications/api-docs/index.htm#/Emails/post_api_v1_emails>`__
134
+
135
+ Args:
136
+ body (Dict[str, Any]): A dictionary containing the details of the email to send.
137
+
138
+ Returns:
139
+ Dict[str, Any]: A dictionary containing the ID of the email sent.
140
+
141
+ SCHEMA:
142
+ .. code-block:: json
143
+
144
+ {
145
+ "recipients": ["string"],
146
+ "cc": ["string"],
147
+ "bcc": ["string"],
148
+ "subject": "string",
149
+ "templateName": "string",
150
+ "templateParameters": {
151
+ "string": "string"
152
+ }
153
+ }
154
+
155
+ Raises:
156
+ UnauthorizedException: The credentials are invalid.
157
+ ForbiddenException: The user does not have permission to perform the operation.
158
+ NotFoundException: The given feature does not exist.
159
+ UnprocessableEntityException: The server was unable to process the request.
160
+ InternalServerErrorException: The server failed to process the request.
161
+ """
162
+ method, endpoint = HttpMethods.POST, f"{self.BASE_ENDPOINT}/emails"
163
+
164
+ return self.session.create_request( # type: ignore[no-any-return]
165
+ endpoint,
166
+ method,
167
+ body=body,
168
+ content_type=ContentType.APPLICATION_JSON,
169
+ )
170
+
171
+ def describe_email(self, email_id: int) -> Dict[str, Any]:
172
+ """Retrieve the details of a specific email.
173
+
174
+ REFERENCE:
175
+ 🔗 `API Documentation <https://service.peak.ai/notifications/api-docs/index.htm#/Emails/get_api_v1_emails__id_>`__
176
+
177
+ Args:
178
+ email_id (int): The ID of the email to retrieve.
179
+
180
+ Returns:
181
+ Dict[str, Any]: A dictionary containing the details of the email.
182
+
183
+ Raises:
184
+ UnauthorizedException: The credentials are invalid.
185
+ ForbiddenException: The user does not have permission to perform the operation.
186
+ NotFoundException: Email with the given ID does not exist.
187
+ UnprocessableEntityException: The server was unable to process the request.
188
+ InternalServerErrorException: The server failed to process the request.
189
+ """
190
+ method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/emails/{email_id}"
191
+
192
+ return self.session.create_request(endpoint, method, content_type=ContentType.APPLICATION_JSON) # type: ignore[no-any-return]
193
+
194
+ @overload
195
+ def list_templates(
196
+ self,
197
+ page_size: Optional[int] = None,
198
+ page_number: Optional[int] = None,
199
+ name: Optional[str] = None,
200
+ scope: Optional[List[str]] = None,
201
+ *,
202
+ return_iterator: Literal[False],
203
+ ) -> Dict[str, Any]: ...
204
+
205
+ @overload
206
+ def list_templates(
207
+ self,
208
+ page_size: Optional[int] = None,
209
+ page_number: Optional[int] = None,
210
+ name: Optional[str] = None,
211
+ scope: Optional[List[str]] = None,
212
+ *,
213
+ return_iterator: Literal[True] = True,
214
+ ) -> Iterator[Dict[str, Any]]: ...
215
+
216
+ def list_templates(
217
+ self,
218
+ page_size: Optional[int] = None,
219
+ page_number: Optional[int] = None,
220
+ name: Optional[str] = None,
221
+ scope: Optional[List[str]] = None,
222
+ *,
223
+ return_iterator: bool = True,
224
+ ) -> Iterator[Dict[str, Any]] | Dict[str, Any]:
225
+ """Retrieve the history of emails sent.
226
+
227
+ REFERENCE:
228
+ 🔗 `API Documentation <https://service.peak.ai/notifications/api-docs/index.htm#/Templates/get_api_v1_emails_templates>`__
229
+
230
+ Args:
231
+ name (str | None): The name of the email template
232
+ scope (List[str] | None): Filter out on the basis of the type of the template - global or custom.
233
+ page_size (int | None): Number of emails to retrieve per page. It is 25 by default.
234
+ page_number (int | None): Page number to retrieve. Only used when return_iterator is False.
235
+ return_iterator (bool): Whether to return an iterator object or list of emails for a specified page number, defaults to True.
236
+
237
+ Returns:
238
+ Iterator[Dict[str, Any]] | Dict[str, Any]: an iterator object which returns an element per iteration, until there are no more elements to return.
239
+ If `return_iterator` is set to False, a dictionary containing the list and pagination details is returned instead.
240
+
241
+ Set `return_iterator` to True if you want automatic client-side pagination, or False if you want server-side pagination.
242
+
243
+ Raises:
244
+ BadRequestException: The given request parameters are invalid.
245
+ UnauthorizedException: The credentials are invalid.
246
+ ForbiddenException: The user does not have permission to perform the operation.
247
+ InternalServerErrorException: The server failed to process the request.
248
+ """
249
+ method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/emails/templates"
250
+
251
+ params: Dict[str, Any] = {
252
+ "searchTerm": name,
253
+ "scope": scope,
254
+ "pageSize": page_size,
255
+ }
256
+
257
+ if return_iterator:
258
+ return self.session.create_generator_request(
259
+ endpoint,
260
+ method,
261
+ content_type=ContentType.APPLICATION_JSON,
262
+ response_key="templates",
263
+ params=params,
264
+ )
265
+
266
+ return self.session.create_request( # type: ignore[no-any-return]
267
+ endpoint,
268
+ method,
269
+ content_type=ContentType.APPLICATION_JSON,
270
+ params={**params, "pageNumber": page_number},
271
+ )
272
+
273
+ def describe_template(self, template_name: str) -> Dict[str, Any]:
274
+ """Retrieve the details of a specific template.
275
+
276
+ REFERENCE:
277
+ 🔗 `API Documentation <https://service.peak.ai/notifications/api-docs/index.htm#/Templates/get_api_v1_emails_templates__name_>`__
278
+
279
+ Args:
280
+ template_name (str): The name of the template to retrieve.
281
+
282
+ Returns:
283
+ Dict[str, Any]: A dictionary containing the details of the template.
284
+
285
+ Raises:
286
+ UnauthorizedException: The credentials are invalid.
287
+ ForbiddenException: The user does not have permission to perform the operation.
288
+ NotFoundException: Email with the given ID does not exist.
289
+ UnprocessableEntityException: The server was unable to process the request.
290
+ InternalServerErrorException: The server failed to process the request.
291
+ """
292
+ method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/emails/templates/{template_name}"
293
+
294
+ return self.session.create_request(endpoint, method, content_type=ContentType.APPLICATION_JSON) # type: ignore[no-any-return]
295
+
296
+
297
+ def get_client(session: Optional[Session] = None) -> Alert:
298
+ """Returns a Alert client, If no session is provided, a default session is used.
299
+
300
+ Args:
301
+ session (Optional[Session]): A Session Object. Default is None.
302
+
303
+ Returns:
304
+ Alert: The alert client object.
305
+ """
306
+ return Alert(session)
307
+
308
+
309
+ __all__ = ["get_client"]
@@ -40,8 +40,7 @@ class Artifact(BaseClient):
40
40
  page_number: Optional[int] = None,
41
41
  *,
42
42
  return_iterator: Literal[False],
43
- ) -> Dict[str, Any]:
44
- ...
43
+ ) -> Dict[str, Any]: ...
45
44
 
46
45
  @overload
47
46
  def list_artifacts(
@@ -50,8 +49,7 @@ class Artifact(BaseClient):
50
49
  page_number: Optional[int] = None,
51
50
  *,
52
51
  return_iterator: Literal[True] = True,
53
- ) -> Iterator[Dict[str, Any]]:
54
- ...
52
+ ) -> Iterator[Dict[str, Any]]: ...
55
53
 
56
54
  def list_artifacts(
57
55
  self,
peak/resources/images.py CHANGED
@@ -55,8 +55,7 @@ class Image(BaseClient):
55
55
  tags: Optional[List[str]] = None,
56
56
  *,
57
57
  return_iterator: Literal[False],
58
- ) -> Dict[str, Any]:
59
- ...
58
+ ) -> Dict[str, Any]: ...
60
59
 
61
60
  @overload
62
61
  def list_images(
@@ -70,8 +69,7 @@ class Image(BaseClient):
70
69
  tags: Optional[List[str]] = None,
71
70
  *,
72
71
  return_iterator: Literal[True] = True,
73
- ) -> Iterator[Dict[str, Any]]:
74
- ...
72
+ ) -> Iterator[Dict[str, Any]]: ...
75
73
 
76
74
  def list_images(
77
75
  self,
@@ -152,8 +150,7 @@ class Image(BaseClient):
152
150
  tags: Optional[List[str]] = None,
153
151
  *,
154
152
  return_iterator: Literal[False],
155
- ) -> Dict[str, Any]:
156
- ...
153
+ ) -> Dict[str, Any]: ...
157
154
 
158
155
  @overload
159
156
  def list_image_versions(
@@ -167,8 +164,7 @@ class Image(BaseClient):
167
164
  tags: Optional[List[str]] = None,
168
165
  *,
169
166
  return_iterator: Literal[True] = True,
170
- ) -> Iterator[Dict[str, Any]]:
171
- ...
167
+ ) -> Iterator[Dict[str, Any]]: ...
172
168
 
173
169
  def list_image_versions(
174
170
  self,
@@ -556,8 +552,8 @@ class Image(BaseClient):
556
552
  PayloadTooLargeException: The artifact exceeds maximum size.
557
553
  InternalServerErrorException: The server failed to process the request.
558
554
  """
559
- image_name = body["name"] if "name" in body else ""
560
- version = body["version"] if "version" in body else ""
555
+ image_name = body.get("name", "")
556
+ version = body.get("version", "")
561
557
  response = (
562
558
  {} if not len(image_name) else self.list_images(page_size=100, return_iterator=False, name=image_name)
563
559
  )
@@ -698,8 +694,7 @@ class Image(BaseClient):
698
694
  build_status: Optional[List[str]] = None,
699
695
  *,
700
696
  return_iterator: Literal[False],
701
- ) -> Dict[str, Any]:
702
- ...
697
+ ) -> Dict[str, Any]: ...
703
698
 
704
699
  @overload
705
700
  def list_image_builds(
@@ -714,8 +709,7 @@ class Image(BaseClient):
714
709
  build_status: Optional[List[str]] = None,
715
710
  *,
716
711
  return_iterator: Literal[True] = True,
717
- ) -> Iterator[Dict[str, Any]]:
718
- ...
712
+ ) -> Iterator[Dict[str, Any]]: ...
719
713
 
720
714
  def list_image_builds(
721
715
  self,
@@ -44,8 +44,7 @@ class Service(BaseClient):
44
44
  service_type: Optional[List[str]] = None,
45
45
  *,
46
46
  return_iterator: Literal[False],
47
- ) -> Dict[str, Any]:
48
- ...
47
+ ) -> Dict[str, Any]: ...
49
48
 
50
49
  @overload
51
50
  def list_services(
@@ -57,8 +56,7 @@ class Service(BaseClient):
57
56
  service_type: Optional[List[str]] = None,
58
57
  *,
59
58
  return_iterator: Literal[True] = True,
60
- ) -> Iterator[Dict[str, Any]]:
61
- ...
59
+ ) -> Iterator[Dict[str, Any]]: ...
62
60
 
63
61
  def list_services(
64
62
  self,
@@ -155,7 +153,8 @@ class Service(BaseClient):
155
153
  "description": "string",
156
154
  "sessionStickiness": "boolean. Not required for 'api' service type.",
157
155
  "entrypoint": "string",
158
- "healthCheckURL": "string"
156
+ "healthCheckURL": "string",
157
+ "minInstances": "number. Default is 1 and maximum is 2",
159
158
  }
160
159
 
161
160
  Raises:
@@ -218,6 +217,7 @@ class Service(BaseClient):
218
217
  "sessionStickiness": "boolean. Not required for 'api' service type.",
219
218
  "entrypoint": "string",
220
219
  "healthCheckURL": "string",
220
+ "minInstances": "number. Default is 1 and maximum is 2",
221
221
  }
222
222
 
223
223
  Raises:
@@ -276,6 +276,7 @@ class Service(BaseClient):
276
276
  "sessionStickiness": "boolean. Not required for 'api' service type.",
277
277
  "entrypoint": "string",
278
278
  "healthCheckURL": "string",
279
+ "minInstances": "number. Default is 1 and maximum is 2",
279
280
  }
280
281
 
281
282
 
@@ -285,7 +286,7 @@ class Service(BaseClient):
285
286
  ForbiddenException: The user does not have permission to perform the operation.
286
287
  InternalServerErrorException: The server failed to process the request.
287
288
  """
288
- service_name = body["name"] if "name" in body else ""
289
+ service_name = body.get("name", "")
289
290
  response = (
290
291
  {} if not len(service_name) else self.list_services(page_size=100, return_iterator=False, name=service_name)
291
292
  )
@@ -0,0 +1,93 @@
1
+ #
2
+ # # Copyright © 2024 Peak AI Limited. or its affiliates. All Rights Reserved.
3
+ # #
4
+ # # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # # may not use this file except in compliance with the License. A copy of
6
+ # # the License is located at:
7
+ # #
8
+ # # https://github.com/PeakBI/peak-sdk/blob/main/LICENSE
9
+ # #
10
+ # # or in the "license" file accompanying this file. This file is
11
+ # # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # # ANY KIND, either express or implied. See the License for the specific
13
+ # # language governing permissions and limitations under the License.
14
+ # #
15
+ # # This file is part of the peak-sdk.
16
+ # # see (https://github.com/PeakBI/peak-sdk)
17
+ # #
18
+ # # You should have received a copy of the APACHE LICENSE, VERSION 2.0
19
+ # # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
20
+ #
21
+
22
+ """User client module."""
23
+ from __future__ import annotations
24
+
25
+ from typing import Dict, Optional
26
+
27
+ from peak.base_client import BaseClient
28
+ from peak.constants import ContentType, HttpMethods
29
+ from peak.helpers import search_action
30
+ from peak.session import Session
31
+ from peak.validators import validate_action, validate_feature_path
32
+
33
+
34
+ class User(BaseClient):
35
+ """Client class for interacting with users resource."""
36
+
37
+ BASE_ENDPOINT = "access-control/api/v2"
38
+
39
+ def check_permissions(self, feature_actions: Dict[str, str]) -> Dict[str, bool]:
40
+ """Check if the user has the specified permissions for the given features or subfeatures.
41
+
42
+ Args:
43
+ feature_actions (Dict[str, str]): A dictionary where keys are feature paths (e.g., "PRICING.GUARDRAILS")
44
+ and values are actions (e.g., "read" or "write").
45
+
46
+ Returns:
47
+ Dict[str, bool]: A dictionary where keys are the same feature paths and values are booleans
48
+ indicating whether the user has the specified action permission for that feature.
49
+
50
+ Raises:
51
+ UnauthorizedException: The credentials are invalid.
52
+ ForbiddenException: The user does not have permission to perform the operation.
53
+ NotFoundException: The given feature does not exist.
54
+ UnprocessableEntityException: The server was unable to process the request.
55
+ InternalServerErrorException: The server failed to process the request.
56
+ """
57
+ method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT}/access/permissions"
58
+
59
+ permissions_response = self.session.create_request(
60
+ endpoint,
61
+ method,
62
+ params={
63
+ "type": "app",
64
+ },
65
+ content_type=ContentType.APPLICATION_JSON,
66
+ )
67
+
68
+ result_permissions = {}
69
+
70
+ for feature_path, action in feature_actions.items():
71
+ validate_action(action)
72
+
73
+ search_result = search_action(feature_path, permissions_response, action)
74
+ validate_feature_path(search_result=search_result, feature_path=feature_path)
75
+
76
+ result_permissions[feature_path] = search_result["has_permission"]
77
+
78
+ return result_permissions
79
+
80
+
81
+ def get_client(session: Optional[Session] = None) -> User:
82
+ """Returns a User client, If no session is provided, a default session is used.
83
+
84
+ Args:
85
+ session (Optional[Session]): A Session Object. Default is None.
86
+
87
+ Returns:
88
+ User: The user client object.
89
+ """
90
+ return User(session)
91
+
92
+
93
+ __all__ = ["get_client"]
peak/resources/webapps.py CHANGED
@@ -49,8 +49,7 @@ class Webapp(BaseClient):
49
49
  name: Optional[str] = None,
50
50
  *,
51
51
  return_iterator: Literal[False],
52
- ) -> Dict[str, Any]:
53
- ...
52
+ ) -> Dict[str, Any]: ...
54
53
 
55
54
  @overload
56
55
  def list_webapps(
@@ -61,8 +60,7 @@ class Webapp(BaseClient):
61
60
  name: Optional[str] = None,
62
61
  *,
63
62
  return_iterator: Literal[True] = True,
64
- ) -> Iterator[Dict[str, Any]]:
65
- ...
63
+ ) -> Iterator[Dict[str, Any]]: ...
66
64
 
67
65
  def list_webapps(
68
66
  self,
@@ -253,7 +251,7 @@ class Webapp(BaseClient):
253
251
  ForbiddenException: The user does not have permission to perform the operation.
254
252
  InternalServerErrorException: The server failed to process the request.
255
253
  """
256
- webapp_name = body["name"] if "name" in body else ""
254
+ webapp_name = body.get("name", "")
257
255
  response = (
258
256
  {} if not len(webapp_name) else self.list_webapps(page_size=100, return_iterator=False, name=webapp_name)
259
257
  )