diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6db19b95..4ad3fef3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.17.0" + ".": "0.18.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index fd2d5539..bb221715 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 609 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-56132999d4ac773438df4415a4bb56c8cf7f067c3c340d80424bf968074f66dc.yml -openapi_spec_hash: c33cea043ddbfe20778e0774313fa7e6 -config_hash: bb4a27712c30f7a2b52e1f3b31766f24 +configured_endpoints: 618 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-1089f2c131ebee7df82e158c4210c07f019b47549d84fe6ea7f022117c83a008.yml +openapi_spec_hash: 9758acbadc1ee1bc0d826d4657e1ad4a +config_hash: 79098512b2ff15053f2813524c207add diff --git a/CHANGELOG.md b/CHANGELOG.md index 3433ecf3..f73fd479 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## 0.18.0 (2025-11-04) + +Full Changelog: [v0.17.0...v0.18.0](https://github.com/G-Core/gcore-python/compare/v0.17.0...v0.18.0) + +### Features + +* **api:** aggregated API specs update ([c69f622](https://github.com/G-Core/gcore-python/commit/c69f622f4d085d5c93978edbf4deb2ecbe4279d6)) +* **api:** aggregated API specs update ([e008291](https://github.com/G-Core/gcore-python/commit/e008291499f90553d12deffbcef5c4a9b6752f61)) +* **api:** aggregated API specs update ([7e17f98](https://github.com/G-Core/gcore-python/commit/7e17f98624fecfb8d1ad5a53a001dcd20ca15214)) +* **api:** aggregated API specs update ([01c7469](https://github.com/G-Core/gcore-python/commit/01c746977c89d813e54b97c87513960a5cba42c3)) +* **api:** aggregated API specs update ([3ef8586](https://github.com/G-Core/gcore-python/commit/3ef8586481df9533a0627310458bb72b9b458d2f)) +* **api:** aggregated API specs update ([af54c88](https://github.com/G-Core/gcore-python/commit/af54c886222ea41e6ef57d8683fbb64e2b688a15)) +* **api:** aggregated API specs update ([4e62953](https://github.com/G-Core/gcore-python/commit/4e629534e07db80d93c46e5ccc5e3d2ba48d9eb4)) +* **api:** aggregated API specs update ([18614cb](https://github.com/G-Core/gcore-python/commit/18614cb786fd3ea9020cee18c2a23c4c81f116f3)) +* **api:** aggregated API specs update ([926c0dd](https://github.com/G-Core/gcore-python/commit/926c0ddfcef420ba47eca7b399ea43462a18371a)) +* **cloud:** add support for postgres ([2802edf](https://github.com/G-Core/gcore-python/commit/2802edf3bbac88b644ba8ff4d5b83dc0606e4b48)) + + +### Bug Fixes + +* **client:** close streams without requiring full consumption ([cd7152c](https://github.com/G-Core/gcore-python/commit/cd7152cd959a9984e5c60edb41d16fa2db342012)) +* **cloud:** members not optional in lb pools create_and_poll ([27bc07a](https://github.com/G-Core/gcore-python/commit/27bc07acab63505e03f4a5b51e21544fe84877ec)) + + +### Chores + +* **cloud:** add *_and_poll() to *WithRawResponse and *WithStreaming ([d8886ce](https://github.com/G-Core/gcore-python/commit/d8886ce4abeadd3d260c3f533e72b778d521482c)) +* **internal/tests:** avoid race condition with implicit client cleanup ([67e4c77](https://github.com/G-Core/gcore-python/commit/67e4c77936fca0b2192b931ec71003dd62383c81)) +* **internal:** grammar fix (it's -> its) ([9bf8a18](https://github.com/G-Core/gcore-python/commit/9bf8a18f42a2122f43d9084ff3287e4d1aa7dd95)) + ## 0.17.0 (2025-10-21) Full Changelog: [v0.16.0...v0.17.0](https://github.com/G-Core/gcore-python/compare/v0.16.0...v0.17.0) diff --git a/README.md b/README.md index 33b1e15e..bcba1e06 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ client = Gcore( ) project = client.cloud.projects.create( - name="New Project", + name="my-project", ) print(project.id) ``` @@ -60,7 +60,7 @@ client = AsyncGcore( async def main() -> None: project = await client.cloud.projects.create( - name="New Project", + name="my-project", ) print(project.id) @@ -95,7 +95,7 @@ async def main() -> None: http_client=DefaultAioHttpClient(), ) as client: project = await client.cloud.projects.create( - name="New Project", + name="my-project", ) print(project.id) @@ -236,7 +236,7 @@ client = Gcore() try: client.cloud.projects.create( - name="New Project", + name="my-project", ) except gcore.APIConnectionError as e: print("The server could not be reached") @@ -280,7 +280,7 @@ client = Gcore( # Or, configure per-request: client.with_options(max_retries=5).cloud.projects.create( - name="New Project", + name="my-project", ) ``` @@ -305,7 +305,7 @@ client = Gcore( # Override per-request: client.with_options(timeout=5.0).cloud.projects.create( - name="New Project", + name="my-project", ) ``` @@ -348,7 +348,7 @@ from gcore import Gcore client = Gcore() response = client.cloud.projects.with_raw_response.create( - name="New Project", + name="my-project", ) print(response.headers.get('X-My-Header')) @@ -368,7 +368,7 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.cloud.projects.with_streaming_response.create( - name="New Project", + name="my-project", ) as response: print(response.headers.get("X-My-Header")) diff --git a/api.md b/api.md index 01ab7916..180b482b 100644 --- a/api.md +++ b/api.md @@ -250,7 +250,7 @@ Methods: - client.cloud.load_balancers.listeners.create(\*, project_id, region_id, \*\*params) -> TaskIDList - client.cloud.load_balancers.listeners.update(listener_id, \*, project_id, region_id, \*\*params) -> TaskIDList - client.cloud.load_balancers.listeners.list(\*, project_id, region_id, \*\*params) -> LoadBalancerListenerList -- client.cloud.load_balancers.listeners.delete(listener_id, \*, project_id, region_id) -> TaskIDList +- client.cloud.load_balancers.listeners.delete(listener_id, \*, project_id, region_id, \*\*params) -> TaskIDList - client.cloud.load_balancers.listeners.get(listener_id, \*, project_id, region_id, \*\*params) -> LoadBalancerListenerDetail ### Pools @@ -1006,6 +1006,63 @@ Methods: - client.cloud.usage_reports.get(\*\*params) -> UsageReport +## Databases + +### Postgres + +#### Clusters + +Types: + +```python +from gcore.types.cloud.databases.postgres import PostgresCluster, PostgresClusterShort +``` + +Methods: + +- client.cloud.databases.postgres.clusters.create(\*, project_id, region_id, \*\*params) -> TaskIDList +- client.cloud.databases.postgres.clusters.update(cluster_name, \*, project_id, region_id, \*\*params) -> TaskIDList +- client.cloud.databases.postgres.clusters.list(\*, project_id, region_id, \*\*params) -> SyncOffsetPage[PostgresClusterShort] +- client.cloud.databases.postgres.clusters.delete(cluster_name, \*, project_id, region_id) -> TaskIDList +- client.cloud.databases.postgres.clusters.get(cluster_name, \*, project_id, region_id) -> PostgresCluster + +##### UserCredentials + +Types: + +```python +from gcore.types.cloud.databases.postgres.clusters import PostgresUserCredentials +``` + +Methods: + +- client.cloud.databases.postgres.clusters.user_credentials.get(username, \*, project_id, region_id, cluster_name) -> PostgresUserCredentials +- client.cloud.databases.postgres.clusters.user_credentials.regenerate(username, \*, project_id, region_id, cluster_name) -> PostgresUserCredentials + +#### Configurations + +Types: + +```python +from gcore.types.cloud.databases.postgres import PostgresConfiguration +``` + +Methods: + +- client.cloud.databases.postgres.configurations.get(\*, project_id, region_id) -> PostgresConfiguration + +#### CustomConfigurations + +Types: + +```python +from gcore.types.cloud.databases.postgres import PgConfValidation +``` + +Methods: + +- client.cloud.databases.postgres.custom_configurations.validate(\*, project_id, region_id, \*\*params) -> PgConfValidation + # Waap Types: @@ -2383,5 +2440,5 @@ from gcore.types.cdn import PublicIPList, PublicNetworkList Methods: -- client.cdn.ip_ranges.list() -> PublicNetworkList -- client.cdn.ip_ranges.list_ips() -> PublicIPList +- client.cdn.ip_ranges.list(\*\*params) -> PublicNetworkList +- client.cdn.ip_ranges.list_ips(\*\*params) -> PublicIPList diff --git a/pyproject.toml b/pyproject.toml index 2b3a98de..9de98340 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "gcore" -version = "0.17.0" +version = "0.18.0" description = "The official Python library for the gcore API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/gcore/_streaming.py b/src/gcore/_streaming.py index bf3046cf..16c106ae 100644 --- a/src/gcore/_streaming.py +++ b/src/gcore/_streaming.py @@ -57,9 +57,8 @@ def __stream__(self) -> Iterator[_T]: for sse in iterator: yield process_data(data=sse.json(), cast_to=cast_to, response=response) - # Ensure the entire stream is consumed - for _sse in iterator: - ... + # As we might not fully consume the response stream, we need to close it explicitly + response.close() def __enter__(self) -> Self: return self @@ -121,9 +120,8 @@ async def __stream__(self) -> AsyncIterator[_T]: async for sse in iterator: yield process_data(data=sse.json(), cast_to=cast_to, response=response) - # Ensure the entire stream is consumed - async for _sse in iterator: - ... + # As we might not fully consume the response stream, we need to close it explicitly + await response.aclose() async def __aenter__(self) -> Self: return self diff --git a/src/gcore/_utils/_utils.py b/src/gcore/_utils/_utils.py index 50d59269..eec7f4a1 100644 --- a/src/gcore/_utils/_utils.py +++ b/src/gcore/_utils/_utils.py @@ -133,7 +133,7 @@ def is_given(obj: _T | NotGiven | Omit) -> TypeGuard[_T]: # Type safe methods for narrowing types with TypeVars. # The default narrowing for isinstance(obj, dict) is dict[unknown, unknown], # however this cause Pyright to rightfully report errors. As we know we don't -# care about the contained types we can safely use `object` in it's place. +# care about the contained types we can safely use `object` in its place. # # There are two separate functions defined, `is_*` and `is_*_t` for different use cases. # `is_*` is for when you're dealing with an unknown input diff --git a/src/gcore/_version.py b/src/gcore/_version.py index 4e59998e..4e588aa0 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.17.0" # x-release-please-version +__version__ = "0.18.0" # x-release-please-version diff --git a/src/gcore/resources/cdn/ip_ranges.py b/src/gcore/resources/cdn/ip_ranges.py index 606e9b83..ee39f4a9 100644 --- a/src/gcore/resources/cdn/ip_ranges.py +++ b/src/gcore/resources/cdn/ip_ranges.py @@ -2,9 +2,12 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx -from ..._types import Body, Query, Headers, NotGiven, not_given +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import is_given, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -13,6 +16,7 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) +from ...types.cdn import ip_range_list_params, ip_range_list_ips_params from ..._base_client import make_request_options from ...types.cdn.public_ip_list import PublicIPList from ...types.cdn.public_network_list import PublicNetworkList @@ -43,6 +47,8 @@ def with_streaming_response(self) -> IPRangesResourceWithStreamingResponse: def list( self, *, + format: Literal["json", "plain"] | Omit = omit, + accept: Literal["application/json", "text/plain"] | 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, @@ -58,11 +64,31 @@ def list( relevance. We recommend using a script for automatically update IP ACL. This request does not require authorization. + + Args: + format: Optional format override. When set, this takes precedence over the `Accept` + header. + + 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 """ + extra_headers = { + **strip_not_given({"Accept": str(accept) if is_given(accept) else not_given}), + **(extra_headers or {}), + } return self._get( "/cdn/public-net-list", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"format": format}, ip_range_list_params.IPRangeListParams), ), cast_to=PublicNetworkList, ) @@ -70,6 +96,8 @@ def list( def list_ips( self, *, + format: Literal["json", "plain"] | Omit = omit, + accept: Literal["application/json", "text/plain"] | 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, @@ -86,11 +114,31 @@ def list_ips( relevance. We recommend using a script to automatically update IP ACL. This request does not require authorization. + + Args: + format: Optional format override. When set, this takes precedence over the `Accept` + header. + + 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 """ + extra_headers = { + **strip_not_given({"Accept": str(accept) if is_given(accept) else not_given}), + **(extra_headers or {}), + } return self._get( "/cdn/public-ip-list", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"format": format}, ip_range_list_ips_params.IPRangeListIPsParams), ), cast_to=PublicIPList, ) @@ -119,6 +167,8 @@ def with_streaming_response(self) -> AsyncIPRangesResourceWithStreamingResponse: async def list( self, *, + format: Literal["json", "plain"] | Omit = omit, + accept: Literal["application/json", "text/plain"] | 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, @@ -134,11 +184,31 @@ async def list( relevance. We recommend using a script for automatically update IP ACL. This request does not require authorization. + + Args: + format: Optional format override. When set, this takes precedence over the `Accept` + header. + + 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 """ + extra_headers = { + **strip_not_given({"Accept": str(accept) if is_given(accept) else not_given}), + **(extra_headers or {}), + } return await self._get( "/cdn/public-net-list", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"format": format}, ip_range_list_params.IPRangeListParams), ), cast_to=PublicNetworkList, ) @@ -146,6 +216,8 @@ async def list( async def list_ips( self, *, + format: Literal["json", "plain"] | Omit = omit, + accept: Literal["application/json", "text/plain"] | 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, @@ -162,11 +234,31 @@ async def list_ips( relevance. We recommend using a script to automatically update IP ACL. This request does not require authorization. + + Args: + format: Optional format override. When set, this takes precedence over the `Accept` + header. + + 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 """ + extra_headers = { + **strip_not_given({"Accept": str(accept) if is_given(accept) else not_given}), + **(extra_headers or {}), + } return await self._get( "/cdn/public-ip-list", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"format": format}, ip_range_list_ips_params.IPRangeListIPsParams), ), cast_to=PublicIPList, ) diff --git a/src/gcore/resources/cdn/statistics.py b/src/gcore/resources/cdn/statistics.py index 14f2fa8c..0e6a32a6 100644 --- a/src/gcore/resources/cdn/statistics.py +++ b/src/gcore/resources/cdn/statistics.py @@ -77,7 +77,7 @@ def get_logs_usage_aggregated( to: End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - flat: The waу parameters are arranged in the response. + flat: The way the parameters are arranged in the response. Possible values: @@ -96,6 +96,9 @@ def get_logs_usage_aggregated( - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -146,22 +149,17 @@ def get_logs_usage_series( Args: from_: Beginning of the requested time period (ISO 8601/RFC 3339 format, UTC.) - Example: - - - &from=2020-01-01T00:00:00.000 - to: End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - Example: - - - &from=2020-01-01T00:00:00.000 - resource: CDN resources IDs by that statistics data is grouped. To request multiple values, use: - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -218,11 +216,6 @@ def get_resource_usage_aggregated( Args: from_: Beginning of the requested time period (ISO 8601/RFC 3339 format, UTC.) - Examples: - - - &from=2018-11-01T00:00:00.000 - - &from=2018-11-01 - metrics: Types of statistics data. Possible values: @@ -279,15 +272,8 @@ def get_resource_usage_aggregated( to: End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - Examples: - - - &to=2018-11-01T00:00:00.000 - - &to=2018-11-01 - - countries: Names of countries for which data is displayed. - - English short name from [ISO 3166 standard][1] without the definite article - "the" should be used. + countries: Names of countries for which data should be displayed. English short name from + [ISO 3166 standard][1] without the definite article ("the") should be used. [1]: https://www.iso.org/obp/ui/#search/code/ @@ -295,7 +281,7 @@ def get_resource_usage_aggregated( - &countries=france&countries=denmark - flat: The waу the parameters are arranged in the response. + flat: The way the parameters are arranged in the response. Possible values: @@ -309,7 +295,9 @@ def get_resource_usage_aggregated( - **resource** – Data is grouped by CDN resources IDs. - **region** – Data is grouped by regions of CDN edge servers. - **country** – Data is grouped by countries of CDN edge servers. - - **vhost** – Data is grouped by resources CNAME. + - **vhost** – Data is grouped by resources CNAMEs. + - **`client_country`** - Data is grouped by countries, based on end-users' + location. To request multiple values, use: @@ -329,7 +317,7 @@ def get_resource_usage_aggregated( - **africa** - Africa - **sa** - South America - resource: CDN resources IDs by which statistics data is grouped. + resource: CDN resources IDs by that statistics data is grouped. To request multiple values, use: @@ -472,6 +460,8 @@ def get_resource_usage_series( - **region** – Data is grouped by regions of CDN edge servers. - **country** – Data is grouped by countries of CDN edge servers. - **vhost** – Data is grouped by resources CNAMEs. + - **`client_country`** - Data is grouped by countries, based on end-users' + location. To request multiple values, use: @@ -491,12 +481,15 @@ def get_resource_usage_series( - **africa** - Africa - **sa** - South America - resource: CDN resource IDs. + resource: CDN resources IDs by that statistics data is grouped. To request multiple values, use: - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -555,7 +548,7 @@ def get_shield_usage_aggregated( to: End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - flat: The waу parameters are arranged in the response. + flat: The way the parameters are arranged in the response. Possible values: @@ -566,7 +559,7 @@ def get_shield_usage_aggregated( Possible value: - - **resource** - Data is grouped by CDN resource. + - **resource** - Data is grouped by CDN resources. resource: CDN resources IDs by that statistics data is grouped. @@ -574,6 +567,9 @@ def get_shield_usage_aggregated( - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -632,6 +628,9 @@ def get_shield_usage_series( - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -705,7 +704,7 @@ async def get_logs_usage_aggregated( to: End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - flat: The waу parameters are arranged in the response. + flat: The way the parameters are arranged in the response. Possible values: @@ -724,6 +723,9 @@ async def get_logs_usage_aggregated( - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -774,22 +776,17 @@ async def get_logs_usage_series( Args: from_: Beginning of the requested time period (ISO 8601/RFC 3339 format, UTC.) - Example: - - - &from=2020-01-01T00:00:00.000 - to: End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - Example: - - - &from=2020-01-01T00:00:00.000 - resource: CDN resources IDs by that statistics data is grouped. To request multiple values, use: - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -846,11 +843,6 @@ async def get_resource_usage_aggregated( Args: from_: Beginning of the requested time period (ISO 8601/RFC 3339 format, UTC.) - Examples: - - - &from=2018-11-01T00:00:00.000 - - &from=2018-11-01 - metrics: Types of statistics data. Possible values: @@ -907,15 +899,8 @@ async def get_resource_usage_aggregated( to: End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - Examples: - - - &to=2018-11-01T00:00:00.000 - - &to=2018-11-01 - - countries: Names of countries for which data is displayed. - - English short name from [ISO 3166 standard][1] without the definite article - "the" should be used. + countries: Names of countries for which data should be displayed. English short name from + [ISO 3166 standard][1] without the definite article ("the") should be used. [1]: https://www.iso.org/obp/ui/#search/code/ @@ -923,7 +908,7 @@ async def get_resource_usage_aggregated( - &countries=france&countries=denmark - flat: The waу the parameters are arranged in the response. + flat: The way the parameters are arranged in the response. Possible values: @@ -937,7 +922,9 @@ async def get_resource_usage_aggregated( - **resource** – Data is grouped by CDN resources IDs. - **region** – Data is grouped by regions of CDN edge servers. - **country** – Data is grouped by countries of CDN edge servers. - - **vhost** – Data is grouped by resources CNAME. + - **vhost** – Data is grouped by resources CNAMEs. + - **`client_country`** - Data is grouped by countries, based on end-users' + location. To request multiple values, use: @@ -957,7 +944,7 @@ async def get_resource_usage_aggregated( - **africa** - Africa - **sa** - South America - resource: CDN resources IDs by which statistics data is grouped. + resource: CDN resources IDs by that statistics data is grouped. To request multiple values, use: @@ -1100,6 +1087,8 @@ async def get_resource_usage_series( - **region** – Data is grouped by regions of CDN edge servers. - **country** – Data is grouped by countries of CDN edge servers. - **vhost** – Data is grouped by resources CNAMEs. + - **`client_country`** - Data is grouped by countries, based on end-users' + location. To request multiple values, use: @@ -1119,12 +1108,15 @@ async def get_resource_usage_series( - **africa** - Africa - **sa** - South America - resource: CDN resource IDs. + resource: CDN resources IDs by that statistics data is grouped. To request multiple values, use: - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1183,7 +1175,7 @@ async def get_shield_usage_aggregated( to: End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - flat: The waу parameters are arranged in the response. + flat: The way the parameters are arranged in the response. Possible values: @@ -1194,7 +1186,7 @@ async def get_shield_usage_aggregated( Possible value: - - **resource** - Data is grouped by CDN resource. + - **resource** - Data is grouped by CDN resources. resource: CDN resources IDs by that statistics data is grouped. @@ -1202,6 +1194,9 @@ async def get_shield_usage_aggregated( - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1260,6 +1255,9 @@ async def get_shield_usage_series( - &resource=1&resource=2 + If CDN resource ID is not specified, data related to all CDN resources is + returned. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request diff --git a/src/gcore/resources/cloud/__init__.py b/src/gcore/resources/cloud/__init__.py index c78945ec..b430fc7c 100644 --- a/src/gcore/resources/cloud/__init__.py +++ b/src/gcore/resources/cloud/__init__.py @@ -96,6 +96,14 @@ BaremetalResourceWithStreamingResponse, AsyncBaremetalResourceWithStreamingResponse, ) +from .databases import ( + DatabasesResource, + AsyncDatabasesResource, + DatabasesResourceWithRawResponse, + AsyncDatabasesResourceWithRawResponse, + DatabasesResourceWithStreamingResponse, + AsyncDatabasesResourceWithStreamingResponse, +) from .inference import ( InferenceResource, AsyncInferenceResource, @@ -374,6 +382,12 @@ "AsyncUsageReportsResourceWithRawResponse", "UsageReportsResourceWithStreamingResponse", "AsyncUsageReportsResourceWithStreamingResponse", + "DatabasesResource", + "AsyncDatabasesResource", + "DatabasesResourceWithRawResponse", + "AsyncDatabasesResourceWithRawResponse", + "DatabasesResourceWithStreamingResponse", + "AsyncDatabasesResourceWithStreamingResponse", "CloudResource", "AsyncCloudResource", "CloudResourceWithRawResponse", diff --git a/src/gcore/resources/cloud/baremetal/servers.py b/src/gcore/resources/cloud/baremetal/servers.py index 88ca7fcc..39be2ae6 100644 --- a/src/gcore/resources/cloud/baremetal/servers.py +++ b/src/gcore/resources/cloud/baremetal/servers.py @@ -1022,6 +1022,12 @@ def __init__(self, servers: ServersResource) -> None: self.rebuild = to_raw_response_wrapper( servers.rebuild, ) + self.create_and_poll = to_raw_response_wrapper( + servers.create_and_poll, + ) + self.rebuild_and_poll = to_raw_response_wrapper( + servers.rebuild_and_poll, + ) class AsyncServersResourceWithRawResponse: @@ -1037,6 +1043,12 @@ def __init__(self, servers: AsyncServersResource) -> None: self.rebuild = async_to_raw_response_wrapper( servers.rebuild, ) + self.create_and_poll = async_to_raw_response_wrapper( + servers.create_and_poll, + ) + self.rebuild_and_poll = async_to_raw_response_wrapper( + servers.rebuild_and_poll, + ) class ServersResourceWithStreamingResponse: @@ -1052,6 +1064,12 @@ def __init__(self, servers: ServersResource) -> None: self.rebuild = to_streamed_response_wrapper( servers.rebuild, ) + self.create_and_poll = to_streamed_response_wrapper( + servers.create_and_poll, + ) + self.rebuild_and_poll = to_streamed_response_wrapper( + servers.rebuild_and_poll, + ) class AsyncServersResourceWithStreamingResponse: @@ -1067,3 +1085,9 @@ def __init__(self, servers: AsyncServersResource) -> None: self.rebuild = async_to_streamed_response_wrapper( servers.rebuild, ) + self.create_and_poll = async_to_streamed_response_wrapper( + servers.create_and_poll, + ) + self.rebuild_and_poll = async_to_streamed_response_wrapper( + servers.rebuild_and_poll, + ) diff --git a/src/gcore/resources/cloud/cloud.py b/src/gcore/resources/cloud/cloud.py index 7628349c..6583dc98 100644 --- a/src/gcore/resources/cloud/cloud.py +++ b/src/gcore/resources/cloud/cloud.py @@ -140,6 +140,14 @@ BaremetalResourceWithStreamingResponse, AsyncBaremetalResourceWithStreamingResponse, ) +from .databases.databases import ( + DatabasesResource, + AsyncDatabasesResource, + DatabasesResourceWithRawResponse, + AsyncDatabasesResourceWithRawResponse, + DatabasesResourceWithStreamingResponse, + AsyncDatabasesResourceWithStreamingResponse, +) from .inference.inference import ( InferenceResource, AsyncInferenceResource, @@ -328,6 +336,10 @@ def cost_reports(self) -> CostReportsResource: def usage_reports(self) -> UsageReportsResource: return UsageReportsResource(self._client) + @cached_property + def databases(self) -> DatabasesResource: + return DatabasesResource(self._client) + @cached_property def with_raw_response(self) -> CloudResourceWithRawResponse: """ @@ -460,6 +472,10 @@ def cost_reports(self) -> AsyncCostReportsResource: def usage_reports(self) -> AsyncUsageReportsResource: return AsyncUsageReportsResource(self._client) + @cached_property + def databases(self) -> AsyncDatabasesResource: + return AsyncDatabasesResource(self._client) + @cached_property def with_raw_response(self) -> AsyncCloudResourceWithRawResponse: """ @@ -595,6 +611,10 @@ def cost_reports(self) -> CostReportsResourceWithRawResponse: def usage_reports(self) -> UsageReportsResourceWithRawResponse: return UsageReportsResourceWithRawResponse(self._cloud.usage_reports) + @cached_property + def databases(self) -> DatabasesResourceWithRawResponse: + return DatabasesResourceWithRawResponse(self._cloud.databases) + class AsyncCloudResourceWithRawResponse: def __init__(self, cloud: AsyncCloudResource) -> None: @@ -711,6 +731,10 @@ def cost_reports(self) -> AsyncCostReportsResourceWithRawResponse: def usage_reports(self) -> AsyncUsageReportsResourceWithRawResponse: return AsyncUsageReportsResourceWithRawResponse(self._cloud.usage_reports) + @cached_property + def databases(self) -> AsyncDatabasesResourceWithRawResponse: + return AsyncDatabasesResourceWithRawResponse(self._cloud.databases) + class CloudResourceWithStreamingResponse: def __init__(self, cloud: CloudResource) -> None: @@ -827,6 +851,10 @@ def cost_reports(self) -> CostReportsResourceWithStreamingResponse: def usage_reports(self) -> UsageReportsResourceWithStreamingResponse: return UsageReportsResourceWithStreamingResponse(self._cloud.usage_reports) + @cached_property + def databases(self) -> DatabasesResourceWithStreamingResponse: + return DatabasesResourceWithStreamingResponse(self._cloud.databases) + class AsyncCloudResourceWithStreamingResponse: def __init__(self, cloud: AsyncCloudResource) -> None: @@ -942,3 +970,7 @@ def cost_reports(self) -> AsyncCostReportsResourceWithStreamingResponse: @cached_property def usage_reports(self) -> AsyncUsageReportsResourceWithStreamingResponse: return AsyncUsageReportsResourceWithStreamingResponse(self._cloud.usage_reports) + + @cached_property + def databases(self) -> AsyncDatabasesResourceWithStreamingResponse: + return AsyncDatabasesResourceWithStreamingResponse(self._cloud.databases) diff --git a/src/gcore/resources/cloud/databases/__init__.py b/src/gcore/resources/cloud/databases/__init__.py new file mode 100644 index 00000000..6935a4f7 --- /dev/null +++ b/src/gcore/resources/cloud/databases/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .postgres import ( + PostgresResource, + AsyncPostgresResource, + PostgresResourceWithRawResponse, + AsyncPostgresResourceWithRawResponse, + PostgresResourceWithStreamingResponse, + AsyncPostgresResourceWithStreamingResponse, +) +from .databases import ( + DatabasesResource, + AsyncDatabasesResource, + DatabasesResourceWithRawResponse, + AsyncDatabasesResourceWithRawResponse, + DatabasesResourceWithStreamingResponse, + AsyncDatabasesResourceWithStreamingResponse, +) + +__all__ = [ + "PostgresResource", + "AsyncPostgresResource", + "PostgresResourceWithRawResponse", + "AsyncPostgresResourceWithRawResponse", + "PostgresResourceWithStreamingResponse", + "AsyncPostgresResourceWithStreamingResponse", + "DatabasesResource", + "AsyncDatabasesResource", + "DatabasesResourceWithRawResponse", + "AsyncDatabasesResourceWithRawResponse", + "DatabasesResourceWithStreamingResponse", + "AsyncDatabasesResourceWithStreamingResponse", +] diff --git a/src/gcore/resources/cloud/databases/databases.py b/src/gcore/resources/cloud/databases/databases.py new file mode 100644 index 00000000..baacc4af --- /dev/null +++ b/src/gcore/resources/cloud/databases/databases.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from .postgres.postgres import ( + PostgresResource, + AsyncPostgresResource, + PostgresResourceWithRawResponse, + AsyncPostgresResourceWithRawResponse, + PostgresResourceWithStreamingResponse, + AsyncPostgresResourceWithStreamingResponse, +) + +__all__ = ["DatabasesResource", "AsyncDatabasesResource"] + + +class DatabasesResource(SyncAPIResource): + @cached_property + def postgres(self) -> PostgresResource: + return PostgresResource(self._client) + + @cached_property + def with_raw_response(self) -> DatabasesResourceWithRawResponse: + """ + 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 DatabasesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DatabasesResourceWithStreamingResponse: + """ + 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 DatabasesResourceWithStreamingResponse(self) + + +class AsyncDatabasesResource(AsyncAPIResource): + @cached_property + def postgres(self) -> AsyncPostgresResource: + return AsyncPostgresResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncDatabasesResourceWithRawResponse: + """ + 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 AsyncDatabasesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDatabasesResourceWithStreamingResponse: + """ + 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 AsyncDatabasesResourceWithStreamingResponse(self) + + +class DatabasesResourceWithRawResponse: + def __init__(self, databases: DatabasesResource) -> None: + self._databases = databases + + @cached_property + def postgres(self) -> PostgresResourceWithRawResponse: + return PostgresResourceWithRawResponse(self._databases.postgres) + + +class AsyncDatabasesResourceWithRawResponse: + def __init__(self, databases: AsyncDatabasesResource) -> None: + self._databases = databases + + @cached_property + def postgres(self) -> AsyncPostgresResourceWithRawResponse: + return AsyncPostgresResourceWithRawResponse(self._databases.postgres) + + +class DatabasesResourceWithStreamingResponse: + def __init__(self, databases: DatabasesResource) -> None: + self._databases = databases + + @cached_property + def postgres(self) -> PostgresResourceWithStreamingResponse: + return PostgresResourceWithStreamingResponse(self._databases.postgres) + + +class AsyncDatabasesResourceWithStreamingResponse: + def __init__(self, databases: AsyncDatabasesResource) -> None: + self._databases = databases + + @cached_property + def postgres(self) -> AsyncPostgresResourceWithStreamingResponse: + return AsyncPostgresResourceWithStreamingResponse(self._databases.postgres) diff --git a/src/gcore/resources/cloud/databases/postgres/__init__.py b/src/gcore/resources/cloud/databases/postgres/__init__.py new file mode 100644 index 00000000..63128146 --- /dev/null +++ b/src/gcore/resources/cloud/databases/postgres/__init__.py @@ -0,0 +1,61 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .clusters import ( + ClustersResource, + AsyncClustersResource, + ClustersResourceWithRawResponse, + AsyncClustersResourceWithRawResponse, + ClustersResourceWithStreamingResponse, + AsyncClustersResourceWithStreamingResponse, +) +from .postgres import ( + PostgresResource, + AsyncPostgresResource, + PostgresResourceWithRawResponse, + AsyncPostgresResourceWithRawResponse, + PostgresResourceWithStreamingResponse, + AsyncPostgresResourceWithStreamingResponse, +) +from .configurations import ( + ConfigurationsResource, + AsyncConfigurationsResource, + ConfigurationsResourceWithRawResponse, + AsyncConfigurationsResourceWithRawResponse, + ConfigurationsResourceWithStreamingResponse, + AsyncConfigurationsResourceWithStreamingResponse, +) +from .custom_configurations import ( + CustomConfigurationsResource, + AsyncCustomConfigurationsResource, + CustomConfigurationsResourceWithRawResponse, + AsyncCustomConfigurationsResourceWithRawResponse, + CustomConfigurationsResourceWithStreamingResponse, + AsyncCustomConfigurationsResourceWithStreamingResponse, +) + +__all__ = [ + "ClustersResource", + "AsyncClustersResource", + "ClustersResourceWithRawResponse", + "AsyncClustersResourceWithRawResponse", + "ClustersResourceWithStreamingResponse", + "AsyncClustersResourceWithStreamingResponse", + "ConfigurationsResource", + "AsyncConfigurationsResource", + "ConfigurationsResourceWithRawResponse", + "AsyncConfigurationsResourceWithRawResponse", + "ConfigurationsResourceWithStreamingResponse", + "AsyncConfigurationsResourceWithStreamingResponse", + "CustomConfigurationsResource", + "AsyncCustomConfigurationsResource", + "CustomConfigurationsResourceWithRawResponse", + "AsyncCustomConfigurationsResourceWithRawResponse", + "CustomConfigurationsResourceWithStreamingResponse", + "AsyncCustomConfigurationsResourceWithStreamingResponse", + "PostgresResource", + "AsyncPostgresResource", + "PostgresResourceWithRawResponse", + "AsyncPostgresResourceWithRawResponse", + "PostgresResourceWithStreamingResponse", + "AsyncPostgresResourceWithStreamingResponse", +] diff --git a/src/gcore/resources/cloud/databases/postgres/clusters/__init__.py b/src/gcore/resources/cloud/databases/postgres/clusters/__init__.py new file mode 100644 index 00000000..677f309e --- /dev/null +++ b/src/gcore/resources/cloud/databases/postgres/clusters/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .clusters import ( + ClustersResource, + AsyncClustersResource, + ClustersResourceWithRawResponse, + AsyncClustersResourceWithRawResponse, + ClustersResourceWithStreamingResponse, + AsyncClustersResourceWithStreamingResponse, +) +from .user_credentials import ( + UserCredentialsResource, + AsyncUserCredentialsResource, + UserCredentialsResourceWithRawResponse, + AsyncUserCredentialsResourceWithRawResponse, + UserCredentialsResourceWithStreamingResponse, + AsyncUserCredentialsResourceWithStreamingResponse, +) + +__all__ = [ + "UserCredentialsResource", + "AsyncUserCredentialsResource", + "UserCredentialsResourceWithRawResponse", + "AsyncUserCredentialsResourceWithRawResponse", + "UserCredentialsResourceWithStreamingResponse", + "AsyncUserCredentialsResourceWithStreamingResponse", + "ClustersResource", + "AsyncClustersResource", + "ClustersResourceWithRawResponse", + "AsyncClustersResourceWithRawResponse", + "ClustersResourceWithStreamingResponse", + "AsyncClustersResourceWithStreamingResponse", +] diff --git a/src/gcore/resources/cloud/databases/postgres/clusters/clusters.py b/src/gcore/resources/cloud/databases/postgres/clusters/clusters.py new file mode 100644 index 00000000..bb01ed8b --- /dev/null +++ b/src/gcore/resources/cloud/databases/postgres/clusters/clusters.py @@ -0,0 +1,716 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable, 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 ......pagination import SyncOffsetPage, AsyncOffsetPage +from .user_credentials import ( + UserCredentialsResource, + AsyncUserCredentialsResource, + UserCredentialsResourceWithRawResponse, + AsyncUserCredentialsResourceWithRawResponse, + UserCredentialsResourceWithStreamingResponse, + AsyncUserCredentialsResourceWithStreamingResponse, +) +from ......_base_client import AsyncPaginator, make_request_options +from ......types.cloud.task_id_list import TaskIDList +from ......types.cloud.databases.postgres import cluster_list_params, cluster_create_params, cluster_update_params +from ......types.cloud.databases.postgres.postgres_cluster import PostgresCluster +from ......types.cloud.databases.postgres.postgres_cluster_short import PostgresClusterShort + +__all__ = ["ClustersResource", "AsyncClustersResource"] + + +class ClustersResource(SyncAPIResource): + @cached_property + def user_credentials(self) -> UserCredentialsResource: + return UserCredentialsResource(self._client) + + @cached_property + def with_raw_response(self) -> ClustersResourceWithRawResponse: + """ + 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 ClustersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ClustersResourceWithStreamingResponse: + """ + 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 ClustersResourceWithStreamingResponse(self) + + def create( + self, + *, + project_id: int | None = None, + region_id: int | None = None, + cluster_name: str, + flavor: cluster_create_params.Flavor, + high_availability: Optional[cluster_create_params.HighAvailability], + network: cluster_create_params.Network, + pg_server_configuration: cluster_create_params.PgServerConfiguration, + storage: cluster_create_params.Storage, + databases: Iterable[cluster_create_params.Database] | Omit = omit, + users: Iterable[cluster_create_params.User] | 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 PostgreSQL cluster with the specified configuration. + + Args: + cluster_name: PostgreSQL cluster name + + flavor: Instance RAM and CPU + + high_availability: High Availability settings + + pg_server_configuration: PosgtreSQL cluster configuration + + storage: Cluster's storage configuration + + 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/dbaas/postgres/clusters/{project_id}/{region_id}", + body=maybe_transform( + { + "cluster_name": cluster_name, + "flavor": flavor, + "high_availability": high_availability, + "network": network, + "pg_server_configuration": pg_server_configuration, + "storage": storage, + "databases": databases, + "users": users, + }, + cluster_create_params.ClusterCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskIDList, + ) + + def update( + self, + cluster_name: str, + *, + project_id: int | None = None, + region_id: int | None = None, + databases: Iterable[cluster_update_params.Database] | Omit = omit, + flavor: Optional[cluster_update_params.Flavor] | Omit = omit, + high_availability: Optional[cluster_update_params.HighAvailability] | Omit = omit, + network: Optional[cluster_update_params.Network] | Omit = omit, + pg_server_configuration: Optional[cluster_update_params.PgServerConfiguration] | Omit = omit, + storage: Optional[cluster_update_params.Storage] | Omit = omit, + users: Iterable[cluster_update_params.User] | 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: + """ + Update the configuration of an existing PostgreSQL cluster. + + Args: + flavor: New instance RAM and CPU + + high_availability: New High Availability settings + + pg_server_configuration: New PosgtreSQL cluster configuration + + storage: New storage configuration + + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + return self._patch( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}", + body=maybe_transform( + { + "databases": databases, + "flavor": flavor, + "high_availability": high_availability, + "network": network, + "pg_server_configuration": pg_server_configuration, + "storage": storage, + "users": users, + }, + cluster_update_params.ClusterUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskIDList, + ) + + def list( + self, + *, + project_id: int | None = None, + region_id: int | None = None, + limit: int | Omit = omit, + offset: int | 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, + ) -> SyncOffsetPage[PostgresClusterShort]: + """List all PostgreSQL clusters in the specified project and region. + + Results can be + filtered by search query and paginated. + + Args: + limit: Maximum number of clusters to return + + offset: Number of clusters to skip + + 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._get_api_list( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}", + page=SyncOffsetPage[PostgresClusterShort], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "offset": offset, + }, + cluster_list_params.ClusterListParams, + ), + ), + model=PostgresClusterShort, + ) + + def delete( + self, + cluster_name: 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 PostgreSQL cluster and all its associated resources. + + Args: + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + return self._delete( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskIDList, + ) + + def get( + self, + cluster_name: 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, + ) -> PostgresCluster: + """ + Get detailed information about a specific PostgreSQL cluster. + + Args: + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + return self._get( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PostgresCluster, + ) + + +class AsyncClustersResource(AsyncAPIResource): + @cached_property + def user_credentials(self) -> AsyncUserCredentialsResource: + return AsyncUserCredentialsResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncClustersResourceWithRawResponse: + """ + 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 AsyncClustersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncClustersResourceWithStreamingResponse: + """ + 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 AsyncClustersResourceWithStreamingResponse(self) + + async def create( + self, + *, + project_id: int | None = None, + region_id: int | None = None, + cluster_name: str, + flavor: cluster_create_params.Flavor, + high_availability: Optional[cluster_create_params.HighAvailability], + network: cluster_create_params.Network, + pg_server_configuration: cluster_create_params.PgServerConfiguration, + storage: cluster_create_params.Storage, + databases: Iterable[cluster_create_params.Database] | Omit = omit, + users: Iterable[cluster_create_params.User] | 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 PostgreSQL cluster with the specified configuration. + + Args: + cluster_name: PostgreSQL cluster name + + flavor: Instance RAM and CPU + + high_availability: High Availability settings + + pg_server_configuration: PosgtreSQL cluster configuration + + storage: Cluster's storage configuration + + 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/dbaas/postgres/clusters/{project_id}/{region_id}", + body=await async_maybe_transform( + { + "cluster_name": cluster_name, + "flavor": flavor, + "high_availability": high_availability, + "network": network, + "pg_server_configuration": pg_server_configuration, + "storage": storage, + "databases": databases, + "users": users, + }, + cluster_create_params.ClusterCreateParams, + ), + 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, + cluster_name: str, + *, + project_id: int | None = None, + region_id: int | None = None, + databases: Iterable[cluster_update_params.Database] | Omit = omit, + flavor: Optional[cluster_update_params.Flavor] | Omit = omit, + high_availability: Optional[cluster_update_params.HighAvailability] | Omit = omit, + network: Optional[cluster_update_params.Network] | Omit = omit, + pg_server_configuration: Optional[cluster_update_params.PgServerConfiguration] | Omit = omit, + storage: Optional[cluster_update_params.Storage] | Omit = omit, + users: Iterable[cluster_update_params.User] | 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: + """ + Update the configuration of an existing PostgreSQL cluster. + + Args: + flavor: New instance RAM and CPU + + high_availability: New High Availability settings + + pg_server_configuration: New PosgtreSQL cluster configuration + + storage: New storage configuration + + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + return await self._patch( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}", + body=await async_maybe_transform( + { + "databases": databases, + "flavor": flavor, + "high_availability": high_availability, + "network": network, + "pg_server_configuration": pg_server_configuration, + "storage": storage, + "users": users, + }, + cluster_update_params.ClusterUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskIDList, + ) + + def list( + self, + *, + project_id: int | None = None, + region_id: int | None = None, + limit: int | Omit = omit, + offset: int | 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, + ) -> AsyncPaginator[PostgresClusterShort, AsyncOffsetPage[PostgresClusterShort]]: + """List all PostgreSQL clusters in the specified project and region. + + Results can be + filtered by search query and paginated. + + Args: + limit: Maximum number of clusters to return + + offset: Number of clusters to skip + + 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._get_api_list( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}", + page=AsyncOffsetPage[PostgresClusterShort], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "offset": offset, + }, + cluster_list_params.ClusterListParams, + ), + ), + model=PostgresClusterShort, + ) + + async def delete( + self, + cluster_name: 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 PostgreSQL cluster and all its associated resources. + + Args: + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + return await self._delete( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}", + 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, + cluster_name: 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, + ) -> PostgresCluster: + """ + Get detailed information about a specific PostgreSQL cluster. + + Args: + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + return await self._get( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PostgresCluster, + ) + + +class ClustersResourceWithRawResponse: + def __init__(self, clusters: ClustersResource) -> None: + self._clusters = clusters + + self.create = to_raw_response_wrapper( + clusters.create, + ) + self.update = to_raw_response_wrapper( + clusters.update, + ) + self.list = to_raw_response_wrapper( + clusters.list, + ) + self.delete = to_raw_response_wrapper( + clusters.delete, + ) + self.get = to_raw_response_wrapper( + clusters.get, + ) + + @cached_property + def user_credentials(self) -> UserCredentialsResourceWithRawResponse: + return UserCredentialsResourceWithRawResponse(self._clusters.user_credentials) + + +class AsyncClustersResourceWithRawResponse: + def __init__(self, clusters: AsyncClustersResource) -> None: + self._clusters = clusters + + self.create = async_to_raw_response_wrapper( + clusters.create, + ) + self.update = async_to_raw_response_wrapper( + clusters.update, + ) + self.list = async_to_raw_response_wrapper( + clusters.list, + ) + self.delete = async_to_raw_response_wrapper( + clusters.delete, + ) + self.get = async_to_raw_response_wrapper( + clusters.get, + ) + + @cached_property + def user_credentials(self) -> AsyncUserCredentialsResourceWithRawResponse: + return AsyncUserCredentialsResourceWithRawResponse(self._clusters.user_credentials) + + +class ClustersResourceWithStreamingResponse: + def __init__(self, clusters: ClustersResource) -> None: + self._clusters = clusters + + self.create = to_streamed_response_wrapper( + clusters.create, + ) + self.update = to_streamed_response_wrapper( + clusters.update, + ) + self.list = to_streamed_response_wrapper( + clusters.list, + ) + self.delete = to_streamed_response_wrapper( + clusters.delete, + ) + self.get = to_streamed_response_wrapper( + clusters.get, + ) + + @cached_property + def user_credentials(self) -> UserCredentialsResourceWithStreamingResponse: + return UserCredentialsResourceWithStreamingResponse(self._clusters.user_credentials) + + +class AsyncClustersResourceWithStreamingResponse: + def __init__(self, clusters: AsyncClustersResource) -> None: + self._clusters = clusters + + self.create = async_to_streamed_response_wrapper( + clusters.create, + ) + self.update = async_to_streamed_response_wrapper( + clusters.update, + ) + self.list = async_to_streamed_response_wrapper( + clusters.list, + ) + self.delete = async_to_streamed_response_wrapper( + clusters.delete, + ) + self.get = async_to_streamed_response_wrapper( + clusters.get, + ) + + @cached_property + def user_credentials(self) -> AsyncUserCredentialsResourceWithStreamingResponse: + return AsyncUserCredentialsResourceWithStreamingResponse(self._clusters.user_credentials) diff --git a/src/gcore/resources/cloud/databases/postgres/clusters/user_credentials.py b/src/gcore/resources/cloud/databases/postgres/clusters/user_credentials.py new file mode 100644 index 00000000..98ad25be --- /dev/null +++ b/src/gcore/resources/cloud/databases/postgres/clusters/user_credentials.py @@ -0,0 +1,281 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ......_types import Body, Query, Headers, NotGiven, not_given +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 ......_base_client import make_request_options +from ......types.cloud.databases.postgres.clusters.postgres_user_credentials import PostgresUserCredentials + +__all__ = ["UserCredentialsResource", "AsyncUserCredentialsResource"] + + +class UserCredentialsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> UserCredentialsResourceWithRawResponse: + """ + 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 UserCredentialsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> UserCredentialsResourceWithStreamingResponse: + """ + 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 UserCredentialsResourceWithStreamingResponse(self) + + def get( + self, + username: str, + *, + project_id: int | None = None, + region_id: int | None = None, + cluster_name: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> PostgresUserCredentials: + """Get the credentials for a specific user in a PostgreSQL cluster. + + This endpoint + can only be used once per user. + + Args: + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + if not username: + raise ValueError(f"Expected a non-empty value for `username` but received {username!r}") + return self._get( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}/users/{username}/credentials", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PostgresUserCredentials, + ) + + def regenerate( + self, + username: str, + *, + project_id: int | None = None, + region_id: int | None = None, + cluster_name: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> PostgresUserCredentials: + """ + Generate new credentials for a specific user in a PostgreSQL cluster. + + Args: + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + if not username: + raise ValueError(f"Expected a non-empty value for `username` but received {username!r}") + return self._post( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}/users/{username}/credentials", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PostgresUserCredentials, + ) + + +class AsyncUserCredentialsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncUserCredentialsResourceWithRawResponse: + """ + 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 AsyncUserCredentialsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncUserCredentialsResourceWithStreamingResponse: + """ + 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 AsyncUserCredentialsResourceWithStreamingResponse(self) + + async def get( + self, + username: str, + *, + project_id: int | None = None, + region_id: int | None = None, + cluster_name: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> PostgresUserCredentials: + """Get the credentials for a specific user in a PostgreSQL cluster. + + This endpoint + can only be used once per user. + + Args: + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + if not username: + raise ValueError(f"Expected a non-empty value for `username` but received {username!r}") + return await self._get( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}/users/{username}/credentials", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PostgresUserCredentials, + ) + + async def regenerate( + self, + username: str, + *, + project_id: int | None = None, + region_id: int | None = None, + cluster_name: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> PostgresUserCredentials: + """ + Generate new credentials for a specific user in a PostgreSQL cluster. + + Args: + 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 cluster_name: + raise ValueError(f"Expected a non-empty value for `cluster_name` but received {cluster_name!r}") + if not username: + raise ValueError(f"Expected a non-empty value for `username` but received {username!r}") + return await self._post( + f"/cloud/v1/dbaas/postgres/clusters/{project_id}/{region_id}/{cluster_name}/users/{username}/credentials", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PostgresUserCredentials, + ) + + +class UserCredentialsResourceWithRawResponse: + def __init__(self, user_credentials: UserCredentialsResource) -> None: + self._user_credentials = user_credentials + + self.get = to_raw_response_wrapper( + user_credentials.get, + ) + self.regenerate = to_raw_response_wrapper( + user_credentials.regenerate, + ) + + +class AsyncUserCredentialsResourceWithRawResponse: + def __init__(self, user_credentials: AsyncUserCredentialsResource) -> None: + self._user_credentials = user_credentials + + self.get = async_to_raw_response_wrapper( + user_credentials.get, + ) + self.regenerate = async_to_raw_response_wrapper( + user_credentials.regenerate, + ) + + +class UserCredentialsResourceWithStreamingResponse: + def __init__(self, user_credentials: UserCredentialsResource) -> None: + self._user_credentials = user_credentials + + self.get = to_streamed_response_wrapper( + user_credentials.get, + ) + self.regenerate = to_streamed_response_wrapper( + user_credentials.regenerate, + ) + + +class AsyncUserCredentialsResourceWithStreamingResponse: + def __init__(self, user_credentials: AsyncUserCredentialsResource) -> None: + self._user_credentials = user_credentials + + self.get = async_to_streamed_response_wrapper( + user_credentials.get, + ) + self.regenerate = async_to_streamed_response_wrapper( + user_credentials.regenerate, + ) diff --git a/src/gcore/resources/cloud/databases/postgres/configurations.py b/src/gcore/resources/cloud/databases/postgres/configurations.py new file mode 100644 index 00000000..c9f30551 --- /dev/null +++ b/src/gcore/resources/cloud/databases/postgres/configurations.py @@ -0,0 +1,169 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ....._types import Body, Query, Headers, NotGiven, not_given +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 ....._base_client import make_request_options +from .....types.cloud.databases.postgres.postgres_configuration import PostgresConfiguration + +__all__ = ["ConfigurationsResource", "AsyncConfigurationsResource"] + + +class ConfigurationsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ConfigurationsResourceWithRawResponse: + """ + 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 ConfigurationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ConfigurationsResourceWithStreamingResponse: + """ + 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 ConfigurationsResourceWithStreamingResponse(self) + + def get( + self, + *, + 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, + ) -> PostgresConfiguration: + """ + Get all available PostgreSQL configurations for the specified region. + + Args: + 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._get( + f"/cloud/v1/dbaas/postgres/configuration/{project_id}/{region_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PostgresConfiguration, + ) + + +class AsyncConfigurationsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncConfigurationsResourceWithRawResponse: + """ + 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 AsyncConfigurationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncConfigurationsResourceWithStreamingResponse: + """ + 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 AsyncConfigurationsResourceWithStreamingResponse(self) + + async def get( + self, + *, + 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, + ) -> PostgresConfiguration: + """ + Get all available PostgreSQL configurations for the specified region. + + Args: + 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._get( + f"/cloud/v1/dbaas/postgres/configuration/{project_id}/{region_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PostgresConfiguration, + ) + + +class ConfigurationsResourceWithRawResponse: + def __init__(self, configurations: ConfigurationsResource) -> None: + self._configurations = configurations + + self.get = to_raw_response_wrapper( + configurations.get, + ) + + +class AsyncConfigurationsResourceWithRawResponse: + def __init__(self, configurations: AsyncConfigurationsResource) -> None: + self._configurations = configurations + + self.get = async_to_raw_response_wrapper( + configurations.get, + ) + + +class ConfigurationsResourceWithStreamingResponse: + def __init__(self, configurations: ConfigurationsResource) -> None: + self._configurations = configurations + + self.get = to_streamed_response_wrapper( + configurations.get, + ) + + +class AsyncConfigurationsResourceWithStreamingResponse: + def __init__(self, configurations: AsyncConfigurationsResource) -> None: + self._configurations = configurations + + self.get = async_to_streamed_response_wrapper( + configurations.get, + ) diff --git a/src/gcore/resources/cloud/databases/postgres/custom_configurations.py b/src/gcore/resources/cloud/databases/postgres/custom_configurations.py new file mode 100644 index 00000000..9ce396df --- /dev/null +++ b/src/gcore/resources/cloud/databases/postgres/custom_configurations.py @@ -0,0 +1,197 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ....._types import Body, Query, Headers, NotGiven, 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 ....._base_client import make_request_options +from .....types.cloud.databases.postgres import custom_configuration_validate_params +from .....types.cloud.databases.postgres.pg_conf_validation import PgConfValidation + +__all__ = ["CustomConfigurationsResource", "AsyncCustomConfigurationsResource"] + + +class CustomConfigurationsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> CustomConfigurationsResourceWithRawResponse: + """ + 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 CustomConfigurationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CustomConfigurationsResourceWithStreamingResponse: + """ + 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 CustomConfigurationsResourceWithStreamingResponse(self) + + def validate( + self, + *, + project_id: int | None = None, + region_id: int | None = None, + pg_conf: str, + version: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> PgConfValidation: + """ + Validate a custom PostgreSQL configuration file. + + Args: + pg_conf: PostgreSQL configuration + + version: PostgreSQL version + + 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/dbaas/postgres/validate_pg_conf/{project_id}/{region_id}", + body=maybe_transform( + { + "pg_conf": pg_conf, + "version": version, + }, + custom_configuration_validate_params.CustomConfigurationValidateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PgConfValidation, + ) + + +class AsyncCustomConfigurationsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncCustomConfigurationsResourceWithRawResponse: + """ + 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 AsyncCustomConfigurationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCustomConfigurationsResourceWithStreamingResponse: + """ + 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 AsyncCustomConfigurationsResourceWithStreamingResponse(self) + + async def validate( + self, + *, + project_id: int | None = None, + region_id: int | None = None, + pg_conf: str, + version: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> PgConfValidation: + """ + Validate a custom PostgreSQL configuration file. + + Args: + pg_conf: PostgreSQL configuration + + version: PostgreSQL version + + 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/dbaas/postgres/validate_pg_conf/{project_id}/{region_id}", + body=await async_maybe_transform( + { + "pg_conf": pg_conf, + "version": version, + }, + custom_configuration_validate_params.CustomConfigurationValidateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PgConfValidation, + ) + + +class CustomConfigurationsResourceWithRawResponse: + def __init__(self, custom_configurations: CustomConfigurationsResource) -> None: + self._custom_configurations = custom_configurations + + self.validate = to_raw_response_wrapper( + custom_configurations.validate, + ) + + +class AsyncCustomConfigurationsResourceWithRawResponse: + def __init__(self, custom_configurations: AsyncCustomConfigurationsResource) -> None: + self._custom_configurations = custom_configurations + + self.validate = async_to_raw_response_wrapper( + custom_configurations.validate, + ) + + +class CustomConfigurationsResourceWithStreamingResponse: + def __init__(self, custom_configurations: CustomConfigurationsResource) -> None: + self._custom_configurations = custom_configurations + + self.validate = to_streamed_response_wrapper( + custom_configurations.validate, + ) + + +class AsyncCustomConfigurationsResourceWithStreamingResponse: + def __init__(self, custom_configurations: AsyncCustomConfigurationsResource) -> None: + self._custom_configurations = custom_configurations + + self.validate = async_to_streamed_response_wrapper( + custom_configurations.validate, + ) diff --git a/src/gcore/resources/cloud/databases/postgres/postgres.py b/src/gcore/resources/cloud/databases/postgres/postgres.py new file mode 100644 index 00000000..ce9c32b7 --- /dev/null +++ b/src/gcore/resources/cloud/databases/postgres/postgres.py @@ -0,0 +1,166 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from ....._compat import cached_property +from ....._resource import SyncAPIResource, AsyncAPIResource +from .configurations import ( + ConfigurationsResource, + AsyncConfigurationsResource, + ConfigurationsResourceWithRawResponse, + AsyncConfigurationsResourceWithRawResponse, + ConfigurationsResourceWithStreamingResponse, + AsyncConfigurationsResourceWithStreamingResponse, +) +from .clusters.clusters import ( + ClustersResource, + AsyncClustersResource, + ClustersResourceWithRawResponse, + AsyncClustersResourceWithRawResponse, + ClustersResourceWithStreamingResponse, + AsyncClustersResourceWithStreamingResponse, +) +from .custom_configurations import ( + CustomConfigurationsResource, + AsyncCustomConfigurationsResource, + CustomConfigurationsResourceWithRawResponse, + AsyncCustomConfigurationsResourceWithRawResponse, + CustomConfigurationsResourceWithStreamingResponse, + AsyncCustomConfigurationsResourceWithStreamingResponse, +) + +__all__ = ["PostgresResource", "AsyncPostgresResource"] + + +class PostgresResource(SyncAPIResource): + @cached_property + def clusters(self) -> ClustersResource: + return ClustersResource(self._client) + + @cached_property + def configurations(self) -> ConfigurationsResource: + return ConfigurationsResource(self._client) + + @cached_property + def custom_configurations(self) -> CustomConfigurationsResource: + return CustomConfigurationsResource(self._client) + + @cached_property + def with_raw_response(self) -> PostgresResourceWithRawResponse: + """ + 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 PostgresResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> PostgresResourceWithStreamingResponse: + """ + 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 PostgresResourceWithStreamingResponse(self) + + +class AsyncPostgresResource(AsyncAPIResource): + @cached_property + def clusters(self) -> AsyncClustersResource: + return AsyncClustersResource(self._client) + + @cached_property + def configurations(self) -> AsyncConfigurationsResource: + return AsyncConfigurationsResource(self._client) + + @cached_property + def custom_configurations(self) -> AsyncCustomConfigurationsResource: + return AsyncCustomConfigurationsResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncPostgresResourceWithRawResponse: + """ + 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 AsyncPostgresResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncPostgresResourceWithStreamingResponse: + """ + 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 AsyncPostgresResourceWithStreamingResponse(self) + + +class PostgresResourceWithRawResponse: + def __init__(self, postgres: PostgresResource) -> None: + self._postgres = postgres + + @cached_property + def clusters(self) -> ClustersResourceWithRawResponse: + return ClustersResourceWithRawResponse(self._postgres.clusters) + + @cached_property + def configurations(self) -> ConfigurationsResourceWithRawResponse: + return ConfigurationsResourceWithRawResponse(self._postgres.configurations) + + @cached_property + def custom_configurations(self) -> CustomConfigurationsResourceWithRawResponse: + return CustomConfigurationsResourceWithRawResponse(self._postgres.custom_configurations) + + +class AsyncPostgresResourceWithRawResponse: + def __init__(self, postgres: AsyncPostgresResource) -> None: + self._postgres = postgres + + @cached_property + def clusters(self) -> AsyncClustersResourceWithRawResponse: + return AsyncClustersResourceWithRawResponse(self._postgres.clusters) + + @cached_property + def configurations(self) -> AsyncConfigurationsResourceWithRawResponse: + return AsyncConfigurationsResourceWithRawResponse(self._postgres.configurations) + + @cached_property + def custom_configurations(self) -> AsyncCustomConfigurationsResourceWithRawResponse: + return AsyncCustomConfigurationsResourceWithRawResponse(self._postgres.custom_configurations) + + +class PostgresResourceWithStreamingResponse: + def __init__(self, postgres: PostgresResource) -> None: + self._postgres = postgres + + @cached_property + def clusters(self) -> ClustersResourceWithStreamingResponse: + return ClustersResourceWithStreamingResponse(self._postgres.clusters) + + @cached_property + def configurations(self) -> ConfigurationsResourceWithStreamingResponse: + return ConfigurationsResourceWithStreamingResponse(self._postgres.configurations) + + @cached_property + def custom_configurations(self) -> CustomConfigurationsResourceWithStreamingResponse: + return CustomConfigurationsResourceWithStreamingResponse(self._postgres.custom_configurations) + + +class AsyncPostgresResourceWithStreamingResponse: + def __init__(self, postgres: AsyncPostgresResource) -> None: + self._postgres = postgres + + @cached_property + def clusters(self) -> AsyncClustersResourceWithStreamingResponse: + return AsyncClustersResourceWithStreamingResponse(self._postgres.clusters) + + @cached_property + def configurations(self) -> AsyncConfigurationsResourceWithStreamingResponse: + return AsyncConfigurationsResourceWithStreamingResponse(self._postgres.configurations) + + @cached_property + def custom_configurations(self) -> AsyncCustomConfigurationsResourceWithStreamingResponse: + return AsyncCustomConfigurationsResourceWithStreamingResponse(self._postgres.custom_configurations) diff --git a/src/gcore/resources/cloud/gpu_baremetal_clusters/gpu_baremetal_clusters.py b/src/gcore/resources/cloud/gpu_baremetal_clusters/gpu_baremetal_clusters.py index 932484d9..2847eea2 100644 --- a/src/gcore/resources/cloud/gpu_baremetal_clusters/gpu_baremetal_clusters.py +++ b/src/gcore/resources/cloud/gpu_baremetal_clusters/gpu_baremetal_clusters.py @@ -1536,6 +1536,15 @@ def __init__(self, gpu_baremetal_clusters: GPUBaremetalClustersResource) -> None self.resize = to_raw_response_wrapper( gpu_baremetal_clusters.resize, ) + self.create_and_poll = to_raw_response_wrapper( + gpu_baremetal_clusters.create_and_poll, + ) + self.rebuild_and_poll = to_raw_response_wrapper( + gpu_baremetal_clusters.rebuild_and_poll, + ) + self.resize_and_poll = to_raw_response_wrapper( + gpu_baremetal_clusters.resize_and_poll, + ) @cached_property def interfaces(self) -> InterfacesResourceWithRawResponse: @@ -1585,6 +1594,15 @@ def __init__(self, gpu_baremetal_clusters: AsyncGPUBaremetalClustersResource) -> self.resize = async_to_raw_response_wrapper( gpu_baremetal_clusters.resize, ) + self.create_and_poll = async_to_raw_response_wrapper( + gpu_baremetal_clusters.create_and_poll, + ) + self.rebuild_and_poll = async_to_raw_response_wrapper( + gpu_baremetal_clusters.rebuild_and_poll, + ) + self.resize_and_poll = async_to_raw_response_wrapper( + gpu_baremetal_clusters.resize_and_poll, + ) @cached_property def interfaces(self) -> AsyncInterfacesResourceWithRawResponse: @@ -1634,6 +1652,15 @@ def __init__(self, gpu_baremetal_clusters: GPUBaremetalClustersResource) -> None self.resize = to_streamed_response_wrapper( gpu_baremetal_clusters.resize, ) + self.create_and_poll = to_streamed_response_wrapper( + gpu_baremetal_clusters.create_and_poll, + ) + self.rebuild_and_poll = to_streamed_response_wrapper( + gpu_baremetal_clusters.rebuild_and_poll, + ) + self.resize_and_poll = to_streamed_response_wrapper( + gpu_baremetal_clusters.resize_and_poll, + ) @cached_property def interfaces(self) -> InterfacesResourceWithStreamingResponse: @@ -1683,6 +1710,15 @@ def __init__(self, gpu_baremetal_clusters: AsyncGPUBaremetalClustersResource) -> self.resize = async_to_streamed_response_wrapper( gpu_baremetal_clusters.resize, ) + self.create_and_poll = async_to_streamed_response_wrapper( + gpu_baremetal_clusters.create_and_poll, + ) + self.rebuild_and_poll = async_to_streamed_response_wrapper( + gpu_baremetal_clusters.rebuild_and_poll, + ) + self.resize_and_poll = async_to_streamed_response_wrapper( + gpu_baremetal_clusters.resize_and_poll, + ) @cached_property def interfaces(self) -> AsyncInterfacesResourceWithStreamingResponse: diff --git a/src/gcore/resources/cloud/gpu_baremetal_clusters/images.py b/src/gcore/resources/cloud/gpu_baremetal_clusters/images.py index fe8c6f81..036a98d9 100644 --- a/src/gcore/resources/cloud/gpu_baremetal_clusters/images.py +++ b/src/gcore/resources/cloud/gpu_baremetal_clusters/images.py @@ -736,6 +736,12 @@ def __init__(self, images: ImagesResource) -> None: self.upload = to_raw_response_wrapper( images.upload, ) + self.delete_and_poll = to_raw_response_wrapper( + images.delete_and_poll, + ) + self.upload_and_poll = to_raw_response_wrapper( + images.upload_and_poll, + ) class AsyncImagesResourceWithRawResponse: @@ -754,6 +760,12 @@ def __init__(self, images: AsyncImagesResource) -> None: self.upload = async_to_raw_response_wrapper( images.upload, ) + self.delete_and_poll = async_to_raw_response_wrapper( + images.delete_and_poll, + ) + self.upload_and_poll = async_to_raw_response_wrapper( + images.upload_and_poll, + ) class ImagesResourceWithStreamingResponse: @@ -772,6 +784,12 @@ def __init__(self, images: ImagesResource) -> None: self.upload = to_streamed_response_wrapper( images.upload, ) + self.delete_and_poll = to_streamed_response_wrapper( + images.delete_and_poll, + ) + self.upload_and_poll = to_streamed_response_wrapper( + images.upload_and_poll, + ) class AsyncImagesResourceWithStreamingResponse: @@ -790,3 +808,9 @@ def __init__(self, images: AsyncImagesResource) -> None: self.upload = async_to_streamed_response_wrapper( images.upload, ) + self.delete_and_poll = async_to_streamed_response_wrapper( + images.delete_and_poll, + ) + self.upload_and_poll = async_to_streamed_response_wrapper( + images.upload_and_poll, + ) diff --git a/src/gcore/resources/cloud/gpu_baremetal_clusters/servers.py b/src/gcore/resources/cloud/gpu_baremetal_clusters/servers.py index f2771dff..0394a1b1 100644 --- a/src/gcore/resources/cloud/gpu_baremetal_clusters/servers.py +++ b/src/gcore/resources/cloud/gpu_baremetal_clusters/servers.py @@ -1355,6 +1355,9 @@ def __init__(self, servers: ServersResource) -> None: self.reboot = to_raw_response_wrapper( servers.reboot, ) + self.delete_and_poll = to_raw_response_wrapper( + servers.delete_and_poll, + ) class AsyncServersResourceWithRawResponse: @@ -1382,6 +1385,9 @@ def __init__(self, servers: AsyncServersResource) -> None: self.reboot = async_to_raw_response_wrapper( servers.reboot, ) + self.delete_and_poll = async_to_raw_response_wrapper( + servers.delete_and_poll, + ) class ServersResourceWithStreamingResponse: @@ -1409,6 +1415,9 @@ def __init__(self, servers: ServersResource) -> None: self.reboot = to_streamed_response_wrapper( servers.reboot, ) + self.delete_and_poll = to_streamed_response_wrapper( + servers.delete_and_poll, + ) class AsyncServersResourceWithStreamingResponse: @@ -1436,3 +1445,6 @@ def __init__(self, servers: AsyncServersResource) -> None: self.reboot = async_to_streamed_response_wrapper( servers.reboot, ) + self.delete_and_poll = async_to_streamed_response_wrapper( + servers.delete_and_poll, + ) diff --git a/src/gcore/resources/cloud/inference/deployments/deployments.py b/src/gcore/resources/cloud/inference/deployments/deployments.py index bc7b8132..cecda529 100644 --- a/src/gcore/resources/cloud/inference/deployments/deployments.py +++ b/src/gcore/resources/cloud/inference/deployments/deployments.py @@ -1463,6 +1463,15 @@ def __init__(self, deployments: DeploymentsResource) -> None: self.stop = to_raw_response_wrapper( deployments.stop, ) + self.create_and_poll = to_raw_response_wrapper( + deployments.create_and_poll, + ) + self.update_and_poll = to_raw_response_wrapper( + deployments.update_and_poll, + ) + self.delete_and_poll = to_raw_response_wrapper( + deployments.delete_and_poll, + ) @cached_property def logs(self) -> LogsResourceWithRawResponse: @@ -1499,6 +1508,15 @@ def __init__(self, deployments: AsyncDeploymentsResource) -> None: self.stop = async_to_raw_response_wrapper( deployments.stop, ) + self.create_and_poll = async_to_raw_response_wrapper( + deployments.create_and_poll, + ) + self.update_and_poll = async_to_raw_response_wrapper( + deployments.update_and_poll, + ) + self.delete_and_poll = async_to_raw_response_wrapper( + deployments.delete_and_poll, + ) @cached_property def logs(self) -> AsyncLogsResourceWithRawResponse: @@ -1535,6 +1553,15 @@ def __init__(self, deployments: DeploymentsResource) -> None: self.stop = to_streamed_response_wrapper( deployments.stop, ) + self.create_and_poll = to_streamed_response_wrapper( + deployments.create_and_poll, + ) + self.update_and_poll = to_streamed_response_wrapper( + deployments.update_and_poll, + ) + self.delete_and_poll = to_streamed_response_wrapper( + deployments.delete_and_poll, + ) @cached_property def logs(self) -> LogsResourceWithStreamingResponse: @@ -1571,6 +1598,15 @@ def __init__(self, deployments: AsyncDeploymentsResource) -> None: self.stop = async_to_streamed_response_wrapper( deployments.stop, ) + self.create_and_poll = async_to_streamed_response_wrapper( + deployments.create_and_poll, + ) + self.update_and_poll = async_to_streamed_response_wrapper( + deployments.update_and_poll, + ) + self.delete_and_poll = async_to_streamed_response_wrapper( + deployments.delete_and_poll, + ) @cached_property def logs(self) -> AsyncLogsResourceWithStreamingResponse: diff --git a/src/gcore/resources/cloud/instances/images.py b/src/gcore/resources/cloud/instances/images.py index 0932052b..cb32712a 100644 --- a/src/gcore/resources/cloud/instances/images.py +++ b/src/gcore/resources/cloud/instances/images.py @@ -1251,6 +1251,15 @@ def __init__(self, images: ImagesResource) -> None: self.upload = to_raw_response_wrapper( images.upload, ) + self.delete_and_poll = to_raw_response_wrapper( + images.delete_and_poll, + ) + self.create_from_volume_and_poll = to_raw_response_wrapper( + images.create_from_volume_and_poll, + ) + self.upload_and_poll = to_raw_response_wrapper( + images.upload_and_poll, + ) class AsyncImagesResourceWithRawResponse: @@ -1275,6 +1284,15 @@ def __init__(self, images: AsyncImagesResource) -> None: self.upload = async_to_raw_response_wrapper( images.upload, ) + self.delete_and_poll = async_to_raw_response_wrapper( + images.delete_and_poll, + ) + self.create_from_volume_and_poll = async_to_raw_response_wrapper( + images.create_from_volume_and_poll, + ) + self.upload_and_poll = async_to_raw_response_wrapper( + images.upload_and_poll, + ) class ImagesResourceWithStreamingResponse: @@ -1299,6 +1317,15 @@ def __init__(self, images: ImagesResource) -> None: self.upload = to_streamed_response_wrapper( images.upload, ) + self.delete_and_poll = to_streamed_response_wrapper( + images.delete_and_poll, + ) + self.create_from_volume_and_poll = to_streamed_response_wrapper( + images.create_from_volume_and_poll, + ) + self.upload_and_poll = to_streamed_response_wrapper( + images.upload_and_poll, + ) class AsyncImagesResourceWithStreamingResponse: @@ -1323,3 +1350,12 @@ def __init__(self, images: AsyncImagesResource) -> None: self.upload = async_to_streamed_response_wrapper( images.upload, ) + self.delete_and_poll = async_to_streamed_response_wrapper( + images.delete_and_poll, + ) + self.create_from_volume_and_poll = async_to_streamed_response_wrapper( + images.create_from_volume_and_poll, + ) + self.upload_and_poll = async_to_streamed_response_wrapper( + images.upload_and_poll, + ) diff --git a/src/gcore/resources/cloud/instances/instances.py b/src/gcore/resources/cloud/instances/instances.py index 170ad2d9..f26959d7 100644 --- a/src/gcore/resources/cloud/instances/instances.py +++ b/src/gcore/resources/cloud/instances/instances.py @@ -2958,6 +2958,21 @@ def __init__(self, instances: InstancesResource) -> None: self.unassign_security_group = to_raw_response_wrapper( instances.unassign_security_group, ) + self.create_and_poll = to_raw_response_wrapper( + instances.create_and_poll, + ) + self.delete_and_poll = to_raw_response_wrapper( + instances.delete_and_poll, + ) + self.add_to_placement_group_and_poll = to_raw_response_wrapper( + instances.add_to_placement_group_and_poll, + ) + self.remove_from_placement_group_and_poll = to_raw_response_wrapper( + instances.remove_from_placement_group_and_poll, + ) + self.resize_and_poll = to_raw_response_wrapper( + instances.resize_and_poll, + ) @cached_property def flavors(self) -> FlavorsResourceWithRawResponse: @@ -3025,6 +3040,21 @@ def __init__(self, instances: AsyncInstancesResource) -> None: self.unassign_security_group = async_to_raw_response_wrapper( instances.unassign_security_group, ) + self.create_and_poll = async_to_raw_response_wrapper( + instances.create_and_poll, + ) + self.delete_and_poll = async_to_raw_response_wrapper( + instances.delete_and_poll, + ) + self.add_to_placement_group_and_poll = async_to_raw_response_wrapper( + instances.add_to_placement_group_and_poll, + ) + self.remove_from_placement_group_and_poll = async_to_raw_response_wrapper( + instances.remove_from_placement_group_and_poll, + ) + self.resize_and_poll = async_to_raw_response_wrapper( + instances.resize_and_poll, + ) @cached_property def flavors(self) -> AsyncFlavorsResourceWithRawResponse: @@ -3092,6 +3122,21 @@ def __init__(self, instances: InstancesResource) -> None: self.unassign_security_group = to_streamed_response_wrapper( instances.unassign_security_group, ) + self.create_and_poll = to_streamed_response_wrapper( + instances.create_and_poll, + ) + self.delete_and_poll = to_streamed_response_wrapper( + instances.delete_and_poll, + ) + self.add_to_placement_group_and_poll = to_streamed_response_wrapper( + instances.add_to_placement_group_and_poll, + ) + self.remove_from_placement_group_and_poll = to_streamed_response_wrapper( + instances.remove_from_placement_group_and_poll, + ) + self.resize_and_poll = to_streamed_response_wrapper( + instances.resize_and_poll, + ) @cached_property def flavors(self) -> FlavorsResourceWithStreamingResponse: @@ -3159,6 +3204,21 @@ def __init__(self, instances: AsyncInstancesResource) -> None: self.unassign_security_group = async_to_streamed_response_wrapper( instances.unassign_security_group, ) + self.create_and_poll = async_to_streamed_response_wrapper( + instances.create_and_poll, + ) + self.delete_and_poll = async_to_streamed_response_wrapper( + instances.delete_and_poll, + ) + self.add_to_placement_group_and_poll = async_to_streamed_response_wrapper( + instances.add_to_placement_group_and_poll, + ) + self.remove_from_placement_group_and_poll = async_to_streamed_response_wrapper( + instances.remove_from_placement_group_and_poll, + ) + self.resize_and_poll = async_to_streamed_response_wrapper( + instances.resize_and_poll, + ) @cached_property def flavors(self) -> AsyncFlavorsResourceWithStreamingResponse: diff --git a/src/gcore/resources/cloud/load_balancers/l7_policies/l7_policies.py b/src/gcore/resources/cloud/load_balancers/l7_policies/l7_policies.py index 79c839a3..f4149fd3 100644 --- a/src/gcore/resources/cloud/load_balancers/l7_policies/l7_policies.py +++ b/src/gcore/resources/cloud/load_balancers/l7_policies/l7_policies.py @@ -958,6 +958,15 @@ def __init__(self, l7_policies: L7PoliciesResource) -> None: self.replace = to_raw_response_wrapper( l7_policies.replace, ) + self.create_and_poll = to_raw_response_wrapper( + l7_policies.create_and_poll, + ) + self.delete_and_poll = to_raw_response_wrapper( + l7_policies.delete_and_poll, + ) + self.replace_and_poll = to_raw_response_wrapper( + l7_policies.replace_and_poll, + ) @cached_property def rules(self) -> RulesResourceWithRawResponse: @@ -983,6 +992,15 @@ def __init__(self, l7_policies: AsyncL7PoliciesResource) -> None: self.replace = async_to_raw_response_wrapper( l7_policies.replace, ) + self.create_and_poll = async_to_raw_response_wrapper( + l7_policies.create_and_poll, + ) + self.delete_and_poll = async_to_raw_response_wrapper( + l7_policies.delete_and_poll, + ) + self.replace_and_poll = async_to_raw_response_wrapper( + l7_policies.replace_and_poll, + ) @cached_property def rules(self) -> AsyncRulesResourceWithRawResponse: @@ -1008,6 +1026,15 @@ def __init__(self, l7_policies: L7PoliciesResource) -> None: self.replace = to_streamed_response_wrapper( l7_policies.replace, ) + self.create_and_poll = to_streamed_response_wrapper( + l7_policies.create_and_poll, + ) + self.delete_and_poll = to_streamed_response_wrapper( + l7_policies.delete_and_poll, + ) + self.replace_and_poll = to_streamed_response_wrapper( + l7_policies.replace_and_poll, + ) @cached_property def rules(self) -> RulesResourceWithStreamingResponse: @@ -1033,6 +1060,15 @@ def __init__(self, l7_policies: AsyncL7PoliciesResource) -> None: self.replace = async_to_streamed_response_wrapper( l7_policies.replace, ) + self.create_and_poll = async_to_streamed_response_wrapper( + l7_policies.create_and_poll, + ) + self.delete_and_poll = async_to_streamed_response_wrapper( + l7_policies.delete_and_poll, + ) + self.replace_and_poll = async_to_streamed_response_wrapper( + l7_policies.replace_and_poll, + ) @cached_property def rules(self) -> AsyncRulesResourceWithStreamingResponse: diff --git a/src/gcore/resources/cloud/load_balancers/l7_policies/rules.py b/src/gcore/resources/cloud/load_balancers/l7_policies/rules.py index c6a33549..844068db 100644 --- a/src/gcore/resources/cloud/load_balancers/l7_policies/rules.py +++ b/src/gcore/resources/cloud/load_balancers/l7_policies/rules.py @@ -994,6 +994,15 @@ def __init__(self, rules: RulesResource) -> None: self.replace = to_raw_response_wrapper( rules.replace, ) + self.create_and_poll = to_raw_response_wrapper( + rules.create_and_poll, + ) + self.delete_and_poll = to_raw_response_wrapper( + rules.delete_and_poll, + ) + self.replace_and_poll = to_raw_response_wrapper( + rules.replace_and_poll, + ) class AsyncRulesResourceWithRawResponse: @@ -1015,6 +1024,15 @@ def __init__(self, rules: AsyncRulesResource) -> None: self.replace = async_to_raw_response_wrapper( rules.replace, ) + self.create_and_poll = async_to_raw_response_wrapper( + rules.create_and_poll, + ) + self.delete_and_poll = async_to_raw_response_wrapper( + rules.delete_and_poll, + ) + self.replace_and_poll = async_to_raw_response_wrapper( + rules.replace_and_poll, + ) class RulesResourceWithStreamingResponse: @@ -1036,6 +1054,15 @@ def __init__(self, rules: RulesResource) -> None: self.replace = to_streamed_response_wrapper( rules.replace, ) + self.create_and_poll = to_streamed_response_wrapper( + rules.create_and_poll, + ) + self.delete_and_poll = to_streamed_response_wrapper( + rules.delete_and_poll, + ) + self.replace_and_poll = to_streamed_response_wrapper( + rules.replace_and_poll, + ) class AsyncRulesResourceWithStreamingResponse: @@ -1057,3 +1084,12 @@ def __init__(self, rules: AsyncRulesResource) -> None: self.replace = async_to_streamed_response_wrapper( rules.replace, ) + self.create_and_poll = async_to_streamed_response_wrapper( + rules.create_and_poll, + ) + self.delete_and_poll = async_to_streamed_response_wrapper( + rules.delete_and_poll, + ) + self.replace_and_poll = async_to_streamed_response_wrapper( + rules.replace_and_poll, + ) diff --git a/src/gcore/resources/cloud/load_balancers/listeners.py b/src/gcore/resources/cloud/load_balancers/listeners.py index 0a831988..1e8c89e0 100644 --- a/src/gcore/resources/cloud/load_balancers/listeners.py +++ b/src/gcore/resources/cloud/load_balancers/listeners.py @@ -23,6 +23,7 @@ listener_get_params, listener_list_params, listener_create_params, + listener_delete_params, listener_update_params, ) from ....types.cloud.lb_listener_protocol import LbListenerProtocol @@ -95,7 +96,8 @@ def create( allowed_cidrs: Network CIDRs from which service will be accessible - connection_limit: Limit of the simultaneous connections + connection_limit: Limit of the simultaneous connections. If -1 is provided, it is translated to + the default value 100000. insert_x_forwarded: Add headers X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto to requests. Only used with HTTP or `TERMINATED_HTTPS` protocols. @@ -186,7 +188,8 @@ def update( allowed_cidrs: Network CIDRs from which service will be accessible - connection_limit: Limit of simultaneous connections + connection_limit: Limit of simultaneous connections. If -1 is provided, it is translated to the + default value 100000. name: Load balancer listener name @@ -302,6 +305,7 @@ def delete( *, project_id: int | None = None, region_id: int | None = None, + delete_default_pool: bool | 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, @@ -319,6 +323,8 @@ def delete( listener_id: Listener ID + delete_default_pool: Delete default pool attached directly to the listener. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -336,7 +342,13 @@ def delete( return self._delete( f"/cloud/v1/lblisteners/{project_id}/{region_id}/{listener_id}", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + {"delete_default_pool": delete_default_pool}, listener_delete_params.ListenerDeleteParams + ), ), cast_to=TaskIDList, ) @@ -624,7 +636,8 @@ async def create( allowed_cidrs: Network CIDRs from which service will be accessible - connection_limit: Limit of the simultaneous connections + connection_limit: Limit of the simultaneous connections. If -1 is provided, it is translated to + the default value 100000. insert_x_forwarded: Add headers X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto to requests. Only used with HTTP or `TERMINATED_HTTPS` protocols. @@ -715,7 +728,8 @@ async def update( allowed_cidrs: Network CIDRs from which service will be accessible - connection_limit: Limit of simultaneous connections + connection_limit: Limit of simultaneous connections. If -1 is provided, it is translated to the + default value 100000. name: Load balancer listener name @@ -831,6 +845,7 @@ async def delete( *, project_id: int | None = None, region_id: int | None = None, + delete_default_pool: bool | 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, @@ -848,6 +863,8 @@ async def delete( listener_id: Listener ID + delete_default_pool: Delete default pool attached directly to the listener. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -865,7 +882,13 @@ async def delete( return await self._delete( f"/cloud/v1/lblisteners/{project_id}/{region_id}/{listener_id}", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"delete_default_pool": delete_default_pool}, listener_delete_params.ListenerDeleteParams + ), ), cast_to=TaskIDList, ) @@ -1109,6 +1132,15 @@ def __init__(self, listeners: ListenersResource) -> None: self.get = to_raw_response_wrapper( listeners.get, ) + self.create_and_poll = to_raw_response_wrapper( + listeners.create_and_poll, + ) + self.delete_and_poll = to_raw_response_wrapper( + listeners.delete_and_poll, + ) + self.update_and_poll = to_raw_response_wrapper( + listeners.update_and_poll, + ) class AsyncListenersResourceWithRawResponse: @@ -1130,6 +1162,15 @@ def __init__(self, listeners: AsyncListenersResource) -> None: self.get = async_to_raw_response_wrapper( listeners.get, ) + self.create_and_poll = async_to_raw_response_wrapper( + listeners.create_and_poll, + ) + self.delete_and_poll = async_to_raw_response_wrapper( + listeners.delete_and_poll, + ) + self.update_and_poll = async_to_raw_response_wrapper( + listeners.update_and_poll, + ) class ListenersResourceWithStreamingResponse: @@ -1151,6 +1192,15 @@ def __init__(self, listeners: ListenersResource) -> None: self.get = to_streamed_response_wrapper( listeners.get, ) + self.create_and_poll = to_streamed_response_wrapper( + listeners.create_and_poll, + ) + self.delete_and_poll = to_streamed_response_wrapper( + listeners.delete_and_poll, + ) + self.update_and_poll = to_streamed_response_wrapper( + listeners.update_and_poll, + ) class AsyncListenersResourceWithStreamingResponse: @@ -1172,3 +1222,12 @@ def __init__(self, listeners: AsyncListenersResource) -> None: self.get = async_to_streamed_response_wrapper( listeners.get, ) + self.create_and_poll = async_to_streamed_response_wrapper( + listeners.create_and_poll, + ) + self.delete_and_poll = async_to_streamed_response_wrapper( + listeners.delete_and_poll, + ) + self.update_and_poll = async_to_streamed_response_wrapper( + listeners.update_and_poll, + ) diff --git a/src/gcore/resources/cloud/load_balancers/load_balancers.py b/src/gcore/resources/cloud/load_balancers/load_balancers.py index 905aef54..3a9dcf02 100644 --- a/src/gcore/resources/cloud/load_balancers/load_balancers.py +++ b/src/gcore/resources/cloud/load_balancers/load_balancers.py @@ -1498,6 +1498,18 @@ def __init__(self, load_balancers: LoadBalancersResource) -> None: self.resize = to_raw_response_wrapper( load_balancers.resize, ) + self.create_and_poll = to_raw_response_wrapper( + load_balancers.create_and_poll, + ) + self.delete_and_poll = to_raw_response_wrapper( + load_balancers.delete_and_poll, + ) + self.failover_and_poll = to_raw_response_wrapper( + load_balancers.failover_and_poll, + ) + self.resize_and_poll = to_raw_response_wrapper( + load_balancers.resize_and_poll, + ) @cached_property def l7_policies(self) -> L7PoliciesResourceWithRawResponse: @@ -1549,6 +1561,18 @@ def __init__(self, load_balancers: AsyncLoadBalancersResource) -> None: self.resize = async_to_raw_response_wrapper( load_balancers.resize, ) + self.create_and_poll = async_to_raw_response_wrapper( + load_balancers.create_and_poll, + ) + self.delete_and_poll = async_to_raw_response_wrapper( + load_balancers.delete_and_poll, + ) + self.failover_and_poll = async_to_raw_response_wrapper( + load_balancers.failover_and_poll, + ) + self.resize_and_poll = async_to_raw_response_wrapper( + load_balancers.resize_and_poll, + ) @cached_property def l7_policies(self) -> AsyncL7PoliciesResourceWithRawResponse: @@ -1600,6 +1624,18 @@ def __init__(self, load_balancers: LoadBalancersResource) -> None: self.resize = to_streamed_response_wrapper( load_balancers.resize, ) + self.create_and_poll = to_streamed_response_wrapper( + load_balancers.create_and_poll, + ) + self.delete_and_poll = to_streamed_response_wrapper( + load_balancers.delete_and_poll, + ) + self.failover_and_poll = to_streamed_response_wrapper( + load_balancers.failover_and_poll, + ) + self.resize_and_poll = to_streamed_response_wrapper( + load_balancers.resize_and_poll, + ) @cached_property def l7_policies(self) -> L7PoliciesResourceWithStreamingResponse: @@ -1651,6 +1687,18 @@ def __init__(self, load_balancers: AsyncLoadBalancersResource) -> None: self.resize = async_to_streamed_response_wrapper( load_balancers.resize, ) + self.create_and_poll = async_to_streamed_response_wrapper( + load_balancers.create_and_poll, + ) + self.delete_and_poll = async_to_streamed_response_wrapper( + load_balancers.delete_and_poll, + ) + self.failover_and_poll = async_to_streamed_response_wrapper( + load_balancers.failover_and_poll, + ) + self.resize_and_poll = async_to_streamed_response_wrapper( + load_balancers.resize_and_poll, + ) @cached_property def l7_policies(self) -> AsyncL7PoliciesResourceWithStreamingResponse: diff --git a/src/gcore/resources/cloud/load_balancers/pools/pools.py b/src/gcore/resources/cloud/load_balancers/pools/pools.py index 3d61764f..121406f7 100644 --- a/src/gcore/resources/cloud/load_balancers/pools/pools.py +++ b/src/gcore/resources/cloud/load_balancers/pools/pools.py @@ -85,7 +85,7 @@ def create( healthmonitor: Optional[pool_create_params.Healthmonitor] | Omit = omit, listener_id: Optional[str] | Omit = omit, load_balancer_id: Optional[str] | Omit = omit, - members: Optional[Iterable[pool_create_params.Member]] | Omit = omit, + members: Iterable[pool_create_params.Member] | Omit = omit, secret_id: Optional[str] | Omit = omit, session_persistence: Optional[pool_create_params.SessionPersistence] | Omit = omit, timeout_client_data: Optional[int] | Omit = omit, @@ -452,7 +452,7 @@ def create_and_poll( healthmonitor: Optional[pool_create_params.Healthmonitor] | Omit = omit, listener_id: Optional[str] | Omit = omit, load_balancer_id: Optional[str] | Omit = omit, - members: Optional[Iterable[pool_create_params.Member]] | Omit = omit, + members: Iterable[pool_create_params.Member] | Omit = omit, secret_id: Optional[str] | Omit = omit, session_persistence: Optional[pool_create_params.SessionPersistence] | Omit = omit, timeout_client_data: Optional[int] | Omit = omit, @@ -652,7 +652,7 @@ async def create( healthmonitor: Optional[pool_create_params.Healthmonitor] | Omit = omit, listener_id: Optional[str] | Omit = omit, load_balancer_id: Optional[str] | Omit = omit, - members: Optional[Iterable[pool_create_params.Member]] | Omit = omit, + members: Iterable[pool_create_params.Member] | Omit = omit, secret_id: Optional[str] | Omit = omit, session_persistence: Optional[pool_create_params.SessionPersistence] | Omit = omit, timeout_client_data: Optional[int] | Omit = omit, @@ -1019,7 +1019,7 @@ async def create_and_poll( healthmonitor: Optional[pool_create_params.Healthmonitor] | Omit = omit, listener_id: Optional[str] | Omit = omit, load_balancer_id: Optional[str] | Omit = omit, - members: Optional[Iterable[pool_create_params.Member]] | Omit = omit, + members: Iterable[pool_create_params.Member] | Omit = omit, secret_id: Optional[str] | Omit = omit, session_persistence: Optional[pool_create_params.SessionPersistence] | Omit = omit, timeout_client_data: Optional[int] | Omit = omit, @@ -1197,6 +1197,15 @@ def __init__(self, pools: PoolsResource) -> None: self.get = to_raw_response_wrapper( pools.get, ) + self.create_and_poll = to_raw_response_wrapper( + pools.create_and_poll, + ) + self.delete_and_poll = to_raw_response_wrapper( + pools.delete_and_poll, + ) + self.update_and_poll = to_raw_response_wrapper( + pools.update_and_poll, + ) @cached_property def health_monitors(self) -> HealthMonitorsResourceWithRawResponse: @@ -1226,6 +1235,15 @@ def __init__(self, pools: AsyncPoolsResource) -> None: self.get = async_to_raw_response_wrapper( pools.get, ) + self.create_and_poll = async_to_raw_response_wrapper( + pools.create_and_poll, + ) + self.delete_and_poll = async_to_raw_response_wrapper( + pools.delete_and_poll, + ) + self.update_and_poll = async_to_raw_response_wrapper( + pools.update_and_poll, + ) @cached_property def health_monitors(self) -> AsyncHealthMonitorsResourceWithRawResponse: @@ -1255,6 +1273,15 @@ def __init__(self, pools: PoolsResource) -> None: self.get = to_streamed_response_wrapper( pools.get, ) + self.create_and_poll = to_streamed_response_wrapper( + pools.create_and_poll, + ) + self.delete_and_poll = to_streamed_response_wrapper( + pools.delete_and_poll, + ) + self.update_and_poll = to_streamed_response_wrapper( + pools.update_and_poll, + ) @cached_property def health_monitors(self) -> HealthMonitorsResourceWithStreamingResponse: @@ -1284,6 +1311,15 @@ def __init__(self, pools: AsyncPoolsResource) -> None: self.get = async_to_streamed_response_wrapper( pools.get, ) + self.create_and_poll = async_to_streamed_response_wrapper( + pools.create_and_poll, + ) + self.delete_and_poll = async_to_streamed_response_wrapper( + pools.delete_and_poll, + ) + self.update_and_poll = async_to_streamed_response_wrapper( + pools.update_and_poll, + ) @cached_property def health_monitors(self) -> AsyncHealthMonitorsResourceWithStreamingResponse: diff --git a/src/gcore/resources/cloud/projects.py b/src/gcore/resources/cloud/projects.py index 2e5ae929..ad5381ec 100644 --- a/src/gcore/resources/cloud/projects.py +++ b/src/gcore/resources/cloud/projects.py @@ -50,9 +50,7 @@ def create( self, *, name: str, - client_id: Optional[int] | Omit = omit, description: Optional[str] | Omit = omit, - state: Optional[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, @@ -68,12 +66,8 @@ def create( Args: name: Unique project name for a client. Each client always has one "default" project. - client_id: ID associated with the client. - description: Description of the project. - state: State of the project. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -87,9 +81,7 @@ def create( body=maybe_transform( { "name": name, - "client_id": client_id, "description": description, - "state": state, }, project_create_params.ProjectCreateParams, ), @@ -112,10 +104,8 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: - """Update project name and description. - - Project management must be enabled to - perform this operation. + """ + Update project name and description. Args: name: Name of the entity, following a specific format. @@ -306,9 +296,7 @@ async def create( self, *, name: str, - client_id: Optional[int] | Omit = omit, description: Optional[str] | Omit = omit, - state: Optional[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, @@ -324,12 +312,8 @@ async def create( Args: name: Unique project name for a client. Each client always has one "default" project. - client_id: ID associated with the client. - description: Description of the project. - state: State of the project. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -343,9 +327,7 @@ async def create( body=await async_maybe_transform( { "name": name, - "client_id": client_id, "description": description, - "state": state, }, project_create_params.ProjectCreateParams, ), @@ -368,10 +350,8 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Project: - """Update project name and description. - - Project management must be enabled to - perform this operation. + """ + Update project name and description. Args: name: Name of the entity, following a specific format. diff --git a/src/gcore/resources/cloud/quotas/requests.py b/src/gcore/resources/cloud/quotas/requests.py index 6857110a..5d778e27 100644 --- a/src/gcore/resources/cloud/quotas/requests.py +++ b/src/gcore/resources/cloud/quotas/requests.py @@ -51,7 +51,6 @@ def create( *, description: str, requested_limits: request_create_params.RequestedLimits, - client_id: int | 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, @@ -67,8 +66,6 @@ def create( requested_limits: Limits you want to increase. - client_id: Client ID that requests the limit increase. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -84,7 +81,6 @@ def create( { "description": description, "requested_limits": requested_limits, - "client_id": client_id, }, request_create_params.RequestCreateParams, ), @@ -239,7 +235,6 @@ async def create( *, description: str, requested_limits: request_create_params.RequestedLimits, - client_id: int | 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, @@ -255,8 +250,6 @@ async def create( requested_limits: Limits you want to increase. - client_id: Client ID that requests the limit increase. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -272,7 +265,6 @@ async def create( { "description": description, "requested_limits": requested_limits, - "client_id": client_id, }, request_create_params.RequestCreateParams, ), diff --git a/src/gcore/resources/cloud/secrets.py b/src/gcore/resources/cloud/secrets.py index 9a6fed1d..0e506c6d 100644 --- a/src/gcore/resources/cloud/secrets.py +++ b/src/gcore/resources/cloud/secrets.py @@ -580,6 +580,9 @@ def __init__(self, secrets: SecretsResource) -> None: self.upload_tls_certificate = to_raw_response_wrapper( secrets.upload_tls_certificate, ) + self.upload_tls_certificate_and_poll = to_raw_response_wrapper( + secrets.upload_tls_certificate_and_poll, + ) class AsyncSecretsResourceWithRawResponse: @@ -598,6 +601,9 @@ def __init__(self, secrets: AsyncSecretsResource) -> None: self.upload_tls_certificate = async_to_raw_response_wrapper( secrets.upload_tls_certificate, ) + self.upload_tls_certificate_and_poll = async_to_raw_response_wrapper( + secrets.upload_tls_certificate_and_poll, + ) class SecretsResourceWithStreamingResponse: @@ -616,6 +622,9 @@ def __init__(self, secrets: SecretsResource) -> None: self.upload_tls_certificate = to_streamed_response_wrapper( secrets.upload_tls_certificate, ) + self.upload_tls_certificate_and_poll = to_streamed_response_wrapper( + secrets.upload_tls_certificate_and_poll, + ) class AsyncSecretsResourceWithStreamingResponse: @@ -634,3 +643,6 @@ def __init__(self, secrets: AsyncSecretsResource) -> None: self.upload_tls_certificate = async_to_streamed_response_wrapper( secrets.upload_tls_certificate, ) + self.upload_tls_certificate_and_poll = async_to_streamed_response_wrapper( + secrets.upload_tls_certificate_and_poll, + ) diff --git a/src/gcore/types/cdn/__init__.py b/src/gcore/types/cdn/__init__.py index ebb15cf3..8cd6fefc 100644 --- a/src/gcore/types/cdn/__init__.py +++ b/src/gcore/types/cdn/__init__.py @@ -30,6 +30,7 @@ from .cdn_audit_log_entry import CdnAuditLogEntry as CdnAuditLogEntry from .log_download_params import LogDownloadParams as LogDownloadParams from .public_network_list import PublicNetworkList as PublicNetworkList +from .ip_range_list_params import IPRangeListParams as IPRangeListParams from .resource_list_params import ResourceListParams as ResourceListParams from .resource_usage_stats import ResourceUsageStats as ResourceUsageStats from .shield_list_response import ShieldListResponse as ShieldListResponse @@ -42,6 +43,7 @@ from .certificate_list_params import CertificateListParams as CertificateListParams from .resource_replace_params import ResourceReplaceParams as ResourceReplaceParams from .shield_aggregated_stats import ShieldAggregatedStats as ShieldAggregatedStats +from .ip_range_list_ips_params import IPRangeListIPsParams as IPRangeListIPsParams from .logs_uploader_validation import LogsUploaderValidation as LogsUploaderValidation from .origin_group_list_params import OriginGroupListParams as OriginGroupListParams from .resource_prefetch_params import ResourcePrefetchParams as ResourcePrefetchParams diff --git a/src/gcore/types/cdn/cdn_resource.py b/src/gcore/types/cdn/cdn_resource.py index dd05e44f..007d4be8 100644 --- a/src/gcore/types/cdn/cdn_resource.py +++ b/src/gcore/types/cdn/cdn_resource.py @@ -759,7 +759,10 @@ class OptionsProxyConnectTimeout(BaseModel): """ value: str - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(BaseModel): @@ -773,7 +776,10 @@ class OptionsProxyReadTimeout(BaseModel): """ value: str - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(BaseModel): diff --git a/src/gcore/types/cdn/ip_range_list_ips_params.py b/src/gcore/types/cdn/ip_range_list_ips_params.py new file mode 100644 index 00000000..f10f642c --- /dev/null +++ b/src/gcore/types/cdn/ip_range_list_ips_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["IPRangeListIPsParams"] + + +class IPRangeListIPsParams(TypedDict, total=False): + format: Literal["json", "plain"] + """ + Optional format override. When set, this takes precedence over the `Accept` + header. + """ + + accept: Annotated[Literal["application/json", "text/plain"], PropertyInfo(alias="Accept")] diff --git a/src/gcore/types/cdn/ip_range_list_params.py b/src/gcore/types/cdn/ip_range_list_params.py new file mode 100644 index 00000000..2de60645 --- /dev/null +++ b/src/gcore/types/cdn/ip_range_list_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["IPRangeListParams"] + + +class IPRangeListParams(TypedDict, total=False): + format: Literal["json", "plain"] + """ + Optional format override. When set, this takes precedence over the `Accept` + header. + """ + + accept: Annotated[Literal["application/json", "text/plain"], PropertyInfo(alias="Accept")] diff --git a/src/gcore/types/cdn/resource_create_params.py b/src/gcore/types/cdn/resource_create_params.py index f31367c0..ce9dad10 100644 --- a/src/gcore/types/cdn/resource_create_params.py +++ b/src/gcore/types/cdn/resource_create_params.py @@ -882,7 +882,10 @@ class OptionsProxyConnectTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(TypedDict, total=False): @@ -896,7 +899,10 @@ class OptionsProxyReadTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(TypedDict, total=False): diff --git a/src/gcore/types/cdn/resource_replace_params.py b/src/gcore/types/cdn/resource_replace_params.py index 717114a4..58e21ac4 100644 --- a/src/gcore/types/cdn/resource_replace_params.py +++ b/src/gcore/types/cdn/resource_replace_params.py @@ -860,7 +860,10 @@ class OptionsProxyConnectTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(TypedDict, total=False): @@ -874,7 +877,10 @@ class OptionsProxyReadTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(TypedDict, total=False): diff --git a/src/gcore/types/cdn/resource_update_params.py b/src/gcore/types/cdn/resource_update_params.py index d980ad8c..a382bda2 100644 --- a/src/gcore/types/cdn/resource_update_params.py +++ b/src/gcore/types/cdn/resource_update_params.py @@ -851,7 +851,10 @@ class OptionsProxyConnectTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(TypedDict, total=False): @@ -865,7 +868,10 @@ class OptionsProxyReadTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(TypedDict, total=False): diff --git a/src/gcore/types/cdn/resource_usage_stats.py b/src/gcore/types/cdn/resource_usage_stats.py index 7a6f6255..93e1fea7 100644 --- a/src/gcore/types/cdn/resource_usage_stats.py +++ b/src/gcore/types/cdn/resource_usage_stats.py @@ -28,7 +28,7 @@ class ResourceUsageStats(BaseModel): Possible values: - **`upstream_bytes`** – Traffic in bytes from an origin server to CDN servers - or to origin shielding, if used. + or to origin shielding when used. - **`sent_bytes`** – Traffic in bytes from CDN servers to clients. - **`shield_bytes`** – Traffic in bytes from origin shielding to CDN servers. - **`backblaze_bytes`** - Traffic in bytes from Backblaze origin. @@ -45,39 +45,40 @@ class ResourceUsageStats(BaseModel): - **`response_types`** – Statistics by content type. It returns a number of responses for content with different MIME types. - **`cache_hit_traffic_ratio`** – Formula: 1 - `upstream_bytes` / `sent_bytes`. - We deduct the non-cached traffic from the total traffic value. - - **`cache_hit_requests_ratio`** – Share of sending cached content. Formula: - `responses_hit` / requests. - - **`shield_traffic_ratio`** – Origin shielding efficiency: how much more - traffic is sent from the origin shielding than from the origin. Formula: - (`shield_bytes` - `upstream_bytes`) / `shield_bytes`. + We deduct the non-cached traffic from the total traffic amount. + - **`cache_hit_requests_ratio`** – Formula: `responses_hit` / requests. The + share of sending cached content. + - **`shield_traffic_ratio`** – Formula: (`shield_bytes` - `upstream_bytes`) / + `shield_bytes`. The efficiency of the Origin Shielding: how much more traffic + is sent from the Origin Shielding than from the origin. - **`image_processed`** - Number of images transformed on the Image optimization service. - **`request_time`** - Time elapsed between the first bytes of a request were processed and logging after the last bytes were sent to a user. - **`upstream_response_time`** - Number of milliseconds it took to receive a response from an origin. If upstream `response_time_` contains several - indications for one request (when there is more than one origin,) we summarize - them. When aggregating several queries, the average is calculated. + indications for one request (in case of more than 1 origin), we summarize + them. In case of aggregating several queries, the average of this amount is + calculated. Metrics **`upstream_response_time`** and **`request_time`** should be requested separately from other metrics """ region: Optional[object] = None - """Locations (regions) by which the data is grouped. + """Regions for which data is displayed. Possible values: + - **na** – North America + - **eu** – Europe + - **cis** – Commonwealth of Independent States - **asia** – Asia - **au** – Australia - - **cis** – CIS (Commonwealth of Independent States) - - **eu** – Europe - **latam** – Latin America - **me** – Middle East - - **na** – North America - - **africa** – Africa - - **sa** – South America + - **africa** - Africa + - **sa** - South America """ resource: Optional[object] = None diff --git a/src/gcore/types/cdn/resources/cdn_resource_rule.py b/src/gcore/types/cdn/resources/cdn_resource_rule.py index 28dc2ebf..8f66f00c 100644 --- a/src/gcore/types/cdn/resources/cdn_resource_rule.py +++ b/src/gcore/types/cdn/resources/cdn_resource_rule.py @@ -736,7 +736,10 @@ class OptionsProxyConnectTimeout(BaseModel): """ value: str - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(BaseModel): @@ -750,7 +753,10 @@ class OptionsProxyReadTimeout(BaseModel): """ value: str - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(BaseModel): diff --git a/src/gcore/types/cdn/resources/rule_create_params.py b/src/gcore/types/cdn/resources/rule_create_params.py index 6c8ab837..4d80f7c6 100644 --- a/src/gcore/types/cdn/resources/rule_create_params.py +++ b/src/gcore/types/cdn/resources/rule_create_params.py @@ -812,7 +812,10 @@ class OptionsProxyConnectTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(TypedDict, total=False): @@ -826,7 +829,10 @@ class OptionsProxyReadTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(TypedDict, total=False): diff --git a/src/gcore/types/cdn/resources/rule_replace_params.py b/src/gcore/types/cdn/resources/rule_replace_params.py index 6eb3eddc..c6bf65cc 100644 --- a/src/gcore/types/cdn/resources/rule_replace_params.py +++ b/src/gcore/types/cdn/resources/rule_replace_params.py @@ -814,7 +814,10 @@ class OptionsProxyConnectTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(TypedDict, total=False): @@ -828,7 +831,10 @@ class OptionsProxyReadTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(TypedDict, total=False): diff --git a/src/gcore/types/cdn/resources/rule_update_params.py b/src/gcore/types/cdn/resources/rule_update_params.py index 154c4cef..e04e0c93 100644 --- a/src/gcore/types/cdn/resources/rule_update_params.py +++ b/src/gcore/types/cdn/resources/rule_update_params.py @@ -814,7 +814,10 @@ class OptionsProxyConnectTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(TypedDict, total=False): @@ -828,7 +831,10 @@ class OptionsProxyReadTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(TypedDict, total=False): diff --git a/src/gcore/types/cdn/rule_template.py b/src/gcore/types/cdn/rule_template.py index 6d73d4f4..1d7b8693 100644 --- a/src/gcore/types/cdn/rule_template.py +++ b/src/gcore/types/cdn/rule_template.py @@ -736,7 +736,10 @@ class OptionsProxyConnectTimeout(BaseModel): """ value: str - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(BaseModel): @@ -750,7 +753,10 @@ class OptionsProxyReadTimeout(BaseModel): """ value: str - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(BaseModel): diff --git a/src/gcore/types/cdn/rule_template_create_params.py b/src/gcore/types/cdn/rule_template_create_params.py index a0e9ea73..30d52eba 100644 --- a/src/gcore/types/cdn/rule_template_create_params.py +++ b/src/gcore/types/cdn/rule_template_create_params.py @@ -796,7 +796,10 @@ class OptionsProxyConnectTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(TypedDict, total=False): @@ -810,7 +813,10 @@ class OptionsProxyReadTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(TypedDict, total=False): diff --git a/src/gcore/types/cdn/rule_template_replace_params.py b/src/gcore/types/cdn/rule_template_replace_params.py index 683bd306..ccb47c56 100644 --- a/src/gcore/types/cdn/rule_template_replace_params.py +++ b/src/gcore/types/cdn/rule_template_replace_params.py @@ -796,7 +796,10 @@ class OptionsProxyConnectTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(TypedDict, total=False): @@ -810,7 +813,10 @@ class OptionsProxyReadTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(TypedDict, total=False): diff --git a/src/gcore/types/cdn/rule_template_update_params.py b/src/gcore/types/cdn/rule_template_update_params.py index c1e77142..2be5eb7e 100644 --- a/src/gcore/types/cdn/rule_template_update_params.py +++ b/src/gcore/types/cdn/rule_template_update_params.py @@ -796,7 +796,10 @@ class OptionsProxyConnectTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 5s**. + """ class OptionsProxyReadTimeout(TypedDict, total=False): @@ -810,7 +813,10 @@ class OptionsProxyReadTimeout(TypedDict, total=False): """ value: Required[str] - """Timeout value in seconds.""" + """Timeout value in seconds. + + Supported range: **1s - 30s**. + """ class OptionsQueryParamsBlacklist(TypedDict, total=False): diff --git a/src/gcore/types/cdn/statistic_get_logs_usage_aggregated_params.py b/src/gcore/types/cdn/statistic_get_logs_usage_aggregated_params.py index a1a50799..e5dff95c 100644 --- a/src/gcore/types/cdn/statistic_get_logs_usage_aggregated_params.py +++ b/src/gcore/types/cdn/statistic_get_logs_usage_aggregated_params.py @@ -17,7 +17,7 @@ class StatisticGetLogsUsageAggregatedParams(TypedDict, total=False): """End of the requested time period (ISO 8601/RFC 3339 format, UTC.)""" flat: bool - """The waу parameters are arranged in the response. + """The way the parameters are arranged in the response. Possible values: @@ -39,4 +39,7 @@ class StatisticGetLogsUsageAggregatedParams(TypedDict, total=False): To request multiple values, use: - &resource=1&resource=2 + + If CDN resource ID is not specified, data related to all CDN resources is + returned. """ diff --git a/src/gcore/types/cdn/statistic_get_logs_usage_series_params.py b/src/gcore/types/cdn/statistic_get_logs_usage_series_params.py index 634f818e..400835af 100644 --- a/src/gcore/types/cdn/statistic_get_logs_usage_series_params.py +++ b/src/gcore/types/cdn/statistic_get_logs_usage_series_params.py @@ -11,20 +11,10 @@ class StatisticGetLogsUsageSeriesParams(TypedDict, total=False): from_: Required[Annotated[str, PropertyInfo(alias="from")]] - """Beginning of the requested time period (ISO 8601/RFC 3339 format, UTC.) - - Example: - - - &from=2020-01-01T00:00:00.000 - """ + """Beginning of the requested time period (ISO 8601/RFC 3339 format, UTC.)""" to: Required[str] - """End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - - Example: - - - &from=2020-01-01T00:00:00.000 - """ + """End of the requested time period (ISO 8601/RFC 3339 format, UTC.)""" resource: int """CDN resources IDs by that statistics data is grouped. @@ -32,4 +22,7 @@ class StatisticGetLogsUsageSeriesParams(TypedDict, total=False): To request multiple values, use: - &resource=1&resource=2 + + If CDN resource ID is not specified, data related to all CDN resources is + returned. """ diff --git a/src/gcore/types/cdn/statistic_get_resource_usage_aggregated_params.py b/src/gcore/types/cdn/statistic_get_resource_usage_aggregated_params.py index 9518ebe1..ccf15dac 100644 --- a/src/gcore/types/cdn/statistic_get_resource_usage_aggregated_params.py +++ b/src/gcore/types/cdn/statistic_get_resource_usage_aggregated_params.py @@ -11,13 +11,7 @@ class StatisticGetResourceUsageAggregatedParams(TypedDict, total=False): from_: Required[Annotated[str, PropertyInfo(alias="from")]] - """Beginning of the requested time period (ISO 8601/RFC 3339 format, UTC.) - - Examples: - - - &from=2018-11-01T00:00:00.000 - - &from=2018-11-01 - """ + """Beginning of the requested time period (ISO 8601/RFC 3339 format, UTC.)""" metrics: Required[str] """Types of statistics data. @@ -78,19 +72,12 @@ class StatisticGetResourceUsageAggregatedParams(TypedDict, total=False): """ to: Required[str] - """End of the requested time period (ISO 8601/RFC 3339 format, UTC.) - - Examples: - - - &to=2018-11-01T00:00:00.000 - - &to=2018-11-01 - """ + """End of the requested time period (ISO 8601/RFC 3339 format, UTC.)""" countries: str - """Names of countries for which data is displayed. - - English short name from [ISO 3166 standard][1] without the definite article - "the" should be used. + """ + Names of countries for which data should be displayed. English short name from + [ISO 3166 standard][1] without the definite article ("the") should be used. [1]: https://www.iso.org/obp/ui/#search/code/ @@ -100,7 +87,7 @@ class StatisticGetResourceUsageAggregatedParams(TypedDict, total=False): """ flat: bool - """The waу the parameters are arranged in the response. + """The way the parameters are arranged in the response. Possible values: @@ -116,7 +103,9 @@ class StatisticGetResourceUsageAggregatedParams(TypedDict, total=False): - **resource** – Data is grouped by CDN resources IDs. - **region** – Data is grouped by regions of CDN edge servers. - **country** – Data is grouped by countries of CDN edge servers. - - **vhost** – Data is grouped by resources CNAME. + - **vhost** – Data is grouped by resources CNAMEs. + - **`client_country`** - Data is grouped by countries, based on end-users' + location. To request multiple values, use: @@ -140,7 +129,7 @@ class StatisticGetResourceUsageAggregatedParams(TypedDict, total=False): """ resource: int - """CDN resources IDs by which statistics data is grouped. + """CDN resources IDs by that statistics data is grouped. To request multiple values, use: diff --git a/src/gcore/types/cdn/statistic_get_resource_usage_series_params.py b/src/gcore/types/cdn/statistic_get_resource_usage_series_params.py index e830094f..27b963f5 100644 --- a/src/gcore/types/cdn/statistic_get_resource_usage_series_params.py +++ b/src/gcore/types/cdn/statistic_get_resource_usage_series_params.py @@ -100,6 +100,8 @@ class StatisticGetResourceUsageSeriesParams(TypedDict, total=False): - **region** – Data is grouped by regions of CDN edge servers. - **country** – Data is grouped by countries of CDN edge servers. - **vhost** – Data is grouped by resources CNAMEs. + - **`client_country`** - Data is grouped by countries, based on end-users' + location. To request multiple values, use: @@ -123,9 +125,12 @@ class StatisticGetResourceUsageSeriesParams(TypedDict, total=False): """ resource: int - """CDN resource IDs. + """CDN resources IDs by that statistics data is grouped. To request multiple values, use: - &resource=1&resource=2 + + If CDN resource ID is not specified, data related to all CDN resources is + returned. """ diff --git a/src/gcore/types/cdn/statistic_get_shield_usage_aggregated_params.py b/src/gcore/types/cdn/statistic_get_shield_usage_aggregated_params.py index eff1d4f0..f40579b7 100644 --- a/src/gcore/types/cdn/statistic_get_shield_usage_aggregated_params.py +++ b/src/gcore/types/cdn/statistic_get_shield_usage_aggregated_params.py @@ -17,7 +17,7 @@ class StatisticGetShieldUsageAggregatedParams(TypedDict, total=False): """End of the requested time period (ISO 8601/RFC 3339 format, UTC.)""" flat: bool - """The waу parameters are arranged in the response. + """The way the parameters are arranged in the response. Possible values: @@ -30,7 +30,7 @@ class StatisticGetShieldUsageAggregatedParams(TypedDict, total=False): Possible value: - - **resource** - Data is grouped by CDN resource. + - **resource** - Data is grouped by CDN resources. """ resource: int @@ -39,4 +39,7 @@ class StatisticGetShieldUsageAggregatedParams(TypedDict, total=False): To request multiple values, use: - &resource=1&resource=2 + + If CDN resource ID is not specified, data related to all CDN resources is + returned. """ diff --git a/src/gcore/types/cdn/statistic_get_shield_usage_series_params.py b/src/gcore/types/cdn/statistic_get_shield_usage_series_params.py index 2b0e1a38..3ba5ad5a 100644 --- a/src/gcore/types/cdn/statistic_get_shield_usage_series_params.py +++ b/src/gcore/types/cdn/statistic_get_shield_usage_series_params.py @@ -22,4 +22,7 @@ class StatisticGetShieldUsageSeriesParams(TypedDict, total=False): To request multiple values, use: - &resource=1&resource=2 + + If CDN resource ID is not specified, data related to all CDN resources is + returned. """ diff --git a/src/gcore/types/cloud/databases/__init__.py b/src/gcore/types/cloud/databases/__init__.py new file mode 100644 index 00000000..f8ee8b14 --- /dev/null +++ b/src/gcore/types/cloud/databases/__init__.py @@ -0,0 +1,3 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations diff --git a/src/gcore/types/cloud/databases/postgres/__init__.py b/src/gcore/types/cloud/databases/postgres/__init__.py new file mode 100644 index 00000000..e4449e2b --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/__init__.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .postgres_cluster import PostgresCluster as PostgresCluster +from .pg_conf_validation import PgConfValidation as PgConfValidation +from .cluster_list_params import ClusterListParams as ClusterListParams +from .cluster_create_params import ClusterCreateParams as ClusterCreateParams +from .cluster_update_params import ClusterUpdateParams as ClusterUpdateParams +from .postgres_cluster_short import PostgresClusterShort as PostgresClusterShort +from .postgres_configuration import PostgresConfiguration as PostgresConfiguration +from .custom_configuration_validate_params import CustomConfigurationValidateParams as CustomConfigurationValidateParams diff --git a/src/gcore/types/cloud/databases/postgres/cluster_create_params.py b/src/gcore/types/cloud/databases/postgres/cluster_create_params.py new file mode 100644 index 00000000..7b569828 --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/cluster_create_params.py @@ -0,0 +1,108 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Iterable, Optional +from typing_extensions import Literal, Required, TypedDict + +from ....._types import SequenceNotStr + +__all__ = [ + "ClusterCreateParams", + "Flavor", + "HighAvailability", + "Network", + "PgServerConfiguration", + "PgServerConfigurationPooler", + "Storage", + "Database", + "User", +] + + +class ClusterCreateParams(TypedDict, total=False): + project_id: int + + region_id: int + + cluster_name: Required[str] + """PostgreSQL cluster name""" + + flavor: Required[Flavor] + """Instance RAM and CPU""" + + high_availability: Required[Optional[HighAvailability]] + """High Availability settings""" + + network: Required[Network] + + pg_server_configuration: Required[PgServerConfiguration] + """PosgtreSQL cluster configuration""" + + storage: Required[Storage] + """Cluster's storage configuration""" + + databases: Iterable[Database] + + users: Iterable[User] + + +class Flavor(TypedDict, total=False): + cpu: Required[int] + """Maximum available cores for instance""" + + memory_gib: Required[int] + """Maximum available RAM for instance""" + + +class HighAvailability(TypedDict, total=False): + replication_mode: Required[Literal["async", "sync"]] + """Type of replication""" + + +class Network(TypedDict, total=False): + acl: Required[SequenceNotStr[str]] + """Allowed IPs and subnets for incoming traffic""" + + network_type: Required[Literal["public"]] + """Network Type""" + + +class PgServerConfigurationPooler(TypedDict, total=False): + mode: Required[Literal["session", "statement", "transaction"]] + + type: Literal["pgbouncer"] + + +class PgServerConfiguration(TypedDict, total=False): + pg_conf: Required[str] + """pg.conf settings""" + + version: Required[str] + """Cluster version""" + + pooler: Optional[PgServerConfigurationPooler] + + +class Storage(TypedDict, total=False): + size_gib: Required[int] + """Total available storage for database""" + + type: Required[str] + """Storage type""" + + +class Database(TypedDict, total=False): + name: Required[str] + """Database name""" + + owner: Required[str] + """Database owner from users list""" + + +class User(TypedDict, total=False): + name: Required[str] + """User name""" + + role_attributes: Required[List[Literal["BYPASSRLS", "CREATEDB", "CREATEROLE", "INHERIT", "LOGIN", "NOLOGIN"]]] + """User's attributes""" diff --git a/src/gcore/types/cloud/databases/postgres/cluster_list_params.py b/src/gcore/types/cloud/databases/postgres/cluster_list_params.py new file mode 100644 index 00000000..301f22e4 --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/cluster_list_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ClusterListParams"] + + +class ClusterListParams(TypedDict, total=False): + project_id: int + + region_id: int + + limit: int + """Maximum number of clusters to return""" + + offset: int + """Number of clusters to skip""" diff --git a/src/gcore/types/cloud/databases/postgres/cluster_update_params.py b/src/gcore/types/cloud/databases/postgres/cluster_update_params.py new file mode 100644 index 00000000..075ee4df --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/cluster_update_params.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Iterable, Optional +from typing_extensions import Literal, Required, TypedDict + +from ....._types import SequenceNotStr + +__all__ = [ + "ClusterUpdateParams", + "Database", + "Flavor", + "HighAvailability", + "Network", + "PgServerConfiguration", + "PgServerConfigurationPooler", + "Storage", + "User", +] + + +class ClusterUpdateParams(TypedDict, total=False): + project_id: int + + region_id: int + + databases: Iterable[Database] + + flavor: Optional[Flavor] + """New instance RAM and CPU""" + + high_availability: Optional[HighAvailability] + """New High Availability settings""" + + network: Optional[Network] + + pg_server_configuration: Optional[PgServerConfiguration] + """New PosgtreSQL cluster configuration""" + + storage: Optional[Storage] + """New storage configuration""" + + users: Iterable[User] + + +class Database(TypedDict, total=False): + name: Required[str] + """Database name""" + + owner: Required[str] + """Database owner from users list""" + + +class Flavor(TypedDict, total=False): + cpu: Required[int] + """Maximum available cores for instance""" + + memory_gib: Required[int] + """Maximum available RAM for instance""" + + +class HighAvailability(TypedDict, total=False): + replication_mode: Required[Literal["async", "sync"]] + """Type of replication""" + + +class Network(TypedDict, total=False): + acl: Required[SequenceNotStr[str]] + """Allowed IPs and subnets for incoming traffic""" + + network_type: Required[Literal["public"]] + """Network Type""" + + +class PgServerConfigurationPooler(TypedDict, total=False): + mode: Required[Literal["session", "statement", "transaction"]] + + type: Literal["pgbouncer"] + + +class PgServerConfiguration(TypedDict, total=False): + pg_conf: Optional[str] + """New pg.conf file settings""" + + pooler: Optional[PgServerConfigurationPooler] + + version: Optional[str] + """New cluster version""" + + +class Storage(TypedDict, total=False): + size_gib: Required[int] + """Total available storage for database""" + + +class User(TypedDict, total=False): + name: Required[str] + """User name""" + + role_attributes: Required[List[Literal["BYPASSRLS", "CREATEDB", "CREATEROLE", "INHERIT", "LOGIN", "NOLOGIN"]]] + """User's attributes""" diff --git a/src/gcore/types/cloud/databases/postgres/clusters/__init__.py b/src/gcore/types/cloud/databases/postgres/clusters/__init__.py new file mode 100644 index 00000000..254c35c0 --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/clusters/__init__.py @@ -0,0 +1,5 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .postgres_user_credentials import PostgresUserCredentials as PostgresUserCredentials diff --git a/src/gcore/types/cloud/databases/postgres/clusters/postgres_user_credentials.py b/src/gcore/types/cloud/databases/postgres/clusters/postgres_user_credentials.py new file mode 100644 index 00000000..fd38e6c6 --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/clusters/postgres_user_credentials.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ......_models import BaseModel + +__all__ = ["PostgresUserCredentials"] + + +class PostgresUserCredentials(BaseModel): + password: str + """Password""" + + username: str + """Username""" diff --git a/src/gcore/types/cloud/databases/postgres/custom_configuration_validate_params.py b/src/gcore/types/cloud/databases/postgres/custom_configuration_validate_params.py new file mode 100644 index 00000000..2cd791ae --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/custom_configuration_validate_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["CustomConfigurationValidateParams"] + + +class CustomConfigurationValidateParams(TypedDict, total=False): + project_id: int + + region_id: int + + pg_conf: Required[str] + """PostgreSQL configuration""" + + version: Required[str] + """PostgreSQL version""" diff --git a/src/gcore/types/cloud/databases/postgres/pg_conf_validation.py b/src/gcore/types/cloud/databases/postgres/pg_conf_validation.py new file mode 100644 index 00000000..8e4ae232 --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/pg_conf_validation.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from ....._models import BaseModel + +__all__ = ["PgConfValidation"] + + +class PgConfValidation(BaseModel): + errors: List[str] + """Errors list""" + + is_valid: bool + """Validity of pg.conf file""" diff --git a/src/gcore/types/cloud/databases/postgres/postgres_cluster.py b/src/gcore/types/cloud/databases/postgres/postgres_cluster.py new file mode 100644 index 00000000..445ba8e3 --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/postgres_cluster.py @@ -0,0 +1,118 @@ +# 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 ....._models import BaseModel + +__all__ = [ + "PostgresCluster", + "Database", + "Flavor", + "HighAvailability", + "Network", + "PgServerConfiguration", + "PgServerConfigurationPooler", + "Storage", + "User", +] + + +class Database(BaseModel): + name: str + """Database name""" + + owner: str + """Database owner from users list""" + + size: int + """Size in bytes""" + + +class Flavor(BaseModel): + cpu: int + """Maximum available cores for instance""" + + memory_gib: int + """Maximum available RAM for instance""" + + +class HighAvailability(BaseModel): + replication_mode: Literal["async", "sync"] + """Type of replication""" + + +class Network(BaseModel): + acl: List[str] + """Allowed IPs and subnets for incoming traffic""" + + connection_string: str + """Connection string to main database""" + + host: str + """database hostname""" + + network_type: Literal["public"] + """Network Type""" + + +class PgServerConfigurationPooler(BaseModel): + mode: Literal["session", "statement", "transaction"] + + type: Optional[Literal["pgbouncer"]] = None + + +class PgServerConfiguration(BaseModel): + pg_conf: str + """pg.conf settings""" + + version: str + """Cluster version""" + + pooler: Optional[PgServerConfigurationPooler] = None + + +class Storage(BaseModel): + size_gib: int + """Total available storage for database""" + + type: str + """Storage type""" + + +class User(BaseModel): + is_secret_revealed: bool + """Display was secret revealed or not""" + + name: str + """User name""" + + role_attributes: List[Literal["BYPASSRLS", "CREATEDB", "CREATEROLE", "INHERIT", "LOGIN", "NOLOGIN"]] + """User's attributes""" + + +class PostgresCluster(BaseModel): + cluster_name: str + + created_at: datetime + + databases: List[Database] + + flavor: Flavor + """Instance RAM and CPU""" + + high_availability: Optional[HighAvailability] = None + + network: Network + + pg_server_configuration: PgServerConfiguration + """Main PG configuration""" + + status: Literal["DELETING", "FAILED", "PREPARING", "READY", "UNHEALTHY", "UNKNOWN", "UPDATING"] + """Current cluster status""" + + storage: Storage + """PG's storage configuration""" + + users: List[User] diff --git a/src/gcore/types/cloud/databases/postgres/postgres_cluster_short.py b/src/gcore/types/cloud/databases/postgres/postgres_cluster_short.py new file mode 100644 index 00000000..1a197123 --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/postgres_cluster_short.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from ....._models import BaseModel + +__all__ = ["PostgresClusterShort"] + + +class PostgresClusterShort(BaseModel): + cluster_name: str + """PostgreSQL cluster name""" + + created_at: datetime + """Creation timestamp""" + + status: Literal["DELETING", "FAILED", "PREPARING", "READY", "UNHEALTHY", "UNKNOWN", "UPDATING"] + """Current cluster status""" + + version: str + """Cluster version""" diff --git a/src/gcore/types/cloud/databases/postgres/postgres_configuration.py b/src/gcore/types/cloud/databases/postgres/postgres_configuration.py new file mode 100644 index 00000000..8be36800 --- /dev/null +++ b/src/gcore/types/cloud/databases/postgres/postgres_configuration.py @@ -0,0 +1,31 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from ....._models import BaseModel + +__all__ = ["PostgresConfiguration", "Flavor", "StorageClass"] + + +class Flavor(BaseModel): + cpu: int + """Maximum available cores for instance""" + + memory_gib: int + """Maximum available RAM for instance""" + + pg_conf: str + + +class StorageClass(BaseModel): + name: str + """Storage type""" + + +class PostgresConfiguration(BaseModel): + flavors: List[Flavor] + + storage_classes: List[StorageClass] + + versions: List[str] + """Available versions""" diff --git a/src/gcore/types/cloud/gpu_baremetal_cluster.py b/src/gcore/types/cloud/gpu_baremetal_cluster.py index aa310a9b..373678bf 100644 --- a/src/gcore/types/cloud/gpu_baremetal_cluster.py +++ b/src/gcore/types/cloud/gpu_baremetal_cluster.py @@ -11,6 +11,7 @@ __all__ = [ "GPUBaremetalCluster", "ServersSettings", + "ServersSettingsFileShare", "ServersSettingsInterface", "ServersSettingsInterfaceExternalInterfaceOutputSerializer", "ServersSettingsInterfaceSubnetInterfaceOutputSerializer", @@ -21,6 +22,14 @@ ] +class ServersSettingsFileShare(BaseModel): + id: str + """Unique identifier of the file share in UUID format.""" + + mount_path: str + """Absolute mount path inside the system where the file share will be mounted.""" + + class ServersSettingsInterfaceExternalInterfaceOutputSerializer(BaseModel): ip_family: Literal["dual", "ipv4", "ipv6"] """Which subnets should be selected: IPv4, IPv6, or use dual stack.""" @@ -90,6 +99,9 @@ class ServersSettingsSecurityGroup(BaseModel): class ServersSettings(BaseModel): + file_shares: List[ServersSettingsFileShare] + """List of file shares mounted across the cluster.""" + interfaces: List[ServersSettingsInterface] security_groups: List[ServersSettingsSecurityGroup] @@ -99,7 +111,7 @@ class ServersSettings(BaseModel): """SSH key name""" user_data: Optional[str] = None - """Optional custom user data (Base64-encoded) Mutually exclusive with 'password'.""" + """Optional custom user data""" class GPUBaremetalCluster(BaseModel): diff --git a/src/gcore/types/cloud/gpu_baremetal_cluster_create_params.py b/src/gcore/types/cloud/gpu_baremetal_cluster_create_params.py index 2dd61b2c..7bdf8a8a 100644 --- a/src/gcore/types/cloud/gpu_baremetal_cluster_create_params.py +++ b/src/gcore/types/cloud/gpu_baremetal_cluster_create_params.py @@ -15,6 +15,7 @@ "ServersSettingsInterfaceAnySubnetInterfaceInputSerializer", "ServersSettingsInterfaceAnySubnetInterfaceInputSerializerFloatingIP", "ServersSettingsCredentials", + "ServersSettingsFileShare", "ServersSettingsSecurityGroup", ] @@ -127,6 +128,14 @@ class ServersSettingsCredentials(TypedDict, total=False): """The 'username' and 'password' fields create a new user on the system""" +class ServersSettingsFileShare(TypedDict, total=False): + id: Required[str] + """Unique identifier of the file share in UUID format.""" + + mount_path: Required[str] + """Absolute mount path inside the system where the file share will be mounted.""" + + class ServersSettingsSecurityGroup(TypedDict, total=False): id: Required[str] """Resource ID""" @@ -139,6 +148,9 @@ class ServersSettings(TypedDict, total=False): credentials: ServersSettingsCredentials """Optional server access credentials""" + file_shares: Iterable[ServersSettingsFileShare] + """List of file shares to be mounted across the cluster.""" + security_groups: Iterable[ServersSettingsSecurityGroup] """List of security groups UUIDs""" diff --git a/src/gcore/types/cloud/k8s/k8s_cluster_kubeconfig.py b/src/gcore/types/cloud/k8s/k8s_cluster_kubeconfig.py index 38aaabe4..c7f7426e 100644 --- a/src/gcore/types/cloud/k8s/k8s_cluster_kubeconfig.py +++ b/src/gcore/types/cloud/k8s/k8s_cluster_kubeconfig.py @@ -9,9 +9,21 @@ class K8sClusterKubeconfig(BaseModel): + client_certificate: str + """String in base64 format. Cluster client certificate""" + + client_key: str + """String in base64 format. Cluster client key""" + + cluster_ca_certificate: str + """String in base64 format. Cluster ca certificate""" + config: str """Cluster kubeconfig""" + host: str + """Cluster host""" + created_at: Optional[datetime] = None """Kubeconfig creation date""" diff --git a/src/gcore/types/cloud/load_balancer_create_params.py b/src/gcore/types/cloud/load_balancer_create_params.py index a41fd6e4..28429738 100644 --- a/src/gcore/types/cloud/load_balancer_create_params.py +++ b/src/gcore/types/cloud/load_balancer_create_params.py @@ -277,7 +277,7 @@ class ListenerPool(TypedDict, total=False): load_balancer_id: Optional[str] """Loadbalancer ID""" - members: Optional[Iterable[ListenerPoolMember]] + members: Iterable[ListenerPoolMember] """Pool members""" secret_id: Optional[str] @@ -318,7 +318,10 @@ class Listener(TypedDict, total=False): """Network CIDRs from which service will be accessible""" connection_limit: int - """Limit of the simultaneous connections""" + """Limit of the simultaneous connections. + + If -1 is provided, it is translated to the default value 100000. + """ insert_x_forwarded: bool """Add headers X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto to requests. diff --git a/src/gcore/types/cloud/load_balancers/__init__.py b/src/gcore/types/cloud/load_balancers/__init__.py index 433f966c..c68b77c9 100644 --- a/src/gcore/types/cloud/load_balancers/__init__.py +++ b/src/gcore/types/cloud/load_balancers/__init__.py @@ -10,6 +10,7 @@ from .listener_get_params import ListenerGetParams as ListenerGetParams from .listener_list_params import ListenerListParams as ListenerListParams from .listener_create_params import ListenerCreateParams as ListenerCreateParams +from .listener_delete_params import ListenerDeleteParams as ListenerDeleteParams from .listener_update_params import ListenerUpdateParams as ListenerUpdateParams from .l7_policy_create_params import L7PolicyCreateParams as L7PolicyCreateParams from .l7_policy_replace_params import L7PolicyReplaceParams as L7PolicyReplaceParams 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 c5b6f5e6..9850d348 100644 --- a/src/gcore/types/cloud/load_balancers/listener_create_params.py +++ b/src/gcore/types/cloud/load_balancers/listener_create_params.py @@ -34,7 +34,10 @@ class ListenerCreateParams(TypedDict, total=False): """Network CIDRs from which service will be accessible""" connection_limit: int - """Limit of the simultaneous connections""" + """Limit of the simultaneous connections. + + If -1 is provided, it is translated to the default value 100000. + """ insert_x_forwarded: bool """Add headers X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto to requests. diff --git a/src/gcore/types/cloud/load_balancers/listener_delete_params.py b/src/gcore/types/cloud/load_balancers/listener_delete_params.py new file mode 100644 index 00000000..7d0e31a4 --- /dev/null +++ b/src/gcore/types/cloud/load_balancers/listener_delete_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ListenerDeleteParams"] + + +class ListenerDeleteParams(TypedDict, total=False): + project_id: int + """Project ID""" + + region_id: int + """Region ID""" + + delete_default_pool: bool + """Delete default pool attached directly to the listener.""" 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 492c990d..42fa7e38 100644 --- a/src/gcore/types/cloud/load_balancers/listener_update_params.py +++ b/src/gcore/types/cloud/load_balancers/listener_update_params.py @@ -21,7 +21,10 @@ class ListenerUpdateParams(TypedDict, total=False): """Network CIDRs from which service will be accessible""" connection_limit: int - """Limit of simultaneous connections""" + """Limit of simultaneous connections. + + If -1 is provided, it is translated to the default value 100000. + """ name: str """Load balancer listener name""" 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 492e9640..c8e503a5 100644 --- a/src/gcore/types/cloud/load_balancers/pool_create_params.py +++ b/src/gcore/types/cloud/load_balancers/pool_create_params.py @@ -45,7 +45,7 @@ class PoolCreateParams(TypedDict, total=False): load_balancer_id: Optional[str] """Loadbalancer ID""" - members: Optional[Iterable[Member]] + members: Iterable[Member] """Pool members""" secret_id: Optional[str] diff --git a/src/gcore/types/cloud/project_create_params.py b/src/gcore/types/cloud/project_create_params.py index 9a9255be..86a3ff86 100644 --- a/src/gcore/types/cloud/project_create_params.py +++ b/src/gcore/types/cloud/project_create_params.py @@ -12,11 +12,5 @@ class ProjectCreateParams(TypedDict, total=False): name: Required[str] """Unique project name for a client. Each client always has one "default" project.""" - client_id: Optional[int] - """ID associated with the client.""" - description: Optional[str] """Description of the project.""" - - state: Optional[str] - """State of the project.""" diff --git a/src/gcore/types/cloud/quotas/request_create_params.py b/src/gcore/types/cloud/quotas/request_create_params.py index 282e29ad..8732cde2 100644 --- a/src/gcore/types/cloud/quotas/request_create_params.py +++ b/src/gcore/types/cloud/quotas/request_create_params.py @@ -15,9 +15,6 @@ class RequestCreateParams(TypedDict, total=False): requested_limits: Required[RequestedLimits] """Limits you want to increase.""" - client_id: int - """Client ID that requests the limit increase.""" - class RequestedLimitsGlobalLimits(TypedDict, total=False): inference_cpu_millicore_count_limit: int diff --git a/src/gcore/types/cloud/security_group.py b/src/gcore/types/cloud/security_group.py index 7407daad..412b43d5 100644 --- a/src/gcore/types/cloud/security_group.py +++ b/src/gcore/types/cloud/security_group.py @@ -33,7 +33,14 @@ class SecurityGroup(BaseModel): """The number of revisions""" tags_v2: List[Tag] - """Tags for a security group""" + """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. + """ updated_at: datetime """Datetime when the security group was last updated""" diff --git a/tests/api_resources/cdn/test_ip_ranges.py b/tests/api_resources/cdn/test_ip_ranges.py index c9bbdb5e..b4967cd6 100644 --- a/tests/api_resources/cdn/test_ip_ranges.py +++ b/tests/api_resources/cdn/test_ip_ranges.py @@ -22,6 +22,14 @@ def test_method_list(self, client: Gcore) -> None: ip_range = client.cdn.ip_ranges.list() assert_matches_type(PublicNetworkList, ip_range, path=["response"]) + @parametrize + def test_method_list_with_all_params(self, client: Gcore) -> None: + ip_range = client.cdn.ip_ranges.list( + format="json", + accept="application/json", + ) + assert_matches_type(PublicNetworkList, ip_range, path=["response"]) + @parametrize def test_raw_response_list(self, client: Gcore) -> None: response = client.cdn.ip_ranges.with_raw_response.list() @@ -47,6 +55,14 @@ def test_method_list_ips(self, client: Gcore) -> None: ip_range = client.cdn.ip_ranges.list_ips() assert_matches_type(PublicIPList, ip_range, path=["response"]) + @parametrize + def test_method_list_ips_with_all_params(self, client: Gcore) -> None: + ip_range = client.cdn.ip_ranges.list_ips( + format="json", + accept="application/json", + ) + assert_matches_type(PublicIPList, ip_range, path=["response"]) + @parametrize def test_raw_response_list_ips(self, client: Gcore) -> None: response = client.cdn.ip_ranges.with_raw_response.list_ips() @@ -78,6 +94,14 @@ async def test_method_list(self, async_client: AsyncGcore) -> None: ip_range = await async_client.cdn.ip_ranges.list() assert_matches_type(PublicNetworkList, ip_range, path=["response"]) + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: + ip_range = await async_client.cdn.ip_ranges.list( + format="json", + accept="application/json", + ) + assert_matches_type(PublicNetworkList, ip_range, path=["response"]) + @parametrize async def test_raw_response_list(self, async_client: AsyncGcore) -> None: response = await async_client.cdn.ip_ranges.with_raw_response.list() @@ -103,6 +127,14 @@ async def test_method_list_ips(self, async_client: AsyncGcore) -> None: ip_range = await async_client.cdn.ip_ranges.list_ips() assert_matches_type(PublicIPList, ip_range, path=["response"]) + @parametrize + async def test_method_list_ips_with_all_params(self, async_client: AsyncGcore) -> None: + ip_range = await async_client.cdn.ip_ranges.list_ips( + format="json", + accept="application/json", + ) + assert_matches_type(PublicIPList, ip_range, path=["response"]) + @parametrize async def test_raw_response_list_ips(self, async_client: AsyncGcore) -> None: response = await async_client.cdn.ip_ranges.with_raw_response.list_ips() diff --git a/tests/api_resources/cdn/test_resources.py b/tests/api_resources/cdn/test_resources.py index aecf0ca9..debacd03 100644 --- a/tests/api_resources/cdn/test_resources.py +++ b/tests/api_resources/cdn/test_resources.py @@ -886,7 +886,7 @@ def test_method_purge_overload_1(self, client: Gcore) -> None: def test_method_purge_with_all_params_overload_1(self, client: Gcore) -> None: resource = client.cdn.resources.purge( resource_id=0, - urls=["string"], + urls=["/some-url.jpg", "/img/example.jpg"], ) assert resource is None @@ -925,7 +925,7 @@ def test_method_purge_overload_2(self, client: Gcore) -> None: def test_method_purge_with_all_params_overload_2(self, client: Gcore) -> None: resource = client.cdn.resources.purge( resource_id=0, - paths=["string"], + paths=["/images/*", "/videos/*"], ) assert resource is None @@ -2202,7 +2202,7 @@ async def test_method_purge_overload_1(self, async_client: AsyncGcore) -> None: async def test_method_purge_with_all_params_overload_1(self, async_client: AsyncGcore) -> None: resource = await async_client.cdn.resources.purge( resource_id=0, - urls=["string"], + urls=["/some-url.jpg", "/img/example.jpg"], ) assert resource is None @@ -2241,7 +2241,7 @@ async def test_method_purge_overload_2(self, async_client: AsyncGcore) -> None: async def test_method_purge_with_all_params_overload_2(self, async_client: AsyncGcore) -> None: resource = await async_client.cdn.resources.purge( resource_id=0, - paths=["string"], + paths=["/images/*", "/videos/*"], ) assert resource is None diff --git a/tests/api_resources/cloud/databases/__init__.py b/tests/api_resources/cloud/databases/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/cloud/databases/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/cloud/databases/postgres/__init__.py b/tests/api_resources/cloud/databases/postgres/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/cloud/databases/postgres/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/cloud/databases/postgres/clusters/__init__.py b/tests/api_resources/cloud/databases/postgres/clusters/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/cloud/databases/postgres/clusters/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/cloud/databases/postgres/clusters/test_user_credentials.py b/tests/api_resources/cloud/databases/postgres/clusters/test_user_credentials.py new file mode 100644 index 00000000..28169d78 --- /dev/null +++ b/tests/api_resources/cloud/databases/postgres/clusters/test_user_credentials.py @@ -0,0 +1,256 @@ +# 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.databases.postgres.clusters import PostgresUserCredentials + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestUserCredentials: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_get(self, client: Gcore) -> None: + user_credential = client.cloud.databases.postgres.clusters.user_credentials.get( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Gcore) -> None: + response = client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.get( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + user_credential = response.parse() + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Gcore) -> None: + with client.cloud.databases.postgres.clusters.user_credentials.with_streaming_response.get( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + user_credential = response.parse() + assert_matches_type(PostgresUserCredentials, user_credential, 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 `cluster_name` but received ''"): + client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.get( + username="username", + project_id=0, + region_id=0, + cluster_name="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `username` but received ''"): + client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.get( + username="", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + + @parametrize + def test_method_regenerate(self, client: Gcore) -> None: + user_credential = client.cloud.databases.postgres.clusters.user_credentials.regenerate( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + @parametrize + def test_raw_response_regenerate(self, client: Gcore) -> None: + response = client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.regenerate( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + user_credential = response.parse() + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + @parametrize + def test_streaming_response_regenerate(self, client: Gcore) -> None: + with client.cloud.databases.postgres.clusters.user_credentials.with_streaming_response.regenerate( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + user_credential = response.parse() + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_regenerate(self, client: Gcore) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `cluster_name` but received ''"): + client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.regenerate( + username="username", + project_id=0, + region_id=0, + cluster_name="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `username` but received ''"): + client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.regenerate( + username="", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + + +class TestAsyncUserCredentials: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_get(self, async_client: AsyncGcore) -> None: + user_credential = await async_client.cloud.databases.postgres.clusters.user_credentials.get( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.get( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + user_credential = await response.parse() + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.databases.postgres.clusters.user_credentials.with_streaming_response.get( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + user_credential = await response.parse() + assert_matches_type(PostgresUserCredentials, user_credential, 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 `cluster_name` but received ''"): + await async_client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.get( + username="username", + project_id=0, + region_id=0, + cluster_name="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `username` but received ''"): + await async_client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.get( + username="", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + + @parametrize + async def test_method_regenerate(self, async_client: AsyncGcore) -> None: + user_credential = await async_client.cloud.databases.postgres.clusters.user_credentials.regenerate( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + @parametrize + async def test_raw_response_regenerate(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.regenerate( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + user_credential = await response.parse() + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + @parametrize + async def test_streaming_response_regenerate(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.databases.postgres.clusters.user_credentials.with_streaming_response.regenerate( + username="username", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + user_credential = await response.parse() + assert_matches_type(PostgresUserCredentials, user_credential, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_regenerate(self, async_client: AsyncGcore) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `cluster_name` but received ''"): + await async_client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.regenerate( + username="username", + project_id=0, + region_id=0, + cluster_name="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `username` but received ''"): + await async_client.cloud.databases.postgres.clusters.user_credentials.with_raw_response.regenerate( + username="", + project_id=0, + region_id=0, + cluster_name="cluster_name", + ) diff --git a/tests/api_resources/cloud/databases/postgres/test_clusters.py b/tests/api_resources/cloud/databases/postgres/test_clusters.py new file mode 100644 index 00000000..224aa613 --- /dev/null +++ b/tests/api_resources/cloud/databases/postgres/test_clusters.py @@ -0,0 +1,731 @@ +# 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.pagination import SyncOffsetPage, AsyncOffsetPage +from gcore.types.cloud import TaskIDList +from gcore.types.cloud.databases.postgres import ( + PostgresCluster, + PostgresClusterShort, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestClusters: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Gcore) -> None: + cluster = client.cloud.databases.postgres.clusters.create( + project_id=0, + region_id=0, + cluster_name="3", + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "version": "version", + }, + storage={ + "size_gib": 100, + "type": "ssd-hiiops", + }, + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Gcore) -> None: + cluster = client.cloud.databases.postgres.clusters.create( + project_id=0, + region_id=0, + cluster_name="3", + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "version": "version", + "pooler": { + "mode": "transaction", + "type": "pgbouncer", + }, + }, + storage={ + "size_gib": 100, + "type": "ssd-hiiops", + }, + databases=[ + { + "name": "mydatabase", + "owner": "myuser", + } + ], + users=[ + { + "name": "myuser", + "role_attributes": ["INHERIT"], + } + ], + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Gcore) -> None: + response = client.cloud.databases.postgres.clusters.with_raw_response.create( + project_id=0, + region_id=0, + cluster_name="3", + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "version": "version", + }, + storage={ + "size_gib": 100, + "type": "ssd-hiiops", + }, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = response.parse() + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Gcore) -> None: + with client.cloud.databases.postgres.clusters.with_streaming_response.create( + project_id=0, + region_id=0, + cluster_name="3", + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "version": "version", + }, + storage={ + "size_gib": 100, + "type": "ssd-hiiops", + }, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = response.parse() + assert_matches_type(TaskIDList, cluster, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_update(self, client: Gcore) -> None: + cluster = client.cloud.databases.postgres.clusters.update( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + def test_method_update_with_all_params(self, client: Gcore) -> None: + cluster = client.cloud.databases.postgres.clusters.update( + cluster_name="cluster_name", + project_id=0, + region_id=0, + databases=[ + { + "name": "mydatabase", + "owner": "myuser", + } + ], + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "pooler": { + "mode": "transaction", + "type": "pgbouncer", + }, + "version": "15", + }, + storage={"size_gib": 100}, + users=[ + { + "name": "myuser", + "role_attributes": ["INHERIT"], + } + ], + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + def test_raw_response_update(self, client: Gcore) -> None: + response = client.cloud.databases.postgres.clusters.with_raw_response.update( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = response.parse() + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + def test_streaming_response_update(self, client: Gcore) -> None: + with client.cloud.databases.postgres.clusters.with_streaming_response.update( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = response.parse() + assert_matches_type(TaskIDList, cluster, 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 `cluster_name` but received ''"): + client.cloud.databases.postgres.clusters.with_raw_response.update( + cluster_name="", + project_id=0, + region_id=0, + ) + + @parametrize + def test_method_list(self, client: Gcore) -> None: + cluster = client.cloud.databases.postgres.clusters.list( + project_id=0, + region_id=0, + ) + assert_matches_type(SyncOffsetPage[PostgresClusterShort], cluster, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Gcore) -> None: + cluster = client.cloud.databases.postgres.clusters.list( + project_id=0, + region_id=0, + limit=0, + offset=0, + ) + assert_matches_type(SyncOffsetPage[PostgresClusterShort], cluster, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Gcore) -> None: + response = client.cloud.databases.postgres.clusters.with_raw_response.list( + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = response.parse() + assert_matches_type(SyncOffsetPage[PostgresClusterShort], cluster, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Gcore) -> None: + with client.cloud.databases.postgres.clusters.with_streaming_response.list( + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = response.parse() + assert_matches_type(SyncOffsetPage[PostgresClusterShort], cluster, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_delete(self, client: Gcore) -> None: + cluster = client.cloud.databases.postgres.clusters.delete( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + def test_raw_response_delete(self, client: Gcore) -> None: + response = client.cloud.databases.postgres.clusters.with_raw_response.delete( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = response.parse() + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + def test_streaming_response_delete(self, client: Gcore) -> None: + with client.cloud.databases.postgres.clusters.with_streaming_response.delete( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = response.parse() + assert_matches_type(TaskIDList, cluster, 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 `cluster_name` but received ''"): + client.cloud.databases.postgres.clusters.with_raw_response.delete( + cluster_name="", + project_id=0, + region_id=0, + ) + + @parametrize + def test_method_get(self, client: Gcore) -> None: + cluster = client.cloud.databases.postgres.clusters.get( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + assert_matches_type(PostgresCluster, cluster, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Gcore) -> None: + response = client.cloud.databases.postgres.clusters.with_raw_response.get( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = response.parse() + assert_matches_type(PostgresCluster, cluster, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Gcore) -> None: + with client.cloud.databases.postgres.clusters.with_streaming_response.get( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = response.parse() + assert_matches_type(PostgresCluster, cluster, 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 `cluster_name` but received ''"): + client.cloud.databases.postgres.clusters.with_raw_response.get( + cluster_name="", + project_id=0, + region_id=0, + ) + + +class TestAsyncClusters: + 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: + cluster = await async_client.cloud.databases.postgres.clusters.create( + project_id=0, + region_id=0, + cluster_name="3", + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "version": "version", + }, + storage={ + "size_gib": 100, + "type": "ssd-hiiops", + }, + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> None: + cluster = await async_client.cloud.databases.postgres.clusters.create( + project_id=0, + region_id=0, + cluster_name="3", + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "version": "version", + "pooler": { + "mode": "transaction", + "type": "pgbouncer", + }, + }, + storage={ + "size_gib": 100, + "type": "ssd-hiiops", + }, + databases=[ + { + "name": "mydatabase", + "owner": "myuser", + } + ], + users=[ + { + "name": "myuser", + "role_attributes": ["INHERIT"], + } + ], + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.databases.postgres.clusters.with_raw_response.create( + project_id=0, + region_id=0, + cluster_name="3", + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "version": "version", + }, + storage={ + "size_gib": 100, + "type": "ssd-hiiops", + }, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = await response.parse() + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.databases.postgres.clusters.with_streaming_response.create( + project_id=0, + region_id=0, + cluster_name="3", + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "version": "version", + }, + storage={ + "size_gib": 100, + "type": "ssd-hiiops", + }, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = await response.parse() + assert_matches_type(TaskIDList, cluster, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_update(self, async_client: AsyncGcore) -> None: + cluster = await async_client.cloud.databases.postgres.clusters.update( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> None: + cluster = await async_client.cloud.databases.postgres.clusters.update( + cluster_name="cluster_name", + project_id=0, + region_id=0, + databases=[ + { + "name": "mydatabase", + "owner": "myuser", + } + ], + flavor={ + "cpu": 1, + "memory_gib": 1, + }, + high_availability={"replication_mode": "sync"}, + network={ + "acl": ["92.33.34.127"], + "network_type": "public", + }, + pg_server_configuration={ + "pg_conf": "\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + "pooler": { + "mode": "transaction", + "type": "pgbouncer", + }, + "version": "15", + }, + storage={"size_gib": 100}, + users=[ + { + "name": "myuser", + "role_attributes": ["INHERIT"], + } + ], + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + async def test_raw_response_update(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.databases.postgres.clusters.with_raw_response.update( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = await response.parse() + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + async def test_streaming_response_update(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.databases.postgres.clusters.with_streaming_response.update( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = await response.parse() + assert_matches_type(TaskIDList, cluster, 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 `cluster_name` but received ''"): + await async_client.cloud.databases.postgres.clusters.with_raw_response.update( + cluster_name="", + project_id=0, + region_id=0, + ) + + @parametrize + async def test_method_list(self, async_client: AsyncGcore) -> None: + cluster = await async_client.cloud.databases.postgres.clusters.list( + project_id=0, + region_id=0, + ) + assert_matches_type(AsyncOffsetPage[PostgresClusterShort], cluster, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: + cluster = await async_client.cloud.databases.postgres.clusters.list( + project_id=0, + region_id=0, + limit=0, + offset=0, + ) + assert_matches_type(AsyncOffsetPage[PostgresClusterShort], cluster, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.databases.postgres.clusters.with_raw_response.list( + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = await response.parse() + assert_matches_type(AsyncOffsetPage[PostgresClusterShort], cluster, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.databases.postgres.clusters.with_streaming_response.list( + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = await response.parse() + assert_matches_type(AsyncOffsetPage[PostgresClusterShort], cluster, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_delete(self, async_client: AsyncGcore) -> None: + cluster = await async_client.cloud.databases.postgres.clusters.delete( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.databases.postgres.clusters.with_raw_response.delete( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = await response.parse() + assert_matches_type(TaskIDList, cluster, path=["response"]) + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.databases.postgres.clusters.with_streaming_response.delete( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = await response.parse() + assert_matches_type(TaskIDList, cluster, 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 `cluster_name` but received ''"): + await async_client.cloud.databases.postgres.clusters.with_raw_response.delete( + cluster_name="", + project_id=0, + region_id=0, + ) + + @parametrize + async def test_method_get(self, async_client: AsyncGcore) -> None: + cluster = await async_client.cloud.databases.postgres.clusters.get( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + assert_matches_type(PostgresCluster, cluster, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.databases.postgres.clusters.with_raw_response.get( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + cluster = await response.parse() + assert_matches_type(PostgresCluster, cluster, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.databases.postgres.clusters.with_streaming_response.get( + cluster_name="cluster_name", + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + cluster = await response.parse() + assert_matches_type(PostgresCluster, cluster, 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 `cluster_name` but received ''"): + await async_client.cloud.databases.postgres.clusters.with_raw_response.get( + cluster_name="", + project_id=0, + region_id=0, + ) diff --git a/tests/api_resources/cloud/databases/postgres/test_configurations.py b/tests/api_resources/cloud/databases/postgres/test_configurations.py new file mode 100644 index 00000000..635483f0 --- /dev/null +++ b/tests/api_resources/cloud/databases/postgres/test_configurations.py @@ -0,0 +1,92 @@ +# 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.databases.postgres import PostgresConfiguration + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestConfigurations: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_get(self, client: Gcore) -> None: + configuration = client.cloud.databases.postgres.configurations.get( + project_id=0, + region_id=0, + ) + assert_matches_type(PostgresConfiguration, configuration, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Gcore) -> None: + response = client.cloud.databases.postgres.configurations.with_raw_response.get( + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + configuration = response.parse() + assert_matches_type(PostgresConfiguration, configuration, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Gcore) -> None: + with client.cloud.databases.postgres.configurations.with_streaming_response.get( + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + configuration = response.parse() + assert_matches_type(PostgresConfiguration, configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncConfigurations: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_get(self, async_client: AsyncGcore) -> None: + configuration = await async_client.cloud.databases.postgres.configurations.get( + project_id=0, + region_id=0, + ) + assert_matches_type(PostgresConfiguration, configuration, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.databases.postgres.configurations.with_raw_response.get( + project_id=0, + region_id=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + configuration = await response.parse() + assert_matches_type(PostgresConfiguration, configuration, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.databases.postgres.configurations.with_streaming_response.get( + project_id=0, + region_id=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + configuration = await response.parse() + assert_matches_type(PostgresConfiguration, configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/cloud/databases/postgres/test_custom_configurations.py b/tests/api_resources/cloud/databases/postgres/test_custom_configurations.py new file mode 100644 index 00000000..1f6935d3 --- /dev/null +++ b/tests/api_resources/cloud/databases/postgres/test_custom_configurations.py @@ -0,0 +1,104 @@ +# 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.databases.postgres import PgConfValidation + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCustomConfigurations: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_validate(self, client: Gcore) -> None: + custom_configuration = client.cloud.databases.postgres.custom_configurations.validate( + project_id=0, + region_id=0, + pg_conf="\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + version="15", + ) + assert_matches_type(PgConfValidation, custom_configuration, path=["response"]) + + @parametrize + def test_raw_response_validate(self, client: Gcore) -> None: + response = client.cloud.databases.postgres.custom_configurations.with_raw_response.validate( + project_id=0, + region_id=0, + pg_conf="\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + version="15", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_configuration = response.parse() + assert_matches_type(PgConfValidation, custom_configuration, path=["response"]) + + @parametrize + def test_streaming_response_validate(self, client: Gcore) -> None: + with client.cloud.databases.postgres.custom_configurations.with_streaming_response.validate( + project_id=0, + region_id=0, + pg_conf="\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + version="15", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_configuration = response.parse() + assert_matches_type(PgConfValidation, custom_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncCustomConfigurations: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_validate(self, async_client: AsyncGcore) -> None: + custom_configuration = await async_client.cloud.databases.postgres.custom_configurations.validate( + project_id=0, + region_id=0, + pg_conf="\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + version="15", + ) + assert_matches_type(PgConfValidation, custom_configuration, path=["response"]) + + @parametrize + async def test_raw_response_validate(self, async_client: AsyncGcore) -> None: + response = await async_client.cloud.databases.postgres.custom_configurations.with_raw_response.validate( + project_id=0, + region_id=0, + pg_conf="\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + version="15", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + custom_configuration = await response.parse() + assert_matches_type(PgConfValidation, custom_configuration, path=["response"]) + + @parametrize + async def test_streaming_response_validate(self, async_client: AsyncGcore) -> None: + async with async_client.cloud.databases.postgres.custom_configurations.with_streaming_response.validate( + project_id=0, + region_id=0, + pg_conf="\nlisten_addresses = 'localhost'\nport = 5432\nmax_connections = 100\nshared_buffers = 128MB\nlogging_collector = on", + version="15", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + custom_configuration = await response.parse() + assert_matches_type(PgConfValidation, custom_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/cloud/load_balancers/test_listeners.py b/tests/api_resources/cloud/load_balancers/test_listeners.py index b7228ea5..628a84f8 100644 --- a/tests/api_resources/cloud/load_balancers/test_listeners.py +++ b/tests/api_resources/cloud/load_balancers/test_listeners.py @@ -211,6 +211,16 @@ def test_method_delete(self, client: Gcore) -> None: ) assert_matches_type(TaskIDList, listener, path=["response"]) + @parametrize + def test_method_delete_with_all_params(self, client: Gcore) -> None: + listener = client.cloud.load_balancers.listeners.delete( + listener_id="00000000-0000-4000-8000-000000000000", + project_id=1, + region_id=1, + delete_default_pool=False, + ) + assert_matches_type(TaskIDList, listener, path=["response"]) + @parametrize def test_raw_response_delete(self, client: Gcore) -> None: response = client.cloud.load_balancers.listeners.with_raw_response.delete( @@ -504,6 +514,16 @@ async def test_method_delete(self, async_client: AsyncGcore) -> None: ) assert_matches_type(TaskIDList, listener, path=["response"]) + @parametrize + async def test_method_delete_with_all_params(self, async_client: AsyncGcore) -> None: + listener = await async_client.cloud.load_balancers.listeners.delete( + listener_id="00000000-0000-4000-8000-000000000000", + project_id=1, + region_id=1, + delete_default_pool=False, + ) + assert_matches_type(TaskIDList, listener, path=["response"]) + @parametrize async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.load_balancers.listeners.with_raw_response.delete( diff --git a/tests/api_resources/cloud/quotas/test_requests.py b/tests/api_resources/cloud/quotas/test_requests.py index 9b2b7487..3c7152a1 100644 --- a/tests/api_resources/cloud/quotas/test_requests.py +++ b/tests/api_resources/cloud/quotas/test_requests.py @@ -97,7 +97,6 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: } ], }, - client_id=1, ) assert request is None @@ -308,7 +307,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> } ], }, - client_id=1, ) assert request is None diff --git a/tests/api_resources/cloud/test_gpu_baremetal_clusters.py b/tests/api_resources/cloud/test_gpu_baremetal_clusters.py index 9fc01cc9..90aa7127 100644 --- a/tests/api_resources/cloud/test_gpu_baremetal_clusters.py +++ b/tests/api_resources/cloud/test_gpu_baremetal_clusters.py @@ -57,6 +57,12 @@ def test_method_create_with_all_params(self, client: Gcore) -> None: "ssh_key_name": "my-ssh-key", "username": "admin", }, + "file_shares": [ + { + "id": "a3f2d1b8-45e6-4f8a-bb5d-19dbf2cd7e9a", + "mount_path": "/mnt/vast", + } + ], "security_groups": [{"id": "b4849ffa-89f2-45a1-951f-0ae5b7809d98"}], "user_data": "eyJ0ZXN0IjogImRhdGEifQ==", }, @@ -549,6 +555,12 @@ async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> "ssh_key_name": "my-ssh-key", "username": "admin", }, + "file_shares": [ + { + "id": "a3f2d1b8-45e6-4f8a-bb5d-19dbf2cd7e9a", + "mount_path": "/mnt/vast", + } + ], "security_groups": [{"id": "b4849ffa-89f2-45a1-951f-0ae5b7809d98"}], "user_data": "eyJ0ZXN0IjogImRhdGEifQ==", }, diff --git a/tests/api_resources/cloud/test_projects.py b/tests/api_resources/cloud/test_projects.py index 33942a79..2a620652 100644 --- a/tests/api_resources/cloud/test_projects.py +++ b/tests/api_resources/cloud/test_projects.py @@ -21,24 +21,22 @@ class TestProjects: @parametrize def test_method_create(self, client: Gcore) -> None: project = client.cloud.projects.create( - name="New Project", + name="my-project", ) assert_matches_type(Project, project, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: Gcore) -> None: project = client.cloud.projects.create( - name="New Project", - client_id=3, + name="my-project", description="Project description", - state="ACTIVE", ) assert_matches_type(Project, project, path=["response"]) @parametrize def test_raw_response_create(self, client: Gcore) -> None: response = client.cloud.projects.with_raw_response.create( - name="New Project", + name="my-project", ) assert response.is_closed is True @@ -49,7 +47,7 @@ def test_raw_response_create(self, client: Gcore) -> None: @parametrize def test_streaming_response_create(self, client: Gcore) -> None: with client.cloud.projects.with_streaming_response.create( - name="New Project", + name="my-project", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -63,7 +61,7 @@ def test_streaming_response_create(self, client: Gcore) -> None: def test_method_update(self, client: Gcore) -> None: project = client.cloud.projects.update( project_id=0, - name="New Project", + name="my-project", ) assert_matches_type(Project, project, path=["response"]) @@ -71,7 +69,7 @@ def test_method_update(self, client: Gcore) -> None: def test_method_update_with_all_params(self, client: Gcore) -> None: project = client.cloud.projects.update( project_id=0, - name="New Project", + name="my-project", description="Project description", ) assert_matches_type(Project, project, path=["response"]) @@ -80,7 +78,7 @@ def test_method_update_with_all_params(self, client: Gcore) -> None: def test_raw_response_update(self, client: Gcore) -> None: response = client.cloud.projects.with_raw_response.update( project_id=0, - name="New Project", + name="my-project", ) assert response.is_closed is True @@ -92,7 +90,7 @@ def test_raw_response_update(self, client: Gcore) -> None: def test_streaming_response_update(self, client: Gcore) -> None: with client.cloud.projects.with_streaming_response.update( project_id=0, - name="New Project", + name="my-project", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -210,24 +208,22 @@ class TestAsyncProjects: @parametrize async def test_method_create(self, async_client: AsyncGcore) -> None: project = await async_client.cloud.projects.create( - name="New Project", + name="my-project", ) assert_matches_type(Project, project, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> None: project = await async_client.cloud.projects.create( - name="New Project", - client_id=3, + name="my-project", description="Project description", - state="ACTIVE", ) assert_matches_type(Project, project, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncGcore) -> None: response = await async_client.cloud.projects.with_raw_response.create( - name="New Project", + name="my-project", ) assert response.is_closed is True @@ -238,7 +234,7 @@ 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.projects.with_streaming_response.create( - name="New Project", + name="my-project", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -252,7 +248,7 @@ async def test_streaming_response_create(self, async_client: AsyncGcore) -> None async def test_method_update(self, async_client: AsyncGcore) -> None: project = await async_client.cloud.projects.update( project_id=0, - name="New Project", + name="my-project", ) assert_matches_type(Project, project, path=["response"]) @@ -260,7 +256,7 @@ async def test_method_update(self, async_client: AsyncGcore) -> None: async def test_method_update_with_all_params(self, async_client: AsyncGcore) -> None: project = await async_client.cloud.projects.update( project_id=0, - name="New Project", + name="my-project", description="Project description", ) assert_matches_type(Project, project, path=["response"]) @@ -269,7 +265,7 @@ 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.cloud.projects.with_raw_response.update( project_id=0, - name="New Project", + name="my-project", ) assert response.is_closed is True @@ -281,7 +277,7 @@ 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.cloud.projects.with_streaming_response.update( project_id=0, - name="New Project", + name="my-project", ) 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 1ef62fe4..8f4855f7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -59,51 +59,49 @@ def _get_open_connections(client: Gcore | AsyncGcore) -> int: class TestGcore: - client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - @pytest.mark.respx(base_url=base_url) - def test_raw_response(self, respx_mock: MockRouter) -> None: + def test_raw_response(self, respx_mock: MockRouter, client: Gcore) -> None: respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = self.client.post("/foo", cast_to=httpx.Response) + response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} @pytest.mark.respx(base_url=base_url) - def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + def test_raw_response_for_binary(self, respx_mock: MockRouter, client: Gcore) -> None: respx_mock.post("/foo").mock( return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') ) - response = self.client.post("/foo", cast_to=httpx.Response) + response = client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} - def test_copy(self) -> None: - copied = self.client.copy() - assert id(copied) != id(self.client) + def test_copy(self, client: Gcore) -> None: + copied = client.copy() + assert id(copied) != id(client) - copied = self.client.copy(api_key="another My API Key") + copied = client.copy(api_key="another My API Key") assert copied.api_key == "another My API Key" - assert self.client.api_key == "My API Key" + assert client.api_key == "My API Key" - def test_copy_default_options(self) -> None: + def test_copy_default_options(self, client: Gcore) -> None: # options that have a default are overridden correctly - copied = self.client.copy(max_retries=7) + copied = client.copy(max_retries=7) assert copied.max_retries == 7 - assert self.client.max_retries == 2 + assert client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 assert copied.max_retries == 7 # timeout - assert isinstance(self.client.timeout, httpx.Timeout) - copied = self.client.copy(timeout=None) + assert isinstance(client.timeout, httpx.Timeout) + copied = client.copy(timeout=None) assert copied.timeout is None - assert isinstance(self.client.timeout, httpx.Timeout) + assert isinstance(client.timeout, httpx.Timeout) def test_copy_default_headers(self) -> None: client = Gcore( @@ -138,6 +136,7 @@ def test_copy_default_headers(self) -> None: match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + client.close() def test_copy_default_query(self) -> None: client = Gcore( @@ -175,13 +174,15 @@ def test_copy_default_query(self) -> None: ): client.copy(set_default_query={}, default_query={"foo": "Bar"}) - def test_copy_signature(self) -> None: + client.close() + + def test_copy_signature(self, client: Gcore) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( # mypy doesn't like that we access the `__init__` property. - self.client.__init__, # type: ignore[misc] + client.__init__, # type: ignore[misc] ) - copy_signature = inspect.signature(self.client.copy) + copy_signature = inspect.signature(client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} for name in init_signature.parameters.keys(): @@ -192,12 +193,12 @@ def test_copy_signature(self) -> None: assert copy_param is not None, f"copy() signature is missing the {name} param" @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") - def test_copy_build_request(self) -> None: + def test_copy_build_request(self, client: Gcore) -> None: options = FinalRequestOptions(method="get", url="/foo") def build_request(options: FinalRequestOptions) -> None: - client = self.client.copy() - client._build_request(options) + client_copy = client.copy() + client_copy._build_request(options) # ensure that the machinery is warmed up before tracing starts. build_request(options) @@ -254,14 +255,12 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic print(frame) raise AssertionError() - def test_request_timeout(self) -> None: - request = self.client._build_request(FinalRequestOptions(method="get", url="/foo")) + def test_request_timeout(self, client: Gcore) -> None: + request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT - request = self.client._build_request( - FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) - ) + request = client._build_request(FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0))) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(100.0) @@ -272,6 +271,8 @@ def test_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(0) + client.close() + def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used with httpx.Client(timeout=None) as http_client: @@ -283,6 +284,8 @@ def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(None) + client.close() + # no timeout given to the httpx client should not use the httpx default with httpx.Client() as http_client: client = Gcore( @@ -293,6 +296,8 @@ def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT + client.close() + # explicitly passing the default timeout currently results in it being ignored with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = Gcore( @@ -303,6 +308,8 @@ def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT # our default + client.close() + async def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): async with httpx.AsyncClient() as http_client: @@ -314,14 +321,14 @@ async def test_invalid_http_client(self) -> None: ) def test_default_headers_option(self) -> None: - client = Gcore( + test_client = Gcore( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" - client2 = Gcore( + test_client2 = Gcore( base_url=base_url, api_key=api_key, _strict_response_validation=True, @@ -330,10 +337,13 @@ def test_default_headers_option(self) -> None: "X-Stainless-Lang": "my-overriding-header", }, ) - request = client2._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" + test_client.close() + test_client2.close() + def test_validate_headers(self) -> None: client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -362,30 +372,28 @@ def test_default_query_option(self) -> None: url = httpx.URL(request.url) assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} - def test_cloud_project_id_client_params(self) -> None: - client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client.close() - with client as c2: - with pytest.raises(ValueError, match="Missing cloud_project_id argument;"): - c2.cloud.projects.update(name="New Project") + def test_cloud_project_id_client_params(self, client: Gcore) -> None: + # Test with base client (no custom params) + with pytest.raises(ValueError, match="Missing cloud_project_id argument;"): + client.cloud.projects.update(name="my-project") client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True, cloud_project_id=0) with client as c2: - c2.cloud.projects.update(name="New Project") + c2.cloud.projects.update(name="my-project") - def test_cloud_region_id_client_params(self) -> None: - client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - - with client as c2: - with pytest.raises(ValueError, match="Missing cloud_region_id argument;"): - c2.cloud.regions.get() + def test_cloud_region_id_client_params(self, client: Gcore) -> None: + # Test with base client (no custom params) + with pytest.raises(ValueError, match="Missing cloud_region_id argument;"): + client.cloud.regions.get() client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True, cloud_region_id=0) with client as c2: c2.cloud.regions.get() - def test_request_extra_json(self) -> None: - request = self.client._build_request( + def test_request_extra_json(self, client: Gcore) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -396,7 +404,7 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": False} - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -407,7 +415,7 @@ def test_request_extra_json(self) -> None: assert data == {"baz": False} # `extra_json` takes priority over `json_data` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -418,8 +426,8 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": None} - def test_request_extra_headers(self) -> None: - request = self.client._build_request( + def test_request_extra_headers(self, client: Gcore) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -429,7 +437,7 @@ def test_request_extra_headers(self) -> None: assert request.headers.get("X-Foo") == "Foo" # `extra_headers` takes priority over `default_headers` when keys clash - request = self.client.with_options(default_headers={"X-Bar": "true"})._build_request( + request = client.with_options(default_headers={"X-Bar": "true"})._build_request( FinalRequestOptions( method="post", url="/foo", @@ -440,8 +448,8 @@ def test_request_extra_headers(self) -> None: ) assert request.headers.get("X-Bar") == "false" - def test_request_extra_query(self) -> None: - request = self.client._build_request( + def test_request_extra_query(self, client: Gcore) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -454,7 +462,7 @@ def test_request_extra_query(self) -> None: assert params == {"my_query_param": "Foo"} # if both `query` and `extra_query` are given, they are merged - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -468,7 +476,7 @@ def test_request_extra_query(self) -> None: assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -511,7 +519,7 @@ def test_multipart_repeating_array(self, client: Gcore) -> None: ] @pytest.mark.respx(base_url=base_url) - def test_basic_union_response(self, respx_mock: MockRouter) -> None: + def test_basic_union_response(self, respx_mock: MockRouter, client: Gcore) -> None: class Model1(BaseModel): name: str @@ -520,12 +528,12 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" @pytest.mark.respx(base_url=base_url) - def test_union_response_different_types(self, respx_mock: MockRouter) -> None: + def test_union_response_different_types(self, respx_mock: MockRouter, client: Gcore) -> None: """Union of objects with the same field name using a different type""" class Model1(BaseModel): @@ -536,18 +544,18 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) - response = self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) - def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter) -> None: + def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter, client: Gcore) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ @@ -563,7 +571,7 @@ class Model(BaseModel): ) ) - response = self.client.get("/foo", cast_to=Model) + response = client.get("/foo", cast_to=Model) assert isinstance(response, Model) assert response.foo == 2 @@ -575,6 +583,8 @@ def test_base_url_setter(self) -> None: assert client.base_url == "https://example.com/from_setter/" + client.close() + def test_base_url_env(self) -> None: with update_env(GCORE_BASE_URL="http://localhost:5000/from/env"): client = Gcore(api_key=api_key, _strict_response_validation=True) @@ -602,6 +612,7 @@ def test_base_url_trailing_slash(self, client: Gcore) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + client.close() @pytest.mark.parametrize( "client", @@ -625,6 +636,7 @@ def test_base_url_no_trailing_slash(self, client: Gcore) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + client.close() @pytest.mark.parametrize( "client", @@ -648,35 +660,36 @@ def test_absolute_request_url(self, client: Gcore) -> None: ), ) assert request.url == "https://myapi.com/foo" + client.close() def test_copied_client_does_not_close_http(self) -> None: - client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - assert not client.is_closed() + test_client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) + assert not test_client.is_closed() - copied = client.copy() - assert copied is not client + copied = test_client.copy() + assert copied is not test_client del copied - assert not client.is_closed() + assert not test_client.is_closed() def test_client_context_manager(self) -> None: - client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - with client as c2: - assert c2 is client + test_client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) + with test_client as c2: + assert c2 is test_client assert not c2.is_closed() - assert not client.is_closed() - assert client.is_closed() + assert not test_client.is_closed() + assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) - def test_client_response_validation_error(self, respx_mock: MockRouter) -> None: + def test_client_response_validation_error(self, respx_mock: MockRouter, client: Gcore) -> None: class Model(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) with pytest.raises(APIResponseValidationError) as exc: - self.client.get("/foo", cast_to=Model) + client.get("/foo", cast_to=Model) assert isinstance(exc.value.__cause__, ValidationError) @@ -696,11 +709,14 @@ class Model(BaseModel): with pytest.raises(APIResponseValidationError): strict_client.get("/foo", cast_to=Model) - client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=False) + non_strict_client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=False) - response = client.get("/foo", cast_to=Model) + response = non_strict_client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] + strict_client.close() + non_strict_client.close() + @pytest.mark.parametrize( "remaining_retries,retry_after,timeout", [ @@ -723,9 +739,9 @@ class Model(BaseModel): ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = Gcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - + def test_parse_retry_after_header( + self, remaining_retries: int, retry_after: str, timeout: float, client: Gcore + ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) calculated = client._calculate_retry_timeout(remaining_retries, options, headers) @@ -737,9 +753,9 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien respx_mock.post("/cloud/v1/projects").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - client.cloud.projects.with_streaming_response.create(name="New Project").__enter__() + client.cloud.projects.with_streaming_response.create(name="my-project").__enter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(client) == 0 @mock.patch("gcore._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -747,8 +763,8 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client respx_mock.post("/cloud/v1/projects").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - client.cloud.projects.with_streaming_response.create(name="New Project").__enter__() - assert _get_open_connections(self.client) == 0 + client.cloud.projects.with_streaming_response.create(name="my-project").__enter__() + assert _get_open_connections(client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("gcore._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @@ -776,7 +792,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/cloud/v1/projects").mock(side_effect=retry_handler) - response = client.cloud.projects.with_raw_response.create(name="New Project") + response = client.cloud.projects.with_raw_response.create(name="my-project") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -799,7 +815,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/cloud/v1/projects").mock(side_effect=retry_handler) response = client.cloud.projects.with_raw_response.create( - name="New Project", extra_headers={"x-stainless-retry-count": Omit()} + name="my-project", extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -824,7 +840,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/cloud/v1/projects").mock(side_effect=retry_handler) response = client.cloud.projects.with_raw_response.create( - name="New Project", extra_headers={"x-stainless-retry-count": "42"} + name="my-project", extra_headers={"x-stainless-retry-count": "42"} ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -852,83 +868,77 @@ def test_default_client_creation(self) -> None: ) @pytest.mark.respx(base_url=base_url) - def test_follow_redirects(self, respx_mock: MockRouter) -> None: + def test_follow_redirects(self, respx_mock: MockRouter, client: Gcore) -> None: # Test that the default follow_redirects=True allows following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) - response = self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + response = client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) assert response.status_code == 200 assert response.json() == {"status": "ok"} @pytest.mark.respx(base_url=base_url) - def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + def test_follow_redirects_disabled(self, respx_mock: MockRouter, client: Gcore) -> None: # Test that follow_redirects=False prevents following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) with pytest.raises(APIStatusError) as exc_info: - self.client.post( - "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response - ) + client.post("/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response) assert exc_info.value.response.status_code == 302 assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" class TestAsyncGcore: - client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio - async def test_raw_response(self, respx_mock: MockRouter) -> None: + async def test_raw_response(self, respx_mock: MockRouter, async_client: AsyncGcore) -> None: respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = await self.client.post("/foo", cast_to=httpx.Response) + response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio - async def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + async def test_raw_response_for_binary(self, respx_mock: MockRouter, async_client: AsyncGcore) -> None: respx_mock.post("/foo").mock( return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') ) - response = await self.client.post("/foo", cast_to=httpx.Response) + response = await async_client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) assert response.json() == {"foo": "bar"} - def test_copy(self) -> None: - copied = self.client.copy() - assert id(copied) != id(self.client) + def test_copy(self, async_client: AsyncGcore) -> None: + copied = async_client.copy() + assert id(copied) != id(async_client) - copied = self.client.copy(api_key="another My API Key") + copied = async_client.copy(api_key="another My API Key") assert copied.api_key == "another My API Key" - assert self.client.api_key == "My API Key" + assert async_client.api_key == "My API Key" - def test_copy_default_options(self) -> None: + def test_copy_default_options(self, async_client: AsyncGcore) -> None: # options that have a default are overridden correctly - copied = self.client.copy(max_retries=7) + copied = async_client.copy(max_retries=7) assert copied.max_retries == 7 - assert self.client.max_retries == 2 + assert async_client.max_retries == 2 copied2 = copied.copy(max_retries=6) assert copied2.max_retries == 6 assert copied.max_retries == 7 # timeout - assert isinstance(self.client.timeout, httpx.Timeout) - copied = self.client.copy(timeout=None) + assert isinstance(async_client.timeout, httpx.Timeout) + copied = async_client.copy(timeout=None) assert copied.timeout is None - assert isinstance(self.client.timeout, httpx.Timeout) + assert isinstance(async_client.timeout, httpx.Timeout) - def test_copy_default_headers(self) -> None: + async def test_copy_default_headers(self) -> None: client = AsyncGcore( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) @@ -961,8 +971,9 @@ def test_copy_default_headers(self) -> None: match="`default_headers` and `set_default_headers` arguments are mutually exclusive", ): client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) + await client.close() - def test_copy_default_query(self) -> None: + async def test_copy_default_query(self) -> None: client = AsyncGcore( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} ) @@ -998,13 +1009,15 @@ def test_copy_default_query(self) -> None: ): client.copy(set_default_query={}, default_query={"foo": "Bar"}) - def test_copy_signature(self) -> None: + await client.close() + + def test_copy_signature(self, async_client: AsyncGcore) -> None: # ensure the same parameters that can be passed to the client are defined in the `.copy()` method init_signature = inspect.signature( # mypy doesn't like that we access the `__init__` property. - self.client.__init__, # type: ignore[misc] + async_client.__init__, # type: ignore[misc] ) - copy_signature = inspect.signature(self.client.copy) + copy_signature = inspect.signature(async_client.copy) exclude_params = {"transport", "proxies", "_strict_response_validation"} for name in init_signature.parameters.keys(): @@ -1015,12 +1028,12 @@ def test_copy_signature(self) -> None: assert copy_param is not None, f"copy() signature is missing the {name} param" @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") - def test_copy_build_request(self) -> None: + def test_copy_build_request(self, async_client: AsyncGcore) -> None: options = FinalRequestOptions(method="get", url="/foo") def build_request(options: FinalRequestOptions) -> None: - client = self.client.copy() - client._build_request(options) + client_copy = async_client.copy() + client_copy._build_request(options) # ensure that the machinery is warmed up before tracing starts. build_request(options) @@ -1077,12 +1090,12 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic print(frame) raise AssertionError() - async def test_request_timeout(self) -> None: - request = self.client._build_request(FinalRequestOptions(method="get", url="/foo")) + async def test_request_timeout(self, async_client: AsyncGcore) -> None: + request = async_client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT - request = self.client._build_request( + request = async_client._build_request( FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) ) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore @@ -1097,6 +1110,8 @@ async def test_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(0) + await client.close() + async def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used async with httpx.AsyncClient(timeout=None) as http_client: @@ -1108,6 +1123,8 @@ async def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == httpx.Timeout(None) + await client.close() + # no timeout given to the httpx client should not use the httpx default async with httpx.AsyncClient() as http_client: client = AsyncGcore( @@ -1118,6 +1135,8 @@ async def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT + await client.close() + # explicitly passing the default timeout currently results in it being ignored async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = AsyncGcore( @@ -1128,6 +1147,8 @@ async def test_http_client_timeout_option(self) -> None: timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore assert timeout == DEFAULT_TIMEOUT # our default + await client.close() + def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): with httpx.Client() as http_client: @@ -1138,15 +1159,15 @@ def test_invalid_http_client(self) -> None: http_client=cast(Any, http_client), ) - def test_default_headers_option(self) -> None: - client = AsyncGcore( + async def test_default_headers_option(self) -> None: + test_client = AsyncGcore( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" - client2 = AsyncGcore( + test_client2 = AsyncGcore( base_url=base_url, api_key=api_key, _strict_response_validation=True, @@ -1155,10 +1176,13 @@ def test_default_headers_option(self) -> None: "X-Stainless-Lang": "my-overriding-header", }, ) - request = client2._build_request(FinalRequestOptions(method="get", url="/foo")) + request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" + await test_client.close() + await test_client2.close() + def test_validate_headers(self) -> None: client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1169,7 +1193,7 @@ def test_validate_headers(self) -> None: client2 = AsyncGcore(base_url=base_url, api_key=None, _strict_response_validation=True) _ = client2 - def test_default_query_option(self) -> None: + async def test_default_query_option(self) -> None: client = AsyncGcore( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} ) @@ -1187,30 +1211,28 @@ def test_default_query_option(self) -> None: url = httpx.URL(request.url) assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} - async def test_cloud_project_id_client_params(self) -> None: - client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) + await client.close() - async with client as c2: - with pytest.raises(ValueError, match="Missing cloud_project_id argument;"): - await c2.cloud.projects.update(name="New Project") + async def test_cloud_project_id_client_params(self, async_client: AsyncGcore) -> None: + # Test with base client (no custom params) + with pytest.raises(ValueError, match="Missing cloud_project_id argument;"): + await async_client.cloud.projects.update(name="my-project") client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True, cloud_project_id=0) async with client as c2: - await c2.cloud.projects.update(name="New Project") + await c2.cloud.projects.update(name="my-project") - async def test_cloud_region_id_client_params(self) -> None: - client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - - async with client as c2: - with pytest.raises(ValueError, match="Missing cloud_region_id argument;"): - await c2.cloud.regions.get() + async def test_cloud_region_id_client_params(self, async_client: AsyncGcore) -> None: + # Test with base client (no custom params) + with pytest.raises(ValueError, match="Missing cloud_region_id argument;"): + await async_client.cloud.regions.get() client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True, cloud_region_id=0) async with client as c2: await c2.cloud.regions.get() - def test_request_extra_json(self) -> None: - request = self.client._build_request( + def test_request_extra_json(self, client: Gcore) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1221,7 +1243,7 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": False} - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1232,7 +1254,7 @@ def test_request_extra_json(self) -> None: assert data == {"baz": False} # `extra_json` takes priority over `json_data` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1243,8 +1265,8 @@ def test_request_extra_json(self) -> None: data = json.loads(request.content.decode("utf-8")) assert data == {"foo": "bar", "baz": None} - def test_request_extra_headers(self) -> None: - request = self.client._build_request( + def test_request_extra_headers(self, client: Gcore) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1254,7 +1276,7 @@ def test_request_extra_headers(self) -> None: assert request.headers.get("X-Foo") == "Foo" # `extra_headers` takes priority over `default_headers` when keys clash - request = self.client.with_options(default_headers={"X-Bar": "true"})._build_request( + request = client.with_options(default_headers={"X-Bar": "true"})._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1265,8 +1287,8 @@ def test_request_extra_headers(self) -> None: ) assert request.headers.get("X-Bar") == "false" - def test_request_extra_query(self) -> None: - request = self.client._build_request( + def test_request_extra_query(self, client: Gcore) -> None: + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1279,7 +1301,7 @@ def test_request_extra_query(self) -> None: assert params == {"my_query_param": "Foo"} # if both `query` and `extra_query` are given, they are merged - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1293,7 +1315,7 @@ def test_request_extra_query(self) -> None: assert params == {"bar": "1", "foo": "2"} # `extra_query` takes priority over `query` when keys clash - request = self.client._build_request( + request = client._build_request( FinalRequestOptions( method="post", url="/foo", @@ -1336,7 +1358,7 @@ def test_multipart_repeating_array(self, async_client: AsyncGcore) -> None: ] @pytest.mark.respx(base_url=base_url) - async def test_basic_union_response(self, respx_mock: MockRouter) -> None: + async def test_basic_union_response(self, respx_mock: MockRouter, async_client: AsyncGcore) -> None: class Model1(BaseModel): name: str @@ -1345,12 +1367,12 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" @pytest.mark.respx(base_url=base_url) - async def test_union_response_different_types(self, respx_mock: MockRouter) -> None: + async def test_union_response_different_types(self, respx_mock: MockRouter, async_client: AsyncGcore) -> None: """Union of objects with the same field name using a different type""" class Model1(BaseModel): @@ -1361,18 +1383,20 @@ class Model2(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model2) assert response.foo == "bar" respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) - response = await self.client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) + response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) assert isinstance(response, Model1) assert response.foo == 1 @pytest.mark.respx(base_url=base_url) - async def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter) -> None: + async def test_non_application_json_content_type_for_json_data( + self, respx_mock: MockRouter, async_client: AsyncGcore + ) -> None: """ Response that sets Content-Type to something other than application/json but returns json data """ @@ -1388,11 +1412,11 @@ class Model(BaseModel): ) ) - response = await self.client.get("/foo", cast_to=Model) + response = await async_client.get("/foo", cast_to=Model) assert isinstance(response, Model) assert response.foo == 2 - def test_base_url_setter(self) -> None: + async def test_base_url_setter(self) -> None: client = AsyncGcore(base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True) assert client.base_url == "https://example.com/from_init/" @@ -1400,7 +1424,9 @@ def test_base_url_setter(self) -> None: assert client.base_url == "https://example.com/from_setter/" - def test_base_url_env(self) -> None: + await client.close() + + async def test_base_url_env(self) -> None: with update_env(GCORE_BASE_URL="http://localhost:5000/from/env"): client = AsyncGcore(api_key=api_key, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" @@ -1420,7 +1446,7 @@ def test_base_url_env(self) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_trailing_slash(self, client: AsyncGcore) -> None: + async def test_base_url_trailing_slash(self, client: AsyncGcore) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1429,6 +1455,7 @@ def test_base_url_trailing_slash(self, client: AsyncGcore) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + await client.close() @pytest.mark.parametrize( "client", @@ -1445,7 +1472,7 @@ def test_base_url_trailing_slash(self, client: AsyncGcore) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_no_trailing_slash(self, client: AsyncGcore) -> None: + async def test_base_url_no_trailing_slash(self, client: AsyncGcore) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1454,6 +1481,7 @@ def test_base_url_no_trailing_slash(self, client: AsyncGcore) -> None: ), ) assert request.url == "http://localhost:5000/custom/path/foo" + await client.close() @pytest.mark.parametrize( "client", @@ -1470,7 +1498,7 @@ def test_base_url_no_trailing_slash(self, client: AsyncGcore) -> None: ], ids=["standard", "custom http client"], ) - def test_absolute_request_url(self, client: AsyncGcore) -> None: + async def test_absolute_request_url(self, client: AsyncGcore) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1479,37 +1507,37 @@ def test_absolute_request_url(self, client: AsyncGcore) -> None: ), ) assert request.url == "https://myapi.com/foo" + await client.close() async def test_copied_client_does_not_close_http(self) -> None: - client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - assert not client.is_closed() + test_client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) + assert not test_client.is_closed() - copied = client.copy() - assert copied is not client + copied = test_client.copy() + assert copied is not test_client del copied await asyncio.sleep(0.2) - assert not client.is_closed() + assert not test_client.is_closed() async def test_client_context_manager(self) -> None: - client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - async with client as c2: - assert c2 is client + test_client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) + async with test_client as c2: + assert c2 is test_client assert not c2.is_closed() - assert not client.is_closed() - assert client.is_closed() + assert not test_client.is_closed() + assert test_client.is_closed() @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio - async def test_client_response_validation_error(self, respx_mock: MockRouter) -> None: + async def test_client_response_validation_error(self, respx_mock: MockRouter, async_client: AsyncGcore) -> None: class Model(BaseModel): foo: str respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) with pytest.raises(APIResponseValidationError) as exc: - await self.client.get("/foo", cast_to=Model) + await async_client.get("/foo", cast_to=Model) assert isinstance(exc.value.__cause__, ValidationError) @@ -1520,7 +1548,6 @@ async def test_client_max_retries_validation(self) -> None: ) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio async def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: class Model(BaseModel): name: str @@ -1532,11 +1559,14 @@ class Model(BaseModel): with pytest.raises(APIResponseValidationError): await strict_client.get("/foo", cast_to=Model) - client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=False) + non_strict_client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=False) - response = await client.get("/foo", cast_to=Model) + response = await non_strict_client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] + await strict_client.close() + await non_strict_client.close() + @pytest.mark.parametrize( "remaining_retries,retry_after,timeout", [ @@ -1559,13 +1589,12 @@ class Model(BaseModel): ], ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - @pytest.mark.asyncio - async def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = AsyncGcore(base_url=base_url, api_key=api_key, _strict_response_validation=True) - + async def test_parse_retry_after_header( + self, remaining_retries: int, retry_after: str, timeout: float, async_client: AsyncGcore + ) -> None: headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) - calculated = client._calculate_retry_timeout(remaining_retries, options, headers) + calculated = async_client._calculate_retry_timeout(remaining_retries, options, headers) assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] @mock.patch("gcore._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @@ -1574,9 +1603,9 @@ async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, respx_mock.post("/cloud/v1/projects").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - await async_client.cloud.projects.with_streaming_response.create(name="New Project").__aenter__() + await async_client.cloud.projects.with_streaming_response.create(name="my-project").__aenter__() - assert _get_open_connections(self.client) == 0 + assert _get_open_connections(async_client) == 0 @mock.patch("gcore._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @@ -1584,13 +1613,12 @@ async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, respx_mock.post("/cloud/v1/projects").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - await async_client.cloud.projects.with_streaming_response.create(name="New Project").__aenter__() - assert _get_open_connections(self.client) == 0 + await async_client.cloud.projects.with_streaming_response.create(name="my-project").__aenter__() + assert _get_open_connections(async_client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("gcore._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio @pytest.mark.parametrize("failure_mode", ["status", "exception"]) async def test_retries_taken( self, @@ -1614,7 +1642,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/cloud/v1/projects").mock(side_effect=retry_handler) - response = await client.cloud.projects.with_raw_response.create(name="New Project") + response = await client.cloud.projects.with_raw_response.create(name="my-project") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1622,7 +1650,6 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("gcore._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio async def test_omit_retry_count_header( self, async_client: AsyncGcore, failures_before_success: int, respx_mock: MockRouter ) -> None: @@ -1640,7 +1667,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/cloud/v1/projects").mock(side_effect=retry_handler) response = await client.cloud.projects.with_raw_response.create( - name="New Project", extra_headers={"x-stainless-retry-count": Omit()} + name="my-project", extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1648,7 +1675,6 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("gcore._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - @pytest.mark.asyncio async def test_overwrite_retry_count_header( self, async_client: AsyncGcore, failures_before_success: int, respx_mock: MockRouter ) -> None: @@ -1666,7 +1692,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/cloud/v1/projects").mock(side_effect=retry_handler) response = await client.cloud.projects.with_raw_response.create( - name="New Project", extra_headers={"x-stainless-retry-count": "42"} + name="my-project", extra_headers={"x-stainless-retry-count": "42"} ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1698,26 +1724,26 @@ async def test_default_client_creation(self) -> None: ) @pytest.mark.respx(base_url=base_url) - async def test_follow_redirects(self, respx_mock: MockRouter) -> None: + async def test_follow_redirects(self, respx_mock: MockRouter, async_client: AsyncGcore) -> None: # Test that the default follow_redirects=True allows following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) - response = await self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + response = await async_client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) assert response.status_code == 200 assert response.json() == {"status": "ok"} @pytest.mark.respx(base_url=base_url) - async def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + async def test_follow_redirects_disabled(self, respx_mock: MockRouter, async_client: AsyncGcore) -> None: # Test that follow_redirects=False prevents following redirects respx_mock.post("/redirect").mock( return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) ) with pytest.raises(APIStatusError) as exc_info: - await self.client.post( + await async_client.post( "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response )