From 6183681a3b05a7ef00db573df23340c5aa5d1552 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 01:23:01 +0000 Subject: [PATCH] feat(api): fix internal URL mappings (#2267) --- .stats.yml | 2 +- api.md | 56 ++ src/cloudflare/_client.py | 37 ++ src/cloudflare/resources/abuse_reports.py | 492 ++++++++++++++++++ .../resources/zero_trust/devices/__init__.py | 14 + .../resources/zero_trust/devices/devices.py | 32 ++ .../zero_trust/devices/fleet_status.py | 220 ++++++++ .../resources/zero_trust/dex/__init__.py | 14 + .../zero_trust/dex/commands/__init__.py | 47 ++ .../zero_trust/dex/commands/commands.py | 417 +++++++++++++++ .../zero_trust/dex/commands/downloads.py | 190 +++++++ .../zero_trust/dex/commands/quota.py | 176 +++++++ .../resources/zero_trust/dex/dex.py | 33 ++ src/cloudflare/resources/zones/holds.py | 134 ++++- .../types/abuse_reports/__init__.py | 6 + .../abuse_report_create_params.py | 140 +++++ .../abuse_report_create_response.py | 7 + .../types/zero_trust/devices/__init__.py | 2 + .../devices/fleet_status_get_params.py | 20 + .../devices/fleet_status_get_response.py | 268 ++++++++++ .../types/zero_trust/dex/__init__.py | 4 + .../zero_trust/dex/command_create_params.py | 57 ++ .../zero_trust/dex/command_create_response.py | 30 ++ .../zero_trust/dex/command_list_params.py | 39 ++ .../zero_trust/dex/command_list_response.py | 30 ++ .../types/zero_trust/dex/commands/__init__.py | 2 + .../dex/commands/quota_get_response.py | 18 + src/cloudflare/types/zones/__init__.py | 1 + .../types/zones/hold_edit_params.py | 29 ++ tests/api_resources/test_abuse_reports.py | 233 +++++++++ .../zero_trust/devices/test_fleet_status.py | 150 ++++++ .../zero_trust/dex/commands/__init__.py | 1 + .../zero_trust/dex/commands/test_downloads.py | 184 +++++++ .../zero_trust/dex/commands/test_quota.py | 98 ++++ .../zero_trust/dex/test_commands.py | 281 ++++++++++ tests/api_resources/zones/test_holds.py | 94 ++++ 36 files changed, 3556 insertions(+), 2 deletions(-) create mode 100644 src/cloudflare/resources/abuse_reports.py create mode 100644 src/cloudflare/resources/zero_trust/devices/fleet_status.py create mode 100644 src/cloudflare/resources/zero_trust/dex/commands/__init__.py create mode 100644 src/cloudflare/resources/zero_trust/dex/commands/commands.py create mode 100644 src/cloudflare/resources/zero_trust/dex/commands/downloads.py create mode 100644 src/cloudflare/resources/zero_trust/dex/commands/quota.py create mode 100644 src/cloudflare/types/abuse_reports/__init__.py create mode 100644 src/cloudflare/types/abuse_reports/abuse_report_create_params.py create mode 100644 src/cloudflare/types/abuse_reports/abuse_report_create_response.py create mode 100644 src/cloudflare/types/zero_trust/devices/fleet_status_get_params.py create mode 100644 src/cloudflare/types/zero_trust/devices/fleet_status_get_response.py create mode 100644 src/cloudflare/types/zero_trust/dex/command_create_params.py create mode 100644 src/cloudflare/types/zero_trust/dex/command_create_response.py create mode 100644 src/cloudflare/types/zero_trust/dex/command_list_params.py create mode 100644 src/cloudflare/types/zero_trust/dex/command_list_response.py create mode 100644 src/cloudflare/types/zero_trust/dex/commands/quota_get_response.py create mode 100644 src/cloudflare/types/zones/hold_edit_params.py create mode 100644 tests/api_resources/test_abuse_reports.py create mode 100644 tests/api_resources/zero_trust/devices/test_fleet_status.py create mode 100644 tests/api_resources/zero_trust/dex/commands/__init__.py create mode 100644 tests/api_resources/zero_trust/dex/commands/test_downloads.py create mode 100644 tests/api_resources/zero_trust/dex/commands/test_quota.py create mode 100644 tests/api_resources/zero_trust/dex/test_commands.py diff --git a/.stats.yml b/.stats.yml index 3b704f87bcf..5d7b2c16a46 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 1455 +configured_endpoints: 1462 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare%2Fcloudflare-4118c37824cecf34c05447175906b84c57105e89ea6a092fee7047b46613e094.yml diff --git a/api.md b/api.md index 6e0daf9fc74..1d108198dc0 100644 --- a/api.md +++ b/api.md @@ -417,6 +417,7 @@ Methods: - client.zones.holds.create(\*, zone_id, \*\*params) -> ZoneHold - client.zones.holds.delete(\*, zone_id, \*\*params) -> ZoneHold +- client.zones.holds.edit(\*, zone_id, \*\*params) -> ZoneHold - client.zones.holds.get(\*, zone_id) -> ZoneHold ## Subscriptions @@ -4841,6 +4842,18 @@ Methods: - client.zero_trust.devices.networks.delete(network_id, \*, account_id) -> Optional[NetworkDeleteResponse] - client.zero_trust.devices.networks.get(network_id, \*, account_id) -> Optional[DeviceNetwork] +### FleetStatus + +Types: + +```python +from cloudflare.types.zero_trust.devices import FleetStatusGetResponse +``` + +Methods: + +- client.zero_trust.devices.fleet_status.get(device_id, \*, account_id, \*\*params) -> FleetStatusGetResponse + ### Policies Types: @@ -5579,6 +5592,37 @@ from cloudflare.types.zero_trust import ( ) ``` +### Commands + +Types: + +```python +from cloudflare.types.zero_trust.dex import CommandCreateResponse, CommandListResponse +``` + +Methods: + +- client.zero_trust.dex.commands.create(\*, account_id, \*\*params) -> Optional[CommandCreateResponse] +- client.zero_trust.dex.commands.list(\*, account_id, \*\*params) -> SyncV4PagePagination[Optional[CommandListResponse]] + +#### Downloads + +Methods: + +- client.zero_trust.dex.commands.downloads.get(filename, \*, account_id, command_id) -> BinaryAPIResponse + +#### Quota + +Types: + +```python +from cloudflare.types.zero_trust.dex.commands import QuotaGetResponse +``` + +Methods: + +- client.zero_trust.dex.commands.quota.get(\*, account_id) -> Optional[QuotaGetResponse] + ### Colos Types: @@ -8359,3 +8403,15 @@ from cloudflare.types.content_scanning import SettingGetResponse Methods: - client.content_scanning.settings.get(\*, zone_id) -> SettingGetResponse + +# AbuseReports + +Types: + +```python +from cloudflare.types.abuse_reports import AbuseReportCreateResponse +``` + +Methods: + +- client.abuse_reports.create(report_type, \*, account_id, \*\*params) -> str diff --git a/src/cloudflare/_client.py b/src/cloudflare/_client.py index ec966ca654c..4d5c2d1b7ff 100644 --- a/src/cloudflare/_client.py +++ b/src/cloudflare/_client.py @@ -91,6 +91,7 @@ dns_firewall, healthchecks, security_txt, + abuse_reports, email_routing, magic_transit, waiting_rooms, @@ -711,6 +712,12 @@ def content_scanning(self) -> content_scanning.ContentScanningResource: return ContentScanningResource(self) + @cached_property + def abuse_reports(self) -> abuse_reports.AbuseReportsResource: + from .resources.abuse_reports import AbuseReportsResource + + return AbuseReportsResource(self) + @cached_property def with_raw_response(self) -> CloudflareWithRawResponse: return CloudflareWithRawResponse(self) @@ -1470,6 +1477,12 @@ def content_scanning(self) -> content_scanning.AsyncContentScanningResource: return AsyncContentScanningResource(self) + @cached_property + def abuse_reports(self) -> abuse_reports.AsyncAbuseReportsResource: + from .resources.abuse_reports import AsyncAbuseReportsResource + + return AsyncAbuseReportsResource(self) + @cached_property def with_raw_response(self) -> AsyncCloudflareWithRawResponse: return AsyncCloudflareWithRawResponse(self) @@ -2164,6 +2177,12 @@ def content_scanning(self) -> content_scanning.ContentScanningResourceWithRawRes return ContentScanningResourceWithRawResponse(self._client.content_scanning) + @cached_property + def abuse_reports(self) -> abuse_reports.AbuseReportsResourceWithRawResponse: + from .resources.abuse_reports import AbuseReportsResourceWithRawResponse + + return AbuseReportsResourceWithRawResponse(self._client.abuse_reports) + class AsyncCloudflareWithRawResponse: _client: AsyncCloudflare @@ -2677,6 +2696,12 @@ def content_scanning(self) -> content_scanning.AsyncContentScanningResourceWithR return AsyncContentScanningResourceWithRawResponse(self._client.content_scanning) + @cached_property + def abuse_reports(self) -> abuse_reports.AsyncAbuseReportsResourceWithRawResponse: + from .resources.abuse_reports import AsyncAbuseReportsResourceWithRawResponse + + return AsyncAbuseReportsResourceWithRawResponse(self._client.abuse_reports) + class CloudflareWithStreamedResponse: _client: Cloudflare @@ -3190,6 +3215,12 @@ def content_scanning(self) -> content_scanning.ContentScanningResourceWithStream return ContentScanningResourceWithStreamingResponse(self._client.content_scanning) + @cached_property + def abuse_reports(self) -> abuse_reports.AbuseReportsResourceWithStreamingResponse: + from .resources.abuse_reports import AbuseReportsResourceWithStreamingResponse + + return AbuseReportsResourceWithStreamingResponse(self._client.abuse_reports) + class AsyncCloudflareWithStreamedResponse: _client: AsyncCloudflare @@ -3713,6 +3744,12 @@ def content_scanning(self) -> content_scanning.AsyncContentScanningResourceWithS return AsyncContentScanningResourceWithStreamingResponse(self._client.content_scanning) + @cached_property + def abuse_reports(self) -> abuse_reports.AsyncAbuseReportsResourceWithStreamingResponse: + from .resources.abuse_reports import AsyncAbuseReportsResourceWithStreamingResponse + + return AsyncAbuseReportsResourceWithStreamingResponse(self._client.abuse_reports) + Client = Cloudflare diff --git a/src/cloudflare/resources/abuse_reports.py b/src/cloudflare/resources/abuse_reports.py new file mode 100644 index 00000000000..45241233b4a --- /dev/null +++ b/src/cloudflare/resources/abuse_reports.py @@ -0,0 +1,492 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Type, cast +from typing_extensions import Literal + +import httpx + +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +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 .._wrappers import ResultWrapper +from .._base_client import make_request_options +from ..types.abuse_reports import abuse_report_create_params +from ..types.abuse_reports.abuse_report_create_response import AbuseReportCreateResponse + +__all__ = ["AbuseReportsResource", "AsyncAbuseReportsResource"] + + +class AbuseReportsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> AbuseReportsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AbuseReportsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AbuseReportsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AbuseReportsResourceWithStreamingResponse(self) + + def create( + self, + report_type: Literal[ + "abuse_dmca", + "abuse_trademark", + "abuse_general", + "abuse_phishing", + "abuse_children", + "abuse_threat", + "abuse_registrar_whois", + "abuse_ncsei", + ], + *, + account_id: str, + act: Literal[ + "abuse_dmca", + "abuse_trademark", + "abuse_general", + "abuse_phishing", + "abuse_children", + "abuse_threat", + "abuse_registrar_whois", + "abuse_ncsei", + ], + email: str, + email2: str, + host_notification: Literal["send", "send-anon", "none"], + ncmec_notification: Literal["send", "send-anon", "none"], + owner_notification: Literal["send", "send-anon", "none"], + urls: str, + address1: str | NotGiven = NOT_GIVEN, + agent_name: str | NotGiven = NOT_GIVEN, + agree: Literal[0, 1] | NotGiven = NOT_GIVEN, + city: str | NotGiven = NOT_GIVEN, + comments: str | NotGiven = NOT_GIVEN, + company: str | NotGiven = NOT_GIVEN, + country: str | NotGiven = NOT_GIVEN, + destination_ips: str | NotGiven = NOT_GIVEN, + justification: str | NotGiven = NOT_GIVEN, + name: str | NotGiven = NOT_GIVEN, + ncsei_subject_representation: bool | NotGiven = NOT_GIVEN, + original_work: str | NotGiven = NOT_GIVEN, + ports_protocols: str | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + source_ips: str | NotGiven = NOT_GIVEN, + state: str | NotGiven = NOT_GIVEN, + tele: str | NotGiven = NOT_GIVEN, + title: str | NotGiven = NOT_GIVEN, + trademark_number: str | NotGiven = NOT_GIVEN, + trademark_office: str | NotGiven = NOT_GIVEN, + trademark_symbol: str | NotGiven = NOT_GIVEN, + # 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, + ) -> str: + """ + Submit the Abuse Report of a particular type + + Args: + report_type: The abuse report type + + act: The abuse report type + + email: A valid email of the abuse reporter + + email2: Should match the value provided in `email` + + host_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark + reports cannot be anonymous. + + ncmec_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark + reports cannot be anonymous. + + owner_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark + reports cannot be anonymous. + + urls: A list of valid URLs separated by ‘ ’ (new line character). The list of the URLs + should not exceed 250 URLs. All URLs should have the same hostname. Each URL + should be unique + + address1: Text not exceeding 100 characters + + agent_name: The name of the copyright holder. Text not exceeding 60 characters. + + agree: Can be 0 or 1 + + city: Text not exceeding 255 characters + + comments: Any additional comments about the infringement not exceeding 2000 characters + + company: Text not exceeding 100 characters + + country: Text not exceeding 255 characters + + destination_ips: A list of IP addresses separated by ‘ ’ (new line character). The list of + destination IPs should not exceed 30 IP addresses. Each one of the IP addresses + ought to be unique + + justification: A detailed description of the infringement, including any necessary access + details and the exact steps needed to view the content, not exceeding 5000 + characters + + name: Text not exceeding 255 characters + + ncsei_subject_representation: If the submitter is the target of NCSEI in the URLs of the abuse report + + original_work: Text not exceeding 255 characters + + ports_protocols: A comma separated list of ports and protocols e.g. 80/TCP, 22/UDP. The total + size of the field should not exceed 2000 characters. Each individual + port/protocol should not exceed 100 characters. The list should not have more + than 30 unique ports and protocols. + + signature: Required for DMCA reports, should be same as Name. An affirmation that all + information in the report is true and accurate while agreeing to the policies of + Cloudflare's abuse reports + + source_ips: A list of IP addresses separated by ‘ ’ (new line character). The list of source + IPs should not exceed 30 IP addresses. Each one of the IP addresses ought to be + unique + + state: Text not exceeding 255 characters + + tele: Text not exceeding 20 characters + + title: Text not exceeding 255 characters + + trademark_number: Text not exceeding 1000 characters + + trademark_office: Text not exceeding 1000 characters + + trademark_symbol: Text not exceeding 1000 characters + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not report_type: + raise ValueError(f"Expected a non-empty value for `report_type` but received {report_type!r}") + return self._post( + f"/accounts/{account_id}/v1/abuse-reports/{report_type}", + body=maybe_transform( + { + "act": act, + "email": email, + "email2": email2, + "host_notification": host_notification, + "ncmec_notification": ncmec_notification, + "owner_notification": owner_notification, + "urls": urls, + "address1": address1, + "agent_name": agent_name, + "agree": agree, + "city": city, + "comments": comments, + "company": company, + "country": country, + "destination_ips": destination_ips, + "justification": justification, + "name": name, + "ncsei_subject_representation": ncsei_subject_representation, + "original_work": original_work, + "ports_protocols": ports_protocols, + "signature": signature, + "source_ips": source_ips, + "state": state, + "tele": tele, + "title": title, + "trademark_number": trademark_number, + "trademark_office": trademark_office, + "trademark_symbol": trademark_symbol, + }, + abuse_report_create_params.AbuseReportCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[AbuseReportCreateResponse]._unwrapper, + ), + cast_to=cast(Type[str], ResultWrapper[str]), + ) + + +class AsyncAbuseReportsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAbuseReportsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncAbuseReportsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAbuseReportsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncAbuseReportsResourceWithStreamingResponse(self) + + async def create( + self, + report_type: Literal[ + "abuse_dmca", + "abuse_trademark", + "abuse_general", + "abuse_phishing", + "abuse_children", + "abuse_threat", + "abuse_registrar_whois", + "abuse_ncsei", + ], + *, + account_id: str, + act: Literal[ + "abuse_dmca", + "abuse_trademark", + "abuse_general", + "abuse_phishing", + "abuse_children", + "abuse_threat", + "abuse_registrar_whois", + "abuse_ncsei", + ], + email: str, + email2: str, + host_notification: Literal["send", "send-anon", "none"], + ncmec_notification: Literal["send", "send-anon", "none"], + owner_notification: Literal["send", "send-anon", "none"], + urls: str, + address1: str | NotGiven = NOT_GIVEN, + agent_name: str | NotGiven = NOT_GIVEN, + agree: Literal[0, 1] | NotGiven = NOT_GIVEN, + city: str | NotGiven = NOT_GIVEN, + comments: str | NotGiven = NOT_GIVEN, + company: str | NotGiven = NOT_GIVEN, + country: str | NotGiven = NOT_GIVEN, + destination_ips: str | NotGiven = NOT_GIVEN, + justification: str | NotGiven = NOT_GIVEN, + name: str | NotGiven = NOT_GIVEN, + ncsei_subject_representation: bool | NotGiven = NOT_GIVEN, + original_work: str | NotGiven = NOT_GIVEN, + ports_protocols: str | NotGiven = NOT_GIVEN, + signature: str | NotGiven = NOT_GIVEN, + source_ips: str | NotGiven = NOT_GIVEN, + state: str | NotGiven = NOT_GIVEN, + tele: str | NotGiven = NOT_GIVEN, + title: str | NotGiven = NOT_GIVEN, + trademark_number: str | NotGiven = NOT_GIVEN, + trademark_office: str | NotGiven = NOT_GIVEN, + trademark_symbol: str | NotGiven = NOT_GIVEN, + # 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, + ) -> str: + """ + Submit the Abuse Report of a particular type + + Args: + report_type: The abuse report type + + act: The abuse report type + + email: A valid email of the abuse reporter + + email2: Should match the value provided in `email` + + host_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark + reports cannot be anonymous. + + ncmec_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark + reports cannot be anonymous. + + owner_notification: Notification type based on the abuse type. NOTE: Copyright (DMCA) and Trademark + reports cannot be anonymous. + + urls: A list of valid URLs separated by ‘ ’ (new line character). The list of the URLs + should not exceed 250 URLs. All URLs should have the same hostname. Each URL + should be unique + + address1: Text not exceeding 100 characters + + agent_name: The name of the copyright holder. Text not exceeding 60 characters. + + agree: Can be 0 or 1 + + city: Text not exceeding 255 characters + + comments: Any additional comments about the infringement not exceeding 2000 characters + + company: Text not exceeding 100 characters + + country: Text not exceeding 255 characters + + destination_ips: A list of IP addresses separated by ‘ ’ (new line character). The list of + destination IPs should not exceed 30 IP addresses. Each one of the IP addresses + ought to be unique + + justification: A detailed description of the infringement, including any necessary access + details and the exact steps needed to view the content, not exceeding 5000 + characters + + name: Text not exceeding 255 characters + + ncsei_subject_representation: If the submitter is the target of NCSEI in the URLs of the abuse report + + original_work: Text not exceeding 255 characters + + ports_protocols: A comma separated list of ports and protocols e.g. 80/TCP, 22/UDP. The total + size of the field should not exceed 2000 characters. Each individual + port/protocol should not exceed 100 characters. The list should not have more + than 30 unique ports and protocols. + + signature: Required for DMCA reports, should be same as Name. An affirmation that all + information in the report is true and accurate while agreeing to the policies of + Cloudflare's abuse reports + + source_ips: A list of IP addresses separated by ‘ ’ (new line character). The list of source + IPs should not exceed 30 IP addresses. Each one of the IP addresses ought to be + unique + + state: Text not exceeding 255 characters + + tele: Text not exceeding 20 characters + + title: Text not exceeding 255 characters + + trademark_number: Text not exceeding 1000 characters + + trademark_office: Text not exceeding 1000 characters + + trademark_symbol: Text not exceeding 1000 characters + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not report_type: + raise ValueError(f"Expected a non-empty value for `report_type` but received {report_type!r}") + return await self._post( + f"/accounts/{account_id}/v1/abuse-reports/{report_type}", + body=await async_maybe_transform( + { + "act": act, + "email": email, + "email2": email2, + "host_notification": host_notification, + "ncmec_notification": ncmec_notification, + "owner_notification": owner_notification, + "urls": urls, + "address1": address1, + "agent_name": agent_name, + "agree": agree, + "city": city, + "comments": comments, + "company": company, + "country": country, + "destination_ips": destination_ips, + "justification": justification, + "name": name, + "ncsei_subject_representation": ncsei_subject_representation, + "original_work": original_work, + "ports_protocols": ports_protocols, + "signature": signature, + "source_ips": source_ips, + "state": state, + "tele": tele, + "title": title, + "trademark_number": trademark_number, + "trademark_office": trademark_office, + "trademark_symbol": trademark_symbol, + }, + abuse_report_create_params.AbuseReportCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[AbuseReportCreateResponse]._unwrapper, + ), + cast_to=cast(Type[str], ResultWrapper[str]), + ) + + +class AbuseReportsResourceWithRawResponse: + def __init__(self, abuse_reports: AbuseReportsResource) -> None: + self._abuse_reports = abuse_reports + + self.create = to_raw_response_wrapper( + abuse_reports.create, + ) + + +class AsyncAbuseReportsResourceWithRawResponse: + def __init__(self, abuse_reports: AsyncAbuseReportsResource) -> None: + self._abuse_reports = abuse_reports + + self.create = async_to_raw_response_wrapper( + abuse_reports.create, + ) + + +class AbuseReportsResourceWithStreamingResponse: + def __init__(self, abuse_reports: AbuseReportsResource) -> None: + self._abuse_reports = abuse_reports + + self.create = to_streamed_response_wrapper( + abuse_reports.create, + ) + + +class AsyncAbuseReportsResourceWithStreamingResponse: + def __init__(self, abuse_reports: AsyncAbuseReportsResource) -> None: + self._abuse_reports = abuse_reports + + self.create = async_to_streamed_response_wrapper( + abuse_reports.create, + ) diff --git a/src/cloudflare/resources/zero_trust/devices/__init__.py b/src/cloudflare/resources/zero_trust/devices/__init__.py index 3002bba6155..5b55d59405f 100644 --- a/src/cloudflare/resources/zero_trust/devices/__init__.py +++ b/src/cloudflare/resources/zero_trust/devices/__init__.py @@ -64,6 +64,14 @@ DEXTestsResourceWithStreamingResponse, AsyncDEXTestsResourceWithStreamingResponse, ) +from .fleet_status import ( + FleetStatusResource, + AsyncFleetStatusResource, + FleetStatusResourceWithRawResponse, + AsyncFleetStatusResourceWithRawResponse, + FleetStatusResourceWithStreamingResponse, + AsyncFleetStatusResourceWithStreamingResponse, +) from .override_codes import ( OverrideCodesResource, AsyncOverrideCodesResource, @@ -86,6 +94,12 @@ "AsyncNetworksResourceWithRawResponse", "NetworksResourceWithStreamingResponse", "AsyncNetworksResourceWithStreamingResponse", + "FleetStatusResource", + "AsyncFleetStatusResource", + "FleetStatusResourceWithRawResponse", + "AsyncFleetStatusResourceWithRawResponse", + "FleetStatusResourceWithStreamingResponse", + "AsyncFleetStatusResourceWithStreamingResponse", "PoliciesResource", "AsyncPoliciesResource", "PoliciesResourceWithRawResponse", diff --git a/src/cloudflare/resources/zero_trust/devices/devices.py b/src/cloudflare/resources/zero_trust/devices/devices.py index 73e50bc540a..c8da8b5a201 100644 --- a/src/cloudflare/resources/zero_trust/devices/devices.py +++ b/src/cloudflare/resources/zero_trust/devices/devices.py @@ -72,6 +72,14 @@ async_to_streamed_response_wrapper, ) from ...._wrappers import ResultWrapper +from .fleet_status import ( + FleetStatusResource, + AsyncFleetStatusResource, + FleetStatusResourceWithRawResponse, + AsyncFleetStatusResourceWithRawResponse, + FleetStatusResourceWithStreamingResponse, + AsyncFleetStatusResourceWithStreamingResponse, +) from ....pagination import SyncSinglePage, AsyncSinglePage from .override_codes import ( OverrideCodesResource, @@ -99,6 +107,10 @@ def dex_tests(self) -> DEXTestsResource: def networks(self) -> NetworksResource: return NetworksResource(self._client) + @cached_property + def fleet_status(self) -> FleetStatusResource: + return FleetStatusResource(self._client) + @cached_property def policies(self) -> PoliciesResource: return PoliciesResource(self._client) @@ -233,6 +245,10 @@ def dex_tests(self) -> AsyncDEXTestsResource: def networks(self) -> AsyncNetworksResource: return AsyncNetworksResource(self._client) + @cached_property + def fleet_status(self) -> AsyncFleetStatusResource: + return AsyncFleetStatusResource(self._client) + @cached_property def policies(self) -> AsyncPoliciesResource: return AsyncPoliciesResource(self._client) @@ -377,6 +393,10 @@ def dex_tests(self) -> DEXTestsResourceWithRawResponse: def networks(self) -> NetworksResourceWithRawResponse: return NetworksResourceWithRawResponse(self._devices.networks) + @cached_property + def fleet_status(self) -> FleetStatusResourceWithRawResponse: + return FleetStatusResourceWithRawResponse(self._devices.fleet_status) + @cached_property def policies(self) -> PoliciesResourceWithRawResponse: return PoliciesResourceWithRawResponse(self._devices.policies) @@ -421,6 +441,10 @@ def dex_tests(self) -> AsyncDEXTestsResourceWithRawResponse: def networks(self) -> AsyncNetworksResourceWithRawResponse: return AsyncNetworksResourceWithRawResponse(self._devices.networks) + @cached_property + def fleet_status(self) -> AsyncFleetStatusResourceWithRawResponse: + return AsyncFleetStatusResourceWithRawResponse(self._devices.fleet_status) + @cached_property def policies(self) -> AsyncPoliciesResourceWithRawResponse: return AsyncPoliciesResourceWithRawResponse(self._devices.policies) @@ -465,6 +489,10 @@ def dex_tests(self) -> DEXTestsResourceWithStreamingResponse: def networks(self) -> NetworksResourceWithStreamingResponse: return NetworksResourceWithStreamingResponse(self._devices.networks) + @cached_property + def fleet_status(self) -> FleetStatusResourceWithStreamingResponse: + return FleetStatusResourceWithStreamingResponse(self._devices.fleet_status) + @cached_property def policies(self) -> PoliciesResourceWithStreamingResponse: return PoliciesResourceWithStreamingResponse(self._devices.policies) @@ -509,6 +537,10 @@ def dex_tests(self) -> AsyncDEXTestsResourceWithStreamingResponse: def networks(self) -> AsyncNetworksResourceWithStreamingResponse: return AsyncNetworksResourceWithStreamingResponse(self._devices.networks) + @cached_property + def fleet_status(self) -> AsyncFleetStatusResourceWithStreamingResponse: + return AsyncFleetStatusResourceWithStreamingResponse(self._devices.fleet_status) + @cached_property def policies(self) -> AsyncPoliciesResourceWithStreamingResponse: return AsyncPoliciesResourceWithStreamingResponse(self._devices.policies) diff --git a/src/cloudflare/resources/zero_trust/devices/fleet_status.py b/src/cloudflare/resources/zero_trust/devices/fleet_status.py new file mode 100644 index 00000000000..57b2c298c03 --- /dev/null +++ b/src/cloudflare/resources/zero_trust/devices/fleet_status.py @@ -0,0 +1,220 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven +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.zero_trust.devices import fleet_status_get_params +from ....types.zero_trust.devices.fleet_status_get_response import FleetStatusGetResponse + +__all__ = ["FleetStatusResource", "AsyncFleetStatusResource"] + + +class FleetStatusResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> FleetStatusResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return FleetStatusResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FleetStatusResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return FleetStatusResourceWithStreamingResponse(self) + + def get( + self, + device_id: str, + *, + account_id: str, + since_minutes: float, + colo: str | NotGiven = NOT_GIVEN, + time_now: str | NotGiven = NOT_GIVEN, + # 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, + ) -> FleetStatusGetResponse: + """ + Get the live status of a latest device given device_id from the device_state + table + + Args: + device_id: Device-specific ID, given as UUID v4 + + since_minutes: Number of minutes before current time + + colo: List of data centers to filter results + + time_now: Number of minutes before current time + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + return self._get( + f"/accounts/{account_id}/dex/devices/{device_id}/fleet-status/live", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "since_minutes": since_minutes, + "colo": colo, + "time_now": time_now, + }, + fleet_status_get_params.FleetStatusGetParams, + ), + ), + cast_to=FleetStatusGetResponse, + ) + + +class AsyncFleetStatusResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncFleetStatusResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncFleetStatusResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFleetStatusResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncFleetStatusResourceWithStreamingResponse(self) + + async def get( + self, + device_id: str, + *, + account_id: str, + since_minutes: float, + colo: str | NotGiven = NOT_GIVEN, + time_now: str | NotGiven = NOT_GIVEN, + # 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, + ) -> FleetStatusGetResponse: + """ + Get the live status of a latest device given device_id from the device_state + table + + Args: + device_id: Device-specific ID, given as UUID v4 + + since_minutes: Number of minutes before current time + + colo: List of data centers to filter results + + time_now: Number of minutes before current time + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + return await self._get( + f"/accounts/{account_id}/dex/devices/{device_id}/fleet-status/live", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "since_minutes": since_minutes, + "colo": colo, + "time_now": time_now, + }, + fleet_status_get_params.FleetStatusGetParams, + ), + ), + cast_to=FleetStatusGetResponse, + ) + + +class FleetStatusResourceWithRawResponse: + def __init__(self, fleet_status: FleetStatusResource) -> None: + self._fleet_status = fleet_status + + self.get = to_raw_response_wrapper( + fleet_status.get, + ) + + +class AsyncFleetStatusResourceWithRawResponse: + def __init__(self, fleet_status: AsyncFleetStatusResource) -> None: + self._fleet_status = fleet_status + + self.get = async_to_raw_response_wrapper( + fleet_status.get, + ) + + +class FleetStatusResourceWithStreamingResponse: + def __init__(self, fleet_status: FleetStatusResource) -> None: + self._fleet_status = fleet_status + + self.get = to_streamed_response_wrapper( + fleet_status.get, + ) + + +class AsyncFleetStatusResourceWithStreamingResponse: + def __init__(self, fleet_status: AsyncFleetStatusResource) -> None: + self._fleet_status = fleet_status + + self.get = async_to_streamed_response_wrapper( + fleet_status.get, + ) diff --git a/src/cloudflare/resources/zero_trust/dex/__init__.py b/src/cloudflare/resources/zero_trust/dex/__init__.py index b79e8e9ec69..defe96da107 100644 --- a/src/cloudflare/resources/zero_trust/dex/__init__.py +++ b/src/cloudflare/resources/zero_trust/dex/__init__.py @@ -24,6 +24,14 @@ TestsResourceWithStreamingResponse, AsyncTestsResourceWithStreamingResponse, ) +from .commands import ( + CommandsResource, + AsyncCommandsResource, + CommandsResourceWithRawResponse, + AsyncCommandsResourceWithRawResponse, + CommandsResourceWithStreamingResponse, + AsyncCommandsResourceWithStreamingResponse, +) from .http_tests import ( HTTPTestsResource, AsyncHTTPTestsResource, @@ -58,6 +66,12 @@ ) __all__ = [ + "CommandsResource", + "AsyncCommandsResource", + "CommandsResourceWithRawResponse", + "AsyncCommandsResourceWithRawResponse", + "CommandsResourceWithStreamingResponse", + "AsyncCommandsResourceWithStreamingResponse", "ColosResource", "AsyncColosResource", "ColosResourceWithRawResponse", diff --git a/src/cloudflare/resources/zero_trust/dex/commands/__init__.py b/src/cloudflare/resources/zero_trust/dex/commands/__init__.py new file mode 100644 index 00000000000..4566edefe96 --- /dev/null +++ b/src/cloudflare/resources/zero_trust/dex/commands/__init__.py @@ -0,0 +1,47 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .quota import ( + QuotaResource, + AsyncQuotaResource, + QuotaResourceWithRawResponse, + AsyncQuotaResourceWithRawResponse, + QuotaResourceWithStreamingResponse, + AsyncQuotaResourceWithStreamingResponse, +) +from .commands import ( + CommandsResource, + AsyncCommandsResource, + CommandsResourceWithRawResponse, + AsyncCommandsResourceWithRawResponse, + CommandsResourceWithStreamingResponse, + AsyncCommandsResourceWithStreamingResponse, +) +from .downloads import ( + DownloadsResource, + AsyncDownloadsResource, + DownloadsResourceWithRawResponse, + AsyncDownloadsResourceWithRawResponse, + DownloadsResourceWithStreamingResponse, + AsyncDownloadsResourceWithStreamingResponse, +) + +__all__ = [ + "DownloadsResource", + "AsyncDownloadsResource", + "DownloadsResourceWithRawResponse", + "AsyncDownloadsResourceWithRawResponse", + "DownloadsResourceWithStreamingResponse", + "AsyncDownloadsResourceWithStreamingResponse", + "QuotaResource", + "AsyncQuotaResource", + "QuotaResourceWithRawResponse", + "AsyncQuotaResourceWithRawResponse", + "QuotaResourceWithStreamingResponse", + "AsyncQuotaResourceWithStreamingResponse", + "CommandsResource", + "AsyncCommandsResource", + "CommandsResourceWithRawResponse", + "AsyncCommandsResourceWithRawResponse", + "CommandsResourceWithStreamingResponse", + "AsyncCommandsResourceWithStreamingResponse", +] diff --git a/src/cloudflare/resources/zero_trust/dex/commands/commands.py b/src/cloudflare/resources/zero_trust/dex/commands/commands.py new file mode 100644 index 00000000000..f0041c4f8c9 --- /dev/null +++ b/src/cloudflare/resources/zero_trust/dex/commands/commands.py @@ -0,0 +1,417 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Type, Union, Iterable, Optional, cast +from datetime import datetime +from typing_extensions import Literal + +import httpx + +from .quota import ( + QuotaResource, + AsyncQuotaResource, + QuotaResourceWithRawResponse, + AsyncQuotaResourceWithRawResponse, + QuotaResourceWithStreamingResponse, + AsyncQuotaResourceWithStreamingResponse, +) +from .downloads import ( + DownloadsResource, + AsyncDownloadsResource, + DownloadsResourceWithRawResponse, + AsyncDownloadsResourceWithRawResponse, + DownloadsResourceWithStreamingResponse, + AsyncDownloadsResourceWithStreamingResponse, +) +from ....._types import NOT_GIVEN, Body, Query, Headers, NotGiven +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 ....._wrappers import ResultWrapper +from .....pagination import SyncV4PagePagination, AsyncV4PagePagination +from ....._base_client import AsyncPaginator, make_request_options +from .....types.zero_trust.dex import command_list_params, command_create_params +from .....types.zero_trust.dex.command_list_response import CommandListResponse +from .....types.zero_trust.dex.command_create_response import CommandCreateResponse + +__all__ = ["CommandsResource", "AsyncCommandsResource"] + + +class CommandsResource(SyncAPIResource): + @cached_property + def downloads(self) -> DownloadsResource: + return DownloadsResource(self._client) + + @cached_property + def quota(self) -> QuotaResource: + return QuotaResource(self._client) + + @cached_property + def with_raw_response(self) -> CommandsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return CommandsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CommandsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return CommandsResourceWithStreamingResponse(self) + + def create( + self, + *, + account_id: str, + commands: Iterable[command_create_params.Command], + # 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, + ) -> Optional[CommandCreateResponse]: + """ + Initiate commands for up to 10 devices per account + + Args: + commands: List of device-level commands to execute + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._post( + f"/accounts/{account_id}/dex/commands", + body=maybe_transform({"commands": commands}, command_create_params.CommandCreateParams), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[CommandCreateResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[CommandCreateResponse]], ResultWrapper[CommandCreateResponse]), + ) + + def list( + self, + *, + account_id: str, + page: float, + per_page: float, + command_type: str | NotGiven = NOT_GIVEN, + device_id: str | NotGiven = NOT_GIVEN, + from_: Union[str, datetime] | NotGiven = NOT_GIVEN, + status: Literal["PENDING_EXEC", "PENDING_UPLOAD", "SUCCESS", "FAILED"] | NotGiven = NOT_GIVEN, + to: Union[str, datetime] | NotGiven = NOT_GIVEN, + user_email: str | NotGiven = NOT_GIVEN, + # 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, + ) -> SyncV4PagePagination[Optional[CommandListResponse]]: + """ + Retrieves a paginated list of commands issued to devices under the specified + account, optionally filtered by time range, device, or other parameters + + Args: + page: Page number for pagination + + per_page: Number of results per page + + command_type: Optionally filter executed commands by command type + + device_id: Unique identifier for a device + + from_: Start time for the query in ISO (RFC3339 - ISO 8601) format + + status: Optionally filter executed commands by status + + to: End time for the query in ISO (RFC3339 - ISO 8601) format + + user_email: Email tied to the device + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._get_api_list( + f"/accounts/{account_id}/dex/commands", + page=SyncV4PagePagination[Optional[CommandListResponse]], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "page": page, + "per_page": per_page, + "command_type": command_type, + "device_id": device_id, + "from_": from_, + "status": status, + "to": to, + "user_email": user_email, + }, + command_list_params.CommandListParams, + ), + ), + model=CommandListResponse, + ) + + +class AsyncCommandsResource(AsyncAPIResource): + @cached_property + def downloads(self) -> AsyncDownloadsResource: + return AsyncDownloadsResource(self._client) + + @cached_property + def quota(self) -> AsyncQuotaResource: + return AsyncQuotaResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncCommandsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncCommandsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCommandsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncCommandsResourceWithStreamingResponse(self) + + async def create( + self, + *, + account_id: str, + commands: Iterable[command_create_params.Command], + # 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, + ) -> Optional[CommandCreateResponse]: + """ + Initiate commands for up to 10 devices per account + + Args: + commands: List of device-level commands to execute + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return await self._post( + f"/accounts/{account_id}/dex/commands", + body=await async_maybe_transform({"commands": commands}, command_create_params.CommandCreateParams), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[CommandCreateResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[CommandCreateResponse]], ResultWrapper[CommandCreateResponse]), + ) + + def list( + self, + *, + account_id: str, + page: float, + per_page: float, + command_type: str | NotGiven = NOT_GIVEN, + device_id: str | NotGiven = NOT_GIVEN, + from_: Union[str, datetime] | NotGiven = NOT_GIVEN, + status: Literal["PENDING_EXEC", "PENDING_UPLOAD", "SUCCESS", "FAILED"] | NotGiven = NOT_GIVEN, + to: Union[str, datetime] | NotGiven = NOT_GIVEN, + user_email: str | NotGiven = NOT_GIVEN, + # 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[Optional[CommandListResponse], AsyncV4PagePagination[Optional[CommandListResponse]]]: + """ + Retrieves a paginated list of commands issued to devices under the specified + account, optionally filtered by time range, device, or other parameters + + Args: + page: Page number for pagination + + per_page: Number of results per page + + command_type: Optionally filter executed commands by command type + + device_id: Unique identifier for a device + + from_: Start time for the query in ISO (RFC3339 - ISO 8601) format + + status: Optionally filter executed commands by status + + to: End time for the query in ISO (RFC3339 - ISO 8601) format + + user_email: Email tied to the device + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._get_api_list( + f"/accounts/{account_id}/dex/commands", + page=AsyncV4PagePagination[Optional[CommandListResponse]], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "page": page, + "per_page": per_page, + "command_type": command_type, + "device_id": device_id, + "from_": from_, + "status": status, + "to": to, + "user_email": user_email, + }, + command_list_params.CommandListParams, + ), + ), + model=CommandListResponse, + ) + + +class CommandsResourceWithRawResponse: + def __init__(self, commands: CommandsResource) -> None: + self._commands = commands + + self.create = to_raw_response_wrapper( + commands.create, + ) + self.list = to_raw_response_wrapper( + commands.list, + ) + + @cached_property + def downloads(self) -> DownloadsResourceWithRawResponse: + return DownloadsResourceWithRawResponse(self._commands.downloads) + + @cached_property + def quota(self) -> QuotaResourceWithRawResponse: + return QuotaResourceWithRawResponse(self._commands.quota) + + +class AsyncCommandsResourceWithRawResponse: + def __init__(self, commands: AsyncCommandsResource) -> None: + self._commands = commands + + self.create = async_to_raw_response_wrapper( + commands.create, + ) + self.list = async_to_raw_response_wrapper( + commands.list, + ) + + @cached_property + def downloads(self) -> AsyncDownloadsResourceWithRawResponse: + return AsyncDownloadsResourceWithRawResponse(self._commands.downloads) + + @cached_property + def quota(self) -> AsyncQuotaResourceWithRawResponse: + return AsyncQuotaResourceWithRawResponse(self._commands.quota) + + +class CommandsResourceWithStreamingResponse: + def __init__(self, commands: CommandsResource) -> None: + self._commands = commands + + self.create = to_streamed_response_wrapper( + commands.create, + ) + self.list = to_streamed_response_wrapper( + commands.list, + ) + + @cached_property + def downloads(self) -> DownloadsResourceWithStreamingResponse: + return DownloadsResourceWithStreamingResponse(self._commands.downloads) + + @cached_property + def quota(self) -> QuotaResourceWithStreamingResponse: + return QuotaResourceWithStreamingResponse(self._commands.quota) + + +class AsyncCommandsResourceWithStreamingResponse: + def __init__(self, commands: AsyncCommandsResource) -> None: + self._commands = commands + + self.create = async_to_streamed_response_wrapper( + commands.create, + ) + self.list = async_to_streamed_response_wrapper( + commands.list, + ) + + @cached_property + def downloads(self) -> AsyncDownloadsResourceWithStreamingResponse: + return AsyncDownloadsResourceWithStreamingResponse(self._commands.downloads) + + @cached_property + def quota(self) -> AsyncQuotaResourceWithStreamingResponse: + return AsyncQuotaResourceWithStreamingResponse(self._commands.quota) diff --git a/src/cloudflare/resources/zero_trust/dex/commands/downloads.py b/src/cloudflare/resources/zero_trust/dex/commands/downloads.py new file mode 100644 index 00000000000..57b8e0320aa --- /dev/null +++ b/src/cloudflare/resources/zero_trust/dex/commands/downloads.py @@ -0,0 +1,190 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ....._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ....._compat import cached_property +from ....._resource import SyncAPIResource, AsyncAPIResource +from ....._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, + to_custom_raw_response_wrapper, + to_custom_streamed_response_wrapper, + async_to_custom_raw_response_wrapper, + async_to_custom_streamed_response_wrapper, +) +from ....._base_client import make_request_options + +__all__ = ["DownloadsResource", "AsyncDownloadsResource"] + + +class DownloadsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> DownloadsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return DownloadsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DownloadsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return DownloadsResourceWithStreamingResponse(self) + + def get( + self, + filename: str, + *, + account_id: str, + command_id: 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, + ) -> BinaryAPIResponse: + """Downloads artifacts for an executed command. + + Bulk downloads are not supported + + Args: + command_id: Unique identifier for a command + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not command_id: + raise ValueError(f"Expected a non-empty value for `command_id` but received {command_id!r}") + if not filename: + raise ValueError(f"Expected a non-empty value for `filename` but received {filename!r}") + extra_headers = {"Accept": "application/zip", **(extra_headers or {})} + return self._get( + f"/accounts/{account_id}/dex/commands/{command_id}/downloads/{filename}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BinaryAPIResponse, + ) + + +class AsyncDownloadsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncDownloadsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncDownloadsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDownloadsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncDownloadsResourceWithStreamingResponse(self) + + async def get( + self, + filename: str, + *, + account_id: str, + command_id: 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, + ) -> AsyncBinaryAPIResponse: + """Downloads artifacts for an executed command. + + Bulk downloads are not supported + + Args: + command_id: Unique identifier for a command + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + if not command_id: + raise ValueError(f"Expected a non-empty value for `command_id` but received {command_id!r}") + if not filename: + raise ValueError(f"Expected a non-empty value for `filename` but received {filename!r}") + extra_headers = {"Accept": "application/zip", **(extra_headers or {})} + return await self._get( + f"/accounts/{account_id}/dex/commands/{command_id}/downloads/{filename}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AsyncBinaryAPIResponse, + ) + + +class DownloadsResourceWithRawResponse: + def __init__(self, downloads: DownloadsResource) -> None: + self._downloads = downloads + + self.get = to_custom_raw_response_wrapper( + downloads.get, + BinaryAPIResponse, + ) + + +class AsyncDownloadsResourceWithRawResponse: + def __init__(self, downloads: AsyncDownloadsResource) -> None: + self._downloads = downloads + + self.get = async_to_custom_raw_response_wrapper( + downloads.get, + AsyncBinaryAPIResponse, + ) + + +class DownloadsResourceWithStreamingResponse: + def __init__(self, downloads: DownloadsResource) -> None: + self._downloads = downloads + + self.get = to_custom_streamed_response_wrapper( + downloads.get, + StreamedBinaryAPIResponse, + ) + + +class AsyncDownloadsResourceWithStreamingResponse: + def __init__(self, downloads: AsyncDownloadsResource) -> None: + self._downloads = downloads + + self.get = async_to_custom_streamed_response_wrapper( + downloads.get, + AsyncStreamedBinaryAPIResponse, + ) diff --git a/src/cloudflare/resources/zero_trust/dex/commands/quota.py b/src/cloudflare/resources/zero_trust/dex/commands/quota.py new file mode 100644 index 00000000000..8a0ba05b4b3 --- /dev/null +++ b/src/cloudflare/resources/zero_trust/dex/commands/quota.py @@ -0,0 +1,176 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Type, Optional, cast + +import httpx + +from ....._types import NOT_GIVEN, Body, Query, Headers, NotGiven +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 ....._wrappers import ResultWrapper +from ....._base_client import make_request_options +from .....types.zero_trust.dex.commands.quota_get_response import QuotaGetResponse + +__all__ = ["QuotaResource", "AsyncQuotaResource"] + + +class QuotaResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> QuotaResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return QuotaResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> QuotaResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return QuotaResourceWithStreamingResponse(self) + + def get( + self, + *, + account_id: 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, + ) -> Optional[QuotaGetResponse]: + """ + Retrieves the current quota usage and limits for device commands within a + specific account, including the time when the quota will reset + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return self._get( + f"/accounts/{account_id}/dex/commands/quota", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[QuotaGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[QuotaGetResponse]], ResultWrapper[QuotaGetResponse]), + ) + + +class AsyncQuotaResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncQuotaResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers + """ + return AsyncQuotaResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncQuotaResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response + """ + return AsyncQuotaResourceWithStreamingResponse(self) + + async def get( + self, + *, + account_id: 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, + ) -> Optional[QuotaGetResponse]: + """ + Retrieves the current quota usage and limits for device commands within a + specific account, including the time when the quota will reset + + 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 not account_id: + raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") + return await self._get( + f"/accounts/{account_id}/dex/commands/quota", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[Optional[QuotaGetResponse]]._unwrapper, + ), + cast_to=cast(Type[Optional[QuotaGetResponse]], ResultWrapper[QuotaGetResponse]), + ) + + +class QuotaResourceWithRawResponse: + def __init__(self, quota: QuotaResource) -> None: + self._quota = quota + + self.get = to_raw_response_wrapper( + quota.get, + ) + + +class AsyncQuotaResourceWithRawResponse: + def __init__(self, quota: AsyncQuotaResource) -> None: + self._quota = quota + + self.get = async_to_raw_response_wrapper( + quota.get, + ) + + +class QuotaResourceWithStreamingResponse: + def __init__(self, quota: QuotaResource) -> None: + self._quota = quota + + self.get = to_streamed_response_wrapper( + quota.get, + ) + + +class AsyncQuotaResourceWithStreamingResponse: + def __init__(self, quota: AsyncQuotaResource) -> None: + self._quota = quota + + self.get = async_to_streamed_response_wrapper( + quota.get, + ) diff --git a/src/cloudflare/resources/zero_trust/dex/dex.py b/src/cloudflare/resources/zero_trust/dex/dex.py index 654a940a2a3..c8f838301e9 100644 --- a/src/cloudflare/resources/zero_trust/dex/dex.py +++ b/src/cloudflare/resources/zero_trust/dex/dex.py @@ -18,6 +18,14 @@ TestsResourceWithStreamingResponse, AsyncTestsResourceWithStreamingResponse, ) +from .commands import ( + CommandsResource, + AsyncCommandsResource, + CommandsResourceWithRawResponse, + AsyncCommandsResourceWithRawResponse, + CommandsResourceWithStreamingResponse, + AsyncCommandsResourceWithStreamingResponse, +) from ...._compat import cached_property from .http_tests import ( HTTPTestsResource, @@ -45,6 +53,7 @@ TracerouteTestsResourceWithStreamingResponse, AsyncTracerouteTestsResourceWithStreamingResponse, ) +from .commands.commands import CommandsResource, AsyncCommandsResource from .http_tests.http_tests import HTTPTestsResource, AsyncHTTPTestsResource from .traceroute_test_results import ( TracerouteTestResultsResource, @@ -64,6 +73,10 @@ class DEXResource(SyncAPIResource): + @cached_property + def commands(self) -> CommandsResource: + return CommandsResource(self._client) + @cached_property def colos(self) -> ColosResource: return ColosResource(self._client) @@ -109,6 +122,10 @@ def with_streaming_response(self) -> DEXResourceWithStreamingResponse: class AsyncDEXResource(AsyncAPIResource): + @cached_property + def commands(self) -> AsyncCommandsResource: + return AsyncCommandsResource(self._client) + @cached_property def colos(self) -> AsyncColosResource: return AsyncColosResource(self._client) @@ -157,6 +174,10 @@ class DEXResourceWithRawResponse: def __init__(self, dex: DEXResource) -> None: self._dex = dex + @cached_property + def commands(self) -> CommandsResourceWithRawResponse: + return CommandsResourceWithRawResponse(self._dex.commands) + @cached_property def colos(self) -> ColosResourceWithRawResponse: return ColosResourceWithRawResponse(self._dex.colos) @@ -186,6 +207,10 @@ class AsyncDEXResourceWithRawResponse: def __init__(self, dex: AsyncDEXResource) -> None: self._dex = dex + @cached_property + def commands(self) -> AsyncCommandsResourceWithRawResponse: + return AsyncCommandsResourceWithRawResponse(self._dex.commands) + @cached_property def colos(self) -> AsyncColosResourceWithRawResponse: return AsyncColosResourceWithRawResponse(self._dex.colos) @@ -215,6 +240,10 @@ class DEXResourceWithStreamingResponse: def __init__(self, dex: DEXResource) -> None: self._dex = dex + @cached_property + def commands(self) -> CommandsResourceWithStreamingResponse: + return CommandsResourceWithStreamingResponse(self._dex.commands) + @cached_property def colos(self) -> ColosResourceWithStreamingResponse: return ColosResourceWithStreamingResponse(self._dex.colos) @@ -244,6 +273,10 @@ class AsyncDEXResourceWithStreamingResponse: def __init__(self, dex: AsyncDEXResource) -> None: self._dex = dex + @cached_property + def commands(self) -> AsyncCommandsResourceWithStreamingResponse: + return AsyncCommandsResourceWithStreamingResponse(self._dex.commands) + @cached_property def colos(self) -> AsyncColosResourceWithStreamingResponse: return AsyncColosResourceWithStreamingResponse(self._dex.colos) diff --git a/src/cloudflare/resources/zones/holds.py b/src/cloudflare/resources/zones/holds.py index 38fbee1a43f..50ff188a172 100644 --- a/src/cloudflare/resources/zones/holds.py +++ b/src/cloudflare/resources/zones/holds.py @@ -20,7 +20,7 @@ async_to_streamed_response_wrapper, ) from ..._wrappers import ResultWrapper -from ...types.zones import hold_create_params, hold_delete_params +from ...types.zones import hold_edit_params, hold_create_params, hold_delete_params from ..._base_client import make_request_options from ...types.zones.zone_hold import ZoneHold @@ -140,6 +140,66 @@ def delete( cast_to=cast(Type[ZoneHold], ResultWrapper[ZoneHold]), ) + def edit( + self, + *, + zone_id: str, + hold_after: str | NotGiven = NOT_GIVEN, + include_subdomains: bool | NotGiven = NOT_GIVEN, + # 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, + ) -> ZoneHold: + """ + Update the `hold_after` and/or `include_subdomains` values on an existing zone + hold. The hold is enabled if the `hold_after` date-time value is in the past. + + Args: + zone_id: Identifier + + hold_after: If `hold_after` is provided and future-dated, the hold will be temporarily + disabled, then automatically re-enabled by the system at the time specified in + this RFC3339-formatted timestamp. A past-dated `hold_after` value will have no + effect on an existing, enabled hold. Providing an empty string will set its + value to the current time. + + include_subdomains: If `true`, the zone hold will extend to block any subdomain of the given zone, + as well as SSL4SaaS Custom Hostnames. For example, a zone hold on a zone with + the hostname 'example.com' and include_subdomains=true will block 'example.com', + 'staging.example.com', 'api.staging.example.com', etc. + + 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 not zone_id: + raise ValueError(f"Expected a non-empty value for `zone_id` but received {zone_id!r}") + return self._patch( + f"/zones/{zone_id}/hold", + body=maybe_transform( + { + "hold_after": hold_after, + "include_subdomains": include_subdomains, + }, + hold_edit_params.HoldEditParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[ZoneHold]._unwrapper, + ), + cast_to=cast(Type[ZoneHold], ResultWrapper[ZoneHold]), + ) + def get( self, *, @@ -296,6 +356,66 @@ async def delete( cast_to=cast(Type[ZoneHold], ResultWrapper[ZoneHold]), ) + async def edit( + self, + *, + zone_id: str, + hold_after: str | NotGiven = NOT_GIVEN, + include_subdomains: bool | NotGiven = NOT_GIVEN, + # 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, + ) -> ZoneHold: + """ + Update the `hold_after` and/or `include_subdomains` values on an existing zone + hold. The hold is enabled if the `hold_after` date-time value is in the past. + + Args: + zone_id: Identifier + + hold_after: If `hold_after` is provided and future-dated, the hold will be temporarily + disabled, then automatically re-enabled by the system at the time specified in + this RFC3339-formatted timestamp. A past-dated `hold_after` value will have no + effect on an existing, enabled hold. Providing an empty string will set its + value to the current time. + + include_subdomains: If `true`, the zone hold will extend to block any subdomain of the given zone, + as well as SSL4SaaS Custom Hostnames. For example, a zone hold on a zone with + the hostname 'example.com' and include_subdomains=true will block 'example.com', + 'staging.example.com', 'api.staging.example.com', etc. + + 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 not zone_id: + raise ValueError(f"Expected a non-empty value for `zone_id` but received {zone_id!r}") + return await self._patch( + f"/zones/{zone_id}/hold", + body=await async_maybe_transform( + { + "hold_after": hold_after, + "include_subdomains": include_subdomains, + }, + hold_edit_params.HoldEditParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + post_parser=ResultWrapper[ZoneHold]._unwrapper, + ), + cast_to=cast(Type[ZoneHold], ResultWrapper[ZoneHold]), + ) + async def get( self, *, @@ -347,6 +467,9 @@ def __init__(self, holds: HoldsResource) -> None: self.delete = to_raw_response_wrapper( holds.delete, ) + self.edit = to_raw_response_wrapper( + holds.edit, + ) self.get = to_raw_response_wrapper( holds.get, ) @@ -362,6 +485,9 @@ def __init__(self, holds: AsyncHoldsResource) -> None: self.delete = async_to_raw_response_wrapper( holds.delete, ) + self.edit = async_to_raw_response_wrapper( + holds.edit, + ) self.get = async_to_raw_response_wrapper( holds.get, ) @@ -377,6 +503,9 @@ def __init__(self, holds: HoldsResource) -> None: self.delete = to_streamed_response_wrapper( holds.delete, ) + self.edit = to_streamed_response_wrapper( + holds.edit, + ) self.get = to_streamed_response_wrapper( holds.get, ) @@ -392,6 +521,9 @@ def __init__(self, holds: AsyncHoldsResource) -> None: self.delete = async_to_streamed_response_wrapper( holds.delete, ) + self.edit = async_to_streamed_response_wrapper( + holds.edit, + ) self.get = async_to_streamed_response_wrapper( holds.get, ) diff --git a/src/cloudflare/types/abuse_reports/__init__.py b/src/cloudflare/types/abuse_reports/__init__.py new file mode 100644 index 00000000000..c17465cb40c --- /dev/null +++ b/src/cloudflare/types/abuse_reports/__init__.py @@ -0,0 +1,6 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .abuse_report_create_params import AbuseReportCreateParams as AbuseReportCreateParams +from .abuse_report_create_response import AbuseReportCreateResponse as AbuseReportCreateResponse diff --git a/src/cloudflare/types/abuse_reports/abuse_report_create_params.py b/src/cloudflare/types/abuse_reports/abuse_report_create_params.py new file mode 100644 index 00000000000..ff19f93f7c5 --- /dev/null +++ b/src/cloudflare/types/abuse_reports/abuse_report_create_params.py @@ -0,0 +1,140 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["AbuseReportCreateParams"] + + +class AbuseReportCreateParams(TypedDict, total=False): + account_id: Required[str] + + act: Required[ + Literal[ + "abuse_dmca", + "abuse_trademark", + "abuse_general", + "abuse_phishing", + "abuse_children", + "abuse_threat", + "abuse_registrar_whois", + "abuse_ncsei", + ] + ] + """The abuse report type""" + + email: Required[str] + """A valid email of the abuse reporter""" + + email2: Required[str] + """Should match the value provided in `email`""" + + host_notification: Required[Literal["send", "send-anon", "none"]] + """Notification type based on the abuse type. + + NOTE: Copyright (DMCA) and Trademark reports cannot be anonymous. + """ + + ncmec_notification: Required[Literal["send", "send-anon", "none"]] + """Notification type based on the abuse type. + + NOTE: Copyright (DMCA) and Trademark reports cannot be anonymous. + """ + + owner_notification: Required[Literal["send", "send-anon", "none"]] + """Notification type based on the abuse type. + + NOTE: Copyright (DMCA) and Trademark reports cannot be anonymous. + """ + + urls: Required[str] + """A list of valid URLs separated by ‘ ’ (new line character). + + The list of the URLs should not exceed 250 URLs. All URLs should have the same + hostname. Each URL should be unique + """ + + address1: str + """Text not exceeding 100 characters""" + + agent_name: str + """The name of the copyright holder. Text not exceeding 60 characters.""" + + agree: Literal[0, 1] + """Can be 0 or 1""" + + city: str + """Text not exceeding 255 characters""" + + comments: str + """Any additional comments about the infringement not exceeding 2000 characters""" + + company: str + """Text not exceeding 100 characters""" + + country: str + """Text not exceeding 255 characters""" + + destination_ips: str + """A list of IP addresses separated by ‘ ’ (new line character). + + The list of destination IPs should not exceed 30 IP addresses. Each one of the + IP addresses ought to be unique + """ + + justification: str + """ + A detailed description of the infringement, including any necessary access + details and the exact steps needed to view the content, not exceeding 5000 + characters + """ + + name: str + """Text not exceeding 255 characters""" + + ncsei_subject_representation: bool + """If the submitter is the target of NCSEI in the URLs of the abuse report""" + + original_work: str + """Text not exceeding 255 characters""" + + ports_protocols: str + """A comma separated list of ports and protocols e.g. + + 80/TCP, 22/UDP. The total size of the field should not exceed 2000 characters. + Each individual port/protocol should not exceed 100 characters. The list should + not have more than 30 unique ports and protocols. + """ + + signature: str + """Required for DMCA reports, should be same as Name. + + An affirmation that all information in the report is true and accurate while + agreeing to the policies of Cloudflare's abuse reports + """ + + source_ips: str + """A list of IP addresses separated by ‘ ’ (new line character). + + The list of source IPs should not exceed 30 IP addresses. Each one of the IP + addresses ought to be unique + """ + + state: str + """Text not exceeding 255 characters""" + + tele: str + """Text not exceeding 20 characters""" + + title: str + """Text not exceeding 255 characters""" + + trademark_number: str + """Text not exceeding 1000 characters""" + + trademark_office: str + """Text not exceeding 1000 characters""" + + trademark_symbol: str + """Text not exceeding 1000 characters""" diff --git a/src/cloudflare/types/abuse_reports/abuse_report_create_response.py b/src/cloudflare/types/abuse_reports/abuse_report_create_response.py new file mode 100644 index 00000000000..03fc4011e68 --- /dev/null +++ b/src/cloudflare/types/abuse_reports/abuse_report_create_response.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import TypeAlias + +__all__ = ["AbuseReportCreateResponse"] + +AbuseReportCreateResponse: TypeAlias = str diff --git a/src/cloudflare/types/zero_trust/devices/__init__.py b/src/cloudflare/types/zero_trust/devices/__init__.py index 831df46d499..37d71da7a5e 100644 --- a/src/cloudflare/types/zero_trust/devices/__init__.py +++ b/src/cloudflare/types/zero_trust/devices/__init__.py @@ -49,6 +49,7 @@ from .unique_client_id_input import UniqueClientIDInput as UniqueClientIDInput from .unrevoke_create_params import UnrevokeCreateParams as UnrevokeCreateParams from .crowdstrike_input_param import CrowdstrikeInputParam as CrowdstrikeInputParam +from .fleet_status_get_params import FleetStatusGetParams as FleetStatusGetParams from .network_delete_response import NetworkDeleteResponse as NetworkDeleteResponse from .posture_delete_response import PostureDeleteResponse as PostureDeleteResponse from .sentinelone_input_param import SentineloneInputParam as SentineloneInputParam @@ -56,6 +57,7 @@ from .dex_test_delete_response import DEXTestDeleteResponse as DEXTestDeleteResponse from .unrevoke_create_response import UnrevokeCreateResponse as UnrevokeCreateResponse from .domain_joined_input_param import DomainJoinedInputParam as DomainJoinedInputParam +from .fleet_status_get_response import FleetStatusGetResponse as FleetStatusGetResponse from .workspace_one_input_param import WorkspaceOneInputParam as WorkspaceOneInputParam from .split_tunnel_exclude_param import SplitTunnelExcludeParam as SplitTunnelExcludeParam from .split_tunnel_include_param import SplitTunnelIncludeParam as SplitTunnelIncludeParam diff --git a/src/cloudflare/types/zero_trust/devices/fleet_status_get_params.py b/src/cloudflare/types/zero_trust/devices/fleet_status_get_params.py new file mode 100644 index 00000000000..09a81b98c51 --- /dev/null +++ b/src/cloudflare/types/zero_trust/devices/fleet_status_get_params.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["FleetStatusGetParams"] + + +class FleetStatusGetParams(TypedDict, total=False): + account_id: Required[str] + + since_minutes: Required[float] + """Number of minutes before current time""" + + colo: str + """List of data centers to filter results""" + + time_now: str + """Number of minutes before current time""" diff --git a/src/cloudflare/types/zero_trust/devices/fleet_status_get_response.py b/src/cloudflare/types/zero_trust/devices/fleet_status_get_response.py new file mode 100644 index 00000000000..f4feee2cb0c --- /dev/null +++ b/src/cloudflare/types/zero_trust/devices/fleet_status_get_response.py @@ -0,0 +1,268 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from ...._models import BaseModel + +__all__ = [ + "FleetStatusGetResponse", + "CPUPctByApp", + "DeviceIPV4", + "DeviceIPV4Location", + "DeviceIPV6", + "DeviceIPV6Location", + "GatewayIPV4", + "GatewayIPV4Location", + "GatewayIPV6", + "GatewayIPV6Location", + "ISPIPV4", + "ISPIPV4Location", + "ISPIPV6", + "ISPIPV6Location", + "RamUsedPctByApp", +] + + +class CPUPctByApp(BaseModel): + cpu_pct: Optional[float] = None + + name: Optional[str] = None + + +class DeviceIPV4Location(BaseModel): + city: Optional[str] = None + + country_iso: Optional[str] = None + + state_iso: Optional[str] = None + + zip: Optional[str] = None + + +class DeviceIPV4(BaseModel): + address: Optional[str] = None + + asn: Optional[int] = None + + aso: Optional[str] = None + + location: Optional[DeviceIPV4Location] = None + + netmask: Optional[str] = None + + version: Optional[str] = None + + +class DeviceIPV6Location(BaseModel): + city: Optional[str] = None + + country_iso: Optional[str] = None + + state_iso: Optional[str] = None + + zip: Optional[str] = None + + +class DeviceIPV6(BaseModel): + address: Optional[str] = None + + asn: Optional[int] = None + + aso: Optional[str] = None + + location: Optional[DeviceIPV6Location] = None + + netmask: Optional[str] = None + + version: Optional[str] = None + + +class GatewayIPV4Location(BaseModel): + city: Optional[str] = None + + country_iso: Optional[str] = None + + state_iso: Optional[str] = None + + zip: Optional[str] = None + + +class GatewayIPV4(BaseModel): + address: Optional[str] = None + + asn: Optional[int] = None + + aso: Optional[str] = None + + location: Optional[GatewayIPV4Location] = None + + netmask: Optional[str] = None + + version: Optional[str] = None + + +class GatewayIPV6Location(BaseModel): + city: Optional[str] = None + + country_iso: Optional[str] = None + + state_iso: Optional[str] = None + + zip: Optional[str] = None + + +class GatewayIPV6(BaseModel): + address: Optional[str] = None + + asn: Optional[int] = None + + aso: Optional[str] = None + + location: Optional[GatewayIPV6Location] = None + + netmask: Optional[str] = None + + version: Optional[str] = None + + +class ISPIPV4Location(BaseModel): + city: Optional[str] = None + + country_iso: Optional[str] = None + + state_iso: Optional[str] = None + + zip: Optional[str] = None + + +class ISPIPV4(BaseModel): + address: Optional[str] = None + + asn: Optional[int] = None + + aso: Optional[str] = None + + location: Optional[ISPIPV4Location] = None + + netmask: Optional[str] = None + + version: Optional[str] = None + + +class ISPIPV6Location(BaseModel): + city: Optional[str] = None + + country_iso: Optional[str] = None + + state_iso: Optional[str] = None + + zip: Optional[str] = None + + +class ISPIPV6(BaseModel): + address: Optional[str] = None + + asn: Optional[int] = None + + aso: Optional[str] = None + + location: Optional[ISPIPV6Location] = None + + netmask: Optional[str] = None + + version: Optional[str] = None + + +class RamUsedPctByApp(BaseModel): + name: Optional[str] = None + + ram_used_pct: Optional[float] = None + + +class FleetStatusGetResponse(BaseModel): + colo: str + """Cloudflare colo""" + + device_id: str = FieldInfo(alias="deviceId") + """Device identifier (UUID v4)""" + + mode: str + """The mode under which the WARP client is run""" + + platform: str + """Operating system""" + + status: str + """Network status""" + + timestamp: str + """Timestamp in ISO format""" + + version: str + """WARP client version""" + + always_on: Optional[bool] = FieldInfo(alias="alwaysOn", default=None) + + battery_charging: Optional[bool] = FieldInfo(alias="batteryCharging", default=None) + + battery_cycles: Optional[int] = FieldInfo(alias="batteryCycles", default=None) + + battery_pct: Optional[float] = FieldInfo(alias="batteryPct", default=None) + + connection_type: Optional[str] = FieldInfo(alias="connectionType", default=None) + + cpu_pct: Optional[float] = FieldInfo(alias="cpuPct", default=None) + + cpu_pct_by_app: Optional[List[List[CPUPctByApp]]] = FieldInfo(alias="cpuPctByApp", default=None) + + device_ipv4: Optional[DeviceIPV4] = FieldInfo(alias="deviceIpv4", default=None) + + device_ipv6: Optional[DeviceIPV6] = FieldInfo(alias="deviceIpv6", default=None) + + device_name: Optional[str] = FieldInfo(alias="deviceName", default=None) + """Device identifier (human readable)""" + + disk_read_bps: Optional[int] = FieldInfo(alias="diskReadBps", default=None) + + disk_usage_pct: Optional[float] = FieldInfo(alias="diskUsagePct", default=None) + + disk_write_bps: Optional[int] = FieldInfo(alias="diskWriteBps", default=None) + + doh_subdomain: Optional[str] = FieldInfo(alias="dohSubdomain", default=None) + + estimated_loss_pct: Optional[float] = FieldInfo(alias="estimatedLossPct", default=None) + + firewall_enabled: Optional[bool] = FieldInfo(alias="firewallEnabled", default=None) + + gateway_ipv4: Optional[GatewayIPV4] = FieldInfo(alias="gatewayIpv4", default=None) + + gateway_ipv6: Optional[GatewayIPV6] = FieldInfo(alias="gatewayIpv6", default=None) + + handshake_latency_ms: Optional[float] = FieldInfo(alias="handshakeLatencyMs", default=None) + + isp_ipv4: Optional[ISPIPV4] = FieldInfo(alias="ispIpv4", default=None) + + isp_ipv6: Optional[ISPIPV6] = FieldInfo(alias="ispIpv6", default=None) + + metal: Optional[str] = None + + network_rcvd_bps: Optional[int] = FieldInfo(alias="networkRcvdBps", default=None) + + network_sent_bps: Optional[int] = FieldInfo(alias="networkSentBps", default=None) + + network_ssid: Optional[str] = FieldInfo(alias="networkSsid", default=None) + + person_email: Optional[str] = FieldInfo(alias="personEmail", default=None) + """User contact email address""" + + ram_available_kb: Optional[int] = FieldInfo(alias="ramAvailableKb", default=None) + + ram_used_pct: Optional[float] = FieldInfo(alias="ramUsedPct", default=None) + + ram_used_pct_by_app: Optional[List[List[RamUsedPctByApp]]] = FieldInfo(alias="ramUsedPctByApp", default=None) + + switch_locked: Optional[bool] = FieldInfo(alias="switchLocked", default=None) + + wifi_strength_dbm: Optional[int] = FieldInfo(alias="wifiStrengthDbm", default=None) diff --git a/src/cloudflare/types/zero_trust/dex/__init__.py b/src/cloudflare/types/zero_trust/dex/__init__.py index d891e1d3a9d..cd977b0b14c 100644 --- a/src/cloudflare/types/zero_trust/dex/__init__.py +++ b/src/cloudflare/types/zero_trust/dex/__init__.py @@ -8,8 +8,12 @@ from .http_details import HTTPDetails as HTTPDetails from .colo_list_params import ColoListParams as ColoListParams from .test_list_params import TestListParams as TestListParams +from .command_list_params import CommandListParams as CommandListParams from .http_test_get_params import HTTPTestGetParams as HTTPTestGetParams from .aggregate_time_period import AggregateTimePeriod as AggregateTimePeriod +from .command_create_params import CommandCreateParams as CommandCreateParams +from .command_list_response import CommandListResponse as CommandListResponse +from .command_create_response import CommandCreateResponse as CommandCreateResponse from .fleet_status_live_params import FleetStatusLiveParams as FleetStatusLiveParams from .fleet_status_live_response import FleetStatusLiveResponse as FleetStatusLiveResponse from .traceroute_test_get_params import TracerouteTestGetParams as TracerouteTestGetParams diff --git a/src/cloudflare/types/zero_trust/dex/command_create_params.py b/src/cloudflare/types/zero_trust/dex/command_create_params.py new file mode 100644 index 00000000000..cbab76ab1c1 --- /dev/null +++ b/src/cloudflare/types/zero_trust/dex/command_create_params.py @@ -0,0 +1,57 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Iterable +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ...._utils import PropertyInfo + +__all__ = ["CommandCreateParams", "Command", "CommandCommandArgs"] + + +class CommandCreateParams(TypedDict, total=False): + account_id: Required[str] + + commands: Required[Iterable[Command]] + """List of device-level commands to execute""" + + +class CommandCommandArgs(TypedDict, total=False): + interfaces: List[Literal["default", "tunnel"]] + """List of interfaces to capture packets on""" + + max_file_size_mb: Annotated[float, PropertyInfo(alias="max-file-size-mb")] + """Maximum file size (in MB) for the capture file. + + Specifies the maximum file size of the warp-diag zip artifact that can be + uploaded. If the zip artifact exceeds the specified max file size, it will NOT + be uploaded + """ + + packet_size_bytes: Annotated[float, PropertyInfo(alias="packet-size-bytes")] + """Maximum number of bytes to save for each packet""" + + test_all_routes: Annotated[bool, PropertyInfo(alias="test-all-routes")] + """Test an IP address from all included or excluded ranges. + + Tests an IP address from all included or excluded ranges. Essentially the same + as running 'route get '' and collecting the results. This option may + increase the time taken to collect the warp-diag + """ + + time_limit_min: Annotated[float, PropertyInfo(alias="time-limit-min")] + """Limit on capture duration (in minutes)""" + + +class Command(TypedDict, total=False): + command_type: Required[Literal["pcap", "warp-diag"]] + """Type of command to execute on the device""" + + device_id: Required[str] + """Unique identifier for the device""" + + user_email: Required[str] + """Email tied to the device""" + + command_args: CommandCommandArgs diff --git a/src/cloudflare/types/zero_trust/dex/command_create_response.py b/src/cloudflare/types/zero_trust/dex/command_create_response.py new file mode 100644 index 00000000000..e3a1e432678 --- /dev/null +++ b/src/cloudflare/types/zero_trust/dex/command_create_response.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from typing_extensions import Literal + +from ...._models import BaseModel + +__all__ = ["CommandCreateResponse", "Command"] + + +class Command(BaseModel): + id: Optional[str] = None + """Unique identifier for the command""" + + args: Optional[Dict[str, str]] = None + """Command arguments""" + + device_id: Optional[str] = None + """Identifier for the device associated with the command""" + + status: Optional[Literal["PENDING_EXEC", "PENDING_UPLOAD", "SUCCESS", "FAILED"]] = None + """Current status of the command""" + + type: Optional[str] = None + """Type of the command (e.g., "pcap" or "warp-diag")""" + + +class CommandCreateResponse(BaseModel): + commands: Optional[List[Command]] = None + """List of created commands""" diff --git a/src/cloudflare/types/zero_trust/dex/command_list_params.py b/src/cloudflare/types/zero_trust/dex/command_list_params.py new file mode 100644 index 00000000000..cbe58116f27 --- /dev/null +++ b/src/cloudflare/types/zero_trust/dex/command_list_params.py @@ -0,0 +1,39 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ...._utils import PropertyInfo + +__all__ = ["CommandListParams"] + + +class CommandListParams(TypedDict, total=False): + account_id: Required[str] + + page: Required[float] + """Page number for pagination""" + + per_page: Required[float] + """Number of results per page""" + + command_type: str + """Optionally filter executed commands by command type""" + + device_id: str + """Unique identifier for a device""" + + from_: Annotated[Union[str, datetime], PropertyInfo(alias="from", format="iso8601")] + """Start time for the query in ISO (RFC3339 - ISO 8601) format""" + + status: Literal["PENDING_EXEC", "PENDING_UPLOAD", "SUCCESS", "FAILED"] + """Optionally filter executed commands by status""" + + to: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """End time for the query in ISO (RFC3339 - ISO 8601) format""" + + user_email: str + """Email tied to the device""" diff --git a/src/cloudflare/types/zero_trust/dex/command_list_response.py b/src/cloudflare/types/zero_trust/dex/command_list_response.py new file mode 100644 index 00000000000..601cef906ce --- /dev/null +++ b/src/cloudflare/types/zero_trust/dex/command_list_response.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime + +from ...._models import BaseModel + +__all__ = ["CommandListResponse", "Command"] + + +class Command(BaseModel): + id: Optional[str] = None + + completed_date: Optional[datetime] = None + + created_date: Optional[datetime] = None + + device_id: Optional[str] = None + + filename: Optional[str] = None + + status: Optional[str] = None + + type: Optional[str] = None + + user_email: Optional[str] = None + + +class CommandListResponse(BaseModel): + commands: Optional[List[Command]] = None diff --git a/src/cloudflare/types/zero_trust/dex/commands/__init__.py b/src/cloudflare/types/zero_trust/dex/commands/__init__.py index f8ee8b14b1c..83304891f5e 100644 --- a/src/cloudflare/types/zero_trust/dex/commands/__init__.py +++ b/src/cloudflare/types/zero_trust/dex/commands/__init__.py @@ -1,3 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations + +from .quota_get_response import QuotaGetResponse as QuotaGetResponse diff --git a/src/cloudflare/types/zero_trust/dex/commands/quota_get_response.py b/src/cloudflare/types/zero_trust/dex/commands/quota_get_response.py new file mode 100644 index 00000000000..df1cc7d0596 --- /dev/null +++ b/src/cloudflare/types/zero_trust/dex/commands/quota_get_response.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime + +from ....._models import BaseModel + +__all__ = ["QuotaGetResponse"] + + +class QuotaGetResponse(BaseModel): + quota: float + """The remaining number of commands that can be initiated for an account""" + + quota_usage: float + """The number of commands that have been initiated for an account""" + + reset_time: datetime + """The time when the quota resets""" diff --git a/src/cloudflare/types/zones/__init__.py b/src/cloudflare/types/zones/__init__.py index f82d8f8e328..63621e80433 100644 --- a/src/cloudflare/types/zones/__init__.py +++ b/src/cloudflare/types/zones/__init__.py @@ -49,6 +49,7 @@ from .websocket_param import WebsocketParam as WebsocketParam from .always_use_https import AlwaysUseHTTPS as AlwaysUseHTTPS from .development_mode import DevelopmentMode as DevelopmentMode +from .hold_edit_params import HoldEditParams as HoldEditParams from .orange_to_orange import OrangeToOrange as OrangeToOrange from .prefetch_preload import PrefetchPreload as PrefetchPreload from .security_headers import SecurityHeaders as SecurityHeaders diff --git a/src/cloudflare/types/zones/hold_edit_params.py b/src/cloudflare/types/zones/hold_edit_params.py new file mode 100644 index 00000000000..fc5e878576f --- /dev/null +++ b/src/cloudflare/types/zones/hold_edit_params.py @@ -0,0 +1,29 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["HoldEditParams"] + + +class HoldEditParams(TypedDict, total=False): + zone_id: Required[str] + """Identifier""" + + hold_after: str + """ + If `hold_after` is provided and future-dated, the hold will be temporarily + disabled, then automatically re-enabled by the system at the time specified in + this RFC3339-formatted timestamp. A past-dated `hold_after` value will have no + effect on an existing, enabled hold. Providing an empty string will set its + value to the current time. + """ + + include_subdomains: bool + """ + If `true`, the zone hold will extend to block any subdomain of the given zone, + as well as SSL4SaaS Custom Hostnames. For example, a zone hold on a zone with + the hostname 'example.com' and include_subdomains=true will block 'example.com', + 'staging.example.com', 'api.staging.example.com', etc. + """ diff --git a/tests/api_resources/test_abuse_reports.py b/tests/api_resources/test_abuse_reports.py new file mode 100644 index 00000000000..105b9e07063 --- /dev/null +++ b/tests/api_resources/test_abuse_reports.py @@ -0,0 +1,233 @@ +# 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 cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAbuseReports: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Cloudflare) -> None: + abuse_report = client.abuse_reports.create( + report_type="abuse_dmca", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + ) + assert_matches_type(str, abuse_report, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Cloudflare) -> None: + abuse_report = client.abuse_reports.create( + report_type="abuse_dmca", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + address1="x", + agent_name="x", + agree=0, + city="x", + comments="x", + company="x", + country="x", + destination_ips="destination_ips", + justification="x", + name="x", + ncsei_subject_representation=True, + original_work="x", + ports_protocols="ports_protocols", + signature="signature", + source_ips="source_ips", + state="x", + tele="x", + title="x", + trademark_number="x", + trademark_office="x", + trademark_symbol="x", + ) + assert_matches_type(str, abuse_report, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Cloudflare) -> None: + response = client.abuse_reports.with_raw_response.create( + report_type="abuse_dmca", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + abuse_report = response.parse() + assert_matches_type(str, abuse_report, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Cloudflare) -> None: + with client.abuse_reports.with_streaming_response.create( + report_type="abuse_dmca", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + abuse_report = response.parse() + assert_matches_type(str, abuse_report, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_create(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.abuse_reports.with_raw_response.create( + report_type="abuse_dmca", + account_id="", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + ) + + +class TestAsyncAbuseReports: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_create(self, async_client: AsyncCloudflare) -> None: + abuse_report = await async_client.abuse_reports.create( + report_type="abuse_dmca", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + ) + assert_matches_type(str, abuse_report, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncCloudflare) -> None: + abuse_report = await async_client.abuse_reports.create( + report_type="abuse_dmca", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + address1="x", + agent_name="x", + agree=0, + city="x", + comments="x", + company="x", + country="x", + destination_ips="destination_ips", + justification="x", + name="x", + ncsei_subject_representation=True, + original_work="x", + ports_protocols="ports_protocols", + signature="signature", + source_ips="source_ips", + state="x", + tele="x", + title="x", + trademark_number="x", + trademark_office="x", + trademark_symbol="x", + ) + assert_matches_type(str, abuse_report, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None: + response = await async_client.abuse_reports.with_raw_response.create( + report_type="abuse_dmca", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + abuse_report = await response.parse() + assert_matches_type(str, abuse_report, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncCloudflare) -> None: + async with async_client.abuse_reports.with_streaming_response.create( + report_type="abuse_dmca", + account_id="023e105f4ecef8ad9ca31a8372d0c353", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + abuse_report = await response.parse() + assert_matches_type(str, abuse_report, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_create(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.abuse_reports.with_raw_response.create( + report_type="abuse_dmca", + account_id="", + act="abuse_dmca", + email="email", + email2="email2", + host_notification="send", + ncmec_notification="send", + owner_notification="send", + urls="urls", + ) diff --git a/tests/api_resources/zero_trust/devices/test_fleet_status.py b/tests/api_resources/zero_trust/devices/test_fleet_status.py new file mode 100644 index 00000000000..308864477e0 --- /dev/null +++ b/tests/api_resources/zero_trust/devices/test_fleet_status.py @@ -0,0 +1,150 @@ +# 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 cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type +from cloudflare.types.zero_trust.devices import FleetStatusGetResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFleetStatus: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_get(self, client: Cloudflare) -> None: + fleet_status = client.zero_trust.devices.fleet_status.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + ) + assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"]) + + @parametrize + def test_method_get_with_all_params(self, client: Cloudflare) -> None: + fleet_status = client.zero_trust.devices.fleet_status.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + colo="SJC", + time_now="2023-10-11T00:00:00Z", + ) + assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Cloudflare) -> None: + response = client.zero_trust.devices.fleet_status.with_raw_response.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + fleet_status = response.parse() + assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Cloudflare) -> None: + with client.zero_trust.devices.fleet_status.with_streaming_response.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + fleet_status = response.parse() + assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.devices.fleet_status.with_raw_response.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="", + since_minutes=10, + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + client.zero_trust.devices.fleet_status.with_raw_response.get( + device_id="", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + ) + + +class TestAsyncFleetStatus: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_get(self, async_client: AsyncCloudflare) -> None: + fleet_status = await async_client.zero_trust.devices.fleet_status.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + ) + assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"]) + + @parametrize + async def test_method_get_with_all_params(self, async_client: AsyncCloudflare) -> None: + fleet_status = await async_client.zero_trust.devices.fleet_status.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + colo="SJC", + time_now="2023-10-11T00:00:00Z", + ) + assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.devices.fleet_status.with_raw_response.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + fleet_status = await response.parse() + assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.devices.fleet_status.with_streaming_response.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + fleet_status = await response.parse() + assert_matches_type(FleetStatusGetResponse, fleet_status, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.devices.fleet_status.with_raw_response.get( + device_id="cb49c27f-7f97-49c5-b6f3-f7c01ead0fd7", + account_id="", + since_minutes=10, + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + await async_client.zero_trust.devices.fleet_status.with_raw_response.get( + device_id="", + account_id="01a7362d577a6c3019a474fd6f485823", + since_minutes=10, + ) diff --git a/tests/api_resources/zero_trust/dex/commands/__init__.py b/tests/api_resources/zero_trust/dex/commands/__init__.py new file mode 100644 index 00000000000..fd8019a9a1a --- /dev/null +++ b/tests/api_resources/zero_trust/dex/commands/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/zero_trust/dex/commands/test_downloads.py b/tests/api_resources/zero_trust/dex/commands/test_downloads.py new file mode 100644 index 00000000000..66711dbdd5a --- /dev/null +++ b/tests/api_resources/zero_trust/dex/commands/test_downloads.py @@ -0,0 +1,184 @@ +# 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 httpx +import pytest +from respx import MockRouter + +from cloudflare import Cloudflare, AsyncCloudflare +from cloudflare._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestDownloads: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_get(self, client: Cloudflare, respx_mock: MockRouter) -> None: + respx_mock.get( + "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename" + ).mock(return_value=httpx.Response(200, json={"foo": "bar"})) + download = client.zero_trust.dex.commands.downloads.get( + filename="filename", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) + assert download.is_closed + assert download.json() == {"foo": "bar"} + assert cast(Any, download.is_closed) is True + assert isinstance(download, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_raw_response_get(self, client: Cloudflare, respx_mock: MockRouter) -> None: + respx_mock.get( + "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename" + ).mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + download = client.zero_trust.dex.commands.downloads.with_raw_response.get( + filename="filename", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) + + assert download.is_closed is True + assert download.http_request.headers.get("X-Stainless-Lang") == "python" + assert download.json() == {"foo": "bar"} + assert isinstance(download, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_streaming_response_get(self, client: Cloudflare, respx_mock: MockRouter) -> None: + respx_mock.get( + "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename" + ).mock(return_value=httpx.Response(200, json={"foo": "bar"})) + with client.zero_trust.dex.commands.downloads.with_streaming_response.get( + filename="filename", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) as download: + assert not download.is_closed + assert download.http_request.headers.get("X-Stainless-Lang") == "python" + + assert download.json() == {"foo": "bar"} + assert cast(Any, download.is_closed) is True + assert isinstance(download, StreamedBinaryAPIResponse) + + assert cast(Any, download.is_closed) is True + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_path_params_get(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.dex.commands.downloads.with_raw_response.get( + filename="filename", + account_id="", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `command_id` but received ''"): + client.zero_trust.dex.commands.downloads.with_raw_response.get( + filename="filename", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `filename` but received ''"): + client.zero_trust.dex.commands.downloads.with_raw_response.get( + filename="", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) + + +class TestAsyncDownloads: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_get(self, async_client: AsyncCloudflare, respx_mock: MockRouter) -> None: + respx_mock.get( + "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename" + ).mock(return_value=httpx.Response(200, json={"foo": "bar"})) + download = await async_client.zero_trust.dex.commands.downloads.get( + filename="filename", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) + assert download.is_closed + assert await download.json() == {"foo": "bar"} + assert cast(Any, download.is_closed) is True + assert isinstance(download, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_raw_response_get(self, async_client: AsyncCloudflare, respx_mock: MockRouter) -> None: + respx_mock.get( + "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename" + ).mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + download = await async_client.zero_trust.dex.commands.downloads.with_raw_response.get( + filename="filename", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) + + assert download.is_closed is True + assert download.http_request.headers.get("X-Stainless-Lang") == "python" + assert await download.json() == {"foo": "bar"} + assert isinstance(download, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_streaming_response_get(self, async_client: AsyncCloudflare, respx_mock: MockRouter) -> None: + respx_mock.get( + "/accounts/01a7362d577a6c3019a474fd6f485823/dex/commands/5758fefe-ae7e-4538-a39b-1fef6abcb909/downloads/filename" + ).mock(return_value=httpx.Response(200, json={"foo": "bar"})) + async with async_client.zero_trust.dex.commands.downloads.with_streaming_response.get( + filename="filename", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) as download: + assert not download.is_closed + assert download.http_request.headers.get("X-Stainless-Lang") == "python" + + assert await download.json() == {"foo": "bar"} + assert cast(Any, download.is_closed) is True + assert isinstance(download, AsyncStreamedBinaryAPIResponse) + + assert cast(Any, download.is_closed) is True + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.dex.commands.downloads.with_raw_response.get( + filename="filename", + account_id="", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `command_id` but received ''"): + await async_client.zero_trust.dex.commands.downloads.with_raw_response.get( + filename="filename", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `filename` but received ''"): + await async_client.zero_trust.dex.commands.downloads.with_raw_response.get( + filename="", + account_id="01a7362d577a6c3019a474fd6f485823", + command_id="5758fefe-ae7e-4538-a39b-1fef6abcb909", + ) diff --git a/tests/api_resources/zero_trust/dex/commands/test_quota.py b/tests/api_resources/zero_trust/dex/commands/test_quota.py new file mode 100644 index 00000000000..5291e9d3113 --- /dev/null +++ b/tests/api_resources/zero_trust/dex/commands/test_quota.py @@ -0,0 +1,98 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, Optional, cast + +import pytest + +from cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type +from cloudflare.types.zero_trust.dex.commands import QuotaGetResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestQuota: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_get(self, client: Cloudflare) -> None: + quota = client.zero_trust.dex.commands.quota.get( + account_id="01a7362d577a6c3019a474fd6f485823", + ) + assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Cloudflare) -> None: + response = client.zero_trust.dex.commands.quota.with_raw_response.get( + account_id="01a7362d577a6c3019a474fd6f485823", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + quota = response.parse() + assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Cloudflare) -> None: + with client.zero_trust.dex.commands.quota.with_streaming_response.get( + account_id="01a7362d577a6c3019a474fd6f485823", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + quota = response.parse() + assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_get(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.dex.commands.quota.with_raw_response.get( + account_id="", + ) + + +class TestAsyncQuota: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_get(self, async_client: AsyncCloudflare) -> None: + quota = await async_client.zero_trust.dex.commands.quota.get( + account_id="01a7362d577a6c3019a474fd6f485823", + ) + assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.dex.commands.quota.with_raw_response.get( + account_id="01a7362d577a6c3019a474fd6f485823", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + quota = await response.parse() + assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.dex.commands.quota.with_streaming_response.get( + account_id="01a7362d577a6c3019a474fd6f485823", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + quota = await response.parse() + assert_matches_type(Optional[QuotaGetResponse], quota, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_get(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.dex.commands.quota.with_raw_response.get( + account_id="", + ) diff --git a/tests/api_resources/zero_trust/dex/test_commands.py b/tests/api_resources/zero_trust/dex/test_commands.py new file mode 100644 index 00000000000..9692c4fde6c --- /dev/null +++ b/tests/api_resources/zero_trust/dex/test_commands.py @@ -0,0 +1,281 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, Optional, cast + +import pytest + +from cloudflare import Cloudflare, AsyncCloudflare +from tests.utils import assert_matches_type +from cloudflare._utils import parse_datetime +from cloudflare.pagination import SyncV4PagePagination, AsyncV4PagePagination +from cloudflare.types.zero_trust.dex import ( + CommandListResponse, + CommandCreateResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCommands: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Cloudflare) -> None: + command = client.zero_trust.dex.commands.create( + account_id="01a7362d577a6c3019a474fd6f485823", + commands=[ + { + "command_type": "pcap", + "device_id": "device_id", + "user_email": "user_email", + } + ], + ) + assert_matches_type(Optional[CommandCreateResponse], command, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Cloudflare) -> None: + response = client.zero_trust.dex.commands.with_raw_response.create( + account_id="01a7362d577a6c3019a474fd6f485823", + commands=[ + { + "command_type": "pcap", + "device_id": "device_id", + "user_email": "user_email", + } + ], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + command = response.parse() + assert_matches_type(Optional[CommandCreateResponse], command, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Cloudflare) -> None: + with client.zero_trust.dex.commands.with_streaming_response.create( + account_id="01a7362d577a6c3019a474fd6f485823", + commands=[ + { + "command_type": "pcap", + "device_id": "device_id", + "user_email": "user_email", + } + ], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + command = response.parse() + assert_matches_type(Optional[CommandCreateResponse], command, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_create(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.dex.commands.with_raw_response.create( + account_id="", + commands=[ + { + "command_type": "pcap", + "device_id": "device_id", + "user_email": "user_email", + } + ], + ) + + @parametrize + def test_method_list(self, client: Cloudflare) -> None: + command = client.zero_trust.dex.commands.list( + account_id="01a7362d577a6c3019a474fd6f485823", + page=1, + per_page=50, + ) + assert_matches_type(SyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Cloudflare) -> None: + command = client.zero_trust.dex.commands.list( + account_id="01a7362d577a6c3019a474fd6f485823", + page=1, + per_page=50, + command_type="command_type", + device_id="device_id", + from_=parse_datetime("2023-08-20T20:45:00Z"), + status="PENDING_EXEC", + to=parse_datetime("2023-08-24T20:45:00Z"), + user_email="user_email", + ) + assert_matches_type(SyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Cloudflare) -> None: + response = client.zero_trust.dex.commands.with_raw_response.list( + account_id="01a7362d577a6c3019a474fd6f485823", + page=1, + per_page=50, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + command = response.parse() + assert_matches_type(SyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Cloudflare) -> None: + with client.zero_trust.dex.commands.with_streaming_response.list( + account_id="01a7362d577a6c3019a474fd6f485823", + page=1, + per_page=50, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + command = response.parse() + assert_matches_type(SyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.zero_trust.dex.commands.with_raw_response.list( + account_id="", + page=1, + per_page=50, + ) + + +class TestAsyncCommands: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_create(self, async_client: AsyncCloudflare) -> None: + command = await async_client.zero_trust.dex.commands.create( + account_id="01a7362d577a6c3019a474fd6f485823", + commands=[ + { + "command_type": "pcap", + "device_id": "device_id", + "user_email": "user_email", + } + ], + ) + assert_matches_type(Optional[CommandCreateResponse], command, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.dex.commands.with_raw_response.create( + account_id="01a7362d577a6c3019a474fd6f485823", + commands=[ + { + "command_type": "pcap", + "device_id": "device_id", + "user_email": "user_email", + } + ], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + command = await response.parse() + assert_matches_type(Optional[CommandCreateResponse], command, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.dex.commands.with_streaming_response.create( + account_id="01a7362d577a6c3019a474fd6f485823", + commands=[ + { + "command_type": "pcap", + "device_id": "device_id", + "user_email": "user_email", + } + ], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + command = await response.parse() + assert_matches_type(Optional[CommandCreateResponse], command, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_create(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.dex.commands.with_raw_response.create( + account_id="", + commands=[ + { + "command_type": "pcap", + "device_id": "device_id", + "user_email": "user_email", + } + ], + ) + + @parametrize + async def test_method_list(self, async_client: AsyncCloudflare) -> None: + command = await async_client.zero_trust.dex.commands.list( + account_id="01a7362d577a6c3019a474fd6f485823", + page=1, + per_page=50, + ) + assert_matches_type(AsyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncCloudflare) -> None: + command = await async_client.zero_trust.dex.commands.list( + account_id="01a7362d577a6c3019a474fd6f485823", + page=1, + per_page=50, + command_type="command_type", + device_id="device_id", + from_=parse_datetime("2023-08-20T20:45:00Z"), + status="PENDING_EXEC", + to=parse_datetime("2023-08-24T20:45:00Z"), + user_email="user_email", + ) + assert_matches_type(AsyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zero_trust.dex.commands.with_raw_response.list( + account_id="01a7362d577a6c3019a474fd6f485823", + page=1, + per_page=50, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + command = await response.parse() + assert_matches_type(AsyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None: + async with async_client.zero_trust.dex.commands.with_streaming_response.list( + account_id="01a7362d577a6c3019a474fd6f485823", + page=1, + per_page=50, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + command = await response.parse() + assert_matches_type(AsyncV4PagePagination[Optional[CommandListResponse]], command, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + await async_client.zero_trust.dex.commands.with_raw_response.list( + account_id="", + page=1, + per_page=50, + ) diff --git a/tests/api_resources/zones/test_holds.py b/tests/api_resources/zones/test_holds.py index bc033b8fdc7..b34e5066342 100644 --- a/tests/api_resources/zones/test_holds.py +++ b/tests/api_resources/zones/test_holds.py @@ -109,6 +109,53 @@ def test_path_params_delete(self, client: Cloudflare) -> None: zone_id="", ) + @parametrize + def test_method_edit(self, client: Cloudflare) -> None: + hold = client.zones.holds.edit( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(ZoneHold, hold, path=["response"]) + + @parametrize + def test_method_edit_with_all_params(self, client: Cloudflare) -> None: + hold = client.zones.holds.edit( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + hold_after="2023-01-31T15:56:36+00:00", + include_subdomains=True, + ) + assert_matches_type(ZoneHold, hold, path=["response"]) + + @parametrize + def test_raw_response_edit(self, client: Cloudflare) -> None: + response = client.zones.holds.with_raw_response.edit( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = response.parse() + assert_matches_type(ZoneHold, hold, path=["response"]) + + @parametrize + def test_streaming_response_edit(self, client: Cloudflare) -> None: + with client.zones.holds.with_streaming_response.edit( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = response.parse() + assert_matches_type(ZoneHold, hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_edit(self, client: Cloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"): + client.zones.holds.with_raw_response.edit( + zone_id="", + ) + @parametrize def test_method_get(self, client: Cloudflare) -> None: hold = client.zones.holds.get( @@ -243,6 +290,53 @@ async def test_path_params_delete(self, async_client: AsyncCloudflare) -> None: zone_id="", ) + @parametrize + async def test_method_edit(self, async_client: AsyncCloudflare) -> None: + hold = await async_client.zones.holds.edit( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + assert_matches_type(ZoneHold, hold, path=["response"]) + + @parametrize + async def test_method_edit_with_all_params(self, async_client: AsyncCloudflare) -> None: + hold = await async_client.zones.holds.edit( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + hold_after="2023-01-31T15:56:36+00:00", + include_subdomains=True, + ) + assert_matches_type(ZoneHold, hold, path=["response"]) + + @parametrize + async def test_raw_response_edit(self, async_client: AsyncCloudflare) -> None: + response = await async_client.zones.holds.with_raw_response.edit( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = await response.parse() + assert_matches_type(ZoneHold, hold, path=["response"]) + + @parametrize + async def test_streaming_response_edit(self, async_client: AsyncCloudflare) -> None: + async with async_client.zones.holds.with_streaming_response.edit( + zone_id="023e105f4ecef8ad9ca31a8372d0c353", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = await response.parse() + assert_matches_type(ZoneHold, hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_edit(self, async_client: AsyncCloudflare) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"): + await async_client.zones.holds.with_raw_response.edit( + zone_id="", + ) + @parametrize async def test_method_get(self, async_client: AsyncCloudflare) -> None: hold = await async_client.zones.holds.get(