diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd5753ba..21d8baf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/gcore-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Rye run: | @@ -44,7 +44,7 @@ jobs: id-token: write runs-on: ${{ github.repository == 'stainless-sdks/gcore-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Rye run: | @@ -81,7 +81,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/gcore-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Rye run: | diff --git a/.github/workflows/detect-breaking-changes.yml b/.github/workflows/detect-breaking-changes.yml index 4640f451..ffca94cc 100644 --- a/.github/workflows/detect-breaking-changes.yml +++ b/.github/workflows/detect-breaking-changes.yml @@ -15,7 +15,7 @@ jobs: run: | echo "FETCH_DEPTH=$(expr ${{ github.event.pull_request.commits }} + 1)" >> $GITHUB_ENV - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: # Ensure we can check out the pull request base in the script below. fetch-depth: ${{ env.FETCH_DEPTH }} diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 8c7b0787..3cebca63 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Rye run: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index a7b36139..927bb62a 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'G-Core/gcore-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Check release environment run: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8935e932..b8dda9bf 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.28.0" + ".": "0.29.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 698a6006..70d5bc3d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 641 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-2c3abe1f1637f97f6bc750aff6eb77efc45ac2b527376541ac2af6b9626b35af.yml -openapi_spec_hash: ff74a4ccd9ec5ddb1a65963d52e709ba -config_hash: df463160c27e4de887be7c27454ac4e0 +configured_endpoints: 645 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-3fc43b72b82321f8d4ceea9ea44d7ab14e75872dbe66e3e698e1f59ba300ec55.yml +openapi_spec_hash: 1b1043a0ef7bcf106abf14f9187f5755 +config_hash: 7085751e6bd8f3fd13cfebe04bb99fed diff --git a/CHANGELOG.md b/CHANGELOG.md index 70bc6a1c..e4b5a07b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,44 @@ # Changelog +## 0.29.0 (2026-01-19) + +Full Changelog: [v0.28.0...v0.29.0](https://github.com/G-Core/gcore-python/compare/v0.28.0...v0.29.0) + +### ⚠ BREAKING CHANGES + +* **cloud:** rename instance flavor model + +### Features + +* **api:** aggregated API specs update ([02468c1](https://github.com/G-Core/gcore-python/commit/02468c1c9e318746cd3b251f0250bdc94e1ea6c0)) +* **api:** aggregated API specs update ([34ed205](https://github.com/G-Core/gcore-python/commit/34ed205d304b9fb6606629ff42c4112739a102e8)) +* **api:** aggregated API specs update ([5e0ea7b](https://github.com/G-Core/gcore-python/commit/5e0ea7be815dddcaeace5af49d07d3d74dff3224)) +* **api:** aggregated API specs update ([3350bb9](https://github.com/G-Core/gcore-python/commit/3350bb9ec9d12d9299b505f62e5e335deaf37421)) +* **api:** aggregated API specs update ([d2e76de](https://github.com/G-Core/gcore-python/commit/d2e76de6e6e070d6253ba6ee5102cbadb9fc1ff4)) +* **api:** aggregated API specs update ([667f129](https://github.com/G-Core/gcore-python/commit/667f129c821808b2f2a250a90d4fb6adb36195e9)) +* **api:** aggregated API specs update ([e4f64fd](https://github.com/G-Core/gcore-python/commit/e4f64fd76cb32caa28782a171a4cf1cb4c47674d)) +* **api:** aggregated API specs update ([9f567f9](https://github.com/G-Core/gcore-python/commit/9f567f9268490b9c1b403a502ddd5f5e7a617534)) +* **api:** aggregated API specs update ([43225eb](https://github.com/G-Core/gcore-python/commit/43225eb53397a63c3b44c518a20e665561d1a86e)) +* **api:** aggregated API specs update ([3dc71fe](https://github.com/G-Core/gcore-python/commit/3dc71fe42e2466ae8040af28c77153383609e041)) +* **api:** aggregated API specs update ([3c15807](https://github.com/G-Core/gcore-python/commit/3c15807ac8fdc5c0ca42421896f829054eaa82cf)) +* **client:** add support for binary request streaming ([e5a58a3](https://github.com/G-Core/gcore-python/commit/e5a58a3024caa8212a2dd9e86c78087185fc798c)) +* **client:** add support for binary request streaming ([780229b](https://github.com/G-Core/gcore-python/commit/780229bb9a47ad9b822e1bd3df576a6918a177ed)) +* **cloud:** add support for volume snapshots ([19103d9](https://github.com/G-Core/gcore-python/commit/19103d9b95b37e597d545052d957d2593810307c)) + + +### Bug Fixes + +* **cloud:** rename instance flavor model ([3374f91](https://github.com/G-Core/gcore-python/commit/3374f91b05a70fbc617ef2e070b8fec96e0b08b8)) +* **cloud:** update type for instance flavor in examples ([fabf3fb](https://github.com/G-Core/gcore-python/commit/fabf3fb6c466d52a3df10bcf46c7cbdcf82242cf)) +* **examples:** ignore deprecated warnings for floating IPs ([9101b4f](https://github.com/G-Core/gcore-python/commit/9101b4f3204029c75a0dfd8e984436883a941baf)) +* **examples:** ignore deprecated warnings for security groups ([823f421](https://github.com/G-Core/gcore-python/commit/823f421a34f787b95099f1dec06b5b64cc206cf4)) +* use correct collection models ([31379f2](https://github.com/G-Core/gcore-python/commit/31379f2467ba06d4a049ce786d84f0c4dbb3d7c1)) + + +### Chores + +* **internal:** update `actions/checkout` version ([a407b00](https://github.com/G-Core/gcore-python/commit/a407b00b9771801ce82d55b0edd9a85c271fa7e2)) + ## 0.28.0 (2025-12-30) Full Changelog: [v0.27.0...v0.28.0](https://github.com/G-Core/gcore-python/compare/v0.27.0...v0.28.0) diff --git a/LICENSE b/LICENSE index b28d04ff..03c99139 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Gcore + Copyright 2026 Gcore Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/api.md b/api.md index ff599062..a877e26b 100644 --- a/api.md +++ b/api.md @@ -957,7 +957,7 @@ Methods: Types: ```python -from gcore.types.cloud.instances import InstanceFlavor, InstanceFlavorList +from gcore.types.cloud.instances import InstanceFlavorDetailed, InstanceFlavorList ``` Methods: @@ -1165,6 +1165,21 @@ Methods: - client.cloud.databases.postgres.custom_configurations.validate(\*, project_id, region_id, \*\*params) -> PgConfValidation +## VolumeSnapshots + +Types: + +```python +from gcore.types.cloud import Snapshot +``` + +Methods: + +- client.cloud.volume_snapshots.create(\*, project_id, region_id, \*\*params) -> TaskIDList +- client.cloud.volume_snapshots.update(snapshot_id, \*, project_id, region_id, \*\*params) -> Snapshot +- client.cloud.volume_snapshots.delete(snapshot_id, \*, project_id, region_id) -> TaskIDList +- client.cloud.volume_snapshots.get(snapshot_id, \*, project_id, region_id) -> Snapshot + # Waap Types: diff --git a/examples/cloud/floating_ips.py b/examples/cloud/floating_ips.py index ed5dd2c2..a2b44c48 100644 --- a/examples/cloud/floating_ips.py +++ b/examples/cloud/floating_ips.py @@ -60,7 +60,7 @@ def get_floating_ip(*, client: Gcore, floating_ip_id: str) -> None: def assign_floating_ip(*, client: Gcore, floating_ip_id: str, port_id: str) -> None: print("\n=== ASSIGN FLOATING IP ===") - floating_ip = client.cloud.floating_ips.assign( + floating_ip = client.cloud.floating_ips.assign( # pyright: ignore[reportDeprecated] floating_ip_id=floating_ip_id, port_id=port_id, ) @@ -70,7 +70,7 @@ def assign_floating_ip(*, client: Gcore, floating_ip_id: str, port_id: str) -> N def unassign_floating_ip(*, client: Gcore, floating_ip_id: str) -> None: print("\n=== UNASSIGN FLOATING IP ===") - floating_ip = client.cloud.floating_ips.unassign(floating_ip_id=floating_ip_id) + floating_ip = client.cloud.floating_ips.unassign(floating_ip_id=floating_ip_id) # pyright: ignore[reportDeprecated] print(f"Unassigned floating IP: ID={floating_ip.id}") print("========================") diff --git a/examples/cloud/floating_ips_async.py b/examples/cloud/floating_ips_async.py index f79c81ef..aea3370e 100644 --- a/examples/cloud/floating_ips_async.py +++ b/examples/cloud/floating_ips_async.py @@ -60,7 +60,7 @@ async def get_floating_ip(*, client: AsyncGcore, floating_ip_id: str) -> None: async def assign_floating_ip(*, client: AsyncGcore, floating_ip_id: str, port_id: str) -> None: print("\n=== ASSIGN FLOATING IP ===") - floating_ip = await client.cloud.floating_ips.assign( + floating_ip = await client.cloud.floating_ips.assign( # pyright: ignore[reportDeprecated] floating_ip_id=floating_ip_id, port_id=port_id, ) @@ -70,7 +70,7 @@ async def assign_floating_ip(*, client: AsyncGcore, floating_ip_id: str, port_id async def unassign_floating_ip(*, client: AsyncGcore, floating_ip_id: str) -> None: print("\n=== UNASSIGN FLOATING IP ===") - floating_ip = await client.cloud.floating_ips.unassign(floating_ip_id=floating_ip_id) + floating_ip = await client.cloud.floating_ips.unassign(floating_ip_id=floating_ip_id) # pyright: ignore[reportDeprecated] print(f"Unassigned floating IP: ID={floating_ip.id}") print("========================") diff --git a/examples/cloud/instances.py b/examples/cloud/instances.py index 9f8cf217..00606115 100644 --- a/examples/cloud/instances.py +++ b/examples/cloud/instances.py @@ -8,7 +8,7 @@ InterfaceNewInterfaceExternalSerializerPydantic, VolumeCreateInstanceCreateVolumeFromImageSerializer, ) -from gcore.types.cloud.instances.instance_flavor import InstanceFlavor +from gcore.types.cloud.instances.instance_flavor_detailed import InstanceFlavorDetailed def main() -> None: @@ -328,7 +328,7 @@ def delete_image(*, client: Gcore, image_id: str) -> None: print("========================") -def _print_flavor_details(flavors: List[InstanceFlavor]) -> None: +def _print_flavor_details(flavors: List[InstanceFlavorDetailed]) -> None: display_count = 3 if len(flavors) < display_count: display_count = len(flavors) diff --git a/examples/cloud/instances_async.py b/examples/cloud/instances_async.py index 5f895ac0..6dee1888 100644 --- a/examples/cloud/instances_async.py +++ b/examples/cloud/instances_async.py @@ -9,7 +9,7 @@ InterfaceNewInterfaceExternalSerializerPydantic, VolumeCreateInstanceCreateVolumeFromImageSerializer, ) -from gcore.types.cloud.instances.instance_flavor import InstanceFlavor +from gcore.types.cloud.instances.instance_flavor_detailed import InstanceFlavorDetailed async def main() -> None: @@ -333,7 +333,7 @@ async def delete_image(*, client: AsyncGcore, image_id: str) -> None: print("========================") -async def _print_flavor_details(flavors: List[InstanceFlavor]) -> None: +async def _print_flavor_details(flavors: List[InstanceFlavorDetailed]) -> None: display_count = 3 if len(flavors) < display_count: display_count = len(flavors) diff --git a/examples/cloud/security_groups.py b/examples/cloud/security_groups.py index 2620e283..9d46c6df 100644 --- a/examples/cloud/security_groups.py +++ b/examples/cloud/security_groups.py @@ -32,7 +32,7 @@ def main() -> None: def create_security_group(*, client: Gcore) -> str: print("\n=== CREATE SECURITY GROUP ===") - security_group = client.cloud.security_groups.create(security_group=SecurityGroup(name="gcore-go-example")) + security_group = client.cloud.security_groups.create(security_group=SecurityGroup(name="gcore-go-example")) # pyright: ignore[reportDeprecated] print(f"Created security group: ID={security_group.id}, name={security_group.name}") print("========================") return security_group.id @@ -57,7 +57,7 @@ def get_security_group(*, client: Gcore, security_group_id: str) -> None: def update_security_group(*, client: Gcore, security_group_id: str) -> None: print("\n=== UPDATE SECURITY GROUP ===") - security_group = client.cloud.security_groups.update( + security_group = client.cloud.security_groups.update( # pyright: ignore[reportDeprecated] group_id=security_group_id, name="gcore-go-example-updated", ) diff --git a/examples/cloud/security_groups_async.py b/examples/cloud/security_groups_async.py index dacb1cfc..543cba84 100644 --- a/examples/cloud/security_groups_async.py +++ b/examples/cloud/security_groups_async.py @@ -34,7 +34,7 @@ async def main() -> None: async def create_security_group(client: AsyncGcore) -> str: print("\n=== CREATE SECURITY GROUP ===") - security_group = await client.cloud.security_groups.create(security_group=SecurityGroup(name="gcore-go-example")) + security_group = await client.cloud.security_groups.create(security_group=SecurityGroup(name="gcore-go-example")) # pyright: ignore[reportDeprecated] print(f"Created security group: ID={security_group.id}, name={security_group.name}") print("========================") return security_group.id @@ -61,7 +61,7 @@ async def get_security_group(*, client: AsyncGcore, security_group_id: str) -> N async def update_security_group(*, client: AsyncGcore, security_group_id: str) -> None: print("\n=== UPDATE SECURITY GROUP ===") - security_group = await client.cloud.security_groups.update( + security_group = await client.cloud.security_groups.update( # pyright: ignore[reportDeprecated] group_id=security_group_id, name="gcore-go-example-updated", ) diff --git a/pyproject.toml b/pyproject.toml index 65c062eb..89661fbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "gcore" -version = "0.28.0" +version = "0.29.0" description = "The official Python library for the gcore API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/gcore/_base_client.py b/src/gcore/_base_client.py index b68aa376..e4303b57 100644 --- a/src/gcore/_base_client.py +++ b/src/gcore/_base_client.py @@ -9,6 +9,7 @@ import inspect import logging import platform +import warnings import email.utils from types import TracebackType from random import random @@ -51,9 +52,11 @@ ResponseT, AnyMapping, PostParser, + BinaryTypes, RequestFiles, HttpxSendArgs, RequestOptions, + AsyncBinaryTypes, HttpxRequestFiles, ModelBuilderProtocol, not_given, @@ -477,8 +480,19 @@ def _build_request( retries_taken: int = 0, ) -> httpx.Request: if log.isEnabledFor(logging.DEBUG): - log.debug("Request options: %s", model_dump(options, exclude_unset=True)) - + log.debug( + "Request options: %s", + model_dump( + options, + exclude_unset=True, + # Pydantic v1 can't dump every type we support in content, so we exclude it for now. + exclude={ + "content", + } + if PYDANTIC_V1 + else {}, + ), + ) kwargs: dict[str, Any] = {} json_data = options.json_data @@ -532,7 +546,13 @@ def _build_request( is_body_allowed = options.method.lower() != "get" if is_body_allowed: - if isinstance(json_data, bytes): + if options.content is not None and json_data is not None: + raise TypeError("Passing both `content` and `json_data` is not supported") + if options.content is not None and files is not None: + raise TypeError("Passing both `content` and `files` is not supported") + if options.content is not None: + kwargs["content"] = options.content + elif isinstance(json_data, bytes): kwargs["content"] = json_data else: kwargs["json"] = json_data if is_given(json_data) else None @@ -1194,6 +1214,7 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: Literal[False] = False, @@ -1206,6 +1227,7 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: Literal[True], @@ -1219,6 +1241,7 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: bool, @@ -1231,13 +1254,25 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: bool = False, stream_cls: type[_StreamT] | None = None, ) -> ResponseT | _StreamT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="post", url=path, json_data=body, files=to_httpx_files(files), **options + method="post", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) @@ -1247,9 +1282,24 @@ def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, + files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options) + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) + opts = FinalRequestOptions.construct( + method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options + ) return self.request(cast_to, opts) def put( @@ -1258,11 +1308,23 @@ def put( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="put", url=path, json_data=body, files=to_httpx_files(files), **options + method="put", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return self.request(cast_to, opts) @@ -1272,9 +1334,19 @@ def delete( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options) + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) + opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options) return self.request(cast_to, opts) def get_api_list( @@ -1714,6 +1786,7 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: Literal[False] = False, @@ -1726,6 +1799,7 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: Literal[True], @@ -1739,6 +1813,7 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: bool, @@ -1751,13 +1826,25 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: bool = False, stream_cls: type[_AsyncStreamT] | None = None, ) -> ResponseT | _AsyncStreamT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="post", url=path, json_data=body, files=await async_to_httpx_files(files), **options + method="post", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) @@ -1767,9 +1854,29 @@ async def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, + files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options) + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) + opts = FinalRequestOptions.construct( + method="patch", + url=path, + json_data=body, + content=content, + files=await async_to_httpx_files(files), + **options, + ) return await self.request(cast_to, opts) async def put( @@ -1778,11 +1885,23 @@ async def put( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="put", url=path, json_data=body, files=await async_to_httpx_files(files), **options + method="put", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts) @@ -1792,9 +1911,19 @@ async def delete( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options) + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) + opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options) return await self.request(cast_to, opts) def get_api_list( diff --git a/src/gcore/_models.py b/src/gcore/_models.py index ca9500b2..29070e05 100644 --- a/src/gcore/_models.py +++ b/src/gcore/_models.py @@ -3,7 +3,20 @@ import os import inspect import weakref -from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, Callable, Optional, cast +from typing import ( + IO, + TYPE_CHECKING, + Any, + Type, + Union, + Generic, + TypeVar, + Callable, + Iterable, + Optional, + AsyncIterable, + cast, +) from datetime import date, datetime from typing_extensions import ( List, @@ -787,6 +800,7 @@ class FinalRequestOptionsInput(TypedDict, total=False): timeout: float | Timeout | None files: HttpxRequestFiles | None idempotency_key: str + content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] json_data: Body extra_json: AnyMapping follow_redirects: bool @@ -805,6 +819,7 @@ class FinalRequestOptions(pydantic.BaseModel): post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() follow_redirects: Union[bool, None] = None + content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] = None # It should be noted that we cannot use `json` here as that would override # a BaseModel method in an incompatible fashion. json_data: Union[Body, None] = None diff --git a/src/gcore/_types.py b/src/gcore/_types.py index 6877c20a..bbc3b7c8 100644 --- a/src/gcore/_types.py +++ b/src/gcore/_types.py @@ -13,9 +13,11 @@ Mapping, TypeVar, Callable, + Iterable, Iterator, Optional, Sequence, + AsyncIterable, ) from typing_extensions import ( Set, @@ -56,6 +58,13 @@ else: Base64FileInput = Union[IO[bytes], PathLike] FileContent = Union[IO[bytes], bytes, PathLike] # PathLike is not subscriptable in Python 3.8. + + +# Used for sending raw binary data / streaming data in request bodies +# e.g. for file uploads without multipart encoding +BinaryTypes = Union[bytes, bytearray, IO[bytes], Iterable[bytes]] +AsyncBinaryTypes = Union[bytes, bytearray, IO[bytes], AsyncIterable[bytes]] + FileTypes = Union[ # file (or bytes) FileContent, diff --git a/src/gcore/_version.py b/src/gcore/_version.py index 6f1dd8f4..606d0626 100644 --- a/src/gcore/_version.py +++ b/src/gcore/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "gcore" -__version__ = "0.28.0" # x-release-please-version +__version__ = "0.29.0" # x-release-please-version diff --git a/src/gcore/resources/cdn/logs_uploader/policies.py b/src/gcore/resources/cdn/logs_uploader/policies.py index 1ea24646..a6d933fb 100644 --- a/src/gcore/resources/cdn/logs_uploader/policies.py +++ b/src/gcore/resources/cdn/logs_uploader/policies.py @@ -3,6 +3,7 @@ from __future__ import annotations from typing import Dict, Iterable, Optional +from typing_extensions import Literal import httpx @@ -55,11 +56,12 @@ def create( *, date_format: str | Omit = omit, description: str | Omit = omit, + escape_special_characters: bool | Omit = omit, field_delimiter: str | Omit = omit, field_separator: str | Omit = omit, fields: SequenceNotStr[str] | Omit = omit, file_name_template: str | Omit = omit, - format_type: str | Omit = omit, + format_type: Literal["json", ""] | Omit = omit, include_empty_logs: bool | Omit = omit, include_shield_logs: bool | Omit = omit, name: str | Omit = omit, @@ -83,6 +85,17 @@ def create( description: Description of the policy. + escape_special_characters: When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + field_delimiter: Field delimiter for logs. field_separator: Field separator for logs. @@ -93,6 +106,12 @@ def create( format_type: Format type for logs. + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + include_empty_logs: Include empty logs in the upload. include_shield_logs: Include logs from origin shielding in the upload. @@ -125,6 +144,7 @@ def create( { "date_format": date_format, "description": description, + "escape_special_characters": escape_special_characters, "field_delimiter": field_delimiter, "field_separator": field_separator, "fields": fields, @@ -153,11 +173,12 @@ def update( *, date_format: str | Omit = omit, description: str | Omit = omit, + escape_special_characters: bool | Omit = omit, field_delimiter: str | Omit = omit, field_separator: str | Omit = omit, fields: SequenceNotStr[str] | Omit = omit, file_name_template: str | Omit = omit, - format_type: str | Omit = omit, + format_type: Literal["json", ""] | Omit = omit, include_empty_logs: bool | Omit = omit, include_shield_logs: bool | Omit = omit, name: str | Omit = omit, @@ -181,6 +202,17 @@ def update( description: Description of the policy. + escape_special_characters: When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + field_delimiter: Field delimiter for logs. field_separator: Field separator for logs. @@ -191,6 +223,12 @@ def update( format_type: Format type for logs. + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + include_empty_logs: Include empty logs in the upload. include_shield_logs: Include logs from origin shielding in the upload. @@ -223,6 +261,7 @@ def update( { "date_format": date_format, "description": description, + "escape_special_characters": escape_special_characters, "field_delimiter": field_delimiter, "field_separator": field_separator, "fields": fields, @@ -384,11 +423,12 @@ def replace( *, date_format: str | Omit = omit, description: str | Omit = omit, + escape_special_characters: bool | Omit = omit, field_delimiter: str | Omit = omit, field_separator: str | Omit = omit, fields: SequenceNotStr[str] | Omit = omit, file_name_template: str | Omit = omit, - format_type: str | Omit = omit, + format_type: Literal["json", ""] | Omit = omit, include_empty_logs: bool | Omit = omit, include_shield_logs: bool | Omit = omit, name: str | Omit = omit, @@ -412,6 +452,17 @@ def replace( description: Description of the policy. + escape_special_characters: When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + field_delimiter: Field delimiter for logs. field_separator: Field separator for logs. @@ -422,6 +473,12 @@ def replace( format_type: Format type for logs. + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + include_empty_logs: Include empty logs in the upload. include_shield_logs: Include logs from origin shielding in the upload. @@ -454,6 +511,7 @@ def replace( { "date_format": date_format, "description": description, + "escape_special_characters": escape_special_characters, "field_delimiter": field_delimiter, "field_separator": field_separator, "fields": fields, @@ -502,11 +560,12 @@ async def create( *, date_format: str | Omit = omit, description: str | Omit = omit, + escape_special_characters: bool | Omit = omit, field_delimiter: str | Omit = omit, field_separator: str | Omit = omit, fields: SequenceNotStr[str] | Omit = omit, file_name_template: str | Omit = omit, - format_type: str | Omit = omit, + format_type: Literal["json", ""] | Omit = omit, include_empty_logs: bool | Omit = omit, include_shield_logs: bool | Omit = omit, name: str | Omit = omit, @@ -530,6 +589,17 @@ async def create( description: Description of the policy. + escape_special_characters: When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + field_delimiter: Field delimiter for logs. field_separator: Field separator for logs. @@ -540,6 +610,12 @@ async def create( format_type: Format type for logs. + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + include_empty_logs: Include empty logs in the upload. include_shield_logs: Include logs from origin shielding in the upload. @@ -572,6 +648,7 @@ async def create( { "date_format": date_format, "description": description, + "escape_special_characters": escape_special_characters, "field_delimiter": field_delimiter, "field_separator": field_separator, "fields": fields, @@ -600,11 +677,12 @@ async def update( *, date_format: str | Omit = omit, description: str | Omit = omit, + escape_special_characters: bool | Omit = omit, field_delimiter: str | Omit = omit, field_separator: str | Omit = omit, fields: SequenceNotStr[str] | Omit = omit, file_name_template: str | Omit = omit, - format_type: str | Omit = omit, + format_type: Literal["json", ""] | Omit = omit, include_empty_logs: bool | Omit = omit, include_shield_logs: bool | Omit = omit, name: str | Omit = omit, @@ -628,6 +706,17 @@ async def update( description: Description of the policy. + escape_special_characters: When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + field_delimiter: Field delimiter for logs. field_separator: Field separator for logs. @@ -638,6 +727,12 @@ async def update( format_type: Format type for logs. + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + include_empty_logs: Include empty logs in the upload. include_shield_logs: Include logs from origin shielding in the upload. @@ -670,6 +765,7 @@ async def update( { "date_format": date_format, "description": description, + "escape_special_characters": escape_special_characters, "field_delimiter": field_delimiter, "field_separator": field_separator, "fields": fields, @@ -831,11 +927,12 @@ async def replace( *, date_format: str | Omit = omit, description: str | Omit = omit, + escape_special_characters: bool | Omit = omit, field_delimiter: str | Omit = omit, field_separator: str | Omit = omit, fields: SequenceNotStr[str] | Omit = omit, file_name_template: str | Omit = omit, - format_type: str | Omit = omit, + format_type: Literal["json", ""] | Omit = omit, include_empty_logs: bool | Omit = omit, include_shield_logs: bool | Omit = omit, name: str | Omit = omit, @@ -859,6 +956,17 @@ async def replace( description: Description of the policy. + escape_special_characters: When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + field_delimiter: Field delimiter for logs. field_separator: Field separator for logs. @@ -869,6 +977,12 @@ async def replace( format_type: Format type for logs. + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + include_empty_logs: Include empty logs in the upload. include_shield_logs: Include logs from origin shielding in the upload. @@ -901,6 +1015,7 @@ async def replace( { "date_format": date_format, "description": description, + "escape_special_characters": escape_special_characters, "field_delimiter": field_delimiter, "field_separator": field_separator, "fields": fields, diff --git a/src/gcore/resources/cloud/__init__.py b/src/gcore/resources/cloud/__init__.py index 36c2a495..df7277aa 100644 --- a/src/gcore/resources/cloud/__init__.py +++ b/src/gcore/resources/cloud/__init__.py @@ -216,6 +216,14 @@ PlacementGroupsResourceWithStreamingResponse, AsyncPlacementGroupsResourceWithStreamingResponse, ) +from .volume_snapshots import ( + VolumeSnapshotsResource, + AsyncVolumeSnapshotsResource, + VolumeSnapshotsResourceWithRawResponse, + AsyncVolumeSnapshotsResourceWithRawResponse, + VolumeSnapshotsResourceWithStreamingResponse, + AsyncVolumeSnapshotsResourceWithStreamingResponse, +) from .reserved_fixed_ips import ( ReservedFixedIPsResource, AsyncReservedFixedIPsResource, @@ -402,6 +410,12 @@ "AsyncDatabasesResourceWithRawResponse", "DatabasesResourceWithStreamingResponse", "AsyncDatabasesResourceWithStreamingResponse", + "VolumeSnapshotsResource", + "AsyncVolumeSnapshotsResource", + "VolumeSnapshotsResourceWithRawResponse", + "AsyncVolumeSnapshotsResourceWithRawResponse", + "VolumeSnapshotsResourceWithStreamingResponse", + "AsyncVolumeSnapshotsResourceWithStreamingResponse", "CloudResource", "AsyncCloudResource", "CloudResourceWithRawResponse", diff --git a/src/gcore/resources/cloud/audit_logs.py b/src/gcore/resources/cloud/audit_logs.py index f92e7daa..f47fa720 100644 --- a/src/gcore/resources/cloud/audit_logs.py +++ b/src/gcore/resources/cloud/audit_logs.py @@ -92,7 +92,6 @@ def list( api_group: List[ Literal[ "ai_cluster", - "backup_service", "caas_container", "caas_key", "caas_pull_secret", @@ -311,7 +310,6 @@ def list( api_group: List[ Literal[ "ai_cluster", - "backup_service", "caas_container", "caas_key", "caas_pull_secret", diff --git a/src/gcore/resources/cloud/cloud.py b/src/gcore/resources/cloud/cloud.py index f8c91a68..47a7caab 100644 --- a/src/gcore/resources/cloud/cloud.py +++ b/src/gcore/resources/cloud/cloud.py @@ -124,6 +124,14 @@ PlacementGroupsResourceWithStreamingResponse, AsyncPlacementGroupsResourceWithStreamingResponse, ) +from .volume_snapshots import ( + VolumeSnapshotsResource, + AsyncVolumeSnapshotsResource, + VolumeSnapshotsResourceWithRawResponse, + AsyncVolumeSnapshotsResourceWithRawResponse, + VolumeSnapshotsResourceWithStreamingResponse, + AsyncVolumeSnapshotsResourceWithStreamingResponse, +) from .networks.networks import ( NetworksResource, AsyncNetworksResource, @@ -352,6 +360,10 @@ def usage_reports(self) -> UsageReportsResource: def databases(self) -> DatabasesResource: return DatabasesResource(self._client) + @cached_property + def volume_snapshots(self) -> VolumeSnapshotsResource: + return VolumeSnapshotsResource(self._client) + @cached_property def with_raw_response(self) -> CloudResourceWithRawResponse: """ @@ -492,6 +504,10 @@ def usage_reports(self) -> AsyncUsageReportsResource: def databases(self) -> AsyncDatabasesResource: return AsyncDatabasesResource(self._client) + @cached_property + def volume_snapshots(self) -> AsyncVolumeSnapshotsResource: + return AsyncVolumeSnapshotsResource(self._client) + @cached_property def with_raw_response(self) -> AsyncCloudResourceWithRawResponse: """ @@ -635,6 +651,10 @@ def usage_reports(self) -> UsageReportsResourceWithRawResponse: def databases(self) -> DatabasesResourceWithRawResponse: return DatabasesResourceWithRawResponse(self._cloud.databases) + @cached_property + def volume_snapshots(self) -> VolumeSnapshotsResourceWithRawResponse: + return VolumeSnapshotsResourceWithRawResponse(self._cloud.volume_snapshots) + class AsyncCloudResourceWithRawResponse: def __init__(self, cloud: AsyncCloudResource) -> None: @@ -759,6 +779,10 @@ def usage_reports(self) -> AsyncUsageReportsResourceWithRawResponse: def databases(self) -> AsyncDatabasesResourceWithRawResponse: return AsyncDatabasesResourceWithRawResponse(self._cloud.databases) + @cached_property + def volume_snapshots(self) -> AsyncVolumeSnapshotsResourceWithRawResponse: + return AsyncVolumeSnapshotsResourceWithRawResponse(self._cloud.volume_snapshots) + class CloudResourceWithStreamingResponse: def __init__(self, cloud: CloudResource) -> None: @@ -883,6 +907,10 @@ def usage_reports(self) -> UsageReportsResourceWithStreamingResponse: def databases(self) -> DatabasesResourceWithStreamingResponse: return DatabasesResourceWithStreamingResponse(self._cloud.databases) + @cached_property + def volume_snapshots(self) -> VolumeSnapshotsResourceWithStreamingResponse: + return VolumeSnapshotsResourceWithStreamingResponse(self._cloud.volume_snapshots) + class AsyncCloudResourceWithStreamingResponse: def __init__(self, cloud: AsyncCloudResource) -> None: @@ -1006,3 +1034,7 @@ def usage_reports(self) -> AsyncUsageReportsResourceWithStreamingResponse: @cached_property def databases(self) -> AsyncDatabasesResourceWithStreamingResponse: return AsyncDatabasesResourceWithStreamingResponse(self._cloud.databases) + + @cached_property + def volume_snapshots(self) -> AsyncVolumeSnapshotsResourceWithStreamingResponse: + return AsyncVolumeSnapshotsResourceWithStreamingResponse(self._cloud.volume_snapshots) diff --git a/src/gcore/resources/cloud/floating_ips.py b/src/gcore/resources/cloud/floating_ips.py index 319627bc..a2cfd223 100644 --- a/src/gcore/resources/cloud/floating_ips.py +++ b/src/gcore/resources/cloud/floating_ips.py @@ -2,6 +2,7 @@ from __future__ import annotations +import typing_extensions from typing import Dict, Optional import httpx @@ -123,6 +124,7 @@ def create( cast_to=TaskIDList, ) + @typing_extensions.deprecated("deprecated") def update( self, floating_ip_id: str, @@ -138,7 +140,8 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FloatingIP: """ - Update floating IP + **Deprecated**: Use PATCH + /v2/floatingips/{`project_id`}/{`region_id`}/{`floating_ip_id`} instead Args: project_id: Project ID @@ -313,6 +316,7 @@ def delete( cast_to=TaskIDList, ) + @typing_extensions.deprecated("deprecated") def assign( self, floating_ip_id: str, @@ -331,7 +335,16 @@ def assign( """ Assign floating IP to instance or loadbalancer + **Deprecated**: Use PATCH + /v2/floatingips/{`project_id`}/{`region_id`}/{`floating_ip_id`} instead + Args: + project_id: Project ID + + region_id: Region ID + + floating_ip_id: Floating IP ID + port_id: Port ID fixed_ip_address: Fixed IP address @@ -410,6 +423,7 @@ def get( cast_to=FloatingIP, ) + @typing_extensions.deprecated("deprecated") def unassign( self, floating_ip_id: str, @@ -424,9 +438,16 @@ def unassign( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FloatingIP: """ - Unassign floating IP + **Deprecated**: Use PATCH + /v2/floatingips/{`project_id`}/{`region_id`}/{`floating_ip_id`} instead Args: + project_id: Project ID + + region_id: Region ID + + floating_ip_id: Floating IP ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -627,6 +648,7 @@ async def create( cast_to=TaskIDList, ) + @typing_extensions.deprecated("deprecated") async def update( self, floating_ip_id: str, @@ -642,7 +664,8 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FloatingIP: """ - Update floating IP + **Deprecated**: Use PATCH + /v2/floatingips/{`project_id`}/{`region_id`}/{`floating_ip_id`} instead Args: project_id: Project ID @@ -817,6 +840,7 @@ async def delete( cast_to=TaskIDList, ) + @typing_extensions.deprecated("deprecated") async def assign( self, floating_ip_id: str, @@ -835,7 +859,16 @@ async def assign( """ Assign floating IP to instance or loadbalancer + **Deprecated**: Use PATCH + /v2/floatingips/{`project_id`}/{`region_id`}/{`floating_ip_id`} instead + Args: + project_id: Project ID + + region_id: Region ID + + floating_ip_id: Floating IP ID + port_id: Port ID fixed_ip_address: Fixed IP address @@ -914,6 +947,7 @@ async def get( cast_to=FloatingIP, ) + @typing_extensions.deprecated("deprecated") async def unassign( self, floating_ip_id: str, @@ -928,9 +962,16 @@ async def unassign( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FloatingIP: """ - Unassign floating IP + **Deprecated**: Use PATCH + /v2/floatingips/{`project_id`}/{`region_id`}/{`floating_ip_id`} instead Args: + project_id: Project ID + + region_id: Region ID + + floating_ip_id: Floating IP ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1049,8 +1090,10 @@ def __init__(self, floating_ips: FloatingIPsResource) -> None: self.create = to_raw_response_wrapper( floating_ips.create, ) - self.update = to_raw_response_wrapper( - floating_ips.update, + self.update = ( # pyright: ignore[reportDeprecated] + to_raw_response_wrapper( + floating_ips.update, # pyright: ignore[reportDeprecated], + ) ) self.list = to_raw_response_wrapper( floating_ips.list, @@ -1058,14 +1101,18 @@ def __init__(self, floating_ips: FloatingIPsResource) -> None: self.delete = to_raw_response_wrapper( floating_ips.delete, ) - self.assign = to_raw_response_wrapper( - floating_ips.assign, + self.assign = ( # pyright: ignore[reportDeprecated] + to_raw_response_wrapper( + floating_ips.assign, # pyright: ignore[reportDeprecated], + ) ) self.get = to_raw_response_wrapper( floating_ips.get, ) - self.unassign = to_raw_response_wrapper( - floating_ips.unassign, + self.unassign = ( # pyright: ignore[reportDeprecated] + to_raw_response_wrapper( + floating_ips.unassign, # pyright: ignore[reportDeprecated], + ) ) self.create_and_poll = to_raw_response_wrapper( floating_ips.create_and_poll, @@ -1082,8 +1129,10 @@ def __init__(self, floating_ips: AsyncFloatingIPsResource) -> None: self.create = async_to_raw_response_wrapper( floating_ips.create, ) - self.update = async_to_raw_response_wrapper( - floating_ips.update, + self.update = ( # pyright: ignore[reportDeprecated] + async_to_raw_response_wrapper( + floating_ips.update, # pyright: ignore[reportDeprecated], + ) ) self.list = async_to_raw_response_wrapper( floating_ips.list, @@ -1091,14 +1140,18 @@ def __init__(self, floating_ips: AsyncFloatingIPsResource) -> None: self.delete = async_to_raw_response_wrapper( floating_ips.delete, ) - self.assign = async_to_raw_response_wrapper( - floating_ips.assign, + self.assign = ( # pyright: ignore[reportDeprecated] + async_to_raw_response_wrapper( + floating_ips.assign, # pyright: ignore[reportDeprecated], + ) ) self.get = async_to_raw_response_wrapper( floating_ips.get, ) - self.unassign = async_to_raw_response_wrapper( - floating_ips.unassign, + self.unassign = ( # pyright: ignore[reportDeprecated] + async_to_raw_response_wrapper( + floating_ips.unassign, # pyright: ignore[reportDeprecated], + ) ) self.create_and_poll = async_to_raw_response_wrapper( floating_ips.create_and_poll, @@ -1115,8 +1168,10 @@ def __init__(self, floating_ips: FloatingIPsResource) -> None: self.create = to_streamed_response_wrapper( floating_ips.create, ) - self.update = to_streamed_response_wrapper( - floating_ips.update, + self.update = ( # pyright: ignore[reportDeprecated] + to_streamed_response_wrapper( + floating_ips.update, # pyright: ignore[reportDeprecated], + ) ) self.list = to_streamed_response_wrapper( floating_ips.list, @@ -1124,14 +1179,18 @@ def __init__(self, floating_ips: FloatingIPsResource) -> None: self.delete = to_streamed_response_wrapper( floating_ips.delete, ) - self.assign = to_streamed_response_wrapper( - floating_ips.assign, + self.assign = ( # pyright: ignore[reportDeprecated] + to_streamed_response_wrapper( + floating_ips.assign, # pyright: ignore[reportDeprecated], + ) ) self.get = to_streamed_response_wrapper( floating_ips.get, ) - self.unassign = to_streamed_response_wrapper( - floating_ips.unassign, + self.unassign = ( # pyright: ignore[reportDeprecated] + to_streamed_response_wrapper( + floating_ips.unassign, # pyright: ignore[reportDeprecated], + ) ) self.create_and_poll = to_streamed_response_wrapper( floating_ips.create_and_poll, @@ -1148,8 +1207,10 @@ def __init__(self, floating_ips: AsyncFloatingIPsResource) -> None: self.create = async_to_streamed_response_wrapper( floating_ips.create, ) - self.update = async_to_streamed_response_wrapper( - floating_ips.update, + self.update = ( # pyright: ignore[reportDeprecated] + async_to_streamed_response_wrapper( + floating_ips.update, # pyright: ignore[reportDeprecated], + ) ) self.list = async_to_streamed_response_wrapper( floating_ips.list, @@ -1157,14 +1218,18 @@ def __init__(self, floating_ips: AsyncFloatingIPsResource) -> None: self.delete = async_to_streamed_response_wrapper( floating_ips.delete, ) - self.assign = async_to_streamed_response_wrapper( - floating_ips.assign, + self.assign = ( # pyright: ignore[reportDeprecated] + async_to_streamed_response_wrapper( + floating_ips.assign, # pyright: ignore[reportDeprecated], + ) ) self.get = async_to_streamed_response_wrapper( floating_ips.get, ) - self.unassign = async_to_streamed_response_wrapper( - floating_ips.unassign, + self.unassign = ( # pyright: ignore[reportDeprecated] + async_to_streamed_response_wrapper( + floating_ips.unassign, # pyright: ignore[reportDeprecated], + ) ) self.create_and_poll = async_to_streamed_response_wrapper( floating_ips.create_and_poll, diff --git a/src/gcore/resources/cloud/load_balancers/flavors.py b/src/gcore/resources/cloud/load_balancers/flavors.py index 8d126cd7..df4739a5 100644 --- a/src/gcore/resources/cloud/load_balancers/flavors.py +++ b/src/gcore/resources/cloud/load_balancers/flavors.py @@ -61,6 +61,10 @@ def list( price values as 0. If you get Pricing Error contact the support Args: + project_id: Project ID + + region_id: Region ID + include_prices: Set to true if the response should include flavor prices extra_headers: Send extra headers @@ -128,6 +132,10 @@ async def list( price values as 0. If you get Pricing Error contact the support Args: + project_id: Project ID + + region_id: Region ID + include_prices: Set to true if the response should include flavor prices extra_headers: Send extra headers diff --git a/src/gcore/resources/cloud/load_balancers/listeners.py b/src/gcore/resources/cloud/load_balancers/listeners.py index fe0177c0..518b61b1 100644 --- a/src/gcore/resources/cloud/load_balancers/listeners.py +++ b/src/gcore/resources/cloud/load_balancers/listeners.py @@ -113,9 +113,11 @@ def create( timeout_client_data: Frontend client inactivity timeout in milliseconds - timeout_member_connect: Backend member connection timeout in milliseconds + timeout_member_connect: Backend member connection timeout in milliseconds. We are recommending to use + `pool.timeout_member_connect` instead. - timeout_member_data: Backend member inactivity timeout in milliseconds + timeout_member_data: Backend member inactivity timeout in milliseconds. We are recommending to use + `pool.timeout_member_data` instead. user_list: Load balancer listener list of username and encrypted password items @@ -205,9 +207,11 @@ def update( timeout_client_data: Frontend client inactivity timeout in milliseconds - timeout_member_connect: Backend member connection timeout in milliseconds + timeout_member_connect: Backend member connection timeout in milliseconds. We are recommending to use + `pool.timeout_member_connect` instead. - timeout_member_data: Backend member inactivity timeout in milliseconds + timeout_member_data: Backend member inactivity timeout in milliseconds. We are recommending to use + `pool.timeout_member_data` instead. user_list: Load balancer listener users list @@ -657,9 +661,11 @@ async def create( timeout_client_data: Frontend client inactivity timeout in milliseconds - timeout_member_connect: Backend member connection timeout in milliseconds + timeout_member_connect: Backend member connection timeout in milliseconds. We are recommending to use + `pool.timeout_member_connect` instead. - timeout_member_data: Backend member inactivity timeout in milliseconds + timeout_member_data: Backend member inactivity timeout in milliseconds. We are recommending to use + `pool.timeout_member_data` instead. user_list: Load balancer listener list of username and encrypted password items @@ -749,9 +755,11 @@ async def update( timeout_client_data: Frontend client inactivity timeout in milliseconds - timeout_member_connect: Backend member connection timeout in milliseconds + timeout_member_connect: Backend member connection timeout in milliseconds. We are recommending to use + `pool.timeout_member_connect` instead. - timeout_member_data: Backend member inactivity timeout in milliseconds + timeout_member_data: Backend member inactivity timeout in milliseconds. We are recommending to use + `pool.timeout_member_data` instead. user_list: Load balancer listener users list diff --git a/src/gcore/resources/cloud/load_balancers/load_balancers.py b/src/gcore/resources/cloud/load_balancers/load_balancers.py index 3674e809..f25262eb 100644 --- a/src/gcore/resources/cloud/load_balancers/load_balancers.py +++ b/src/gcore/resources/cloud/load_balancers/load_balancers.py @@ -3,6 +3,7 @@ from __future__ import annotations from typing import Dict, Iterable, Optional +from typing_extensions import Literal import httpx @@ -157,6 +158,10 @@ def create( Create load balancer Args: + project_id: Project ID + + region_id: Region ID + flavor: Load balancer flavor name floating_ip: Floating IP configuration for assignment @@ -257,6 +262,12 @@ def update( remain unchanged. Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + logging: Logging configuration name: Name. @@ -332,7 +343,25 @@ def list( logging_enabled: bool | Omit = omit, name: str | Omit = omit, offset: int | Omit = omit, - order_by: str | Omit = omit, + order_by: Literal[ + "created_at.asc", + "created_at.desc", + "flavor.asc", + "flavor.desc", + "name.asc", + "name.desc", + "operating_status.asc", + "operating_status.desc", + "provisioning_status.asc", + "provisioning_status.desc", + "updated_at.asc", + "updated_at.desc", + "vip_address.asc", + "vip_address.desc", + "vip_ip_family.asc", + "vip_ip_family.desc", + ] + | Omit = omit, show_stats: bool | Omit = omit, tag_key: SequenceNotStr[str] | Omit = omit, tag_key_value: str | Omit = omit, @@ -348,26 +377,27 @@ def list( List load balancers Args: + project_id: Project ID + + region_id: Region ID + assigned_floating: With or without assigned floating IP - limit: Limit the number of returned limit request entities. + limit: Limit of items on a single page - logging_enabled: With or without logging + logging_enabled: With or without logging enabled name: Filter by name - offset: Offset value is used to exclude the first set of records from the result. + offset: Offset in results list - order_by: Ordering Load Balancer list result by name, `created_at`, `updated_at`, - `operating_status`, `provisioning_status`, `vip_address`, `vip_ip_family` and - flavor fields of the load balancer and directions (name.asc), default is - "`created_at`.asc" + order_by: Order by field and direction. show_stats: Show statistics - tag_key: Filter by tag keys. + tag_key: Optional. Filter by tag keys. ?`tag_key`=key1&`tag_key`=key2 - tag_key_value: Filter by tag key-value pairs. Must be a valid JSON string. + tag_key_value: Optional. Filter by tag key-value pairs. with_ddos: Show Advanced DDoS protection profile, if exists @@ -621,6 +651,12 @@ def delete( Delete load balancer Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -661,6 +697,12 @@ def failover( Failover load balancer Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + force: Validate current load balancer status before failover or not. extra_headers: Send extra headers @@ -705,9 +747,15 @@ def get( Get load balancer Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + show_stats: Show statistics - with_ddos: Show DDoS profile + with_ddos: Show Advanced DDoS protection profile, if exists extra_headers: Send extra headers @@ -759,6 +807,12 @@ def resize( Resize load balancer Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + flavor: Name of the desired flavor to resize to. extra_headers: Send extra headers @@ -857,6 +911,10 @@ async def create( Create load balancer Args: + project_id: Project ID + + region_id: Region ID + flavor: Load balancer flavor name floating_ip: Floating IP configuration for assignment @@ -957,6 +1015,12 @@ async def update( remain unchanged. Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + logging: Logging configuration name: Name. @@ -1032,7 +1096,25 @@ def list( logging_enabled: bool | Omit = omit, name: str | Omit = omit, offset: int | Omit = omit, - order_by: str | Omit = omit, + order_by: Literal[ + "created_at.asc", + "created_at.desc", + "flavor.asc", + "flavor.desc", + "name.asc", + "name.desc", + "operating_status.asc", + "operating_status.desc", + "provisioning_status.asc", + "provisioning_status.desc", + "updated_at.asc", + "updated_at.desc", + "vip_address.asc", + "vip_address.desc", + "vip_ip_family.asc", + "vip_ip_family.desc", + ] + | Omit = omit, show_stats: bool | Omit = omit, tag_key: SequenceNotStr[str] | Omit = omit, tag_key_value: str | Omit = omit, @@ -1048,26 +1130,27 @@ def list( List load balancers Args: + project_id: Project ID + + region_id: Region ID + assigned_floating: With or without assigned floating IP - limit: Limit the number of returned limit request entities. + limit: Limit of items on a single page - logging_enabled: With or without logging + logging_enabled: With or without logging enabled name: Filter by name - offset: Offset value is used to exclude the first set of records from the result. + offset: Offset in results list - order_by: Ordering Load Balancer list result by name, `created_at`, `updated_at`, - `operating_status`, `provisioning_status`, `vip_address`, `vip_ip_family` and - flavor fields of the load balancer and directions (name.asc), default is - "`created_at`.asc" + order_by: Order by field and direction. show_stats: Show statistics - tag_key: Filter by tag keys. + tag_key: Optional. Filter by tag keys. ?`tag_key`=key1&`tag_key`=key2 - tag_key_value: Filter by tag key-value pairs. Must be a valid JSON string. + tag_key_value: Optional. Filter by tag key-value pairs. with_ddos: Show Advanced DDoS protection profile, if exists @@ -1321,6 +1404,12 @@ async def delete( Delete load balancer Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1361,6 +1450,12 @@ async def failover( Failover load balancer Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + force: Validate current load balancer status before failover or not. extra_headers: Send extra headers @@ -1407,9 +1502,15 @@ async def get( Get load balancer Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + show_stats: Show statistics - with_ddos: Show DDoS profile + with_ddos: Show Advanced DDoS protection profile, if exists extra_headers: Send extra headers @@ -1461,6 +1562,12 @@ async def resize( Resize load balancer Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + flavor: Name of the desired flavor to resize to. extra_headers: Send extra headers diff --git a/src/gcore/resources/cloud/load_balancers/metrics.py b/src/gcore/resources/cloud/load_balancers/metrics.py index e7647609..a66adc6e 100644 --- a/src/gcore/resources/cloud/load_balancers/metrics.py +++ b/src/gcore/resources/cloud/load_balancers/metrics.py @@ -62,6 +62,12 @@ def list( Get load balancer metrics, including cpu, memory and network Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + time_interval: Time interval time_unit: Time interval unit @@ -135,6 +141,12 @@ async def list( Get load balancer metrics, including cpu, memory and network Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + time_interval: Time interval time_unit: Time interval unit diff --git a/src/gcore/resources/cloud/load_balancers/pools/pools.py b/src/gcore/resources/cloud/load_balancers/pools/pools.py index 121406f7..5b5b7909 100644 --- a/src/gcore/resources/cloud/load_balancers/pools/pools.py +++ b/src/gcore/resources/cloud/load_balancers/pools/pools.py @@ -128,7 +128,8 @@ def create( session_persistence: Session persistence details - timeout_client_data: Frontend client inactivity timeout in milliseconds + timeout_client_data: Frontend client inactivity timeout in milliseconds. We are recommending to use + `listener.timeout_client_data` instead. timeout_member_connect: Backend member connection timeout in milliseconds @@ -244,7 +245,8 @@ def update( session_persistence: New session persistence settings - timeout_client_data: Frontend client inactivity timeout in milliseconds + timeout_client_data: Frontend client inactivity timeout in milliseconds. We are recommending to use + `listener.timeout_client_data` instead. timeout_member_connect: Backend member connection timeout in milliseconds @@ -695,7 +697,8 @@ async def create( session_persistence: Session persistence details - timeout_client_data: Frontend client inactivity timeout in milliseconds + timeout_client_data: Frontend client inactivity timeout in milliseconds. We are recommending to use + `listener.timeout_client_data` instead. timeout_member_connect: Backend member connection timeout in milliseconds @@ -811,7 +814,8 @@ async def update( session_persistence: New session persistence settings - timeout_client_data: Frontend client inactivity timeout in milliseconds + timeout_client_data: Frontend client inactivity timeout in milliseconds. We are recommending to use + `listener.timeout_client_data` instead. timeout_member_connect: Backend member connection timeout in milliseconds diff --git a/src/gcore/resources/cloud/load_balancers/statuses.py b/src/gcore/resources/cloud/load_balancers/statuses.py index e537b073..c2711ddd 100644 --- a/src/gcore/resources/cloud/load_balancers/statuses.py +++ b/src/gcore/resources/cloud/load_balancers/statuses.py @@ -56,6 +56,10 @@ def list( List load balancers statuses Args: + project_id: Project ID + + region_id: Region ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -93,6 +97,12 @@ def get( Get load balancer status Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -152,6 +162,10 @@ async def list( List load balancers statuses Args: + project_id: Project ID + + region_id: Region ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -189,6 +203,12 @@ async def get( Get load balancer status Args: + project_id: Project ID + + region_id: Region ID + + load_balancer_id: Load-Balancer ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request diff --git a/src/gcore/resources/cloud/networks/routers.py b/src/gcore/resources/cloud/networks/routers.py index 52cf6cf8..b9a03134 100644 --- a/src/gcore/resources/cloud/networks/routers.py +++ b/src/gcore/resources/cloud/networks/routers.py @@ -124,8 +124,10 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Router: - """ - Update the configuration of an existing router. + """Update the configuration of an existing router. + + **Deprecated**: Use PATCH + /v2/routers/{`project_id`}/{`region_id`}/{`router_id`} Args: external_gateway_info: New external gateway. @@ -491,8 +493,10 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Router: - """ - Update the configuration of an existing router. + """Update the configuration of an existing router. + + **Deprecated**: Use PATCH + /v2/routers/{`project_id`}/{`region_id`}/{`router_id`} Args: external_gateway_info: New external gateway. diff --git a/src/gcore/resources/cloud/networks/subnets.py b/src/gcore/resources/cloud/networks/subnets.py index 7c123a14..f1ea953f 100644 --- a/src/gcore/resources/cloud/networks/subnets.py +++ b/src/gcore/resources/cloud/networks/subnets.py @@ -218,7 +218,7 @@ def update( project_id: int | None = None, region_id: int | None = None, dns_nameservers: Optional[SequenceNotStr[str]] | Omit = omit, - enable_dhcp: Optional[bool] | Omit = omit, + enable_dhcp: bool | Omit = omit, gateway_ip: Optional[str] | Omit = omit, host_routes: Optional[Iterable[subnet_update_params.HostRoute]] | Omit = omit, name: Optional[str] | Omit = omit, @@ -683,7 +683,7 @@ async def update( project_id: int | None = None, region_id: int | None = None, dns_nameservers: Optional[SequenceNotStr[str]] | Omit = omit, - enable_dhcp: Optional[bool] | Omit = omit, + enable_dhcp: bool | Omit = omit, gateway_ip: Optional[str] | Omit = omit, host_routes: Optional[Iterable[subnet_update_params.HostRoute]] | Omit = omit, name: Optional[str] | Omit = omit, diff --git a/src/gcore/resources/cloud/quotas/requests.py b/src/gcore/resources/cloud/quotas/requests.py index 5d778e27..5a12175b 100644 --- a/src/gcore/resources/cloud/quotas/requests.py +++ b/src/gcore/resources/cloud/quotas/requests.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import List +from typing import List, Union, Iterable +from datetime import datetime from typing_extensions import Literal import httpx @@ -93,8 +94,11 @@ def create( def list( self, *, + created_from: Union[str, datetime] | Omit = omit, + created_to: Union[str, datetime] | Omit = omit, limit: int | Omit = omit, offset: int | Omit = omit, + request_ids: Iterable[int] | Omit = omit, status: List[Literal["done", "in progress", "rejected"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -107,11 +111,17 @@ def list( Get a list of sent requests to change current quotas and their statuses. Args: + created_from: Filter limit requests created at or after this datetime (inclusive) + + created_to: Filter limit requests created at or before this datetime (inclusive) + limit: Optional. Limit the number of returned items offset: Optional. Offset value is used to exclude the first set of records from the result + request_ids: List of limit request IDs for filtering + status: List of limit requests statuses for filtering extra_headers: Send extra headers @@ -132,8 +142,11 @@ def list( timeout=timeout, query=maybe_transform( { + "created_from": created_from, + "created_to": created_to, "limit": limit, "offset": offset, + "request_ids": request_ids, "status": status, }, request_list_params.RequestListParams, @@ -277,8 +290,11 @@ async def create( def list( self, *, + created_from: Union[str, datetime] | Omit = omit, + created_to: Union[str, datetime] | Omit = omit, limit: int | Omit = omit, offset: int | Omit = omit, + request_ids: Iterable[int] | Omit = omit, status: List[Literal["done", "in progress", "rejected"]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -291,11 +307,17 @@ def list( Get a list of sent requests to change current quotas and their statuses. Args: + created_from: Filter limit requests created at or after this datetime (inclusive) + + created_to: Filter limit requests created at or before this datetime (inclusive) + limit: Optional. Limit the number of returned items offset: Optional. Offset value is used to exclude the first set of records from the result + request_ids: List of limit request IDs for filtering + status: List of limit requests statuses for filtering extra_headers: Send extra headers @@ -316,8 +338,11 @@ def list( timeout=timeout, query=maybe_transform( { + "created_from": created_from, + "created_to": created_to, "limit": limit, "offset": offset, + "request_ids": request_ids, "status": status, }, request_list_params.RequestListParams, diff --git a/src/gcore/resources/cloud/security_groups/rules.py b/src/gcore/resources/cloud/security_groups/rules.py index aacd3921..dc4cdfa2 100644 --- a/src/gcore/resources/cloud/security_groups/rules.py +++ b/src/gcore/resources/cloud/security_groups/rules.py @@ -50,8 +50,8 @@ def create( *, project_id: int | None = None, region_id: int | None = None, + direction: Literal["egress", "ingress"], description: str | Omit = omit, - direction: Literal["egress", "ingress"] | Omit = omit, ethertype: Literal["IPv4", "IPv6"] | Omit = omit, port_range_max: Optional[int] | Omit = omit, port_range_min: Optional[int] | Omit = omit, @@ -95,10 +95,16 @@ def create( Add a new rule to an existing security group. Args: - description: Rule description + project_id: Project ID + + region_id: Region ID + + group_id: Group ID direction: Ingress or egress, which is the direction in which the security group is applied + description: Rule description + ethertype: Ether type port_range_max: The maximum port number in the range that is matched by the security group rule @@ -129,8 +135,8 @@ def create( f"/cloud/v1/securitygroups/{project_id}/{region_id}/{group_id}/rules", body=maybe_transform( { - "description": description, "direction": direction, + "description": description, "ethertype": ethertype, "port_range_max": port_range_max, "port_range_min": port_range_min, @@ -163,6 +169,12 @@ def delete( Delete a specific rule from a security group. Args: + project_id: Project ID + + region_id: Region ID + + rule_id: Rule ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -238,6 +250,12 @@ def replace( Update the configuration of an existing security group rule. Args: + project_id: Project ID + + region_id: Region ID + + rule_id: Rule ID + direction: Ingress or egress, which is the direction in which the security group rule is applied @@ -321,8 +339,8 @@ async def create( *, project_id: int | None = None, region_id: int | None = None, + direction: Literal["egress", "ingress"], description: str | Omit = omit, - direction: Literal["egress", "ingress"] | Omit = omit, ethertype: Literal["IPv4", "IPv6"] | Omit = omit, port_range_max: Optional[int] | Omit = omit, port_range_min: Optional[int] | Omit = omit, @@ -366,10 +384,16 @@ async def create( Add a new rule to an existing security group. Args: - description: Rule description + project_id: Project ID + + region_id: Region ID + + group_id: Group ID direction: Ingress or egress, which is the direction in which the security group is applied + description: Rule description + ethertype: Ether type port_range_max: The maximum port number in the range that is matched by the security group rule @@ -400,8 +424,8 @@ async def create( f"/cloud/v1/securitygroups/{project_id}/{region_id}/{group_id}/rules", body=await async_maybe_transform( { - "description": description, "direction": direction, + "description": description, "ethertype": ethertype, "port_range_max": port_range_max, "port_range_min": port_range_min, @@ -434,6 +458,12 @@ async def delete( Delete a specific rule from a security group. Args: + project_id: Project ID + + region_id: Region ID + + rule_id: Rule ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -509,6 +539,12 @@ async def replace( Update the configuration of an existing security group rule. Args: + project_id: Project ID + + region_id: Region ID + + rule_id: Rule ID + direction: Ingress or egress, which is the direction in which the security group rule is applied diff --git a/src/gcore/resources/cloud/security_groups/security_groups.py b/src/gcore/resources/cloud/security_groups/security_groups.py index ca0d7b65..a287b6bf 100644 --- a/src/gcore/resources/cloud/security_groups/security_groups.py +++ b/src/gcore/resources/cloud/security_groups/security_groups.py @@ -2,6 +2,7 @@ from __future__ import annotations +import typing_extensions from typing import Iterable, Optional import httpx @@ -62,6 +63,7 @@ def with_streaming_response(self) -> SecurityGroupsResourceWithStreamingResponse """ return SecurityGroupsResourceWithStreamingResponse(self) + @typing_extensions.deprecated("deprecated") def create( self, *, @@ -77,7 +79,7 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecurityGroup: """ - Create a new security group with the specified configuration. + **Deprecated** Use `/v2/security_groups//` instead. Args: project_id: Project ID @@ -115,6 +117,7 @@ def create( cast_to=SecurityGroup, ) + @typing_extensions.deprecated("deprecated") def update( self, group_id: str, @@ -132,9 +135,16 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecurityGroup: """ - Update the configuration of an existing security group. + **Deprecated** Use `/v2/security_groups///` + instead. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + changed_rules: List of rules to create or delete name: Name @@ -202,6 +212,7 @@ def list( project_id: int | None = None, region_id: int | None = None, limit: int | Omit = omit, + name: str | Omit = omit, offset: int | Omit = omit, tag_key: SequenceNotStr[str] | Omit = omit, tag_key_value: str | Omit = omit, @@ -222,6 +233,8 @@ def list( limit: Limit of items on a single page + name: Optional. Filter by name. Must be specified a full name of the security group. + offset: Offset in results list tag_key: Optional. Filter by tag keys. ?`tag_key`=key1&`tag_key`=key2 @@ -251,6 +264,7 @@ def list( query=maybe_transform( { "limit": limit, + "name": name, "offset": offset, "tag_key": tag_key, "tag_key_value": tag_key_value, @@ -278,6 +292,12 @@ def delete( Delete a specific security group and all its associated rules. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -319,6 +339,12 @@ def copy( Create a deep copy of an existing security group. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + name: Name. extra_headers: Send extra headers @@ -361,6 +387,12 @@ def get( Get detailed information about a specific security group. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -400,6 +432,12 @@ def revert_to_default( Revert a security group to its previous state. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -447,6 +485,7 @@ def with_streaming_response(self) -> AsyncSecurityGroupsResourceWithStreamingRes """ return AsyncSecurityGroupsResourceWithStreamingResponse(self) + @typing_extensions.deprecated("deprecated") async def create( self, *, @@ -462,7 +501,7 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecurityGroup: """ - Create a new security group with the specified configuration. + **Deprecated** Use `/v2/security_groups//` instead. Args: project_id: Project ID @@ -500,6 +539,7 @@ async def create( cast_to=SecurityGroup, ) + @typing_extensions.deprecated("deprecated") async def update( self, group_id: str, @@ -517,9 +557,16 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SecurityGroup: """ - Update the configuration of an existing security group. + **Deprecated** Use `/v2/security_groups///` + instead. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + changed_rules: List of rules to create or delete name: Name @@ -587,6 +634,7 @@ def list( project_id: int | None = None, region_id: int | None = None, limit: int | Omit = omit, + name: str | Omit = omit, offset: int | Omit = omit, tag_key: SequenceNotStr[str] | Omit = omit, tag_key_value: str | Omit = omit, @@ -607,6 +655,8 @@ def list( limit: Limit of items on a single page + name: Optional. Filter by name. Must be specified a full name of the security group. + offset: Offset in results list tag_key: Optional. Filter by tag keys. ?`tag_key`=key1&`tag_key`=key2 @@ -636,6 +686,7 @@ def list( query=maybe_transform( { "limit": limit, + "name": name, "offset": offset, "tag_key": tag_key, "tag_key_value": tag_key_value, @@ -663,6 +714,12 @@ async def delete( Delete a specific security group and all its associated rules. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -704,6 +761,12 @@ async def copy( Create a deep copy of an existing security group. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + name: Name. extra_headers: Send extra headers @@ -746,6 +809,12 @@ async def get( Get detailed information about a specific security group. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -785,6 +854,12 @@ async def revert_to_default( Revert a security group to its previous state. Args: + project_id: Project ID + + region_id: Region ID + + group_id: Group ID + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -812,11 +887,15 @@ class SecurityGroupsResourceWithRawResponse: def __init__(self, security_groups: SecurityGroupsResource) -> None: self._security_groups = security_groups - self.create = to_raw_response_wrapper( - security_groups.create, + self.create = ( # pyright: ignore[reportDeprecated] + to_raw_response_wrapper( + security_groups.create, # pyright: ignore[reportDeprecated], + ) ) - self.update = to_raw_response_wrapper( - security_groups.update, + self.update = ( # pyright: ignore[reportDeprecated] + to_raw_response_wrapper( + security_groups.update, # pyright: ignore[reportDeprecated], + ) ) self.list = to_raw_response_wrapper( security_groups.list, @@ -843,11 +922,15 @@ class AsyncSecurityGroupsResourceWithRawResponse: def __init__(self, security_groups: AsyncSecurityGroupsResource) -> None: self._security_groups = security_groups - self.create = async_to_raw_response_wrapper( - security_groups.create, + self.create = ( # pyright: ignore[reportDeprecated] + async_to_raw_response_wrapper( + security_groups.create, # pyright: ignore[reportDeprecated], + ) ) - self.update = async_to_raw_response_wrapper( - security_groups.update, + self.update = ( # pyright: ignore[reportDeprecated] + async_to_raw_response_wrapper( + security_groups.update, # pyright: ignore[reportDeprecated], + ) ) self.list = async_to_raw_response_wrapper( security_groups.list, @@ -874,11 +957,15 @@ class SecurityGroupsResourceWithStreamingResponse: def __init__(self, security_groups: SecurityGroupsResource) -> None: self._security_groups = security_groups - self.create = to_streamed_response_wrapper( - security_groups.create, + self.create = ( # pyright: ignore[reportDeprecated] + to_streamed_response_wrapper( + security_groups.create, # pyright: ignore[reportDeprecated], + ) ) - self.update = to_streamed_response_wrapper( - security_groups.update, + self.update = ( # pyright: ignore[reportDeprecated] + to_streamed_response_wrapper( + security_groups.update, # pyright: ignore[reportDeprecated], + ) ) self.list = to_streamed_response_wrapper( security_groups.list, @@ -905,11 +992,15 @@ class AsyncSecurityGroupsResourceWithStreamingResponse: def __init__(self, security_groups: AsyncSecurityGroupsResource) -> None: self._security_groups = security_groups - self.create = async_to_streamed_response_wrapper( - security_groups.create, + self.create = ( # pyright: ignore[reportDeprecated] + async_to_streamed_response_wrapper( + security_groups.create, # pyright: ignore[reportDeprecated], + ) ) - self.update = async_to_streamed_response_wrapper( - security_groups.update, + self.update = ( # pyright: ignore[reportDeprecated] + async_to_streamed_response_wrapper( + security_groups.update, # pyright: ignore[reportDeprecated], + ) ) self.list = async_to_streamed_response_wrapper( security_groups.list, diff --git a/src/gcore/resources/cloud/tasks.py b/src/gcore/resources/cloud/tasks.py index c8449a3a..a566b03d 100644 --- a/src/gcore/resources/cloud/tasks.py +++ b/src/gcore/resources/cloud/tasks.py @@ -152,9 +152,9 @@ def list( '`create_l7rule`', '`create_lblistener`', '`create_lbmember`', '`create_lbpool`', '`create_lbpool_health_monitor`', '`create_loadbalancer`', '`create_network`', '`create_reserved_fixed_ip`', '`create_router`', - '`create_secret`', '`create_servergroup`', '`create_sfs`', '`create_snapshot`', - '`create_subnet`', '`create_vm`', '`create_volume`', - '`deactivate_ddos_profile`', '`delete_ai_cluster_gpu`', + '`create_secret`', '`create_security_group`', '`create_servergroup`', + '`create_sfs`', '`create_snapshot`', '`create_subnet`', '`create_vm`', + '`create_volume`', '`deactivate_ddos_profile`', '`delete_ai_cluster_gpu`', '`delete_caas_container`', '`delete_dbaas_postgres_cluster`', '`delete_ddos_profile`', '`delete_faas_function`', '`delete_faas_namespace`', '`delete_fip`', '`delete_gpu_virtual_cluster`', '`delete_gpu_virtual_server`', @@ -182,11 +182,12 @@ def list( '`start_gpu_virtual_server`', '`start_vm`', '`stop_gpu_baremetal_server`', '`stop_gpu_virtual_cluster`', '`stop_gpu_virtual_server`', '`stop_vm`', '`suspend_vm`', '`sync_private_flavors`', '`update_ddos_profile`', - '`update_inference_application`', '`update_inference_instance`', - '`update_k8s_cluster_v2`', '`update_l7policy`', '`update_lbmetadata`', - '`update_port_allowed_address_pairs`', '`update_sfs`', - '`update_tags_gpu_virtual_cluster`', '`upgrade_k8s_cluster_v2`', - '`upscale_ai_cluster_gpu`', '`upscale_gpu_virtual_cluster`'] + '`update_floating_ip`', '`update_inference_application`', + '`update_inference_instance`', '`update_k8s_cluster_v2`', '`update_l7policy`', + '`update_lbmetadata`', '`update_port_allowed_address_pairs`', '`update_router`', + '`update_security_group`', '`update_sfs`', '`update_tags_gpu_virtual_cluster`', + '`upgrade_k8s_cluster_v2`', '`upscale_ai_cluster_gpu`', + '`upscale_gpu_virtual_cluster`'] to_timestamp: ISO formatted datetime string. Filter the tasks by creation date less than or equal to `to_timestamp` @@ -470,9 +471,9 @@ def list( '`create_l7rule`', '`create_lblistener`', '`create_lbmember`', '`create_lbpool`', '`create_lbpool_health_monitor`', '`create_loadbalancer`', '`create_network`', '`create_reserved_fixed_ip`', '`create_router`', - '`create_secret`', '`create_servergroup`', '`create_sfs`', '`create_snapshot`', - '`create_subnet`', '`create_vm`', '`create_volume`', - '`deactivate_ddos_profile`', '`delete_ai_cluster_gpu`', + '`create_secret`', '`create_security_group`', '`create_servergroup`', + '`create_sfs`', '`create_snapshot`', '`create_subnet`', '`create_vm`', + '`create_volume`', '`deactivate_ddos_profile`', '`delete_ai_cluster_gpu`', '`delete_caas_container`', '`delete_dbaas_postgres_cluster`', '`delete_ddos_profile`', '`delete_faas_function`', '`delete_faas_namespace`', '`delete_fip`', '`delete_gpu_virtual_cluster`', '`delete_gpu_virtual_server`', @@ -500,11 +501,12 @@ def list( '`start_gpu_virtual_server`', '`start_vm`', '`stop_gpu_baremetal_server`', '`stop_gpu_virtual_cluster`', '`stop_gpu_virtual_server`', '`stop_vm`', '`suspend_vm`', '`sync_private_flavors`', '`update_ddos_profile`', - '`update_inference_application`', '`update_inference_instance`', - '`update_k8s_cluster_v2`', '`update_l7policy`', '`update_lbmetadata`', - '`update_port_allowed_address_pairs`', '`update_sfs`', - '`update_tags_gpu_virtual_cluster`', '`upgrade_k8s_cluster_v2`', - '`upscale_ai_cluster_gpu`', '`upscale_gpu_virtual_cluster`'] + '`update_floating_ip`', '`update_inference_application`', + '`update_inference_instance`', '`update_k8s_cluster_v2`', '`update_l7policy`', + '`update_lbmetadata`', '`update_port_allowed_address_pairs`', '`update_router`', + '`update_security_group`', '`update_sfs`', '`update_tags_gpu_virtual_cluster`', + '`upgrade_k8s_cluster_v2`', '`upscale_ai_cluster_gpu`', + '`upscale_gpu_virtual_cluster`'] to_timestamp: ISO formatted datetime string. Filter the tasks by creation date less than or equal to `to_timestamp` diff --git a/src/gcore/resources/cloud/volume_snapshots.py b/src/gcore/resources/cloud/volume_snapshots.py new file mode 100644 index 00000000..fefcddb8 --- /dev/null +++ b/src/gcore/resources/cloud/volume_snapshots.py @@ -0,0 +1,611 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Optional + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.cloud import volume_snapshot_create_params, volume_snapshot_update_params +from ..._base_client import make_request_options +from ...types.cloud.snapshot import Snapshot +from ...types.cloud.task_id_list import TaskIDList +from ...types.cloud.tag_update_map_param import TagUpdateMapParam + +__all__ = ["VolumeSnapshotsResource", "AsyncVolumeSnapshotsResource"] + + +class VolumeSnapshotsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> VolumeSnapshotsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/G-Core/gcore-python#accessing-raw-response-data-eg-headers + """ + return VolumeSnapshotsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> VolumeSnapshotsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/G-Core/gcore-python#with_streaming_response + """ + return VolumeSnapshotsResourceWithStreamingResponse(self) + + def create( + self, + *, + project_id: int | None = None, + region_id: int | None = None, + name: str, + volume_id: str, + description: str | Omit = omit, + tags: Dict[str, str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TaskIDList: + """ + Create a new snapshot from a volume. + + Args: + name: Snapshot name + + volume_id: Volume ID to make snapshot of + + description: Snapshot description + + tags: Key-value tags to associate with the resource. A tag is a key-value pair that + can be associated with a resource, enabling efficient filtering and grouping for + better organization and management. Both tag keys and values have a maximum + length of 255 characters. Some tags are read-only and cannot be modified by the + user. Tags are also integrated with cost reports, allowing cost data to be + filtered based on tag keys or values. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if project_id is None: + project_id = self._client._get_cloud_project_id_path_param() + if region_id is None: + region_id = self._client._get_cloud_region_id_path_param() + return self._post( + f"/cloud/v1/snapshots/{project_id}/{region_id}", + body=maybe_transform( + { + "name": name, + "volume_id": volume_id, + "description": description, + "tags": tags, + }, + volume_snapshot_create_params.VolumeSnapshotCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskIDList, + ) + + def update( + self, + snapshot_id: str, + *, + project_id: int | None = None, + region_id: int | None = None, + name: str | Omit = omit, + tags: Optional[TagUpdateMapParam] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Snapshot: + """ + Rename snapshot or update tags. + + Args: + project_id: Project ID + + region_id: Region ID + + snapshot_id: Unique identifier of the snapshot + + name: Display name for the snapshot (3-63 chars). Used in customer portal and API. + Does not affect snapshot data. + + tags: Update key-value tags using JSON Merge Patch semantics (RFC 7386). Provide + key-value pairs to add or update tags. Set tag values to `null` to remove tags. + Unspecified tags remain unchanged. Read-only tags are always preserved and + cannot be modified. + + **Examples:** + + - **Add/update tags:** + `{'tags': {'environment': 'production', 'team': 'backend'}}` adds new tags or + updates existing ones. + + - **Delete tags:** `{'tags': {'old_tag': null}}` removes specific tags. + + - **Remove all tags:** `{'tags': null}` removes all user-managed tags (read-only + tags are preserved). + + - **Partial update:** `{'tags': {'environment': 'staging'}}` only updates + specified tags. + + - **Mixed operations:** + `{'tags': {'environment': 'production', 'cost_center': 'engineering', 'deprecated_tag': null}}` + adds/updates 'environment' and '`cost_center`' while removing + '`deprecated_tag`', preserving other existing tags. + + - **Replace all:** first delete existing tags with null values, then add new + ones in the same request. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if project_id is None: + project_id = self._client._get_cloud_project_id_path_param() + if region_id is None: + region_id = self._client._get_cloud_region_id_path_param() + if not snapshot_id: + raise ValueError(f"Expected a non-empty value for `snapshot_id` but received {snapshot_id!r}") + return self._patch( + f"/cloud/v1/snapshots/{project_id}/{region_id}/{snapshot_id}", + body=maybe_transform( + { + "name": name, + "tags": tags, + }, + volume_snapshot_update_params.VolumeSnapshotUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Snapshot, + ) + + def delete( + self, + snapshot_id: str, + *, + project_id: int | None = None, + region_id: int | None = None, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TaskIDList: + """ + Delete a specific snapshot. + + Args: + project_id: Project ID + + region_id: Region ID + + snapshot_id: Unique identifier of the snapshot + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if project_id is None: + project_id = self._client._get_cloud_project_id_path_param() + if region_id is None: + region_id = self._client._get_cloud_region_id_path_param() + if not snapshot_id: + raise ValueError(f"Expected a non-empty value for `snapshot_id` but received {snapshot_id!r}") + return self._delete( + f"/cloud/v1/snapshots/{project_id}/{region_id}/{snapshot_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskIDList, + ) + + def get( + self, + snapshot_id: str, + *, + project_id: int | None = None, + region_id: int | None = None, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Snapshot: + """ + Get detailed information about a specific snapshot. + + Args: + project_id: Project ID + + region_id: Region ID + + snapshot_id: Unique identifier of the snapshot + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if project_id is None: + project_id = self._client._get_cloud_project_id_path_param() + if region_id is None: + region_id = self._client._get_cloud_region_id_path_param() + if not snapshot_id: + raise ValueError(f"Expected a non-empty value for `snapshot_id` but received {snapshot_id!r}") + return self._get( + f"/cloud/v1/snapshots/{project_id}/{region_id}/{snapshot_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Snapshot, + ) + + +class AsyncVolumeSnapshotsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncVolumeSnapshotsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/G-Core/gcore-python#accessing-raw-response-data-eg-headers + """ + return AsyncVolumeSnapshotsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncVolumeSnapshotsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/G-Core/gcore-python#with_streaming_response + """ + return AsyncVolumeSnapshotsResourceWithStreamingResponse(self) + + async def create( + self, + *, + project_id: int | None = None, + region_id: int | None = None, + name: str, + volume_id: str, + description: str | Omit = omit, + tags: Dict[str, str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TaskIDList: + """ + Create a new snapshot from a volume. + + Args: + name: Snapshot name + + volume_id: Volume ID to make snapshot of + + description: Snapshot description + + tags: Key-value tags to associate with the resource. A tag is a key-value pair that + can be associated with a resource, enabling efficient filtering and grouping for + better organization and management. Both tag keys and values have a maximum + length of 255 characters. Some tags are read-only and cannot be modified by the + user. Tags are also integrated with cost reports, allowing cost data to be + filtered based on tag keys or values. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if project_id is None: + project_id = self._client._get_cloud_project_id_path_param() + if region_id is None: + region_id = self._client._get_cloud_region_id_path_param() + return await self._post( + f"/cloud/v1/snapshots/{project_id}/{region_id}", + body=await async_maybe_transform( + { + "name": name, + "volume_id": volume_id, + "description": description, + "tags": tags, + }, + volume_snapshot_create_params.VolumeSnapshotCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskIDList, + ) + + async def update( + self, + snapshot_id: str, + *, + project_id: int | None = None, + region_id: int | None = None, + name: str | Omit = omit, + tags: Optional[TagUpdateMapParam] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Snapshot: + """ + Rename snapshot or update tags. + + Args: + project_id: Project ID + + region_id: Region ID + + snapshot_id: Unique identifier of the snapshot + + name: Display name for the snapshot (3-63 chars). Used in customer portal and API. + Does not affect snapshot data. + + tags: Update key-value tags using JSON Merge Patch semantics (RFC 7386). Provide + key-value pairs to add or update tags. Set tag values to `null` to remove tags. + Unspecified tags remain unchanged. Read-only tags are always preserved and + cannot be modified. + + **Examples:** + + - **Add/update tags:** + `{'tags': {'environment': 'production', 'team': 'backend'}}` adds new tags or + updates existing ones. + + - **Delete tags:** `{'tags': {'old_tag': null}}` removes specific tags. + + - **Remove all tags:** `{'tags': null}` removes all user-managed tags (read-only + tags are preserved). + + - **Partial update:** `{'tags': {'environment': 'staging'}}` only updates + specified tags. + + - **Mixed operations:** + `{'tags': {'environment': 'production', 'cost_center': 'engineering', 'deprecated_tag': null}}` + adds/updates 'environment' and '`cost_center`' while removing + '`deprecated_tag`', preserving other existing tags. + + - **Replace all:** first delete existing tags with null values, then add new + ones in the same request. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if project_id is None: + project_id = self._client._get_cloud_project_id_path_param() + if region_id is None: + region_id = self._client._get_cloud_region_id_path_param() + if not snapshot_id: + raise ValueError(f"Expected a non-empty value for `snapshot_id` but received {snapshot_id!r}") + return await self._patch( + f"/cloud/v1/snapshots/{project_id}/{region_id}/{snapshot_id}", + body=await async_maybe_transform( + { + "name": name, + "tags": tags, + }, + volume_snapshot_update_params.VolumeSnapshotUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Snapshot, + ) + + async def delete( + self, + snapshot_id: str, + *, + project_id: int | None = None, + region_id: int | None = None, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TaskIDList: + """ + Delete a specific snapshot. + + Args: + project_id: Project ID + + region_id: Region ID + + snapshot_id: Unique identifier of the snapshot + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if project_id is None: + project_id = self._client._get_cloud_project_id_path_param() + if region_id is None: + region_id = self._client._get_cloud_region_id_path_param() + if not snapshot_id: + raise ValueError(f"Expected a non-empty value for `snapshot_id` but received {snapshot_id!r}") + return await self._delete( + f"/cloud/v1/snapshots/{project_id}/{region_id}/{snapshot_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskIDList, + ) + + async def get( + self, + snapshot_id: str, + *, + project_id: int | None = None, + region_id: int | None = None, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Snapshot: + """ + Get detailed information about a specific snapshot. + + Args: + project_id: Project ID + + region_id: Region ID + + snapshot_id: Unique identifier of the snapshot + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if project_id is None: + project_id = self._client._get_cloud_project_id_path_param() + if region_id is None: + region_id = self._client._get_cloud_region_id_path_param() + if not snapshot_id: + raise ValueError(f"Expected a non-empty value for `snapshot_id` but received {snapshot_id!r}") + return await self._get( + f"/cloud/v1/snapshots/{project_id}/{region_id}/{snapshot_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Snapshot, + ) + + +class VolumeSnapshotsResourceWithRawResponse: + def __init__(self, volume_snapshots: VolumeSnapshotsResource) -> None: + self._volume_snapshots = volume_snapshots + + self.create = to_raw_response_wrapper( + volume_snapshots.create, + ) + self.update = to_raw_response_wrapper( + volume_snapshots.update, + ) + self.delete = to_raw_response_wrapper( + volume_snapshots.delete, + ) + self.get = to_raw_response_wrapper( + volume_snapshots.get, + ) + + +class AsyncVolumeSnapshotsResourceWithRawResponse: + def __init__(self, volume_snapshots: AsyncVolumeSnapshotsResource) -> None: + self._volume_snapshots = volume_snapshots + + self.create = async_to_raw_response_wrapper( + volume_snapshots.create, + ) + self.update = async_to_raw_response_wrapper( + volume_snapshots.update, + ) + self.delete = async_to_raw_response_wrapper( + volume_snapshots.delete, + ) + self.get = async_to_raw_response_wrapper( + volume_snapshots.get, + ) + + +class VolumeSnapshotsResourceWithStreamingResponse: + def __init__(self, volume_snapshots: VolumeSnapshotsResource) -> None: + self._volume_snapshots = volume_snapshots + + self.create = to_streamed_response_wrapper( + volume_snapshots.create, + ) + self.update = to_streamed_response_wrapper( + volume_snapshots.update, + ) + self.delete = to_streamed_response_wrapper( + volume_snapshots.delete, + ) + self.get = to_streamed_response_wrapper( + volume_snapshots.get, + ) + + +class AsyncVolumeSnapshotsResourceWithStreamingResponse: + def __init__(self, volume_snapshots: AsyncVolumeSnapshotsResource) -> None: + self._volume_snapshots = volume_snapshots + + self.create = async_to_streamed_response_wrapper( + volume_snapshots.create, + ) + self.update = async_to_streamed_response_wrapper( + volume_snapshots.update, + ) + self.delete = async_to_streamed_response_wrapper( + volume_snapshots.delete, + ) + self.get = async_to_streamed_response_wrapper( + volume_snapshots.get, + ) diff --git a/src/gcore/resources/fastedge/binaries.py b/src/gcore/resources/fastedge/binaries.py index c88f90da..1fe86c54 100644 --- a/src/gcore/resources/fastedge/binaries.py +++ b/src/gcore/resources/fastedge/binaries.py @@ -2,10 +2,22 @@ from __future__ import annotations +import os + import httpx from ..._files import read_file_content, async_read_file_content -from ..._types import Body, Query, Headers, NoneType, NotGiven, FileContent, not_given +from ..._types import ( + Body, + Query, + Headers, + NoneType, + NotGiven, + BinaryTypes, + FileContent, + AsyncBinaryTypes, + not_given, +) from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -44,7 +56,7 @@ def with_streaming_response(self) -> BinariesResourceWithStreamingResponse: def create( self, - body: FileContent, + body: FileContent | BinaryTypes, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -68,7 +80,7 @@ def create( extra_headers = {"Content-Type": "application/octet-stream", **(extra_headers or {})} return self._post( "/fastedge/v1/binaries/raw", - body=read_file_content(body), + content=read_file_content(body) if isinstance(body, os.PathLike) else body, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -180,7 +192,7 @@ def with_streaming_response(self) -> AsyncBinariesResourceWithStreamingResponse: async def create( self, - body: FileContent, + body: FileContent | AsyncBinaryTypes, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -204,7 +216,7 @@ async def create( extra_headers = {"Content-Type": "application/octet-stream", **(extra_headers or {})} return await self._post( "/fastedge/v1/binaries/raw", - body=await async_read_file_content(body), + content=await async_read_file_content(body) if isinstance(body, os.PathLike) else body, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/gcore/resources/iam/users.py b/src/gcore/resources/iam/users.py index 3cf6bbef..46d9a50c 100644 --- a/src/gcore/resources/iam/users.py +++ b/src/gcore/resources/iam/users.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Iterable, Optional +from typing import List, Optional from typing_extensions import Literal import httpx @@ -52,13 +52,11 @@ def update( self, user_id: int, *, - auth_types: List[Literal["password", "sso", "github", "google-oauth2"]] | Omit = omit, - company: str | Omit = omit, - email: str | Omit = omit, - groups: Iterable[user_update_params.Group] | Omit = omit, - lang: Literal["de", "en", "ru", "zh", "az"] | Omit = omit, - name: Optional[str] | Omit = omit, - phone: Optional[str] | Omit = omit, + auth_types: List[Literal["password", "sso", "github", "google-oauth2"]], + email: str, + lang: Literal["de", "en", "ru", "zh", "az"], + name: Optional[str], + phone: Optional[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -73,20 +71,8 @@ def update( List of auth types available for the account. - company: User's company. - email: User's email address. - groups: User's group in the current account. - - IAM supports 5 groups: - - - Users - - Administrators - - Engineers - - Purge and Prefetch only (API) - - Purge and Prefetch only (API+Web) - lang: User's language. Defines language of the control panel and email messages. @@ -108,9 +94,7 @@ def update( body=maybe_transform( { "auth_types": auth_types, - "company": company, "email": email, - "groups": groups, "lang": lang, "name": name, "phone": phone, @@ -325,13 +309,11 @@ async def update( self, user_id: int, *, - auth_types: List[Literal["password", "sso", "github", "google-oauth2"]] | Omit = omit, - company: str | Omit = omit, - email: str | Omit = omit, - groups: Iterable[user_update_params.Group] | Omit = omit, - lang: Literal["de", "en", "ru", "zh", "az"] | Omit = omit, - name: Optional[str] | Omit = omit, - phone: Optional[str] | Omit = omit, + auth_types: List[Literal["password", "sso", "github", "google-oauth2"]], + email: str, + lang: Literal["de", "en", "ru", "zh", "az"], + name: Optional[str], + phone: Optional[str], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -346,20 +328,8 @@ async def update( List of auth types available for the account. - company: User's company. - email: User's email address. - groups: User's group in the current account. - - IAM supports 5 groups: - - - Users - - Administrators - - Engineers - - Purge and Prefetch only (API) - - Purge and Prefetch only (API+Web) - lang: User's language. Defines language of the control panel and email messages. @@ -381,9 +351,7 @@ async def update( body=await async_maybe_transform( { "auth_types": auth_types, - "company": company, "email": email, - "groups": groups, "lang": lang, "name": name, "phone": phone, diff --git a/src/gcore/types/cdn/logs_uploader/logs_uploader_policy.py b/src/gcore/types/cdn/logs_uploader/logs_uploader_policy.py index 241cb7d5..dd6cfc5a 100644 --- a/src/gcore/types/cdn/logs_uploader/logs_uploader_policy.py +++ b/src/gcore/types/cdn/logs_uploader/logs_uploader_policy.py @@ -2,6 +2,7 @@ from typing import Dict, List, Optional from datetime import datetime +from typing_extensions import Literal from ...._models import BaseModel @@ -23,6 +24,20 @@ class LogsUploaderPolicy(BaseModel): description: Optional[str] = None """Description of the policy.""" + escape_special_characters: Optional[bool] = None + """ + When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + """ + field_delimiter: Optional[str] = None """Field delimiter for logs.""" @@ -35,8 +50,15 @@ class LogsUploaderPolicy(BaseModel): file_name_template: Optional[str] = None """Template for log file name.""" - format_type: Optional[str] = None - """Format type for logs.""" + format_type: Optional[Literal["json", ""]] = None + """Format type for logs. + + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + """ include_empty_logs: Optional[bool] = None """Include empty logs in the upload.""" diff --git a/src/gcore/types/cdn/logs_uploader/policy_create_params.py b/src/gcore/types/cdn/logs_uploader/policy_create_params.py index 4d763619..7179d9d1 100644 --- a/src/gcore/types/cdn/logs_uploader/policy_create_params.py +++ b/src/gcore/types/cdn/logs_uploader/policy_create_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Dict, Optional -from typing_extensions import TypedDict +from typing_extensions import Literal, TypedDict from ...._types import SequenceNotStr @@ -17,6 +17,20 @@ class PolicyCreateParams(TypedDict, total=False): description: str """Description of the policy.""" + escape_special_characters: bool + """ + When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + """ + field_delimiter: str """Field delimiter for logs.""" @@ -29,8 +43,15 @@ class PolicyCreateParams(TypedDict, total=False): file_name_template: str """Template for log file name.""" - format_type: str - """Format type for logs.""" + format_type: Literal["json", ""] + """Format type for logs. + + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + """ include_empty_logs: bool """Include empty logs in the upload.""" diff --git a/src/gcore/types/cdn/logs_uploader/policy_replace_params.py b/src/gcore/types/cdn/logs_uploader/policy_replace_params.py index 7c62d955..cc779079 100644 --- a/src/gcore/types/cdn/logs_uploader/policy_replace_params.py +++ b/src/gcore/types/cdn/logs_uploader/policy_replace_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Dict, Optional -from typing_extensions import TypedDict +from typing_extensions import Literal, TypedDict from ...._types import SequenceNotStr @@ -17,6 +17,20 @@ class PolicyReplaceParams(TypedDict, total=False): description: str """Description of the policy.""" + escape_special_characters: bool + """ + When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + """ + field_delimiter: str """Field delimiter for logs.""" @@ -29,8 +43,15 @@ class PolicyReplaceParams(TypedDict, total=False): file_name_template: str """Template for log file name.""" - format_type: str - """Format type for logs.""" + format_type: Literal["json", ""] + """Format type for logs. + + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + """ include_empty_logs: bool """Include empty logs in the upload.""" diff --git a/src/gcore/types/cdn/logs_uploader/policy_update_params.py b/src/gcore/types/cdn/logs_uploader/policy_update_params.py index c1bb5811..0e8ce99d 100644 --- a/src/gcore/types/cdn/logs_uploader/policy_update_params.py +++ b/src/gcore/types/cdn/logs_uploader/policy_update_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Dict, Optional -from typing_extensions import TypedDict +from typing_extensions import Literal, TypedDict from ...._types import SequenceNotStr @@ -17,6 +17,20 @@ class PolicyUpdateParams(TypedDict, total=False): description: str """Description of the policy.""" + escape_special_characters: bool + """ + When set to true, the service sanitizes string values by escaping characters + that may be unsafe for transport, logging, or downstream processing. + + The following categories of characters are escaped: + + - Control and non-printable characters + - Quotation marks and escape characters + - Characters outside the standard ASCII range + + The resulting output contains only printable ASCII characters. + """ + field_delimiter: str """Field delimiter for logs.""" @@ -29,8 +43,15 @@ class PolicyUpdateParams(TypedDict, total=False): file_name_template: str """Template for log file name.""" - format_type: str - """Format type for logs.""" + format_type: Literal["json", ""] + """Format type for logs. + + Possible values: + + - **""** - empty, it means it will apply the format configurations from the + policy. + - **"json"** - output the logs as json lines. + """ include_empty_logs: bool """Include empty logs in the upload.""" diff --git a/src/gcore/types/cloud/__init__.py b/src/gcore/types/cloud/__init__.py index 86a27485..450b32e1 100644 --- a/src/gcore/types/cloud/__init__.py +++ b/src/gcore/types/cloud/__init__.py @@ -18,6 +18,7 @@ from .ssh_key import SSHKey as SSHKey from .instance import Instance as Instance from .registry import Registry as Registry +from .snapshot import Snapshot as Snapshot from .gpu_image import GPUImage as GPUImage from .ip_ranges import IPRanges as IPRanges from .file_share import FileShare as FileShare @@ -135,7 +136,6 @@ from .security_group_copy_params import SecurityGroupCopyParams as SecurityGroupCopyParams from .security_group_list_params import SecurityGroupListParams as SecurityGroupListParams from .ddos_profile_template_field import DDOSProfileTemplateField as DDOSProfileTemplateField -from .flavor_hardware_description import FlavorHardwareDescription as FlavorHardwareDescription from .instance_get_console_params import InstanceGetConsoleParams as InstanceGetConsoleParams from .laas_index_retention_policy import LaasIndexRetentionPolicy as LaasIndexRetentionPolicy from .lb_session_persistence_type import LbSessionPersistenceType as LbSessionPersistenceType @@ -154,6 +154,8 @@ from .load_balancer_listener_detail import LoadBalancerListenerDetail as LoadBalancerListenerDetail from .placement_group_create_params import PlacementGroupCreateParams as PlacementGroupCreateParams from .reserved_fixed_ip_list_params import ReservedFixedIPListParams as ReservedFixedIPListParams +from .volume_snapshot_create_params import VolumeSnapshotCreateParams as VolumeSnapshotCreateParams +from .volume_snapshot_update_params import VolumeSnapshotUpdateParams as VolumeSnapshotUpdateParams from .cost_report_aggregated_monthly import CostReportAggregatedMonthly as CostReportAggregatedMonthly from .inference_region_capacity_list import InferenceRegionCapacityList as InferenceRegionCapacityList from .load_balancer_operating_status import LoadBalancerOperatingStatus as LoadBalancerOperatingStatus diff --git a/src/gcore/types/cloud/audit_log_entry.py b/src/gcore/types/cloud/audit_log_entry.py index f73e831e..80a077ae 100644 --- a/src/gcore/types/cloud/audit_log_entry.py +++ b/src/gcore/types/cloud/audit_log_entry.py @@ -161,7 +161,6 @@ class AuditLogEntry(BaseModel): api_group: Literal[ "ai_cluster", - "backup_service", "caas_container", "caas_key", "caas_pull_secret", diff --git a/src/gcore/types/cloud/audit_log_list_params.py b/src/gcore/types/cloud/audit_log_list_params.py index cec69e6a..87bcacce 100644 --- a/src/gcore/types/cloud/audit_log_list_params.py +++ b/src/gcore/types/cloud/audit_log_list_params.py @@ -57,7 +57,6 @@ class AuditLogListParams(TypedDict, total=False): api_group: List[ Literal[ "ai_cluster", - "backup_service", "caas_container", "caas_key", "caas_pull_secret", diff --git a/src/gcore/types/cloud/cost_report_detailed.py b/src/gcore/types/cloud/cost_report_detailed.py index 5669ad22..348099af 100644 --- a/src/gcore/types/cloud/cost_report_detailed.py +++ b/src/gcore/types/cloud/cost_report_detailed.py @@ -365,6 +365,9 @@ class ResultResourceEgressTrafficWithCostSerializer(BaseModel): first_seen: datetime """First time the resource was seen in the given period""" + instance_name: Optional[str] = None + """Name of the instance""" + instance_type: Literal["baremetal", "vm"] """Type of the instance""" @@ -394,9 +397,6 @@ class ResultResourceEgressTrafficWithCostSerializer(BaseModel): vm_id: str """ID of the bare metal server the traffic is associated with""" - instance_name: Optional[str] = None - """Name of the instance""" - class ResultResourceExternalIPWithCostSerializer(BaseModel): attached_to_vm: Optional[str] = None @@ -1011,6 +1011,9 @@ class ResultResourceSnapshotWithCostSerializer(BaseModel): class ResultResourceVolumeWithCostSerializer(BaseModel): + attached_to_vm: Optional[str] = None + """ID of the VM the volume is attached to""" + billing_feature_name: Optional[str] = None billing_metric_name: str @@ -1066,9 +1069,6 @@ class ResultResourceVolumeWithCostSerializer(BaseModel): volume_type: str """Type of the volume""" - attached_to_vm: Optional[str] = None - """ID of the VM the volume is attached to""" - class ResultResourceDbaasPostgreSQLPoolerWithCostSerializer(BaseModel): billing_feature_name: Optional[str] = None diff --git a/src/gcore/types/cloud/flavor_hardware_description.py b/src/gcore/types/cloud/flavor_hardware_description.py deleted file mode 100644 index c03f2150..00000000 --- a/src/gcore/types/cloud/flavor_hardware_description.py +++ /dev/null @@ -1,27 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from ..._models import BaseModel - -__all__ = ["FlavorHardwareDescription"] - - -class FlavorHardwareDescription(BaseModel): - cpu: Optional[str] = None - """Human-readable CPU description""" - - disk: Optional[str] = None - """Human-readable disk description""" - - ephemeral: Optional[str] = None - """Human-readable ephemeral disk description""" - - gpu: Optional[str] = None - """Human-readable GPU description""" - - network: Optional[str] = None - """Human-readable NIC description""" - - ram: Optional[str] = None - """Human-readable RAM description""" diff --git a/src/gcore/types/cloud/floating_ip_assign_params.py b/src/gcore/types/cloud/floating_ip_assign_params.py index e90fcfee..6e3cf613 100644 --- a/src/gcore/types/cloud/floating_ip_assign_params.py +++ b/src/gcore/types/cloud/floating_ip_assign_params.py @@ -10,8 +10,10 @@ class FloatingIPAssignParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" port_id: Required[str] """Port ID""" diff --git a/src/gcore/types/cloud/gpu_baremetal/gpu_baremetal_cluster.py b/src/gcore/types/cloud/gpu_baremetal/gpu_baremetal_cluster.py index 17cfcf4e..5eb7f5da 100644 --- a/src/gcore/types/cloud/gpu_baremetal/gpu_baremetal_cluster.py +++ b/src/gcore/types/cloud/gpu_baremetal/gpu_baremetal_cluster.py @@ -148,7 +148,9 @@ class GPUBaremetalCluster(BaseModel): servers_settings: ServersSettings - status: Literal["active", "deleting", "error", "new", "resizing"] + status: Literal[ + "active", "creating", "degraded", "deleting", "error", "new", "rebooting", "rebuilding", "resizing", "shutoff" + ] """Cluster status""" tags: List[Tag] diff --git a/src/gcore/types/cloud/gpu_virtual/gpu_virtual_cluster.py b/src/gcore/types/cloud/gpu_virtual/gpu_virtual_cluster.py index 9b71eb5e..3561daea 100644 --- a/src/gcore/types/cloud/gpu_virtual/gpu_virtual_cluster.py +++ b/src/gcore/types/cloud/gpu_virtual/gpu_virtual_cluster.py @@ -176,7 +176,9 @@ class GPUVirtualCluster(BaseModel): servers_settings: ServersSettings - status: Literal["active", "deleting", "error", "new", "resizing"] + status: Literal[ + "active", "creating", "degraded", "deleting", "error", "new", "rebooting", "rebuilding", "resizing", "shutoff" + ] """Cluster status""" tags: List[Tag] diff --git a/src/gcore/types/cloud/inference/deployment_update_params.py b/src/gcore/types/cloud/inference/deployment_update_params.py index 85037b7b..ad86e3eb 100644 --- a/src/gcore/types/cloud/inference/deployment_update_params.py +++ b/src/gcore/types/cloud/inference/deployment_update_params.py @@ -230,10 +230,10 @@ class ContainerScale(TypedDict, total=False): class Container(TypedDict, total=False): - region_id: Required[Optional[int]] + region_id: Required[int] """Region id for the container""" - scale: Required[Optional[ContainerScale]] + scale: Required[ContainerScale] """Scale for the container""" diff --git a/src/gcore/types/cloud/instances/__init__.py b/src/gcore/types/cloud/instances/__init__.py index c2f77cfe..fb06e51e 100644 --- a/src/gcore/types/cloud/instances/__init__.py +++ b/src/gcore/types/cloud/instances/__init__.py @@ -4,7 +4,6 @@ from .metrics import Metrics as Metrics from .metrics_list import MetricsList as MetricsList -from .instance_flavor import InstanceFlavor as InstanceFlavor from .image_get_params import ImageGetParams as ImageGetParams from .image_list_params import ImageListParams as ImageListParams from .flavor_list_params import FlavorListParams as FlavorListParams @@ -14,4 +13,5 @@ from .instance_flavor_list import InstanceFlavorList as InstanceFlavorList from .interface_attach_params import InterfaceAttachParams as InterfaceAttachParams from .interface_detach_params import InterfaceDetachParams as InterfaceDetachParams +from .instance_flavor_detailed import InstanceFlavorDetailed as InstanceFlavorDetailed from .image_create_from_volume_params import ImageCreateFromVolumeParams as ImageCreateFromVolumeParams diff --git a/src/gcore/types/cloud/instances/instance_flavor.py b/src/gcore/types/cloud/instances/instance_flavor.py deleted file mode 100644 index 07fbe85f..00000000 --- a/src/gcore/types/cloud/instances/instance_flavor.py +++ /dev/null @@ -1,51 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, Optional -from typing_extensions import Literal - -from ...._models import BaseModel - -__all__ = ["InstanceFlavor"] - - -class InstanceFlavor(BaseModel): - """Instances flavor schema""" - - architecture: str - """Flavor architecture type""" - - disabled: bool - """Disabled flavor flag""" - - flavor_id: str - """Flavor ID is the same as name""" - - flavor_name: str - """Flavor name""" - - os_type: str - """Flavor operating system""" - - ram: int - """RAM size in MiB""" - - vcpus: int - """Virtual CPU count. For bare metal flavors, it's a physical CPU count""" - - capacity: Optional[int] = None - """Number of available instances of given configuration""" - - currency_code: Optional[str] = None - """Currency code. Shown if the `include_prices` query parameter if set to true""" - - hardware_description: Optional[Dict[str, str]] = None - """Additional hardware description""" - - price_per_hour: Optional[float] = None - """Price per hour. Shown if the `include_prices` query parameter if set to true""" - - price_per_month: Optional[float] = None - """Price per month. Shown if the `include_prices` query parameter if set to true""" - - price_status: Optional[Literal["error", "hide", "show"]] = None - """Price status for the UI""" diff --git a/src/gcore/types/cloud/instances/instance_flavor_detailed.py b/src/gcore/types/cloud/instances/instance_flavor_detailed.py new file mode 100644 index 00000000..b1605b03 --- /dev/null +++ b/src/gcore/types/cloud/instances/instance_flavor_detailed.py @@ -0,0 +1,85 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, Union, Optional +from typing_extensions import Literal, TypeAlias + +from ...._models import BaseModel + +__all__ = [ + "InstanceFlavorDetailed", + "InstanceFlavorExtendedSerializerWithoutPrice", + "InstanceFlavorExtendedSerializerWithPrice", +] + + +class InstanceFlavorExtendedSerializerWithoutPrice(BaseModel): + """Instances flavor schema without price information""" + + architecture: str + """Flavor architecture type""" + + disabled: bool + """Disabled flavor flag""" + + flavor_id: str + """Flavor ID is the same as name""" + + flavor_name: str + """Flavor name""" + + hardware_description: Dict[str, str] + """Additional hardware description""" + + os_type: str + """Flavor operating system""" + + ram: int + """RAM size in MiB""" + + vcpus: int + """Virtual CPU count""" + + +class InstanceFlavorExtendedSerializerWithPrice(BaseModel): + """Instances flavor schema with price information""" + + architecture: str + """Flavor architecture type""" + + currency_code: Optional[str] = None + """Currency code""" + + disabled: bool + """Disabled flavor flag""" + + flavor_id: str + """Flavor ID is the same as name""" + + flavor_name: str + """Flavor name""" + + hardware_description: Dict[str, str] + """Additional hardware description""" + + os_type: str + """Flavor operating system""" + + price_per_hour: Optional[float] = None + """Price per hour""" + + price_per_month: Optional[float] = None + """Price per month""" + + price_status: Optional[Literal["error", "hide", "show"]] = None + """Price status for the UI""" + + ram: int + """RAM size in MiB""" + + vcpus: int + """Virtual CPU count""" + + +InstanceFlavorDetailed: TypeAlias = Union[ + InstanceFlavorExtendedSerializerWithoutPrice, InstanceFlavorExtendedSerializerWithPrice +] diff --git a/src/gcore/types/cloud/instances/instance_flavor_list.py b/src/gcore/types/cloud/instances/instance_flavor_list.py index 5d1e52c2..3977e00c 100644 --- a/src/gcore/types/cloud/instances/instance_flavor_list.py +++ b/src/gcore/types/cloud/instances/instance_flavor_list.py @@ -3,7 +3,7 @@ from typing import List from ...._models import BaseModel -from .instance_flavor import InstanceFlavor +from .instance_flavor_detailed import InstanceFlavorDetailed __all__ = ["InstanceFlavorList"] @@ -12,5 +12,5 @@ class InstanceFlavorList(BaseModel): count: int """Number of objects""" - results: List[InstanceFlavor] + results: List[InstanceFlavorDetailed] """Objects""" diff --git a/src/gcore/types/cloud/load_balancer_create_params.py b/src/gcore/types/cloud/load_balancer_create_params.py index 16e66ced..49939fac 100644 --- a/src/gcore/types/cloud/load_balancer_create_params.py +++ b/src/gcore/types/cloud/load_balancer_create_params.py @@ -33,8 +33,10 @@ class LoadBalancerCreateParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" flavor: str """Load balancer flavor name""" @@ -278,12 +280,6 @@ class ListenerPool(TypedDict, total=False): healthmonitor: Optional[ListenerPoolHealthmonitor] """Health monitor details""" - listener_id: Optional[str] - """Listener ID""" - - load_balancer_id: Optional[str] - """Loadbalancer ID""" - members: Iterable[ListenerPoolMember] """Pool members""" @@ -294,7 +290,10 @@ class ListenerPool(TypedDict, total=False): """Session persistence details""" timeout_client_data: Optional[int] - """Frontend client inactivity timeout in milliseconds""" + """Frontend client inactivity timeout in milliseconds. + + We are recommending to use `listener.timeout_client_data` instead. + """ timeout_member_connect: Optional[int] """Backend member connection timeout in milliseconds""" @@ -355,10 +354,16 @@ class Listener(TypedDict, total=False): """Frontend client inactivity timeout in milliseconds""" timeout_member_connect: Optional[int] - """Backend member connection timeout in milliseconds""" + """Backend member connection timeout in milliseconds. + + We are recommending to use `pool.timeout_member_connect` instead. + """ timeout_member_data: Optional[int] - """Backend member inactivity timeout in milliseconds""" + """Backend member inactivity timeout in milliseconds. + + We are recommending to use `pool.timeout_member_data` instead. + """ user_list: Iterable[ListenerUserList] """Load balancer listener list of username and encrypted password items""" diff --git a/src/gcore/types/cloud/load_balancer_failover_params.py b/src/gcore/types/cloud/load_balancer_failover_params.py index b4a727a7..90da9688 100644 --- a/src/gcore/types/cloud/load_balancer_failover_params.py +++ b/src/gcore/types/cloud/load_balancer_failover_params.py @@ -9,8 +9,10 @@ class LoadBalancerFailoverParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" force: bool """Validate current load balancer status before failover or not.""" diff --git a/src/gcore/types/cloud/load_balancer_flavor_detail.py b/src/gcore/types/cloud/load_balancer_flavor_detail.py index 6088eff6..f4040178 100644 --- a/src/gcore/types/cloud/load_balancer_flavor_detail.py +++ b/src/gcore/types/cloud/load_balancer_flavor_detail.py @@ -1,14 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing import Optional +from typing_extensions import Literal from ..._models import BaseModel -from .flavor_hardware_description import FlavorHardwareDescription -__all__ = ["LoadBalancerFlavorDetail", "HardwareDescription"] - -HardwareDescription: TypeAlias = Union[FlavorHardwareDescription, Dict[str, object]] +__all__ = ["LoadBalancerFlavorDetail"] class LoadBalancerFlavorDetail(BaseModel): @@ -18,9 +15,6 @@ class LoadBalancerFlavorDetail(BaseModel): flavor_name: str """Flavor name""" - hardware_description: HardwareDescription - """Additional hardware description.""" - ram: int """RAM size in MiB""" diff --git a/src/gcore/types/cloud/load_balancer_flavor_list.py b/src/gcore/types/cloud/load_balancer_flavor_list.py index 7b10dbd7..9a1d170c 100644 --- a/src/gcore/types/cloud/load_balancer_flavor_list.py +++ b/src/gcore/types/cloud/load_balancer_flavor_list.py @@ -1,16 +1,34 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import List, Union +from typing_extensions import TypeAlias from ..._models import BaseModel from .load_balancer_flavor_detail import LoadBalancerFlavorDetail -__all__ = ["LoadBalancerFlavorList"] +__all__ = ["LoadBalancerFlavorList", "Result", "ResultLbFlavorSerializer"] + + +class ResultLbFlavorSerializer(BaseModel): + flavor_id: str + """Flavor ID is the same as name""" + + flavor_name: str + """Flavor name""" + + ram: int + """RAM size in MiB""" + + vcpus: int + """Virtual CPU count. For bare metal flavors, it's a physical CPU count""" + + +Result: TypeAlias = Union[ResultLbFlavorSerializer, LoadBalancerFlavorDetail] class LoadBalancerFlavorList(BaseModel): count: int """Number of objects""" - results: List[LoadBalancerFlavorDetail] + results: List[Result] """Objects""" diff --git a/src/gcore/types/cloud/load_balancer_get_params.py b/src/gcore/types/cloud/load_balancer_get_params.py index 233a6f3e..d1644e83 100644 --- a/src/gcore/types/cloud/load_balancer_get_params.py +++ b/src/gcore/types/cloud/load_balancer_get_params.py @@ -9,11 +9,13 @@ class LoadBalancerGetParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" show_stats: bool """Show statistics""" with_ddos: bool - """Show DDoS profile""" + """Show Advanced DDoS protection profile, if exists""" diff --git a/src/gcore/types/cloud/load_balancer_list_params.py b/src/gcore/types/cloud/load_balancer_list_params.py index 81ab5ea7..d6a71ba9 100644 --- a/src/gcore/types/cloud/load_balancer_list_params.py +++ b/src/gcore/types/cloud/load_balancer_list_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing_extensions import Literal, TypedDict from ..._types import SequenceNotStr @@ -11,40 +11,54 @@ class LoadBalancerListParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" assigned_floating: bool """With or without assigned floating IP""" limit: int - """Limit the number of returned limit request entities.""" + """Limit of items on a single page""" logging_enabled: bool - """With or without logging""" + """With or without logging enabled""" name: str """Filter by name""" offset: int - """Offset value is used to exclude the first set of records from the result.""" - - order_by: str - """ - Ordering Load Balancer list result by name, `created_at`, `updated_at`, - `operating_status`, `provisioning_status`, `vip_address`, `vip_ip_family` and - flavor fields of the load balancer and directions (name.asc), default is - "`created_at`.asc" - """ + """Offset in results list""" + + order_by: Literal[ + "created_at.asc", + "created_at.desc", + "flavor.asc", + "flavor.desc", + "name.asc", + "name.desc", + "operating_status.asc", + "operating_status.desc", + "provisioning_status.asc", + "provisioning_status.desc", + "updated_at.asc", + "updated_at.desc", + "vip_address.asc", + "vip_address.desc", + "vip_ip_family.asc", + "vip_ip_family.desc", + ] + """Order by field and direction.""" show_stats: bool """Show statistics""" tag_key: SequenceNotStr[str] - """Filter by tag keys.""" + """Optional. Filter by tag keys. ?`tag_key`=key1&`tag_key`=key2""" tag_key_value: str - """Filter by tag key-value pairs. Must be a valid JSON string.""" + """Optional. Filter by tag key-value pairs.""" with_ddos: bool """Show Advanced DDoS protection profile, if exists""" diff --git a/src/gcore/types/cloud/load_balancer_resize_params.py b/src/gcore/types/cloud/load_balancer_resize_params.py index 05055dfe..80d1a0b5 100644 --- a/src/gcore/types/cloud/load_balancer_resize_params.py +++ b/src/gcore/types/cloud/load_balancer_resize_params.py @@ -9,8 +9,10 @@ class LoadBalancerResizeParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" flavor: Required[str] """Name of the desired flavor to resize to.""" diff --git a/src/gcore/types/cloud/load_balancer_update_params.py b/src/gcore/types/cloud/load_balancer_update_params.py index 94770401..0b6f23d8 100644 --- a/src/gcore/types/cloud/load_balancer_update_params.py +++ b/src/gcore/types/cloud/load_balancer_update_params.py @@ -14,8 +14,10 @@ class LoadBalancerUpdateParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" logging: Logging """Logging configuration""" diff --git a/src/gcore/types/cloud/load_balancers/flavor_list_params.py b/src/gcore/types/cloud/load_balancers/flavor_list_params.py index 4db3ee38..af622cd6 100644 --- a/src/gcore/types/cloud/load_balancers/flavor_list_params.py +++ b/src/gcore/types/cloud/load_balancers/flavor_list_params.py @@ -9,8 +9,10 @@ class FlavorListParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" include_prices: bool """Set to true if the response should include flavor prices""" diff --git a/src/gcore/types/cloud/load_balancers/listener_create_params.py b/src/gcore/types/cloud/load_balancers/listener_create_params.py index 8dc00324..c688d661 100644 --- a/src/gcore/types/cloud/load_balancers/listener_create_params.py +++ b/src/gcore/types/cloud/load_balancers/listener_create_params.py @@ -64,10 +64,16 @@ class ListenerCreateParams(TypedDict, total=False): """Frontend client inactivity timeout in milliseconds""" timeout_member_connect: Optional[int] - """Backend member connection timeout in milliseconds""" + """Backend member connection timeout in milliseconds. + + We are recommending to use `pool.timeout_member_connect` instead. + """ timeout_member_data: Optional[int] - """Backend member inactivity timeout in milliseconds""" + """Backend member inactivity timeout in milliseconds. + + We are recommending to use `pool.timeout_member_data` instead. + """ user_list: Iterable[UserList] """Load balancer listener list of username and encrypted password items""" diff --git a/src/gcore/types/cloud/load_balancers/listener_update_params.py b/src/gcore/types/cloud/load_balancers/listener_update_params.py index 42fa7e38..002bb912 100644 --- a/src/gcore/types/cloud/load_balancers/listener_update_params.py +++ b/src/gcore/types/cloud/load_balancers/listener_update_params.py @@ -45,10 +45,16 @@ class ListenerUpdateParams(TypedDict, total=False): """Frontend client inactivity timeout in milliseconds""" timeout_member_connect: Optional[int] - """Backend member connection timeout in milliseconds""" + """Backend member connection timeout in milliseconds. + + We are recommending to use `pool.timeout_member_connect` instead. + """ timeout_member_data: Optional[int] - """Backend member inactivity timeout in milliseconds""" + """Backend member inactivity timeout in milliseconds. + + We are recommending to use `pool.timeout_member_data` instead. + """ user_list: Optional[Iterable[UserList]] """Load balancer listener users list""" diff --git a/src/gcore/types/cloud/load_balancers/metric_list_params.py b/src/gcore/types/cloud/load_balancers/metric_list_params.py index 4af5e414..a88d2c11 100644 --- a/src/gcore/types/cloud/load_balancers/metric_list_params.py +++ b/src/gcore/types/cloud/load_balancers/metric_list_params.py @@ -11,8 +11,10 @@ class MetricListParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" time_interval: Required[int] """Time interval""" diff --git a/src/gcore/types/cloud/load_balancers/pool_create_params.py b/src/gcore/types/cloud/load_balancers/pool_create_params.py index 079e78ed..81987648 100644 --- a/src/gcore/types/cloud/load_balancers/pool_create_params.py +++ b/src/gcore/types/cloud/load_balancers/pool_create_params.py @@ -55,7 +55,10 @@ class PoolCreateParams(TypedDict, total=False): """Session persistence details""" timeout_client_data: Optional[int] - """Frontend client inactivity timeout in milliseconds""" + """Frontend client inactivity timeout in milliseconds. + + We are recommending to use `listener.timeout_client_data` instead. + """ timeout_member_connect: Optional[int] """Backend member connection timeout in milliseconds""" diff --git a/src/gcore/types/cloud/load_balancers/pool_update_params.py b/src/gcore/types/cloud/load_balancers/pool_update_params.py index 381e4247..b5a32f86 100644 --- a/src/gcore/types/cloud/load_balancers/pool_update_params.py +++ b/src/gcore/types/cloud/load_balancers/pool_update_params.py @@ -53,7 +53,10 @@ class PoolUpdateParams(TypedDict, total=False): """New session persistence settings""" timeout_client_data: Optional[int] - """Frontend client inactivity timeout in milliseconds""" + """Frontend client inactivity timeout in milliseconds. + + We are recommending to use `listener.timeout_client_data` instead. + """ timeout_member_connect: Optional[int] """Backend member connection timeout in milliseconds""" diff --git a/src/gcore/types/cloud/networks/subnet_update_params.py b/src/gcore/types/cloud/networks/subnet_update_params.py index 0a79030b..267a9af7 100644 --- a/src/gcore/types/cloud/networks/subnet_update_params.py +++ b/src/gcore/types/cloud/networks/subnet_update_params.py @@ -21,7 +21,7 @@ class SubnetUpdateParams(TypedDict, total=False): dns_nameservers: Optional[SequenceNotStr[str]] """List IP addresses of DNS servers to advertise via DHCP.""" - enable_dhcp: Optional[bool] + enable_dhcp: bool """True if DHCP should be enabled""" gateway_ip: Optional[str] diff --git a/src/gcore/types/cloud/quotas/request_list_params.py b/src/gcore/types/cloud/quotas/request_list_params.py index ede95106..56e39b19 100644 --- a/src/gcore/types/cloud/quotas/request_list_params.py +++ b/src/gcore/types/cloud/quotas/request_list_params.py @@ -2,13 +2,22 @@ from __future__ import annotations -from typing import List -from typing_extensions import Literal, TypedDict +from typing import List, Union, Iterable +from datetime import datetime +from typing_extensions import Literal, Annotated, TypedDict + +from ...._utils import PropertyInfo __all__ = ["RequestListParams"] class RequestListParams(TypedDict, total=False): + created_from: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """Filter limit requests created at or after this datetime (inclusive)""" + + created_to: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """Filter limit requests created at or before this datetime (inclusive)""" + limit: int """Optional. Limit the number of returned items""" @@ -18,5 +27,8 @@ class RequestListParams(TypedDict, total=False): Offset value is used to exclude the first set of records from the result """ + request_ids: Iterable[int] + """List of limit request IDs for filtering""" + status: List[Literal["done", "in progress", "rejected"]] """List of limit requests statuses for filtering""" diff --git a/src/gcore/types/cloud/region.py b/src/gcore/types/cloud/region.py index ac2fa29b..e7bde6fe 100644 --- a/src/gcore/types/cloud/region.py +++ b/src/gcore/types/cloud/region.py @@ -30,8 +30,8 @@ class Region(BaseModel): coordinates: Optional[Coordinates] = None """Coordinates of the region""" - country: Optional[str] = None - """Country""" + country: str + """Two-letter country code, ISO 3166-1 alpha-2""" created_at: datetime """Region creation date and time""" diff --git a/src/gcore/types/cloud/registries/registry_user.py b/src/gcore/types/cloud/registries/registry_user.py index 81e7d4b8..23de4c01 100644 --- a/src/gcore/types/cloud/registries/registry_user.py +++ b/src/gcore/types/cloud/registries/registry_user.py @@ -1,6 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional from datetime import datetime from ...._models import BaseModel @@ -24,5 +23,5 @@ class RegistryUser(BaseModel): name: str """User name""" - read_only: Optional[bool] = None + read_only: bool """Read-only user""" diff --git a/src/gcore/types/cloud/registries/registry_user_created.py b/src/gcore/types/cloud/registries/registry_user_created.py index 6cb1ae87..42564a72 100644 --- a/src/gcore/types/cloud/registries/registry_user_created.py +++ b/src/gcore/types/cloud/registries/registry_user_created.py @@ -1,6 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional from datetime import datetime from ...._models import BaseModel @@ -24,8 +23,8 @@ class RegistryUserCreated(BaseModel): name: str """User name""" - read_only: Optional[bool] = None + read_only: bool """Read-only user""" - secret: Optional[str] = None + secret: str """User secret""" diff --git a/src/gcore/types/cloud/registries/user_refresh_secret_response.py b/src/gcore/types/cloud/registries/user_refresh_secret_response.py index 17fb1144..255c1e8a 100644 --- a/src/gcore/types/cloud/registries/user_refresh_secret_response.py +++ b/src/gcore/types/cloud/registries/user_refresh_secret_response.py @@ -1,6 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional from datetime import datetime from ...._models import BaseModel @@ -24,8 +23,8 @@ class UserRefreshSecretResponse(BaseModel): name: str """User name""" - read_only: Optional[bool] = None + read_only: bool """Read-only user""" - secret: Optional[str] = None + secret: str """User secret""" diff --git a/src/gcore/types/cloud/security_group_copy_params.py b/src/gcore/types/cloud/security_group_copy_params.py index 6a1666e9..c93aa980 100644 --- a/src/gcore/types/cloud/security_group_copy_params.py +++ b/src/gcore/types/cloud/security_group_copy_params.py @@ -9,8 +9,10 @@ class SecurityGroupCopyParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" name: Required[str] """Name.""" diff --git a/src/gcore/types/cloud/security_group_create_params.py b/src/gcore/types/cloud/security_group_create_params.py index 7ae07e15..b932ad13 100644 --- a/src/gcore/types/cloud/security_group_create_params.py +++ b/src/gcore/types/cloud/security_group_create_params.py @@ -25,14 +25,14 @@ class SecurityGroupCreateParams(TypedDict, total=False): class SecurityGroupSecurityGroupRule(TypedDict, total=False): - description: str - """Rule description""" - - direction: Literal["egress", "ingress"] + direction: Required[Literal["egress", "ingress"]] """ Ingress or egress, which is the direction in which the security group is applied """ + description: str + """Rule description""" + ethertype: Literal["IPv4", "IPv6"] """Ether type""" diff --git a/src/gcore/types/cloud/security_group_list_params.py b/src/gcore/types/cloud/security_group_list_params.py index 22b3bd2c..0f13ddad 100644 --- a/src/gcore/types/cloud/security_group_list_params.py +++ b/src/gcore/types/cloud/security_group_list_params.py @@ -19,6 +19,9 @@ class SecurityGroupListParams(TypedDict, total=False): limit: int """Limit of items on a single page""" + name: str + """Optional. Filter by name. Must be specified a full name of the security group.""" + offset: int """Offset in results list""" diff --git a/src/gcore/types/cloud/security_group_rule.py b/src/gcore/types/cloud/security_group_rule.py index 533537e8..aa717ba6 100644 --- a/src/gcore/types/cloud/security_group_rule.py +++ b/src/gcore/types/cloud/security_group_rule.py @@ -16,24 +16,15 @@ class SecurityGroupRule(BaseModel): created_at: datetime """Datetime when the rule was created""" + description: Optional[str] = None + """Rule description""" + direction: Literal["egress", "ingress"] """ Ingress or egress, which is the direction in which the security group rule is applied """ - revision_number: int - """The revision number of the resource""" - - security_group_id: str - """The security group ID to associate with this security group rule""" - - updated_at: datetime - """Datetime when the rule was last updated""" - - description: Optional[str] = None - """Rule description""" - ethertype: Optional[Literal["IPv4", "IPv6"]] = None """ Must be IPv4 or IPv6, and addresses represented in CIDR must match the ingress @@ -81,3 +72,12 @@ class SecurityGroupRule(BaseModel): remote_ip_prefix: Optional[str] = None """The remote IP prefix that is matched by this security group rule""" + + revision_number: int + """The revision number of the resource""" + + security_group_id: str + """The security group ID to associate with this security group rule""" + + updated_at: datetime + """Datetime when the rule was last updated""" diff --git a/src/gcore/types/cloud/security_group_update_params.py b/src/gcore/types/cloud/security_group_update_params.py index d085c208..1ac56005 100644 --- a/src/gcore/types/cloud/security_group_update_params.py +++ b/src/gcore/types/cloud/security_group_update_params.py @@ -12,8 +12,10 @@ class SecurityGroupUpdateParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" changed_rules: Iterable[ChangedRule] """List of rules to create or delete""" diff --git a/src/gcore/types/cloud/security_groups/rule_create_params.py b/src/gcore/types/cloud/security_groups/rule_create_params.py index a8ff773d..46fdd411 100644 --- a/src/gcore/types/cloud/security_groups/rule_create_params.py +++ b/src/gcore/types/cloud/security_groups/rule_create_params.py @@ -3,24 +3,26 @@ from __future__ import annotations from typing import Optional -from typing_extensions import Literal, TypedDict +from typing_extensions import Literal, Required, TypedDict __all__ = ["RuleCreateParams"] class RuleCreateParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" - description: str - """Rule description""" - - direction: Literal["egress", "ingress"] + direction: Required[Literal["egress", "ingress"]] """ Ingress or egress, which is the direction in which the security group is applied """ + description: str + """Rule description""" + ethertype: Literal["IPv4", "IPv6"] """Ether type""" diff --git a/src/gcore/types/cloud/security_groups/rule_replace_params.py b/src/gcore/types/cloud/security_groups/rule_replace_params.py index be16eb3b..55d7a2ca 100644 --- a/src/gcore/types/cloud/security_groups/rule_replace_params.py +++ b/src/gcore/types/cloud/security_groups/rule_replace_params.py @@ -10,8 +10,10 @@ class RuleReplaceParams(TypedDict, total=False): project_id: int + """Project ID""" region_id: int + """Region ID""" direction: Required[Literal["egress", "ingress"]] """ diff --git a/src/gcore/types/cloud/snapshot.py b/src/gcore/types/cloud/snapshot.py new file mode 100644 index 00000000..ac5ca594 --- /dev/null +++ b/src/gcore/types/cloud/snapshot.py @@ -0,0 +1,75 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .tag import Tag +from ..._models import BaseModel + +__all__ = ["Snapshot"] + + +class Snapshot(BaseModel): + id: str + """Snapshot ID""" + + created_at: datetime + """Datetime when the snapshot was created""" + + creator_task_id: str + """Task that created this entity""" + + description: Optional[str] = None + """Snapshot description""" + + name: str + """Snapshot name""" + + project_id: int + """Project ID""" + + region: str + """Region name""" + + region_id: int + """Region ID""" + + size: int + """Snapshot size, GiB""" + + status: Literal[ + "available", + "backing-up", + "creating", + "deleted", + "deleting", + "error", + "error_deleting", + "restoring", + "unmanaging", + ] + """Snapshot status""" + + tags: List[Tag] + """List of key-value tags associated with the resource. + + A tag is a key-value pair that can be associated with a resource, enabling + efficient filtering and grouping for better organization and management. Some + tags are read-only and cannot be modified by the user. Tags are also integrated + with cost reports, allowing cost data to be filtered based on tag keys or + values. + """ + + task_id: Optional[str] = None + """The UUID of the active task that currently holds a lock on the resource. + + This lock prevents concurrent modifications to ensure consistency. If `null`, + the resource is not locked. + """ + + updated_at: datetime + """Datetime when the snapshot was last updated""" + + volume_id: str + """ID of the volume this snapshot was made from""" diff --git a/src/gcore/types/cloud/task.py b/src/gcore/types/cloud/task.py index aaa2f782..7eae7f01 100644 --- a/src/gcore/types/cloud/task.py +++ b/src/gcore/types/cloud/task.py @@ -98,6 +98,9 @@ class CreatedResources(BaseModel): secrets: Optional[List[str]] = None """IDs of created secrets""" + security_groups: Optional[List[str]] = None + """IDs of created security groups""" + servergroups: Optional[List[str]] = None """IDs of created server groups""" diff --git a/src/gcore/types/cloud/task_list_params.py b/src/gcore/types/cloud/task_list_params.py index 0fc29cca..440e4900 100644 --- a/src/gcore/types/cloud/task_list_params.py +++ b/src/gcore/types/cloud/task_list_params.py @@ -71,9 +71,9 @@ class TaskListParams(TypedDict, total=False): '`create_l7rule`', '`create_lblistener`', '`create_lbmember`', '`create_lbpool`', '`create_lbpool_health_monitor`', '`create_loadbalancer`', '`create_network`', '`create_reserved_fixed_ip`', '`create_router`', - '`create_secret`', '`create_servergroup`', '`create_sfs`', '`create_snapshot`', - '`create_subnet`', '`create_vm`', '`create_volume`', - '`deactivate_ddos_profile`', '`delete_ai_cluster_gpu`', + '`create_secret`', '`create_security_group`', '`create_servergroup`', + '`create_sfs`', '`create_snapshot`', '`create_subnet`', '`create_vm`', + '`create_volume`', '`deactivate_ddos_profile`', '`delete_ai_cluster_gpu`', '`delete_caas_container`', '`delete_dbaas_postgres_cluster`', '`delete_ddos_profile`', '`delete_faas_function`', '`delete_faas_namespace`', '`delete_fip`', '`delete_gpu_virtual_cluster`', '`delete_gpu_virtual_server`', @@ -101,11 +101,12 @@ class TaskListParams(TypedDict, total=False): '`start_gpu_virtual_server`', '`start_vm`', '`stop_gpu_baremetal_server`', '`stop_gpu_virtual_cluster`', '`stop_gpu_virtual_server`', '`stop_vm`', '`suspend_vm`', '`sync_private_flavors`', '`update_ddos_profile`', - '`update_inference_application`', '`update_inference_instance`', - '`update_k8s_cluster_v2`', '`update_l7policy`', '`update_lbmetadata`', - '`update_port_allowed_address_pairs`', '`update_sfs`', - '`update_tags_gpu_virtual_cluster`', '`upgrade_k8s_cluster_v2`', - '`upscale_ai_cluster_gpu`', '`upscale_gpu_virtual_cluster`'] + '`update_floating_ip`', '`update_inference_application`', + '`update_inference_instance`', '`update_k8s_cluster_v2`', '`update_l7policy`', + '`update_lbmetadata`', '`update_port_allowed_address_pairs`', '`update_router`', + '`update_security_group`', '`update_sfs`', '`update_tags_gpu_virtual_cluster`', + '`upgrade_k8s_cluster_v2`', '`upscale_ai_cluster_gpu`', + '`upscale_gpu_virtual_cluster`'] """ to_timestamp: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] diff --git a/src/gcore/types/cloud/usage_report.py b/src/gcore/types/cloud/usage_report.py index 6649aebf..659a5421 100644 --- a/src/gcore/types/cloud/usage_report.py +++ b/src/gcore/types/cloud/usage_report.py @@ -343,6 +343,9 @@ class ResourceResourceEgressTrafficSerializer(BaseModel): first_seen: datetime """First time the resource was seen in the given period""" + instance_name: Optional[str] = None + """Name of the instance""" + instance_type: Literal["baremetal", "vm"] """Type of the instance""" @@ -372,9 +375,6 @@ class ResourceResourceEgressTrafficSerializer(BaseModel): vm_id: str """ID of the bare metal server the traffic is associated with""" - instance_name: Optional[str] = None - """Name of the instance""" - class ResourceResourceExternalIPSerializer(BaseModel): """ @@ -917,6 +917,9 @@ class ResourceResourceVolumeSerializer(BaseModel): in all cost and usage reports results (but not in totals) """ + attached_to_vm: Optional[str] = None + """ID of the VM the volume is attached to""" + billing_metric_name: str """Name of the billing metric""" @@ -961,9 +964,6 @@ class ResourceResourceVolumeSerializer(BaseModel): volume_type: str """Type of the volume""" - attached_to_vm: Optional[str] = None - """ID of the VM the volume is attached to""" - class ResourceResourceDbaasPostgreSQLPoolerSerializer(BaseModel): billing_metric_name: str diff --git a/src/gcore/types/cloud/volume_snapshot_create_params.py b/src/gcore/types/cloud/volume_snapshot_create_params.py new file mode 100644 index 00000000..b832806b --- /dev/null +++ b/src/gcore/types/cloud/volume_snapshot_create_params.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict +from typing_extensions import Required, TypedDict + +__all__ = ["VolumeSnapshotCreateParams"] + + +class VolumeSnapshotCreateParams(TypedDict, total=False): + project_id: int + + region_id: int + + name: Required[str] + """Snapshot name""" + + volume_id: Required[str] + """Volume ID to make snapshot of""" + + description: str + """Snapshot description""" + + tags: Dict[str, str] + """Key-value tags to associate with the resource. + + A tag is a key-value pair that can be associated with a resource, enabling + efficient filtering and grouping for better organization and management. Both + tag keys and values have a maximum length of 255 characters. Some tags are + read-only and cannot be modified by the user. Tags are also integrated with cost + reports, allowing cost data to be filtered based on tag keys or values. + """ diff --git a/src/gcore/types/cloud/volume_snapshot_update_params.py b/src/gcore/types/cloud/volume_snapshot_update_params.py new file mode 100644 index 00000000..5e279e7e --- /dev/null +++ b/src/gcore/types/cloud/volume_snapshot_update_params.py @@ -0,0 +1,54 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import TypedDict + +from .tag_update_map_param import TagUpdateMapParam + +__all__ = ["VolumeSnapshotUpdateParams"] + + +class VolumeSnapshotUpdateParams(TypedDict, total=False): + project_id: int + """Project ID""" + + region_id: int + """Region ID""" + + name: str + """Display name for the snapshot (3-63 chars). + + Used in customer portal and API. Does not affect snapshot data. + """ + + tags: Optional[TagUpdateMapParam] + """Update key-value tags using JSON Merge Patch semantics (RFC 7386). + + Provide key-value pairs to add or update tags. Set tag values to `null` to + remove tags. Unspecified tags remain unchanged. Read-only tags are always + preserved and cannot be modified. + + **Examples:** + + - **Add/update tags:** + `{'tags': {'environment': 'production', 'team': 'backend'}}` adds new tags or + updates existing ones. + + - **Delete tags:** `{'tags': {'old_tag': null}}` removes specific tags. + + - **Remove all tags:** `{'tags': null}` removes all user-managed tags (read-only + tags are preserved). + + - **Partial update:** `{'tags': {'environment': 'staging'}}` only updates + specified tags. + + - **Mixed operations:** + `{'tags': {'environment': 'production', 'cost_center': 'engineering', 'deprecated_tag': null}}` + adds/updates 'environment' and '`cost_center`' while removing + '`deprecated_tag`', preserving other existing tags. + + - **Replace all:** first delete existing tags with null values, then add new + ones in the same request. + """ diff --git a/src/gcore/types/dns/zone_get_response.py b/src/gcore/types/dns/zone_get_response.py index 38422c5c..b984fa7a 100644 --- a/src/gcore/types/dns/zone_get_response.py +++ b/src/gcore/types/dns/zone_get_response.py @@ -1,15 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional - -from pydantic import Field as FieldInfo +from typing import Dict, List, Optional from ..._models import BaseModel -__all__ = ["ZoneGetResponse", "Zone", "ZoneRecord", "ZoneRrsetsAmount", "ZoneRrsetsAmountDynamic"] +__all__ = ["ZoneGetResponse", "Record", "RrsetsAmount", "RrsetsAmountDynamic"] -class ZoneRecord(BaseModel): +class Record(BaseModel): """Record - readonly short version of rrset""" name: Optional[str] = None @@ -21,7 +19,7 @@ class ZoneRecord(BaseModel): type: Optional[str] = None -class ZoneRrsetsAmountDynamic(BaseModel): +class RrsetsAmountDynamic(BaseModel): """Amount of dynamic RRsets in zone""" healthcheck: Optional[int] = None @@ -31,8 +29,8 @@ class ZoneRrsetsAmountDynamic(BaseModel): """Total amount of dynamic RRsets in zone""" -class ZoneRrsetsAmount(BaseModel): - dynamic: Optional[ZoneRrsetsAmountDynamic] = None +class RrsetsAmount(BaseModel): + dynamic: Optional[RrsetsAmountDynamic] = None """Amount of dynamic RRsets in zone""" static: Optional[int] = None @@ -42,8 +40,8 @@ class ZoneRrsetsAmount(BaseModel): """Total amount of RRsets in zone""" -class Zone(BaseModel): - """OutputZone""" +class ZoneGetResponse(BaseModel): + """Complete zone info with all records included""" id: Optional[int] = None """ @@ -51,8 +49,6 @@ class Zone(BaseModel): of getting deleted zones by admin. """ - client_id: Optional[int] = None - contact: Optional[str] = None """email address of the administrator responsible for this zone""" @@ -62,13 +58,15 @@ class Zone(BaseModel): dnssec is disabled for the zone """ + enabled: Optional[bool] = None + expiry: Optional[int] = None """ number of seconds after which secondary name servers should stop answering request for this zone """ - meta: Optional[object] = None + meta: Optional[Dict[str, object]] = None """arbitrarily data of zone in json format""" name: Optional[str] = None @@ -80,7 +78,7 @@ class Zone(BaseModel): primary_server: Optional[str] = None """primary master name server for zone""" - records: Optional[List[ZoneRecord]] = None + records: Optional[List[Record]] = None refresh: Optional[int] = None """ @@ -94,7 +92,7 @@ class Zone(BaseModel): serial number """ - rrsets_amount: Optional[ZoneRrsetsAmount] = None + rrsets_amount: Optional[RrsetsAmount] = None serial: Optional[int] = None """ @@ -105,10 +103,3 @@ class Zone(BaseModel): """ status: Optional[str] = None - - -class ZoneGetResponse(BaseModel): - """Complete zone info with all records included""" - - zone: Optional[Zone] = FieldInfo(alias="Zone", default=None) - """OutputZone""" diff --git a/src/gcore/types/dns/zone_list_response.py b/src/gcore/types/dns/zone_list_response.py index 16d0629b..4b0a0277 100644 --- a/src/gcore/types/dns/zone_list_response.py +++ b/src/gcore/types/dns/zone_list_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from ..._models import BaseModel @@ -60,13 +60,15 @@ class Zone(BaseModel): dnssec is disabled for the zone """ + enabled: Optional[bool] = None + expiry: Optional[int] = None """ number of seconds after which secondary name servers should stop answering request for this zone """ - meta: Optional[object] = None + meta: Optional[Dict[str, object]] = None """arbitrarily data of zone in json format""" name: Optional[str] = None diff --git a/src/gcore/types/dns/zones/dns_output_rrset.py b/src/gcore/types/dns/zones/dns_output_rrset.py index 13a99e28..67b794d6 100644 --- a/src/gcore/types/dns/zones/dns_output_rrset.py +++ b/src/gcore/types/dns/zones/dns_output_rrset.py @@ -38,11 +38,11 @@ class ResourceRecord(BaseModel): 2. `continents` (array of string) 3. `countries` (array of string) 4. `latlong` (array of float64, latitude and longitude) - 5. `fallback` (bool) - 6. `backup` (bool) - 7. `notes` (string) - 8. `weight` (float) - 9. `ip` (string) + 5. `backup` (bool) + 6. `notes` (string) + 7. `weight` (float) + 8. `ip` (string) + 9. `default` (bool) Some keys are reserved for balancing, @see https://api.gcore.com/dns/v2/info/meta diff --git a/src/gcore/types/iam/user.py b/src/gcore/types/iam/user.py index ba27f51d..0dcaa14b 100644 --- a/src/gcore/types/iam/user.py +++ b/src/gcore/types/iam/user.py @@ -5,7 +5,19 @@ from ..._models import BaseModel -__all__ = ["User", "Group"] +__all__ = ["User", "ClientAndRole", "Group"] + + +class ClientAndRole(BaseModel): + client_company_name: str + + client_id: int + + user_id: int + """User's ID.""" + + user_roles: List[str] + """User role in this client.""" class Group(BaseModel): @@ -25,32 +37,35 @@ class Group(BaseModel): class User(BaseModel): - id: Optional[int] = None + id: int """User's ID.""" - activated: Optional[bool] = None + activated: bool """Email confirmation: - `true` – user confirmed the email; - `false` – user did not confirm the email. """ - auth_types: Optional[List[Literal["password", "sso", "github", "google-oauth2"]]] = None + auth_types: List[Literal["password", "sso", "github", "google-oauth2"]] """System field. List of auth types available for the account.""" - client: Optional[float] = None + client: float """User's account ID.""" - company: Optional[str] = None + client_and_roles: List[ClientAndRole] + """List of user's clients. User can access to one or more clients.""" + + company: str """User's company.""" - deleted: Optional[bool] = None + deleted: bool """Deletion flag. If `true` then user was deleted.""" - email: Optional[str] = None + email: str """User's email address.""" - groups: Optional[List[Group]] = None + groups: List[Group] """User's group in the current account. IAM supports 5 groups: @@ -62,7 +77,10 @@ class User(BaseModel): - Purge and Prefetch only (API+Web) """ - lang: Optional[Literal["de", "en", "ru", "zh", "az"]] = None + is_active: bool + """User activity flag.""" + + lang: Literal["de", "en", "ru", "zh", "az"] """User's language. Defines language of the control panel and email messages. @@ -74,18 +92,18 @@ class User(BaseModel): phone: Optional[str] = None """User's phone.""" - reseller: Optional[int] = None + reseller: int """Services provider ID.""" - sso_auth: Optional[bool] = None + sso_auth: bool """SSO authentication flag. If `true` then user can login via SAML SSO.""" - two_fa: Optional[bool] = None + two_fa: bool """Two-step verification: - `true` – user enabled two-step verification; - `false` – user disabled two-step verification. """ - user_type: Optional[Literal["common"]] = None + user_type: Literal["common", "reseller", "seller"] """User's type.""" diff --git a/src/gcore/types/iam/user_update_params.py b/src/gcore/types/iam/user_update_params.py index 80d93a28..2874ef20 100644 --- a/src/gcore/types/iam/user_update_params.py +++ b/src/gcore/types/iam/user_update_params.py @@ -2,56 +2,27 @@ from __future__ import annotations -from typing import List, Iterable, Optional -from typing_extensions import Literal, TypedDict +from typing import List, Optional +from typing_extensions import Literal, Required, TypedDict -__all__ = ["UserUpdateParams", "Group"] +__all__ = ["UserUpdateParams"] class UserUpdateParams(TypedDict, total=False): - auth_types: List[Literal["password", "sso", "github", "google-oauth2"]] + auth_types: Required[List[Literal["password", "sso", "github", "google-oauth2"]]] """System field. List of auth types available for the account.""" - company: str - """User's company.""" - - email: str + email: Required[str] """User's email address.""" - groups: Iterable[Group] - """User's group in the current account. - - IAM supports 5 groups: - - - Users - - Administrators - - Engineers - - Purge and Prefetch only (API) - - Purge and Prefetch only (API+Web) - """ - - lang: Literal["de", "en", "ru", "zh", "az"] + lang: Required[Literal["de", "en", "ru", "zh", "az"]] """User's language. Defines language of the control panel and email messages. """ - name: Optional[str] + name: Required[Optional[str]] """User's name.""" - phone: Optional[str] + phone: Required[Optional[str]] """User's phone.""" - - -class Group(TypedDict, total=False): - id: int - """Group's ID: Possible values are: - - - 1 - Administrators* 2 - Users* 5 - Engineers* 3009 - Purge and Prefetch only - (API+Web)* 3022 - Purge and Prefetch only (API) - """ - - name: Literal[ - "Users", "Administrators", "Engineers", "Purge and Prefetch only (API)", "Purge and Prefetch only (API+Web)" - ] - """Group's name.""" diff --git a/tests/api_resources/cdn/logs_uploader/test_policies.py b/tests/api_resources/cdn/logs_uploader/test_policies.py index 07ed96bf..e197ed4c 100644 --- a/tests/api_resources/cdn/logs_uploader/test_policies.py +++ b/tests/api_resources/cdn/logs_uploader/test_policies.py @@ -31,11 +31,12 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: policy = client.cdn.logs_uploader.policies.create( date_format="[02/Jan/2006:15:04:05 -0700]", description="New policy", + escape_special_characters=True, field_delimiter=",", field_separator=";", fields=["remote_addr", "status"], file_name_template="{{YYYY}}_{{MM}}_{{DD}}_{{HH}}_{{mm}}_{{ss}}_access.log.gz", - format_type="flvproxy", + format_type="json", include_empty_logs=True, include_shield_logs=True, name="Policy", @@ -80,11 +81,12 @@ def test_method_update_with_all_params(self, client: Gcore) -> None: id=0, date_format="[02/Jan/2006:15:04:05 -0700]", description="New policy", + escape_special_characters=True, field_delimiter=",", field_separator=";", fields=["remote_addr", "status"], file_name_template="{{YYYY}}_{{MM}}_{{DD}}_{{HH}}_{{mm}}_{{ss}}_access.log.gz", - format_type="flvproxy", + format_type="json", include_empty_logs=True, include_shield_logs=True, name="Policy", @@ -253,11 +255,12 @@ def test_method_replace_with_all_params(self, client: Gcore) -> None: id=0, date_format="[02/Jan/2006:15:04:05 -0700]", description="New policy", + escape_special_characters=True, field_delimiter=",", field_separator=";", fields=["remote_addr", "status"], file_name_template="{{YYYY}}_{{MM}}_{{DD}}_{{HH}}_{{mm}}_{{ss}}_access.log.gz", - format_type="flvproxy", + format_type="json", include_empty_logs=True, include_shield_logs=True, name="Policy", @@ -309,11 +312,12 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> policy = await async_client.cdn.logs_uploader.policies.create( date_format="[02/Jan/2006:15:04:05 -0700]", description="New policy", + escape_special_characters=True, field_delimiter=",", field_separator=";", fields=["remote_addr", "status"], file_name_template="{{YYYY}}_{{MM}}_{{DD}}_{{HH}}_{{mm}}_{{ss}}_access.log.gz", - format_type="flvproxy", + format_type="json", include_empty_logs=True, include_shield_logs=True, name="Policy", @@ -358,11 +362,12 @@ async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> id=0, date_format="[02/Jan/2006:15:04:05 -0700]", description="New policy", + escape_special_characters=True, field_delimiter=",", field_separator=";", fields=["remote_addr", "status"], file_name_template="{{YYYY}}_{{MM}}_{{DD}}_{{HH}}_{{mm}}_{{ss}}_access.log.gz", - format_type="flvproxy", + format_type="json", include_empty_logs=True, include_shield_logs=True, name="Policy", @@ -531,11 +536,12 @@ async def test_method_replace_with_all_params(self, async_client: AsyncGcore) -> id=0, date_format="[02/Jan/2006:15:04:05 -0700]", description="New policy", + escape_special_characters=True, field_delimiter=",", field_separator=";", fields=["remote_addr", "status"], file_name_template="{{YYYY}}_{{MM}}_{{DD}}_{{HH}}_{{mm}}_{{ss}}_access.log.gz", - format_type="flvproxy", + format_type="json", include_empty_logs=True, include_shield_logs=True, name="Policy", diff --git a/tests/api_resources/cloud/inference/test_deployments.py b/tests/api_resources/cloud/inference/test_deployments.py index 6b9b0802..a9e40264 100644 --- a/tests/api_resources/cloud/inference/test_deployments.py +++ b/tests/api_resources/cloud/inference/test_deployments.py @@ -230,7 +230,7 @@ def test_method_update_with_all_params(self, client: Gcore) -> None: command=["nginx", "-g", "daemon off;"], containers=[ { - "region_id": 0, + "region_id": 1337, "scale": { "max": 3, "min": 1, @@ -839,7 +839,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> command=["nginx", "-g", "daemon off;"], containers=[ { - "region_id": 0, + "region_id": 1337, "scale": { "max": 3, "min": 1, diff --git a/tests/api_resources/cloud/load_balancers/pools/test_members.py b/tests/api_resources/cloud/load_balancers/pools/test_members.py index 3037fa30..57533ae8 100644 --- a/tests/api_resources/cloud/load_balancers/pools/test_members.py +++ b/tests/api_resources/cloud/load_balancers/pools/test_members.py @@ -40,7 +40,7 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: backup=True, instance_id="a7e7e8d6-0bf7-4ac9-8170-831b47ee2ba9", monitor_address="monitor_address", - monitor_port=0, + monitor_port=1, subnet_id="32283b0b-b560-4690-810c-f672cbb2e28d", weight=1, ) @@ -176,7 +176,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> backup=True, instance_id="a7e7e8d6-0bf7-4ac9-8170-831b47ee2ba9", monitor_address="monitor_address", - monitor_port=0, + monitor_port=1, subnet_id="32283b0b-b560-4690-810c-f672cbb2e28d", weight=1, ) diff --git a/tests/api_resources/cloud/load_balancers/test_flavors.py b/tests/api_resources/cloud/load_balancers/test_flavors.py index 51b2776e..49f14df1 100644 --- a/tests/api_resources/cloud/load_balancers/test_flavors.py +++ b/tests/api_resources/cloud/load_balancers/test_flavors.py @@ -20,16 +20,16 @@ class TestFlavors: @parametrize def test_method_list(self, client: Gcore) -> None: flavor = client.cloud.load_balancers.flavors.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancerFlavorList, flavor, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Gcore) -> None: flavor = client.cloud.load_balancers.flavors.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, include_prices=True, ) assert_matches_type(LoadBalancerFlavorList, flavor, path=["response"]) @@ -37,8 +37,8 @@ def test_method_list_with_all_params(self, client: Gcore) -> None: @parametrize def test_raw_response_list(self, client: Gcore) -> None: response = client.cloud.load_balancers.flavors.with_raw_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -49,8 +49,8 @@ def test_raw_response_list(self, client: Gcore) -> None: @parametrize def test_streaming_response_list(self, client: Gcore) -> None: with client.cloud.load_balancers.flavors.with_streaming_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -69,16 +69,16 @@ class TestAsyncFlavors: @parametrize async def test_method_list(self, async_client: AsyncGcore) -> None: flavor = await async_client.cloud.load_balancers.flavors.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancerFlavorList, flavor, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: flavor = await async_client.cloud.load_balancers.flavors.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, include_prices=True, ) assert_matches_type(LoadBalancerFlavorList, flavor, path=["response"]) @@ -86,8 +86,8 @@ async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> No @parametrize async def test_raw_response_list(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.flavors.with_raw_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -98,8 +98,8 @@ async def test_raw_response_list(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.flavors.with_streaming_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/cloud/load_balancers/test_metrics.py b/tests/api_resources/cloud/load_balancers/test_metrics.py index 281f1d68..3ab21ffd 100644 --- a/tests/api_resources/cloud/load_balancers/test_metrics.py +++ b/tests/api_resources/cloud/load_balancers/test_metrics.py @@ -20,9 +20,9 @@ class TestMetrics: @parametrize def test_method_list(self, client: Gcore) -> None: metric = client.cloud.load_balancers.metrics.list( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, time_interval=6, time_unit="day", ) @@ -31,9 +31,9 @@ def test_method_list(self, client: Gcore) -> None: @parametrize def test_raw_response_list(self, client: Gcore) -> None: response = client.cloud.load_balancers.metrics.with_raw_response.list( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, time_interval=6, time_unit="day", ) @@ -46,9 +46,9 @@ def test_raw_response_list(self, client: Gcore) -> None: @parametrize def test_streaming_response_list(self, client: Gcore) -> None: with client.cloud.load_balancers.metrics.with_streaming_response.list( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, time_interval=6, time_unit="day", ) as response: @@ -65,8 +65,8 @@ def test_path_params_list(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): client.cloud.load_balancers.metrics.with_raw_response.list( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, time_interval=6, time_unit="day", ) @@ -80,9 +80,9 @@ class TestAsyncMetrics: @parametrize async def test_method_list(self, async_client: AsyncGcore) -> None: metric = await async_client.cloud.load_balancers.metrics.list( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, time_interval=6, time_unit="day", ) @@ -91,9 +91,9 @@ async def test_method_list(self, async_client: AsyncGcore) -> None: @parametrize async def test_raw_response_list(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.metrics.with_raw_response.list( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, time_interval=6, time_unit="day", ) @@ -106,9 +106,9 @@ async def test_raw_response_list(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.metrics.with_streaming_response.list( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, time_interval=6, time_unit="day", ) as response: @@ -125,8 +125,8 @@ async def test_path_params_list(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): await async_client.cloud.load_balancers.metrics.with_raw_response.list( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, time_interval=6, time_unit="day", ) diff --git a/tests/api_resources/cloud/load_balancers/test_pools.py b/tests/api_resources/cloud/load_balancers/test_pools.py index 0b095c3d..3a381afc 100644 --- a/tests/api_resources/cloud/load_balancers/test_pools.py +++ b/tests/api_resources/cloud/load_balancers/test_pools.py @@ -58,7 +58,7 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: "backup": True, "instance_id": "a7e7e8d6-0bf7-4ac9-8170-831b47ee2ba9", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 2, }, @@ -69,7 +69,7 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: "backup": True, "instance_id": "169942e0-9b53-42df-95ef-1a8b6525c2bd", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 4, }, @@ -155,7 +155,7 @@ def test_method_update_with_all_params(self, client: Gcore) -> None: "backup": True, "instance_id": "a7e7e8d6-0bf7-4ac9-8170-831b47ee2ba9", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 1, } @@ -396,7 +396,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> "backup": True, "instance_id": "a7e7e8d6-0bf7-4ac9-8170-831b47ee2ba9", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 2, }, @@ -407,7 +407,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> "backup": True, "instance_id": "169942e0-9b53-42df-95ef-1a8b6525c2bd", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 4, }, @@ -493,7 +493,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> "backup": True, "instance_id": "a7e7e8d6-0bf7-4ac9-8170-831b47ee2ba9", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 1, } diff --git a/tests/api_resources/cloud/load_balancers/test_statuses.py b/tests/api_resources/cloud/load_balancers/test_statuses.py index da7e88cb..9de4628c 100644 --- a/tests/api_resources/cloud/load_balancers/test_statuses.py +++ b/tests/api_resources/cloud/load_balancers/test_statuses.py @@ -20,16 +20,16 @@ class TestStatuses: @parametrize def test_method_list(self, client: Gcore) -> None: status = client.cloud.load_balancers.statuses.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancerStatusList, status, path=["response"]) @parametrize def test_raw_response_list(self, client: Gcore) -> None: response = client.cloud.load_balancers.statuses.with_raw_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -40,8 +40,8 @@ def test_raw_response_list(self, client: Gcore) -> None: @parametrize def test_streaming_response_list(self, client: Gcore) -> None: with client.cloud.load_balancers.statuses.with_streaming_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -54,18 +54,18 @@ def test_streaming_response_list(self, client: Gcore) -> None: @parametrize def test_method_get(self, client: Gcore) -> None: status = client.cloud.load_balancers.statuses.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancerStatus, status, path=["response"]) @parametrize def test_raw_response_get(self, client: Gcore) -> None: response = client.cloud.load_balancers.statuses.with_raw_response.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -76,9 +76,9 @@ def test_raw_response_get(self, client: Gcore) -> None: @parametrize def test_streaming_response_get(self, client: Gcore) -> None: with client.cloud.load_balancers.statuses.with_streaming_response.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -93,8 +93,8 @@ def test_path_params_get(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): client.cloud.load_balancers.statuses.with_raw_response.get( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) @@ -106,16 +106,16 @@ class TestAsyncStatuses: @parametrize async def test_method_list(self, async_client: AsyncGcore) -> None: status = await async_client.cloud.load_balancers.statuses.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancerStatusList, status, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.statuses.with_raw_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -126,8 +126,8 @@ async def test_raw_response_list(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.statuses.with_streaming_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -140,18 +140,18 @@ async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: @parametrize async def test_method_get(self, async_client: AsyncGcore) -> None: status = await async_client.cloud.load_balancers.statuses.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancerStatus, status, path=["response"]) @parametrize async def test_raw_response_get(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.statuses.with_raw_response.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -162,9 +162,9 @@ async def test_raw_response_get(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_get(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.statuses.with_streaming_response.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -179,6 +179,6 @@ async def test_path_params_get(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): await async_client.cloud.load_balancers.statuses.with_raw_response.get( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) diff --git a/tests/api_resources/cloud/quotas/test_requests.py b/tests/api_resources/cloud/quotas/test_requests.py index 3c7152a1..00d49bcd 100644 --- a/tests/api_resources/cloud/quotas/test_requests.py +++ b/tests/api_resources/cloud/quotas/test_requests.py @@ -9,6 +9,7 @@ from gcore import Gcore, AsyncGcore from tests.utils import assert_matches_type +from gcore._utils import parse_datetime from gcore.pagination import SyncOffsetPage, AsyncOffsetPage from gcore.types.cloud.quotas import RequestGetResponse, RequestListResponse @@ -134,8 +135,11 @@ def test_method_list(self, client: Gcore) -> None: @parametrize def test_method_list_with_all_params(self, client: Gcore) -> None: request = client.cloud.quotas.requests.list( + created_from=parse_datetime("2024-01-01T00:00:00Z"), + created_to=parse_datetime("2024-12-31T23:59:59Z"), limit=1000, offset=0, + request_ids=[1, 2, 3], status=["done", "in progress"], ) assert_matches_type(SyncOffsetPage[RequestListResponse], request, path=["response"]) @@ -344,8 +348,11 @@ async def test_method_list(self, async_client: AsyncGcore) -> None: @parametrize async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: request = await async_client.cloud.quotas.requests.list( + created_from=parse_datetime("2024-01-01T00:00:00Z"), + created_to=parse_datetime("2024-12-31T23:59:59Z"), limit=1000, offset=0, + request_ids=[1, 2, 3], status=["done", "in progress"], ) assert_matches_type(AsyncOffsetPage[RequestListResponse], request, path=["response"]) diff --git a/tests/api_resources/cloud/security_groups/test_rules.py b/tests/api_resources/cloud/security_groups/test_rules.py index 6f84f09a..b3e9f95f 100644 --- a/tests/api_resources/cloud/security_groups/test_rules.py +++ b/tests/api_resources/cloud/security_groups/test_rules.py @@ -20,20 +20,21 @@ class TestRules: @parametrize def test_method_create(self, client: Gcore) -> None: rule = client.cloud.security_groups.rules.create( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + direction="ingress", ) assert_matches_type(SecurityGroupRule, rule, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: Gcore) -> None: rule = client.cloud.security_groups.rules.create( - group_id="group_id", - project_id=0, - region_id=0, - description="Some description", + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", + description="Some description", ethertype="IPv4", port_range_max=80, port_range_min=80, @@ -46,9 +47,10 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: @parametrize def test_raw_response_create(self, client: Gcore) -> None: response = client.cloud.security_groups.rules.with_raw_response.create( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + direction="ingress", ) assert response.is_closed is True @@ -59,9 +61,10 @@ def test_raw_response_create(self, client: Gcore) -> None: @parametrize def test_streaming_response_create(self, client: Gcore) -> None: with client.cloud.security_groups.rules.with_streaming_response.create( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + direction="ingress", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -76,25 +79,26 @@ def test_path_params_create(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): client.cloud.security_groups.rules.with_raw_response.create( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, + direction="ingress", ) @parametrize def test_method_delete(self, client: Gcore) -> None: rule = client.cloud.security_groups.rules.delete( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert rule is None @parametrize def test_raw_response_delete(self, client: Gcore) -> None: response = client.cloud.security_groups.rules.with_raw_response.delete( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert response.is_closed is True @@ -105,9 +109,9 @@ def test_raw_response_delete(self, client: Gcore) -> None: @parametrize def test_streaming_response_delete(self, client: Gcore) -> None: with client.cloud.security_groups.rules.with_streaming_response.delete( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -122,16 +126,16 @@ def test_path_params_delete(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `rule_id` but received ''"): client.cloud.security_groups.rules.with_raw_response.delete( rule_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, ) @parametrize def test_method_replace(self, client: Gcore) -> None: rule = client.cloud.security_groups.rules.replace( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", ) @@ -140,9 +144,9 @@ def test_method_replace(self, client: Gcore) -> None: @parametrize def test_method_replace_with_all_params(self, client: Gcore) -> None: rule = client.cloud.security_groups.rules.replace( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", description="Some description", @@ -158,9 +162,9 @@ def test_method_replace_with_all_params(self, client: Gcore) -> None: @parametrize def test_raw_response_replace(self, client: Gcore) -> None: response = client.cloud.security_groups.rules.with_raw_response.replace( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", ) @@ -173,9 +177,9 @@ def test_raw_response_replace(self, client: Gcore) -> None: @parametrize def test_streaming_response_replace(self, client: Gcore) -> None: with client.cloud.security_groups.rules.with_streaming_response.replace( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", ) as response: @@ -192,8 +196,8 @@ def test_path_params_replace(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `rule_id` but received ''"): client.cloud.security_groups.rules.with_raw_response.replace( rule_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", ) @@ -207,20 +211,21 @@ class TestAsyncRules: @parametrize async def test_method_create(self, async_client: AsyncGcore) -> None: rule = await async_client.cloud.security_groups.rules.create( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + direction="ingress", ) assert_matches_type(SecurityGroupRule, rule, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> None: rule = await async_client.cloud.security_groups.rules.create( - group_id="group_id", - project_id=0, - region_id=0, - description="Some description", + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", + description="Some description", ethertype="IPv4", port_range_max=80, port_range_min=80, @@ -233,9 +238,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> @parametrize async def test_raw_response_create(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.security_groups.rules.with_raw_response.create( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + direction="ingress", ) assert response.is_closed is True @@ -246,9 +252,10 @@ async def test_raw_response_create(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncGcore) -> None: async with async_client.cloud.security_groups.rules.with_streaming_response.create( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + direction="ingress", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -263,25 +270,26 @@ async def test_path_params_create(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): await async_client.cloud.security_groups.rules.with_raw_response.create( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, + direction="ingress", ) @parametrize async def test_method_delete(self, async_client: AsyncGcore) -> None: rule = await async_client.cloud.security_groups.rules.delete( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert rule is None @parametrize async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.security_groups.rules.with_raw_response.delete( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert response.is_closed is True @@ -292,9 +300,9 @@ async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncGcore) -> None: async with async_client.cloud.security_groups.rules.with_streaming_response.delete( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -309,16 +317,16 @@ async def test_path_params_delete(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `rule_id` but received ''"): await async_client.cloud.security_groups.rules.with_raw_response.delete( rule_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, ) @parametrize async def test_method_replace(self, async_client: AsyncGcore) -> None: rule = await async_client.cloud.security_groups.rules.replace( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", ) @@ -327,9 +335,9 @@ async def test_method_replace(self, async_client: AsyncGcore) -> None: @parametrize async def test_method_replace_with_all_params(self, async_client: AsyncGcore) -> None: rule = await async_client.cloud.security_groups.rules.replace( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", description="Some description", @@ -345,9 +353,9 @@ async def test_method_replace_with_all_params(self, async_client: AsyncGcore) -> @parametrize async def test_raw_response_replace(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.security_groups.rules.with_raw_response.replace( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", ) @@ -360,9 +368,9 @@ async def test_raw_response_replace(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_replace(self, async_client: AsyncGcore) -> None: async with async_client.cloud.security_groups.rules.with_streaming_response.replace( - rule_id="rule_id", - project_id=0, - region_id=0, + rule_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", ) as response: @@ -379,8 +387,8 @@ async def test_path_params_replace(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `rule_id` but received ''"): await async_client.cloud.security_groups.rules.with_raw_response.replace( rule_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, direction="ingress", security_group_id="00000000-0000-4000-8000-000000000000", ) diff --git a/tests/api_resources/cloud/test_floating_ips.py b/tests/api_resources/cloud/test_floating_ips.py index 9768e23c..b2394861 100644 --- a/tests/api_resources/cloud/test_floating_ips.py +++ b/tests/api_resources/cloud/test_floating_ips.py @@ -16,6 +16,8 @@ FloatingIPDetailed, ) +# pyright: reportDeprecated=false + base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -69,30 +71,35 @@ def test_streaming_response_create(self, client: Gcore) -> None: @parametrize def test_method_update(self, client: Gcore) -> None: - floating_ip = client.cloud.floating_ips.update( - floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", - project_id=1, - region_id=1, - ) + with pytest.warns(DeprecationWarning): + floating_ip = client.cloud.floating_ips.update( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: Gcore) -> None: - floating_ip = client.cloud.floating_ips.update( - floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", - project_id=1, - region_id=1, - tags={"foo": "my-tag-value"}, - ) + with pytest.warns(DeprecationWarning): + floating_ip = client.cloud.floating_ips.update( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + tags={"foo": "my-tag-value"}, + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize def test_raw_response_update(self, client: Gcore) -> None: - response = client.cloud.floating_ips.with_raw_response.update( - floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", - project_id=1, - region_id=1, - ) + with pytest.warns(DeprecationWarning): + response = client.cloud.floating_ips.with_raw_response.update( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -101,27 +108,29 @@ def test_raw_response_update(self, client: Gcore) -> None: @parametrize def test_streaming_response_update(self, client: Gcore) -> None: - with client.cloud.floating_ips.with_streaming_response.update( - floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", - project_id=1, - region_id=1, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + with pytest.warns(DeprecationWarning): + with client.cloud.floating_ips.with_streaming_response.update( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" - floating_ip = response.parse() - assert_matches_type(FloatingIP, floating_ip, path=["response"]) + floating_ip = response.parse() + assert_matches_type(FloatingIP, floating_ip, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: Gcore) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): - client.cloud.floating_ips.with_raw_response.update( - floating_ip_id="", - project_id=1, - region_id=1, - ) + with pytest.warns(DeprecationWarning): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): + client.cloud.floating_ips.with_raw_response.update( + floating_ip_id="", + project_id=1, + region_id=1, + ) @parametrize def test_method_list(self, client: Gcore) -> None: @@ -218,33 +227,38 @@ def test_path_params_delete(self, client: Gcore) -> None: @parametrize def test_method_assign(self, client: Gcore) -> None: - floating_ip = client.cloud.floating_ips.assign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - ) + with pytest.warns(DeprecationWarning): + floating_ip = client.cloud.floating_ips.assign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize def test_method_assign_with_all_params(self, client: Gcore) -> None: - floating_ip = client.cloud.floating_ips.assign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - fixed_ip_address="192.168.10.15", - ) + with pytest.warns(DeprecationWarning): + floating_ip = client.cloud.floating_ips.assign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + fixed_ip_address="192.168.10.15", + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize def test_raw_response_assign(self, client: Gcore) -> None: - response = client.cloud.floating_ips.with_raw_response.assign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - ) + with pytest.warns(DeprecationWarning): + response = client.cloud.floating_ips.with_raw_response.assign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -253,29 +267,31 @@ def test_raw_response_assign(self, client: Gcore) -> None: @parametrize def test_streaming_response_assign(self, client: Gcore) -> None: - with client.cloud.floating_ips.with_streaming_response.assign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + with pytest.warns(DeprecationWarning): + with client.cloud.floating_ips.with_streaming_response.assign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" - floating_ip = response.parse() - assert_matches_type(FloatingIP, floating_ip, path=["response"]) + floating_ip = response.parse() + assert_matches_type(FloatingIP, floating_ip, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_assign(self, client: Gcore) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): - client.cloud.floating_ips.with_raw_response.assign( - floating_ip_id="", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - ) + with pytest.warns(DeprecationWarning): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): + client.cloud.floating_ips.with_raw_response.assign( + floating_ip_id="", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + ) @parametrize def test_method_get(self, client: Gcore) -> None: @@ -325,20 +341,23 @@ def test_path_params_get(self, client: Gcore) -> None: @parametrize def test_method_unassign(self, client: Gcore) -> None: - floating_ip = client.cloud.floating_ips.unassign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + floating_ip = client.cloud.floating_ips.unassign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize def test_raw_response_unassign(self, client: Gcore) -> None: - response = client.cloud.floating_ips.with_raw_response.unassign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + response = client.cloud.floating_ips.with_raw_response.unassign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -347,27 +366,29 @@ def test_raw_response_unassign(self, client: Gcore) -> None: @parametrize def test_streaming_response_unassign(self, client: Gcore) -> None: - with client.cloud.floating_ips.with_streaming_response.unassign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + with pytest.warns(DeprecationWarning): + with client.cloud.floating_ips.with_streaming_response.unassign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" - floating_ip = response.parse() - assert_matches_type(FloatingIP, floating_ip, path=["response"]) + floating_ip = response.parse() + assert_matches_type(FloatingIP, floating_ip, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_unassign(self, client: Gcore) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): - client.cloud.floating_ips.with_raw_response.unassign( - floating_ip_id="", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): + client.cloud.floating_ips.with_raw_response.unassign( + floating_ip_id="", + project_id=1, + region_id=1, + ) class TestAsyncFloatingIPs: @@ -422,30 +443,35 @@ async def test_streaming_response_create(self, async_client: AsyncGcore) -> None @parametrize async def test_method_update(self, async_client: AsyncGcore) -> None: - floating_ip = await async_client.cloud.floating_ips.update( - floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", - project_id=1, - region_id=1, - ) + with pytest.warns(DeprecationWarning): + floating_ip = await async_client.cloud.floating_ips.update( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> None: - floating_ip = await async_client.cloud.floating_ips.update( - floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", - project_id=1, - region_id=1, - tags={"foo": "my-tag-value"}, - ) + with pytest.warns(DeprecationWarning): + floating_ip = await async_client.cloud.floating_ips.update( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + tags={"foo": "my-tag-value"}, + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncGcore) -> None: - response = await async_client.cloud.floating_ips.with_raw_response.update( - floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", - project_id=1, - region_id=1, - ) + with pytest.warns(DeprecationWarning): + response = await async_client.cloud.floating_ips.with_raw_response.update( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -454,27 +480,29 @@ async def test_raw_response_update(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_update(self, async_client: AsyncGcore) -> None: - async with async_client.cloud.floating_ips.with_streaming_response.update( - floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", - project_id=1, - region_id=1, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + with pytest.warns(DeprecationWarning): + async with async_client.cloud.floating_ips.with_streaming_response.update( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" - floating_ip = await response.parse() - assert_matches_type(FloatingIP, floating_ip, path=["response"]) + floating_ip = await response.parse() + assert_matches_type(FloatingIP, floating_ip, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncGcore) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): - await async_client.cloud.floating_ips.with_raw_response.update( - floating_ip_id="", - project_id=1, - region_id=1, - ) + with pytest.warns(DeprecationWarning): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): + await async_client.cloud.floating_ips.with_raw_response.update( + floating_ip_id="", + project_id=1, + region_id=1, + ) @parametrize async def test_method_list(self, async_client: AsyncGcore) -> None: @@ -571,33 +599,38 @@ async def test_path_params_delete(self, async_client: AsyncGcore) -> None: @parametrize async def test_method_assign(self, async_client: AsyncGcore) -> None: - floating_ip = await async_client.cloud.floating_ips.assign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - ) + with pytest.warns(DeprecationWarning): + floating_ip = await async_client.cloud.floating_ips.assign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize async def test_method_assign_with_all_params(self, async_client: AsyncGcore) -> None: - floating_ip = await async_client.cloud.floating_ips.assign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - fixed_ip_address="192.168.10.15", - ) + with pytest.warns(DeprecationWarning): + floating_ip = await async_client.cloud.floating_ips.assign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + fixed_ip_address="192.168.10.15", + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize async def test_raw_response_assign(self, async_client: AsyncGcore) -> None: - response = await async_client.cloud.floating_ips.with_raw_response.assign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - ) + with pytest.warns(DeprecationWarning): + response = await async_client.cloud.floating_ips.with_raw_response.assign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -606,29 +639,31 @@ async def test_raw_response_assign(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_assign(self, async_client: AsyncGcore) -> None: - async with async_client.cloud.floating_ips.with_streaming_response.assign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + with pytest.warns(DeprecationWarning): + async with async_client.cloud.floating_ips.with_streaming_response.assign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" - floating_ip = await response.parse() - assert_matches_type(FloatingIP, floating_ip, path=["response"]) + floating_ip = await response.parse() + assert_matches_type(FloatingIP, floating_ip, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_assign(self, async_client: AsyncGcore) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): - await async_client.cloud.floating_ips.with_raw_response.assign( - floating_ip_id="", - project_id=0, - region_id=0, - port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", - ) + with pytest.warns(DeprecationWarning): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): + await async_client.cloud.floating_ips.with_raw_response.assign( + floating_ip_id="", + project_id=1, + region_id=1, + port_id="ee2402d0-f0cd-4503-9b75-69be1d11c5f1", + ) @parametrize async def test_method_get(self, async_client: AsyncGcore) -> None: @@ -678,20 +713,23 @@ async def test_path_params_get(self, async_client: AsyncGcore) -> None: @parametrize async def test_method_unassign(self, async_client: AsyncGcore) -> None: - floating_ip = await async_client.cloud.floating_ips.unassign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + floating_ip = await async_client.cloud.floating_ips.unassign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) + assert_matches_type(FloatingIP, floating_ip, path=["response"]) @parametrize async def test_raw_response_unassign(self, async_client: AsyncGcore) -> None: - response = await async_client.cloud.floating_ips.with_raw_response.unassign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + response = await async_client.cloud.floating_ips.with_raw_response.unassign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -700,24 +738,26 @@ async def test_raw_response_unassign(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_unassign(self, async_client: AsyncGcore) -> None: - async with async_client.cloud.floating_ips.with_streaming_response.unassign( - floating_ip_id="floating_ip_id", - project_id=0, - region_id=0, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + with pytest.warns(DeprecationWarning): + async with async_client.cloud.floating_ips.with_streaming_response.unassign( + floating_ip_id="c64e5db1-5f1f-43ec-a8d9-5090df85b82d", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" - floating_ip = await response.parse() - assert_matches_type(FloatingIP, floating_ip, path=["response"]) + floating_ip = await response.parse() + assert_matches_type(FloatingIP, floating_ip, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_unassign(self, async_client: AsyncGcore) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): - await async_client.cloud.floating_ips.with_raw_response.unassign( - floating_ip_id="", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `floating_ip_id` but received ''"): + await async_client.cloud.floating_ips.with_raw_response.unassign( + floating_ip_id="", + project_id=1, + region_id=1, + ) diff --git a/tests/api_resources/cloud/test_load_balancers.py b/tests/api_resources/cloud/test_load_balancers.py index faf824ef..814fbc75 100644 --- a/tests/api_resources/cloud/test_load_balancers.py +++ b/tests/api_resources/cloud/test_load_balancers.py @@ -24,16 +24,16 @@ class TestLoadBalancers: @parametrize def test_method_create(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.create( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.create( - project_id=0, - region_id=0, + project_id=1, + region_id=7, flavor="lb1-1-2", floating_ip={ "existing_floating_id": "c64e5db1-5f1f-43ec-a8d9-5090df85b82d", @@ -64,8 +64,6 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: "max_retries_down": 3, "url_path": "/", }, - "listener_id": "listener_id", - "load_balancer_id": "bbb35f84-35cc-4b2f-84c2-a6a29bba68aa", "members": [ { "address": "192.168.1.101", @@ -74,7 +72,7 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: "backup": True, "instance_id": "a7e7e8d6-0bf7-4ac9-8170-831b47ee2ba9", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 2, }, @@ -85,7 +83,7 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: "backup": True, "instance_id": "169942e0-9b53-42df-95ef-1a8b6525c2bd", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 4, }, @@ -135,8 +133,8 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: @parametrize def test_raw_response_create(self, client: Gcore) -> None: response = client.cloud.load_balancers.with_raw_response.create( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -147,8 +145,8 @@ def test_raw_response_create(self, client: Gcore) -> None: @parametrize def test_streaming_response_create(self, client: Gcore) -> None: with client.cloud.load_balancers.with_streaming_response.create( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -161,18 +159,18 @@ def test_streaming_response_create(self, client: Gcore) -> None: @parametrize def test_method_update(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.update( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancer, load_balancer, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.update( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, logging={ "destination_region_id": 1, "enabled": True, @@ -188,9 +186,9 @@ def test_method_update_with_all_params(self, client: Gcore) -> None: @parametrize def test_raw_response_update(self, client: Gcore) -> None: response = client.cloud.load_balancers.with_raw_response.update( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -201,9 +199,9 @@ def test_raw_response_update(self, client: Gcore) -> None: @parametrize def test_streaming_response_update(self, client: Gcore) -> None: with client.cloud.load_balancers.with_streaming_response.update( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -218,31 +216,31 @@ def test_path_params_update(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): client.cloud.load_balancers.with_raw_response.update( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) @parametrize def test_method_list(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert_matches_type(SyncOffsetPage[LoadBalancer], load_balancer, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, assigned_floating=True, - limit=0, + limit=1000, logging_enabled=True, - name="name", + name="lb_name", offset=0, - order_by="order_by", + order_by="name.asc", show_stats=True, - tag_key=["string"], + tag_key=["key1", "key2"], tag_key_value="tag_key_value", with_ddos=True, ) @@ -251,8 +249,8 @@ def test_method_list_with_all_params(self, client: Gcore) -> None: @parametrize def test_raw_response_list(self, client: Gcore) -> None: response = client.cloud.load_balancers.with_raw_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -263,8 +261,8 @@ def test_raw_response_list(self, client: Gcore) -> None: @parametrize def test_streaming_response_list(self, client: Gcore) -> None: with client.cloud.load_balancers.with_streaming_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -277,18 +275,18 @@ def test_streaming_response_list(self, client: Gcore) -> None: @parametrize def test_method_delete(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.delete( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @parametrize def test_raw_response_delete(self, client: Gcore) -> None: response = client.cloud.load_balancers.with_raw_response.delete( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -299,9 +297,9 @@ def test_raw_response_delete(self, client: Gcore) -> None: @parametrize def test_streaming_response_delete(self, client: Gcore) -> None: with client.cloud.load_balancers.with_streaming_response.delete( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -316,25 +314,25 @@ def test_path_params_delete(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): client.cloud.load_balancers.with_raw_response.delete( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) @parametrize def test_method_failover(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.failover( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @parametrize def test_method_failover_with_all_params(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.failover( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, force=True, ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @@ -342,9 +340,9 @@ def test_method_failover_with_all_params(self, client: Gcore) -> None: @parametrize def test_raw_response_failover(self, client: Gcore) -> None: response = client.cloud.load_balancers.with_raw_response.failover( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -355,9 +353,9 @@ def test_raw_response_failover(self, client: Gcore) -> None: @parametrize def test_streaming_response_failover(self, client: Gcore) -> None: with client.cloud.load_balancers.with_streaming_response.failover( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -372,25 +370,25 @@ def test_path_params_failover(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): client.cloud.load_balancers.with_raw_response.failover( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) @parametrize def test_method_get(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancer, load_balancer, path=["response"]) @parametrize def test_method_get_with_all_params(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, show_stats=True, with_ddos=True, ) @@ -399,9 +397,9 @@ def test_method_get_with_all_params(self, client: Gcore) -> None: @parametrize def test_raw_response_get(self, client: Gcore) -> None: response = client.cloud.load_balancers.with_raw_response.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -412,9 +410,9 @@ def test_raw_response_get(self, client: Gcore) -> None: @parametrize def test_streaming_response_get(self, client: Gcore) -> None: with client.cloud.load_balancers.with_streaming_response.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -429,16 +427,16 @@ def test_path_params_get(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): client.cloud.load_balancers.with_raw_response.get( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) @parametrize def test_method_resize(self, client: Gcore) -> None: load_balancer = client.cloud.load_balancers.resize( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, flavor="lb1-2-4", ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @@ -446,9 +444,9 @@ def test_method_resize(self, client: Gcore) -> None: @parametrize def test_raw_response_resize(self, client: Gcore) -> None: response = client.cloud.load_balancers.with_raw_response.resize( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, flavor="lb1-2-4", ) @@ -460,9 +458,9 @@ def test_raw_response_resize(self, client: Gcore) -> None: @parametrize def test_streaming_response_resize(self, client: Gcore) -> None: with client.cloud.load_balancers.with_streaming_response.resize( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, flavor="lb1-2-4", ) as response: assert not response.is_closed @@ -478,8 +476,8 @@ def test_path_params_resize(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): client.cloud.load_balancers.with_raw_response.resize( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, flavor="lb1-2-4", ) @@ -492,16 +490,16 @@ class TestAsyncLoadBalancers: @parametrize async def test_method_create(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.create( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.create( - project_id=0, - region_id=0, + project_id=1, + region_id=7, flavor="lb1-1-2", floating_ip={ "existing_floating_id": "c64e5db1-5f1f-43ec-a8d9-5090df85b82d", @@ -532,8 +530,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> "max_retries_down": 3, "url_path": "/", }, - "listener_id": "listener_id", - "load_balancer_id": "bbb35f84-35cc-4b2f-84c2-a6a29bba68aa", "members": [ { "address": "192.168.1.101", @@ -542,7 +538,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> "backup": True, "instance_id": "a7e7e8d6-0bf7-4ac9-8170-831b47ee2ba9", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 2, }, @@ -553,7 +549,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> "backup": True, "instance_id": "169942e0-9b53-42df-95ef-1a8b6525c2bd", "monitor_address": "monitor_address", - "monitor_port": 0, + "monitor_port": 1, "subnet_id": "32283b0b-b560-4690-810c-f672cbb2e28d", "weight": 4, }, @@ -603,8 +599,8 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> @parametrize async def test_raw_response_create(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.with_raw_response.create( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -615,8 +611,8 @@ async def test_raw_response_create(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.with_streaming_response.create( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -629,18 +625,18 @@ async def test_streaming_response_create(self, async_client: AsyncGcore) -> None @parametrize async def test_method_update(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.update( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancer, load_balancer, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.update( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, logging={ "destination_region_id": 1, "enabled": True, @@ -656,9 +652,9 @@ async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> @parametrize async def test_raw_response_update(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.with_raw_response.update( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -669,9 +665,9 @@ async def test_raw_response_update(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_update(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.with_streaming_response.update( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -686,31 +682,31 @@ async def test_path_params_update(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): await async_client.cloud.load_balancers.with_raw_response.update( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) @parametrize async def test_method_list(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert_matches_type(AsyncOffsetPage[LoadBalancer], load_balancer, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, assigned_floating=True, - limit=0, + limit=1000, logging_enabled=True, - name="name", + name="lb_name", offset=0, - order_by="order_by", + order_by="name.asc", show_stats=True, - tag_key=["string"], + tag_key=["key1", "key2"], tag_key_value="tag_key_value", with_ddos=True, ) @@ -719,8 +715,8 @@ async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> No @parametrize async def test_raw_response_list(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.with_raw_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -731,8 +727,8 @@ async def test_raw_response_list(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.with_streaming_response.list( - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -745,18 +741,18 @@ async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: @parametrize async def test_method_delete(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.delete( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.with_raw_response.delete( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -767,9 +763,9 @@ async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.with_streaming_response.delete( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -784,25 +780,25 @@ async def test_path_params_delete(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): await async_client.cloud.load_balancers.with_raw_response.delete( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) @parametrize async def test_method_failover(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.failover( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @parametrize async def test_method_failover_with_all_params(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.failover( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, force=True, ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @@ -810,9 +806,9 @@ async def test_method_failover_with_all_params(self, async_client: AsyncGcore) - @parametrize async def test_raw_response_failover(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.with_raw_response.failover( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -823,9 +819,9 @@ async def test_raw_response_failover(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_failover(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.with_streaming_response.failover( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -840,25 +836,25 @@ async def test_path_params_failover(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): await async_client.cloud.load_balancers.with_raw_response.failover( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) @parametrize async def test_method_get(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert_matches_type(LoadBalancer, load_balancer, path=["response"]) @parametrize async def test_method_get_with_all_params(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, show_stats=True, with_ddos=True, ) @@ -867,9 +863,9 @@ async def test_method_get_with_all_params(self, async_client: AsyncGcore) -> Non @parametrize async def test_raw_response_get(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.with_raw_response.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) assert response.is_closed is True @@ -880,9 +876,9 @@ async def test_raw_response_get(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_get(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.with_streaming_response.get( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -897,16 +893,16 @@ async def test_path_params_get(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): await async_client.cloud.load_balancers.with_raw_response.get( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, ) @parametrize async def test_method_resize(self, async_client: AsyncGcore) -> None: load_balancer = await async_client.cloud.load_balancers.resize( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, flavor="lb1-2-4", ) assert_matches_type(TaskIDList, load_balancer, path=["response"]) @@ -914,9 +910,9 @@ async def test_method_resize(self, async_client: AsyncGcore) -> None: @parametrize async def test_raw_response_resize(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.with_raw_response.resize( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, flavor="lb1-2-4", ) @@ -928,9 +924,9 @@ async def test_raw_response_resize(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_resize(self, async_client: AsyncGcore) -> None: async with async_client.cloud.load_balancers.with_streaming_response.resize( - load_balancer_id="load_balancer_id", - project_id=0, - region_id=0, + load_balancer_id="ac307687-31a4-4a11-a949-6bea1b2878f5", + project_id=1, + region_id=7, flavor="lb1-2-4", ) as response: assert not response.is_closed @@ -946,7 +942,7 @@ async def test_path_params_resize(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `load_balancer_id` but received ''"): await async_client.cloud.load_balancers.with_raw_response.resize( load_balancer_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=7, flavor="lb1-2-4", ) diff --git a/tests/api_resources/cloud/test_security_groups.py b/tests/api_resources/cloud/test_security_groups.py index 41883f9e..0b842fd6 100644 --- a/tests/api_resources/cloud/test_security_groups.py +++ b/tests/api_resources/cloud/test_security_groups.py @@ -14,6 +14,8 @@ SecurityGroup, ) +# pyright: reportDeprecated=false + base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -22,46 +24,51 @@ class TestSecurityGroups: @parametrize def test_method_create(self, client: Gcore) -> None: - security_group = client.cloud.security_groups.create( - project_id=1, - region_id=1, - security_group={"name": "my_security_group"}, - ) + with pytest.warns(DeprecationWarning): + security_group = client.cloud.security_groups.create( + project_id=1, + region_id=1, + security_group={"name": "my_security_group"}, + ) + assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: Gcore) -> None: - security_group = client.cloud.security_groups.create( - project_id=1, - region_id=1, - security_group={ - "name": "my_security_group", - "description": "Some description", - "security_group_rules": [ - { - "description": "Some description", - "direction": "ingress", - "ethertype": "IPv4", - "port_range_max": 80, - "port_range_min": 80, - "protocol": "tcp", - "remote_group_id": "00000000-0000-4000-8000-000000000000", - "remote_ip_prefix": "10.0.0.0/8", - } - ], - "tags": {"my-tag": "my-tag-value"}, - }, - instances=["00000000-0000-4000-8000-000000000000"], - ) + with pytest.warns(DeprecationWarning): + security_group = client.cloud.security_groups.create( + project_id=1, + region_id=1, + security_group={ + "name": "my_security_group", + "description": "Some description", + "security_group_rules": [ + { + "direction": "ingress", + "description": "Some description", + "ethertype": "IPv4", + "port_range_max": 80, + "port_range_min": 80, + "protocol": "tcp", + "remote_group_id": "00000000-0000-4000-8000-000000000000", + "remote_ip_prefix": "10.0.0.0/8", + } + ], + "tags": {"my-tag": "my-tag-value"}, + }, + instances=["00000000-0000-4000-8000-000000000000"], + ) + assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize def test_raw_response_create(self, client: Gcore) -> None: - response = client.cloud.security_groups.with_raw_response.create( - project_id=1, - region_id=1, - security_group={"name": "my_security_group"}, - ) + with pytest.warns(DeprecationWarning): + response = client.cloud.security_groups.with_raw_response.create( + project_id=1, + region_id=1, + security_group={"name": "my_security_group"}, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -70,60 +77,66 @@ def test_raw_response_create(self, client: Gcore) -> None: @parametrize def test_streaming_response_create(self, client: Gcore) -> None: - with client.cloud.security_groups.with_streaming_response.create( - project_id=1, - region_id=1, - security_group={"name": "my_security_group"}, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - security_group = response.parse() - assert_matches_type(SecurityGroup, security_group, path=["response"]) + with pytest.warns(DeprecationWarning): + with client.cloud.security_groups.with_streaming_response.create( + project_id=1, + region_id=1, + security_group={"name": "my_security_group"}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + security_group = response.parse() + assert_matches_type(SecurityGroup, security_group, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_method_update(self, client: Gcore) -> None: - security_group = client.cloud.security_groups.update( - group_id="group_id", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + security_group = client.cloud.security_groups.update( + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + ) + assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: Gcore) -> None: - security_group = client.cloud.security_groups.update( - group_id="group_id", - project_id=0, - region_id=0, - changed_rules=[ - { - "action": "delete", - "description": "Some description", - "direction": "egress", - "ethertype": "IPv4", - "port_range_max": 80, - "port_range_min": 80, - "protocol": "tcp", - "remote_group_id": "00000000-0000-4000-8000-000000000000", - "remote_ip_prefix": "10.0.0.0/8", - "security_group_rule_id": "00000000-0000-4000-8000-000000000000", - } - ], - name="some_name", - tags={"foo": "my-tag-value"}, - ) + with pytest.warns(DeprecationWarning): + security_group = client.cloud.security_groups.update( + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + changed_rules=[ + { + "action": "delete", + "description": "Some description", + "direction": "egress", + "ethertype": "IPv4", + "port_range_max": 80, + "port_range_min": 80, + "protocol": "tcp", + "remote_group_id": "00000000-0000-4000-8000-000000000000", + "remote_ip_prefix": "10.0.0.0/8", + "security_group_rule_id": "00000000-0000-4000-8000-000000000000", + } + ], + name="some_name", + tags={"foo": "my-tag-value"}, + ) + assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize def test_raw_response_update(self, client: Gcore) -> None: - response = client.cloud.security_groups.with_raw_response.update( - group_id="group_id", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + response = client.cloud.security_groups.with_raw_response.update( + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -132,27 +145,29 @@ def test_raw_response_update(self, client: Gcore) -> None: @parametrize def test_streaming_response_update(self, client: Gcore) -> None: - with client.cloud.security_groups.with_streaming_response.update( - group_id="group_id", - project_id=0, - region_id=0, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - security_group = response.parse() - assert_matches_type(SecurityGroup, security_group, path=["response"]) + with pytest.warns(DeprecationWarning): + with client.cloud.security_groups.with_streaming_response.update( + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + security_group = response.parse() + assert_matches_type(SecurityGroup, security_group, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: Gcore) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): - client.cloud.security_groups.with_raw_response.update( - group_id="", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): + client.cloud.security_groups.with_raw_response.update( + group_id="", + project_id=1, + region_id=1, + ) @parametrize def test_method_list(self, client: Gcore) -> None: @@ -168,6 +183,7 @@ def test_method_list_with_all_params(self, client: Gcore) -> None: project_id=1, region_id=1, limit=10, + name="my_security_group", offset=0, tag_key=["key1", "key2"], tag_key_value="tag_key_value", @@ -203,18 +219,18 @@ def test_streaming_response_list(self, client: Gcore) -> None: @parametrize def test_method_delete(self, client: Gcore) -> None: security_group = client.cloud.security_groups.delete( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert security_group is None @parametrize def test_raw_response_delete(self, client: Gcore) -> None: response = client.cloud.security_groups.with_raw_response.delete( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert response.is_closed is True @@ -225,9 +241,9 @@ def test_raw_response_delete(self, client: Gcore) -> None: @parametrize def test_streaming_response_delete(self, client: Gcore) -> None: with client.cloud.security_groups.with_streaming_response.delete( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -242,16 +258,16 @@ def test_path_params_delete(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): client.cloud.security_groups.with_raw_response.delete( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, ) @parametrize def test_method_copy(self, client: Gcore) -> None: security_group = client.cloud.security_groups.copy( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, name="some_name", ) assert_matches_type(SecurityGroup, security_group, path=["response"]) @@ -259,9 +275,9 @@ def test_method_copy(self, client: Gcore) -> None: @parametrize def test_raw_response_copy(self, client: Gcore) -> None: response = client.cloud.security_groups.with_raw_response.copy( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, name="some_name", ) @@ -273,9 +289,9 @@ def test_raw_response_copy(self, client: Gcore) -> None: @parametrize def test_streaming_response_copy(self, client: Gcore) -> None: with client.cloud.security_groups.with_streaming_response.copy( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, name="some_name", ) as response: assert not response.is_closed @@ -291,26 +307,26 @@ def test_path_params_copy(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): client.cloud.security_groups.with_raw_response.copy( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, name="some_name", ) @parametrize def test_method_get(self, client: Gcore) -> None: security_group = client.cloud.security_groups.get( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize def test_raw_response_get(self, client: Gcore) -> None: response = client.cloud.security_groups.with_raw_response.get( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert response.is_closed is True @@ -321,9 +337,9 @@ def test_raw_response_get(self, client: Gcore) -> None: @parametrize def test_streaming_response_get(self, client: Gcore) -> None: with client.cloud.security_groups.with_streaming_response.get( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -338,25 +354,25 @@ def test_path_params_get(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): client.cloud.security_groups.with_raw_response.get( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, ) @parametrize def test_method_revert_to_default(self, client: Gcore) -> None: security_group = client.cloud.security_groups.revert_to_default( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize def test_raw_response_revert_to_default(self, client: Gcore) -> None: response = client.cloud.security_groups.with_raw_response.revert_to_default( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert response.is_closed is True @@ -367,9 +383,9 @@ def test_raw_response_revert_to_default(self, client: Gcore) -> None: @parametrize def test_streaming_response_revert_to_default(self, client: Gcore) -> None: with client.cloud.security_groups.with_streaming_response.revert_to_default( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -384,8 +400,8 @@ def test_path_params_revert_to_default(self, client: Gcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): client.cloud.security_groups.with_raw_response.revert_to_default( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, ) @@ -396,46 +412,51 @@ class TestAsyncSecurityGroups: @parametrize async def test_method_create(self, async_client: AsyncGcore) -> None: - security_group = await async_client.cloud.security_groups.create( - project_id=1, - region_id=1, - security_group={"name": "my_security_group"}, - ) + with pytest.warns(DeprecationWarning): + security_group = await async_client.cloud.security_groups.create( + project_id=1, + region_id=1, + security_group={"name": "my_security_group"}, + ) + assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> None: - security_group = await async_client.cloud.security_groups.create( - project_id=1, - region_id=1, - security_group={ - "name": "my_security_group", - "description": "Some description", - "security_group_rules": [ - { - "description": "Some description", - "direction": "ingress", - "ethertype": "IPv4", - "port_range_max": 80, - "port_range_min": 80, - "protocol": "tcp", - "remote_group_id": "00000000-0000-4000-8000-000000000000", - "remote_ip_prefix": "10.0.0.0/8", - } - ], - "tags": {"my-tag": "my-tag-value"}, - }, - instances=["00000000-0000-4000-8000-000000000000"], - ) + with pytest.warns(DeprecationWarning): + security_group = await async_client.cloud.security_groups.create( + project_id=1, + region_id=1, + security_group={ + "name": "my_security_group", + "description": "Some description", + "security_group_rules": [ + { + "direction": "ingress", + "description": "Some description", + "ethertype": "IPv4", + "port_range_max": 80, + "port_range_min": 80, + "protocol": "tcp", + "remote_group_id": "00000000-0000-4000-8000-000000000000", + "remote_ip_prefix": "10.0.0.0/8", + } + ], + "tags": {"my-tag": "my-tag-value"}, + }, + instances=["00000000-0000-4000-8000-000000000000"], + ) + assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncGcore) -> None: - response = await async_client.cloud.security_groups.with_raw_response.create( - project_id=1, - region_id=1, - security_group={"name": "my_security_group"}, - ) + with pytest.warns(DeprecationWarning): + response = await async_client.cloud.security_groups.with_raw_response.create( + project_id=1, + region_id=1, + security_group={"name": "my_security_group"}, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -444,60 +465,66 @@ async def test_raw_response_create(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncGcore) -> None: - async with async_client.cloud.security_groups.with_streaming_response.create( - project_id=1, - region_id=1, - security_group={"name": "my_security_group"}, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - security_group = await response.parse() - assert_matches_type(SecurityGroup, security_group, path=["response"]) + with pytest.warns(DeprecationWarning): + async with async_client.cloud.security_groups.with_streaming_response.create( + project_id=1, + region_id=1, + security_group={"name": "my_security_group"}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + security_group = await response.parse() + assert_matches_type(SecurityGroup, security_group, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_method_update(self, async_client: AsyncGcore) -> None: - security_group = await async_client.cloud.security_groups.update( - group_id="group_id", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + security_group = await async_client.cloud.security_groups.update( + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + ) + assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> None: - security_group = await async_client.cloud.security_groups.update( - group_id="group_id", - project_id=0, - region_id=0, - changed_rules=[ - { - "action": "delete", - "description": "Some description", - "direction": "egress", - "ethertype": "IPv4", - "port_range_max": 80, - "port_range_min": 80, - "protocol": "tcp", - "remote_group_id": "00000000-0000-4000-8000-000000000000", - "remote_ip_prefix": "10.0.0.0/8", - "security_group_rule_id": "00000000-0000-4000-8000-000000000000", - } - ], - name="some_name", - tags={"foo": "my-tag-value"}, - ) + with pytest.warns(DeprecationWarning): + security_group = await async_client.cloud.security_groups.update( + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + changed_rules=[ + { + "action": "delete", + "description": "Some description", + "direction": "egress", + "ethertype": "IPv4", + "port_range_max": 80, + "port_range_min": 80, + "protocol": "tcp", + "remote_group_id": "00000000-0000-4000-8000-000000000000", + "remote_ip_prefix": "10.0.0.0/8", + "security_group_rule_id": "00000000-0000-4000-8000-000000000000", + } + ], + name="some_name", + tags={"foo": "my-tag-value"}, + ) + assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize async def test_raw_response_update(self, async_client: AsyncGcore) -> None: - response = await async_client.cloud.security_groups.with_raw_response.update( - group_id="group_id", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + response = await async_client.cloud.security_groups.with_raw_response.update( + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -506,27 +533,29 @@ async def test_raw_response_update(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_update(self, async_client: AsyncGcore) -> None: - async with async_client.cloud.security_groups.with_streaming_response.update( - group_id="group_id", - project_id=0, - region_id=0, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - security_group = await response.parse() - assert_matches_type(SecurityGroup, security_group, path=["response"]) + with pytest.warns(DeprecationWarning): + async with async_client.cloud.security_groups.with_streaming_response.update( + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + security_group = await response.parse() + assert_matches_type(SecurityGroup, security_group, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncGcore) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): - await async_client.cloud.security_groups.with_raw_response.update( - group_id="", - project_id=0, - region_id=0, - ) + with pytest.warns(DeprecationWarning): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): + await async_client.cloud.security_groups.with_raw_response.update( + group_id="", + project_id=1, + region_id=1, + ) @parametrize async def test_method_list(self, async_client: AsyncGcore) -> None: @@ -542,6 +571,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> No project_id=1, region_id=1, limit=10, + name="my_security_group", offset=0, tag_key=["key1", "key2"], tag_key_value="tag_key_value", @@ -577,18 +607,18 @@ async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: @parametrize async def test_method_delete(self, async_client: AsyncGcore) -> None: security_group = await async_client.cloud.security_groups.delete( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert security_group is None @parametrize async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.security_groups.with_raw_response.delete( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert response.is_closed is True @@ -599,9 +629,9 @@ async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncGcore) -> None: async with async_client.cloud.security_groups.with_streaming_response.delete( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -616,16 +646,16 @@ async def test_path_params_delete(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): await async_client.cloud.security_groups.with_raw_response.delete( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, ) @parametrize async def test_method_copy(self, async_client: AsyncGcore) -> None: security_group = await async_client.cloud.security_groups.copy( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, name="some_name", ) assert_matches_type(SecurityGroup, security_group, path=["response"]) @@ -633,9 +663,9 @@ async def test_method_copy(self, async_client: AsyncGcore) -> None: @parametrize async def test_raw_response_copy(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.security_groups.with_raw_response.copy( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, name="some_name", ) @@ -647,9 +677,9 @@ async def test_raw_response_copy(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_copy(self, async_client: AsyncGcore) -> None: async with async_client.cloud.security_groups.with_streaming_response.copy( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, name="some_name", ) as response: assert not response.is_closed @@ -665,26 +695,26 @@ async def test_path_params_copy(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): await async_client.cloud.security_groups.with_raw_response.copy( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, name="some_name", ) @parametrize async def test_method_get(self, async_client: AsyncGcore) -> None: security_group = await async_client.cloud.security_groups.get( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize async def test_raw_response_get(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.security_groups.with_raw_response.get( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert response.is_closed is True @@ -695,9 +725,9 @@ async def test_raw_response_get(self, async_client: AsyncGcore) -> None: @parametrize async def test_streaming_response_get(self, async_client: AsyncGcore) -> None: async with async_client.cloud.security_groups.with_streaming_response.get( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -712,25 +742,25 @@ async def test_path_params_get(self, async_client: AsyncGcore) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): await async_client.cloud.security_groups.with_raw_response.get( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, ) @parametrize async def test_method_revert_to_default(self, async_client: AsyncGcore) -> None: security_group = await async_client.cloud.security_groups.revert_to_default( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert_matches_type(SecurityGroup, security_group, path=["response"]) @parametrize async def test_raw_response_revert_to_default(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.security_groups.with_raw_response.revert_to_default( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) assert response.is_closed is True @@ -741,9 +771,9 @@ async def test_raw_response_revert_to_default(self, async_client: AsyncGcore) -> @parametrize async def test_streaming_response_revert_to_default(self, async_client: AsyncGcore) -> None: async with async_client.cloud.security_groups.with_streaming_response.revert_to_default( - group_id="group_id", - project_id=0, - region_id=0, + group_id="024a29e9-b4b7-4c91-9a46-505be123d9f8", + project_id=1, + region_id=1, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -758,6 +788,6 @@ async def test_path_params_revert_to_default(self, async_client: AsyncGcore) -> with pytest.raises(ValueError, match=r"Expected a non-empty value for `group_id` but received ''"): await async_client.cloud.security_groups.with_raw_response.revert_to_default( group_id="", - project_id=0, - region_id=0, + project_id=1, + region_id=1, ) diff --git a/tests/api_resources/cloud/test_volume_snapshots.py b/tests/api_resources/cloud/test_volume_snapshots.py new file mode 100644 index 00000000..4b2d7bfd --- /dev/null +++ b/tests/api_resources/cloud/test_volume_snapshots.py @@ -0,0 +1,429 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from gcore import Gcore, AsyncGcore +from tests.utils import assert_matches_type +from gcore.types.cloud import ( + Snapshot, + TaskIDList, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestVolumeSnapshots: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Gcore) -> None: + volume_snapshot = client.cloud.volume_snapshots.create( + project_id=0, + region_id=0, + name="my-snapshot", + volume_id="67baa7d1-08ea-4fc5-bef2-6b2465b7d227", + ) + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Gcore) -> None: + volume_snapshot = client.cloud.volume_snapshots.create( + project_id=0, + region_id=0, + name="my-snapshot", + volume_id="67baa7d1-08ea-4fc5-bef2-6b2465b7d227", + description="Snapshot description", + tags={"my-tag": "my-tag-value"}, + ) + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Gcore) -> None: + response = client.cloud.volume_snapshots.with_raw_response.create( + project_id=0, + region_id=0, + name="my-snapshot", + volume_id="67baa7d1-08ea-4fc5-bef2-6b2465b7d227", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + volume_snapshot = response.parse() + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Gcore) -> None: + with client.cloud.volume_snapshots.with_streaming_response.create( + project_id=0, + region_id=0, + name="my-snapshot", + volume_id="67baa7d1-08ea-4fc5-bef2-6b2465b7d227", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + volume_snapshot = response.parse() + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_update(self, client: Gcore) -> None: + volume_snapshot = client.cloud.volume_snapshots.update( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + def test_method_update_with_all_params(self, client: Gcore) -> None: + volume_snapshot = client.cloud.volume_snapshots.update( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + name="my-backup-snapshot", + tags={"foo": "my-tag-value"}, + ) + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + def test_raw_response_update(self, client: Gcore) -> None: + response = client.cloud.volume_snapshots.with_raw_response.update( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + volume_snapshot = response.parse() + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + def test_streaming_response_update(self, client: Gcore) -> None: + with client.cloud.volume_snapshots.with_streaming_response.update( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + volume_snapshot = response.parse() + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_update(self, client: Gcore) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `snapshot_id` but received ''"): + client.cloud.volume_snapshots.with_raw_response.update( + snapshot_id="", + project_id=1, + region_id=1, + ) + + @parametrize + def test_method_delete(self, client: Gcore) -> None: + volume_snapshot = client.cloud.volume_snapshots.delete( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + def test_raw_response_delete(self, client: Gcore) -> None: + response = client.cloud.volume_snapshots.with_raw_response.delete( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + volume_snapshot = response.parse() + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + def test_streaming_response_delete(self, client: Gcore) -> None: + with client.cloud.volume_snapshots.with_streaming_response.delete( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + volume_snapshot = response.parse() + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: Gcore) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `snapshot_id` but received ''"): + client.cloud.volume_snapshots.with_raw_response.delete( + snapshot_id="", + project_id=1, + region_id=1, + ) + + @parametrize + def test_method_get(self, client: Gcore) -> None: + volume_snapshot = client.cloud.volume_snapshots.get( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Gcore) -> None: + response = client.cloud.volume_snapshots.with_raw_response.get( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + volume_snapshot = response.parse() + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Gcore) -> None: + with client.cloud.volume_snapshots.with_streaming_response.get( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + volume_snapshot = response.parse() + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get(self, client: Gcore) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `snapshot_id` but received ''"): + client.cloud.volume_snapshots.with_raw_response.get( + snapshot_id="", + project_id=1, + region_id=1, + ) + + +class TestAsyncVolumeSnapshots: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncGcore) -> None: + volume_snapshot = await async_client.cloud.volume_snapshots.create( + project_id=0, + region_id=0, + name="my-snapshot", + volume_id="67baa7d1-08ea-4fc5-bef2-6b2465b7d227", + ) + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> None: + volume_snapshot = await async_client.cloud.volume_snapshots.create( + project_id=0, + region_id=0, + name="my-snapshot", + volume_id="67baa7d1-08ea-4fc5-bef2-6b2465b7d227", + description="Snapshot description", + tags={"my-tag": "my-tag-value"}, + ) + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.volume_snapshots.with_raw_response.create( + project_id=0, + region_id=0, + name="my-snapshot", + volume_id="67baa7d1-08ea-4fc5-bef2-6b2465b7d227", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + volume_snapshot = await response.parse() + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.volume_snapshots.with_streaming_response.create( + project_id=0, + region_id=0, + name="my-snapshot", + volume_id="67baa7d1-08ea-4fc5-bef2-6b2465b7d227", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + volume_snapshot = await response.parse() + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_update(self, async_client: AsyncGcore) -> None: + volume_snapshot = await async_client.cloud.volume_snapshots.update( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> None: + volume_snapshot = await async_client.cloud.volume_snapshots.update( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + name="my-backup-snapshot", + tags={"foo": "my-tag-value"}, + ) + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + async def test_raw_response_update(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.volume_snapshots.with_raw_response.update( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + volume_snapshot = await response.parse() + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + async def test_streaming_response_update(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.volume_snapshots.with_streaming_response.update( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + volume_snapshot = await response.parse() + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_update(self, async_client: AsyncGcore) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `snapshot_id` but received ''"): + await async_client.cloud.volume_snapshots.with_raw_response.update( + snapshot_id="", + project_id=1, + region_id=1, + ) + + @parametrize + async def test_method_delete(self, async_client: AsyncGcore) -> None: + volume_snapshot = await async_client.cloud.volume_snapshots.delete( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.volume_snapshots.with_raw_response.delete( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + volume_snapshot = await response.parse() + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.volume_snapshots.with_streaming_response.delete( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + volume_snapshot = await response.parse() + assert_matches_type(TaskIDList, volume_snapshot, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncGcore) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `snapshot_id` but received ''"): + await async_client.cloud.volume_snapshots.with_raw_response.delete( + snapshot_id="", + project_id=1, + region_id=1, + ) + + @parametrize + async def test_method_get(self, async_client: AsyncGcore) -> None: + volume_snapshot = await async_client.cloud.volume_snapshots.get( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.volume_snapshots.with_raw_response.get( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + volume_snapshot = await response.parse() + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.volume_snapshots.with_streaming_response.get( + snapshot_id="726ecfcc-7fd0-4e30-a86e-7892524aa483", + project_id=1, + region_id=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + volume_snapshot = await response.parse() + assert_matches_type(Snapshot, volume_snapshot, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get(self, async_client: AsyncGcore) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `snapshot_id` but received ''"): + await async_client.cloud.volume_snapshots.with_raw_response.get( + snapshot_id="", + project_id=1, + region_id=1, + ) diff --git a/tests/api_resources/iam/test_users.py b/tests/api_resources/iam/test_users.py index 6c3635a9..72116b06 100644 --- a/tests/api_resources/iam/test_users.py +++ b/tests/api_resources/iam/test_users.py @@ -25,24 +25,10 @@ class TestUsers: @parametrize def test_method_update(self, client: Gcore) -> None: - user = client.iam.users.update( - user_id=0, - ) - assert_matches_type(UserUpdated, user, path=["response"]) - - @parametrize - def test_method_update_with_all_params(self, client: Gcore) -> None: user = client.iam.users.update( user_id=0, auth_types=["password"], - company="company", email="dev@stainless.com", - groups=[ - { - "id": 1, - "name": "Administrators", - } - ], lang="de", name="name", phone="phone", @@ -53,6 +39,11 @@ def test_method_update_with_all_params(self, client: Gcore) -> None: def test_raw_response_update(self, client: Gcore) -> None: response = client.iam.users.with_raw_response.update( user_id=0, + auth_types=["password"], + email="dev@stainless.com", + lang="de", + name="name", + phone="phone", ) assert response.is_closed is True @@ -64,6 +55,11 @@ def test_raw_response_update(self, client: Gcore) -> None: def test_streaming_response_update(self, client: Gcore) -> None: with client.iam.users.with_streaming_response.update( user_id=0, + auth_types=["password"], + email="dev@stainless.com", + lang="de", + name="name", + phone="phone", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -230,24 +226,10 @@ class TestAsyncUsers: @parametrize async def test_method_update(self, async_client: AsyncGcore) -> None: - user = await async_client.iam.users.update( - user_id=0, - ) - assert_matches_type(UserUpdated, user, path=["response"]) - - @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> None: user = await async_client.iam.users.update( user_id=0, auth_types=["password"], - company="company", email="dev@stainless.com", - groups=[ - { - "id": 1, - "name": "Administrators", - } - ], lang="de", name="name", phone="phone", @@ -258,6 +240,11 @@ async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> async def test_raw_response_update(self, async_client: AsyncGcore) -> None: response = await async_client.iam.users.with_raw_response.update( user_id=0, + auth_types=["password"], + email="dev@stainless.com", + lang="de", + name="name", + phone="phone", ) assert response.is_closed is True @@ -269,6 +256,11 @@ async def test_raw_response_update(self, async_client: AsyncGcore) -> None: async def test_streaming_response_update(self, async_client: AsyncGcore) -> None: async with async_client.iam.users.with_streaming_response.update( user_id=0, + auth_types=["password"], + email="dev@stainless.com", + lang="de", + name="name", + phone="phone", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/test_client.py b/tests/test_client.py index 65c6446b..67601f11 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -8,10 +8,11 @@ import json import asyncio import inspect +import dataclasses import tracemalloc -from typing import Any, Union, cast +from typing import Any, Union, TypeVar, Callable, Iterable, Iterator, Optional, Coroutine, cast from unittest import mock -from typing_extensions import Literal +from typing_extensions import Literal, AsyncIterator, override import httpx import pytest @@ -36,6 +37,7 @@ from .utils import update_env +T = TypeVar("T") base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My API Key" @@ -50,6 +52,57 @@ def _low_retry_timeout(*_args: Any, **_kwargs: Any) -> float: return 0.1 +def mirror_request_content(request: httpx.Request) -> httpx.Response: + return httpx.Response(200, content=request.content) + + +# note: we can't use the httpx.MockTransport class as it consumes the request +# body itself, which means we can't test that the body is read lazily +class MockTransport(httpx.BaseTransport, httpx.AsyncBaseTransport): + def __init__( + self, + handler: Callable[[httpx.Request], httpx.Response] + | Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]], + ) -> None: + self.handler = handler + + @override + def handle_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert not inspect.iscoroutinefunction(self.handler), "handler must not be a coroutine function" + assert inspect.isfunction(self.handler), "handler must be a function" + return self.handler(request) + + @override + async def handle_async_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert inspect.iscoroutinefunction(self.handler), "handler must be a coroutine function" + return await self.handler(request) + + +@dataclasses.dataclass +class Counter: + value: int = 0 + + +def _make_sync_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> Iterator[T]: + for item in iterable: + if counter: + counter.value += 1 + yield item + + +async def _make_async_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> AsyncIterator[T]: + for item in iterable: + if counter: + counter.value += 1 + yield item + + def _get_open_connections(client: Gcore | AsyncGcore) -> int: transport = client._client._transport assert isinstance(transport, httpx.HTTPTransport) or isinstance(transport, httpx.AsyncHTTPTransport) @@ -518,6 +571,70 @@ def test_multipart_repeating_array(self, client: Gcore) -> None: b"", ] + @pytest.mark.respx(base_url=base_url) + def test_binary_content_upload(self, respx_mock: MockRouter, client: Gcore) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + response = client.post( + "/upload", + content=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + + def test_binary_content_upload_with_iterator(self) -> None: + file_content = b"Hello, this is a test file." + counter = Counter() + iterator = _make_sync_iterator([file_content], counter=counter) + + def mock_handler(request: httpx.Request) -> httpx.Response: + assert counter.value == 0, "the request body should not have been read" + return httpx.Response(200, content=request.read()) + + with Gcore( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.Client(transport=MockTransport(handler=mock_handler)), + ) as client: + response = client.post( + "/upload", + content=iterator, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 + + @pytest.mark.respx(base_url=base_url) + def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRouter, client: Gcore) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + with pytest.deprecated_call( + match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." + ): + response = client.post( + "/upload", + body=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + @pytest.mark.respx(base_url=base_url) def test_basic_union_response(self, respx_mock: MockRouter, client: Gcore) -> None: class Model1(BaseModel): @@ -1357,6 +1474,72 @@ def test_multipart_repeating_array(self, async_client: AsyncGcore) -> None: b"", ] + @pytest.mark.respx(base_url=base_url) + async def test_binary_content_upload(self, respx_mock: MockRouter, async_client: AsyncGcore) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + response = await async_client.post( + "/upload", + content=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + + async def test_binary_content_upload_with_asynciterator(self) -> None: + file_content = b"Hello, this is a test file." + counter = Counter() + iterator = _make_async_iterator([file_content], counter=counter) + + async def mock_handler(request: httpx.Request) -> httpx.Response: + assert counter.value == 0, "the request body should not have been read" + return httpx.Response(200, content=await request.aread()) + + async with AsyncGcore( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.AsyncClient(transport=MockTransport(handler=mock_handler)), + ) as client: + response = await client.post( + "/upload", + content=iterator, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 + + @pytest.mark.respx(base_url=base_url) + async def test_binary_content_upload_with_body_is_deprecated( + self, respx_mock: MockRouter, async_client: AsyncGcore + ) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + with pytest.deprecated_call( + match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." + ): + response = await async_client.post( + "/upload", + body=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + @pytest.mark.respx(base_url=base_url) async def test_basic_union_response(self, respx_mock: MockRouter, async_client: AsyncGcore) -> None: class Model1(BaseModel):