From 926c0ddfcef420ba47eca7b399ea43462a18371a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 08:49:18 +0000 Subject: [PATCH 01/27] feat(api): aggregated API specs update --- .stats.yml | 4 +- api.md | 4 +- src/gcore/resources/cdn/ip_ranges.py | 102 +++++++++++++++- src/gcore/resources/cdn/statistics.py | 114 +++++++++--------- src/gcore/resources/cloud/quotas/requests.py | 8 -- src/gcore/types/cdn/__init__.py | 2 + .../types/cdn/ip_range_list_ips_params.py | 19 +++ src/gcore/types/cdn/ip_range_list_params.py | 19 +++ src/gcore/types/cdn/resource_usage_stats.py | 31 ++--- ...tistic_get_logs_usage_aggregated_params.py | 5 +- .../statistic_get_logs_usage_series_params.py | 17 +-- ...ic_get_resource_usage_aggregated_params.py | 31 ++--- ...tistic_get_resource_usage_series_params.py | 7 +- ...stic_get_shield_usage_aggregated_params.py | 7 +- ...tatistic_get_shield_usage_series_params.py | 3 + .../cloud/quotas/request_create_params.py | 3 - src/gcore/types/cloud/security_group.py | 9 +- tests/api_resources/cdn/test_ip_ranges.py | 32 +++++ .../cloud/quotas/test_requests.py | 2 - 19 files changed, 286 insertions(+), 133 deletions(-) create mode 100644 src/gcore/types/cdn/ip_range_list_ips_params.py create mode 100644 src/gcore/types/cdn/ip_range_list_params.py diff --git a/.stats.yml b/.stats.yml index fd2d5539..c8537dbe 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 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-593c5e99888d61f0b89a96221b71679316ae326fe0bf7468d93a3f4d73d06e8c.yml +openapi_spec_hash: cfd6560b017a4ff1d003e335b739f2f3 config_hash: bb4a27712c30f7a2b52e1f3b31766f24 diff --git a/api.md b/api.md index 01ab7916..8904e330 100644 --- a/api.md +++ b/api.md @@ -2383,5 +2383,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/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/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/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/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_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/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/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/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 From 434bf068d53bb1cf34329710f484b6873ed457a0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 09:44:53 +0000 Subject: [PATCH 02/27] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c8537dbe..e310623d 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-593c5e99888d61f0b89a96221b71679316ae326fe0bf7468d93a3f4d73d06e8c.yml -openapi_spec_hash: cfd6560b017a4ff1d003e335b739f2f3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-f1aa5e69e579d8ef50ab8dbc55b74e312029a61a8764dd5eb6b71d186f31ffc4.yml +openapi_spec_hash: 79d6c39952e4e8ef5a10705031cc88af config_hash: bb4a27712c30f7a2b52e1f3b31766f24 From 203e4ba94f655ae11fae8ed32611f6291f2acaf1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 13:41:14 +0000 Subject: [PATCH 03/27] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e310623d..20191264 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-f1aa5e69e579d8ef50ab8dbc55b74e312029a61a8764dd5eb6b71d186f31ffc4.yml -openapi_spec_hash: 79d6c39952e4e8ef5a10705031cc88af +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-7f43b28f5f3787d90ad3097b603d78732c31602963a0706e9d3faab773ffe35a.yml +openapi_spec_hash: d3684a66988042fe56ddad6fea6a0373 config_hash: bb4a27712c30f7a2b52e1f3b31766f24 From 4dc12a7f67f12022e019ff0305697d4e91dbef51 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 15:12:26 +0000 Subject: [PATCH 04/27] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 20191264..4e936b75 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-7f43b28f5f3787d90ad3097b603d78732c31602963a0706e9d3faab773ffe35a.yml -openapi_spec_hash: d3684a66988042fe56ddad6fea6a0373 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-926c452d13564ca1a0c7a5f6d4596d9ae2f0b62087bfe0f3229eae1e76cb9a86.yml +openapi_spec_hash: a887cd2beb7fe136a63a14ad3508462b config_hash: bb4a27712c30f7a2b52e1f3b31766f24 From a281b357bb9f765e5a12d1beedd1eb703d71b13f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Oct 2025 07:22:39 +0000 Subject: [PATCH 05/27] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4e936b75..dab5821b 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-926c452d13564ca1a0c7a5f6d4596d9ae2f0b62087bfe0f3229eae1e76cb9a86.yml -openapi_spec_hash: a887cd2beb7fe136a63a14ad3508462b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-f7fe3d141383d9367eea75565a3dae94897e44354066b110db09dacf0f581187.yml +openapi_spec_hash: f710af685b8aa4d0f7962a77fd13ee40 config_hash: bb4a27712c30f7a2b52e1f3b31766f24 From 05ac34fc31ea3bff2a5db5f0cce753c8d0fa2ba2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 07:50:27 +0000 Subject: [PATCH 06/27] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index dab5821b..de0ab459 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-f7fe3d141383d9367eea75565a3dae94897e44354066b110db09dacf0f581187.yml -openapi_spec_hash: f710af685b8aa4d0f7962a77fd13ee40 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-99fc33842c158346e3b39e07fc0cef0151a5fe60c003494d60d73e3e1221d083.yml +openapi_spec_hash: 0a9e2bf938e4490d06959e14b65f3ab0 config_hash: bb4a27712c30f7a2b52e1f3b31766f24 From 25247c75001ac77c3f1c25da38ec57cd394ec5e6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 08:22:47 +0000 Subject: [PATCH 07/27] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index de0ab459..78cae3bd 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-99fc33842c158346e3b39e07fc0cef0151a5fe60c003494d60d73e3e1221d083.yml -openapi_spec_hash: 0a9e2bf938e4490d06959e14b65f3ab0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-286a65430a65eb4a40437fca2268857a509498373c2d8def0557e6dbd873dd41.yml +openapi_spec_hash: 25cb371f8eacd4951b1f7f8451201e83 config_hash: bb4a27712c30f7a2b52e1f3b31766f24 From d8886ce4abeadd3d260c3f533e72b778d521482c Mon Sep 17 00:00:00 2001 From: Danil Krox Date: Fri, 24 Oct 2025 15:30:26 +0200 Subject: [PATCH 08/27] chore(cloud): add *_and_poll() to *WithRawResponse and *WithStreaming --- .../resources/cloud/baremetal/servers.py | 24 ++++++++ .../gpu_baremetal_clusters.py | 36 +++++++++++ .../cloud/gpu_baremetal_clusters/images.py | 24 ++++++++ .../cloud/gpu_baremetal_clusters/servers.py | 12 ++++ .../inference/deployments/deployments.py | 36 +++++++++++ src/gcore/resources/cloud/instances/images.py | 36 +++++++++++ .../resources/cloud/instances/instances.py | 60 +++++++++++++++++++ .../load_balancers/l7_policies/l7_policies.py | 36 +++++++++++ .../cloud/load_balancers/l7_policies/rules.py | 36 +++++++++++ .../cloud/load_balancers/listeners.py | 36 +++++++++++ .../cloud/load_balancers/load_balancers.py | 48 +++++++++++++++ .../cloud/load_balancers/pools/pools.py | 36 +++++++++++ src/gcore/resources/cloud/secrets.py | 12 ++++ 13 files changed, 432 insertions(+) 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/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..da0a38a1 100644 --- a/src/gcore/resources/cloud/load_balancers/listeners.py +++ b/src/gcore/resources/cloud/load_balancers/listeners.py @@ -1109,6 +1109,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 +1139,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 +1169,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 +1199,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..b258a0f1 100644 --- a/src/gcore/resources/cloud/load_balancers/pools/pools.py +++ b/src/gcore/resources/cloud/load_balancers/pools/pools.py @@ -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/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, + ) From 18614cb786fd3ea9020cee18c2a23c4c81f116f3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 08:13:41 +0000 Subject: [PATCH 09/27] feat(api): aggregated API specs update --- .stats.yml | 4 ++-- tests/api_resources/cdn/test_resources.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 78cae3bd..60b9cef8 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-286a65430a65eb4a40437fca2268857a509498373c2d8def0557e6dbd873dd41.yml -openapi_spec_hash: 25cb371f8eacd4951b1f7f8451201e83 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-3f6cc1eae983d7512f2a83d113890737b5af78501b08d3b87d1c6a8e888671c7.yml +openapi_spec_hash: 41d631be71afa942d320dc4f57f2b919 config_hash: bb4a27712c30f7a2b52e1f3b31766f24 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 From da1429d0a0a3dba3079b816c930b44853e5946d4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 12:15:28 +0000 Subject: [PATCH 10/27] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 60b9cef8..8927182b 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-3f6cc1eae983d7512f2a83d113890737b5af78501b08d3b87d1c6a8e888671c7.yml -openapi_spec_hash: 41d631be71afa942d320dc4f57f2b919 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-40612ca61459a98a98276b2788ba9fcdb457df1ecbbaa3556a3a379ce4de8272.yml +openapi_spec_hash: 619b199ac27e1919bc7d9996455fd96b config_hash: bb4a27712c30f7a2b52e1f3b31766f24 From 4e629534e07db80d93c46e5ccc5e3d2ba48d9eb4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:10:49 +0000 Subject: [PATCH 11/27] feat(api): aggregated API specs update --- .stats.yml | 4 ++-- src/gcore/types/cdn/cdn_resource.py | 10 ++++++++-- src/gcore/types/cdn/resource_create_params.py | 10 ++++++++-- src/gcore/types/cdn/resource_replace_params.py | 10 ++++++++-- src/gcore/types/cdn/resource_update_params.py | 10 ++++++++-- src/gcore/types/cdn/resources/cdn_resource_rule.py | 10 ++++++++-- src/gcore/types/cdn/resources/rule_create_params.py | 10 ++++++++-- src/gcore/types/cdn/resources/rule_replace_params.py | 10 ++++++++-- src/gcore/types/cdn/resources/rule_update_params.py | 10 ++++++++-- src/gcore/types/cdn/rule_template.py | 10 ++++++++-- src/gcore/types/cdn/rule_template_create_params.py | 10 ++++++++-- src/gcore/types/cdn/rule_template_replace_params.py | 10 ++++++++-- src/gcore/types/cdn/rule_template_update_params.py | 10 ++++++++-- 13 files changed, 98 insertions(+), 26 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8927182b..c7e76cf1 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-40612ca61459a98a98276b2788ba9fcdb457df1ecbbaa3556a3a379ce4de8272.yml -openapi_spec_hash: 619b199ac27e1919bc7d9996455fd96b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-9a8804253e6b10b100fd87d24631d4b6e3fb018fa6e57bb9a7404af7cae5c132.yml +openapi_spec_hash: 1fd683372fd558a27e495fb2d2aa7141 config_hash: bb4a27712c30f7a2b52e1f3b31766f24 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/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/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): From 94f0e4695389f59df18aeda5ef4eaebcb95d90ed Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 10:11:42 +0000 Subject: [PATCH 12/27] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c7e76cf1..c6f718d3 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-9a8804253e6b10b100fd87d24631d4b6e3fb018fa6e57bb9a7404af7cae5c132.yml -openapi_spec_hash: 1fd683372fd558a27e495fb2d2aa7141 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-7a2f7e9dd81da1b84b614443585eb99dca6581b155f778de2af43cf9e02ff144.yml +openapi_spec_hash: 236bdc057e30d676bc46e7d4f22cbee7 config_hash: bb4a27712c30f7a2b52e1f3b31766f24 From af54c886222ea41e6ef57d8683fbb64e2b688a15 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 12:15:36 +0000 Subject: [PATCH 13/27] feat(api): aggregated API specs update --- .stats.yml | 4 +-- api.md | 2 +- .../cloud/load_balancers/listeners.py | 35 +++++++++++++++---- .../cloud/load_balancer_create_params.py | 5 ++- .../types/cloud/load_balancers/__init__.py | 1 + .../load_balancers/listener_create_params.py | 5 ++- .../load_balancers/listener_delete_params.py | 18 ++++++++++ .../load_balancers/listener_update_params.py | 5 ++- .../cloud/load_balancers/test_listeners.py | 20 +++++++++++ 9 files changed, 83 insertions(+), 12 deletions(-) create mode 100644 src/gcore/types/cloud/load_balancers/listener_delete_params.py diff --git a/.stats.yml b/.stats.yml index c6f718d3..035cadcd 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-7a2f7e9dd81da1b84b614443585eb99dca6581b155f778de2af43cf9e02ff144.yml -openapi_spec_hash: 236bdc057e30d676bc46e7d4f22cbee7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-7bb076221b6b8c4e465291804fa37dfec95dc815c0670753eec9e02420aef8eb.yml +openapi_spec_hash: 5c56fa55767a46498c083e3fa940c227 config_hash: bb4a27712c30f7a2b52e1f3b31766f24 diff --git a/api.md b/api.md index 8904e330..6ff46915 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 diff --git a/src/gcore/resources/cloud/load_balancers/listeners.py b/src/gcore/resources/cloud/load_balancers/listeners.py index da0a38a1..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, ) diff --git a/src/gcore/types/cloud/load_balancer_create_params.py b/src/gcore/types/cloud/load_balancer_create_params.py index a41fd6e4..0ab6f5ce 100644 --- a/src/gcore/types/cloud/load_balancer_create_params.py +++ b/src/gcore/types/cloud/load_balancer_create_params.py @@ -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/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( From a25394192b45e4da62fbf94ead1f9774598052b3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 09:46:24 +0000 Subject: [PATCH 14/27] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 035cadcd..e33bba97 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-7bb076221b6b8c4e465291804fa37dfec95dc815c0670753eec9e02420aef8eb.yml openapi_spec_hash: 5c56fa55767a46498c083e3fa940c227 -config_hash: bb4a27712c30f7a2b52e1f3b31766f24 +config_hash: 25b1dd444559d26e51bf85892358c0bc From cd7152cd959a9984e5c60edb41d16fa2db342012 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:43:04 +0000 Subject: [PATCH 15/27] fix(client): close streams without requiring full consumption --- src/gcore/_streaming.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) 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 From 3ef8586481df9533a0627310458bb72b9b458d2f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:15:35 +0000 Subject: [PATCH 16/27] feat(api): aggregated API specs update --- .stats.yml | 4 ++-- src/gcore/types/cloud/gpu_baremetal_cluster.py | 14 +++++++++++++- .../cloud/gpu_baremetal_cluster_create_params.py | 12 ++++++++++++ .../cloud/test_gpu_baremetal_clusters.py | 12 ++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index e33bba97..f535120f 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-7bb076221b6b8c4e465291804fa37dfec95dc815c0670753eec9e02420aef8eb.yml -openapi_spec_hash: 5c56fa55767a46498c083e3fa940c227 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-848b764e60807c1c1aedd39ebdbadd2ee63dcc6ae3910179cdfff3ef80429563.yml +openapi_spec_hash: 04d6bac6704e464b0fa52af0cd0e18a2 config_hash: 25b1dd444559d26e51bf85892358c0bc 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/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==", }, From 67e4c77936fca0b2192b931ec71003dd62383c81 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 11:03:32 +0000 Subject: [PATCH 17/27] chore(internal/tests): avoid race condition with implicit client cleanup --- tests/test_client.py | 398 +++++++++++++++++++++++-------------------- 1 file changed, 212 insertions(+), 186 deletions(-) diff --git a/tests/test_client.py b/tests/test_client.py index 1ef62fe4..5e4cd0ed 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="New 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") - 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) @@ -739,7 +755,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien with pytest.raises(APITimeoutError): client.cloud.projects.with_streaming_response.create(name="New 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) @@ -748,7 +764,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client with pytest.raises(APIStatusError): client.cloud.projects.with_streaming_response.create(name="New Project").__enter__() - assert _get_open_connections(self.client) == 0 + 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) @@ -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="New 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") - 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) @@ -1576,7 +1605,7 @@ async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, with pytest.raises(APITimeoutError): await async_client.cloud.projects.with_streaming_response.create(name="New 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) @@ -1585,12 +1614,11 @@ async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, with pytest.raises(APIStatusError): await async_client.cloud.projects.with_streaming_response.create(name="New Project").__aenter__() - assert _get_open_connections(self.client) == 0 + 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, @@ -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: @@ -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: @@ -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 ) From 62b23ee2f8f81f4f2159cee48dc6133463bbf526 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 14:25:37 +0000 Subject: [PATCH 18/27] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index f535120f..4f5a18fa 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-848b764e60807c1c1aedd39ebdbadd2ee63dcc6ae3910179cdfff3ef80429563.yml openapi_spec_hash: 04d6bac6704e464b0fa52af0cd0e18a2 -config_hash: 25b1dd444559d26e51bf85892358c0bc +config_hash: 4758209f53bb13d06f55e4cf6c952b6d From 9f6d1a715b8a64fc4973d80f5d511ecaf878837e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 16:12:06 +0000 Subject: [PATCH 19/27] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4f5a18fa..c4fe28d4 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-848b764e60807c1c1aedd39ebdbadd2ee63dcc6ae3910179cdfff3ef80429563.yml -openapi_spec_hash: 04d6bac6704e464b0fa52af0cd0e18a2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-0346b042bad7a80c3a1d4281080d8196a2e7fe31d16555fa09a969c17135802d.yml +openapi_spec_hash: 89f372e20779803f35c14b4189960972 config_hash: 4758209f53bb13d06f55e4cf6c952b6d From 01c746977c89d813e54b97c87513960a5cba42c3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 10:12:06 +0000 Subject: [PATCH 20/27] feat(api): aggregated API specs update --- .stats.yml | 6 +- api.md | 42 +- src/gcore/_client.py | 9 - src/gcore/resources/__init__.py | 14 - src/gcore/resources/security/__init__.py | 75 -- src/gcore/resources/security/bgp_announces.py | 308 -------- src/gcore/resources/security/events.py | 234 ------- .../resources/security/profile_templates.py | 143 ---- src/gcore/resources/security/profiles.py | 661 ------------------ src/gcore/resources/security/security.py | 198 ------ src/gcore/types/security/__init__.py | 15 - .../security/bgp_announce_list_params.py | 18 - .../security/bgp_announce_list_response.py | 10 - .../security/bgp_announce_toggle_params.py | 16 - src/gcore/types/security/client_announce.py | 15 - src/gcore/types/security/client_profile.py | 56 -- .../types/security/client_profile_template.py | 43 -- src/gcore/types/security/client_view.py | 29 - src/gcore/types/security/event_list_params.py | 38 - .../types/security/profile_create_params.py | 24 - .../types/security/profile_list_params.py | 17 - .../types/security/profile_list_response.py | 10 - .../types/security/profile_recreate_params.py | 24 - .../types/security/profile_replace_params.py | 24 - .../profile_template_list_response.py | 10 - tests/api_resources/security/__init__.py | 1 - .../security/test_bgp_announces.py | 180 ----- tests/api_resources/security/test_events.py | 102 --- .../security/test_profile_templates.py | 74 -- tests/api_resources/security/test_profiles.py | 537 -------------- 30 files changed, 5 insertions(+), 2928 deletions(-) delete mode 100644 src/gcore/resources/security/__init__.py delete mode 100644 src/gcore/resources/security/bgp_announces.py delete mode 100644 src/gcore/resources/security/events.py delete mode 100644 src/gcore/resources/security/profile_templates.py delete mode 100644 src/gcore/resources/security/profiles.py delete mode 100644 src/gcore/resources/security/security.py delete mode 100644 src/gcore/types/security/bgp_announce_list_params.py delete mode 100644 src/gcore/types/security/bgp_announce_list_response.py delete mode 100644 src/gcore/types/security/bgp_announce_toggle_params.py delete mode 100644 src/gcore/types/security/client_announce.py delete mode 100644 src/gcore/types/security/client_profile.py delete mode 100644 src/gcore/types/security/client_profile_template.py delete mode 100644 src/gcore/types/security/client_view.py delete mode 100644 src/gcore/types/security/event_list_params.py delete mode 100644 src/gcore/types/security/profile_create_params.py delete mode 100644 src/gcore/types/security/profile_list_params.py delete mode 100644 src/gcore/types/security/profile_list_response.py delete mode 100644 src/gcore/types/security/profile_recreate_params.py delete mode 100644 src/gcore/types/security/profile_replace_params.py delete mode 100644 src/gcore/types/security/profile_template_list_response.py delete mode 100644 tests/api_resources/security/__init__.py delete mode 100644 tests/api_resources/security/test_bgp_announces.py delete mode 100644 tests/api_resources/security/test_events.py delete mode 100644 tests/api_resources/security/test_profile_templates.py delete mode 100644 tests/api_resources/security/test_profiles.py diff --git a/.stats.yml b/.stats.yml index c4fe28d4..d0525a7d 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-0346b042bad7a80c3a1d4281080d8196a2e7fe31d16555fa09a969c17135802d.yml -openapi_spec_hash: 89f372e20779803f35c14b4189960972 +configured_endpoints: 599 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-963021ac0cb8a12826d7e00d317340e71748a27c18553422a76d882d2e8ad389.yml +openapi_spec_hash: 0c1ea27cd584bf0d47fed367663053b2 config_hash: 4758209f53bb13d06f55e4cf6c952b6d diff --git a/api.md b/api.md index 6ff46915..2fe398c1 100644 --- a/api.md +++ b/api.md @@ -1789,60 +1789,22 @@ Methods: # Security -## Events - -Types: - -```python -from gcore.types.security import ClientView -``` - -Methods: - -- client.security.events.list(\*\*params) -> SyncOffsetPage[ClientView] - -## BgpAnnounces - -Types: - -```python -from gcore.types.security import ClientAnnounce, BgpAnnounceListResponse -``` - -Methods: - -- client.security.bgp_announces.list(\*\*params) -> BgpAnnounceListResponse -- client.security.bgp_announces.toggle(\*\*params) -> object - ## ProfileTemplates Types: ```python -from gcore.types.security import ClientProfileTemplate, ProfileTemplateListResponse +from gcore.types.security import ClientProfileTemplate ``` -Methods: - -- client.security.profile_templates.list() -> ProfileTemplateListResponse - ## Profiles Types: ```python -from gcore.types.security import ClientProfile, ProfileListResponse +from gcore.types.security import ClientProfile ``` -Methods: - -- client.security.profiles.create(\*\*params) -> ClientProfile -- client.security.profiles.list(\*\*params) -> ProfileListResponse -- client.security.profiles.delete(id) -> None -- client.security.profiles.get(id) -> ClientProfile -- client.security.profiles.recreate(id, \*\*params) -> ClientProfile -- client.security.profiles.replace(id, \*\*params) -> ClientProfile - # DNS Types: diff --git a/src/gcore/_client.py b/src/gcore/_client.py index d900f571..df7f4886 100644 --- a/src/gcore/_client.py +++ b/src/gcore/_client.py @@ -35,7 +35,6 @@ from .resources.cloud import cloud from .resources.storage import storage from .resources.fastedge import fastedge -from .resources.security import security from .resources.streaming import streaming __all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "Gcore", "AsyncGcore", "Client", "AsyncClient"] @@ -47,7 +46,6 @@ class Gcore(SyncAPIClient): iam: iam.IamResource fastedge: fastedge.FastedgeResource streaming: streaming.StreamingResource - security: security.SecurityResource dns: dns.DNSResource storage: storage.StorageResource cdn: cdn.CdnResource @@ -140,7 +138,6 @@ def __init__( self.iam = iam.IamResource(self) self.fastedge = fastedge.FastedgeResource(self) self.streaming = streaming.StreamingResource(self) - self.security = security.SecurityResource(self) self.dns = dns.DNSResource(self) self.storage = storage.StorageResource(self) self.cdn = cdn.CdnResource(self) @@ -284,7 +281,6 @@ class AsyncGcore(AsyncAPIClient): iam: iam.AsyncIamResource fastedge: fastedge.AsyncFastedgeResource streaming: streaming.AsyncStreamingResource - security: security.AsyncSecurityResource dns: dns.AsyncDNSResource storage: storage.AsyncStorageResource cdn: cdn.AsyncCdnResource @@ -377,7 +373,6 @@ def __init__( self.iam = iam.AsyncIamResource(self) self.fastedge = fastedge.AsyncFastedgeResource(self) self.streaming = streaming.AsyncStreamingResource(self) - self.security = security.AsyncSecurityResource(self) self.dns = dns.AsyncDNSResource(self) self.storage = storage.AsyncStorageResource(self) self.cdn = cdn.AsyncCdnResource(self) @@ -522,7 +517,6 @@ def __init__(self, client: Gcore) -> None: self.iam = iam.IamResourceWithRawResponse(client.iam) self.fastedge = fastedge.FastedgeResourceWithRawResponse(client.fastedge) self.streaming = streaming.StreamingResourceWithRawResponse(client.streaming) - self.security = security.SecurityResourceWithRawResponse(client.security) self.dns = dns.DNSResourceWithRawResponse(client.dns) self.storage = storage.StorageResourceWithRawResponse(client.storage) self.cdn = cdn.CdnResourceWithRawResponse(client.cdn) @@ -535,7 +529,6 @@ def __init__(self, client: AsyncGcore) -> None: self.iam = iam.AsyncIamResourceWithRawResponse(client.iam) self.fastedge = fastedge.AsyncFastedgeResourceWithRawResponse(client.fastedge) self.streaming = streaming.AsyncStreamingResourceWithRawResponse(client.streaming) - self.security = security.AsyncSecurityResourceWithRawResponse(client.security) self.dns = dns.AsyncDNSResourceWithRawResponse(client.dns) self.storage = storage.AsyncStorageResourceWithRawResponse(client.storage) self.cdn = cdn.AsyncCdnResourceWithRawResponse(client.cdn) @@ -548,7 +541,6 @@ def __init__(self, client: Gcore) -> None: self.iam = iam.IamResourceWithStreamingResponse(client.iam) self.fastedge = fastedge.FastedgeResourceWithStreamingResponse(client.fastedge) self.streaming = streaming.StreamingResourceWithStreamingResponse(client.streaming) - self.security = security.SecurityResourceWithStreamingResponse(client.security) self.dns = dns.DNSResourceWithStreamingResponse(client.dns) self.storage = storage.StorageResourceWithStreamingResponse(client.storage) self.cdn = cdn.CdnResourceWithStreamingResponse(client.cdn) @@ -561,7 +553,6 @@ def __init__(self, client: AsyncGcore) -> None: self.iam = iam.AsyncIamResourceWithStreamingResponse(client.iam) self.fastedge = fastedge.AsyncFastedgeResourceWithStreamingResponse(client.fastedge) self.streaming = streaming.AsyncStreamingResourceWithStreamingResponse(client.streaming) - self.security = security.AsyncSecurityResourceWithStreamingResponse(client.security) self.dns = dns.AsyncDNSResourceWithStreamingResponse(client.dns) self.storage = storage.AsyncStorageResourceWithStreamingResponse(client.storage) self.cdn = cdn.AsyncCdnResourceWithStreamingResponse(client.cdn) diff --git a/src/gcore/resources/__init__.py b/src/gcore/resources/__init__.py index c8aaa6a7..d7b63884 100644 --- a/src/gcore/resources/__init__.py +++ b/src/gcore/resources/__init__.py @@ -56,14 +56,6 @@ FastedgeResourceWithStreamingResponse, AsyncFastedgeResourceWithStreamingResponse, ) -from .security import ( - SecurityResource, - AsyncSecurityResource, - SecurityResourceWithRawResponse, - AsyncSecurityResourceWithRawResponse, - SecurityResourceWithStreamingResponse, - AsyncSecurityResourceWithStreamingResponse, -) from .streaming import ( StreamingResource, AsyncStreamingResource, @@ -104,12 +96,6 @@ "AsyncStreamingResourceWithRawResponse", "StreamingResourceWithStreamingResponse", "AsyncStreamingResourceWithStreamingResponse", - "SecurityResource", - "AsyncSecurityResource", - "SecurityResourceWithRawResponse", - "AsyncSecurityResourceWithRawResponse", - "SecurityResourceWithStreamingResponse", - "AsyncSecurityResourceWithStreamingResponse", "DNSResource", "AsyncDNSResource", "DNSResourceWithRawResponse", diff --git a/src/gcore/resources/security/__init__.py b/src/gcore/resources/security/__init__.py deleted file mode 100644 index a1a7a5ea..00000000 --- a/src/gcore/resources/security/__init__.py +++ /dev/null @@ -1,75 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .events import ( - EventsResource, - AsyncEventsResource, - EventsResourceWithRawResponse, - AsyncEventsResourceWithRawResponse, - EventsResourceWithStreamingResponse, - AsyncEventsResourceWithStreamingResponse, -) -from .profiles import ( - ProfilesResource, - AsyncProfilesResource, - ProfilesResourceWithRawResponse, - AsyncProfilesResourceWithRawResponse, - ProfilesResourceWithStreamingResponse, - AsyncProfilesResourceWithStreamingResponse, -) -from .security import ( - SecurityResource, - AsyncSecurityResource, - SecurityResourceWithRawResponse, - AsyncSecurityResourceWithRawResponse, - SecurityResourceWithStreamingResponse, - AsyncSecurityResourceWithStreamingResponse, -) -from .bgp_announces import ( - BgpAnnouncesResource, - AsyncBgpAnnouncesResource, - BgpAnnouncesResourceWithRawResponse, - AsyncBgpAnnouncesResourceWithRawResponse, - BgpAnnouncesResourceWithStreamingResponse, - AsyncBgpAnnouncesResourceWithStreamingResponse, -) -from .profile_templates import ( - ProfileTemplatesResource, - AsyncProfileTemplatesResource, - ProfileTemplatesResourceWithRawResponse, - AsyncProfileTemplatesResourceWithRawResponse, - ProfileTemplatesResourceWithStreamingResponse, - AsyncProfileTemplatesResourceWithStreamingResponse, -) - -__all__ = [ - "EventsResource", - "AsyncEventsResource", - "EventsResourceWithRawResponse", - "AsyncEventsResourceWithRawResponse", - "EventsResourceWithStreamingResponse", - "AsyncEventsResourceWithStreamingResponse", - "BgpAnnouncesResource", - "AsyncBgpAnnouncesResource", - "BgpAnnouncesResourceWithRawResponse", - "AsyncBgpAnnouncesResourceWithRawResponse", - "BgpAnnouncesResourceWithStreamingResponse", - "AsyncBgpAnnouncesResourceWithStreamingResponse", - "ProfileTemplatesResource", - "AsyncProfileTemplatesResource", - "ProfileTemplatesResourceWithRawResponse", - "AsyncProfileTemplatesResourceWithRawResponse", - "ProfileTemplatesResourceWithStreamingResponse", - "AsyncProfileTemplatesResourceWithStreamingResponse", - "ProfilesResource", - "AsyncProfilesResource", - "ProfilesResourceWithRawResponse", - "AsyncProfilesResourceWithRawResponse", - "ProfilesResourceWithStreamingResponse", - "AsyncProfilesResourceWithStreamingResponse", - "SecurityResource", - "AsyncSecurityResource", - "SecurityResourceWithRawResponse", - "AsyncSecurityResourceWithRawResponse", - "SecurityResourceWithStreamingResponse", - "AsyncSecurityResourceWithStreamingResponse", -] diff --git a/src/gcore/resources/security/bgp_announces.py b/src/gcore/resources/security/bgp_announces.py deleted file mode 100644 index 26b3bc96..00000000 --- a/src/gcore/resources/security/bgp_announces.py +++ /dev/null @@ -1,308 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Literal - -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 ..._base_client import make_request_options -from ...types.security import bgp_announce_list_params, bgp_announce_toggle_params -from ...types.security.bgp_announce_list_response import BgpAnnounceListResponse - -__all__ = ["BgpAnnouncesResource", "AsyncBgpAnnouncesResource"] - - -class BgpAnnouncesResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> BgpAnnouncesResourceWithRawResponse: - """ - 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 BgpAnnouncesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> BgpAnnouncesResourceWithStreamingResponse: - """ - 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 BgpAnnouncesResourceWithStreamingResponse(self) - - def list( - self, - *, - announced: Optional[bool] | Omit = omit, - client_id: Optional[int] | Omit = omit, - origin: Optional[Literal["STATIC", "DYNAMIC"]] | Omit = omit, - site: 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> BgpAnnounceListResponse: - """Get BGP announces filtered by parameters. - - Shows announces in active profiles, - meaning that to get a non-empty response, the client must have at least one - active profile. - - 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 - """ - return self._get( - "/security/sifter/v2/protected_addresses/announces", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "announced": announced, - "client_id": client_id, - "origin": origin, - "site": site, - }, - bgp_announce_list_params.BgpAnnounceListParams, - ), - ), - cast_to=BgpAnnounceListResponse, - ) - - def toggle( - self, - *, - announce: str, - enabled: bool, - client_id: Optional[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, - ) -> object: - """Change BGP announces (it can be enabled or disabled, but not created or - updated). - - Can be applied to already existing announces in active profiles, - meaning that the client must have at least one active profile. - - 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 - """ - return self._post( - "/security/sifter/v2/protected_addresses/announces", - body=maybe_transform( - { - "announce": announce, - "enabled": enabled, - }, - bgp_announce_toggle_params.BgpAnnounceToggleParams, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"client_id": client_id}, bgp_announce_toggle_params.BgpAnnounceToggleParams), - ), - cast_to=object, - ) - - -class AsyncBgpAnnouncesResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncBgpAnnouncesResourceWithRawResponse: - """ - 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 AsyncBgpAnnouncesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncBgpAnnouncesResourceWithStreamingResponse: - """ - 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 AsyncBgpAnnouncesResourceWithStreamingResponse(self) - - async def list( - self, - *, - announced: Optional[bool] | Omit = omit, - client_id: Optional[int] | Omit = omit, - origin: Optional[Literal["STATIC", "DYNAMIC"]] | Omit = omit, - site: 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> BgpAnnounceListResponse: - """Get BGP announces filtered by parameters. - - Shows announces in active profiles, - meaning that to get a non-empty response, the client must have at least one - active profile. - - 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 - """ - return await self._get( - "/security/sifter/v2/protected_addresses/announces", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "announced": announced, - "client_id": client_id, - "origin": origin, - "site": site, - }, - bgp_announce_list_params.BgpAnnounceListParams, - ), - ), - cast_to=BgpAnnounceListResponse, - ) - - async def toggle( - self, - *, - announce: str, - enabled: bool, - client_id: Optional[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, - ) -> object: - """Change BGP announces (it can be enabled or disabled, but not created or - updated). - - Can be applied to already existing announces in active profiles, - meaning that the client must have at least one active profile. - - 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 - """ - return await self._post( - "/security/sifter/v2/protected_addresses/announces", - body=await async_maybe_transform( - { - "announce": announce, - "enabled": enabled, - }, - bgp_announce_toggle_params.BgpAnnounceToggleParams, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - {"client_id": client_id}, bgp_announce_toggle_params.BgpAnnounceToggleParams - ), - ), - cast_to=object, - ) - - -class BgpAnnouncesResourceWithRawResponse: - def __init__(self, bgp_announces: BgpAnnouncesResource) -> None: - self._bgp_announces = bgp_announces - - self.list = to_raw_response_wrapper( - bgp_announces.list, - ) - self.toggle = to_raw_response_wrapper( - bgp_announces.toggle, - ) - - -class AsyncBgpAnnouncesResourceWithRawResponse: - def __init__(self, bgp_announces: AsyncBgpAnnouncesResource) -> None: - self._bgp_announces = bgp_announces - - self.list = async_to_raw_response_wrapper( - bgp_announces.list, - ) - self.toggle = async_to_raw_response_wrapper( - bgp_announces.toggle, - ) - - -class BgpAnnouncesResourceWithStreamingResponse: - def __init__(self, bgp_announces: BgpAnnouncesResource) -> None: - self._bgp_announces = bgp_announces - - self.list = to_streamed_response_wrapper( - bgp_announces.list, - ) - self.toggle = to_streamed_response_wrapper( - bgp_announces.toggle, - ) - - -class AsyncBgpAnnouncesResourceWithStreamingResponse: - def __init__(self, bgp_announces: AsyncBgpAnnouncesResource) -> None: - self._bgp_announces = bgp_announces - - self.list = async_to_streamed_response_wrapper( - bgp_announces.list, - ) - self.toggle = async_to_streamed_response_wrapper( - bgp_announces.toggle, - ) diff --git a/src/gcore/resources/security/events.py b/src/gcore/resources/security/events.py deleted file mode 100644 index e0699398..00000000 --- a/src/gcore/resources/security/events.py +++ /dev/null @@ -1,234 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Union, Optional -from datetime import datetime -from typing_extensions import Literal - -import httpx - -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import 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 ..._base_client import AsyncPaginator, make_request_options -from ...types.security import event_list_params -from ...types.security.client_view import ClientView - -__all__ = ["EventsResource", "AsyncEventsResource"] - - -class EventsResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> EventsResourceWithRawResponse: - """ - 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 EventsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> EventsResourceWithStreamingResponse: - """ - 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 EventsResourceWithStreamingResponse(self) - - def list( - self, - *, - alert_type: Optional[Literal["ddos_alert", "rtbh_alert"]] | Omit = omit, - date_from: Union[Union[str, datetime], str] | Omit = omit, - date_to: Union[Union[str, datetime], str] | Omit = omit, - limit: int | Omit = omit, - offset: int | Omit = omit, - ordering: Literal[ - "attack_start_time", - "-attack_start_time", - "attack_power_bps", - "-attack_power_bps", - "attack_power_pps", - "-attack_power_pps", - "number_of_ip_involved_in_attack", - "-number_of_ip_involved_in_attack", - "alert_type", - "-alert_type", - ] - | Omit = omit, - targeted_ip_addresses: 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncOffsetPage[ClientView]: - """ - Event Logs Clients View - - 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 - """ - return self._get_api_list( - "/security/notifier/v1/event_logs", - page=SyncOffsetPage[ClientView], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "alert_type": alert_type, - "date_from": date_from, - "date_to": date_to, - "limit": limit, - "offset": offset, - "ordering": ordering, - "targeted_ip_addresses": targeted_ip_addresses, - }, - event_list_params.EventListParams, - ), - ), - model=ClientView, - ) - - -class AsyncEventsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncEventsResourceWithRawResponse: - """ - 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 AsyncEventsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncEventsResourceWithStreamingResponse: - """ - 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 AsyncEventsResourceWithStreamingResponse(self) - - def list( - self, - *, - alert_type: Optional[Literal["ddos_alert", "rtbh_alert"]] | Omit = omit, - date_from: Union[Union[str, datetime], str] | Omit = omit, - date_to: Union[Union[str, datetime], str] | Omit = omit, - limit: int | Omit = omit, - offset: int | Omit = omit, - ordering: Literal[ - "attack_start_time", - "-attack_start_time", - "attack_power_bps", - "-attack_power_bps", - "attack_power_pps", - "-attack_power_pps", - "number_of_ip_involved_in_attack", - "-number_of_ip_involved_in_attack", - "alert_type", - "-alert_type", - ] - | Omit = omit, - targeted_ip_addresses: 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[ClientView, AsyncOffsetPage[ClientView]]: - """ - Event Logs Clients View - - 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 - """ - return self._get_api_list( - "/security/notifier/v1/event_logs", - page=AsyncOffsetPage[ClientView], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "alert_type": alert_type, - "date_from": date_from, - "date_to": date_to, - "limit": limit, - "offset": offset, - "ordering": ordering, - "targeted_ip_addresses": targeted_ip_addresses, - }, - event_list_params.EventListParams, - ), - ), - model=ClientView, - ) - - -class EventsResourceWithRawResponse: - def __init__(self, events: EventsResource) -> None: - self._events = events - - self.list = to_raw_response_wrapper( - events.list, - ) - - -class AsyncEventsResourceWithRawResponse: - def __init__(self, events: AsyncEventsResource) -> None: - self._events = events - - self.list = async_to_raw_response_wrapper( - events.list, - ) - - -class EventsResourceWithStreamingResponse: - def __init__(self, events: EventsResource) -> None: - self._events = events - - self.list = to_streamed_response_wrapper( - events.list, - ) - - -class AsyncEventsResourceWithStreamingResponse: - def __init__(self, events: AsyncEventsResource) -> None: - self._events = events - - self.list = async_to_streamed_response_wrapper( - events.list, - ) diff --git a/src/gcore/resources/security/profile_templates.py b/src/gcore/resources/security/profile_templates.py deleted file mode 100644 index 307f3c0d..00000000 --- a/src/gcore/resources/security/profile_templates.py +++ /dev/null @@ -1,143 +0,0 @@ -# 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.security.profile_template_list_response import ProfileTemplateListResponse - -__all__ = ["ProfileTemplatesResource", "AsyncProfileTemplatesResource"] - - -class ProfileTemplatesResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> ProfileTemplatesResourceWithRawResponse: - """ - 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 ProfileTemplatesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> ProfileTemplatesResourceWithStreamingResponse: - """ - 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 ProfileTemplatesResourceWithStreamingResponse(self) - - def list( - self, - *, - # 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, - ) -> ProfileTemplateListResponse: - """Get list of profile templates. - - Profile template is used as a template to create - profile. Client receives only common and created for him profile templates. - """ - return self._get( - "/security/iaas/profile-templates", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProfileTemplateListResponse, - ) - - -class AsyncProfileTemplatesResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncProfileTemplatesResourceWithRawResponse: - """ - 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 AsyncProfileTemplatesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncProfileTemplatesResourceWithStreamingResponse: - """ - 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 AsyncProfileTemplatesResourceWithStreamingResponse(self) - - async def list( - self, - *, - # 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, - ) -> ProfileTemplateListResponse: - """Get list of profile templates. - - Profile template is used as a template to create - profile. Client receives only common and created for him profile templates. - """ - return await self._get( - "/security/iaas/profile-templates", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProfileTemplateListResponse, - ) - - -class ProfileTemplatesResourceWithRawResponse: - def __init__(self, profile_templates: ProfileTemplatesResource) -> None: - self._profile_templates = profile_templates - - self.list = to_raw_response_wrapper( - profile_templates.list, - ) - - -class AsyncProfileTemplatesResourceWithRawResponse: - def __init__(self, profile_templates: AsyncProfileTemplatesResource) -> None: - self._profile_templates = profile_templates - - self.list = async_to_raw_response_wrapper( - profile_templates.list, - ) - - -class ProfileTemplatesResourceWithStreamingResponse: - def __init__(self, profile_templates: ProfileTemplatesResource) -> None: - self._profile_templates = profile_templates - - self.list = to_streamed_response_wrapper( - profile_templates.list, - ) - - -class AsyncProfileTemplatesResourceWithStreamingResponse: - def __init__(self, profile_templates: AsyncProfileTemplatesResource) -> None: - self._profile_templates = profile_templates - - self.list = async_to_streamed_response_wrapper( - profile_templates.list, - ) diff --git a/src/gcore/resources/security/profiles.py b/src/gcore/resources/security/profiles.py deleted file mode 100644 index 2ddf3257..00000000 --- a/src/gcore/resources/security/profiles.py +++ /dev/null @@ -1,661 +0,0 @@ -# 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, NoneType, 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 ..._base_client import make_request_options -from ...types.security import ( - profile_list_params, - profile_create_params, - profile_replace_params, - profile_recreate_params, -) -from ...types.security.client_profile import ClientProfile -from ...types.security.profile_list_response import ProfileListResponse - -__all__ = ["ProfilesResource", "AsyncProfilesResource"] - - -class ProfilesResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> ProfilesResourceWithRawResponse: - """ - 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 ProfilesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> ProfilesResourceWithStreamingResponse: - """ - 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 ProfilesResourceWithStreamingResponse(self) - - def create( - self, - *, - fields: Iterable[profile_create_params.Field], - profile_template: int, - site: str, - ip_address: 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ClientProfile: - """Create protection profile. - - Protection is enabled at the same time as profile is - created - - 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 - """ - return self._post( - "/security/iaas/v2/profiles", - body=maybe_transform( - { - "fields": fields, - "profile_template": profile_template, - "site": site, - "ip_address": ip_address, - }, - profile_create_params.ProfileCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClientProfile, - ) - - def list( - self, - *, - exclude_empty_address: bool | Omit = omit, - include_deleted: bool | Omit = omit, - ip_address: str | Omit = omit, - site: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProfileListResponse: - """Get list of protection profiles. - - Client receives only profiles created by him - - 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 - """ - return self._get( - "/security/iaas/v2/profiles", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "exclude_empty_address": exclude_empty_address, - "include_deleted": include_deleted, - "ip_address": ip_address, - "site": site, - }, - profile_list_params.ProfileListParams, - ), - ), - cast_to=ProfileListResponse, - ) - - def delete( - self, - id: int, - *, - # 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, - ) -> None: - """Delete protection profile. - - Protection is disabled at the same time as profile is - deleted - - 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 - """ - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - f"/security/iaas/v2/profiles/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def get( - self, - id: int, - *, - # 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, - ) -> ClientProfile: - """ - Get profile by id - - 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 - """ - return self._get( - f"/security/iaas/v2/profiles/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClientProfile, - ) - - def recreate( - self, - id: int, - *, - fields: Iterable[profile_recreate_params.Field], - profile_template: int, - ip_address: Optional[str] | Omit = omit, - site: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ClientProfile: - """ - Recreate profile with another profile template (for other cases use detail API) - - 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 - """ - return self._put( - f"/security/iaas/v2/profiles/{id}/recreate", - body=maybe_transform( - { - "fields": fields, - "profile_template": profile_template, - "ip_address": ip_address, - "site": site, - }, - profile_recreate_params.ProfileRecreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClientProfile, - ) - - def replace( - self, - id: int, - *, - fields: Iterable[profile_replace_params.Field], - profile_template: int, - ip_address: Optional[str] | Omit = omit, - site: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ClientProfile: - """Update profile. - - Protection policies are updated at the same time as profile - updated - - 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 - """ - return self._put( - f"/security/iaas/v2/profiles/{id}", - body=maybe_transform( - { - "fields": fields, - "profile_template": profile_template, - "ip_address": ip_address, - "site": site, - }, - profile_replace_params.ProfileReplaceParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClientProfile, - ) - - -class AsyncProfilesResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncProfilesResourceWithRawResponse: - """ - 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 AsyncProfilesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncProfilesResourceWithStreamingResponse: - """ - 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 AsyncProfilesResourceWithStreamingResponse(self) - - async def create( - self, - *, - fields: Iterable[profile_create_params.Field], - profile_template: int, - site: str, - ip_address: 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, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ClientProfile: - """Create protection profile. - - Protection is enabled at the same time as profile is - created - - 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 - """ - return await self._post( - "/security/iaas/v2/profiles", - body=await async_maybe_transform( - { - "fields": fields, - "profile_template": profile_template, - "site": site, - "ip_address": ip_address, - }, - profile_create_params.ProfileCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClientProfile, - ) - - async def list( - self, - *, - exclude_empty_address: bool | Omit = omit, - include_deleted: bool | Omit = omit, - ip_address: str | Omit = omit, - site: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProfileListResponse: - """Get list of protection profiles. - - Client receives only profiles created by him - - 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 - """ - return await self._get( - "/security/iaas/v2/profiles", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "exclude_empty_address": exclude_empty_address, - "include_deleted": include_deleted, - "ip_address": ip_address, - "site": site, - }, - profile_list_params.ProfileListParams, - ), - ), - cast_to=ProfileListResponse, - ) - - async def delete( - self, - id: int, - *, - # 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, - ) -> None: - """Delete protection profile. - - Protection is disabled at the same time as profile is - deleted - - 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 - """ - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._delete( - f"/security/iaas/v2/profiles/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def get( - self, - id: int, - *, - # 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, - ) -> ClientProfile: - """ - Get profile by id - - 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 - """ - return await self._get( - f"/security/iaas/v2/profiles/{id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClientProfile, - ) - - async def recreate( - self, - id: int, - *, - fields: Iterable[profile_recreate_params.Field], - profile_template: int, - ip_address: Optional[str] | Omit = omit, - site: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ClientProfile: - """ - Recreate profile with another profile template (for other cases use detail API) - - 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 - """ - return await self._put( - f"/security/iaas/v2/profiles/{id}/recreate", - body=await async_maybe_transform( - { - "fields": fields, - "profile_template": profile_template, - "ip_address": ip_address, - "site": site, - }, - profile_recreate_params.ProfileRecreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClientProfile, - ) - - async def replace( - self, - id: int, - *, - fields: Iterable[profile_replace_params.Field], - profile_template: int, - ip_address: Optional[str] | Omit = omit, - site: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ClientProfile: - """Update profile. - - Protection policies are updated at the same time as profile - updated - - 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 - """ - return await self._put( - f"/security/iaas/v2/profiles/{id}", - body=await async_maybe_transform( - { - "fields": fields, - "profile_template": profile_template, - "ip_address": ip_address, - "site": site, - }, - profile_replace_params.ProfileReplaceParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClientProfile, - ) - - -class ProfilesResourceWithRawResponse: - def __init__(self, profiles: ProfilesResource) -> None: - self._profiles = profiles - - self.create = to_raw_response_wrapper( - profiles.create, - ) - self.list = to_raw_response_wrapper( - profiles.list, - ) - self.delete = to_raw_response_wrapper( - profiles.delete, - ) - self.get = to_raw_response_wrapper( - profiles.get, - ) - self.recreate = to_raw_response_wrapper( - profiles.recreate, - ) - self.replace = to_raw_response_wrapper( - profiles.replace, - ) - - -class AsyncProfilesResourceWithRawResponse: - def __init__(self, profiles: AsyncProfilesResource) -> None: - self._profiles = profiles - - self.create = async_to_raw_response_wrapper( - profiles.create, - ) - self.list = async_to_raw_response_wrapper( - profiles.list, - ) - self.delete = async_to_raw_response_wrapper( - profiles.delete, - ) - self.get = async_to_raw_response_wrapper( - profiles.get, - ) - self.recreate = async_to_raw_response_wrapper( - profiles.recreate, - ) - self.replace = async_to_raw_response_wrapper( - profiles.replace, - ) - - -class ProfilesResourceWithStreamingResponse: - def __init__(self, profiles: ProfilesResource) -> None: - self._profiles = profiles - - self.create = to_streamed_response_wrapper( - profiles.create, - ) - self.list = to_streamed_response_wrapper( - profiles.list, - ) - self.delete = to_streamed_response_wrapper( - profiles.delete, - ) - self.get = to_streamed_response_wrapper( - profiles.get, - ) - self.recreate = to_streamed_response_wrapper( - profiles.recreate, - ) - self.replace = to_streamed_response_wrapper( - profiles.replace, - ) - - -class AsyncProfilesResourceWithStreamingResponse: - def __init__(self, profiles: AsyncProfilesResource) -> None: - self._profiles = profiles - - self.create = async_to_streamed_response_wrapper( - profiles.create, - ) - self.list = async_to_streamed_response_wrapper( - profiles.list, - ) - self.delete = async_to_streamed_response_wrapper( - profiles.delete, - ) - self.get = async_to_streamed_response_wrapper( - profiles.get, - ) - self.recreate = async_to_streamed_response_wrapper( - profiles.recreate, - ) - self.replace = async_to_streamed_response_wrapper( - profiles.replace, - ) diff --git a/src/gcore/resources/security/security.py b/src/gcore/resources/security/security.py deleted file mode 100644 index 2d0d9c11..00000000 --- a/src/gcore/resources/security/security.py +++ /dev/null @@ -1,198 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .events import ( - EventsResource, - AsyncEventsResource, - EventsResourceWithRawResponse, - AsyncEventsResourceWithRawResponse, - EventsResourceWithStreamingResponse, - AsyncEventsResourceWithStreamingResponse, -) -from .profiles import ( - ProfilesResource, - AsyncProfilesResource, - ProfilesResourceWithRawResponse, - AsyncProfilesResourceWithRawResponse, - ProfilesResourceWithStreamingResponse, - AsyncProfilesResourceWithStreamingResponse, -) -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from .bgp_announces import ( - BgpAnnouncesResource, - AsyncBgpAnnouncesResource, - BgpAnnouncesResourceWithRawResponse, - AsyncBgpAnnouncesResourceWithRawResponse, - BgpAnnouncesResourceWithStreamingResponse, - AsyncBgpAnnouncesResourceWithStreamingResponse, -) -from .profile_templates import ( - ProfileTemplatesResource, - AsyncProfileTemplatesResource, - ProfileTemplatesResourceWithRawResponse, - AsyncProfileTemplatesResourceWithRawResponse, - ProfileTemplatesResourceWithStreamingResponse, - AsyncProfileTemplatesResourceWithStreamingResponse, -) - -__all__ = ["SecurityResource", "AsyncSecurityResource"] - - -class SecurityResource(SyncAPIResource): - @cached_property - def events(self) -> EventsResource: - return EventsResource(self._client) - - @cached_property - def bgp_announces(self) -> BgpAnnouncesResource: - return BgpAnnouncesResource(self._client) - - @cached_property - def profile_templates(self) -> ProfileTemplatesResource: - return ProfileTemplatesResource(self._client) - - @cached_property - def profiles(self) -> ProfilesResource: - return ProfilesResource(self._client) - - @cached_property - def with_raw_response(self) -> SecurityResourceWithRawResponse: - """ - 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 SecurityResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> SecurityResourceWithStreamingResponse: - """ - 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 SecurityResourceWithStreamingResponse(self) - - -class AsyncSecurityResource(AsyncAPIResource): - @cached_property - def events(self) -> AsyncEventsResource: - return AsyncEventsResource(self._client) - - @cached_property - def bgp_announces(self) -> AsyncBgpAnnouncesResource: - return AsyncBgpAnnouncesResource(self._client) - - @cached_property - def profile_templates(self) -> AsyncProfileTemplatesResource: - return AsyncProfileTemplatesResource(self._client) - - @cached_property - def profiles(self) -> AsyncProfilesResource: - return AsyncProfilesResource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncSecurityResourceWithRawResponse: - """ - 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 AsyncSecurityResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncSecurityResourceWithStreamingResponse: - """ - 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 AsyncSecurityResourceWithStreamingResponse(self) - - -class SecurityResourceWithRawResponse: - def __init__(self, security: SecurityResource) -> None: - self._security = security - - @cached_property - def events(self) -> EventsResourceWithRawResponse: - return EventsResourceWithRawResponse(self._security.events) - - @cached_property - def bgp_announces(self) -> BgpAnnouncesResourceWithRawResponse: - return BgpAnnouncesResourceWithRawResponse(self._security.bgp_announces) - - @cached_property - def profile_templates(self) -> ProfileTemplatesResourceWithRawResponse: - return ProfileTemplatesResourceWithRawResponse(self._security.profile_templates) - - @cached_property - def profiles(self) -> ProfilesResourceWithRawResponse: - return ProfilesResourceWithRawResponse(self._security.profiles) - - -class AsyncSecurityResourceWithRawResponse: - def __init__(self, security: AsyncSecurityResource) -> None: - self._security = security - - @cached_property - def events(self) -> AsyncEventsResourceWithRawResponse: - return AsyncEventsResourceWithRawResponse(self._security.events) - - @cached_property - def bgp_announces(self) -> AsyncBgpAnnouncesResourceWithRawResponse: - return AsyncBgpAnnouncesResourceWithRawResponse(self._security.bgp_announces) - - @cached_property - def profile_templates(self) -> AsyncProfileTemplatesResourceWithRawResponse: - return AsyncProfileTemplatesResourceWithRawResponse(self._security.profile_templates) - - @cached_property - def profiles(self) -> AsyncProfilesResourceWithRawResponse: - return AsyncProfilesResourceWithRawResponse(self._security.profiles) - - -class SecurityResourceWithStreamingResponse: - def __init__(self, security: SecurityResource) -> None: - self._security = security - - @cached_property - def events(self) -> EventsResourceWithStreamingResponse: - return EventsResourceWithStreamingResponse(self._security.events) - - @cached_property - def bgp_announces(self) -> BgpAnnouncesResourceWithStreamingResponse: - return BgpAnnouncesResourceWithStreamingResponse(self._security.bgp_announces) - - @cached_property - def profile_templates(self) -> ProfileTemplatesResourceWithStreamingResponse: - return ProfileTemplatesResourceWithStreamingResponse(self._security.profile_templates) - - @cached_property - def profiles(self) -> ProfilesResourceWithStreamingResponse: - return ProfilesResourceWithStreamingResponse(self._security.profiles) - - -class AsyncSecurityResourceWithStreamingResponse: - def __init__(self, security: AsyncSecurityResource) -> None: - self._security = security - - @cached_property - def events(self) -> AsyncEventsResourceWithStreamingResponse: - return AsyncEventsResourceWithStreamingResponse(self._security.events) - - @cached_property - def bgp_announces(self) -> AsyncBgpAnnouncesResourceWithStreamingResponse: - return AsyncBgpAnnouncesResourceWithStreamingResponse(self._security.bgp_announces) - - @cached_property - def profile_templates(self) -> AsyncProfileTemplatesResourceWithStreamingResponse: - return AsyncProfileTemplatesResourceWithStreamingResponse(self._security.profile_templates) - - @cached_property - def profiles(self) -> AsyncProfilesResourceWithStreamingResponse: - return AsyncProfilesResourceWithStreamingResponse(self._security.profiles) diff --git a/src/gcore/types/security/__init__.py b/src/gcore/types/security/__init__.py index 4994ea70..f8ee8b14 100644 --- a/src/gcore/types/security/__init__.py +++ b/src/gcore/types/security/__init__.py @@ -1,18 +1,3 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations - -from .client_view import ClientView as ClientView -from .client_profile import ClientProfile as ClientProfile -from .client_announce import ClientAnnounce as ClientAnnounce -from .event_list_params import EventListParams as EventListParams -from .profile_list_params import ProfileListParams as ProfileListParams -from .profile_create_params import ProfileCreateParams as ProfileCreateParams -from .profile_list_response import ProfileListResponse as ProfileListResponse -from .profile_replace_params import ProfileReplaceParams as ProfileReplaceParams -from .client_profile_template import ClientProfileTemplate as ClientProfileTemplate -from .profile_recreate_params import ProfileRecreateParams as ProfileRecreateParams -from .bgp_announce_list_params import BgpAnnounceListParams as BgpAnnounceListParams -from .bgp_announce_list_response import BgpAnnounceListResponse as BgpAnnounceListResponse -from .bgp_announce_toggle_params import BgpAnnounceToggleParams as BgpAnnounceToggleParams -from .profile_template_list_response import ProfileTemplateListResponse as ProfileTemplateListResponse diff --git a/src/gcore/types/security/bgp_announce_list_params.py b/src/gcore/types/security/bgp_announce_list_params.py deleted file mode 100644 index 390464fe..00000000 --- a/src/gcore/types/security/bgp_announce_list_params.py +++ /dev/null @@ -1,18 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Literal, TypedDict - -__all__ = ["BgpAnnounceListParams"] - - -class BgpAnnounceListParams(TypedDict, total=False): - announced: Optional[bool] - - client_id: Optional[int] - - origin: Optional[Literal["STATIC", "DYNAMIC"]] - - site: Optional[str] diff --git a/src/gcore/types/security/bgp_announce_list_response.py b/src/gcore/types/security/bgp_announce_list_response.py deleted file mode 100644 index 6981ba90..00000000 --- a/src/gcore/types/security/bgp_announce_list_response.py +++ /dev/null @@ -1,10 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List -from typing_extensions import TypeAlias - -from .client_announce import ClientAnnounce - -__all__ = ["BgpAnnounceListResponse"] - -BgpAnnounceListResponse: TypeAlias = List[ClientAnnounce] diff --git a/src/gcore/types/security/bgp_announce_toggle_params.py b/src/gcore/types/security/bgp_announce_toggle_params.py deleted file mode 100644 index 4c5dd1b6..00000000 --- a/src/gcore/types/security/bgp_announce_toggle_params.py +++ /dev/null @@ -1,16 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Required, TypedDict - -__all__ = ["BgpAnnounceToggleParams"] - - -class BgpAnnounceToggleParams(TypedDict, total=False): - announce: Required[str] - - enabled: Required[bool] - - client_id: Optional[int] diff --git a/src/gcore/types/security/client_announce.py b/src/gcore/types/security/client_announce.py deleted file mode 100644 index ef276615..00000000 --- a/src/gcore/types/security/client_announce.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List - -from ..._models import BaseModel - -__all__ = ["ClientAnnounce"] - - -class ClientAnnounce(BaseModel): - announced: List[str] - - client_id: int - - not_announced: List[str] diff --git a/src/gcore/types/security/client_profile.py b/src/gcore/types/security/client_profile.py deleted file mode 100644 index e02111b5..00000000 --- a/src/gcore/types/security/client_profile.py +++ /dev/null @@ -1,56 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional - -from ..._models import BaseModel -from .client_profile_template import ClientProfileTemplate - -__all__ = ["ClientProfile", "Field", "Options"] - - -class Field(BaseModel): - id: int - - base_field: int - - default: str - - description: str - - field_type: str - - name: str - - required: bool - - validation_schema: Dict[str, object] - - field_value: Optional[object] = None - - -class Options(BaseModel): - active: bool - - bgp: bool - - price: str - - -class ClientProfile(BaseModel): - id: int - - fields: List[Field] - - options: Options - - plan: str - - profile_template: ClientProfileTemplate - - protocols: List[Dict[str, object]] - - site: str - - status: Dict[str, object] - - ip_address: Optional[str] = None diff --git a/src/gcore/types/security/client_profile_template.py b/src/gcore/types/security/client_profile_template.py deleted file mode 100644 index 4ea63e14..00000000 --- a/src/gcore/types/security/client_profile_template.py +++ /dev/null @@ -1,43 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional -from datetime import datetime -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["ClientProfileTemplate", "Field"] - - -class Field(BaseModel): - id: int - - name: str - - default: Optional[str] = None - - description: Optional[str] = None - - field_type: Optional[Literal["int", "bool", "str"]] = None - - required: Optional[bool] = None - - validation_schema: Optional[Dict[str, object]] = None - - -class ClientProfileTemplate(BaseModel): - id: int - - created: datetime - - fields: List[Field] - - name: str - - version: str - - base_template: Optional[int] = None - - description: Optional[str] = None - - template_sifter: Optional[str] = None diff --git a/src/gcore/types/security/client_view.py b/src/gcore/types/security/client_view.py deleted file mode 100644 index 802060ab..00000000 --- a/src/gcore/types/security/client_view.py +++ /dev/null @@ -1,29 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["ClientView"] - - -class ClientView(BaseModel): - id: str - - alert_type: Optional[Literal["ddos_alert", "rtbh_alert"]] = None - - attack_power_bps: Optional[float] = None - - attack_power_pps: Optional[float] = None - - attack_start_time: Optional[datetime] = None - - client_id: Optional[int] = None - - notification_type: Optional[str] = None - - number_of_ip_involved_in_attack: Optional[int] = None - - targeted_ip_addresses: Optional[str] = None diff --git a/src/gcore/types/security/event_list_params.py b/src/gcore/types/security/event_list_params.py deleted file mode 100644 index 0bd703c3..00000000 --- a/src/gcore/types/security/event_list_params.py +++ /dev/null @@ -1,38 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Union, Optional -from datetime import datetime -from typing_extensions import Literal, Annotated, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["EventListParams"] - - -class EventListParams(TypedDict, total=False): - alert_type: Optional[Literal["ddos_alert", "rtbh_alert"]] - - date_from: Annotated[Union[Union[str, datetime], str], PropertyInfo(format="iso8601")] - - date_to: Annotated[Union[Union[str, datetime], str], PropertyInfo(format="iso8601")] - - limit: int - - offset: int - - ordering: Literal[ - "attack_start_time", - "-attack_start_time", - "attack_power_bps", - "-attack_power_bps", - "attack_power_pps", - "-attack_power_pps", - "number_of_ip_involved_in_attack", - "-number_of_ip_involved_in_attack", - "alert_type", - "-alert_type", - ] - - targeted_ip_addresses: Optional[str] diff --git a/src/gcore/types/security/profile_create_params.py b/src/gcore/types/security/profile_create_params.py deleted file mode 100644 index ad7b982c..00000000 --- a/src/gcore/types/security/profile_create_params.py +++ /dev/null @@ -1,24 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Iterable, Optional -from typing_extensions import Required, TypedDict - -__all__ = ["ProfileCreateParams", "Field"] - - -class ProfileCreateParams(TypedDict, total=False): - fields: Required[Iterable[Field]] - - profile_template: Required[int] - - site: Required[str] - - ip_address: Optional[str] - - -class Field(TypedDict, total=False): - base_field: Required[int] - - field_value: object diff --git a/src/gcore/types/security/profile_list_params.py b/src/gcore/types/security/profile_list_params.py deleted file mode 100644 index e54f232f..00000000 --- a/src/gcore/types/security/profile_list_params.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["ProfileListParams"] - - -class ProfileListParams(TypedDict, total=False): - exclude_empty_address: bool - - include_deleted: bool - - ip_address: str - - site: str diff --git a/src/gcore/types/security/profile_list_response.py b/src/gcore/types/security/profile_list_response.py deleted file mode 100644 index 816021c8..00000000 --- a/src/gcore/types/security/profile_list_response.py +++ /dev/null @@ -1,10 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List -from typing_extensions import TypeAlias - -from .client_profile import ClientProfile - -__all__ = ["ProfileListResponse"] - -ProfileListResponse: TypeAlias = List[ClientProfile] diff --git a/src/gcore/types/security/profile_recreate_params.py b/src/gcore/types/security/profile_recreate_params.py deleted file mode 100644 index e1dd3d10..00000000 --- a/src/gcore/types/security/profile_recreate_params.py +++ /dev/null @@ -1,24 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Iterable, Optional -from typing_extensions import Required, TypedDict - -__all__ = ["ProfileRecreateParams", "Field"] - - -class ProfileRecreateParams(TypedDict, total=False): - fields: Required[Iterable[Field]] - - profile_template: Required[int] - - ip_address: Optional[str] - - site: str - - -class Field(TypedDict, total=False): - base_field: Required[int] - - field_value: object diff --git a/src/gcore/types/security/profile_replace_params.py b/src/gcore/types/security/profile_replace_params.py deleted file mode 100644 index 9684dffd..00000000 --- a/src/gcore/types/security/profile_replace_params.py +++ /dev/null @@ -1,24 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Iterable, Optional -from typing_extensions import Required, TypedDict - -__all__ = ["ProfileReplaceParams", "Field"] - - -class ProfileReplaceParams(TypedDict, total=False): - fields: Required[Iterable[Field]] - - profile_template: Required[int] - - ip_address: Optional[str] - - site: str - - -class Field(TypedDict, total=False): - base_field: Required[int] - - field_value: object diff --git a/src/gcore/types/security/profile_template_list_response.py b/src/gcore/types/security/profile_template_list_response.py deleted file mode 100644 index 2264e970..00000000 --- a/src/gcore/types/security/profile_template_list_response.py +++ /dev/null @@ -1,10 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List -from typing_extensions import TypeAlias - -from .client_profile_template import ClientProfileTemplate - -__all__ = ["ProfileTemplateListResponse"] - -ProfileTemplateListResponse: TypeAlias = List[ClientProfileTemplate] diff --git a/tests/api_resources/security/__init__.py b/tests/api_resources/security/__init__.py deleted file mode 100644 index fd8019a9..00000000 --- a/tests/api_resources/security/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/security/test_bgp_announces.py b/tests/api_resources/security/test_bgp_announces.py deleted file mode 100644 index c1115976..00000000 --- a/tests/api_resources/security/test_bgp_announces.py +++ /dev/null @@ -1,180 +0,0 @@ -# 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.security import BgpAnnounceListResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestBgpAnnounces: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_list(self, client: Gcore) -> None: - bgp_announce = client.security.bgp_announces.list() - assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) - - @parametrize - def test_method_list_with_all_params(self, client: Gcore) -> None: - bgp_announce = client.security.bgp_announces.list( - announced=True, - client_id=0, - origin="STATIC", - site="x", - ) - assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Gcore) -> None: - response = client.security.bgp_announces.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bgp_announce = response.parse() - assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Gcore) -> None: - with client.security.bgp_announces.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bgp_announce = response.parse() - assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_toggle(self, client: Gcore) -> None: - bgp_announce = client.security.bgp_announces.toggle( - announce="192.9.9.1/32", - enabled=True, - ) - assert_matches_type(object, bgp_announce, path=["response"]) - - @parametrize - def test_method_toggle_with_all_params(self, client: Gcore) -> None: - bgp_announce = client.security.bgp_announces.toggle( - announce="192.9.9.1/32", - enabled=True, - client_id=0, - ) - assert_matches_type(object, bgp_announce, path=["response"]) - - @parametrize - def test_raw_response_toggle(self, client: Gcore) -> None: - response = client.security.bgp_announces.with_raw_response.toggle( - announce="192.9.9.1/32", - enabled=True, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bgp_announce = response.parse() - assert_matches_type(object, bgp_announce, path=["response"]) - - @parametrize - def test_streaming_response_toggle(self, client: Gcore) -> None: - with client.security.bgp_announces.with_streaming_response.toggle( - announce="192.9.9.1/32", - enabled=True, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bgp_announce = response.parse() - assert_matches_type(object, bgp_announce, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncBgpAnnounces: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_list(self, async_client: AsyncGcore) -> None: - bgp_announce = await async_client.security.bgp_announces.list() - assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) - - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: - bgp_announce = await async_client.security.bgp_announces.list( - announced=True, - client_id=0, - origin="STATIC", - site="x", - ) - assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncGcore) -> None: - response = await async_client.security.bgp_announces.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bgp_announce = await response.parse() - assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: - async with async_client.security.bgp_announces.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bgp_announce = await response.parse() - assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_toggle(self, async_client: AsyncGcore) -> None: - bgp_announce = await async_client.security.bgp_announces.toggle( - announce="192.9.9.1/32", - enabled=True, - ) - assert_matches_type(object, bgp_announce, path=["response"]) - - @parametrize - async def test_method_toggle_with_all_params(self, async_client: AsyncGcore) -> None: - bgp_announce = await async_client.security.bgp_announces.toggle( - announce="192.9.9.1/32", - enabled=True, - client_id=0, - ) - assert_matches_type(object, bgp_announce, path=["response"]) - - @parametrize - async def test_raw_response_toggle(self, async_client: AsyncGcore) -> None: - response = await async_client.security.bgp_announces.with_raw_response.toggle( - announce="192.9.9.1/32", - enabled=True, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - bgp_announce = await response.parse() - assert_matches_type(object, bgp_announce, path=["response"]) - - @parametrize - async def test_streaming_response_toggle(self, async_client: AsyncGcore) -> None: - async with async_client.security.bgp_announces.with_streaming_response.toggle( - announce="192.9.9.1/32", - enabled=True, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - bgp_announce = await response.parse() - assert_matches_type(object, bgp_announce, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/security/test_events.py b/tests/api_resources/security/test_events.py deleted file mode 100644 index 650de2cf..00000000 --- a/tests/api_resources/security/test_events.py +++ /dev/null @@ -1,102 +0,0 @@ -# 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._utils import parse_datetime -from gcore.pagination import SyncOffsetPage, AsyncOffsetPage -from gcore.types.security import ClientView - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestEvents: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_list(self, client: Gcore) -> None: - event = client.security.events.list() - assert_matches_type(SyncOffsetPage[ClientView], event, path=["response"]) - - @parametrize - def test_method_list_with_all_params(self, client: Gcore) -> None: - event = client.security.events.list( - alert_type="ddos_alert", - date_from=parse_datetime("2019-12-27T18:11:19.117Z"), - date_to=parse_datetime("2019-12-27T18:11:19.117Z"), - limit=1, - offset=0, - ordering="attack_start_time", - targeted_ip_addresses="targeted_ip_addresses", - ) - assert_matches_type(SyncOffsetPage[ClientView], event, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Gcore) -> None: - response = client.security.events.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - event = response.parse() - assert_matches_type(SyncOffsetPage[ClientView], event, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Gcore) -> None: - with client.security.events.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - event = response.parse() - assert_matches_type(SyncOffsetPage[ClientView], event, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncEvents: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_list(self, async_client: AsyncGcore) -> None: - event = await async_client.security.events.list() - assert_matches_type(AsyncOffsetPage[ClientView], event, path=["response"]) - - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: - event = await async_client.security.events.list( - alert_type="ddos_alert", - date_from=parse_datetime("2019-12-27T18:11:19.117Z"), - date_to=parse_datetime("2019-12-27T18:11:19.117Z"), - limit=1, - offset=0, - ordering="attack_start_time", - targeted_ip_addresses="targeted_ip_addresses", - ) - assert_matches_type(AsyncOffsetPage[ClientView], event, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncGcore) -> None: - response = await async_client.security.events.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - event = await response.parse() - assert_matches_type(AsyncOffsetPage[ClientView], event, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: - async with async_client.security.events.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - event = await response.parse() - assert_matches_type(AsyncOffsetPage[ClientView], event, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/security/test_profile_templates.py b/tests/api_resources/security/test_profile_templates.py deleted file mode 100644 index 7df4918f..00000000 --- a/tests/api_resources/security/test_profile_templates.py +++ /dev/null @@ -1,74 +0,0 @@ -# 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.security import ProfileTemplateListResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestProfileTemplates: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_list(self, client: Gcore) -> None: - profile_template = client.security.profile_templates.list() - assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Gcore) -> None: - response = client.security.profile_templates.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile_template = response.parse() - assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Gcore) -> None: - with client.security.profile_templates.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile_template = response.parse() - assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncProfileTemplates: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_list(self, async_client: AsyncGcore) -> None: - profile_template = await async_client.security.profile_templates.list() - assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncGcore) -> None: - response = await async_client.security.profile_templates.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile_template = await response.parse() - assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: - async with async_client.security.profile_templates.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile_template = await response.parse() - assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/security/test_profiles.py b/tests/api_resources/security/test_profiles.py deleted file mode 100644 index c79499ab..00000000 --- a/tests/api_resources/security/test_profiles.py +++ /dev/null @@ -1,537 +0,0 @@ -# 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.security import ( - ClientProfile, - ProfileListResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestProfiles: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Gcore) -> None: - profile = client.security.profiles.create( - fields=[{"base_field": 1}], - profile_template=1, - site="GNC", - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_method_create_with_all_params(self, client: Gcore) -> None: - profile = client.security.profiles.create( - fields=[ - { - "base_field": 1, - "field_value": {}, - } - ], - profile_template=1, - site="GNC", - ip_address="123.43.2.10", - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_raw_response_create(self, client: Gcore) -> None: - response = client.security.profiles.with_raw_response.create( - fields=[{"base_field": 1}], - profile_template=1, - site="GNC", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_streaming_response_create(self, client: Gcore) -> None: - with client.security.profiles.with_streaming_response.create( - fields=[{"base_field": 1}], - profile_template=1, - site="GNC", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_list(self, client: Gcore) -> None: - profile = client.security.profiles.list() - assert_matches_type(ProfileListResponse, profile, path=["response"]) - - @parametrize - def test_method_list_with_all_params(self, client: Gcore) -> None: - profile = client.security.profiles.list( - exclude_empty_address=True, - include_deleted=True, - ip_address="ip_address", - site="site", - ) - assert_matches_type(ProfileListResponse, profile, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Gcore) -> None: - response = client.security.profiles.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = response.parse() - assert_matches_type(ProfileListResponse, profile, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Gcore) -> None: - with client.security.profiles.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = response.parse() - assert_matches_type(ProfileListResponse, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_delete(self, client: Gcore) -> None: - profile = client.security.profiles.delete( - 0, - ) - assert profile is None - - @parametrize - def test_raw_response_delete(self, client: Gcore) -> None: - response = client.security.profiles.with_raw_response.delete( - 0, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = response.parse() - assert profile is None - - @parametrize - def test_streaming_response_delete(self, client: Gcore) -> None: - with client.security.profiles.with_streaming_response.delete( - 0, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = response.parse() - assert profile is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_get(self, client: Gcore) -> None: - profile = client.security.profiles.get( - 0, - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_raw_response_get(self, client: Gcore) -> None: - response = client.security.profiles.with_raw_response.get( - 0, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_streaming_response_get(self, client: Gcore) -> None: - with client.security.profiles.with_streaming_response.get( - 0, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_recreate(self, client: Gcore) -> None: - profile = client.security.profiles.recreate( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_method_recreate_with_all_params(self, client: Gcore) -> None: - profile = client.security.profiles.recreate( - id=0, - fields=[ - { - "base_field": 1, - "field_value": {}, - } - ], - profile_template=1, - ip_address="ip_address", - site="ED", - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_raw_response_recreate(self, client: Gcore) -> None: - response = client.security.profiles.with_raw_response.recreate( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_streaming_response_recreate(self, client: Gcore) -> None: - with client.security.profiles.with_streaming_response.recreate( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_replace(self, client: Gcore) -> None: - profile = client.security.profiles.replace( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_method_replace_with_all_params(self, client: Gcore) -> None: - profile = client.security.profiles.replace( - id=0, - fields=[ - { - "base_field": 1, - "field_value": {}, - } - ], - profile_template=1, - ip_address="ip_address", - site="ED", - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_raw_response_replace(self, client: Gcore) -> None: - response = client.security.profiles.with_raw_response.replace( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - def test_streaming_response_replace(self, client: Gcore) -> None: - with client.security.profiles.with_streaming_response.replace( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncProfiles: - 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: - profile = await async_client.security.profiles.create( - fields=[{"base_field": 1}], - profile_template=1, - site="GNC", - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> None: - profile = await async_client.security.profiles.create( - fields=[ - { - "base_field": 1, - "field_value": {}, - } - ], - profile_template=1, - site="GNC", - ip_address="123.43.2.10", - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_raw_response_create(self, async_client: AsyncGcore) -> None: - response = await async_client.security.profiles.with_raw_response.create( - fields=[{"base_field": 1}], - profile_template=1, - site="GNC", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = await response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncGcore) -> None: - async with async_client.security.profiles.with_streaming_response.create( - fields=[{"base_field": 1}], - profile_template=1, - site="GNC", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = await response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_list(self, async_client: AsyncGcore) -> None: - profile = await async_client.security.profiles.list() - assert_matches_type(ProfileListResponse, profile, path=["response"]) - - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: - profile = await async_client.security.profiles.list( - exclude_empty_address=True, - include_deleted=True, - ip_address="ip_address", - site="site", - ) - assert_matches_type(ProfileListResponse, profile, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncGcore) -> None: - response = await async_client.security.profiles.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = await response.parse() - assert_matches_type(ProfileListResponse, profile, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: - async with async_client.security.profiles.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = await response.parse() - assert_matches_type(ProfileListResponse, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_delete(self, async_client: AsyncGcore) -> None: - profile = await async_client.security.profiles.delete( - 0, - ) - assert profile is None - - @parametrize - async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: - response = await async_client.security.profiles.with_raw_response.delete( - 0, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = await response.parse() - assert profile is None - - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncGcore) -> None: - async with async_client.security.profiles.with_streaming_response.delete( - 0, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = await response.parse() - assert profile is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_get(self, async_client: AsyncGcore) -> None: - profile = await async_client.security.profiles.get( - 0, - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_raw_response_get(self, async_client: AsyncGcore) -> None: - response = await async_client.security.profiles.with_raw_response.get( - 0, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = await response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_streaming_response_get(self, async_client: AsyncGcore) -> None: - async with async_client.security.profiles.with_streaming_response.get( - 0, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = await response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_recreate(self, async_client: AsyncGcore) -> None: - profile = await async_client.security.profiles.recreate( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_method_recreate_with_all_params(self, async_client: AsyncGcore) -> None: - profile = await async_client.security.profiles.recreate( - id=0, - fields=[ - { - "base_field": 1, - "field_value": {}, - } - ], - profile_template=1, - ip_address="ip_address", - site="ED", - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_raw_response_recreate(self, async_client: AsyncGcore) -> None: - response = await async_client.security.profiles.with_raw_response.recreate( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = await response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_streaming_response_recreate(self, async_client: AsyncGcore) -> None: - async with async_client.security.profiles.with_streaming_response.recreate( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = await response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_replace(self, async_client: AsyncGcore) -> None: - profile = await async_client.security.profiles.replace( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_method_replace_with_all_params(self, async_client: AsyncGcore) -> None: - profile = await async_client.security.profiles.replace( - id=0, - fields=[ - { - "base_field": 1, - "field_value": {}, - } - ], - profile_template=1, - ip_address="ip_address", - site="ED", - ) - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_raw_response_replace(self, async_client: AsyncGcore) -> None: - response = await async_client.security.profiles.with_raw_response.replace( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - profile = await response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - @parametrize - async def test_streaming_response_replace(self, async_client: AsyncGcore) -> None: - async with async_client.security.profiles.with_streaming_response.replace( - id=0, - fields=[{"base_field": 1}], - profile_template=1, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - profile = await response.parse() - assert_matches_type(ClientProfile, profile, path=["response"]) - - assert cast(Any, response.is_closed) is True From 9bf8a18f42a2122f43d9084ff3287e4d1aa7dd95 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 16:11:06 +0000 Subject: [PATCH 21/27] chore(internal): grammar fix (it's -> its) --- src/gcore/_utils/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 7e17f98624fecfb8d1ad5a53a001dcd20ca15214 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 07:34:13 +0000 Subject: [PATCH 22/27] feat(api): aggregated API specs update --- .stats.yml | 4 ++-- .../resources/cloud/load_balancers/pools/pools.py | 4 ++-- src/gcore/types/cloud/k8s/k8s_cluster_kubeconfig.py | 12 ++++++++++++ src/gcore/types/cloud/load_balancer_create_params.py | 2 +- .../types/cloud/load_balancers/pool_create_params.py | 2 +- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index d0525a7d..505403dc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 599 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-963021ac0cb8a12826d7e00d317340e71748a27c18553422a76d882d2e8ad389.yml -openapi_spec_hash: 0c1ea27cd584bf0d47fed367663053b2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-54e13cd82113c74d43e82dc26f72f31cc1c7dcbdba376c44513a707a954ad778.yml +openapi_spec_hash: 044a6432c14ebaa2c163ad90733d10a8 config_hash: 4758209f53bb13d06f55e4cf6c952b6d diff --git a/src/gcore/resources/cloud/load_balancers/pools/pools.py b/src/gcore/resources/cloud/load_balancers/pools/pools.py index b258a0f1..3dd5314b 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, @@ -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, 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 0ab6f5ce..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] 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] From e008291499f90553d12deffbcef5c4a9b6752f61 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 10:11:50 +0000 Subject: [PATCH 23/27] feat(api): aggregated API specs update --- .stats.yml | 4 +-- README.md | 16 ++++----- src/gcore/resources/cloud/projects.py | 28 +++------------ .../types/cloud/project_create_params.py | 6 ---- tests/api_resources/cloud/test_projects.py | 36 +++++++++---------- tests/test_client.py | 28 +++++++-------- 6 files changed, 44 insertions(+), 74 deletions(-) diff --git a/.stats.yml b/.stats.yml index 505403dc..373cf5e0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 599 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-54e13cd82113c74d43e82dc26f72f31cc1c7dcbdba376c44513a707a954ad778.yml -openapi_spec_hash: 044a6432c14ebaa2c163ad90733d10a8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-62590a431788ed5841ef8a0e86fdf0d666ef18819a2a1c784a573b03fb314f60.yml +openapi_spec_hash: cf5994f5522f209e3c2e3290bc7b418a config_hash: 4758209f53bb13d06f55e4cf6c952b6d 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/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/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/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 5e4cd0ed..8f4855f7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -377,11 +377,11 @@ def test_default_query_option(self) -> None: 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="New Project") + 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, client: Gcore) -> None: # Test with base client (no custom params) @@ -753,7 +753,7 @@ 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(client) == 0 @@ -763,7 +763,7 @@ 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__() + 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]) @@ -792,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 @@ -815,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 @@ -840,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" @@ -1216,11 +1216,11 @@ async def test_default_query_option(self) -> None: 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="New Project") + 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, async_client: AsyncGcore) -> None: # Test with base client (no custom params) @@ -1603,7 +1603,7 @@ 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(async_client) == 0 @@ -1613,7 +1613,7 @@ 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__() + 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]) @@ -1642,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 @@ -1667,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 @@ -1692,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" From c69f622f4d085d5c93978edbf4deb2ecbe4279d6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 13:57:16 +0000 Subject: [PATCH 24/27] feat(api): aggregated API specs update --- .stats.yml | 6 +- api.md | 42 +- src/gcore/_client.py | 9 + src/gcore/resources/__init__.py | 14 + src/gcore/resources/security/__init__.py | 75 ++ src/gcore/resources/security/bgp_announces.py | 308 ++++++++ src/gcore/resources/security/events.py | 234 +++++++ .../resources/security/profile_templates.py | 143 ++++ src/gcore/resources/security/profiles.py | 661 ++++++++++++++++++ src/gcore/resources/security/security.py | 198 ++++++ src/gcore/types/security/__init__.py | 15 + .../security/bgp_announce_list_params.py | 18 + .../security/bgp_announce_list_response.py | 10 + .../security/bgp_announce_toggle_params.py | 16 + src/gcore/types/security/client_announce.py | 15 + src/gcore/types/security/client_profile.py | 56 ++ .../types/security/client_profile_template.py | 43 ++ src/gcore/types/security/client_view.py | 29 + src/gcore/types/security/event_list_params.py | 38 + .../types/security/profile_create_params.py | 24 + .../types/security/profile_list_params.py | 17 + .../types/security/profile_list_response.py | 10 + .../types/security/profile_recreate_params.py | 24 + .../types/security/profile_replace_params.py | 24 + .../profile_template_list_response.py | 10 + tests/api_resources/security/__init__.py | 1 + .../security/test_bgp_announces.py | 180 +++++ tests/api_resources/security/test_events.py | 102 +++ .../security/test_profile_templates.py | 74 ++ tests/api_resources/security/test_profiles.py | 537 ++++++++++++++ 30 files changed, 2928 insertions(+), 5 deletions(-) create mode 100644 src/gcore/resources/security/__init__.py create mode 100644 src/gcore/resources/security/bgp_announces.py create mode 100644 src/gcore/resources/security/events.py create mode 100644 src/gcore/resources/security/profile_templates.py create mode 100644 src/gcore/resources/security/profiles.py create mode 100644 src/gcore/resources/security/security.py create mode 100644 src/gcore/types/security/bgp_announce_list_params.py create mode 100644 src/gcore/types/security/bgp_announce_list_response.py create mode 100644 src/gcore/types/security/bgp_announce_toggle_params.py create mode 100644 src/gcore/types/security/client_announce.py create mode 100644 src/gcore/types/security/client_profile.py create mode 100644 src/gcore/types/security/client_profile_template.py create mode 100644 src/gcore/types/security/client_view.py create mode 100644 src/gcore/types/security/event_list_params.py create mode 100644 src/gcore/types/security/profile_create_params.py create mode 100644 src/gcore/types/security/profile_list_params.py create mode 100644 src/gcore/types/security/profile_list_response.py create mode 100644 src/gcore/types/security/profile_recreate_params.py create mode 100644 src/gcore/types/security/profile_replace_params.py create mode 100644 src/gcore/types/security/profile_template_list_response.py create mode 100644 tests/api_resources/security/__init__.py create mode 100644 tests/api_resources/security/test_bgp_announces.py create mode 100644 tests/api_resources/security/test_events.py create mode 100644 tests/api_resources/security/test_profile_templates.py create mode 100644 tests/api_resources/security/test_profiles.py diff --git a/.stats.yml b/.stats.yml index 373cf5e0..72bd8302 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 599 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-62590a431788ed5841ef8a0e86fdf0d666ef18819a2a1c784a573b03fb314f60.yml -openapi_spec_hash: cf5994f5522f209e3c2e3290bc7b418a +configured_endpoints: 609 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-1089f2c131ebee7df82e158c4210c07f019b47549d84fe6ea7f022117c83a008.yml +openapi_spec_hash: 9758acbadc1ee1bc0d826d4657e1ad4a config_hash: 4758209f53bb13d06f55e4cf6c952b6d diff --git a/api.md b/api.md index 2fe398c1..6ff46915 100644 --- a/api.md +++ b/api.md @@ -1789,22 +1789,60 @@ Methods: # Security +## Events + +Types: + +```python +from gcore.types.security import ClientView +``` + +Methods: + +- client.security.events.list(\*\*params) -> SyncOffsetPage[ClientView] + +## BgpAnnounces + +Types: + +```python +from gcore.types.security import ClientAnnounce, BgpAnnounceListResponse +``` + +Methods: + +- client.security.bgp_announces.list(\*\*params) -> BgpAnnounceListResponse +- client.security.bgp_announces.toggle(\*\*params) -> object + ## ProfileTemplates Types: ```python -from gcore.types.security import ClientProfileTemplate +from gcore.types.security import ClientProfileTemplate, ProfileTemplateListResponse ``` +Methods: + +- client.security.profile_templates.list() -> ProfileTemplateListResponse + ## Profiles Types: ```python -from gcore.types.security import ClientProfile +from gcore.types.security import ClientProfile, ProfileListResponse ``` +Methods: + +- client.security.profiles.create(\*\*params) -> ClientProfile +- client.security.profiles.list(\*\*params) -> ProfileListResponse +- client.security.profiles.delete(id) -> None +- client.security.profiles.get(id) -> ClientProfile +- client.security.profiles.recreate(id, \*\*params) -> ClientProfile +- client.security.profiles.replace(id, \*\*params) -> ClientProfile + # DNS Types: diff --git a/src/gcore/_client.py b/src/gcore/_client.py index df7f4886..d900f571 100644 --- a/src/gcore/_client.py +++ b/src/gcore/_client.py @@ -35,6 +35,7 @@ from .resources.cloud import cloud from .resources.storage import storage from .resources.fastedge import fastedge +from .resources.security import security from .resources.streaming import streaming __all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "Gcore", "AsyncGcore", "Client", "AsyncClient"] @@ -46,6 +47,7 @@ class Gcore(SyncAPIClient): iam: iam.IamResource fastedge: fastedge.FastedgeResource streaming: streaming.StreamingResource + security: security.SecurityResource dns: dns.DNSResource storage: storage.StorageResource cdn: cdn.CdnResource @@ -138,6 +140,7 @@ def __init__( self.iam = iam.IamResource(self) self.fastedge = fastedge.FastedgeResource(self) self.streaming = streaming.StreamingResource(self) + self.security = security.SecurityResource(self) self.dns = dns.DNSResource(self) self.storage = storage.StorageResource(self) self.cdn = cdn.CdnResource(self) @@ -281,6 +284,7 @@ class AsyncGcore(AsyncAPIClient): iam: iam.AsyncIamResource fastedge: fastedge.AsyncFastedgeResource streaming: streaming.AsyncStreamingResource + security: security.AsyncSecurityResource dns: dns.AsyncDNSResource storage: storage.AsyncStorageResource cdn: cdn.AsyncCdnResource @@ -373,6 +377,7 @@ def __init__( self.iam = iam.AsyncIamResource(self) self.fastedge = fastedge.AsyncFastedgeResource(self) self.streaming = streaming.AsyncStreamingResource(self) + self.security = security.AsyncSecurityResource(self) self.dns = dns.AsyncDNSResource(self) self.storage = storage.AsyncStorageResource(self) self.cdn = cdn.AsyncCdnResource(self) @@ -517,6 +522,7 @@ def __init__(self, client: Gcore) -> None: self.iam = iam.IamResourceWithRawResponse(client.iam) self.fastedge = fastedge.FastedgeResourceWithRawResponse(client.fastedge) self.streaming = streaming.StreamingResourceWithRawResponse(client.streaming) + self.security = security.SecurityResourceWithRawResponse(client.security) self.dns = dns.DNSResourceWithRawResponse(client.dns) self.storage = storage.StorageResourceWithRawResponse(client.storage) self.cdn = cdn.CdnResourceWithRawResponse(client.cdn) @@ -529,6 +535,7 @@ def __init__(self, client: AsyncGcore) -> None: self.iam = iam.AsyncIamResourceWithRawResponse(client.iam) self.fastedge = fastedge.AsyncFastedgeResourceWithRawResponse(client.fastedge) self.streaming = streaming.AsyncStreamingResourceWithRawResponse(client.streaming) + self.security = security.AsyncSecurityResourceWithRawResponse(client.security) self.dns = dns.AsyncDNSResourceWithRawResponse(client.dns) self.storage = storage.AsyncStorageResourceWithRawResponse(client.storage) self.cdn = cdn.AsyncCdnResourceWithRawResponse(client.cdn) @@ -541,6 +548,7 @@ def __init__(self, client: Gcore) -> None: self.iam = iam.IamResourceWithStreamingResponse(client.iam) self.fastedge = fastedge.FastedgeResourceWithStreamingResponse(client.fastedge) self.streaming = streaming.StreamingResourceWithStreamingResponse(client.streaming) + self.security = security.SecurityResourceWithStreamingResponse(client.security) self.dns = dns.DNSResourceWithStreamingResponse(client.dns) self.storage = storage.StorageResourceWithStreamingResponse(client.storage) self.cdn = cdn.CdnResourceWithStreamingResponse(client.cdn) @@ -553,6 +561,7 @@ def __init__(self, client: AsyncGcore) -> None: self.iam = iam.AsyncIamResourceWithStreamingResponse(client.iam) self.fastedge = fastedge.AsyncFastedgeResourceWithStreamingResponse(client.fastedge) self.streaming = streaming.AsyncStreamingResourceWithStreamingResponse(client.streaming) + self.security = security.AsyncSecurityResourceWithStreamingResponse(client.security) self.dns = dns.AsyncDNSResourceWithStreamingResponse(client.dns) self.storage = storage.AsyncStorageResourceWithStreamingResponse(client.storage) self.cdn = cdn.AsyncCdnResourceWithStreamingResponse(client.cdn) diff --git a/src/gcore/resources/__init__.py b/src/gcore/resources/__init__.py index d7b63884..c8aaa6a7 100644 --- a/src/gcore/resources/__init__.py +++ b/src/gcore/resources/__init__.py @@ -56,6 +56,14 @@ FastedgeResourceWithStreamingResponse, AsyncFastedgeResourceWithStreamingResponse, ) +from .security import ( + SecurityResource, + AsyncSecurityResource, + SecurityResourceWithRawResponse, + AsyncSecurityResourceWithRawResponse, + SecurityResourceWithStreamingResponse, + AsyncSecurityResourceWithStreamingResponse, +) from .streaming import ( StreamingResource, AsyncStreamingResource, @@ -96,6 +104,12 @@ "AsyncStreamingResourceWithRawResponse", "StreamingResourceWithStreamingResponse", "AsyncStreamingResourceWithStreamingResponse", + "SecurityResource", + "AsyncSecurityResource", + "SecurityResourceWithRawResponse", + "AsyncSecurityResourceWithRawResponse", + "SecurityResourceWithStreamingResponse", + "AsyncSecurityResourceWithStreamingResponse", "DNSResource", "AsyncDNSResource", "DNSResourceWithRawResponse", diff --git a/src/gcore/resources/security/__init__.py b/src/gcore/resources/security/__init__.py new file mode 100644 index 00000000..a1a7a5ea --- /dev/null +++ b/src/gcore/resources/security/__init__.py @@ -0,0 +1,75 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .events import ( + EventsResource, + AsyncEventsResource, + EventsResourceWithRawResponse, + AsyncEventsResourceWithRawResponse, + EventsResourceWithStreamingResponse, + AsyncEventsResourceWithStreamingResponse, +) +from .profiles import ( + ProfilesResource, + AsyncProfilesResource, + ProfilesResourceWithRawResponse, + AsyncProfilesResourceWithRawResponse, + ProfilesResourceWithStreamingResponse, + AsyncProfilesResourceWithStreamingResponse, +) +from .security import ( + SecurityResource, + AsyncSecurityResource, + SecurityResourceWithRawResponse, + AsyncSecurityResourceWithRawResponse, + SecurityResourceWithStreamingResponse, + AsyncSecurityResourceWithStreamingResponse, +) +from .bgp_announces import ( + BgpAnnouncesResource, + AsyncBgpAnnouncesResource, + BgpAnnouncesResourceWithRawResponse, + AsyncBgpAnnouncesResourceWithRawResponse, + BgpAnnouncesResourceWithStreamingResponse, + AsyncBgpAnnouncesResourceWithStreamingResponse, +) +from .profile_templates import ( + ProfileTemplatesResource, + AsyncProfileTemplatesResource, + ProfileTemplatesResourceWithRawResponse, + AsyncProfileTemplatesResourceWithRawResponse, + ProfileTemplatesResourceWithStreamingResponse, + AsyncProfileTemplatesResourceWithStreamingResponse, +) + +__all__ = [ + "EventsResource", + "AsyncEventsResource", + "EventsResourceWithRawResponse", + "AsyncEventsResourceWithRawResponse", + "EventsResourceWithStreamingResponse", + "AsyncEventsResourceWithStreamingResponse", + "BgpAnnouncesResource", + "AsyncBgpAnnouncesResource", + "BgpAnnouncesResourceWithRawResponse", + "AsyncBgpAnnouncesResourceWithRawResponse", + "BgpAnnouncesResourceWithStreamingResponse", + "AsyncBgpAnnouncesResourceWithStreamingResponse", + "ProfileTemplatesResource", + "AsyncProfileTemplatesResource", + "ProfileTemplatesResourceWithRawResponse", + "AsyncProfileTemplatesResourceWithRawResponse", + "ProfileTemplatesResourceWithStreamingResponse", + "AsyncProfileTemplatesResourceWithStreamingResponse", + "ProfilesResource", + "AsyncProfilesResource", + "ProfilesResourceWithRawResponse", + "AsyncProfilesResourceWithRawResponse", + "ProfilesResourceWithStreamingResponse", + "AsyncProfilesResourceWithStreamingResponse", + "SecurityResource", + "AsyncSecurityResource", + "SecurityResourceWithRawResponse", + "AsyncSecurityResourceWithRawResponse", + "SecurityResourceWithStreamingResponse", + "AsyncSecurityResourceWithStreamingResponse", +] diff --git a/src/gcore/resources/security/bgp_announces.py b/src/gcore/resources/security/bgp_announces.py new file mode 100644 index 00000000..26b3bc96 --- /dev/null +++ b/src/gcore/resources/security/bgp_announces.py @@ -0,0 +1,308 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Literal + +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 ..._base_client import make_request_options +from ...types.security import bgp_announce_list_params, bgp_announce_toggle_params +from ...types.security.bgp_announce_list_response import BgpAnnounceListResponse + +__all__ = ["BgpAnnouncesResource", "AsyncBgpAnnouncesResource"] + + +class BgpAnnouncesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> BgpAnnouncesResourceWithRawResponse: + """ + 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 BgpAnnouncesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BgpAnnouncesResourceWithStreamingResponse: + """ + 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 BgpAnnouncesResourceWithStreamingResponse(self) + + def list( + self, + *, + announced: Optional[bool] | Omit = omit, + client_id: Optional[int] | Omit = omit, + origin: Optional[Literal["STATIC", "DYNAMIC"]] | Omit = omit, + site: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BgpAnnounceListResponse: + """Get BGP announces filtered by parameters. + + Shows announces in active profiles, + meaning that to get a non-empty response, the client must have at least one + active profile. + + 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 + """ + return self._get( + "/security/sifter/v2/protected_addresses/announces", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "announced": announced, + "client_id": client_id, + "origin": origin, + "site": site, + }, + bgp_announce_list_params.BgpAnnounceListParams, + ), + ), + cast_to=BgpAnnounceListResponse, + ) + + def toggle( + self, + *, + announce: str, + enabled: bool, + client_id: Optional[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, + ) -> object: + """Change BGP announces (it can be enabled or disabled, but not created or + updated). + + Can be applied to already existing announces in active profiles, + meaning that the client must have at least one active profile. + + 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 + """ + return self._post( + "/security/sifter/v2/protected_addresses/announces", + body=maybe_transform( + { + "announce": announce, + "enabled": enabled, + }, + bgp_announce_toggle_params.BgpAnnounceToggleParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"client_id": client_id}, bgp_announce_toggle_params.BgpAnnounceToggleParams), + ), + cast_to=object, + ) + + +class AsyncBgpAnnouncesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncBgpAnnouncesResourceWithRawResponse: + """ + 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 AsyncBgpAnnouncesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBgpAnnouncesResourceWithStreamingResponse: + """ + 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 AsyncBgpAnnouncesResourceWithStreamingResponse(self) + + async def list( + self, + *, + announced: Optional[bool] | Omit = omit, + client_id: Optional[int] | Omit = omit, + origin: Optional[Literal["STATIC", "DYNAMIC"]] | Omit = omit, + site: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BgpAnnounceListResponse: + """Get BGP announces filtered by parameters. + + Shows announces in active profiles, + meaning that to get a non-empty response, the client must have at least one + active profile. + + 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 + """ + return await self._get( + "/security/sifter/v2/protected_addresses/announces", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "announced": announced, + "client_id": client_id, + "origin": origin, + "site": site, + }, + bgp_announce_list_params.BgpAnnounceListParams, + ), + ), + cast_to=BgpAnnounceListResponse, + ) + + async def toggle( + self, + *, + announce: str, + enabled: bool, + client_id: Optional[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, + ) -> object: + """Change BGP announces (it can be enabled or disabled, but not created or + updated). + + Can be applied to already existing announces in active profiles, + meaning that the client must have at least one active profile. + + 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 + """ + return await self._post( + "/security/sifter/v2/protected_addresses/announces", + body=await async_maybe_transform( + { + "announce": announce, + "enabled": enabled, + }, + bgp_announce_toggle_params.BgpAnnounceToggleParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"client_id": client_id}, bgp_announce_toggle_params.BgpAnnounceToggleParams + ), + ), + cast_to=object, + ) + + +class BgpAnnouncesResourceWithRawResponse: + def __init__(self, bgp_announces: BgpAnnouncesResource) -> None: + self._bgp_announces = bgp_announces + + self.list = to_raw_response_wrapper( + bgp_announces.list, + ) + self.toggle = to_raw_response_wrapper( + bgp_announces.toggle, + ) + + +class AsyncBgpAnnouncesResourceWithRawResponse: + def __init__(self, bgp_announces: AsyncBgpAnnouncesResource) -> None: + self._bgp_announces = bgp_announces + + self.list = async_to_raw_response_wrapper( + bgp_announces.list, + ) + self.toggle = async_to_raw_response_wrapper( + bgp_announces.toggle, + ) + + +class BgpAnnouncesResourceWithStreamingResponse: + def __init__(self, bgp_announces: BgpAnnouncesResource) -> None: + self._bgp_announces = bgp_announces + + self.list = to_streamed_response_wrapper( + bgp_announces.list, + ) + self.toggle = to_streamed_response_wrapper( + bgp_announces.toggle, + ) + + +class AsyncBgpAnnouncesResourceWithStreamingResponse: + def __init__(self, bgp_announces: AsyncBgpAnnouncesResource) -> None: + self._bgp_announces = bgp_announces + + self.list = async_to_streamed_response_wrapper( + bgp_announces.list, + ) + self.toggle = async_to_streamed_response_wrapper( + bgp_announces.toggle, + ) diff --git a/src/gcore/resources/security/events.py b/src/gcore/resources/security/events.py new file mode 100644 index 00000000..e0699398 --- /dev/null +++ b/src/gcore/resources/security/events.py @@ -0,0 +1,234 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Literal + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import 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 ..._base_client import AsyncPaginator, make_request_options +from ...types.security import event_list_params +from ...types.security.client_view import ClientView + +__all__ = ["EventsResource", "AsyncEventsResource"] + + +class EventsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> EventsResourceWithRawResponse: + """ + 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 EventsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> EventsResourceWithStreamingResponse: + """ + 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 EventsResourceWithStreamingResponse(self) + + def list( + self, + *, + alert_type: Optional[Literal["ddos_alert", "rtbh_alert"]] | Omit = omit, + date_from: Union[Union[str, datetime], str] | Omit = omit, + date_to: Union[Union[str, datetime], str] | Omit = omit, + limit: int | Omit = omit, + offset: int | Omit = omit, + ordering: Literal[ + "attack_start_time", + "-attack_start_time", + "attack_power_bps", + "-attack_power_bps", + "attack_power_pps", + "-attack_power_pps", + "number_of_ip_involved_in_attack", + "-number_of_ip_involved_in_attack", + "alert_type", + "-alert_type", + ] + | Omit = omit, + targeted_ip_addresses: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncOffsetPage[ClientView]: + """ + Event Logs Clients View + + 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 + """ + return self._get_api_list( + "/security/notifier/v1/event_logs", + page=SyncOffsetPage[ClientView], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "alert_type": alert_type, + "date_from": date_from, + "date_to": date_to, + "limit": limit, + "offset": offset, + "ordering": ordering, + "targeted_ip_addresses": targeted_ip_addresses, + }, + event_list_params.EventListParams, + ), + ), + model=ClientView, + ) + + +class AsyncEventsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncEventsResourceWithRawResponse: + """ + 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 AsyncEventsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncEventsResourceWithStreamingResponse: + """ + 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 AsyncEventsResourceWithStreamingResponse(self) + + def list( + self, + *, + alert_type: Optional[Literal["ddos_alert", "rtbh_alert"]] | Omit = omit, + date_from: Union[Union[str, datetime], str] | Omit = omit, + date_to: Union[Union[str, datetime], str] | Omit = omit, + limit: int | Omit = omit, + offset: int | Omit = omit, + ordering: Literal[ + "attack_start_time", + "-attack_start_time", + "attack_power_bps", + "-attack_power_bps", + "attack_power_pps", + "-attack_power_pps", + "number_of_ip_involved_in_attack", + "-number_of_ip_involved_in_attack", + "alert_type", + "-alert_type", + ] + | Omit = omit, + targeted_ip_addresses: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[ClientView, AsyncOffsetPage[ClientView]]: + """ + Event Logs Clients View + + 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 + """ + return self._get_api_list( + "/security/notifier/v1/event_logs", + page=AsyncOffsetPage[ClientView], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "alert_type": alert_type, + "date_from": date_from, + "date_to": date_to, + "limit": limit, + "offset": offset, + "ordering": ordering, + "targeted_ip_addresses": targeted_ip_addresses, + }, + event_list_params.EventListParams, + ), + ), + model=ClientView, + ) + + +class EventsResourceWithRawResponse: + def __init__(self, events: EventsResource) -> None: + self._events = events + + self.list = to_raw_response_wrapper( + events.list, + ) + + +class AsyncEventsResourceWithRawResponse: + def __init__(self, events: AsyncEventsResource) -> None: + self._events = events + + self.list = async_to_raw_response_wrapper( + events.list, + ) + + +class EventsResourceWithStreamingResponse: + def __init__(self, events: EventsResource) -> None: + self._events = events + + self.list = to_streamed_response_wrapper( + events.list, + ) + + +class AsyncEventsResourceWithStreamingResponse: + def __init__(self, events: AsyncEventsResource) -> None: + self._events = events + + self.list = async_to_streamed_response_wrapper( + events.list, + ) diff --git a/src/gcore/resources/security/profile_templates.py b/src/gcore/resources/security/profile_templates.py new file mode 100644 index 00000000..307f3c0d --- /dev/null +++ b/src/gcore/resources/security/profile_templates.py @@ -0,0 +1,143 @@ +# 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.security.profile_template_list_response import ProfileTemplateListResponse + +__all__ = ["ProfileTemplatesResource", "AsyncProfileTemplatesResource"] + + +class ProfileTemplatesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ProfileTemplatesResourceWithRawResponse: + """ + 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 ProfileTemplatesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ProfileTemplatesResourceWithStreamingResponse: + """ + 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 ProfileTemplatesResourceWithStreamingResponse(self) + + def list( + self, + *, + # 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, + ) -> ProfileTemplateListResponse: + """Get list of profile templates. + + Profile template is used as a template to create + profile. Client receives only common and created for him profile templates. + """ + return self._get( + "/security/iaas/profile-templates", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProfileTemplateListResponse, + ) + + +class AsyncProfileTemplatesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncProfileTemplatesResourceWithRawResponse: + """ + 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 AsyncProfileTemplatesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncProfileTemplatesResourceWithStreamingResponse: + """ + 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 AsyncProfileTemplatesResourceWithStreamingResponse(self) + + async def list( + self, + *, + # 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, + ) -> ProfileTemplateListResponse: + """Get list of profile templates. + + Profile template is used as a template to create + profile. Client receives only common and created for him profile templates. + """ + return await self._get( + "/security/iaas/profile-templates", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProfileTemplateListResponse, + ) + + +class ProfileTemplatesResourceWithRawResponse: + def __init__(self, profile_templates: ProfileTemplatesResource) -> None: + self._profile_templates = profile_templates + + self.list = to_raw_response_wrapper( + profile_templates.list, + ) + + +class AsyncProfileTemplatesResourceWithRawResponse: + def __init__(self, profile_templates: AsyncProfileTemplatesResource) -> None: + self._profile_templates = profile_templates + + self.list = async_to_raw_response_wrapper( + profile_templates.list, + ) + + +class ProfileTemplatesResourceWithStreamingResponse: + def __init__(self, profile_templates: ProfileTemplatesResource) -> None: + self._profile_templates = profile_templates + + self.list = to_streamed_response_wrapper( + profile_templates.list, + ) + + +class AsyncProfileTemplatesResourceWithStreamingResponse: + def __init__(self, profile_templates: AsyncProfileTemplatesResource) -> None: + self._profile_templates = profile_templates + + self.list = async_to_streamed_response_wrapper( + profile_templates.list, + ) diff --git a/src/gcore/resources/security/profiles.py b/src/gcore/resources/security/profiles.py new file mode 100644 index 00000000..2ddf3257 --- /dev/null +++ b/src/gcore/resources/security/profiles.py @@ -0,0 +1,661 @@ +# 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, NoneType, 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 ..._base_client import make_request_options +from ...types.security import ( + profile_list_params, + profile_create_params, + profile_replace_params, + profile_recreate_params, +) +from ...types.security.client_profile import ClientProfile +from ...types.security.profile_list_response import ProfileListResponse + +__all__ = ["ProfilesResource", "AsyncProfilesResource"] + + +class ProfilesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ProfilesResourceWithRawResponse: + """ + 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 ProfilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ProfilesResourceWithStreamingResponse: + """ + 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 ProfilesResourceWithStreamingResponse(self) + + def create( + self, + *, + fields: Iterable[profile_create_params.Field], + profile_template: int, + site: str, + ip_address: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ClientProfile: + """Create protection profile. + + Protection is enabled at the same time as profile is + created + + 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 + """ + return self._post( + "/security/iaas/v2/profiles", + body=maybe_transform( + { + "fields": fields, + "profile_template": profile_template, + "site": site, + "ip_address": ip_address, + }, + profile_create_params.ProfileCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ClientProfile, + ) + + def list( + self, + *, + exclude_empty_address: bool | Omit = omit, + include_deleted: bool | Omit = omit, + ip_address: str | Omit = omit, + site: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ProfileListResponse: + """Get list of protection profiles. + + Client receives only profiles created by him + + 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 + """ + return self._get( + "/security/iaas/v2/profiles", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "exclude_empty_address": exclude_empty_address, + "include_deleted": include_deleted, + "ip_address": ip_address, + "site": site, + }, + profile_list_params.ProfileListParams, + ), + ), + cast_to=ProfileListResponse, + ) + + def delete( + self, + id: int, + *, + # 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, + ) -> None: + """Delete protection profile. + + Protection is disabled at the same time as profile is + deleted + + 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 + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/security/iaas/v2/profiles/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def get( + self, + id: int, + *, + # 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, + ) -> ClientProfile: + """ + Get profile by id + + 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 + """ + return self._get( + f"/security/iaas/v2/profiles/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ClientProfile, + ) + + def recreate( + self, + id: int, + *, + fields: Iterable[profile_recreate_params.Field], + profile_template: int, + ip_address: Optional[str] | Omit = omit, + site: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ClientProfile: + """ + Recreate profile with another profile template (for other cases use detail API) + + 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 + """ + return self._put( + f"/security/iaas/v2/profiles/{id}/recreate", + body=maybe_transform( + { + "fields": fields, + "profile_template": profile_template, + "ip_address": ip_address, + "site": site, + }, + profile_recreate_params.ProfileRecreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ClientProfile, + ) + + def replace( + self, + id: int, + *, + fields: Iterable[profile_replace_params.Field], + profile_template: int, + ip_address: Optional[str] | Omit = omit, + site: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ClientProfile: + """Update profile. + + Protection policies are updated at the same time as profile + updated + + 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 + """ + return self._put( + f"/security/iaas/v2/profiles/{id}", + body=maybe_transform( + { + "fields": fields, + "profile_template": profile_template, + "ip_address": ip_address, + "site": site, + }, + profile_replace_params.ProfileReplaceParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ClientProfile, + ) + + +class AsyncProfilesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncProfilesResourceWithRawResponse: + """ + 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 AsyncProfilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncProfilesResourceWithStreamingResponse: + """ + 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 AsyncProfilesResourceWithStreamingResponse(self) + + async def create( + self, + *, + fields: Iterable[profile_create_params.Field], + profile_template: int, + site: str, + ip_address: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ClientProfile: + """Create protection profile. + + Protection is enabled at the same time as profile is + created + + 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 + """ + return await self._post( + "/security/iaas/v2/profiles", + body=await async_maybe_transform( + { + "fields": fields, + "profile_template": profile_template, + "site": site, + "ip_address": ip_address, + }, + profile_create_params.ProfileCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ClientProfile, + ) + + async def list( + self, + *, + exclude_empty_address: bool | Omit = omit, + include_deleted: bool | Omit = omit, + ip_address: str | Omit = omit, + site: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ProfileListResponse: + """Get list of protection profiles. + + Client receives only profiles created by him + + 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 + """ + return await self._get( + "/security/iaas/v2/profiles", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "exclude_empty_address": exclude_empty_address, + "include_deleted": include_deleted, + "ip_address": ip_address, + "site": site, + }, + profile_list_params.ProfileListParams, + ), + ), + cast_to=ProfileListResponse, + ) + + async def delete( + self, + id: int, + *, + # 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, + ) -> None: + """Delete protection profile. + + Protection is disabled at the same time as profile is + deleted + + 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 + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + f"/security/iaas/v2/profiles/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def get( + self, + id: int, + *, + # 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, + ) -> ClientProfile: + """ + Get profile by id + + 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 + """ + return await self._get( + f"/security/iaas/v2/profiles/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ClientProfile, + ) + + async def recreate( + self, + id: int, + *, + fields: Iterable[profile_recreate_params.Field], + profile_template: int, + ip_address: Optional[str] | Omit = omit, + site: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ClientProfile: + """ + Recreate profile with another profile template (for other cases use detail API) + + 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 + """ + return await self._put( + f"/security/iaas/v2/profiles/{id}/recreate", + body=await async_maybe_transform( + { + "fields": fields, + "profile_template": profile_template, + "ip_address": ip_address, + "site": site, + }, + profile_recreate_params.ProfileRecreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ClientProfile, + ) + + async def replace( + self, + id: int, + *, + fields: Iterable[profile_replace_params.Field], + profile_template: int, + ip_address: Optional[str] | Omit = omit, + site: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ClientProfile: + """Update profile. + + Protection policies are updated at the same time as profile + updated + + 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 + """ + return await self._put( + f"/security/iaas/v2/profiles/{id}", + body=await async_maybe_transform( + { + "fields": fields, + "profile_template": profile_template, + "ip_address": ip_address, + "site": site, + }, + profile_replace_params.ProfileReplaceParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ClientProfile, + ) + + +class ProfilesResourceWithRawResponse: + def __init__(self, profiles: ProfilesResource) -> None: + self._profiles = profiles + + self.create = to_raw_response_wrapper( + profiles.create, + ) + self.list = to_raw_response_wrapper( + profiles.list, + ) + self.delete = to_raw_response_wrapper( + profiles.delete, + ) + self.get = to_raw_response_wrapper( + profiles.get, + ) + self.recreate = to_raw_response_wrapper( + profiles.recreate, + ) + self.replace = to_raw_response_wrapper( + profiles.replace, + ) + + +class AsyncProfilesResourceWithRawResponse: + def __init__(self, profiles: AsyncProfilesResource) -> None: + self._profiles = profiles + + self.create = async_to_raw_response_wrapper( + profiles.create, + ) + self.list = async_to_raw_response_wrapper( + profiles.list, + ) + self.delete = async_to_raw_response_wrapper( + profiles.delete, + ) + self.get = async_to_raw_response_wrapper( + profiles.get, + ) + self.recreate = async_to_raw_response_wrapper( + profiles.recreate, + ) + self.replace = async_to_raw_response_wrapper( + profiles.replace, + ) + + +class ProfilesResourceWithStreamingResponse: + def __init__(self, profiles: ProfilesResource) -> None: + self._profiles = profiles + + self.create = to_streamed_response_wrapper( + profiles.create, + ) + self.list = to_streamed_response_wrapper( + profiles.list, + ) + self.delete = to_streamed_response_wrapper( + profiles.delete, + ) + self.get = to_streamed_response_wrapper( + profiles.get, + ) + self.recreate = to_streamed_response_wrapper( + profiles.recreate, + ) + self.replace = to_streamed_response_wrapper( + profiles.replace, + ) + + +class AsyncProfilesResourceWithStreamingResponse: + def __init__(self, profiles: AsyncProfilesResource) -> None: + self._profiles = profiles + + self.create = async_to_streamed_response_wrapper( + profiles.create, + ) + self.list = async_to_streamed_response_wrapper( + profiles.list, + ) + self.delete = async_to_streamed_response_wrapper( + profiles.delete, + ) + self.get = async_to_streamed_response_wrapper( + profiles.get, + ) + self.recreate = async_to_streamed_response_wrapper( + profiles.recreate, + ) + self.replace = async_to_streamed_response_wrapper( + profiles.replace, + ) diff --git a/src/gcore/resources/security/security.py b/src/gcore/resources/security/security.py new file mode 100644 index 00000000..2d0d9c11 --- /dev/null +++ b/src/gcore/resources/security/security.py @@ -0,0 +1,198 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .events import ( + EventsResource, + AsyncEventsResource, + EventsResourceWithRawResponse, + AsyncEventsResourceWithRawResponse, + EventsResourceWithStreamingResponse, + AsyncEventsResourceWithStreamingResponse, +) +from .profiles import ( + ProfilesResource, + AsyncProfilesResource, + ProfilesResourceWithRawResponse, + AsyncProfilesResourceWithRawResponse, + ProfilesResourceWithStreamingResponse, + AsyncProfilesResourceWithStreamingResponse, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from .bgp_announces import ( + BgpAnnouncesResource, + AsyncBgpAnnouncesResource, + BgpAnnouncesResourceWithRawResponse, + AsyncBgpAnnouncesResourceWithRawResponse, + BgpAnnouncesResourceWithStreamingResponse, + AsyncBgpAnnouncesResourceWithStreamingResponse, +) +from .profile_templates import ( + ProfileTemplatesResource, + AsyncProfileTemplatesResource, + ProfileTemplatesResourceWithRawResponse, + AsyncProfileTemplatesResourceWithRawResponse, + ProfileTemplatesResourceWithStreamingResponse, + AsyncProfileTemplatesResourceWithStreamingResponse, +) + +__all__ = ["SecurityResource", "AsyncSecurityResource"] + + +class SecurityResource(SyncAPIResource): + @cached_property + def events(self) -> EventsResource: + return EventsResource(self._client) + + @cached_property + def bgp_announces(self) -> BgpAnnouncesResource: + return BgpAnnouncesResource(self._client) + + @cached_property + def profile_templates(self) -> ProfileTemplatesResource: + return ProfileTemplatesResource(self._client) + + @cached_property + def profiles(self) -> ProfilesResource: + return ProfilesResource(self._client) + + @cached_property + def with_raw_response(self) -> SecurityResourceWithRawResponse: + """ + 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 SecurityResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> SecurityResourceWithStreamingResponse: + """ + 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 SecurityResourceWithStreamingResponse(self) + + +class AsyncSecurityResource(AsyncAPIResource): + @cached_property + def events(self) -> AsyncEventsResource: + return AsyncEventsResource(self._client) + + @cached_property + def bgp_announces(self) -> AsyncBgpAnnouncesResource: + return AsyncBgpAnnouncesResource(self._client) + + @cached_property + def profile_templates(self) -> AsyncProfileTemplatesResource: + return AsyncProfileTemplatesResource(self._client) + + @cached_property + def profiles(self) -> AsyncProfilesResource: + return AsyncProfilesResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncSecurityResourceWithRawResponse: + """ + 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 AsyncSecurityResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncSecurityResourceWithStreamingResponse: + """ + 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 AsyncSecurityResourceWithStreamingResponse(self) + + +class SecurityResourceWithRawResponse: + def __init__(self, security: SecurityResource) -> None: + self._security = security + + @cached_property + def events(self) -> EventsResourceWithRawResponse: + return EventsResourceWithRawResponse(self._security.events) + + @cached_property + def bgp_announces(self) -> BgpAnnouncesResourceWithRawResponse: + return BgpAnnouncesResourceWithRawResponse(self._security.bgp_announces) + + @cached_property + def profile_templates(self) -> ProfileTemplatesResourceWithRawResponse: + return ProfileTemplatesResourceWithRawResponse(self._security.profile_templates) + + @cached_property + def profiles(self) -> ProfilesResourceWithRawResponse: + return ProfilesResourceWithRawResponse(self._security.profiles) + + +class AsyncSecurityResourceWithRawResponse: + def __init__(self, security: AsyncSecurityResource) -> None: + self._security = security + + @cached_property + def events(self) -> AsyncEventsResourceWithRawResponse: + return AsyncEventsResourceWithRawResponse(self._security.events) + + @cached_property + def bgp_announces(self) -> AsyncBgpAnnouncesResourceWithRawResponse: + return AsyncBgpAnnouncesResourceWithRawResponse(self._security.bgp_announces) + + @cached_property + def profile_templates(self) -> AsyncProfileTemplatesResourceWithRawResponse: + return AsyncProfileTemplatesResourceWithRawResponse(self._security.profile_templates) + + @cached_property + def profiles(self) -> AsyncProfilesResourceWithRawResponse: + return AsyncProfilesResourceWithRawResponse(self._security.profiles) + + +class SecurityResourceWithStreamingResponse: + def __init__(self, security: SecurityResource) -> None: + self._security = security + + @cached_property + def events(self) -> EventsResourceWithStreamingResponse: + return EventsResourceWithStreamingResponse(self._security.events) + + @cached_property + def bgp_announces(self) -> BgpAnnouncesResourceWithStreamingResponse: + return BgpAnnouncesResourceWithStreamingResponse(self._security.bgp_announces) + + @cached_property + def profile_templates(self) -> ProfileTemplatesResourceWithStreamingResponse: + return ProfileTemplatesResourceWithStreamingResponse(self._security.profile_templates) + + @cached_property + def profiles(self) -> ProfilesResourceWithStreamingResponse: + return ProfilesResourceWithStreamingResponse(self._security.profiles) + + +class AsyncSecurityResourceWithStreamingResponse: + def __init__(self, security: AsyncSecurityResource) -> None: + self._security = security + + @cached_property + def events(self) -> AsyncEventsResourceWithStreamingResponse: + return AsyncEventsResourceWithStreamingResponse(self._security.events) + + @cached_property + def bgp_announces(self) -> AsyncBgpAnnouncesResourceWithStreamingResponse: + return AsyncBgpAnnouncesResourceWithStreamingResponse(self._security.bgp_announces) + + @cached_property + def profile_templates(self) -> AsyncProfileTemplatesResourceWithStreamingResponse: + return AsyncProfileTemplatesResourceWithStreamingResponse(self._security.profile_templates) + + @cached_property + def profiles(self) -> AsyncProfilesResourceWithStreamingResponse: + return AsyncProfilesResourceWithStreamingResponse(self._security.profiles) diff --git a/src/gcore/types/security/__init__.py b/src/gcore/types/security/__init__.py index f8ee8b14..4994ea70 100644 --- a/src/gcore/types/security/__init__.py +++ b/src/gcore/types/security/__init__.py @@ -1,3 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations + +from .client_view import ClientView as ClientView +from .client_profile import ClientProfile as ClientProfile +from .client_announce import ClientAnnounce as ClientAnnounce +from .event_list_params import EventListParams as EventListParams +from .profile_list_params import ProfileListParams as ProfileListParams +from .profile_create_params import ProfileCreateParams as ProfileCreateParams +from .profile_list_response import ProfileListResponse as ProfileListResponse +from .profile_replace_params import ProfileReplaceParams as ProfileReplaceParams +from .client_profile_template import ClientProfileTemplate as ClientProfileTemplate +from .profile_recreate_params import ProfileRecreateParams as ProfileRecreateParams +from .bgp_announce_list_params import BgpAnnounceListParams as BgpAnnounceListParams +from .bgp_announce_list_response import BgpAnnounceListResponse as BgpAnnounceListResponse +from .bgp_announce_toggle_params import BgpAnnounceToggleParams as BgpAnnounceToggleParams +from .profile_template_list_response import ProfileTemplateListResponse as ProfileTemplateListResponse diff --git a/src/gcore/types/security/bgp_announce_list_params.py b/src/gcore/types/security/bgp_announce_list_params.py new file mode 100644 index 00000000..390464fe --- /dev/null +++ b/src/gcore/types/security/bgp_announce_list_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 import Optional +from typing_extensions import Literal, TypedDict + +__all__ = ["BgpAnnounceListParams"] + + +class BgpAnnounceListParams(TypedDict, total=False): + announced: Optional[bool] + + client_id: Optional[int] + + origin: Optional[Literal["STATIC", "DYNAMIC"]] + + site: Optional[str] diff --git a/src/gcore/types/security/bgp_announce_list_response.py b/src/gcore/types/security/bgp_announce_list_response.py new file mode 100644 index 00000000..6981ba90 --- /dev/null +++ b/src/gcore/types/security/bgp_announce_list_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import TypeAlias + +from .client_announce import ClientAnnounce + +__all__ = ["BgpAnnounceListResponse"] + +BgpAnnounceListResponse: TypeAlias = List[ClientAnnounce] diff --git a/src/gcore/types/security/bgp_announce_toggle_params.py b/src/gcore/types/security/bgp_announce_toggle_params.py new file mode 100644 index 00000000..4c5dd1b6 --- /dev/null +++ b/src/gcore/types/security/bgp_announce_toggle_params.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Required, TypedDict + +__all__ = ["BgpAnnounceToggleParams"] + + +class BgpAnnounceToggleParams(TypedDict, total=False): + announce: Required[str] + + enabled: Required[bool] + + client_id: Optional[int] diff --git a/src/gcore/types/security/client_announce.py b/src/gcore/types/security/client_announce.py new file mode 100644 index 00000000..ef276615 --- /dev/null +++ b/src/gcore/types/security/client_announce.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__ = ["ClientAnnounce"] + + +class ClientAnnounce(BaseModel): + announced: List[str] + + client_id: int + + not_announced: List[str] diff --git a/src/gcore/types/security/client_profile.py b/src/gcore/types/security/client_profile.py new file mode 100644 index 00000000..e02111b5 --- /dev/null +++ b/src/gcore/types/security/client_profile.py @@ -0,0 +1,56 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional + +from ..._models import BaseModel +from .client_profile_template import ClientProfileTemplate + +__all__ = ["ClientProfile", "Field", "Options"] + + +class Field(BaseModel): + id: int + + base_field: int + + default: str + + description: str + + field_type: str + + name: str + + required: bool + + validation_schema: Dict[str, object] + + field_value: Optional[object] = None + + +class Options(BaseModel): + active: bool + + bgp: bool + + price: str + + +class ClientProfile(BaseModel): + id: int + + fields: List[Field] + + options: Options + + plan: str + + profile_template: ClientProfileTemplate + + protocols: List[Dict[str, object]] + + site: str + + status: Dict[str, object] + + ip_address: Optional[str] = None diff --git a/src/gcore/types/security/client_profile_template.py b/src/gcore/types/security/client_profile_template.py new file mode 100644 index 00000000..4ea63e14 --- /dev/null +++ b/src/gcore/types/security/client_profile_template.py @@ -0,0 +1,43 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["ClientProfileTemplate", "Field"] + + +class Field(BaseModel): + id: int + + name: str + + default: Optional[str] = None + + description: Optional[str] = None + + field_type: Optional[Literal["int", "bool", "str"]] = None + + required: Optional[bool] = None + + validation_schema: Optional[Dict[str, object]] = None + + +class ClientProfileTemplate(BaseModel): + id: int + + created: datetime + + fields: List[Field] + + name: str + + version: str + + base_template: Optional[int] = None + + description: Optional[str] = None + + template_sifter: Optional[str] = None diff --git a/src/gcore/types/security/client_view.py b/src/gcore/types/security/client_view.py new file mode 100644 index 00000000..802060ab --- /dev/null +++ b/src/gcore/types/security/client_view.py @@ -0,0 +1,29 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["ClientView"] + + +class ClientView(BaseModel): + id: str + + alert_type: Optional[Literal["ddos_alert", "rtbh_alert"]] = None + + attack_power_bps: Optional[float] = None + + attack_power_pps: Optional[float] = None + + attack_start_time: Optional[datetime] = None + + client_id: Optional[int] = None + + notification_type: Optional[str] = None + + number_of_ip_involved_in_attack: Optional[int] = None + + targeted_ip_addresses: Optional[str] = None diff --git a/src/gcore/types/security/event_list_params.py b/src/gcore/types/security/event_list_params.py new file mode 100644 index 00000000..0bd703c3 --- /dev/null +++ b/src/gcore/types/security/event_list_params.py @@ -0,0 +1,38 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["EventListParams"] + + +class EventListParams(TypedDict, total=False): + alert_type: Optional[Literal["ddos_alert", "rtbh_alert"]] + + date_from: Annotated[Union[Union[str, datetime], str], PropertyInfo(format="iso8601")] + + date_to: Annotated[Union[Union[str, datetime], str], PropertyInfo(format="iso8601")] + + limit: int + + offset: int + + ordering: Literal[ + "attack_start_time", + "-attack_start_time", + "attack_power_bps", + "-attack_power_bps", + "attack_power_pps", + "-attack_power_pps", + "number_of_ip_involved_in_attack", + "-number_of_ip_involved_in_attack", + "alert_type", + "-alert_type", + ] + + targeted_ip_addresses: Optional[str] diff --git a/src/gcore/types/security/profile_create_params.py b/src/gcore/types/security/profile_create_params.py new file mode 100644 index 00000000..ad7b982c --- /dev/null +++ b/src/gcore/types/security/profile_create_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable, Optional +from typing_extensions import Required, TypedDict + +__all__ = ["ProfileCreateParams", "Field"] + + +class ProfileCreateParams(TypedDict, total=False): + fields: Required[Iterable[Field]] + + profile_template: Required[int] + + site: Required[str] + + ip_address: Optional[str] + + +class Field(TypedDict, total=False): + base_field: Required[int] + + field_value: object diff --git a/src/gcore/types/security/profile_list_params.py b/src/gcore/types/security/profile_list_params.py new file mode 100644 index 00000000..e54f232f --- /dev/null +++ b/src/gcore/types/security/profile_list_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ProfileListParams"] + + +class ProfileListParams(TypedDict, total=False): + exclude_empty_address: bool + + include_deleted: bool + + ip_address: str + + site: str diff --git a/src/gcore/types/security/profile_list_response.py b/src/gcore/types/security/profile_list_response.py new file mode 100644 index 00000000..816021c8 --- /dev/null +++ b/src/gcore/types/security/profile_list_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import TypeAlias + +from .client_profile import ClientProfile + +__all__ = ["ProfileListResponse"] + +ProfileListResponse: TypeAlias = List[ClientProfile] diff --git a/src/gcore/types/security/profile_recreate_params.py b/src/gcore/types/security/profile_recreate_params.py new file mode 100644 index 00000000..e1dd3d10 --- /dev/null +++ b/src/gcore/types/security/profile_recreate_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable, Optional +from typing_extensions import Required, TypedDict + +__all__ = ["ProfileRecreateParams", "Field"] + + +class ProfileRecreateParams(TypedDict, total=False): + fields: Required[Iterable[Field]] + + profile_template: Required[int] + + ip_address: Optional[str] + + site: str + + +class Field(TypedDict, total=False): + base_field: Required[int] + + field_value: object diff --git a/src/gcore/types/security/profile_replace_params.py b/src/gcore/types/security/profile_replace_params.py new file mode 100644 index 00000000..9684dffd --- /dev/null +++ b/src/gcore/types/security/profile_replace_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable, Optional +from typing_extensions import Required, TypedDict + +__all__ = ["ProfileReplaceParams", "Field"] + + +class ProfileReplaceParams(TypedDict, total=False): + fields: Required[Iterable[Field]] + + profile_template: Required[int] + + ip_address: Optional[str] + + site: str + + +class Field(TypedDict, total=False): + base_field: Required[int] + + field_value: object diff --git a/src/gcore/types/security/profile_template_list_response.py b/src/gcore/types/security/profile_template_list_response.py new file mode 100644 index 00000000..2264e970 --- /dev/null +++ b/src/gcore/types/security/profile_template_list_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import TypeAlias + +from .client_profile_template import ClientProfileTemplate + +__all__ = ["ProfileTemplateListResponse"] + +ProfileTemplateListResponse: TypeAlias = List[ClientProfileTemplate] diff --git a/tests/api_resources/security/__init__.py b/tests/api_resources/security/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/security/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/security/test_bgp_announces.py b/tests/api_resources/security/test_bgp_announces.py new file mode 100644 index 00000000..c1115976 --- /dev/null +++ b/tests/api_resources/security/test_bgp_announces.py @@ -0,0 +1,180 @@ +# 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.security import BgpAnnounceListResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestBgpAnnounces: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: Gcore) -> None: + bgp_announce = client.security.bgp_announces.list() + assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Gcore) -> None: + bgp_announce = client.security.bgp_announces.list( + announced=True, + client_id=0, + origin="STATIC", + site="x", + ) + assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Gcore) -> None: + response = client.security.bgp_announces.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bgp_announce = response.parse() + assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Gcore) -> None: + with client.security.bgp_announces.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bgp_announce = response.parse() + assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_toggle(self, client: Gcore) -> None: + bgp_announce = client.security.bgp_announces.toggle( + announce="192.9.9.1/32", + enabled=True, + ) + assert_matches_type(object, bgp_announce, path=["response"]) + + @parametrize + def test_method_toggle_with_all_params(self, client: Gcore) -> None: + bgp_announce = client.security.bgp_announces.toggle( + announce="192.9.9.1/32", + enabled=True, + client_id=0, + ) + assert_matches_type(object, bgp_announce, path=["response"]) + + @parametrize + def test_raw_response_toggle(self, client: Gcore) -> None: + response = client.security.bgp_announces.with_raw_response.toggle( + announce="192.9.9.1/32", + enabled=True, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bgp_announce = response.parse() + assert_matches_type(object, bgp_announce, path=["response"]) + + @parametrize + def test_streaming_response_toggle(self, client: Gcore) -> None: + with client.security.bgp_announces.with_streaming_response.toggle( + announce="192.9.9.1/32", + enabled=True, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bgp_announce = response.parse() + assert_matches_type(object, bgp_announce, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncBgpAnnounces: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_list(self, async_client: AsyncGcore) -> None: + bgp_announce = await async_client.security.bgp_announces.list() + assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: + bgp_announce = await async_client.security.bgp_announces.list( + announced=True, + client_id=0, + origin="STATIC", + site="x", + ) + assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncGcore) -> None: + response = await async_client.security.bgp_announces.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bgp_announce = await response.parse() + assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: + async with async_client.security.bgp_announces.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bgp_announce = await response.parse() + assert_matches_type(BgpAnnounceListResponse, bgp_announce, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_toggle(self, async_client: AsyncGcore) -> None: + bgp_announce = await async_client.security.bgp_announces.toggle( + announce="192.9.9.1/32", + enabled=True, + ) + assert_matches_type(object, bgp_announce, path=["response"]) + + @parametrize + async def test_method_toggle_with_all_params(self, async_client: AsyncGcore) -> None: + bgp_announce = await async_client.security.bgp_announces.toggle( + announce="192.9.9.1/32", + enabled=True, + client_id=0, + ) + assert_matches_type(object, bgp_announce, path=["response"]) + + @parametrize + async def test_raw_response_toggle(self, async_client: AsyncGcore) -> None: + response = await async_client.security.bgp_announces.with_raw_response.toggle( + announce="192.9.9.1/32", + enabled=True, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bgp_announce = await response.parse() + assert_matches_type(object, bgp_announce, path=["response"]) + + @parametrize + async def test_streaming_response_toggle(self, async_client: AsyncGcore) -> None: + async with async_client.security.bgp_announces.with_streaming_response.toggle( + announce="192.9.9.1/32", + enabled=True, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bgp_announce = await response.parse() + assert_matches_type(object, bgp_announce, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/security/test_events.py b/tests/api_resources/security/test_events.py new file mode 100644 index 00000000..650de2cf --- /dev/null +++ b/tests/api_resources/security/test_events.py @@ -0,0 +1,102 @@ +# 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._utils import parse_datetime +from gcore.pagination import SyncOffsetPage, AsyncOffsetPage +from gcore.types.security import ClientView + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestEvents: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: Gcore) -> None: + event = client.security.events.list() + assert_matches_type(SyncOffsetPage[ClientView], event, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Gcore) -> None: + event = client.security.events.list( + alert_type="ddos_alert", + date_from=parse_datetime("2019-12-27T18:11:19.117Z"), + date_to=parse_datetime("2019-12-27T18:11:19.117Z"), + limit=1, + offset=0, + ordering="attack_start_time", + targeted_ip_addresses="targeted_ip_addresses", + ) + assert_matches_type(SyncOffsetPage[ClientView], event, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Gcore) -> None: + response = client.security.events.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = response.parse() + assert_matches_type(SyncOffsetPage[ClientView], event, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Gcore) -> None: + with client.security.events.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + event = response.parse() + assert_matches_type(SyncOffsetPage[ClientView], event, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncEvents: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_list(self, async_client: AsyncGcore) -> None: + event = await async_client.security.events.list() + assert_matches_type(AsyncOffsetPage[ClientView], event, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: + event = await async_client.security.events.list( + alert_type="ddos_alert", + date_from=parse_datetime("2019-12-27T18:11:19.117Z"), + date_to=parse_datetime("2019-12-27T18:11:19.117Z"), + limit=1, + offset=0, + ordering="attack_start_time", + targeted_ip_addresses="targeted_ip_addresses", + ) + assert_matches_type(AsyncOffsetPage[ClientView], event, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncGcore) -> None: + response = await async_client.security.events.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = await response.parse() + assert_matches_type(AsyncOffsetPage[ClientView], event, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: + async with async_client.security.events.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + event = await response.parse() + assert_matches_type(AsyncOffsetPage[ClientView], event, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/security/test_profile_templates.py b/tests/api_resources/security/test_profile_templates.py new file mode 100644 index 00000000..7df4918f --- /dev/null +++ b/tests/api_resources/security/test_profile_templates.py @@ -0,0 +1,74 @@ +# 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.security import ProfileTemplateListResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestProfileTemplates: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: Gcore) -> None: + profile_template = client.security.profile_templates.list() + assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Gcore) -> None: + response = client.security.profile_templates.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile_template = response.parse() + assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Gcore) -> None: + with client.security.profile_templates.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile_template = response.parse() + assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncProfileTemplates: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_list(self, async_client: AsyncGcore) -> None: + profile_template = await async_client.security.profile_templates.list() + assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncGcore) -> None: + response = await async_client.security.profile_templates.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile_template = await response.parse() + assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: + async with async_client.security.profile_templates.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile_template = await response.parse() + assert_matches_type(ProfileTemplateListResponse, profile_template, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/security/test_profiles.py b/tests/api_resources/security/test_profiles.py new file mode 100644 index 00000000..c79499ab --- /dev/null +++ b/tests/api_resources/security/test_profiles.py @@ -0,0 +1,537 @@ +# 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.security import ( + ClientProfile, + ProfileListResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestProfiles: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Gcore) -> None: + profile = client.security.profiles.create( + fields=[{"base_field": 1}], + profile_template=1, + site="GNC", + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Gcore) -> None: + profile = client.security.profiles.create( + fields=[ + { + "base_field": 1, + "field_value": {}, + } + ], + profile_template=1, + site="GNC", + ip_address="123.43.2.10", + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Gcore) -> None: + response = client.security.profiles.with_raw_response.create( + fields=[{"base_field": 1}], + profile_template=1, + site="GNC", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Gcore) -> None: + with client.security.profiles.with_streaming_response.create( + fields=[{"base_field": 1}], + profile_template=1, + site="GNC", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_list(self, client: Gcore) -> None: + profile = client.security.profiles.list() + assert_matches_type(ProfileListResponse, profile, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Gcore) -> None: + profile = client.security.profiles.list( + exclude_empty_address=True, + include_deleted=True, + ip_address="ip_address", + site="site", + ) + assert_matches_type(ProfileListResponse, profile, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Gcore) -> None: + response = client.security.profiles.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = response.parse() + assert_matches_type(ProfileListResponse, profile, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Gcore) -> None: + with client.security.profiles.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = response.parse() + assert_matches_type(ProfileListResponse, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_delete(self, client: Gcore) -> None: + profile = client.security.profiles.delete( + 0, + ) + assert profile is None + + @parametrize + def test_raw_response_delete(self, client: Gcore) -> None: + response = client.security.profiles.with_raw_response.delete( + 0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = response.parse() + assert profile is None + + @parametrize + def test_streaming_response_delete(self, client: Gcore) -> None: + with client.security.profiles.with_streaming_response.delete( + 0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = response.parse() + assert profile is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_get(self, client: Gcore) -> None: + profile = client.security.profiles.get( + 0, + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Gcore) -> None: + response = client.security.profiles.with_raw_response.get( + 0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Gcore) -> None: + with client.security.profiles.with_streaming_response.get( + 0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_recreate(self, client: Gcore) -> None: + profile = client.security.profiles.recreate( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_method_recreate_with_all_params(self, client: Gcore) -> None: + profile = client.security.profiles.recreate( + id=0, + fields=[ + { + "base_field": 1, + "field_value": {}, + } + ], + profile_template=1, + ip_address="ip_address", + site="ED", + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_raw_response_recreate(self, client: Gcore) -> None: + response = client.security.profiles.with_raw_response.recreate( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_streaming_response_recreate(self, client: Gcore) -> None: + with client.security.profiles.with_streaming_response.recreate( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_replace(self, client: Gcore) -> None: + profile = client.security.profiles.replace( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_method_replace_with_all_params(self, client: Gcore) -> None: + profile = client.security.profiles.replace( + id=0, + fields=[ + { + "base_field": 1, + "field_value": {}, + } + ], + profile_template=1, + ip_address="ip_address", + site="ED", + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_raw_response_replace(self, client: Gcore) -> None: + response = client.security.profiles.with_raw_response.replace( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + def test_streaming_response_replace(self, client: Gcore) -> None: + with client.security.profiles.with_streaming_response.replace( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncProfiles: + 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: + profile = await async_client.security.profiles.create( + fields=[{"base_field": 1}], + profile_template=1, + site="GNC", + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncGcore) -> None: + profile = await async_client.security.profiles.create( + fields=[ + { + "base_field": 1, + "field_value": {}, + } + ], + profile_template=1, + site="GNC", + ip_address="123.43.2.10", + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncGcore) -> None: + response = await async_client.security.profiles.with_raw_response.create( + fields=[{"base_field": 1}], + profile_template=1, + site="GNC", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = await response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncGcore) -> None: + async with async_client.security.profiles.with_streaming_response.create( + fields=[{"base_field": 1}], + profile_template=1, + site="GNC", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = await response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_list(self, async_client: AsyncGcore) -> None: + profile = await async_client.security.profiles.list() + assert_matches_type(ProfileListResponse, profile, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncGcore) -> None: + profile = await async_client.security.profiles.list( + exclude_empty_address=True, + include_deleted=True, + ip_address="ip_address", + site="site", + ) + assert_matches_type(ProfileListResponse, profile, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncGcore) -> None: + response = await async_client.security.profiles.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = await response.parse() + assert_matches_type(ProfileListResponse, profile, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncGcore) -> None: + async with async_client.security.profiles.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = await response.parse() + assert_matches_type(ProfileListResponse, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_delete(self, async_client: AsyncGcore) -> None: + profile = await async_client.security.profiles.delete( + 0, + ) + assert profile is None + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncGcore) -> None: + response = await async_client.security.profiles.with_raw_response.delete( + 0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = await response.parse() + assert profile is None + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncGcore) -> None: + async with async_client.security.profiles.with_streaming_response.delete( + 0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = await response.parse() + assert profile is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_get(self, async_client: AsyncGcore) -> None: + profile = await async_client.security.profiles.get( + 0, + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncGcore) -> None: + response = await async_client.security.profiles.with_raw_response.get( + 0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = await response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncGcore) -> None: + async with async_client.security.profiles.with_streaming_response.get( + 0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = await response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_recreate(self, async_client: AsyncGcore) -> None: + profile = await async_client.security.profiles.recreate( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_method_recreate_with_all_params(self, async_client: AsyncGcore) -> None: + profile = await async_client.security.profiles.recreate( + id=0, + fields=[ + { + "base_field": 1, + "field_value": {}, + } + ], + profile_template=1, + ip_address="ip_address", + site="ED", + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_raw_response_recreate(self, async_client: AsyncGcore) -> None: + response = await async_client.security.profiles.with_raw_response.recreate( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = await response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_streaming_response_recreate(self, async_client: AsyncGcore) -> None: + async with async_client.security.profiles.with_streaming_response.recreate( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = await response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_replace(self, async_client: AsyncGcore) -> None: + profile = await async_client.security.profiles.replace( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_method_replace_with_all_params(self, async_client: AsyncGcore) -> None: + profile = await async_client.security.profiles.replace( + id=0, + fields=[ + { + "base_field": 1, + "field_value": {}, + } + ], + profile_template=1, + ip_address="ip_address", + site="ED", + ) + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_raw_response_replace(self, async_client: AsyncGcore) -> None: + response = await async_client.security.profiles.with_raw_response.replace( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + profile = await response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + @parametrize + async def test_streaming_response_replace(self, async_client: AsyncGcore) -> None: + async with async_client.security.profiles.with_streaming_response.replace( + id=0, + fields=[{"base_field": 1}], + profile_template=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + profile = await response.parse() + assert_matches_type(ClientProfile, profile, path=["response"]) + + assert cast(Any, response.is_closed) is True From 27bc07acab63505e03f4a5b51e21544fe84877ec Mon Sep 17 00:00:00 2001 From: Pedro Oliveira <8281907+pedrodeoliveira@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:04:30 +0000 Subject: [PATCH 25/27] fix(cloud): members not optional in lb pools create_and_poll --- src/gcore/resources/cloud/load_balancers/pools/pools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gcore/resources/cloud/load_balancers/pools/pools.py b/src/gcore/resources/cloud/load_balancers/pools/pools.py index 3dd5314b..121406f7 100644 --- a/src/gcore/resources/cloud/load_balancers/pools/pools.py +++ b/src/gcore/resources/cloud/load_balancers/pools/pools.py @@ -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, @@ -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, From 2802edf3bbac88b644ba8ff4d5b83dc0606e4b48 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:47:43 +0000 Subject: [PATCH 26/27] feat(cloud): add support for postgres --- .stats.yml | 4 +- api.md | 57 ++ src/gcore/resources/cloud/__init__.py | 14 + src/gcore/resources/cloud/cloud.py | 32 + .../resources/cloud/databases/__init__.py | 33 + .../resources/cloud/databases/databases.py | 102 +++ .../cloud/databases/postgres/__init__.py | 61 ++ .../databases/postgres/clusters/__init__.py | 33 + .../databases/postgres/clusters/clusters.py | 716 +++++++++++++++++ .../postgres/clusters/user_credentials.py | 281 +++++++ .../databases/postgres/configurations.py | 169 ++++ .../postgres/custom_configurations.py | 197 +++++ .../cloud/databases/postgres/postgres.py | 166 ++++ src/gcore/types/cloud/databases/__init__.py | 3 + .../cloud/databases/postgres/__init__.py | 12 + .../postgres/cluster_create_params.py | 108 +++ .../databases/postgres/cluster_list_params.py | 19 + .../postgres/cluster_update_params.py | 102 +++ .../databases/postgres/clusters/__init__.py | 5 + .../clusters/postgres_user_credentials.py | 13 + .../custom_configuration_validate_params.py | 19 + .../databases/postgres/pg_conf_validation.py | 15 + .../databases/postgres/postgres_cluster.py | 118 +++ .../postgres/postgres_cluster_short.py | 22 + .../postgres/postgres_configuration.py | 31 + .../api_resources/cloud/databases/__init__.py | 1 + .../cloud/databases/postgres/__init__.py | 1 + .../databases/postgres/clusters/__init__.py | 1 + .../clusters/test_user_credentials.py | 256 ++++++ .../cloud/databases/postgres/test_clusters.py | 731 ++++++++++++++++++ .../databases/postgres/test_configurations.py | 92 +++ .../postgres/test_custom_configurations.py | 104 +++ 32 files changed, 3516 insertions(+), 2 deletions(-) create mode 100644 src/gcore/resources/cloud/databases/__init__.py create mode 100644 src/gcore/resources/cloud/databases/databases.py create mode 100644 src/gcore/resources/cloud/databases/postgres/__init__.py create mode 100644 src/gcore/resources/cloud/databases/postgres/clusters/__init__.py create mode 100644 src/gcore/resources/cloud/databases/postgres/clusters/clusters.py create mode 100644 src/gcore/resources/cloud/databases/postgres/clusters/user_credentials.py create mode 100644 src/gcore/resources/cloud/databases/postgres/configurations.py create mode 100644 src/gcore/resources/cloud/databases/postgres/custom_configurations.py create mode 100644 src/gcore/resources/cloud/databases/postgres/postgres.py create mode 100644 src/gcore/types/cloud/databases/__init__.py create mode 100644 src/gcore/types/cloud/databases/postgres/__init__.py create mode 100644 src/gcore/types/cloud/databases/postgres/cluster_create_params.py create mode 100644 src/gcore/types/cloud/databases/postgres/cluster_list_params.py create mode 100644 src/gcore/types/cloud/databases/postgres/cluster_update_params.py create mode 100644 src/gcore/types/cloud/databases/postgres/clusters/__init__.py create mode 100644 src/gcore/types/cloud/databases/postgres/clusters/postgres_user_credentials.py create mode 100644 src/gcore/types/cloud/databases/postgres/custom_configuration_validate_params.py create mode 100644 src/gcore/types/cloud/databases/postgres/pg_conf_validation.py create mode 100644 src/gcore/types/cloud/databases/postgres/postgres_cluster.py create mode 100644 src/gcore/types/cloud/databases/postgres/postgres_cluster_short.py create mode 100644 src/gcore/types/cloud/databases/postgres/postgres_configuration.py create mode 100644 tests/api_resources/cloud/databases/__init__.py create mode 100644 tests/api_resources/cloud/databases/postgres/__init__.py create mode 100644 tests/api_resources/cloud/databases/postgres/clusters/__init__.py create mode 100644 tests/api_resources/cloud/databases/postgres/clusters/test_user_credentials.py create mode 100644 tests/api_resources/cloud/databases/postgres/test_clusters.py create mode 100644 tests/api_resources/cloud/databases/postgres/test_configurations.py create mode 100644 tests/api_resources/cloud/databases/postgres/test_custom_configurations.py diff --git a/.stats.yml b/.stats.yml index 72bd8302..bb221715 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 609 +configured_endpoints: 618 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gcore%2Fgcore-1089f2c131ebee7df82e158c4210c07f019b47549d84fe6ea7f022117c83a008.yml openapi_spec_hash: 9758acbadc1ee1bc0d826d4657e1ad4a -config_hash: 4758209f53bb13d06f55e4cf6c952b6d +config_hash: 79098512b2ff15053f2813524c207add diff --git a/api.md b/api.md index 6ff46915..180b482b 100644 --- a/api.md +++ b/api.md @@ -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: 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/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/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/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 From 286449dce9f2ef848b2abdd1206252e3e5f2cc77 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:48:16 +0000 Subject: [PATCH 27/27] release: 0.18.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/gcore/_version.py | 2 +- 4 files changed, 33 insertions(+), 3 deletions(-) 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/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/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/_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