peak-sdk 1.0.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.
- peak/__init__.py +36 -0
- peak/_version.py +21 -0
- peak/auth.py +22 -0
- peak/base_client.py +52 -0
- peak/cli/__init_.py +20 -0
- peak/cli/args.py +84 -0
- peak/cli/cli.py +56 -0
- peak/cli/helpers.py +187 -0
- peak/cli/press/__init__.py +21 -0
- peak/cli/press/apps/__init__.py +40 -0
- peak/cli/press/apps/deployments.py +238 -0
- peak/cli/press/apps/specs.py +387 -0
- peak/cli/press/blocks/__init__.py +40 -0
- peak/cli/press/blocks/deployments.py +240 -0
- peak/cli/press/blocks/specs.py +492 -0
- peak/cli/press/deployments.py +78 -0
- peak/cli/press/specs.py +131 -0
- peak/cli/resources/__init__.py +21 -0
- peak/cli/resources/artifacts.py +310 -0
- peak/cli/resources/images.py +886 -0
- peak/cli/resources/webapps.py +356 -0
- peak/cli/resources/workflows.py +703 -0
- peak/cli/ruff.toml +11 -0
- peak/cli/version.py +49 -0
- peak/compression.py +162 -0
- peak/config.py +24 -0
- peak/constants.py +105 -0
- peak/exceptions.py +217 -0
- peak/handler.py +358 -0
- peak/helpers.py +184 -0
- peak/logger.py +48 -0
- peak/press/__init__.py +28 -0
- peak/press/apps.py +669 -0
- peak/press/blocks.py +707 -0
- peak/press/deployments.py +145 -0
- peak/press/specs.py +260 -0
- peak/py.typed +0 -0
- peak/resources/__init__.py +28 -0
- peak/resources/artifacts.py +343 -0
- peak/resources/images.py +675 -0
- peak/resources/webapps.py +278 -0
- peak/resources/workflows.py +625 -0
- peak/session.py +259 -0
- peak/telemetry.py +201 -0
- peak/template.py +231 -0
- peak/validators.py +48 -0
- peak_sdk-1.0.0.dist-info/LICENSE +201 -0
- peak_sdk-1.0.0.dist-info/METADATA +199 -0
- peak_sdk-1.0.0.dist-info/RECORD +51 -0
- peak_sdk-1.0.0.dist-info/WHEEL +4 -0
- peak_sdk-1.0.0.dist-info/entry_points.txt +3 -0
peak/resources/images.py
ADDED
@@ -0,0 +1,675 @@
|
|
1
|
+
#
|
2
|
+
# # Copyright © 2023 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
|
+
"""image client module."""
|
22
|
+
from __future__ import annotations
|
23
|
+
|
24
|
+
from typing import Any, Dict, Iterator, List, Literal, Optional, Tuple, overload
|
25
|
+
|
26
|
+
from peak.base_client import BaseClient
|
27
|
+
from peak.constants import ArtifactInfo, ContentType, HttpMethods
|
28
|
+
from peak.helpers import parse_body_for_multipart_request
|
29
|
+
from peak.session import Session
|
30
|
+
|
31
|
+
|
32
|
+
class Image(BaseClient):
|
33
|
+
"""Image Client Class."""
|
34
|
+
|
35
|
+
BASE_ENDPOINT = "image-management/api/v1"
|
36
|
+
BASE_ENDPOINT_V2 = "image-management/api/v2"
|
37
|
+
|
38
|
+
def __get_artifact_details(self, artifact: Optional[ArtifactInfo] = None) -> Tuple[str | None, list[str] | None]:
|
39
|
+
path, ignore_files = None, None
|
40
|
+
|
41
|
+
if artifact:
|
42
|
+
path = artifact.get("path")
|
43
|
+
ignore_files = artifact.get("ignore_files")
|
44
|
+
|
45
|
+
return path, ignore_files
|
46
|
+
|
47
|
+
@overload
|
48
|
+
def list_images(
|
49
|
+
self,
|
50
|
+
page_size: Optional[int] = None,
|
51
|
+
page_number: Optional[int] = None,
|
52
|
+
name: Optional[str] = None,
|
53
|
+
status: Optional[List[str]] = None,
|
54
|
+
scope: Optional[List[str]] = None,
|
55
|
+
last_build_status: Optional[List[str]] = None,
|
56
|
+
tags: Optional[List[str]] = None,
|
57
|
+
*,
|
58
|
+
return_iterator: Literal[False],
|
59
|
+
) -> Dict[str, Any]:
|
60
|
+
...
|
61
|
+
|
62
|
+
@overload
|
63
|
+
def list_images(
|
64
|
+
self,
|
65
|
+
page_size: Optional[int] = None,
|
66
|
+
page_number: Optional[int] = None,
|
67
|
+
name: Optional[str] = None,
|
68
|
+
status: Optional[List[str]] = None,
|
69
|
+
scope: Optional[List[str]] = None,
|
70
|
+
last_build_status: Optional[List[str]] = None,
|
71
|
+
tags: Optional[List[str]] = None,
|
72
|
+
*,
|
73
|
+
return_iterator: Literal[True] = True,
|
74
|
+
) -> Iterator[Dict[str, Any]]:
|
75
|
+
...
|
76
|
+
|
77
|
+
def list_images(
|
78
|
+
self,
|
79
|
+
page_size: Optional[int] = None,
|
80
|
+
page_number: Optional[int] = None,
|
81
|
+
name: Optional[str] = None,
|
82
|
+
status: Optional[List[str]] = None,
|
83
|
+
scope: Optional[List[str]] = None,
|
84
|
+
last_build_status: Optional[List[str]] = None,
|
85
|
+
tags: Optional[List[str]] = None,
|
86
|
+
*,
|
87
|
+
return_iterator: bool = True,
|
88
|
+
) -> Iterator[Dict[str, Any]] | Dict[str, Any]:
|
89
|
+
"""Retrieve the list of images.
|
90
|
+
|
91
|
+
REFERENCE:
|
92
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/images/get_api_v2_images>`__
|
93
|
+
|
94
|
+
Args:
|
95
|
+
page_size (int | None): The number of images per page.
|
96
|
+
page_number (int | None): The page number to retrieve. Only used when `return_iterator` is False.
|
97
|
+
name: (str | None): Image Name or version to search for.
|
98
|
+
status (List[str] | None): Filter images on the basis of the status of the latest version.
|
99
|
+
Allowed values are - not-ready, ready, in-use
|
100
|
+
scope (List[str] | None): Filter out on the basis of the type of the image - global or custom.
|
101
|
+
last_build_status (List[str] | None): Filter out on the basis of last build status of the latest version.
|
102
|
+
Allowed values are - building, failed, success, stopped, stopping
|
103
|
+
tags (List[str] | None): Filter out on the basis of the tags attached to the latest version.
|
104
|
+
return_iterator (bool): Whether to return an iterator object or list of images for a specified page number, defaults to True.
|
105
|
+
|
106
|
+
Returns:
|
107
|
+
Iterator[Dict[str, Any]] | Dict[str, Any]: an iterator object which returns an element per iteration, until there are no more elements to return.
|
108
|
+
If `return_iterator` is set to False, a dictionary containing the list and pagination details is returned instead.
|
109
|
+
|
110
|
+
Set `return_iterator` to True if you want automatic client-side pagination, or False if you want server-side pagination.
|
111
|
+
|
112
|
+
Raises:
|
113
|
+
BadRequestException: The given request parameters are invalid.
|
114
|
+
UnauthorizedException: The credentials are invalid.
|
115
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
116
|
+
InternalServerErrorException: The server failed to process the request.
|
117
|
+
"""
|
118
|
+
method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT_V2}/images/"
|
119
|
+
params = {
|
120
|
+
"pageSize": page_size,
|
121
|
+
"searchTerm": name,
|
122
|
+
"status": status,
|
123
|
+
"scope": scope,
|
124
|
+
"lastBuildStatus": last_build_status,
|
125
|
+
"tags": tags,
|
126
|
+
}
|
127
|
+
|
128
|
+
if return_iterator:
|
129
|
+
return self.session.create_generator_request(
|
130
|
+
endpoint,
|
131
|
+
method,
|
132
|
+
content_type=ContentType.APPLICATION_JSON,
|
133
|
+
response_key="images",
|
134
|
+
params=params,
|
135
|
+
)
|
136
|
+
|
137
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
138
|
+
endpoint,
|
139
|
+
method,
|
140
|
+
content_type=ContentType.APPLICATION_JSON,
|
141
|
+
params={**params, "pageNumber": page_number},
|
142
|
+
)
|
143
|
+
|
144
|
+
@overload
|
145
|
+
def list_image_versions(
|
146
|
+
self,
|
147
|
+
image_id: int,
|
148
|
+
page_size: Optional[int] = None,
|
149
|
+
page_number: Optional[int] = None,
|
150
|
+
version: Optional[str] = None,
|
151
|
+
status: Optional[List[str]] = None,
|
152
|
+
last_build_status: Optional[List[str]] = None,
|
153
|
+
tags: Optional[List[str]] = None,
|
154
|
+
*,
|
155
|
+
return_iterator: Literal[False],
|
156
|
+
) -> Dict[str, Any]:
|
157
|
+
...
|
158
|
+
|
159
|
+
@overload
|
160
|
+
def list_image_versions(
|
161
|
+
self,
|
162
|
+
image_id: int,
|
163
|
+
page_size: Optional[int] = None,
|
164
|
+
page_number: Optional[int] = None,
|
165
|
+
version: Optional[str] = None,
|
166
|
+
status: Optional[List[str]] = None,
|
167
|
+
last_build_status: Optional[List[str]] = None,
|
168
|
+
tags: Optional[List[str]] = None,
|
169
|
+
*,
|
170
|
+
return_iterator: Literal[True] = True,
|
171
|
+
) -> Iterator[Dict[str, Any]]:
|
172
|
+
...
|
173
|
+
|
174
|
+
def list_image_versions(
|
175
|
+
self,
|
176
|
+
image_id: int,
|
177
|
+
page_size: Optional[int] = None,
|
178
|
+
page_number: Optional[int] = None,
|
179
|
+
version: Optional[str] = None,
|
180
|
+
status: Optional[List[str]] = None,
|
181
|
+
last_build_status: Optional[List[str]] = None,
|
182
|
+
tags: Optional[List[str]] = None,
|
183
|
+
*,
|
184
|
+
return_iterator: bool = True,
|
185
|
+
) -> Iterator[Dict[str, Any]] | Dict[str, Any]:
|
186
|
+
"""Retrieve a list of image versions.
|
187
|
+
|
188
|
+
REFERENCE:
|
189
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/versions/get_api_v2_images__imageId__versions>`__
|
190
|
+
|
191
|
+
Args:
|
192
|
+
image_id (int): The Image id for which we want to get versions.
|
193
|
+
page_size (int | None): The number of images per page.
|
194
|
+
page_number (int | None): The page number to retrieve. Only used when `return_iterator` is False.
|
195
|
+
version: (str | None): Search by version.
|
196
|
+
status (List[str] | None): Filter versions on the basis of their status.
|
197
|
+
Allowed values are - not-ready, ready, in-use
|
198
|
+
last_build_status (List[str] | None): Filter out on the basis of last build status of version.
|
199
|
+
Allowed values are - building, failed, success, stopped, stopping
|
200
|
+
tags (List[str] | None): Filter out on the basis of the tags attached to the version.
|
201
|
+
return_iterator (bool): Whether to return an iterator object or list of images for a specified page number, defaults to True.
|
202
|
+
|
203
|
+
Returns:
|
204
|
+
Iterator[Dict[str, Any] | Dict[str, Any]: An iterator object which returns an element per iteration, until there are no more elements to return.
|
205
|
+
If `return_iterator` is set to False, a dictionary containing the list and pagination details is returned instead.
|
206
|
+
|
207
|
+
Set `return_iterator` to True if you want automatic client-side pagination, or False if you want server-side pagination.
|
208
|
+
|
209
|
+
Raises:
|
210
|
+
BadRequestException: The given request parameters are invalid.
|
211
|
+
UnauthorizedException: The credentials are invalid.
|
212
|
+
ForbiddenException: The user does not have permission to perform this operation.
|
213
|
+
InternalServerErrorException: The server failed to process the request.
|
214
|
+
"""
|
215
|
+
method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT_V2}/images/{image_id}/versions"
|
216
|
+
params = {
|
217
|
+
"pageSize": page_size,
|
218
|
+
"searchTerm": version,
|
219
|
+
"status": status,
|
220
|
+
"lastBuildStatus": last_build_status,
|
221
|
+
"tags": tags,
|
222
|
+
}
|
223
|
+
|
224
|
+
if return_iterator:
|
225
|
+
return self.session.create_generator_request(
|
226
|
+
endpoint,
|
227
|
+
method,
|
228
|
+
content_type=ContentType.APPLICATION_JSON,
|
229
|
+
response_key="versions",
|
230
|
+
params=params,
|
231
|
+
)
|
232
|
+
|
233
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
234
|
+
endpoint,
|
235
|
+
method,
|
236
|
+
content_type=ContentType.APPLICATION_JSON,
|
237
|
+
params={**params, "pageNumber": page_number},
|
238
|
+
)
|
239
|
+
|
240
|
+
def create_image(
|
241
|
+
self,
|
242
|
+
body: Dict[str, Any],
|
243
|
+
artifact: Optional[ArtifactInfo] = None,
|
244
|
+
) -> Dict[str, Any]:
|
245
|
+
"""Create a new image.
|
246
|
+
|
247
|
+
REFERENCE:
|
248
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/images/post_api_v2_images>`__
|
249
|
+
|
250
|
+
Args:
|
251
|
+
body (Dict[str, Any]): Represents the body to be used to create image. Details about all the various supported keys
|
252
|
+
can be found in the API doc.
|
253
|
+
|
254
|
+
artifact (Optional[ArtifactInfo]): Mapping of artifact attributes that specifies how the artifact will be generated,
|
255
|
+
it accepts two keys `path`, which is required and `ignore_files` which is optional, and defaults to `.dockerignore`, it is strongly advised that users use `ignore_files` when generating artifacts to avoid copying any extra files in artifact.
|
256
|
+
|
257
|
+
Returns:
|
258
|
+
Dict[str, Any]: `buildId`, `imageId`, and `versionId` of the newly created image and the corresponding version.
|
259
|
+
|
260
|
+
Raises:
|
261
|
+
BadRequestException: The given request parameters are invalid.
|
262
|
+
UnauthorizedException: The credentials are invalid.
|
263
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
264
|
+
PayloadTooLargeException: The artifact exceeds maximum size.
|
265
|
+
InternalServerErrorException: The server failed to process the request.
|
266
|
+
"""
|
267
|
+
method, endpoint = HttpMethods.POST, f"{self.BASE_ENDPOINT_V2}/images/"
|
268
|
+
|
269
|
+
path, ignore_files = self.__get_artifact_details(artifact)
|
270
|
+
body = parse_body_for_multipart_request(body)
|
271
|
+
|
272
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
273
|
+
endpoint,
|
274
|
+
method,
|
275
|
+
content_type=ContentType.MULTIPART_FORM_DATA,
|
276
|
+
body=body,
|
277
|
+
path=path,
|
278
|
+
ignore_files=ignore_files,
|
279
|
+
)
|
280
|
+
|
281
|
+
def create_version(
|
282
|
+
self,
|
283
|
+
image_id: int,
|
284
|
+
body: Dict[str, Any],
|
285
|
+
artifact: Optional[ArtifactInfo] = None,
|
286
|
+
) -> Dict[str, Any]:
|
287
|
+
"""Create a new version.
|
288
|
+
|
289
|
+
REFERENCE:
|
290
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/versions/post_api_v2_images__imageId__versions>`__
|
291
|
+
|
292
|
+
Args:
|
293
|
+
image_id (int): The ID of the image for which we have to create a new version.
|
294
|
+
body (Dict[str, Any]): Represents the body to be used to create image version. Details about all the various supported keys
|
295
|
+
can be found in the API doc.
|
296
|
+
artifact (Optional[ArtifactInfo]): Mapping of artifact attributes that specifies how the artifact will be generated,
|
297
|
+
it accepts two keys `path`, which is required and `ignore_files` which is optional, and defaults to `.dockerignore`, it is strongly advised that users use `ignore_files` when generating artifacts to avoid copying any extra files in artifact.
|
298
|
+
|
299
|
+
Returns:
|
300
|
+
Dict[str, Any]: `imageId`, `buildId`, `versionId` and `autodeploymentId` of the newly created version.
|
301
|
+
|
302
|
+
Raises:
|
303
|
+
BadRequestException: The given request parameters are invalid.
|
304
|
+
UnauthorizedException: The credentials are invalid.
|
305
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
306
|
+
PayloadTooLargeException: The artifact exceeds maximum size.
|
307
|
+
InternalServerErrorException: The server failed to process the request.
|
308
|
+
"""
|
309
|
+
method, endpoint = HttpMethods.POST, f"{self.BASE_ENDPOINT_V2}/images/{image_id}/versions"
|
310
|
+
|
311
|
+
path, ignore_files = self.__get_artifact_details(artifact)
|
312
|
+
body = parse_body_for_multipart_request(body)
|
313
|
+
|
314
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
315
|
+
endpoint,
|
316
|
+
method,
|
317
|
+
content_type=ContentType.MULTIPART_FORM_DATA,
|
318
|
+
body=body,
|
319
|
+
path=path,
|
320
|
+
ignore_files=ignore_files,
|
321
|
+
)
|
322
|
+
|
323
|
+
def describe_image(
|
324
|
+
self,
|
325
|
+
image_id: int,
|
326
|
+
) -> Dict[str, Any]:
|
327
|
+
"""Retrieve details of a specific image and its latest version.
|
328
|
+
|
329
|
+
REFERENCE:
|
330
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/images/get_api_v2_images__imageId_>`__
|
331
|
+
|
332
|
+
Args:
|
333
|
+
image_id (int): The ID of the image to retrieve.
|
334
|
+
|
335
|
+
Returns:
|
336
|
+
Dict[str, Any]: A dictionary containing the details of the image and its latest version.
|
337
|
+
|
338
|
+
Raises:
|
339
|
+
BadRequestException: The given request parameters are invalid.
|
340
|
+
UnauthorizedException: The credentials are invalid.
|
341
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
342
|
+
NotFoundException: The given image does not exist.
|
343
|
+
UnprocessableEntityException: The server was unable to process the request.
|
344
|
+
InternalServerErrorException: The server failed to process the request.
|
345
|
+
"""
|
346
|
+
method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT_V2}/images/{image_id}"
|
347
|
+
|
348
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
349
|
+
endpoint,
|
350
|
+
method,
|
351
|
+
content_type=ContentType.APPLICATION_JSON,
|
352
|
+
)
|
353
|
+
|
354
|
+
def describe_version(
|
355
|
+
self,
|
356
|
+
image_id: int,
|
357
|
+
version_id: int,
|
358
|
+
) -> Dict[str, Any]:
|
359
|
+
"""Retrieve details of a specific version.
|
360
|
+
|
361
|
+
REFERENCE:
|
362
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/versions/get_api_v2_images__imageId__versions__versionId_>`__
|
363
|
+
|
364
|
+
Args:
|
365
|
+
image_id (int): The ID of the image to retrieve.
|
366
|
+
version_id (int): The ID of the image to retrieve.
|
367
|
+
|
368
|
+
Returns:
|
369
|
+
Dict[str, Any]: a dictionary containing the details of the version.
|
370
|
+
|
371
|
+
Raises:
|
372
|
+
BadRequestException: The given request parameters are invalid.
|
373
|
+
UnauthorizedException: The credentials are invalid.
|
374
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
375
|
+
NotFoundException: The given image does not exist.
|
376
|
+
UnprocessableEntityException: The server was unable to process the request.
|
377
|
+
InternalServerErrorException: The server failed to process the request.
|
378
|
+
"""
|
379
|
+
method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT_V2}/images/{image_id}/versions/{version_id}"
|
380
|
+
|
381
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
382
|
+
endpoint,
|
383
|
+
method,
|
384
|
+
content_type=ContentType.APPLICATION_JSON,
|
385
|
+
)
|
386
|
+
|
387
|
+
def update_version(
|
388
|
+
self,
|
389
|
+
image_id: int,
|
390
|
+
version_id: int,
|
391
|
+
body: Dict[str, Any],
|
392
|
+
artifact: Optional[ArtifactInfo] = None,
|
393
|
+
) -> dict[str, str]:
|
394
|
+
"""Update an existing image version.
|
395
|
+
|
396
|
+
REFERENCE:
|
397
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/versions/patch_api_v2_images__imageId__versions__versionId_>`__
|
398
|
+
|
399
|
+
Args:
|
400
|
+
image_id (int): The ID of the image to update.
|
401
|
+
version_id (int): The ID of the version to update.
|
402
|
+
body (Dict[str, Any]): Represents the body to be used to update image version. Details about all the various supported keys
|
403
|
+
can be found in the API doc.
|
404
|
+
artifact (Optional[ArtifactInfo]): Mapping of artifact attributes that specifies how the artifact will be generated,
|
405
|
+
it accepts two keys `path`, which is required and `ignore_files` which is optional, and defaults to `.dockerignore`, it is strongly advised that users use `ignore_files` when generating artifacts to avoid copying any extra files in artifact.
|
406
|
+
|
407
|
+
Returns:
|
408
|
+
Dict[str, Any]: `imageId`, `buildId`, `versionId` and `autodeploymentId` of the updated version.
|
409
|
+
|
410
|
+
Raises:
|
411
|
+
BadRequestException: The given request parameters are invalid.
|
412
|
+
UnauthorizedException: The credentials are invalid.
|
413
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
414
|
+
NotFoundException: The given image or version does not exist.
|
415
|
+
PayloadTooLargeException: The artifact exceeds maximum size.
|
416
|
+
UnprocessableEntityException: The server was unable to process the request.
|
417
|
+
InternalServerErrorException: The server failed to process the request.
|
418
|
+
"""
|
419
|
+
method, endpoint = HttpMethods.PATCH, f"{self.BASE_ENDPOINT_V2}/images/{image_id}/versions/{version_id}"
|
420
|
+
|
421
|
+
path, ignore_files = self.__get_artifact_details(artifact)
|
422
|
+
body = parse_body_for_multipart_request(body)
|
423
|
+
|
424
|
+
response: Dict[str, Any] = self.session.create_request(
|
425
|
+
endpoint,
|
426
|
+
method,
|
427
|
+
content_type=ContentType.MULTIPART_FORM_DATA,
|
428
|
+
body=body,
|
429
|
+
path=path,
|
430
|
+
ignore_files=ignore_files,
|
431
|
+
)
|
432
|
+
return response
|
433
|
+
|
434
|
+
def create_or_update_image_version(
|
435
|
+
self,
|
436
|
+
body: Dict[str, Any],
|
437
|
+
artifact: Optional[ArtifactInfo] = None,
|
438
|
+
) -> Dict[str, Any]:
|
439
|
+
"""Create a new image or version if none exists, update version if exists based on image name and version combination.
|
440
|
+
|
441
|
+
REFERENCE:
|
442
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/images/post_api_v2_images>`__
|
443
|
+
|
444
|
+
Args:
|
445
|
+
body (Dict[str, Any]): Represents the body to be used to create image. Details about all the various supported keys
|
446
|
+
can be found in the API doc.
|
447
|
+
|
448
|
+
artifact (Optional[ArtifactInfo]): Mapping of artifact attributes that specifies how the artifact will be generated,
|
449
|
+
it accepts two keys `path`, which is required and `ignore_files` which is optional, and defaults to `.dockerignore`, it is strongly advised that users use `ignore_files` when generating artifacts to avoid copying any extra files in artifact.
|
450
|
+
|
451
|
+
Returns:
|
452
|
+
Dict[str, Any]: `buildId`, `imageId`, and `versionId` of the newly created image and the corresponding version when no image/version exists.
|
453
|
+
In case when image exists but version doesn't it will return `buildId` and `versionId` of the newly created version along with `imageId` of the existing image.
|
454
|
+
In case when image and version exists, it will return `buildId` for the updated version along with `imageId` and `versionId` of the existing image / version.
|
455
|
+
|
456
|
+
Raises:
|
457
|
+
BadRequestException: The given request parameters are invalid.
|
458
|
+
UnauthorizedException: The credentials are invalid.
|
459
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
460
|
+
PayloadTooLargeException: The artifact exceeds maximum size.
|
461
|
+
InternalServerErrorException: The server failed to process the request.
|
462
|
+
"""
|
463
|
+
image_name = body["name"] if "name" in body else ""
|
464
|
+
version = body["version"] if "version" in body else ""
|
465
|
+
response = (
|
466
|
+
{} if not len(image_name) else self.list_images(page_size=100, return_iterator=False, name=image_name)
|
467
|
+
)
|
468
|
+
filtered_images = list(filter(lambda image: image.get("name", "") == image_name, response.get("images", [])))
|
469
|
+
|
470
|
+
if len(filtered_images) > 0:
|
471
|
+
image_id = filtered_images[0]["id"]
|
472
|
+
versions_response = (
|
473
|
+
{}
|
474
|
+
if not len(version)
|
475
|
+
else self.list_image_versions(
|
476
|
+
image_id=image_id,
|
477
|
+
version=version,
|
478
|
+
page_size=1,
|
479
|
+
return_iterator=False,
|
480
|
+
)
|
481
|
+
)
|
482
|
+
filtered_versions = list(
|
483
|
+
filter(lambda ver: ver.get("version", "") == version, versions_response.get("versions", [])),
|
484
|
+
)
|
485
|
+
if len(filtered_versions) > 0:
|
486
|
+
version_id = filtered_versions[0]["id"]
|
487
|
+
return self.update_version(image_id=image_id, version_id=version_id, body=body, artifact=artifact)
|
488
|
+
|
489
|
+
return self.create_version(image_id=image_id, body=body, artifact=artifact)
|
490
|
+
|
491
|
+
return self.create_image(body=body, artifact=artifact)
|
492
|
+
|
493
|
+
def delete_image(
|
494
|
+
self,
|
495
|
+
image_id: int,
|
496
|
+
) -> Dict[None, None]:
|
497
|
+
"""Delete an Image.
|
498
|
+
|
499
|
+
REFERENCE:
|
500
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/images/delete_api_v1_images__imageId_>`__
|
501
|
+
|
502
|
+
Args:
|
503
|
+
image_id (int): The ID of the image to delete.
|
504
|
+
|
505
|
+
Returns:
|
506
|
+
dict: Empty dictionary object.
|
507
|
+
|
508
|
+
Raises:
|
509
|
+
UnauthorizedException: The credentials are invalid.
|
510
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
511
|
+
NotFoundException: The given image does not exist.
|
512
|
+
UnprocessableEntityException: The server was unable to process the request.
|
513
|
+
InternalServerErrorException: The server failed to process the request.
|
514
|
+
"""
|
515
|
+
method, endpoint = HttpMethods.DELETE, f"{self.BASE_ENDPOINT}/images/{image_id}"
|
516
|
+
|
517
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
518
|
+
endpoint,
|
519
|
+
method,
|
520
|
+
content_type=ContentType.APPLICATION_JSON,
|
521
|
+
)
|
522
|
+
|
523
|
+
def delete_version(
|
524
|
+
self,
|
525
|
+
image_id: int,
|
526
|
+
version_id: int,
|
527
|
+
) -> Dict[None, None]:
|
528
|
+
"""Delete an Image Version.
|
529
|
+
|
530
|
+
REFERENCE:
|
531
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/versions/delete_api_v2_images__imageId__versions__versionId_>`__
|
532
|
+
|
533
|
+
Args:
|
534
|
+
image_id (int): The ID of the image to delete.
|
535
|
+
version_id (int): The ID of the version to delete.
|
536
|
+
|
537
|
+
Returns:
|
538
|
+
dict: Empty dictionary object.
|
539
|
+
|
540
|
+
Raises:
|
541
|
+
UnauthorizedException: The credentials are invalid.
|
542
|
+
ForbiddenException: The user does not have permission to perform this operation.
|
543
|
+
NotFoundException: The given image does not exist.
|
544
|
+
UnprocessableEntityException: The server was unable to process the request.
|
545
|
+
InternalServerErrorException: The server failed to process the request.
|
546
|
+
"""
|
547
|
+
method, endpoint = HttpMethods.DELETE, f"{self.BASE_ENDPOINT_V2}/images/{image_id}/versions/{version_id}"
|
548
|
+
|
549
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
550
|
+
endpoint,
|
551
|
+
method,
|
552
|
+
content_type=ContentType.APPLICATION_JSON,
|
553
|
+
)
|
554
|
+
|
555
|
+
@overload
|
556
|
+
def list_image_builds(
|
557
|
+
self,
|
558
|
+
image_id: int,
|
559
|
+
date_from: Optional[str] = None,
|
560
|
+
date_to: Optional[str] = None,
|
561
|
+
page_size: Optional[int] = None,
|
562
|
+
page_number: Optional[int] = None,
|
563
|
+
count: Optional[int] = None,
|
564
|
+
version_ids: Optional[List[str]] = None,
|
565
|
+
build_status: Optional[List[str]] = None,
|
566
|
+
*,
|
567
|
+
return_iterator: Literal[False],
|
568
|
+
) -> Dict[str, Any]:
|
569
|
+
...
|
570
|
+
|
571
|
+
@overload
|
572
|
+
def list_image_builds(
|
573
|
+
self,
|
574
|
+
image_id: int,
|
575
|
+
date_from: Optional[str] = None,
|
576
|
+
date_to: Optional[str] = None,
|
577
|
+
page_size: Optional[int] = None,
|
578
|
+
page_number: Optional[int] = None,
|
579
|
+
count: Optional[int] = None,
|
580
|
+
version_ids: Optional[List[str]] = None,
|
581
|
+
build_status: Optional[List[str]] = None,
|
582
|
+
*,
|
583
|
+
return_iterator: Literal[True] = True,
|
584
|
+
) -> Iterator[Dict[str, Any]]:
|
585
|
+
...
|
586
|
+
|
587
|
+
def list_image_builds(
|
588
|
+
self,
|
589
|
+
image_id: int,
|
590
|
+
date_from: Optional[str] = None,
|
591
|
+
date_to: Optional[str] = None,
|
592
|
+
page_size: Optional[int] = None,
|
593
|
+
page_number: Optional[int] = None,
|
594
|
+
count: Optional[int] = None,
|
595
|
+
version_ids: Optional[List[str]] = None,
|
596
|
+
build_status: Optional[List[str]] = None,
|
597
|
+
*,
|
598
|
+
return_iterator: bool = True,
|
599
|
+
) -> Iterator[Dict[str, Any]] | Dict[str, Any]:
|
600
|
+
"""Lists image builds.
|
601
|
+
|
602
|
+
REFERENCE:
|
603
|
+
🔗 `API Documentation <https://service.peak.ai/image-management/api-docs/index.htm#/builds/get_api_v2_images__imageId__builds>`__
|
604
|
+
|
605
|
+
Args:
|
606
|
+
image_id (int): ID of the image to fetch image build history.
|
607
|
+
date_from (str | None): The date after which the image builds should be included (in ISO format).
|
608
|
+
It is 90 days from current date by default.
|
609
|
+
date_to (str | None): The date till which the image builds should be included (in ISO format).
|
610
|
+
It is current date by default.
|
611
|
+
page_size (int | None): Number of builds per page.
|
612
|
+
page_number (int | None): Page number to retrieve. Only used when return_iterator is False.
|
613
|
+
count (int | None): Number of builds required (Ordered by latest to earliest).
|
614
|
+
For example, if 5 is provided, it will return last 5 builds.
|
615
|
+
It is -1 by default which means it will return all the available builds within the given dates.
|
616
|
+
version_ids (List[str] | None): List of version ids to filter builds.
|
617
|
+
build_status (List[str] | None): List of build statuses to filter builds.
|
618
|
+
|
619
|
+
|
620
|
+
return_iterator (bool): Whether to return an iterator object or a dictionary of list of image builds. Defaults to True.
|
621
|
+
|
622
|
+
Returns:
|
623
|
+
Iterator[Dict[str, Any]] | Dict[str, Any]: an iterator object which returns an element per iteration, until there are no more elements to return.
|
624
|
+
If `return_iterator` is set to False, a dictionary containing the list and pagination details is returned instead.
|
625
|
+
|
626
|
+
Set `return_iterator` to True if you want automatic client-side pagination, or False if you want server-side pagination.
|
627
|
+
|
628
|
+
Raises:
|
629
|
+
BadRequestException: BadRequestException: The given request parameters are invalid.
|
630
|
+
UnauthorizedException: The credentials are invalid.
|
631
|
+
ForbiddenException: The user does not have permission to perform the operation.
|
632
|
+
NotFoundException: The given image does not exist.
|
633
|
+
InternalServerErrorException: The server failed to process the request.
|
634
|
+
"""
|
635
|
+
method, endpoint = HttpMethods.GET, f"{self.BASE_ENDPOINT_V2}/images/{image_id}/builds"
|
636
|
+
|
637
|
+
params: Dict[str, Any] = {
|
638
|
+
"dateTo": date_to,
|
639
|
+
"dateFrom": date_from,
|
640
|
+
"pageSize": page_size,
|
641
|
+
"count": -1 if count is None else count,
|
642
|
+
"versions": version_ids,
|
643
|
+
"buildStatus": build_status,
|
644
|
+
}
|
645
|
+
|
646
|
+
if return_iterator:
|
647
|
+
return self.session.create_generator_request(
|
648
|
+
endpoint,
|
649
|
+
method,
|
650
|
+
content_type=ContentType.APPLICATION_JSON,
|
651
|
+
params=params,
|
652
|
+
response_key="builds",
|
653
|
+
)
|
654
|
+
|
655
|
+
return self.session.create_request( # type: ignore[no-any-return]
|
656
|
+
endpoint,
|
657
|
+
method,
|
658
|
+
content_type=ContentType.APPLICATION_JSON,
|
659
|
+
params={**params, "pageNumber": page_number},
|
660
|
+
)
|
661
|
+
|
662
|
+
|
663
|
+
def get_client(session: Optional[Session] = None) -> Image:
|
664
|
+
"""Returns an Image Management client, If no session is provided, a default session is used.
|
665
|
+
|
666
|
+
Args:
|
667
|
+
session (Optional[Session]): A Session Object. Default is None.
|
668
|
+
|
669
|
+
Returns:
|
670
|
+
Image: the image client object
|
671
|
+
"""
|
672
|
+
return Image(session)
|
673
|
+
|
674
|
+
|
675
|
+
__all__: List[str] = ["get_client"]
|