From 917114df90ac1938f819116c8f6595d93f0d96f8 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 30 Jan 2025 17:20:14 +0100 Subject: [PATCH 01/73] feat(webhosting): add public dns raw data (#837) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> --- scaleway-async/scaleway_async/webhosting/v1/marshalling.py | 4 ++++ scaleway-async/scaleway_async/webhosting/v1/types.py | 5 +++++ scaleway/scaleway/webhosting/v1/marshalling.py | 4 ++++ scaleway/scaleway/webhosting/v1/types.py | 5 +++++ 4 files changed, 18 insertions(+) diff --git a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py index 1c85301fe..6a43cdaac 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py +++ b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py @@ -185,6 +185,10 @@ def unmarshal_DnsRecord(data: Any) -> DnsRecord: if field is not None: args["status"] = field + field = data.get("raw_data", None) + if field is not None: + args["raw_data"] = field + field = data.get("priority", None) if field is not None: args["priority"] = field diff --git a/scaleway-async/scaleway_async/webhosting/v1/types.py b/scaleway-async/scaleway_async/webhosting/v1/types.py index 97a576899..3b3852f94 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/types.py +++ b/scaleway-async/scaleway_async/webhosting/v1/types.py @@ -312,6 +312,11 @@ class DnsRecord: Record status. """ + raw_data: str + """ + Record representation as it appears in the zone file or DNS management system. + """ + priority: Optional[int] """ Record priority level. diff --git a/scaleway/scaleway/webhosting/v1/marshalling.py b/scaleway/scaleway/webhosting/v1/marshalling.py index 1c85301fe..6a43cdaac 100644 --- a/scaleway/scaleway/webhosting/v1/marshalling.py +++ b/scaleway/scaleway/webhosting/v1/marshalling.py @@ -185,6 +185,10 @@ def unmarshal_DnsRecord(data: Any) -> DnsRecord: if field is not None: args["status"] = field + field = data.get("raw_data", None) + if field is not None: + args["raw_data"] = field + field = data.get("priority", None) if field is not None: args["priority"] = field diff --git a/scaleway/scaleway/webhosting/v1/types.py b/scaleway/scaleway/webhosting/v1/types.py index 97a576899..3b3852f94 100644 --- a/scaleway/scaleway/webhosting/v1/types.py +++ b/scaleway/scaleway/webhosting/v1/types.py @@ -312,6 +312,11 @@ class DnsRecord: Record status. """ + raw_data: str + """ + Record representation as it appears in the zone file or DNS management system. + """ + priority: Optional[int] """ Record priority level. From 814db6f041ab6f09db0c3e302070d236a717f15c Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 30 Jan 2025 17:26:21 +0100 Subject: [PATCH 02/73] doc(instance): deprecate policy_respected in Server (#838) --- scaleway-async/scaleway_async/instance/v1/types.py | 3 ++- scaleway/scaleway/instance/v1/types.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/scaleway-async/scaleway_async/instance/v1/types.py b/scaleway-async/scaleway_async/instance/v1/types.py index f06dabea0..f4770f9eb 100644 --- a/scaleway-async/scaleway_async/instance/v1/types.py +++ b/scaleway-async/scaleway_async/instance/v1/types.py @@ -516,7 +516,8 @@ class PlacementGroup: policy_respected: bool """ - Returns true if the policy is respected, false otherwise. + In the server endpoints the value is always false as it is deprecated. +In the placement group endpoints the value is correct. """ zone: ScwZone diff --git a/scaleway/scaleway/instance/v1/types.py b/scaleway/scaleway/instance/v1/types.py index f06dabea0..f4770f9eb 100644 --- a/scaleway/scaleway/instance/v1/types.py +++ b/scaleway/scaleway/instance/v1/types.py @@ -516,7 +516,8 @@ class PlacementGroup: policy_respected: bool """ - Returns true if the policy is respected, false otherwise. + In the server endpoints the value is always false as it is deprecated. +In the placement group endpoints the value is correct. """ zone: ScwZone From d21823fa081925b2dbca8b5efce17eda32816550 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 30 Jan 2025 17:29:44 +0100 Subject: [PATCH 03/73] feat(interlink): add disapproved reason to link (#839) --- .../scaleway_async/interlink/v1beta1/marshalling.py | 6 ++++++ scaleway-async/scaleway_async/interlink/v1beta1/types.py | 5 +++++ scaleway/scaleway/interlink/v1beta1/marshalling.py | 6 ++++++ scaleway/scaleway/interlink/v1beta1/types.py | 5 +++++ 4 files changed, 22 insertions(+) diff --git a/scaleway-async/scaleway_async/interlink/v1beta1/marshalling.py b/scaleway-async/scaleway_async/interlink/v1beta1/marshalling.py index b78b208fa..d8b2c084b 100644 --- a/scaleway-async/scaleway_async/interlink/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/interlink/v1beta1/marshalling.py @@ -117,6 +117,12 @@ def unmarshal_Link(data: Any) -> Link: else: args["updated_at"] = None + field = data.get("disapproved_reason", None) + if field is not None: + args["disapproved_reason"] = field + else: + args["disapproved_reason"] = None + return Link(**args) diff --git a/scaleway-async/scaleway_async/interlink/v1beta1/types.py b/scaleway-async/scaleway_async/interlink/v1beta1/types.py index a45046c73..6731f71d9 100644 --- a/scaleway-async/scaleway_async/interlink/v1beta1/types.py +++ b/scaleway-async/scaleway_async/interlink/v1beta1/types.py @@ -173,6 +173,11 @@ class Link: Last modification date of the link. """ + disapproved_reason: Optional[str] + """ + Reason given by partner to explain why they did not approve the request for a hosted link. + """ + @dataclass class Partner: diff --git a/scaleway/scaleway/interlink/v1beta1/marshalling.py b/scaleway/scaleway/interlink/v1beta1/marshalling.py index b78b208fa..d8b2c084b 100644 --- a/scaleway/scaleway/interlink/v1beta1/marshalling.py +++ b/scaleway/scaleway/interlink/v1beta1/marshalling.py @@ -117,6 +117,12 @@ def unmarshal_Link(data: Any) -> Link: else: args["updated_at"] = None + field = data.get("disapproved_reason", None) + if field is not None: + args["disapproved_reason"] = field + else: + args["disapproved_reason"] = None + return Link(**args) diff --git a/scaleway/scaleway/interlink/v1beta1/types.py b/scaleway/scaleway/interlink/v1beta1/types.py index a45046c73..6731f71d9 100644 --- a/scaleway/scaleway/interlink/v1beta1/types.py +++ b/scaleway/scaleway/interlink/v1beta1/types.py @@ -173,6 +173,11 @@ class Link: Last modification date of the link. """ + disapproved_reason: Optional[str] + """ + Reason given by partner to explain why they did not approve the request for a hosted link. + """ + @dataclass class Partner: From c12529a0c2c4b98ada420ed620f23e5ce4c679d9 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 30 Jan 2025 17:30:58 +0100 Subject: [PATCH 04/73] feat(vpc/v2): deprecate ineffectual vpc.v2.Api.MigrateZonalPrivateNetworks call (#840) --- scaleway-async/scaleway_async/vpc/v2/api.py | 1 + scaleway/scaleway/vpc/v2/api.py | 1 + 2 files changed, 2 insertions(+) diff --git a/scaleway-async/scaleway_async/vpc/v2/api.py b/scaleway-async/scaleway_async/vpc/v2/api.py index 5e7325f09..ef974c64d 100644 --- a/scaleway-async/scaleway_async/vpc/v2/api.py +++ b/scaleway-async/scaleway_async/vpc/v2/api.py @@ -643,6 +643,7 @@ async def migrate_zonal_private_networks( :param project_id: Project to target. The specified zoned Private Networks within this Project will be migrated to regional. One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. :param private_network_ids: IDs of the Private Networks to migrate. + :deprecated Usage: :: diff --git a/scaleway/scaleway/vpc/v2/api.py b/scaleway/scaleway/vpc/v2/api.py index 06c9df860..1ab54d2de 100644 --- a/scaleway/scaleway/vpc/v2/api.py +++ b/scaleway/scaleway/vpc/v2/api.py @@ -643,6 +643,7 @@ def migrate_zonal_private_networks( :param project_id: Project to target. The specified zoned Private Networks within this Project will be migrated to regional. One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. :param private_network_ids: IDs of the Private Networks to migrate. + :deprecated Usage: :: From a0ad435824ed00c5cb40699e0c44136cbc46c227 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 30 Jan 2025 17:33:27 +0100 Subject: [PATCH 05/73] feat(iam): return localized quota (#841) --- .../scaleway_async/iam/v1alpha1/__init__.py | 4 ++ .../iam/v1alpha1/marshalling.py | 52 +++++++++++++++++++ .../scaleway_async/iam/v1alpha1/types.py | 36 +++++++++++++ scaleway/scaleway/iam/v1alpha1/__init__.py | 4 ++ scaleway/scaleway/iam/v1alpha1/marshalling.py | 52 +++++++++++++++++++ scaleway/scaleway/iam/v1alpha1/types.py | 36 +++++++++++++ 6 files changed, 184 insertions(+) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py index 3837eaf02..edb257bad 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py @@ -12,11 +12,13 @@ from .types import ListQuotaRequestOrderBy from .types import ListSSHKeysRequestOrderBy from .types import ListUsersRequestOrderBy +from .types import LocalityType from .types import LogAction from .types import LogResourceType from .types import PermissionSetScopeType from .types import UserStatus from .types import UserType +from .types import QuotumLimit from .types import JWT from .types import RuleSpecs from .types import CreateUserRequestMember @@ -119,11 +121,13 @@ "ListQuotaRequestOrderBy", "ListSSHKeysRequestOrderBy", "ListUsersRequestOrderBy", + "LocalityType", "LogAction", "LogResourceType", "PermissionSetScopeType", "UserStatus", "UserType", + "QuotumLimit", "JWT", "RuleSpecs", "CreateUserRequestMember", diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py index 09ce69f0a..c6a9ef1eb 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py @@ -16,6 +16,7 @@ Group, Log, Policy, + QuotumLimit, Quotum, SSHKey, User, @@ -452,6 +453,47 @@ def unmarshal_Policy(data: Any) -> Policy: return Policy(**args) +def unmarshal_QuotumLimit(data: Any) -> QuotumLimit: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QuotumLimit' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("global", None) + if field is not None: + args["global_"] = field + else: + args["global_"] = None + + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("limit", None) + if field is not None: + args["limit"] = field + else: + args["limit"] = None + + field = data.get("unlimited", None) + if field is not None: + args["unlimited"] = field + else: + args["unlimited"] = None + + return QuotumLimit(**args) + + def unmarshal_Quotum(data: Any) -> Quotum: if not isinstance(data, dict): raise TypeError( @@ -476,6 +518,16 @@ def unmarshal_Quotum(data: Any) -> Quotum: if field is not None: args["description"] = field + field = data.get("locality_type", None) + if field is not None: + args["locality_type"] = field + + field = data.get("limits", None) + if field is not None: + args["limits"] = ( + [unmarshal_QuotumLimit(v) for v in field] if field is not None else None + ) + field = data.get("limit", None) if field is not None: args["limit"] = field diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/types.py b/scaleway-async/scaleway_async/iam/v1alpha1/types.py index 6f2adc3f9..571ee9ac8 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/types.py @@ -7,6 +7,10 @@ from enum import Enum from typing import List, Optional +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) from scaleway_core.utils import ( StrEnumMeta, ) @@ -142,6 +146,15 @@ def __str__(self) -> str: return str(self.value) +class LocalityType(str, Enum, metaclass=StrEnumMeta): + GLOBAL = "global" + REGION = "region" + ZONE = "zone" + + def __str__(self) -> str: + return str(self.value) + + class LogAction(str, Enum, metaclass=StrEnumMeta): UNKNOWN_ACTION = "unknown_action" CREATED = "created" @@ -193,6 +206,19 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class QuotumLimit: + global_: Optional[bool] + + region: Optional[ScwRegion] + + zone: Optional[ScwZone] + + limit: Optional[int] + + unlimited: Optional[bool] + + @dataclass class JWT: jti: str @@ -656,6 +682,16 @@ class Quotum: Details about the quota. """ + locality_type: LocalityType + """ + Whether this quotum is applied on at the zone level, region level, or globally. + """ + + limits: List[QuotumLimit] + """ + Limits per locality. + """ + limit: Optional[int] unlimited: Optional[bool] diff --git a/scaleway/scaleway/iam/v1alpha1/__init__.py b/scaleway/scaleway/iam/v1alpha1/__init__.py index 3837eaf02..edb257bad 100644 --- a/scaleway/scaleway/iam/v1alpha1/__init__.py +++ b/scaleway/scaleway/iam/v1alpha1/__init__.py @@ -12,11 +12,13 @@ from .types import ListQuotaRequestOrderBy from .types import ListSSHKeysRequestOrderBy from .types import ListUsersRequestOrderBy +from .types import LocalityType from .types import LogAction from .types import LogResourceType from .types import PermissionSetScopeType from .types import UserStatus from .types import UserType +from .types import QuotumLimit from .types import JWT from .types import RuleSpecs from .types import CreateUserRequestMember @@ -119,11 +121,13 @@ "ListQuotaRequestOrderBy", "ListSSHKeysRequestOrderBy", "ListUsersRequestOrderBy", + "LocalityType", "LogAction", "LogResourceType", "PermissionSetScopeType", "UserStatus", "UserType", + "QuotumLimit", "JWT", "RuleSpecs", "CreateUserRequestMember", diff --git a/scaleway/scaleway/iam/v1alpha1/marshalling.py b/scaleway/scaleway/iam/v1alpha1/marshalling.py index 09ce69f0a..c6a9ef1eb 100644 --- a/scaleway/scaleway/iam/v1alpha1/marshalling.py +++ b/scaleway/scaleway/iam/v1alpha1/marshalling.py @@ -16,6 +16,7 @@ Group, Log, Policy, + QuotumLimit, Quotum, SSHKey, User, @@ -452,6 +453,47 @@ def unmarshal_Policy(data: Any) -> Policy: return Policy(**args) +def unmarshal_QuotumLimit(data: Any) -> QuotumLimit: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QuotumLimit' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("global", None) + if field is not None: + args["global_"] = field + else: + args["global_"] = None + + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("limit", None) + if field is not None: + args["limit"] = field + else: + args["limit"] = None + + field = data.get("unlimited", None) + if field is not None: + args["unlimited"] = field + else: + args["unlimited"] = None + + return QuotumLimit(**args) + + def unmarshal_Quotum(data: Any) -> Quotum: if not isinstance(data, dict): raise TypeError( @@ -476,6 +518,16 @@ def unmarshal_Quotum(data: Any) -> Quotum: if field is not None: args["description"] = field + field = data.get("locality_type", None) + if field is not None: + args["locality_type"] = field + + field = data.get("limits", None) + if field is not None: + args["limits"] = ( + [unmarshal_QuotumLimit(v) for v in field] if field is not None else None + ) + field = data.get("limit", None) if field is not None: args["limit"] = field diff --git a/scaleway/scaleway/iam/v1alpha1/types.py b/scaleway/scaleway/iam/v1alpha1/types.py index 6f2adc3f9..571ee9ac8 100644 --- a/scaleway/scaleway/iam/v1alpha1/types.py +++ b/scaleway/scaleway/iam/v1alpha1/types.py @@ -7,6 +7,10 @@ from enum import Enum from typing import List, Optional +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) from scaleway_core.utils import ( StrEnumMeta, ) @@ -142,6 +146,15 @@ def __str__(self) -> str: return str(self.value) +class LocalityType(str, Enum, metaclass=StrEnumMeta): + GLOBAL = "global" + REGION = "region" + ZONE = "zone" + + def __str__(self) -> str: + return str(self.value) + + class LogAction(str, Enum, metaclass=StrEnumMeta): UNKNOWN_ACTION = "unknown_action" CREATED = "created" @@ -193,6 +206,19 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class QuotumLimit: + global_: Optional[bool] + + region: Optional[ScwRegion] + + zone: Optional[ScwZone] + + limit: Optional[int] + + unlimited: Optional[bool] + + @dataclass class JWT: jti: str @@ -656,6 +682,16 @@ class Quotum: Details about the quota. """ + locality_type: LocalityType + """ + Whether this quotum is applied on at the zone level, region level, or globally. + """ + + limits: List[QuotumLimit] + """ + Limits per locality. + """ + limit: Optional[int] unlimited: Optional[bool] From 13b5b236e8289149f812fdaab769257e93c5f22b Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 30 Jan 2025 17:39:10 +0100 Subject: [PATCH 06/73] feat(vpc/v2): drop MigrateZonalPrivateNetworks (#843) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jules Castéran --- .../scaleway_async/vpc/v2/__init__.py | 2 - scaleway-async/scaleway_async/vpc/v2/api.py | 47 ------------------- .../scaleway_async/vpc/v2/marshalling.py | 31 ------------ scaleway-async/scaleway_async/vpc/v2/types.py | 17 ------- scaleway/scaleway/vpc/v2/__init__.py | 2 - scaleway/scaleway/vpc/v2/api.py | 47 ------------------- scaleway/scaleway/vpc/v2/marshalling.py | 31 ------------ scaleway/scaleway/vpc/v2/types.py | 17 ------- 8 files changed, 194 deletions(-) diff --git a/scaleway-async/scaleway_async/vpc/v2/__init__.py b/scaleway-async/scaleway_async/vpc/v2/__init__.py index 813f24148..6d334b94c 100644 --- a/scaleway-async/scaleway_async/vpc/v2/__init__.py +++ b/scaleway-async/scaleway_async/vpc/v2/__init__.py @@ -28,7 +28,6 @@ from .types import ListSubnetsResponse from .types import ListVPCsRequest from .types import ListVPCsResponse -from .types import MigrateZonalPrivateNetworksRequest from .types import SetSubnetsRequest from .types import SetSubnetsResponse from .types import UpdatePrivateNetworkRequest @@ -65,7 +64,6 @@ "ListSubnetsResponse", "ListVPCsRequest", "ListVPCsResponse", - "MigrateZonalPrivateNetworksRequest", "SetSubnetsRequest", "SetSubnetsResponse", "UpdatePrivateNetworkRequest", diff --git a/scaleway-async/scaleway_async/vpc/v2/api.py b/scaleway-async/scaleway_async/vpc/v2/api.py index ef974c64d..fb3b7fdff 100644 --- a/scaleway-async/scaleway_async/vpc/v2/api.py +++ b/scaleway-async/scaleway_async/vpc/v2/api.py @@ -26,7 +26,6 @@ ListPrivateNetworksResponse, ListSubnetsResponse, ListVPCsResponse, - MigrateZonalPrivateNetworksRequest, PrivateNetwork, Route, SetSubnetsRequest, @@ -52,7 +51,6 @@ marshal_CreateRouteRequest, marshal_CreateVPCRequest, marshal_DeleteSubnetsRequest, - marshal_MigrateZonalPrivateNetworksRequest, marshal_SetSubnetsRequest, marshal_UpdatePrivateNetworkRequest, marshal_UpdateRouteRequest, @@ -626,51 +624,6 @@ async def delete_private_network( self._throw_on_error(res) - async def migrate_zonal_private_networks( - self, - *, - region: Optional[ScwRegion] = None, - organization_id: Optional[str] = None, - project_id: Optional[str] = None, - private_network_ids: Optional[List[str]] = None, - ) -> None: - """ - Migrate Private Networks from zoned to regional. - Transform multiple existing zoned Private Networks (scoped to a single Availability Zone) into regional Private Networks, scoped to an entire region. You can transform one or many Private Networks (specified by their Private Network IDs) within a single Scaleway Organization or Project, with the same call. - :param region: Region to target. If none is passed will use default region from the config. - :param organization_id: Organization ID to target. The specified zoned Private Networks within this Organization will be migrated to regional. - One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. - :param project_id: Project to target. The specified zoned Private Networks within this Project will be migrated to regional. - One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. - :param private_network_ids: IDs of the Private Networks to migrate. - :deprecated - - Usage: - :: - - result = await api.migrate_zonal_private_networks() - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - - res = self._request( - "POST", - f"/vpc/v2/regions/{param_region}/private-networks/migrate-zonal", - body=marshal_MigrateZonalPrivateNetworksRequest( - MigrateZonalPrivateNetworksRequest( - region=region, - private_network_ids=private_network_ids, - organization_id=organization_id, - project_id=project_id, - ), - self.client, - ), - ) - - self._throw_on_error(res) - async def enable_dhcp( self, *, diff --git a/scaleway-async/scaleway_async/vpc/v2/marshalling.py b/scaleway-async/scaleway_async/vpc/v2/marshalling.py index db1733c25..2d8334fa0 100644 --- a/scaleway-async/scaleway_async/vpc/v2/marshalling.py +++ b/scaleway-async/scaleway_async/vpc/v2/marshalling.py @@ -5,10 +5,6 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults -from scaleway_core.utils import ( - OneOfPossibility, - resolve_one_of, -) from .types import ( Subnet, PrivateNetwork, @@ -25,7 +21,6 @@ CreateRouteRequest, CreateVPCRequest, DeleteSubnetsRequest, - MigrateZonalPrivateNetworksRequest, SetSubnetsRequest, UpdatePrivateNetworkRequest, UpdateRouteRequest, @@ -461,32 +456,6 @@ def marshal_DeleteSubnetsRequest( return output -def marshal_MigrateZonalPrivateNetworksRequest( - request: MigrateZonalPrivateNetworksRequest, - defaults: ProfileDefaults, -) -> Dict[str, Any]: - output: Dict[str, Any] = {} - output.update( - resolve_one_of( - [ - OneOfPossibility( - "organization_id", - request.organization_id, - defaults.default_organization_id, - ), - OneOfPossibility( - "project_id", request.project_id, defaults.default_project_id - ), - ] - ), - ) - - if request.private_network_ids is not None: - output["private_network_ids"] = request.private_network_ids - - return output - - def marshal_SetSubnetsRequest( request: SetSubnetsRequest, defaults: ProfileDefaults, diff --git a/scaleway-async/scaleway_async/vpc/v2/types.py b/scaleway-async/scaleway_async/vpc/v2/types.py index 665091b87..c74bcc528 100644 --- a/scaleway-async/scaleway_async/vpc/v2/types.py +++ b/scaleway-async/scaleway_async/vpc/v2/types.py @@ -679,23 +679,6 @@ class ListVPCsResponse: total_count: int -@dataclass -class MigrateZonalPrivateNetworksRequest: - region: Optional[ScwRegion] - """ - Region to target. If none is passed will use default region from the config. - """ - - private_network_ids: Optional[List[str]] - """ - IDs of the Private Networks to migrate. - """ - - organization_id: Optional[str] - - project_id: Optional[str] - - @dataclass class SetSubnetsRequest: private_network_id: str diff --git a/scaleway/scaleway/vpc/v2/__init__.py b/scaleway/scaleway/vpc/v2/__init__.py index 813f24148..6d334b94c 100644 --- a/scaleway/scaleway/vpc/v2/__init__.py +++ b/scaleway/scaleway/vpc/v2/__init__.py @@ -28,7 +28,6 @@ from .types import ListSubnetsResponse from .types import ListVPCsRequest from .types import ListVPCsResponse -from .types import MigrateZonalPrivateNetworksRequest from .types import SetSubnetsRequest from .types import SetSubnetsResponse from .types import UpdatePrivateNetworkRequest @@ -65,7 +64,6 @@ "ListSubnetsResponse", "ListVPCsRequest", "ListVPCsResponse", - "MigrateZonalPrivateNetworksRequest", "SetSubnetsRequest", "SetSubnetsResponse", "UpdatePrivateNetworkRequest", diff --git a/scaleway/scaleway/vpc/v2/api.py b/scaleway/scaleway/vpc/v2/api.py index 1ab54d2de..2932decbe 100644 --- a/scaleway/scaleway/vpc/v2/api.py +++ b/scaleway/scaleway/vpc/v2/api.py @@ -26,7 +26,6 @@ ListPrivateNetworksResponse, ListSubnetsResponse, ListVPCsResponse, - MigrateZonalPrivateNetworksRequest, PrivateNetwork, Route, SetSubnetsRequest, @@ -52,7 +51,6 @@ marshal_CreateRouteRequest, marshal_CreateVPCRequest, marshal_DeleteSubnetsRequest, - marshal_MigrateZonalPrivateNetworksRequest, marshal_SetSubnetsRequest, marshal_UpdatePrivateNetworkRequest, marshal_UpdateRouteRequest, @@ -626,51 +624,6 @@ def delete_private_network( self._throw_on_error(res) - def migrate_zonal_private_networks( - self, - *, - region: Optional[ScwRegion] = None, - organization_id: Optional[str] = None, - project_id: Optional[str] = None, - private_network_ids: Optional[List[str]] = None, - ) -> None: - """ - Migrate Private Networks from zoned to regional. - Transform multiple existing zoned Private Networks (scoped to a single Availability Zone) into regional Private Networks, scoped to an entire region. You can transform one or many Private Networks (specified by their Private Network IDs) within a single Scaleway Organization or Project, with the same call. - :param region: Region to target. If none is passed will use default region from the config. - :param organization_id: Organization ID to target. The specified zoned Private Networks within this Organization will be migrated to regional. - One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. - :param project_id: Project to target. The specified zoned Private Networks within this Project will be migrated to regional. - One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. - :param private_network_ids: IDs of the Private Networks to migrate. - :deprecated - - Usage: - :: - - result = api.migrate_zonal_private_networks() - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - - res = self._request( - "POST", - f"/vpc/v2/regions/{param_region}/private-networks/migrate-zonal", - body=marshal_MigrateZonalPrivateNetworksRequest( - MigrateZonalPrivateNetworksRequest( - region=region, - private_network_ids=private_network_ids, - organization_id=organization_id, - project_id=project_id, - ), - self.client, - ), - ) - - self._throw_on_error(res) - def enable_dhcp( self, *, diff --git a/scaleway/scaleway/vpc/v2/marshalling.py b/scaleway/scaleway/vpc/v2/marshalling.py index db1733c25..2d8334fa0 100644 --- a/scaleway/scaleway/vpc/v2/marshalling.py +++ b/scaleway/scaleway/vpc/v2/marshalling.py @@ -5,10 +5,6 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults -from scaleway_core.utils import ( - OneOfPossibility, - resolve_one_of, -) from .types import ( Subnet, PrivateNetwork, @@ -25,7 +21,6 @@ CreateRouteRequest, CreateVPCRequest, DeleteSubnetsRequest, - MigrateZonalPrivateNetworksRequest, SetSubnetsRequest, UpdatePrivateNetworkRequest, UpdateRouteRequest, @@ -461,32 +456,6 @@ def marshal_DeleteSubnetsRequest( return output -def marshal_MigrateZonalPrivateNetworksRequest( - request: MigrateZonalPrivateNetworksRequest, - defaults: ProfileDefaults, -) -> Dict[str, Any]: - output: Dict[str, Any] = {} - output.update( - resolve_one_of( - [ - OneOfPossibility( - "organization_id", - request.organization_id, - defaults.default_organization_id, - ), - OneOfPossibility( - "project_id", request.project_id, defaults.default_project_id - ), - ] - ), - ) - - if request.private_network_ids is not None: - output["private_network_ids"] = request.private_network_ids - - return output - - def marshal_SetSubnetsRequest( request: SetSubnetsRequest, defaults: ProfileDefaults, diff --git a/scaleway/scaleway/vpc/v2/types.py b/scaleway/scaleway/vpc/v2/types.py index 665091b87..c74bcc528 100644 --- a/scaleway/scaleway/vpc/v2/types.py +++ b/scaleway/scaleway/vpc/v2/types.py @@ -679,23 +679,6 @@ class ListVPCsResponse: total_count: int -@dataclass -class MigrateZonalPrivateNetworksRequest: - region: Optional[ScwRegion] - """ - Region to target. If none is passed will use default region from the config. - """ - - private_network_ids: Optional[List[str]] - """ - IDs of the Private Networks to migrate. - """ - - organization_id: Optional[str] - - project_id: Optional[str] - - @dataclass class SetSubnetsRequest: private_network_id: str From aab3db3ccd67a59023e9be1bc971f84466786740 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 10:21:33 +0100 Subject: [PATCH 07/73] chore(deps-dev): bump ruff from 0.8.4 to 0.9.4 in /scaleway (#847) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scaleway/poetry.lock | 42 ++++++++++++++++++++--------------------- scaleway/pyproject.toml | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/scaleway/poetry.lock b/scaleway/poetry.lock index 52c2b7e34..4becc0599 100644 --- a/scaleway/poetry.lock +++ b/scaleway/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "certifi" @@ -295,29 +295,29 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.8.4" +version = "0.9.4" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"}, - {file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"}, - {file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"}, - {file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"}, - {file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"}, - {file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"}, - {file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"}, + {file = "ruff-0.9.4-py3-none-linux_armv6l.whl", hash = "sha256:64e73d25b954f71ff100bb70f39f1ee09e880728efb4250c632ceed4e4cdf706"}, + {file = "ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6ce6743ed64d9afab4fafeaea70d3631b4d4b28b592db21a5c2d1f0ef52934bf"}, + {file = "ruff-0.9.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54499fb08408e32b57360f6f9de7157a5fec24ad79cb3f42ef2c3f3f728dfe2b"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37c892540108314a6f01f105040b5106aeb829fa5fb0561d2dcaf71485021137"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de9edf2ce4b9ddf43fd93e20ef635a900e25f622f87ed6e3047a664d0e8f810e"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87c90c32357c74f11deb7fbb065126d91771b207bf9bfaaee01277ca59b574ec"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56acd6c694da3695a7461cc55775f3a409c3815ac467279dfa126061d84b314b"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0c93e7d47ed951b9394cf352d6695b31498e68fd5782d6cbc282425655f687a"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d4c8772670aecf037d1bf7a07c39106574d143b26cfe5ed1787d2f31e800214"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfc5f1d7afeda8d5d37660eeca6d389b142d7f2b5a1ab659d9214ebd0e025231"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:faa935fc00ae854d8b638c16a5f1ce881bc3f67446957dd6f2af440a5fc8526b"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6c634fc6f5a0ceae1ab3e13c58183978185d131a29c425e4eaa9f40afe1e6d6"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:433dedf6ddfdec7f1ac7575ec1eb9844fa60c4c8c2f8887a070672b8d353d34c"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d612dbd0f3a919a8cc1d12037168bfa536862066808960e0cc901404b77968f0"}, + {file = "ruff-0.9.4-py3-none-win32.whl", hash = "sha256:db1192ddda2200671f9ef61d9597fcef89d934f5d1705e571a93a67fb13a4402"}, + {file = "ruff-0.9.4-py3-none-win_amd64.whl", hash = "sha256:05bebf4cdbe3ef75430d26c375773978950bbf4ee3c95ccb5448940dc092408e"}, + {file = "ruff-0.9.4-py3-none-win_arm64.whl", hash = "sha256:585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41"}, + {file = "ruff-0.9.4.tar.gz", hash = "sha256:6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7"}, ] [[package]] @@ -421,4 +421,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = ">=3.10" -content-hash = "6f3ba5275f7b3eb4c3d480a0b7fe7e95fd6a816d9c1d0cfd96a6d4c61a0d09e0" +content-hash = "4f889abfd75a3d01edf436c44008a6e0adf7a5442f9fa02870e693751444211c" diff --git a/scaleway/pyproject.toml b/scaleway/pyproject.toml index 9121fa570..5e70af020 100644 --- a/scaleway/pyproject.toml +++ b/scaleway/pyproject.toml @@ -28,7 +28,7 @@ scaleway-core = "*" [tool.poetry.group.dev.dependencies] scaleway-core = { path = "../scaleway-core", develop = true } -ruff = ">=0.5.0,<0.8.5" +ruff = ">=0.5.0,<0.9.5" mypy = "^1.5.1" [build-system] From 110a74a39b512fd75ba107909271093dc0b80692 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:22:03 +0000 Subject: [PATCH 08/73] chore(deps-dev): bump ruff from 0.8.4 to 0.9.4 in /scaleway-core (#846) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scaleway-core/poetry.lock | 42 ++++++++++++++++++------------------ scaleway-core/pyproject.toml | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/scaleway-core/poetry.lock b/scaleway-core/poetry.lock index 8f8961626..b78913605 100644 --- a/scaleway-core/poetry.lock +++ b/scaleway-core/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "certifi" @@ -295,29 +295,29 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.8.4" +version = "0.9.4" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"}, - {file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"}, - {file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"}, - {file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"}, - {file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"}, - {file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"}, - {file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"}, + {file = "ruff-0.9.4-py3-none-linux_armv6l.whl", hash = "sha256:64e73d25b954f71ff100bb70f39f1ee09e880728efb4250c632ceed4e4cdf706"}, + {file = "ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6ce6743ed64d9afab4fafeaea70d3631b4d4b28b592db21a5c2d1f0ef52934bf"}, + {file = "ruff-0.9.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54499fb08408e32b57360f6f9de7157a5fec24ad79cb3f42ef2c3f3f728dfe2b"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37c892540108314a6f01f105040b5106aeb829fa5fb0561d2dcaf71485021137"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de9edf2ce4b9ddf43fd93e20ef635a900e25f622f87ed6e3047a664d0e8f810e"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87c90c32357c74f11deb7fbb065126d91771b207bf9bfaaee01277ca59b574ec"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56acd6c694da3695a7461cc55775f3a409c3815ac467279dfa126061d84b314b"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0c93e7d47ed951b9394cf352d6695b31498e68fd5782d6cbc282425655f687a"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d4c8772670aecf037d1bf7a07c39106574d143b26cfe5ed1787d2f31e800214"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfc5f1d7afeda8d5d37660eeca6d389b142d7f2b5a1ab659d9214ebd0e025231"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:faa935fc00ae854d8b638c16a5f1ce881bc3f67446957dd6f2af440a5fc8526b"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6c634fc6f5a0ceae1ab3e13c58183978185d131a29c425e4eaa9f40afe1e6d6"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:433dedf6ddfdec7f1ac7575ec1eb9844fa60c4c8c2f8887a070672b8d353d34c"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d612dbd0f3a919a8cc1d12037168bfa536862066808960e0cc901404b77968f0"}, + {file = "ruff-0.9.4-py3-none-win32.whl", hash = "sha256:db1192ddda2200671f9ef61d9597fcef89d934f5d1705e571a93a67fb13a4402"}, + {file = "ruff-0.9.4-py3-none-win_amd64.whl", hash = "sha256:05bebf4cdbe3ef75430d26c375773978950bbf4ee3c95ccb5448940dc092408e"}, + {file = "ruff-0.9.4-py3-none-win_arm64.whl", hash = "sha256:585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41"}, + {file = "ruff-0.9.4.tar.gz", hash = "sha256:6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7"}, ] [[package]] @@ -414,4 +414,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = ">=3.10" -content-hash = "61d79741b65f81f6ae1e8cbf7c9e9f18fd949cba49e6773131a020ffab7068a9" +content-hash = "8e35e388293ecef04cfd670afdbb275aeb8f4a4563b0706902e76a70f1dae669" diff --git a/scaleway-core/pyproject.toml b/scaleway-core/pyproject.toml index 7e2b5ca67..c9a0bd39b 100644 --- a/scaleway-core/pyproject.toml +++ b/scaleway-core/pyproject.toml @@ -30,7 +30,7 @@ python-dateutil = "^2.8.2" [tool.poetry.group.dev.dependencies] types-python-dateutil = "^2.8.19" -ruff = ">=0.5.0,<0.8.5" +ruff = ">=0.5.0,<0.9.5" mypy = "^1.5.1" [build-system] From fdfe7aa02f0eb37cea92e520820fbbb66a8802eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:22:23 +0000 Subject: [PATCH 09/73] chore(deps-dev): bump ruff from 0.8.4 to 0.9.4 in /scaleway-async (#845) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scaleway-async/poetry.lock | 42 +++++++++++++++++------------------ scaleway-async/pyproject.toml | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/scaleway-async/poetry.lock b/scaleway-async/poetry.lock index 52c2b7e34..4becc0599 100644 --- a/scaleway-async/poetry.lock +++ b/scaleway-async/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "certifi" @@ -295,29 +295,29 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.8.4" +version = "0.9.4" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"}, - {file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"}, - {file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"}, - {file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"}, - {file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"}, - {file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"}, - {file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"}, + {file = "ruff-0.9.4-py3-none-linux_armv6l.whl", hash = "sha256:64e73d25b954f71ff100bb70f39f1ee09e880728efb4250c632ceed4e4cdf706"}, + {file = "ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6ce6743ed64d9afab4fafeaea70d3631b4d4b28b592db21a5c2d1f0ef52934bf"}, + {file = "ruff-0.9.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54499fb08408e32b57360f6f9de7157a5fec24ad79cb3f42ef2c3f3f728dfe2b"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37c892540108314a6f01f105040b5106aeb829fa5fb0561d2dcaf71485021137"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de9edf2ce4b9ddf43fd93e20ef635a900e25f622f87ed6e3047a664d0e8f810e"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87c90c32357c74f11deb7fbb065126d91771b207bf9bfaaee01277ca59b574ec"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56acd6c694da3695a7461cc55775f3a409c3815ac467279dfa126061d84b314b"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0c93e7d47ed951b9394cf352d6695b31498e68fd5782d6cbc282425655f687a"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d4c8772670aecf037d1bf7a07c39106574d143b26cfe5ed1787d2f31e800214"}, + {file = "ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfc5f1d7afeda8d5d37660eeca6d389b142d7f2b5a1ab659d9214ebd0e025231"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:faa935fc00ae854d8b638c16a5f1ce881bc3f67446957dd6f2af440a5fc8526b"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6c634fc6f5a0ceae1ab3e13c58183978185d131a29c425e4eaa9f40afe1e6d6"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:433dedf6ddfdec7f1ac7575ec1eb9844fa60c4c8c2f8887a070672b8d353d34c"}, + {file = "ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d612dbd0f3a919a8cc1d12037168bfa536862066808960e0cc901404b77968f0"}, + {file = "ruff-0.9.4-py3-none-win32.whl", hash = "sha256:db1192ddda2200671f9ef61d9597fcef89d934f5d1705e571a93a67fb13a4402"}, + {file = "ruff-0.9.4-py3-none-win_amd64.whl", hash = "sha256:05bebf4cdbe3ef75430d26c375773978950bbf4ee3c95ccb5448940dc092408e"}, + {file = "ruff-0.9.4-py3-none-win_arm64.whl", hash = "sha256:585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41"}, + {file = "ruff-0.9.4.tar.gz", hash = "sha256:6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7"}, ] [[package]] @@ -421,4 +421,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = ">=3.10" -content-hash = "6f3ba5275f7b3eb4c3d480a0b7fe7e95fd6a816d9c1d0cfd96a6d4c61a0d09e0" +content-hash = "4f889abfd75a3d01edf436c44008a6e0adf7a5442f9fa02870e693751444211c" diff --git a/scaleway-async/pyproject.toml b/scaleway-async/pyproject.toml index a8dbafaee..8375e9e33 100644 --- a/scaleway-async/pyproject.toml +++ b/scaleway-async/pyproject.toml @@ -28,7 +28,7 @@ scaleway-core = "*" [tool.poetry.group.dev.dependencies] scaleway-core = { path = "../scaleway-core", develop = true } -ruff = ">=0.5.0,<0.8.5" +ruff = ">=0.5.0,<0.9.5" mypy = "^1.5.1" [build-system] From 461ac3799394e2c02a6cf34be0152e1feed34e43 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 3 Feb 2025 10:22:49 +0100 Subject: [PATCH 10/73] chore: remove nat from documentation (#844) --- scaleway-async/scaleway_async/instance/v1/api.py | 8 ++++---- scaleway-async/scaleway_async/instance/v1/types.py | 7 +++---- scaleway/scaleway/instance/v1/api.py | 8 ++++---- scaleway/scaleway/instance/v1/types.py | 7 +++---- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/scaleway-async/scaleway_async/instance/v1/api.py b/scaleway-async/scaleway_async/instance/v1/api.py index 0871eca8f..e7da5e4b0 100644 --- a/scaleway-async/scaleway_async/instance/v1/api.py +++ b/scaleway-async/scaleway_async/instance/v1/api.py @@ -3445,7 +3445,7 @@ async def list_ips( :param name: Filter on the IP address (Works as a LIKE operation on the IP address). :param per_page: A positive integer lower or equal to 100 to select the number of items to return. :param page: A positive integer to choose the page to return. - :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4', 'routed_ipv6' or 'nat'). + :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`ListIpsResponse ` Usage: @@ -3495,7 +3495,7 @@ async def list_ips_all( :param name: Filter on the IP address (Works as a LIKE operation on the IP address). :param per_page: A positive integer lower or equal to 100 to select the number of items to return. :param page: A positive integer to choose the page to return. - :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4', 'routed_ipv6' or 'nat'). + :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`List[Ip] ` Usage: @@ -3540,7 +3540,7 @@ async def create_ip( One-Of ('project_identifier'): at most one of 'project', 'organization' could be set. :param tags: Tags of the IP. :param server: UUID of the Instance you want to attach the IP to. - :param type_: IP type to reserve (either 'routed_ipv4' or 'routed_ipv6', use of 'nat' is deprecated). + :param type_: IP type to reserve (either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`CreateIpResponse ` Usage: @@ -3618,7 +3618,7 @@ async def update_ip( :param ip: IP ID or IP address. :param zone: Zone to target. If none is passed will use default zone from the config. :param reverse: Reverse domain name. - :param type_: Convert a 'nat' IP to a 'routed_ipv4'. + :param type_: Should have no effect. :param tags: An array of keywords you want to tag this IP with. :param server: :return: :class:`UpdateIpResponse ` diff --git a/scaleway-async/scaleway_async/instance/v1/types.py b/scaleway-async/scaleway_async/instance/v1/types.py index f4770f9eb..c9c90e339 100644 --- a/scaleway-async/scaleway_async/instance/v1/types.py +++ b/scaleway-async/scaleway_async/instance/v1/types.py @@ -66,7 +66,6 @@ def __str__(self) -> str: class IpType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_IPTYPE = "unknown_iptype" - NAT = "nat" ROUTED_IPV4 = "routed_ipv4" ROUTED_IPV6 = "routed_ipv6" @@ -1579,7 +1578,7 @@ class CreateIpRequest: type_: Optional[IpType] """ - IP type to reserve (either 'routed_ipv4' or 'routed_ipv6', use of 'nat' is deprecated). + IP type to reserve (either 'routed_ipv4' or 'routed_ipv6'). """ project: Optional[str] @@ -2444,7 +2443,7 @@ class ListIpsRequest: type_: Optional[str] """ - Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4', 'routed_ipv6' or 'nat'). + Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). """ @@ -3180,7 +3179,7 @@ class UpdateIpRequest: type_: Optional[IpType] """ - Convert a 'nat' IP to a 'routed_ipv4'. + Should have no effect. """ tags: Optional[List[str]] diff --git a/scaleway/scaleway/instance/v1/api.py b/scaleway/scaleway/instance/v1/api.py index 2402114e7..c3b81a028 100644 --- a/scaleway/scaleway/instance/v1/api.py +++ b/scaleway/scaleway/instance/v1/api.py @@ -3445,7 +3445,7 @@ def list_ips( :param name: Filter on the IP address (Works as a LIKE operation on the IP address). :param per_page: A positive integer lower or equal to 100 to select the number of items to return. :param page: A positive integer to choose the page to return. - :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4', 'routed_ipv6' or 'nat'). + :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`ListIpsResponse ` Usage: @@ -3495,7 +3495,7 @@ def list_ips_all( :param name: Filter on the IP address (Works as a LIKE operation on the IP address). :param per_page: A positive integer lower or equal to 100 to select the number of items to return. :param page: A positive integer to choose the page to return. - :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4', 'routed_ipv6' or 'nat'). + :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`List[Ip] ` Usage: @@ -3540,7 +3540,7 @@ def create_ip( One-Of ('project_identifier'): at most one of 'project', 'organization' could be set. :param tags: Tags of the IP. :param server: UUID of the Instance you want to attach the IP to. - :param type_: IP type to reserve (either 'routed_ipv4' or 'routed_ipv6', use of 'nat' is deprecated). + :param type_: IP type to reserve (either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`CreateIpResponse ` Usage: @@ -3618,7 +3618,7 @@ def update_ip( :param ip: IP ID or IP address. :param zone: Zone to target. If none is passed will use default zone from the config. :param reverse: Reverse domain name. - :param type_: Convert a 'nat' IP to a 'routed_ipv4'. + :param type_: Should have no effect. :param tags: An array of keywords you want to tag this IP with. :param server: :return: :class:`UpdateIpResponse ` diff --git a/scaleway/scaleway/instance/v1/types.py b/scaleway/scaleway/instance/v1/types.py index f4770f9eb..c9c90e339 100644 --- a/scaleway/scaleway/instance/v1/types.py +++ b/scaleway/scaleway/instance/v1/types.py @@ -66,7 +66,6 @@ def __str__(self) -> str: class IpType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_IPTYPE = "unknown_iptype" - NAT = "nat" ROUTED_IPV4 = "routed_ipv4" ROUTED_IPV6 = "routed_ipv6" @@ -1579,7 +1578,7 @@ class CreateIpRequest: type_: Optional[IpType] """ - IP type to reserve (either 'routed_ipv4' or 'routed_ipv6', use of 'nat' is deprecated). + IP type to reserve (either 'routed_ipv4' or 'routed_ipv6'). """ project: Optional[str] @@ -2444,7 +2443,7 @@ class ListIpsRequest: type_: Optional[str] """ - Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4', 'routed_ipv6' or 'nat'). + Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). """ @@ -3180,7 +3179,7 @@ class UpdateIpRequest: type_: Optional[IpType] """ - Convert a 'nat' IP to a 'routed_ipv4'. + Should have no effect. """ tags: Optional[List[str]] From 7b4a738b0e4bdb6cba6c10b299ccbf46266e76cf Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 4 Feb 2025 17:32:50 +0100 Subject: [PATCH 11/73] feat(webhosting): add public search domains (#848) --- .../scaleway_async/webhosting/v1/__init__.py | 26 +++ .../scaleway_async/webhosting/v1/api.py | 128 ++++++++++++- .../scaleway_async/webhosting/v1/content.py | 14 ++ .../webhosting/v1/marshalling.py | 102 ++++++++++ .../scaleway_async/webhosting/v1/types.py | 175 ++++++++++++++++++ .../scaleway_async/webhosting/v1alpha1/api.py | 2 +- scaleway/scaleway/webhosting/v1/__init__.py | 26 +++ scaleway/scaleway/webhosting/v1/api.py | 128 ++++++++++++- scaleway/scaleway/webhosting/v1/content.py | 14 ++ .../scaleway/webhosting/v1/marshalling.py | 102 ++++++++++ scaleway/scaleway/webhosting/v1/types.py | 175 ++++++++++++++++++ scaleway/scaleway/webhosting/v1alpha1/api.py | 2 +- 12 files changed, 888 insertions(+), 6 deletions(-) diff --git a/scaleway-async/scaleway_async/webhosting/v1/__init__.py b/scaleway-async/scaleway_async/webhosting/v1/__init__.py index 0ae2a2342..467720f2b 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/__init__.py +++ b/scaleway-async/scaleway_async/webhosting/v1/__init__.py @@ -3,6 +3,14 @@ from .types import DnsRecordStatus from .types import DnsRecordType from .types import DnsRecordsStatus +from .types import DomainAction +from .types import DomainAvailabilityAction +from .types import DomainAvailabilityStatus +from .content import DOMAIN_AVAILABILITY_TRANSIENT_STATUSES +from .types import DomainDnsAction +from .types import DomainStatus +from .content import DOMAIN_TRANSIENT_STATUSES +from .types import DomainZoneOwner from .types import HostingStatus from .content import HOSTING_TRANSIENT_STATUSES from .types import HostingSummaryStatus @@ -37,6 +45,7 @@ from .types import HostingSummary from .types import MailAccount from .types import Website +from .types import DomainAvailability from .types import CheckUserOwnsDomainResponse from .types import ControlPanelApiListControlPanelsRequest from .types import DatabaseApiAssignDatabaseUserRequest @@ -52,8 +61,11 @@ from .types import DatabaseApiUnassignDatabaseUserRequest from .types import DnsApiCheckUserOwnsDomainRequest from .types import DnsApiGetDomainDnsRecordsRequest +from .types import DnsApiGetDomainRequest +from .types import DnsApiSearchDomainsRequest from .types import DnsApiSyncDomainDnsRecordsRequest from .types import DnsRecords +from .types import Domain from .types import FtpAccountApiChangeFtpAccountPasswordRequest from .types import FtpAccountApiCreateFtpAccountRequest from .types import FtpAccountApiListFtpAccountsRequest @@ -82,6 +94,7 @@ from .types import OfferApiListOffersRequest from .types import ResetHostingPasswordResponse from .types import ResourceSummary +from .types import SearchDomainsResponse from .types import Session from .types import WebsiteApiListWebsitesRequest from .api import WebhostingV1ControlPanelAPI @@ -97,6 +110,14 @@ "DnsRecordStatus", "DnsRecordType", "DnsRecordsStatus", + "DomainAction", + "DomainAvailabilityAction", + "DomainAvailabilityStatus", + "DOMAIN_AVAILABILITY_TRANSIENT_STATUSES", + "DomainDnsAction", + "DomainStatus", + "DOMAIN_TRANSIENT_STATUSES", + "DomainZoneOwner", "HostingStatus", "HOSTING_TRANSIENT_STATUSES", "HostingSummaryStatus", @@ -131,6 +152,7 @@ "HostingSummary", "MailAccount", "Website", + "DomainAvailability", "CheckUserOwnsDomainResponse", "ControlPanelApiListControlPanelsRequest", "DatabaseApiAssignDatabaseUserRequest", @@ -146,8 +168,11 @@ "DatabaseApiUnassignDatabaseUserRequest", "DnsApiCheckUserOwnsDomainRequest", "DnsApiGetDomainDnsRecordsRequest", + "DnsApiGetDomainRequest", + "DnsApiSearchDomainsRequest", "DnsApiSyncDomainDnsRecordsRequest", "DnsRecords", + "Domain", "FtpAccountApiChangeFtpAccountPasswordRequest", "FtpAccountApiCreateFtpAccountRequest", "FtpAccountApiListFtpAccountsRequest", @@ -176,6 +201,7 @@ "OfferApiListOffersRequest", "ResetHostingPasswordResponse", "ResourceSummary", + "SearchDomainsResponse", "Session", "WebsiteApiListWebsitesRequest", "WebhostingV1ControlPanelAPI", diff --git a/scaleway-async/scaleway_async/webhosting/v1/api.py b/scaleway-async/scaleway_async/webhosting/v1/api.py index c3fbbc036..a32da410b 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/api.py +++ b/scaleway-async/scaleway_async/webhosting/v1/api.py @@ -36,6 +36,7 @@ DnsApiCheckUserOwnsDomainRequest, DnsApiSyncDomainDnsRecordsRequest, DnsRecords, + Domain, FtpAccount, FtpAccountApiChangeFtpAccountPasswordRequest, FtpAccountApiCreateFtpAccountRequest, @@ -59,11 +60,13 @@ OfferOptionRequest, ResetHostingPasswordResponse, ResourceSummary, + SearchDomainsResponse, Session, SyncDomainDnsRecordsRequestRecord, Website, ) from .content import ( + DOMAIN_TRANSIENT_STATUSES, HOSTING_TRANSIENT_STATUSES, ) from .marshalling import ( @@ -73,6 +76,7 @@ unmarshal_MailAccount, unmarshal_CheckUserOwnsDomainResponse, unmarshal_DnsRecords, + unmarshal_Domain, unmarshal_Hosting, unmarshal_ListControlPanelsResponse, unmarshal_ListDatabaseUsersResponse, @@ -84,6 +88,7 @@ unmarshal_ListWebsitesResponse, unmarshal_ResetHostingPasswordResponse, unmarshal_ResourceSummary, + unmarshal_SearchDomainsResponse, unmarshal_Session, marshal_DatabaseApiAssignDatabaseUserRequest, marshal_DatabaseApiChangeDatabaseUserPasswordRequest, @@ -792,7 +797,7 @@ async def check_user_owns_domain( project_id: Optional[str] = None, ) -> CheckUserOwnsDomainResponse: """ - "Check whether you own this domain or not.". + Check whether you own this domain or not. :param domain: Domain for which ownership is to be verified. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the project currently in use. @@ -834,15 +839,17 @@ async def sync_domain_dns_records( update_web_records: bool, update_mail_records: bool, update_all_records: bool, + update_nameservers: bool, region: Optional[ScwRegion] = None, custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] = None, ) -> DnsRecords: """ - "Synchronize your DNS records on the Elements Console and on cPanel.". + Synchronize your DNS records on the Elements Console and on cPanel. :param domain: Domain for which the DNS records will be synchronized. :param update_web_records: Whether or not to synchronize the web records. :param update_mail_records: Whether or not to synchronize the mail records. :param update_all_records: Whether or not to synchronize all types of records. This one has priority. + :param update_nameservers: Whether or not to synchronize domain nameservers. :param region: Region to target. If none is passed will use default region from the config. :param custom_records: Custom records to synchronize. :return: :class:`DnsRecords ` @@ -855,6 +862,7 @@ async def sync_domain_dns_records( update_web_records=False, update_mail_records=False, update_all_records=False, + update_nameservers=False, ) """ @@ -872,6 +880,7 @@ async def sync_domain_dns_records( update_web_records=update_web_records, update_mail_records=update_mail_records, update_all_records=update_all_records, + update_nameservers=update_nameservers, region=region, custom_records=custom_records, ), @@ -882,6 +891,121 @@ async def sync_domain_dns_records( self._throw_on_error(res) return unmarshal_DnsRecords(res.json()) + async def search_domains( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> SearchDomainsResponse: + """ + Search for available domains based on domain name. + :param domain_name: Domain name to search. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to search the domain to create the Web Hosting plan. + :return: :class:`SearchDomainsResponse ` + + Usage: + :: + + result = await api.search_domains( + domain_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/search-domains", + params={ + "domain_name": domain_name, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_SearchDomainsResponse(res.json()) + + async def get_domain( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> Domain: + """ + Retrieve detailed information about a specific domain, including its status, DNS configuration, and ownership. + :param domain_name: Domain name to get. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + :return: :class:`Domain ` + + Usage: + :: + + result = await api.get_domain( + domain_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain_name = validate_path_param("domain_name", domain_name) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain_name}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Domain(res.json()) + + async def wait_for_domain( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + options: Optional[WaitForOptions[Domain, Union[bool, Awaitable[bool]]]] = None, + ) -> Domain: + """ + Retrieve detailed information about a specific domain, including its status, DNS configuration, and ownership. + :param domain_name: Domain name to get. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + :return: :class:`Domain ` + + Usage: + :: + + result = await api.get_domain( + domain_name="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in DOMAIN_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_domain, + options=options, + args={ + "domain_name": domain_name, + "region": region, + "project_id": project_id, + }, + ) + class WebhostingV1OfferAPI(API): """ diff --git a/scaleway-async/scaleway_async/webhosting/v1/content.py b/scaleway-async/scaleway_async/webhosting/v1/content.py index 0d24b738d..7c429cec5 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/content.py +++ b/scaleway-async/scaleway_async/webhosting/v1/content.py @@ -3,10 +3,24 @@ from typing import List from .types import ( + DomainAvailabilityStatus, + DomainStatus, HostingStatus, HostingSummaryStatus, ) +DOMAIN_AVAILABILITY_TRANSIENT_STATUSES: List[DomainAvailabilityStatus] = [ + DomainAvailabilityStatus.VALIDATING, +] +""" +Lists transient statutes of the enum :class:`DomainAvailabilityStatus `. +""" +DOMAIN_TRANSIENT_STATUSES: List[DomainStatus] = [ + DomainStatus.VALIDATING, +] +""" +Lists transient statutes of the enum :class:`DomainStatus `. +""" HOSTING_TRANSIENT_STATUSES: List[HostingStatus] = [ HostingStatus.DELIVERING, HostingStatus.DELETING, diff --git a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py index 6a43cdaac..462a8ccbf 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py +++ b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py @@ -13,6 +13,9 @@ resolve_one_of, ) from .types import ( + DomainAction, + DomainAvailabilityAction, + DomainDnsAction, DatabaseUser, Database, FtpAccount, @@ -21,6 +24,7 @@ DnsRecord, Nameserver, DnsRecords, + Domain, PlatformControlPanelUrls, OfferOption, PlatformControlPanel, @@ -41,6 +45,8 @@ ListWebsitesResponse, ResetHostingPasswordResponse, ResourceSummary, + DomainAvailability, + SearchDomainsResponse, Session, DatabaseApiAssignDatabaseUserRequest, DatabaseApiChangeDatabaseUserPasswordRequest, @@ -248,6 +254,41 @@ def unmarshal_DnsRecords(data: Any) -> DnsRecords: return DnsRecords(**args) +def unmarshal_Domain(data: Any) -> Domain: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Domain' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("available_actions", None) + if field is not None: + args["available_actions"] = ( + [DomainAction(v) for v in field] if field is not None else None + ) + + field = data.get("available_dns_actions", None) + if field is not None: + args["available_dns_actions"] = ( + [DomainDnsAction(v) for v in field] if field is not None else None + ) + + return Domain(**args) + + def unmarshal_PlatformControlPanelUrls(data: Any) -> PlatformControlPanelUrls: if not isinstance(data, dict): raise TypeError( @@ -840,6 +881,64 @@ def unmarshal_ResourceSummary(data: Any) -> ResourceSummary: return ResourceSummary(**args) +def unmarshal_DomainAvailability(data: Any) -> DomainAvailability: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DomainAvailability' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("zone_name", None) + if field is not None: + args["zone_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("available_actions", None) + if field is not None: + args["available_actions"] = ( + [DomainAvailabilityAction(v) for v in field] if field is not None else None + ) + + field = data.get("can_create_hosting", None) + if field is not None: + args["can_create_hosting"] = field + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_Money(field) + else: + args["price"] = None + + return DomainAvailability(**args) + + +def unmarshal_SearchDomainsResponse(data: Any) -> SearchDomainsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SearchDomainsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domains_available", None) + if field is not None: + args["domains_available"] = ( + [unmarshal_DomainAvailability(v) for v in field] + if field is not None + else None + ) + + return SearchDomainsResponse(**args) + + def unmarshal_Session(data: Any) -> Session: if not isinstance(data, dict): raise TypeError( @@ -983,6 +1082,9 @@ def marshal_DnsApiSyncDomainDnsRecordsRequest( if request.update_all_records is not None: output["update_all_records"] = request.update_all_records + if request.update_nameservers is not None: + output["update_nameservers"] = request.update_nameservers + if request.custom_records is not None: output["custom_records"] = [ marshal_SyncDomainDnsRecordsRequestRecord(item, defaults) diff --git a/scaleway-async/scaleway_async/webhosting/v1/types.py b/scaleway-async/scaleway_async/webhosting/v1/types.py index 3b3852f94..ee610795d 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/types.py +++ b/scaleway-async/scaleway_async/webhosting/v1/types.py @@ -51,6 +51,71 @@ def __str__(self) -> str: return str(self.value) +class DomainAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + TRANSFER = "transfer" + MANAGE_EXTERNAL = "manage_external" + RENEW = "renew" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAvailabilityAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + REGISTER = "register" + TRANSFER = "transfer" + MANAGE_EXTERNAL = "manage_external" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAvailabilityStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + AVAILABLE = "available" + NOT_AVAILABLE = "not_available" + OWNED = "owned" + VALIDATING = "validating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class DomainDnsAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_DNS_ACTION = "unknown_dns_action" + AUTO_CONFIG_ALL_RECORDS = "auto_config_all_records" + AUTO_CONFIG_WEB_RECORDS = "auto_config_web_records" + AUTO_CONFIG_MAIL_RECORDS = "auto_config_mail_records" + AUTO_CONFIG_NAMESERVERS = "auto_config_nameservers" + + def __str__(self) -> str: + return str(self.value) + + +class DomainStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + VALIDATING = "validating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class DomainZoneOwner(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ZONE_OWNER = "unknown_zone_owner" + EXTERNAL = "external" + SCALEWAY = "scaleway" + ONLINE = "online" + WEBHOSTING = "webhosting" + + def __str__(self) -> str: + return str(self.value) + + class HostingStatus(str, Enum, metaclass=StrEnumMeta): UNKNOWN_STATUS = "unknown_status" DELIVERING = "delivering" @@ -586,6 +651,39 @@ class Website: """ +@dataclass +class DomainAvailability: + name: str + """ + Fully qualified domain name (FQDN). + """ + + zone_name: str + """ + DNS zone associated with the domain. + """ + + status: DomainAvailabilityStatus + """ + Availability status of the domain. + """ + + available_actions: List[DomainAvailabilityAction] + """ + A list of actions that can be performed on the domain. + """ + + can_create_hosting: bool + """ + Whether a hosting can be created for this domain. + """ + + price: Optional[Money] + """ + Price for registering the domain. + """ + + @dataclass class CheckUserOwnsDomainResponse: owns_domain: bool @@ -885,6 +983,42 @@ class DnsApiGetDomainDnsRecordsRequest: """ +@dataclass +class DnsApiGetDomainRequest: + domain_name: str + """ + Domain name to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + """ + + +@dataclass +class DnsApiSearchDomainsRequest: + domain_name: str + """ + Domain name to search. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to search the domain to create the Web Hosting plan. + """ + + @dataclass class DnsApiSyncDomainDnsRecordsRequest: domain: str @@ -907,6 +1041,11 @@ class DnsApiSyncDomainDnsRecordsRequest: Whether or not to synchronize all types of records. This one has priority. """ + update_nameservers: bool + """ + Whether or not to synchronize domain nameservers. + """ + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. @@ -936,6 +1075,34 @@ class DnsRecords: """ +@dataclass +class Domain: + name: str + """ + Name of the domain. + """ + + status: DomainStatus + """ + Current status of the domain. + """ + + owner: DomainZoneOwner + """ + Zone owner of the domain. + """ + + available_actions: List[DomainAction] + """ + A list of actions that can be performed on the domain. + """ + + available_dns_actions: List[DomainDnsAction] + """ + A list of DNS-related actions that can be auto configured for the domain. + """ + + @dataclass class FtpAccountApiChangeFtpAccountPasswordRequest: hosting_id: str @@ -1600,6 +1767,14 @@ class ResourceSummary: """ +@dataclass +class SearchDomainsResponse: + domains_available: List[DomainAvailability] + """ + List of domains availability. + """ + + @dataclass class Session: url: str diff --git a/scaleway-async/scaleway_async/webhosting/v1alpha1/api.py b/scaleway-async/scaleway_async/webhosting/v1alpha1/api.py index 250e37b0d..c9d4de465 100644 --- a/scaleway-async/scaleway_async/webhosting/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/webhosting/v1alpha1/api.py @@ -499,7 +499,7 @@ async def check_user_owns_domain( res = self._request( "POST", - f"/webhosting/v1/regions/{param_region}/domains/{param_domain}/check-ownership", + f"/webhosting/v1alpha1/regions/{param_region}/domains/{param_domain}/check-ownership", body=marshal_CheckUserOwnsDomainRequest( CheckUserOwnsDomainRequest( domain=domain, diff --git a/scaleway/scaleway/webhosting/v1/__init__.py b/scaleway/scaleway/webhosting/v1/__init__.py index 0ae2a2342..467720f2b 100644 --- a/scaleway/scaleway/webhosting/v1/__init__.py +++ b/scaleway/scaleway/webhosting/v1/__init__.py @@ -3,6 +3,14 @@ from .types import DnsRecordStatus from .types import DnsRecordType from .types import DnsRecordsStatus +from .types import DomainAction +from .types import DomainAvailabilityAction +from .types import DomainAvailabilityStatus +from .content import DOMAIN_AVAILABILITY_TRANSIENT_STATUSES +from .types import DomainDnsAction +from .types import DomainStatus +from .content import DOMAIN_TRANSIENT_STATUSES +from .types import DomainZoneOwner from .types import HostingStatus from .content import HOSTING_TRANSIENT_STATUSES from .types import HostingSummaryStatus @@ -37,6 +45,7 @@ from .types import HostingSummary from .types import MailAccount from .types import Website +from .types import DomainAvailability from .types import CheckUserOwnsDomainResponse from .types import ControlPanelApiListControlPanelsRequest from .types import DatabaseApiAssignDatabaseUserRequest @@ -52,8 +61,11 @@ from .types import DatabaseApiUnassignDatabaseUserRequest from .types import DnsApiCheckUserOwnsDomainRequest from .types import DnsApiGetDomainDnsRecordsRequest +from .types import DnsApiGetDomainRequest +from .types import DnsApiSearchDomainsRequest from .types import DnsApiSyncDomainDnsRecordsRequest from .types import DnsRecords +from .types import Domain from .types import FtpAccountApiChangeFtpAccountPasswordRequest from .types import FtpAccountApiCreateFtpAccountRequest from .types import FtpAccountApiListFtpAccountsRequest @@ -82,6 +94,7 @@ from .types import OfferApiListOffersRequest from .types import ResetHostingPasswordResponse from .types import ResourceSummary +from .types import SearchDomainsResponse from .types import Session from .types import WebsiteApiListWebsitesRequest from .api import WebhostingV1ControlPanelAPI @@ -97,6 +110,14 @@ "DnsRecordStatus", "DnsRecordType", "DnsRecordsStatus", + "DomainAction", + "DomainAvailabilityAction", + "DomainAvailabilityStatus", + "DOMAIN_AVAILABILITY_TRANSIENT_STATUSES", + "DomainDnsAction", + "DomainStatus", + "DOMAIN_TRANSIENT_STATUSES", + "DomainZoneOwner", "HostingStatus", "HOSTING_TRANSIENT_STATUSES", "HostingSummaryStatus", @@ -131,6 +152,7 @@ "HostingSummary", "MailAccount", "Website", + "DomainAvailability", "CheckUserOwnsDomainResponse", "ControlPanelApiListControlPanelsRequest", "DatabaseApiAssignDatabaseUserRequest", @@ -146,8 +168,11 @@ "DatabaseApiUnassignDatabaseUserRequest", "DnsApiCheckUserOwnsDomainRequest", "DnsApiGetDomainDnsRecordsRequest", + "DnsApiGetDomainRequest", + "DnsApiSearchDomainsRequest", "DnsApiSyncDomainDnsRecordsRequest", "DnsRecords", + "Domain", "FtpAccountApiChangeFtpAccountPasswordRequest", "FtpAccountApiCreateFtpAccountRequest", "FtpAccountApiListFtpAccountsRequest", @@ -176,6 +201,7 @@ "OfferApiListOffersRequest", "ResetHostingPasswordResponse", "ResourceSummary", + "SearchDomainsResponse", "Session", "WebsiteApiListWebsitesRequest", "WebhostingV1ControlPanelAPI", diff --git a/scaleway/scaleway/webhosting/v1/api.py b/scaleway/scaleway/webhosting/v1/api.py index 486d77927..d613fc2aa 100644 --- a/scaleway/scaleway/webhosting/v1/api.py +++ b/scaleway/scaleway/webhosting/v1/api.py @@ -36,6 +36,7 @@ DnsApiCheckUserOwnsDomainRequest, DnsApiSyncDomainDnsRecordsRequest, DnsRecords, + Domain, FtpAccount, FtpAccountApiChangeFtpAccountPasswordRequest, FtpAccountApiCreateFtpAccountRequest, @@ -59,11 +60,13 @@ OfferOptionRequest, ResetHostingPasswordResponse, ResourceSummary, + SearchDomainsResponse, Session, SyncDomainDnsRecordsRequestRecord, Website, ) from .content import ( + DOMAIN_TRANSIENT_STATUSES, HOSTING_TRANSIENT_STATUSES, ) from .marshalling import ( @@ -73,6 +76,7 @@ unmarshal_MailAccount, unmarshal_CheckUserOwnsDomainResponse, unmarshal_DnsRecords, + unmarshal_Domain, unmarshal_Hosting, unmarshal_ListControlPanelsResponse, unmarshal_ListDatabaseUsersResponse, @@ -84,6 +88,7 @@ unmarshal_ListWebsitesResponse, unmarshal_ResetHostingPasswordResponse, unmarshal_ResourceSummary, + unmarshal_SearchDomainsResponse, unmarshal_Session, marshal_DatabaseApiAssignDatabaseUserRequest, marshal_DatabaseApiChangeDatabaseUserPasswordRequest, @@ -792,7 +797,7 @@ def check_user_owns_domain( project_id: Optional[str] = None, ) -> CheckUserOwnsDomainResponse: """ - "Check whether you own this domain or not.". + Check whether you own this domain or not. :param domain: Domain for which ownership is to be verified. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the project currently in use. @@ -834,15 +839,17 @@ def sync_domain_dns_records( update_web_records: bool, update_mail_records: bool, update_all_records: bool, + update_nameservers: bool, region: Optional[ScwRegion] = None, custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] = None, ) -> DnsRecords: """ - "Synchronize your DNS records on the Elements Console and on cPanel.". + Synchronize your DNS records on the Elements Console and on cPanel. :param domain: Domain for which the DNS records will be synchronized. :param update_web_records: Whether or not to synchronize the web records. :param update_mail_records: Whether or not to synchronize the mail records. :param update_all_records: Whether or not to synchronize all types of records. This one has priority. + :param update_nameservers: Whether or not to synchronize domain nameservers. :param region: Region to target. If none is passed will use default region from the config. :param custom_records: Custom records to synchronize. :return: :class:`DnsRecords ` @@ -855,6 +862,7 @@ def sync_domain_dns_records( update_web_records=False, update_mail_records=False, update_all_records=False, + update_nameservers=False, ) """ @@ -872,6 +880,7 @@ def sync_domain_dns_records( update_web_records=update_web_records, update_mail_records=update_mail_records, update_all_records=update_all_records, + update_nameservers=update_nameservers, region=region, custom_records=custom_records, ), @@ -882,6 +891,121 @@ def sync_domain_dns_records( self._throw_on_error(res) return unmarshal_DnsRecords(res.json()) + def search_domains( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> SearchDomainsResponse: + """ + Search for available domains based on domain name. + :param domain_name: Domain name to search. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to search the domain to create the Web Hosting plan. + :return: :class:`SearchDomainsResponse ` + + Usage: + :: + + result = api.search_domains( + domain_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/search-domains", + params={ + "domain_name": domain_name, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_SearchDomainsResponse(res.json()) + + def get_domain( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> Domain: + """ + Retrieve detailed information about a specific domain, including its status, DNS configuration, and ownership. + :param domain_name: Domain name to get. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + :return: :class:`Domain ` + + Usage: + :: + + result = api.get_domain( + domain_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain_name = validate_path_param("domain_name", domain_name) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain_name}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Domain(res.json()) + + def wait_for_domain( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + options: Optional[WaitForOptions[Domain, bool]] = None, + ) -> Domain: + """ + Retrieve detailed information about a specific domain, including its status, DNS configuration, and ownership. + :param domain_name: Domain name to get. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + :return: :class:`Domain ` + + Usage: + :: + + result = api.get_domain( + domain_name="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in DOMAIN_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_domain, + options=options, + args={ + "domain_name": domain_name, + "region": region, + "project_id": project_id, + }, + ) + class WebhostingV1OfferAPI(API): """ diff --git a/scaleway/scaleway/webhosting/v1/content.py b/scaleway/scaleway/webhosting/v1/content.py index 0d24b738d..7c429cec5 100644 --- a/scaleway/scaleway/webhosting/v1/content.py +++ b/scaleway/scaleway/webhosting/v1/content.py @@ -3,10 +3,24 @@ from typing import List from .types import ( + DomainAvailabilityStatus, + DomainStatus, HostingStatus, HostingSummaryStatus, ) +DOMAIN_AVAILABILITY_TRANSIENT_STATUSES: List[DomainAvailabilityStatus] = [ + DomainAvailabilityStatus.VALIDATING, +] +""" +Lists transient statutes of the enum :class:`DomainAvailabilityStatus `. +""" +DOMAIN_TRANSIENT_STATUSES: List[DomainStatus] = [ + DomainStatus.VALIDATING, +] +""" +Lists transient statutes of the enum :class:`DomainStatus `. +""" HOSTING_TRANSIENT_STATUSES: List[HostingStatus] = [ HostingStatus.DELIVERING, HostingStatus.DELETING, diff --git a/scaleway/scaleway/webhosting/v1/marshalling.py b/scaleway/scaleway/webhosting/v1/marshalling.py index 6a43cdaac..462a8ccbf 100644 --- a/scaleway/scaleway/webhosting/v1/marshalling.py +++ b/scaleway/scaleway/webhosting/v1/marshalling.py @@ -13,6 +13,9 @@ resolve_one_of, ) from .types import ( + DomainAction, + DomainAvailabilityAction, + DomainDnsAction, DatabaseUser, Database, FtpAccount, @@ -21,6 +24,7 @@ DnsRecord, Nameserver, DnsRecords, + Domain, PlatformControlPanelUrls, OfferOption, PlatformControlPanel, @@ -41,6 +45,8 @@ ListWebsitesResponse, ResetHostingPasswordResponse, ResourceSummary, + DomainAvailability, + SearchDomainsResponse, Session, DatabaseApiAssignDatabaseUserRequest, DatabaseApiChangeDatabaseUserPasswordRequest, @@ -248,6 +254,41 @@ def unmarshal_DnsRecords(data: Any) -> DnsRecords: return DnsRecords(**args) +def unmarshal_Domain(data: Any) -> Domain: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Domain' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("available_actions", None) + if field is not None: + args["available_actions"] = ( + [DomainAction(v) for v in field] if field is not None else None + ) + + field = data.get("available_dns_actions", None) + if field is not None: + args["available_dns_actions"] = ( + [DomainDnsAction(v) for v in field] if field is not None else None + ) + + return Domain(**args) + + def unmarshal_PlatformControlPanelUrls(data: Any) -> PlatformControlPanelUrls: if not isinstance(data, dict): raise TypeError( @@ -840,6 +881,64 @@ def unmarshal_ResourceSummary(data: Any) -> ResourceSummary: return ResourceSummary(**args) +def unmarshal_DomainAvailability(data: Any) -> DomainAvailability: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DomainAvailability' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("zone_name", None) + if field is not None: + args["zone_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("available_actions", None) + if field is not None: + args["available_actions"] = ( + [DomainAvailabilityAction(v) for v in field] if field is not None else None + ) + + field = data.get("can_create_hosting", None) + if field is not None: + args["can_create_hosting"] = field + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_Money(field) + else: + args["price"] = None + + return DomainAvailability(**args) + + +def unmarshal_SearchDomainsResponse(data: Any) -> SearchDomainsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SearchDomainsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domains_available", None) + if field is not None: + args["domains_available"] = ( + [unmarshal_DomainAvailability(v) for v in field] + if field is not None + else None + ) + + return SearchDomainsResponse(**args) + + def unmarshal_Session(data: Any) -> Session: if not isinstance(data, dict): raise TypeError( @@ -983,6 +1082,9 @@ def marshal_DnsApiSyncDomainDnsRecordsRequest( if request.update_all_records is not None: output["update_all_records"] = request.update_all_records + if request.update_nameservers is not None: + output["update_nameservers"] = request.update_nameservers + if request.custom_records is not None: output["custom_records"] = [ marshal_SyncDomainDnsRecordsRequestRecord(item, defaults) diff --git a/scaleway/scaleway/webhosting/v1/types.py b/scaleway/scaleway/webhosting/v1/types.py index 3b3852f94..ee610795d 100644 --- a/scaleway/scaleway/webhosting/v1/types.py +++ b/scaleway/scaleway/webhosting/v1/types.py @@ -51,6 +51,71 @@ def __str__(self) -> str: return str(self.value) +class DomainAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + TRANSFER = "transfer" + MANAGE_EXTERNAL = "manage_external" + RENEW = "renew" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAvailabilityAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + REGISTER = "register" + TRANSFER = "transfer" + MANAGE_EXTERNAL = "manage_external" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAvailabilityStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + AVAILABLE = "available" + NOT_AVAILABLE = "not_available" + OWNED = "owned" + VALIDATING = "validating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class DomainDnsAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_DNS_ACTION = "unknown_dns_action" + AUTO_CONFIG_ALL_RECORDS = "auto_config_all_records" + AUTO_CONFIG_WEB_RECORDS = "auto_config_web_records" + AUTO_CONFIG_MAIL_RECORDS = "auto_config_mail_records" + AUTO_CONFIG_NAMESERVERS = "auto_config_nameservers" + + def __str__(self) -> str: + return str(self.value) + + +class DomainStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + VALIDATING = "validating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class DomainZoneOwner(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ZONE_OWNER = "unknown_zone_owner" + EXTERNAL = "external" + SCALEWAY = "scaleway" + ONLINE = "online" + WEBHOSTING = "webhosting" + + def __str__(self) -> str: + return str(self.value) + + class HostingStatus(str, Enum, metaclass=StrEnumMeta): UNKNOWN_STATUS = "unknown_status" DELIVERING = "delivering" @@ -586,6 +651,39 @@ class Website: """ +@dataclass +class DomainAvailability: + name: str + """ + Fully qualified domain name (FQDN). + """ + + zone_name: str + """ + DNS zone associated with the domain. + """ + + status: DomainAvailabilityStatus + """ + Availability status of the domain. + """ + + available_actions: List[DomainAvailabilityAction] + """ + A list of actions that can be performed on the domain. + """ + + can_create_hosting: bool + """ + Whether a hosting can be created for this domain. + """ + + price: Optional[Money] + """ + Price for registering the domain. + """ + + @dataclass class CheckUserOwnsDomainResponse: owns_domain: bool @@ -885,6 +983,42 @@ class DnsApiGetDomainDnsRecordsRequest: """ +@dataclass +class DnsApiGetDomainRequest: + domain_name: str + """ + Domain name to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + """ + + +@dataclass +class DnsApiSearchDomainsRequest: + domain_name: str + """ + Domain name to search. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to search the domain to create the Web Hosting plan. + """ + + @dataclass class DnsApiSyncDomainDnsRecordsRequest: domain: str @@ -907,6 +1041,11 @@ class DnsApiSyncDomainDnsRecordsRequest: Whether or not to synchronize all types of records. This one has priority. """ + update_nameservers: bool + """ + Whether or not to synchronize domain nameservers. + """ + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. @@ -936,6 +1075,34 @@ class DnsRecords: """ +@dataclass +class Domain: + name: str + """ + Name of the domain. + """ + + status: DomainStatus + """ + Current status of the domain. + """ + + owner: DomainZoneOwner + """ + Zone owner of the domain. + """ + + available_actions: List[DomainAction] + """ + A list of actions that can be performed on the domain. + """ + + available_dns_actions: List[DomainDnsAction] + """ + A list of DNS-related actions that can be auto configured for the domain. + """ + + @dataclass class FtpAccountApiChangeFtpAccountPasswordRequest: hosting_id: str @@ -1600,6 +1767,14 @@ class ResourceSummary: """ +@dataclass +class SearchDomainsResponse: + domains_available: List[DomainAvailability] + """ + List of domains availability. + """ + + @dataclass class Session: url: str diff --git a/scaleway/scaleway/webhosting/v1alpha1/api.py b/scaleway/scaleway/webhosting/v1alpha1/api.py index c960e44a2..afcb9702c 100644 --- a/scaleway/scaleway/webhosting/v1alpha1/api.py +++ b/scaleway/scaleway/webhosting/v1alpha1/api.py @@ -499,7 +499,7 @@ def check_user_owns_domain( res = self._request( "POST", - f"/webhosting/v1/regions/{param_region}/domains/{param_domain}/check-ownership", + f"/webhosting/v1alpha1/regions/{param_region}/domains/{param_domain}/check-ownership", body=marshal_CheckUserOwnsDomainRequest( CheckUserOwnsDomainRequest( domain=domain, From 0da09eb5464e8796a530b2305d0d0ae1eb2bb67d Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Wed, 5 Feb 2025 16:27:48 +0100 Subject: [PATCH 12/73] feat(cockpit): add received_resolved field (#850) --- .../scaleway_async/cockpit/v1/__init__.py | 2 + .../scaleway_async/cockpit/v1/api.py | 48 +++++++++++++++++++ .../scaleway_async/cockpit/v1/marshalling.py | 34 +++++++++++++ .../scaleway_async/cockpit/v1/types.py | 36 +++++++++++++- scaleway/scaleway/cockpit/v1/__init__.py | 2 + scaleway/scaleway/cockpit/v1/api.py | 48 +++++++++++++++++++ scaleway/scaleway/cockpit/v1/marshalling.py | 34 +++++++++++++ scaleway/scaleway/cockpit/v1/types.py | 36 +++++++++++++- 8 files changed, 238 insertions(+), 2 deletions(-) diff --git a/scaleway-async/scaleway_async/cockpit/v1/__init__.py b/scaleway-async/scaleway_async/cockpit/v1/__init__.py index 833733ae8..a648fc794 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/__init__.py +++ b/scaleway-async/scaleway_async/cockpit/v1/__init__.py @@ -62,6 +62,7 @@ from .types import RegionalApiListManagedAlertsRequest from .types import RegionalApiListTokensRequest from .types import RegionalApiTriggerTestAlertRequest +from .types import RegionalApiUpdateContactPointRequest from .types import RegionalApiUpdateDataSourceRequest from .types import UsageOverview from .api import CockpitV1GlobalAPI @@ -130,6 +131,7 @@ "RegionalApiListManagedAlertsRequest", "RegionalApiListTokensRequest", "RegionalApiTriggerTestAlertRequest", + "RegionalApiUpdateContactPointRequest", "RegionalApiUpdateDataSourceRequest", "UsageOverview", "CockpitV1GlobalAPI", diff --git a/scaleway-async/scaleway_async/cockpit/v1/api.py b/scaleway-async/scaleway_async/cockpit/v1/api.py index 77957d558..6833fdbf3 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/api.py +++ b/scaleway-async/scaleway_async/cockpit/v1/api.py @@ -52,6 +52,7 @@ RegionalApiEnableAlertManagerRequest, RegionalApiEnableManagedAlertsRequest, RegionalApiTriggerTestAlertRequest, + RegionalApiUpdateContactPointRequest, RegionalApiUpdateDataSourceRequest, Token, UsageOverview, @@ -87,6 +88,7 @@ marshal_RegionalApiEnableAlertManagerRequest, marshal_RegionalApiEnableManagedAlertsRequest, marshal_RegionalApiTriggerTestAlertRequest, + marshal_RegionalApiUpdateContactPointRequest, marshal_RegionalApiUpdateDataSourceRequest, ) @@ -1230,6 +1232,7 @@ async def create_contact_point( region: Optional[ScwRegion] = None, project_id: Optional[str] = None, email: Optional[ContactPointEmail] = None, + receive_resolved_notifications: Optional[bool] = None, ) -> ContactPoint: """ Create a contact point. @@ -1240,6 +1243,7 @@ async def create_contact_point( :param project_id: ID of the Project to create the contact point in. :param email: Email address of the contact point to create. One-Of ('configuration'): at most one of 'email' could be set. + :param receive_resolved_notifications: Send an email notification when an alert is marked as resolved. :return: :class:`ContactPoint ` Usage: @@ -1259,6 +1263,7 @@ async def create_contact_point( RegionalApiCreateContactPointRequest( region=region, project_id=project_id, + receive_resolved_notifications=receive_resolved_notifications, email=email, ), self.client, @@ -1343,6 +1348,49 @@ async def list_contact_points_all( }, ) + async def update_contact_point( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + email: Optional[ContactPointEmail] = None, + receive_resolved_notifications: Optional[bool] = None, + ) -> ContactPoint: + """ + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project containing the contact point to update. + :param email: Email address of the contact point to update. + One-Of ('configuration'): at most one of 'email' could be set. + :param receive_resolved_notifications: Enable or disable notifications when alert is resolved. + :return: :class:`ContactPoint ` + + Usage: + :: + + result = await api.update_contact_point() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "PATCH", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points", + body=marshal_RegionalApiUpdateContactPointRequest( + RegionalApiUpdateContactPointRequest( + region=region, + project_id=project_id, + receive_resolved_notifications=receive_resolved_notifications, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ContactPoint(res.json()) + async def delete_contact_point( self, *, diff --git a/scaleway-async/scaleway_async/cockpit/v1/marshalling.py b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py index ab3d480cf..6739977d0 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/marshalling.py +++ b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py @@ -45,6 +45,7 @@ RegionalApiEnableAlertManagerRequest, RegionalApiEnableManagedAlertsRequest, RegionalApiTriggerTestAlertRequest, + RegionalApiUpdateContactPointRequest, RegionalApiUpdateDataSourceRequest, ) @@ -76,6 +77,10 @@ def unmarshal_ContactPoint(data: Any) -> ContactPoint: if field is not None: args["region"] = field + field = data.get("receive_resolved_notifications", None) + if field is not None: + args["receive_resolved_notifications"] = field + field = data.get("email", None) if field is not None: args["email"] = unmarshal_ContactPointEmail(field) @@ -773,6 +778,11 @@ def marshal_RegionalApiCreateContactPointRequest( if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id + if request.receive_resolved_notifications is not None: + output["receive_resolved_notifications"] = ( + request.receive_resolved_notifications + ) + return output @@ -894,6 +904,30 @@ def marshal_RegionalApiTriggerTestAlertRequest( return output +def marshal_RegionalApiUpdateContactPointRequest( + request: RegionalApiUpdateContactPointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.receive_resolved_notifications is not None: + output["receive_resolved_notifications"] = ( + request.receive_resolved_notifications + ) + + return output + + def marshal_RegionalApiUpdateDataSourceRequest( request: RegionalApiUpdateDataSourceRequest, defaults: ProfileDefaults, diff --git a/scaleway-async/scaleway_async/cockpit/v1/types.py b/scaleway-async/scaleway_async/cockpit/v1/types.py index c49ae6ddf..d7363a866 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/types.py +++ b/scaleway-async/scaleway_async/cockpit/v1/types.py @@ -151,7 +151,12 @@ class ContactPoint: region: ScwRegion """ - Region to target. If none is passed will use default region from the config. + Region. + """ + + receive_resolved_notifications: bool + """ + Send an email notification when an alert is marked as resolved. """ email: Optional[ContactPointEmail] @@ -847,6 +852,11 @@ class RegionalApiCreateContactPointRequest: ID of the Project to create the contact point in. """ + receive_resolved_notifications: Optional[bool] + """ + Send an email notification when an alert is marked as resolved. + """ + email: Optional[ContactPointEmail] @@ -1260,6 +1270,30 @@ class RegionalApiTriggerTestAlertRequest: """ +@dataclass +class RegionalApiUpdateContactPointRequest: + """ + Update a contact point. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project containing the contact point to update. + """ + + receive_resolved_notifications: Optional[bool] + """ + Enable or disable notifications when alert is resolved. + """ + + email: Optional[ContactPointEmail] + + @dataclass class RegionalApiUpdateDataSourceRequest: """ diff --git a/scaleway/scaleway/cockpit/v1/__init__.py b/scaleway/scaleway/cockpit/v1/__init__.py index 833733ae8..a648fc794 100644 --- a/scaleway/scaleway/cockpit/v1/__init__.py +++ b/scaleway/scaleway/cockpit/v1/__init__.py @@ -62,6 +62,7 @@ from .types import RegionalApiListManagedAlertsRequest from .types import RegionalApiListTokensRequest from .types import RegionalApiTriggerTestAlertRequest +from .types import RegionalApiUpdateContactPointRequest from .types import RegionalApiUpdateDataSourceRequest from .types import UsageOverview from .api import CockpitV1GlobalAPI @@ -130,6 +131,7 @@ "RegionalApiListManagedAlertsRequest", "RegionalApiListTokensRequest", "RegionalApiTriggerTestAlertRequest", + "RegionalApiUpdateContactPointRequest", "RegionalApiUpdateDataSourceRequest", "UsageOverview", "CockpitV1GlobalAPI", diff --git a/scaleway/scaleway/cockpit/v1/api.py b/scaleway/scaleway/cockpit/v1/api.py index b9a60a816..0be7b2ca2 100644 --- a/scaleway/scaleway/cockpit/v1/api.py +++ b/scaleway/scaleway/cockpit/v1/api.py @@ -52,6 +52,7 @@ RegionalApiEnableAlertManagerRequest, RegionalApiEnableManagedAlertsRequest, RegionalApiTriggerTestAlertRequest, + RegionalApiUpdateContactPointRequest, RegionalApiUpdateDataSourceRequest, Token, UsageOverview, @@ -87,6 +88,7 @@ marshal_RegionalApiEnableAlertManagerRequest, marshal_RegionalApiEnableManagedAlertsRequest, marshal_RegionalApiTriggerTestAlertRequest, + marshal_RegionalApiUpdateContactPointRequest, marshal_RegionalApiUpdateDataSourceRequest, ) @@ -1230,6 +1232,7 @@ def create_contact_point( region: Optional[ScwRegion] = None, project_id: Optional[str] = None, email: Optional[ContactPointEmail] = None, + receive_resolved_notifications: Optional[bool] = None, ) -> ContactPoint: """ Create a contact point. @@ -1240,6 +1243,7 @@ def create_contact_point( :param project_id: ID of the Project to create the contact point in. :param email: Email address of the contact point to create. One-Of ('configuration'): at most one of 'email' could be set. + :param receive_resolved_notifications: Send an email notification when an alert is marked as resolved. :return: :class:`ContactPoint ` Usage: @@ -1259,6 +1263,7 @@ def create_contact_point( RegionalApiCreateContactPointRequest( region=region, project_id=project_id, + receive_resolved_notifications=receive_resolved_notifications, email=email, ), self.client, @@ -1343,6 +1348,49 @@ def list_contact_points_all( }, ) + def update_contact_point( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + email: Optional[ContactPointEmail] = None, + receive_resolved_notifications: Optional[bool] = None, + ) -> ContactPoint: + """ + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project containing the contact point to update. + :param email: Email address of the contact point to update. + One-Of ('configuration'): at most one of 'email' could be set. + :param receive_resolved_notifications: Enable or disable notifications when alert is resolved. + :return: :class:`ContactPoint ` + + Usage: + :: + + result = api.update_contact_point() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "PATCH", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points", + body=marshal_RegionalApiUpdateContactPointRequest( + RegionalApiUpdateContactPointRequest( + region=region, + project_id=project_id, + receive_resolved_notifications=receive_resolved_notifications, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ContactPoint(res.json()) + def delete_contact_point( self, *, diff --git a/scaleway/scaleway/cockpit/v1/marshalling.py b/scaleway/scaleway/cockpit/v1/marshalling.py index ab3d480cf..6739977d0 100644 --- a/scaleway/scaleway/cockpit/v1/marshalling.py +++ b/scaleway/scaleway/cockpit/v1/marshalling.py @@ -45,6 +45,7 @@ RegionalApiEnableAlertManagerRequest, RegionalApiEnableManagedAlertsRequest, RegionalApiTriggerTestAlertRequest, + RegionalApiUpdateContactPointRequest, RegionalApiUpdateDataSourceRequest, ) @@ -76,6 +77,10 @@ def unmarshal_ContactPoint(data: Any) -> ContactPoint: if field is not None: args["region"] = field + field = data.get("receive_resolved_notifications", None) + if field is not None: + args["receive_resolved_notifications"] = field + field = data.get("email", None) if field is not None: args["email"] = unmarshal_ContactPointEmail(field) @@ -773,6 +778,11 @@ def marshal_RegionalApiCreateContactPointRequest( if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id + if request.receive_resolved_notifications is not None: + output["receive_resolved_notifications"] = ( + request.receive_resolved_notifications + ) + return output @@ -894,6 +904,30 @@ def marshal_RegionalApiTriggerTestAlertRequest( return output +def marshal_RegionalApiUpdateContactPointRequest( + request: RegionalApiUpdateContactPointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.receive_resolved_notifications is not None: + output["receive_resolved_notifications"] = ( + request.receive_resolved_notifications + ) + + return output + + def marshal_RegionalApiUpdateDataSourceRequest( request: RegionalApiUpdateDataSourceRequest, defaults: ProfileDefaults, diff --git a/scaleway/scaleway/cockpit/v1/types.py b/scaleway/scaleway/cockpit/v1/types.py index c49ae6ddf..d7363a866 100644 --- a/scaleway/scaleway/cockpit/v1/types.py +++ b/scaleway/scaleway/cockpit/v1/types.py @@ -151,7 +151,12 @@ class ContactPoint: region: ScwRegion """ - Region to target. If none is passed will use default region from the config. + Region. + """ + + receive_resolved_notifications: bool + """ + Send an email notification when an alert is marked as resolved. """ email: Optional[ContactPointEmail] @@ -847,6 +852,11 @@ class RegionalApiCreateContactPointRequest: ID of the Project to create the contact point in. """ + receive_resolved_notifications: Optional[bool] + """ + Send an email notification when an alert is marked as resolved. + """ + email: Optional[ContactPointEmail] @@ -1260,6 +1270,30 @@ class RegionalApiTriggerTestAlertRequest: """ +@dataclass +class RegionalApiUpdateContactPointRequest: + """ + Update a contact point. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project containing the contact point to update. + """ + + receive_resolved_notifications: Optional[bool] + """ + Enable or disable notifications when alert is resolved. + """ + + email: Optional[ContactPointEmail] + + @dataclass class RegionalApiUpdateDataSourceRequest: """ From 8c3f3b17ffa209ded8b88d82e113dbb8304307ba Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Wed, 5 Feb 2025 16:28:11 +0100 Subject: [PATCH 13/73] feat(key_manager): review wording (#851) --- .../key_manager/v1alpha1/api.py | 38 +++++++++---------- .../key_manager/v1alpha1/types.py | 18 ++++----- scaleway/scaleway/key_manager/v1alpha1/api.py | 38 +++++++++---------- .../scaleway/key_manager/v1alpha1/types.py | 18 ++++----- 4 files changed, 56 insertions(+), 56 deletions(-) diff --git a/scaleway-async/scaleway_async/key_manager/v1alpha1/api.py b/scaleway-async/scaleway_async/key_manager/v1alpha1/api.py index 293b8d04d..172c26fef 100644 --- a/scaleway-async/scaleway_async/key_manager/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/key_manager/v1alpha1/api.py @@ -64,7 +64,7 @@ async def create_key( ) -> Key: """ Create a key. - Create a key in a given region specified by the `region` parameter. Keys only support symmetric encryption. You can use keys to encrypt or decrypt arbitrary payloads, or to generate data encryption keys that can be used without being stored in Key Manager. + Create a key in a given region specified by the `region` parameter. Keys only support symmetric encryption. You can use keys to encrypt or decrypt arbitrary payloads, or to generate data encryption keys. **Data encryption keys are not stored in Key Manager**. :param unprotected: Default value is `false`. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the Project containing the key. @@ -118,7 +118,7 @@ async def get_key( ) -> Key: """ Get key metadata. - Retrieve the metadata of a key specified by the `region` and `key_id` parameters. + Retrieve metadata for a specified key using the `region` and `key_id` parameters. :param key_id: ID of the key to target. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Key ` @@ -156,7 +156,7 @@ async def update_key( ) -> Key: """ Update a key. - Update a key's metadata (name, description and tags), specified by the `key_id` and `region` parameters. + Modify a key's metadata including name, description and tags, specified by the `key_id` and `region` parameters. :param key_id: ID of the key to update. :param region: Region to target. If none is passed will use default region from the config. :param name: (Optional) Updated name of the key. @@ -205,7 +205,7 @@ async def delete_key( ) -> None: """ Delete a key. - Delete an existing key specified by the `region` and `key_id` parameters. Deleting a key is permanent and cannot be undone. All data encrypted using this key, including data encryption keys, will become unusable. + Permanently delete a key specified by the `region` and `key_id` parameters. This action is irreversible. Any data encrypted with this key, including data encryption keys, will no longer be decipherable. :param key_id: ID of the key to delete. :param region: Region to target. If none is passed will use default region from the config. @@ -237,7 +237,7 @@ async def rotate_key( ) -> Key: """ Rotate a key. - Generate a new version of an existing key with randomly generated key material. Rotated keys can still be used to decrypt previously encrypted data. The key's new material will be used for subsequent encryption operations and data key generation. + Generate a new version of an existing key with new key material. Previous key versions remain usable to decrypt previously encrypted data, but the key's new version will be used for subsequent encryption operations and data key generation. :param key_id: ID of the key to rotate. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Key ` @@ -272,7 +272,7 @@ async def protect_key( ) -> Key: """ Apply key protection. - Apply key protection to a given key specified by the `key_id` parameter. Applying key protection means that your key can be used and modified, but it cannot be deleted. + Apply protection to a given key specified by the `key_id` parameter. Applying key protection means that your key can be used and modified, but it cannot be deleted. :param key_id: ID of the key to apply key protection to. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Key ` @@ -377,7 +377,7 @@ async def disable_key( ) -> Key: """ Disable key. - Disable a given key to be used for cryptographic operations. Disabling a key renders it unusable. You must specify the `region` and `key_id` parameters. + Disable a given key, preventing it to be used for cryptographic operations. Disabling a key renders it unusable. You must specify the `region` and `key_id` parameters. :param key_id: ID of the key to disable. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Key ` @@ -418,7 +418,7 @@ async def list_keys( ) -> ListKeysResponse: """ List keys. - Retrieve the list of keys created within all Projects of an Organization or in a given Project. You must specify the `region`, and either the `organization_id` or the `project_id`. + Retrieve a list of keys across all Projects in an Organization or within a specific Project. You must specify the `region`, and either the `organization_id` or the `project_id`. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: (Optional) Filter by Organization ID. :param project_id: (Optional) Filter by Project ID. @@ -471,7 +471,7 @@ async def list_keys_all( ) -> List[Key]: """ List keys. - Retrieve the list of keys created within all Projects of an Organization or in a given Project. You must specify the `region`, and either the `organization_id` or the `project_id`. + Retrieve a list of keys across all Projects in an Organization or within a specific Project. You must specify the `region`, and either the `organization_id` or the `project_id`. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: (Optional) Filter by Organization ID. :param project_id: (Optional) Filter by Project ID. @@ -513,10 +513,10 @@ async def generate_data_key( algorithm: Optional[DataKeyAlgorithmSymmetricEncryption] = None, ) -> DataKey: """ - Generate a data encryption key. - Generate a new data encryption key to use for cryptographic operations outside of Key Manager. Note that Key Manager does not store your data encryption key. The data encryption key is encrypted and must be decrypted using the key you have created in Key Manager. The data encryption key's plaintext is returned in the response object, for immediate usage. + Create a data encryption key. + Create a new data encryption key for cryptographic operations outside of Key Manager. The data encryption key is encrypted and must be decrypted using the key you have created in Key Manager. - Always store the data encryption key's ciphertext, rather than its plaintext, which must not be stored. To retrieve your key's plaintext, call the Decrypt endpoint with your key's ID and ciphertext. + The data encryption key is returned in plaintext and ciphertext but it should only be stored in its encrypted form (ciphertext). Key Manager does not store your data encryption key. To retrieve your key's plaintext, use the `Decrypt` method with your key's ID and ciphertext. :param key_id: ID of the key. :param without_plaintext: Default value is `false`, meaning that the plaintext is returned. Set it to `true` if you do not wish the plaintext to be returned in the response object. @@ -564,8 +564,8 @@ async def encrypt( associated_data: Optional[str] = None, ) -> EncryptResponse: """ - Encrypt data. - Encrypt data using an existing key, specified by the `key_id` parameter. Only keys with a usage set to **symmetric_encryption** are supported by this method. The maximum payload size that can be encrypted is 64KB of plaintext. + Encrypt a payload. + Encrypt a payload using an existing key, specified by the `key_id` parameter. Only keys with a usage set to `symmetric_encryption` are supported by this method. The maximum payload size that can be encrypted is 64 KB of plaintext. :param key_id: ID of the key to encrypt. :param plaintext: Data size must be between 1 and 65535 bytes. :param region: Region to target. If none is passed will use default region from the config. @@ -612,8 +612,8 @@ async def decrypt( associated_data: Optional[str] = None, ) -> DecryptResponse: """ - Decrypt data. - Decrypt data using an existing key, specified by the `key_id` parameter. The maximum payload size that can be decrypted is the result of the encryption of 64KB of data (around 131KB). + Decrypt an encrypted payload. + Decrypt an encrypted payload using an existing key, specified by the `key_id` parameter. The maximum payload size that can be decrypted is equivalent to the encrypted output of 64 KB of data (around 131 KB). :param key_id: ID of the key to decrypt. :param ciphertext: Data size must be between 1 and 131071 bytes. :param region: Region to target. If none is passed will use default region from the config. @@ -661,11 +661,11 @@ async def import_key_material( ) -> Key: """ Import key material. - Import key material to use to derive a new cryptographic key. The key's origin must be `external`. - :param key_id: The key's origin must be 'external'. + Import externally generated key material into Key Manager to derive a new cryptographic key. The key's origin must be `external`. + :param key_id: The key's origin must be `external`. :param key_material: The key material The key material is a random sequence of bytes used to derive a cryptographic key. :param region: Region to target. If none is passed will use default region from the config. - :param salt: A salt can be used to improve the quality of randomness when the key material is generated from a low entropy source. + :param salt: A salt is random data added to key material to ensure unique derived keys, even if the input is similar. It helps strengthen security when the key material has low randomness (low entropy). :return: :class:`Key ` Usage: diff --git a/scaleway-async/scaleway_async/key_manager/v1alpha1/types.py b/scaleway-async/scaleway_async/key_manager/v1alpha1/types.py index 04b91d423..681162fee 100644 --- a/scaleway-async/scaleway_async/key_manager/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/key_manager/v1alpha1/types.py @@ -66,12 +66,12 @@ def __str__(self) -> str: class KeyRotationPolicy: rotation_period: Optional[str] """ - Duration between two key rotations. The minimum duration is 24 hours and the maximum duration is 876000 hours (1 year). + Time interval between two key rotations. The minimum duration is 24 hours and the maximum duration is 1 year (876000 hours). """ next_rotation_at: Optional[datetime] """ - Date at which the key will be rotated next. + Timestamp indicating the next scheduled rotation. """ @@ -99,17 +99,17 @@ class Key: state: KeyState """ - See the `Key.State` enum for a description of values. + See the `Key.State` enum for a description of possible values. """ rotation_count: int """ - The rotation count tracks the amount of times that the key was rotated. + The rotation count tracks the number of times the key has been rotated. """ usage: Optional[KeyUsage] """ - Keys with a usage set to `symmetric_encryption` are used to encrypt and decrypt data. The only key algorithm currently supported by Key Manager is AES-256-GCM. + Keys with a usage set to `symmetric_encryption` can encrypt and decrypt data using the `AES-256-GCM` key algorithm. Key Manager currently only supports `AES-256-GCM`. """ created_at: Optional[datetime] @@ -144,7 +144,7 @@ class Key: region: ScwRegion """ - Region of the key. + Region where the key is stored. """ description: Optional[str] @@ -220,7 +220,7 @@ class DataKey: algorithm: DataKeyAlgorithmSymmetricEncryption """ - Symmetric encryption algorithm of the data encryption key. + Symmetric encryption algorithm of the data encryption key (`AES-256-GCM`). """ ciphertext: str @@ -409,7 +409,7 @@ class GetKeyRequest: class ImportKeyMaterialRequest: key_id: str """ - The key's origin must be 'external'. + The key's origin must be `external`. """ key_material: str @@ -424,7 +424,7 @@ class ImportKeyMaterialRequest: salt: Optional[str] """ - A salt can be used to improve the quality of randomness when the key material is generated from a low entropy source. + A salt is random data added to key material to ensure unique derived keys, even if the input is similar. It helps strengthen security when the key material has low randomness (low entropy). """ diff --git a/scaleway/scaleway/key_manager/v1alpha1/api.py b/scaleway/scaleway/key_manager/v1alpha1/api.py index 1057a055d..501941014 100644 --- a/scaleway/scaleway/key_manager/v1alpha1/api.py +++ b/scaleway/scaleway/key_manager/v1alpha1/api.py @@ -64,7 +64,7 @@ def create_key( ) -> Key: """ Create a key. - Create a key in a given region specified by the `region` parameter. Keys only support symmetric encryption. You can use keys to encrypt or decrypt arbitrary payloads, or to generate data encryption keys that can be used without being stored in Key Manager. + Create a key in a given region specified by the `region` parameter. Keys only support symmetric encryption. You can use keys to encrypt or decrypt arbitrary payloads, or to generate data encryption keys. **Data encryption keys are not stored in Key Manager**. :param unprotected: Default value is `false`. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the Project containing the key. @@ -118,7 +118,7 @@ def get_key( ) -> Key: """ Get key metadata. - Retrieve the metadata of a key specified by the `region` and `key_id` parameters. + Retrieve metadata for a specified key using the `region` and `key_id` parameters. :param key_id: ID of the key to target. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Key ` @@ -156,7 +156,7 @@ def update_key( ) -> Key: """ Update a key. - Update a key's metadata (name, description and tags), specified by the `key_id` and `region` parameters. + Modify a key's metadata including name, description and tags, specified by the `key_id` and `region` parameters. :param key_id: ID of the key to update. :param region: Region to target. If none is passed will use default region from the config. :param name: (Optional) Updated name of the key. @@ -205,7 +205,7 @@ def delete_key( ) -> None: """ Delete a key. - Delete an existing key specified by the `region` and `key_id` parameters. Deleting a key is permanent and cannot be undone. All data encrypted using this key, including data encryption keys, will become unusable. + Permanently delete a key specified by the `region` and `key_id` parameters. This action is irreversible. Any data encrypted with this key, including data encryption keys, will no longer be decipherable. :param key_id: ID of the key to delete. :param region: Region to target. If none is passed will use default region from the config. @@ -237,7 +237,7 @@ def rotate_key( ) -> Key: """ Rotate a key. - Generate a new version of an existing key with randomly generated key material. Rotated keys can still be used to decrypt previously encrypted data. The key's new material will be used for subsequent encryption operations and data key generation. + Generate a new version of an existing key with new key material. Previous key versions remain usable to decrypt previously encrypted data, but the key's new version will be used for subsequent encryption operations and data key generation. :param key_id: ID of the key to rotate. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Key ` @@ -272,7 +272,7 @@ def protect_key( ) -> Key: """ Apply key protection. - Apply key protection to a given key specified by the `key_id` parameter. Applying key protection means that your key can be used and modified, but it cannot be deleted. + Apply protection to a given key specified by the `key_id` parameter. Applying key protection means that your key can be used and modified, but it cannot be deleted. :param key_id: ID of the key to apply key protection to. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Key ` @@ -377,7 +377,7 @@ def disable_key( ) -> Key: """ Disable key. - Disable a given key to be used for cryptographic operations. Disabling a key renders it unusable. You must specify the `region` and `key_id` parameters. + Disable a given key, preventing it to be used for cryptographic operations. Disabling a key renders it unusable. You must specify the `region` and `key_id` parameters. :param key_id: ID of the key to disable. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Key ` @@ -418,7 +418,7 @@ def list_keys( ) -> ListKeysResponse: """ List keys. - Retrieve the list of keys created within all Projects of an Organization or in a given Project. You must specify the `region`, and either the `organization_id` or the `project_id`. + Retrieve a list of keys across all Projects in an Organization or within a specific Project. You must specify the `region`, and either the `organization_id` or the `project_id`. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: (Optional) Filter by Organization ID. :param project_id: (Optional) Filter by Project ID. @@ -471,7 +471,7 @@ def list_keys_all( ) -> List[Key]: """ List keys. - Retrieve the list of keys created within all Projects of an Organization or in a given Project. You must specify the `region`, and either the `organization_id` or the `project_id`. + Retrieve a list of keys across all Projects in an Organization or within a specific Project. You must specify the `region`, and either the `organization_id` or the `project_id`. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: (Optional) Filter by Organization ID. :param project_id: (Optional) Filter by Project ID. @@ -513,10 +513,10 @@ def generate_data_key( algorithm: Optional[DataKeyAlgorithmSymmetricEncryption] = None, ) -> DataKey: """ - Generate a data encryption key. - Generate a new data encryption key to use for cryptographic operations outside of Key Manager. Note that Key Manager does not store your data encryption key. The data encryption key is encrypted and must be decrypted using the key you have created in Key Manager. The data encryption key's plaintext is returned in the response object, for immediate usage. + Create a data encryption key. + Create a new data encryption key for cryptographic operations outside of Key Manager. The data encryption key is encrypted and must be decrypted using the key you have created in Key Manager. - Always store the data encryption key's ciphertext, rather than its plaintext, which must not be stored. To retrieve your key's plaintext, call the Decrypt endpoint with your key's ID and ciphertext. + The data encryption key is returned in plaintext and ciphertext but it should only be stored in its encrypted form (ciphertext). Key Manager does not store your data encryption key. To retrieve your key's plaintext, use the `Decrypt` method with your key's ID and ciphertext. :param key_id: ID of the key. :param without_plaintext: Default value is `false`, meaning that the plaintext is returned. Set it to `true` if you do not wish the plaintext to be returned in the response object. @@ -564,8 +564,8 @@ def encrypt( associated_data: Optional[str] = None, ) -> EncryptResponse: """ - Encrypt data. - Encrypt data using an existing key, specified by the `key_id` parameter. Only keys with a usage set to **symmetric_encryption** are supported by this method. The maximum payload size that can be encrypted is 64KB of plaintext. + Encrypt a payload. + Encrypt a payload using an existing key, specified by the `key_id` parameter. Only keys with a usage set to `symmetric_encryption` are supported by this method. The maximum payload size that can be encrypted is 64 KB of plaintext. :param key_id: ID of the key to encrypt. :param plaintext: Data size must be between 1 and 65535 bytes. :param region: Region to target. If none is passed will use default region from the config. @@ -612,8 +612,8 @@ def decrypt( associated_data: Optional[str] = None, ) -> DecryptResponse: """ - Decrypt data. - Decrypt data using an existing key, specified by the `key_id` parameter. The maximum payload size that can be decrypted is the result of the encryption of 64KB of data (around 131KB). + Decrypt an encrypted payload. + Decrypt an encrypted payload using an existing key, specified by the `key_id` parameter. The maximum payload size that can be decrypted is equivalent to the encrypted output of 64 KB of data (around 131 KB). :param key_id: ID of the key to decrypt. :param ciphertext: Data size must be between 1 and 131071 bytes. :param region: Region to target. If none is passed will use default region from the config. @@ -661,11 +661,11 @@ def import_key_material( ) -> Key: """ Import key material. - Import key material to use to derive a new cryptographic key. The key's origin must be `external`. - :param key_id: The key's origin must be 'external'. + Import externally generated key material into Key Manager to derive a new cryptographic key. The key's origin must be `external`. + :param key_id: The key's origin must be `external`. :param key_material: The key material The key material is a random sequence of bytes used to derive a cryptographic key. :param region: Region to target. If none is passed will use default region from the config. - :param salt: A salt can be used to improve the quality of randomness when the key material is generated from a low entropy source. + :param salt: A salt is random data added to key material to ensure unique derived keys, even if the input is similar. It helps strengthen security when the key material has low randomness (low entropy). :return: :class:`Key ` Usage: diff --git a/scaleway/scaleway/key_manager/v1alpha1/types.py b/scaleway/scaleway/key_manager/v1alpha1/types.py index 04b91d423..681162fee 100644 --- a/scaleway/scaleway/key_manager/v1alpha1/types.py +++ b/scaleway/scaleway/key_manager/v1alpha1/types.py @@ -66,12 +66,12 @@ def __str__(self) -> str: class KeyRotationPolicy: rotation_period: Optional[str] """ - Duration between two key rotations. The minimum duration is 24 hours and the maximum duration is 876000 hours (1 year). + Time interval between two key rotations. The minimum duration is 24 hours and the maximum duration is 1 year (876000 hours). """ next_rotation_at: Optional[datetime] """ - Date at which the key will be rotated next. + Timestamp indicating the next scheduled rotation. """ @@ -99,17 +99,17 @@ class Key: state: KeyState """ - See the `Key.State` enum for a description of values. + See the `Key.State` enum for a description of possible values. """ rotation_count: int """ - The rotation count tracks the amount of times that the key was rotated. + The rotation count tracks the number of times the key has been rotated. """ usage: Optional[KeyUsage] """ - Keys with a usage set to `symmetric_encryption` are used to encrypt and decrypt data. The only key algorithm currently supported by Key Manager is AES-256-GCM. + Keys with a usage set to `symmetric_encryption` can encrypt and decrypt data using the `AES-256-GCM` key algorithm. Key Manager currently only supports `AES-256-GCM`. """ created_at: Optional[datetime] @@ -144,7 +144,7 @@ class Key: region: ScwRegion """ - Region of the key. + Region where the key is stored. """ description: Optional[str] @@ -220,7 +220,7 @@ class DataKey: algorithm: DataKeyAlgorithmSymmetricEncryption """ - Symmetric encryption algorithm of the data encryption key. + Symmetric encryption algorithm of the data encryption key (`AES-256-GCM`). """ ciphertext: str @@ -409,7 +409,7 @@ class GetKeyRequest: class ImportKeyMaterialRequest: key_id: str """ - The key's origin must be 'external'. + The key's origin must be `external`. """ key_material: str @@ -424,7 +424,7 @@ class ImportKeyMaterialRequest: salt: Optional[str] """ - A salt can be used to improve the quality of randomness when the key material is generated from a low entropy source. + A salt is random data added to key material to ensure unique derived keys, even if the input is similar. It helps strengthen security when the key material has low randomness (low entropy). """ From 661db26c6486b72780168fb4af98e4597a1391c9 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Feb 2025 16:25:30 +0100 Subject: [PATCH 14/73] feat(ipam): register serverless_container and serverless_function (#852) --- scaleway-async/scaleway_async/ipam/v1/api.py | 22 +++++++-------- .../scaleway_async/ipam/v1/types.py | 28 ++++++++++--------- scaleway/scaleway/ipam/v1/api.py | 22 +++++++-------- scaleway/scaleway/ipam/v1/types.py | 28 ++++++++++--------- 4 files changed, 52 insertions(+), 48 deletions(-) diff --git a/scaleway-async/scaleway_async/ipam/v1/api.py b/scaleway-async/scaleway_async/ipam/v1/api.py index 9a82e016b..3b7962f7c 100644 --- a/scaleway-async/scaleway_async/ipam/v1/api.py +++ b/scaleway-async/scaleway_async/ipam/v1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( OneOfPossibility, @@ -50,7 +50,7 @@ async def book_ip( *, source: Source, is_ipv6: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, address: Optional[str] = None, tags: Optional[List[str]] = None, @@ -105,7 +105,7 @@ async def release_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Release an IP. @@ -137,7 +137,7 @@ async def release_ip( async def release_ip_set( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ip_ids: Optional[List[str]] = None, ) -> None: """ @@ -172,7 +172,7 @@ async def get_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> IP: """ Get an IP. @@ -206,7 +206,7 @@ async def update_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, reverses: Optional[List[Reverse]] = None, ) -> IP: @@ -252,7 +252,7 @@ async def update_ip( async def list_i_ps( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -348,7 +348,7 @@ async def list_i_ps( async def list_i_ps_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -436,7 +436,7 @@ async def attach_ip( *, ip_id: str, resource: CustomResource, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> IP: """ Attach IP to custom resource. @@ -481,7 +481,7 @@ async def detach_ip( *, ip_id: str, resource: CustomResource, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> IP: """ Detach IP from a custom resource. @@ -526,7 +526,7 @@ async def move_ip( *, ip_id: str, from_resource: CustomResource, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, to_resource: Optional[CustomResource] = None, ) -> IP: """ diff --git a/scaleway-async/scaleway_async/ipam/v1/types.py b/scaleway-async/scaleway_async/ipam/v1/types.py index f9504238b..0818893ab 100644 --- a/scaleway-async/scaleway_async/ipam/v1/types.py +++ b/scaleway-async/scaleway_async/ipam/v1/types.py @@ -8,8 +8,8 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -48,6 +48,8 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): MGDB_INSTANCE = "mgdb_instance" APPLE_SILICON_SERVER = "apple_silicon_server" APPLE_SILICON_PRIVATE_NIC = "apple_silicon_private_nic" + SERVERLESS_CONTAINER = "serverless_container" + SERVERLESS_FUNCTION = "serverless_function" def __str__(self) -> str: return str(self.value) @@ -143,7 +145,7 @@ class IP: Array of reverses associated with the IP. """ - region: Region + region: ScwRegion """ Region of the IP. """ @@ -168,7 +170,7 @@ class IP: Resource which the IP is attached to. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone of the IP, if zonal. """ @@ -186,7 +188,7 @@ class AttachIPRequest: Custom resource to be attached to the IP. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -204,7 +206,7 @@ class BookIPRequest: Request an IPv6 instead of an IPv4. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -242,7 +244,7 @@ class DetachIPRequest: Custom resource currently attached to the IP. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -255,7 +257,7 @@ class GetIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -263,7 +265,7 @@ class GetIPRequest: @dataclass class ListIPsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -374,7 +376,7 @@ class MoveIPRequest: Custom resource currently attached to the IP. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -392,7 +394,7 @@ class ReleaseIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -400,7 +402,7 @@ class ReleaseIPRequest: @dataclass class ReleaseIPSetRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -415,7 +417,7 @@ class UpdateIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/ipam/v1/api.py b/scaleway/scaleway/ipam/v1/api.py index 8b6e3f35d..e629b62e1 100644 --- a/scaleway/scaleway/ipam/v1/api.py +++ b/scaleway/scaleway/ipam/v1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( OneOfPossibility, @@ -50,7 +50,7 @@ def book_ip( *, source: Source, is_ipv6: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, address: Optional[str] = None, tags: Optional[List[str]] = None, @@ -105,7 +105,7 @@ def release_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Release an IP. @@ -137,7 +137,7 @@ def release_ip( def release_ip_set( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ip_ids: Optional[List[str]] = None, ) -> None: """ @@ -172,7 +172,7 @@ def get_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> IP: """ Get an IP. @@ -206,7 +206,7 @@ def update_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, reverses: Optional[List[Reverse]] = None, ) -> IP: @@ -252,7 +252,7 @@ def update_ip( def list_i_ps( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -348,7 +348,7 @@ def list_i_ps( def list_i_ps_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -436,7 +436,7 @@ def attach_ip( *, ip_id: str, resource: CustomResource, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> IP: """ Attach IP to custom resource. @@ -481,7 +481,7 @@ def detach_ip( *, ip_id: str, resource: CustomResource, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> IP: """ Detach IP from a custom resource. @@ -526,7 +526,7 @@ def move_ip( *, ip_id: str, from_resource: CustomResource, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, to_resource: Optional[CustomResource] = None, ) -> IP: """ diff --git a/scaleway/scaleway/ipam/v1/types.py b/scaleway/scaleway/ipam/v1/types.py index f9504238b..0818893ab 100644 --- a/scaleway/scaleway/ipam/v1/types.py +++ b/scaleway/scaleway/ipam/v1/types.py @@ -8,8 +8,8 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -48,6 +48,8 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): MGDB_INSTANCE = "mgdb_instance" APPLE_SILICON_SERVER = "apple_silicon_server" APPLE_SILICON_PRIVATE_NIC = "apple_silicon_private_nic" + SERVERLESS_CONTAINER = "serverless_container" + SERVERLESS_FUNCTION = "serverless_function" def __str__(self) -> str: return str(self.value) @@ -143,7 +145,7 @@ class IP: Array of reverses associated with the IP. """ - region: Region + region: ScwRegion """ Region of the IP. """ @@ -168,7 +170,7 @@ class IP: Resource which the IP is attached to. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone of the IP, if zonal. """ @@ -186,7 +188,7 @@ class AttachIPRequest: Custom resource to be attached to the IP. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -204,7 +206,7 @@ class BookIPRequest: Request an IPv6 instead of an IPv4. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -242,7 +244,7 @@ class DetachIPRequest: Custom resource currently attached to the IP. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -255,7 +257,7 @@ class GetIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -263,7 +265,7 @@ class GetIPRequest: @dataclass class ListIPsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -374,7 +376,7 @@ class MoveIPRequest: Custom resource currently attached to the IP. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -392,7 +394,7 @@ class ReleaseIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -400,7 +402,7 @@ class ReleaseIPRequest: @dataclass class ReleaseIPSetRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -415,7 +417,7 @@ class UpdateIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ From 44203bed70bbe244d968d8d5284fc7964b478756 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 11 Feb 2025 16:50:27 +0100 Subject: [PATCH 15/73] feat(audit_trail): add key manager to resource api (#853) --- .../audit_trail/v1alpha1/__init__.py | 2 ++ .../audit_trail/v1alpha1/marshalling.py | 18 ++++++++++++++++++ .../audit_trail/v1alpha1/types.py | 8 ++++++++ .../scaleway/audit_trail/v1alpha1/__init__.py | 2 ++ .../audit_trail/v1alpha1/marshalling.py | 18 ++++++++++++++++++ .../scaleway/audit_trail/v1alpha1/types.py | 8 ++++++++ 6 files changed, 56 insertions(+) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/__init__.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/__init__.py index 296f59e5e..e64bad4cd 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/__init__.py @@ -2,6 +2,7 @@ # If you have any remark or suggestion do not hesitate to open an issue. from .types import ListEventsRequestOrderBy from .types import ResourceType +from .types import KeyManagerKeyInfo from .types import KubernetesACLInfo from .types import KubernetesClusterInfo from .types import KubernetesNodeInfo @@ -22,6 +23,7 @@ __all__ = [ "ListEventsRequestOrderBy", "ResourceType", + "KeyManagerKeyInfo", "KubernetesACLInfo", "KubernetesClusterInfo", "KubernetesNodeInfo", diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py index 5b8649e2d..aecfda29e 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py @@ -5,6 +5,7 @@ from dateutil import parser from .types import ( + KeyManagerKeyInfo, KubernetesACLInfo, KubernetesClusterInfo, KubernetesNodeInfo, @@ -21,6 +22,17 @@ ) +def unmarshal_KeyManagerKeyInfo(data: Any) -> KeyManagerKeyInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KeyManagerKeyInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return KeyManagerKeyInfo(**args) + + def unmarshal_KubernetesACLInfo(data: Any) -> KubernetesACLInfo: if not isinstance(data, dict): raise TypeError( @@ -206,6 +218,12 @@ def unmarshal_Resource(data: Any) -> Resource: else: args["kube_acl_info"] = None + field = data.get("keym_key_info", None) + if field is not None: + args["keym_key_info"] = unmarshal_KeyManagerKeyInfo(field) + else: + args["keym_key_info"] = None + return Resource(**args) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py index 73fb6b842..c81bfafbf 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py @@ -31,11 +31,17 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): KUBE_POOL = "kube_pool" KUBE_NODE = "kube_node" KUBE_ACL = "kube_acl" + KEYM_KEY = "keym_key" def __str__(self) -> str: return str(self.value) +@dataclass +class KeyManagerKeyInfo: + pass + + @dataclass class KubernetesACLInfo: pass @@ -101,6 +107,8 @@ class Resource: kube_acl_info: Optional[KubernetesACLInfo] + keym_key_info: Optional[KeyManagerKeyInfo] + @dataclass class ProductService: diff --git a/scaleway/scaleway/audit_trail/v1alpha1/__init__.py b/scaleway/scaleway/audit_trail/v1alpha1/__init__.py index 296f59e5e..e64bad4cd 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/__init__.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/__init__.py @@ -2,6 +2,7 @@ # If you have any remark or suggestion do not hesitate to open an issue. from .types import ListEventsRequestOrderBy from .types import ResourceType +from .types import KeyManagerKeyInfo from .types import KubernetesACLInfo from .types import KubernetesClusterInfo from .types import KubernetesNodeInfo @@ -22,6 +23,7 @@ __all__ = [ "ListEventsRequestOrderBy", "ResourceType", + "KeyManagerKeyInfo", "KubernetesACLInfo", "KubernetesClusterInfo", "KubernetesNodeInfo", diff --git a/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py b/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py index 5b8649e2d..aecfda29e 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py @@ -5,6 +5,7 @@ from dateutil import parser from .types import ( + KeyManagerKeyInfo, KubernetesACLInfo, KubernetesClusterInfo, KubernetesNodeInfo, @@ -21,6 +22,17 @@ ) +def unmarshal_KeyManagerKeyInfo(data: Any) -> KeyManagerKeyInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KeyManagerKeyInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return KeyManagerKeyInfo(**args) + + def unmarshal_KubernetesACLInfo(data: Any) -> KubernetesACLInfo: if not isinstance(data, dict): raise TypeError( @@ -206,6 +218,12 @@ def unmarshal_Resource(data: Any) -> Resource: else: args["kube_acl_info"] = None + field = data.get("keym_key_info", None) + if field is not None: + args["keym_key_info"] = unmarshal_KeyManagerKeyInfo(field) + else: + args["keym_key_info"] = None + return Resource(**args) diff --git a/scaleway/scaleway/audit_trail/v1alpha1/types.py b/scaleway/scaleway/audit_trail/v1alpha1/types.py index 73fb6b842..c81bfafbf 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/types.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/types.py @@ -31,11 +31,17 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): KUBE_POOL = "kube_pool" KUBE_NODE = "kube_node" KUBE_ACL = "kube_acl" + KEYM_KEY = "keym_key" def __str__(self) -> str: return str(self.value) +@dataclass +class KeyManagerKeyInfo: + pass + + @dataclass class KubernetesACLInfo: pass @@ -101,6 +107,8 @@ class Resource: kube_acl_info: Optional[KubernetesACLInfo] + keym_key_info: Optional[KeyManagerKeyInfo] + @dataclass class ProductService: From 09b66d94d7400b17bd6b16abe9377b76ff5e8673 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 13 Feb 2025 11:40:51 +0100 Subject: [PATCH 16/73] feat(k8s): add new token for external nodes (#854) --- scaleway-async/scaleway_async/k8s/v1/marshalling.py | 4 ++++ scaleway-async/scaleway_async/k8s/v1/types.py | 2 ++ scaleway/scaleway/k8s/v1/marshalling.py | 4 ++++ scaleway/scaleway/k8s/v1/types.py | 2 ++ 4 files changed, 12 insertions(+) diff --git a/scaleway-async/scaleway_async/k8s/v1/marshalling.py b/scaleway-async/scaleway_async/k8s/v1/marshalling.py index a325023d3..da0ede590 100644 --- a/scaleway-async/scaleway_async/k8s/v1/marshalling.py +++ b/scaleway-async/scaleway_async/k8s/v1/marshalling.py @@ -713,6 +713,10 @@ def unmarshal_ExternalNode(data: Any) -> ExternalNode: else None ) + field = data.get("iam_token", None) + if field is not None: + args["iam_token"] = field + return ExternalNode(**args) diff --git a/scaleway-async/scaleway_async/k8s/v1/types.py b/scaleway-async/scaleway_async/k8s/v1/types.py index a320b42c3..248f66071 100644 --- a/scaleway-async/scaleway_async/k8s/v1/types.py +++ b/scaleway-async/scaleway_async/k8s/v1/types.py @@ -1428,6 +1428,8 @@ class ExternalNode: node_taints: List[ExternalNodeCoreV1Taint] + iam_token: str + @dataclass class ExternalNodeAuth: diff --git a/scaleway/scaleway/k8s/v1/marshalling.py b/scaleway/scaleway/k8s/v1/marshalling.py index a325023d3..da0ede590 100644 --- a/scaleway/scaleway/k8s/v1/marshalling.py +++ b/scaleway/scaleway/k8s/v1/marshalling.py @@ -713,6 +713,10 @@ def unmarshal_ExternalNode(data: Any) -> ExternalNode: else None ) + field = data.get("iam_token", None) + if field is not None: + args["iam_token"] = field + return ExternalNode(**args) diff --git a/scaleway/scaleway/k8s/v1/types.py b/scaleway/scaleway/k8s/v1/types.py index a320b42c3..248f66071 100644 --- a/scaleway/scaleway/k8s/v1/types.py +++ b/scaleway/scaleway/k8s/v1/types.py @@ -1428,6 +1428,8 @@ class ExternalNode: node_taints: List[ExternalNodeCoreV1Taint] + iam_token: str + @dataclass class ExternalNodeAuth: From edbd5191274e7387cfb437147b647506df872155 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 13 Feb 2025 16:12:12 +0100 Subject: [PATCH 17/73] feat(edge_services): add WAF billing (#855) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> --- .../edge_services/v1alpha1/__init__.py | 2 + .../edge_services/v1alpha1/marshalling.py | 58 +++++++++++++++++-- .../edge_services/v1alpha1/types.py | 44 +++++++++++++- .../edge_services/v1alpha1/__init__.py | 2 + .../edge_services/v1alpha1/marshalling.py | 58 +++++++++++++++++-- .../scaleway/edge_services/v1alpha1/types.py | 44 +++++++++++++- 6 files changed, 194 insertions(+), 14 deletions(-) diff --git a/scaleway-async/scaleway_async/edge_services/v1alpha1/__init__.py b/scaleway-async/scaleway_async/edge_services/v1alpha1/__init__.py index 3b7aa44b5..a69731fd4 100644 --- a/scaleway-async/scaleway_async/edge_services/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/edge_services/v1alpha1/__init__.py @@ -30,6 +30,7 @@ from .types import TLSStage from .types import CheckPEMChainRequestSecretChain from .types import PlanDetails +from .types import PlanUsageDetails from .types import PipelineStages from .types import PurgeRequest from .types import TLSSecretsConfig @@ -115,6 +116,7 @@ "TLSStage", "CheckPEMChainRequestSecretChain", "PlanDetails", + "PlanUsageDetails", "PipelineStages", "PurgeRequest", "TLSSecretsConfig", diff --git a/scaleway-async/scaleway_async/edge_services/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/edge_services/v1alpha1/marshalling.py index d9c1b61f7..f9145ff06 100644 --- a/scaleway-async/scaleway_async/edge_services/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/edge_services/v1alpha1/marshalling.py @@ -29,6 +29,7 @@ CheckLbOriginResponse, CheckPEMChainResponse, PlanDetails, + PlanUsageDetails, GetBillingResponse, ListBackendStagesResponse, ListCacheStagesResponse, @@ -634,9 +635,30 @@ def unmarshal_PlanDetails(data: Any) -> PlanDetails: if field is not None: args["pipeline_limit"] = field + field = data.get("waf_requests", None) + if field is not None: + args["waf_requests"] = field + return PlanDetails(**args) +def unmarshal_PlanUsageDetails(data: Any) -> PlanUsageDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanUsageDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + return PlanUsageDetails(**args) + + def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: if not isinstance(data, dict): raise TypeError( @@ -645,6 +667,12 @@ def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: args: Dict[str, Any] = {} + field = data.get("current_plan", None) + if field is not None: + args["current_plan"] = unmarshal_PlanDetails(field) + else: + args["current_plan"] = None + field = data.get("pipeline_number", None) if field is not None: args["pipeline_number"] = field @@ -657,11 +685,13 @@ def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: if field is not None: args["extra_cache_usage"] = field - field = data.get("current_plan", None) + field = data.get("current_plan_waf_usage", None) if field is not None: - args["current_plan"] = unmarshal_PlanDetails(field) - else: - args["current_plan"] = None + args["current_plan_waf_usage"] = field + + field = data.get("extra_waf_usage", None) + if field is not None: + args["extra_waf_usage"] = field field = data.get("plan_cost", None) if field is not None: @@ -675,12 +705,32 @@ def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: else: args["extra_pipelines_cost"] = None + field = data.get("plans_usage_details", None) + if field is not None: + args["plans_usage_details"] = ( + {key: unmarshal_PlanUsageDetails(value) for key, value in field.items()} + if field is not None + else None + ) + field = data.get("extra_cache_cost", None) if field is not None: args["extra_cache_cost"] = unmarshal_Money(field) else: args["extra_cache_cost"] = None + field = data.get("extra_waf_cost", None) + if field is not None: + args["extra_waf_cost"] = unmarshal_Money(field) + else: + args["extra_waf_cost"] = None + + field = data.get("waf_add_on", None) + if field is not None: + args["waf_add_on"] = unmarshal_Money(field) + else: + args["waf_add_on"] = None + field = data.get("total_cost", None) if field is not None: args["total_cost"] = unmarshal_Money(field) diff --git a/scaleway-async/scaleway_async/edge_services/v1alpha1/types.py b/scaleway-async/scaleway_async/edge_services/v1alpha1/types.py index db2835ea0..a4121656a 100644 --- a/scaleway-async/scaleway_async/edge_services/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/edge_services/v1alpha1/types.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import List, Optional +from typing import Dict, List, Optional from scaleway_core.bridge import ( Money, @@ -502,6 +502,19 @@ class PlanDetails: Number of pipelines included in subscription plan. """ + waf_requests: int + """ + Number of WAF requests included in subscription plan. + """ + + +@dataclass +class PlanUsageDetails: + plan_cost: Optional[Money] + """ + Cost to date (this month) for the corresponding Edge Services subscription plan. + """ + @dataclass class PipelineStages: @@ -758,6 +771,11 @@ class GetBillingRequest: @dataclass class GetBillingResponse: + current_plan: Optional[PlanDetails] + """ + Information on the currently-selected, active Edge Services subscription plan. + """ + pipeline_number: int """ Total number of pipelines currently configured. @@ -773,9 +791,14 @@ class GetBillingResponse: Total amount of extra data egressed from cache in gigabytes from the beginning of the month, not included in the subscription plans. """ - current_plan: Optional[PlanDetails] + current_plan_waf_usage: int """ - Information on the currently-selected, active Edge Services subscription plan. + Total number of requests processed by the WAF since the beginning of the current month, for the active subscription plan. + """ + + extra_waf_usage: int + """ + Total number of extra requests processed by the WAF from the beginning of the month, not included in the subscription plans. """ plan_cost: Optional[Money] @@ -788,11 +811,26 @@ class GetBillingResponse: Cost to date (this month) of pipelines not included in the subscription plans. """ + plans_usage_details: Dict[str, PlanUsageDetails] + """ + Detailed costs and usage for all Edge Services subscription plans that were activated during the month. + """ + extra_cache_cost: Optional[Money] """ Cost to date (this month) of the data egressed from the cache that is not included in the subscription plans. """ + extra_waf_cost: Optional[Money] + """ + Cost to date (this month) of the extra requests processed by the WAF that were not included in the subscription plans. + """ + + waf_add_on: Optional[Money] + """ + Cost of activating WAF add-on (where subscription plan does not include WAF). + """ + total_cost: Optional[Money] """ Total cost to date (this month) of all Edge Services resources including active subscription plan, previously active plans, extra pipelines and extra egress cache data. diff --git a/scaleway/scaleway/edge_services/v1alpha1/__init__.py b/scaleway/scaleway/edge_services/v1alpha1/__init__.py index 3b7aa44b5..a69731fd4 100644 --- a/scaleway/scaleway/edge_services/v1alpha1/__init__.py +++ b/scaleway/scaleway/edge_services/v1alpha1/__init__.py @@ -30,6 +30,7 @@ from .types import TLSStage from .types import CheckPEMChainRequestSecretChain from .types import PlanDetails +from .types import PlanUsageDetails from .types import PipelineStages from .types import PurgeRequest from .types import TLSSecretsConfig @@ -115,6 +116,7 @@ "TLSStage", "CheckPEMChainRequestSecretChain", "PlanDetails", + "PlanUsageDetails", "PipelineStages", "PurgeRequest", "TLSSecretsConfig", diff --git a/scaleway/scaleway/edge_services/v1alpha1/marshalling.py b/scaleway/scaleway/edge_services/v1alpha1/marshalling.py index d9c1b61f7..f9145ff06 100644 --- a/scaleway/scaleway/edge_services/v1alpha1/marshalling.py +++ b/scaleway/scaleway/edge_services/v1alpha1/marshalling.py @@ -29,6 +29,7 @@ CheckLbOriginResponse, CheckPEMChainResponse, PlanDetails, + PlanUsageDetails, GetBillingResponse, ListBackendStagesResponse, ListCacheStagesResponse, @@ -634,9 +635,30 @@ def unmarshal_PlanDetails(data: Any) -> PlanDetails: if field is not None: args["pipeline_limit"] = field + field = data.get("waf_requests", None) + if field is not None: + args["waf_requests"] = field + return PlanDetails(**args) +def unmarshal_PlanUsageDetails(data: Any) -> PlanUsageDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanUsageDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + return PlanUsageDetails(**args) + + def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: if not isinstance(data, dict): raise TypeError( @@ -645,6 +667,12 @@ def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: args: Dict[str, Any] = {} + field = data.get("current_plan", None) + if field is not None: + args["current_plan"] = unmarshal_PlanDetails(field) + else: + args["current_plan"] = None + field = data.get("pipeline_number", None) if field is not None: args["pipeline_number"] = field @@ -657,11 +685,13 @@ def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: if field is not None: args["extra_cache_usage"] = field - field = data.get("current_plan", None) + field = data.get("current_plan_waf_usage", None) if field is not None: - args["current_plan"] = unmarshal_PlanDetails(field) - else: - args["current_plan"] = None + args["current_plan_waf_usage"] = field + + field = data.get("extra_waf_usage", None) + if field is not None: + args["extra_waf_usage"] = field field = data.get("plan_cost", None) if field is not None: @@ -675,12 +705,32 @@ def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: else: args["extra_pipelines_cost"] = None + field = data.get("plans_usage_details", None) + if field is not None: + args["plans_usage_details"] = ( + {key: unmarshal_PlanUsageDetails(value) for key, value in field.items()} + if field is not None + else None + ) + field = data.get("extra_cache_cost", None) if field is not None: args["extra_cache_cost"] = unmarshal_Money(field) else: args["extra_cache_cost"] = None + field = data.get("extra_waf_cost", None) + if field is not None: + args["extra_waf_cost"] = unmarshal_Money(field) + else: + args["extra_waf_cost"] = None + + field = data.get("waf_add_on", None) + if field is not None: + args["waf_add_on"] = unmarshal_Money(field) + else: + args["waf_add_on"] = None + field = data.get("total_cost", None) if field is not None: args["total_cost"] = unmarshal_Money(field) diff --git a/scaleway/scaleway/edge_services/v1alpha1/types.py b/scaleway/scaleway/edge_services/v1alpha1/types.py index db2835ea0..a4121656a 100644 --- a/scaleway/scaleway/edge_services/v1alpha1/types.py +++ b/scaleway/scaleway/edge_services/v1alpha1/types.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import List, Optional +from typing import Dict, List, Optional from scaleway_core.bridge import ( Money, @@ -502,6 +502,19 @@ class PlanDetails: Number of pipelines included in subscription plan. """ + waf_requests: int + """ + Number of WAF requests included in subscription plan. + """ + + +@dataclass +class PlanUsageDetails: + plan_cost: Optional[Money] + """ + Cost to date (this month) for the corresponding Edge Services subscription plan. + """ + @dataclass class PipelineStages: @@ -758,6 +771,11 @@ class GetBillingRequest: @dataclass class GetBillingResponse: + current_plan: Optional[PlanDetails] + """ + Information on the currently-selected, active Edge Services subscription plan. + """ + pipeline_number: int """ Total number of pipelines currently configured. @@ -773,9 +791,14 @@ class GetBillingResponse: Total amount of extra data egressed from cache in gigabytes from the beginning of the month, not included in the subscription plans. """ - current_plan: Optional[PlanDetails] + current_plan_waf_usage: int """ - Information on the currently-selected, active Edge Services subscription plan. + Total number of requests processed by the WAF since the beginning of the current month, for the active subscription plan. + """ + + extra_waf_usage: int + """ + Total number of extra requests processed by the WAF from the beginning of the month, not included in the subscription plans. """ plan_cost: Optional[Money] @@ -788,11 +811,26 @@ class GetBillingResponse: Cost to date (this month) of pipelines not included in the subscription plans. """ + plans_usage_details: Dict[str, PlanUsageDetails] + """ + Detailed costs and usage for all Edge Services subscription plans that were activated during the month. + """ + extra_cache_cost: Optional[Money] """ Cost to date (this month) of the data egressed from the cache that is not included in the subscription plans. """ + extra_waf_cost: Optional[Money] + """ + Cost to date (this month) of the extra requests processed by the WAF that were not included in the subscription plans. + """ + + waf_add_on: Optional[Money] + """ + Cost of activating WAF add-on (where subscription plan does not include WAF). + """ + total_cost: Optional[Money] """ Total cost to date (this month) of all Edge Services resources including active subscription plan, previously active plans, extra pipelines and extra egress cache data. From 3dba7b89ed36bd3f0df6f5660dca418d7bd18ab5 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 13 Feb 2025 17:29:32 +0100 Subject: [PATCH 18/73] feat(apple_silicon): introduce monthly commitment handling (#856) --- .../applesilicon/v1alpha1/__init__.py | 6 ++ .../applesilicon/v1alpha1/api.py | 8 ++ .../applesilicon/v1alpha1/marshalling.py | 79 +++++++++++++++---- .../applesilicon/v1alpha1/types.py | 66 ++++++++++++---- .../applesilicon/v1alpha1/__init__.py | 6 ++ .../scaleway/applesilicon/v1alpha1/api.py | 8 ++ .../applesilicon/v1alpha1/marshalling.py | 79 +++++++++++++++---- .../scaleway/applesilicon/v1alpha1/types.py | 66 ++++++++++++---- 8 files changed, 256 insertions(+), 62 deletions(-) diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/__init__.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/__init__.py index 6078c5b74..e50c753f5 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/__init__.py @@ -1,5 +1,6 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import CommitmentType from .types import ConnectivityDiagnosticActionType from .types import ConnectivityDiagnosticDiagnosticStatus from .types import ListServerPrivateNetworksRequestOrderBy @@ -17,10 +18,12 @@ from .types import ServerTypeGPU from .types import ServerTypeMemory from .types import ServerTypeNetwork +from .types import Commitment from .types import ConnectivityDiagnosticServerHealth from .types import ServerPrivateNetwork from .types import ServerType from .types import Server +from .types import CommitmentTypeValue from .types import ConnectivityDiagnostic from .types import CreateServerRequest from .types import DeleteServerRequest @@ -50,6 +53,7 @@ from .api import ApplesiliconV1Alpha1PrivateNetworkAPI __all__ = [ + "CommitmentType", "ConnectivityDiagnosticActionType", "ConnectivityDiagnosticDiagnosticStatus", "ListServerPrivateNetworksRequestOrderBy", @@ -67,10 +71,12 @@ "ServerTypeGPU", "ServerTypeMemory", "ServerTypeNetwork", + "Commitment", "ConnectivityDiagnosticServerHealth", "ServerPrivateNetwork", "ServerType", "Server", + "CommitmentTypeValue", "ConnectivityDiagnostic", "CreateServerRequest", "DeleteServerRequest", diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py index fa8041c50..d6d3c829b 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py @@ -15,8 +15,10 @@ wait_for_resource_async, ) from .types import ( + CommitmentType, ListServerPrivateNetworksRequestOrderBy, ListServersRequestOrderBy, + CommitmentTypeValue, ConnectivityDiagnostic, CreateServerRequest, ListOSResponse, @@ -133,6 +135,7 @@ async def create_server( name: Optional[str] = None, project_id: Optional[str] = None, os_id: Optional[str] = None, + commitment_type: Optional[CommitmentType] = None, ) -> Server: """ Create a server. @@ -143,6 +146,7 @@ async def create_server( :param name: Create a server with this given name. :param project_id: Create a server in the given project ID. :param os_id: Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. + :param commitment_type: Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing. It can be updated with the Update Server request. Available commitment depends on server type. :return: :class:`Server ` Usage: @@ -167,6 +171,7 @@ async def create_server( name=name or random_name(prefix="as"), project_id=project_id, os_id=os_id, + commitment_type=commitment_type, ), self.client, ), @@ -449,6 +454,7 @@ async def update_server( name: Optional[str] = None, schedule_deletion: Optional[bool] = None, enable_vpc: Optional[bool] = None, + commitment_type: Optional[CommitmentTypeValue] = None, ) -> Server: """ Update a server. @@ -458,6 +464,7 @@ async def update_server( :param name: Updated name for your server. :param schedule_deletion: Specify whether the server should be flagged for automatic deletion. :param enable_vpc: Activate or deactivate Private Network support for this server. + :param commitment_type: Change commitment. Use 'none' to automatically cancel a renewing commitment. :return: :class:`Server ` Usage: @@ -481,6 +488,7 @@ async def update_server( name=name, schedule_deletion=schedule_deletion, enable_vpc=enable_vpc, + commitment_type=commitment_type, ), self.client, ), diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/marshalling.py index edbb4774b..be75811b6 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/marshalling.py @@ -15,6 +15,7 @@ ServerTypeMemory, ServerTypeNetwork, ServerType, + Commitment, Server, ConnectivityDiagnosticServerHealth, ConnectivityDiagnostic, @@ -29,6 +30,7 @@ PrivateNetworkApiSetServerPrivateNetworksRequest, ReinstallServerRequest, StartConnectivityDiagnosticRequest, + CommitmentTypeValue, UpdateServerRequest, ) @@ -285,6 +287,25 @@ def unmarshal_ServerType(data: Any) -> ServerType: return ServerType(**args) +def unmarshal_Commitment(data: Any) -> Commitment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Commitment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("cancelled", None) + if field is not None: + args["cancelled"] = field + + return Commitment(**args) + + def unmarshal_Server(data: Any) -> Server: if not isinstance(data, dict): raise TypeError( @@ -337,22 +358,6 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["status"] = field - field = data.get("deletion_scheduled", None) - if field is not None: - args["deletion_scheduled"] = field - - field = data.get("zone", None) - if field is not None: - args["zone"] = field - - field = data.get("delivered", None) - if field is not None: - args["delivered"] = field - - field = data.get("vpc_status", None) - if field is not None: - args["vpc_status"] = field - field = data.get("os", None) if field is not None: args["os"] = unmarshal_OS(field) @@ -379,6 +384,28 @@ def unmarshal_Server(data: Any) -> Server: else: args["deletable_at"] = None + field = data.get("deletion_scheduled", None) + if field is not None: + args["deletion_scheduled"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("delivered", None) + if field is not None: + args["delivered"] = field + + field = data.get("vpc_status", None) + if field is not None: + args["vpc_status"] = field + + field = data.get("commitment", None) + if field is not None: + args["commitment"] = unmarshal_Commitment(field) + else: + args["commitment"] = None + return Server(**args) @@ -605,6 +632,9 @@ def marshal_CreateServerRequest( if request.os_id is not None: output["os_id"] = request.os_id + if request.commitment_type is not None: + output["commitment_type"] = str(request.commitment_type) + return output @@ -661,6 +691,18 @@ def marshal_StartConnectivityDiagnosticRequest( return output +def marshal_CommitmentTypeValue( + request: CommitmentTypeValue, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.commitment_type is not None: + output["commitment_type"] = str(request.commitment_type) + + return output + + def marshal_UpdateServerRequest( request: UpdateServerRequest, defaults: ProfileDefaults, @@ -676,4 +718,9 @@ def marshal_UpdateServerRequest( if request.enable_vpc is not None: output["enable_vpc"] = request.enable_vpc + if request.commitment_type is not None: + output["commitment_type"] = marshal_CommitmentTypeValue( + request.commitment_type, defaults + ) + return output diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py index 0fcedef7c..7826d2b8a 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py @@ -15,6 +15,15 @@ ) +class CommitmentType(str, Enum, metaclass=StrEnumMeta): + DURATION_24H = "duration_24h" + RENEWED_MONTHLY = "renewed_monthly" + NONE = "none" + + def __str__(self) -> str: + return str(self.value) + + class ConnectivityDiagnosticActionType(str, Enum, metaclass=StrEnumMeta): REBOOT_SERVER = "reboot_server" REINSTALL_SERVER = "reinstall_server" @@ -181,6 +190,13 @@ class ServerTypeNetwork: public_bandwidth_bps: int +@dataclass +class Commitment: + type_: CommitmentType + + cancelled: bool + + @dataclass class ConnectivityDiagnosticServerHealth: is_server_alive: bool @@ -349,6 +365,26 @@ class Server: Current status of the server. """ + os: Optional[OS] + """ + Initially installed OS, this does not necessarily reflect the current OS version. + """ + + created_at: Optional[datetime] + """ + Date on which the server was created. + """ + + updated_at: Optional[datetime] + """ + Date on which the server was last updated. + """ + + deletable_at: Optional[datetime] + """ + Date from which the server can be deleted. + """ + deletion_scheduled: bool """ Set to true to mark the server for automatic deletion depending on `deletable_at` date. Set to false to cancel an existing deletion schedule. Leave unset otherwise. @@ -369,25 +405,15 @@ class Server: Activation status of optional Private Network feature support for this server. """ - os: Optional[OS] + commitment: Optional[Commitment] """ - Initially installed OS, this does not necessarily reflect the current OS version. + Commitment scheme applied to this server. """ - created_at: Optional[datetime] - """ - Date on which the server was created. - """ - updated_at: Optional[datetime] - """ - Date on which the server was last updated. - """ - - deletable_at: Optional[datetime] - """ - Date from which the server can be deleted. - """ +@dataclass +class CommitmentTypeValue: + commitment_type: CommitmentType @dataclass @@ -437,6 +463,11 @@ class CreateServerRequest: Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. """ + commitment_type: Optional[CommitmentType] + """ + Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing. It can be updated with the Update Server request. Available commitment depends on server type. + """ + @dataclass class DeleteServerRequest: @@ -806,3 +837,8 @@ class UpdateServerRequest: """ Activate or deactivate Private Network support for this server. """ + + commitment_type: Optional[CommitmentTypeValue] + """ + Change commitment. Use 'none' to automatically cancel a renewing commitment. + """ diff --git a/scaleway/scaleway/applesilicon/v1alpha1/__init__.py b/scaleway/scaleway/applesilicon/v1alpha1/__init__.py index 6078c5b74..e50c753f5 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/__init__.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/__init__.py @@ -1,5 +1,6 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import CommitmentType from .types import ConnectivityDiagnosticActionType from .types import ConnectivityDiagnosticDiagnosticStatus from .types import ListServerPrivateNetworksRequestOrderBy @@ -17,10 +18,12 @@ from .types import ServerTypeGPU from .types import ServerTypeMemory from .types import ServerTypeNetwork +from .types import Commitment from .types import ConnectivityDiagnosticServerHealth from .types import ServerPrivateNetwork from .types import ServerType from .types import Server +from .types import CommitmentTypeValue from .types import ConnectivityDiagnostic from .types import CreateServerRequest from .types import DeleteServerRequest @@ -50,6 +53,7 @@ from .api import ApplesiliconV1Alpha1PrivateNetworkAPI __all__ = [ + "CommitmentType", "ConnectivityDiagnosticActionType", "ConnectivityDiagnosticDiagnosticStatus", "ListServerPrivateNetworksRequestOrderBy", @@ -67,10 +71,12 @@ "ServerTypeGPU", "ServerTypeMemory", "ServerTypeNetwork", + "Commitment", "ConnectivityDiagnosticServerHealth", "ServerPrivateNetwork", "ServerType", "Server", + "CommitmentTypeValue", "ConnectivityDiagnostic", "CreateServerRequest", "DeleteServerRequest", diff --git a/scaleway/scaleway/applesilicon/v1alpha1/api.py b/scaleway/scaleway/applesilicon/v1alpha1/api.py index 22b8d1846..2ed357428 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/api.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/api.py @@ -15,8 +15,10 @@ wait_for_resource, ) from .types import ( + CommitmentType, ListServerPrivateNetworksRequestOrderBy, ListServersRequestOrderBy, + CommitmentTypeValue, ConnectivityDiagnostic, CreateServerRequest, ListOSResponse, @@ -133,6 +135,7 @@ def create_server( name: Optional[str] = None, project_id: Optional[str] = None, os_id: Optional[str] = None, + commitment_type: Optional[CommitmentType] = None, ) -> Server: """ Create a server. @@ -143,6 +146,7 @@ def create_server( :param name: Create a server with this given name. :param project_id: Create a server in the given project ID. :param os_id: Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. + :param commitment_type: Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing. It can be updated with the Update Server request. Available commitment depends on server type. :return: :class:`Server ` Usage: @@ -167,6 +171,7 @@ def create_server( name=name or random_name(prefix="as"), project_id=project_id, os_id=os_id, + commitment_type=commitment_type, ), self.client, ), @@ -449,6 +454,7 @@ def update_server( name: Optional[str] = None, schedule_deletion: Optional[bool] = None, enable_vpc: Optional[bool] = None, + commitment_type: Optional[CommitmentTypeValue] = None, ) -> Server: """ Update a server. @@ -458,6 +464,7 @@ def update_server( :param name: Updated name for your server. :param schedule_deletion: Specify whether the server should be flagged for automatic deletion. :param enable_vpc: Activate or deactivate Private Network support for this server. + :param commitment_type: Change commitment. Use 'none' to automatically cancel a renewing commitment. :return: :class:`Server ` Usage: @@ -481,6 +488,7 @@ def update_server( name=name, schedule_deletion=schedule_deletion, enable_vpc=enable_vpc, + commitment_type=commitment_type, ), self.client, ), diff --git a/scaleway/scaleway/applesilicon/v1alpha1/marshalling.py b/scaleway/scaleway/applesilicon/v1alpha1/marshalling.py index edbb4774b..be75811b6 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/marshalling.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/marshalling.py @@ -15,6 +15,7 @@ ServerTypeMemory, ServerTypeNetwork, ServerType, + Commitment, Server, ConnectivityDiagnosticServerHealth, ConnectivityDiagnostic, @@ -29,6 +30,7 @@ PrivateNetworkApiSetServerPrivateNetworksRequest, ReinstallServerRequest, StartConnectivityDiagnosticRequest, + CommitmentTypeValue, UpdateServerRequest, ) @@ -285,6 +287,25 @@ def unmarshal_ServerType(data: Any) -> ServerType: return ServerType(**args) +def unmarshal_Commitment(data: Any) -> Commitment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Commitment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("cancelled", None) + if field is not None: + args["cancelled"] = field + + return Commitment(**args) + + def unmarshal_Server(data: Any) -> Server: if not isinstance(data, dict): raise TypeError( @@ -337,22 +358,6 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["status"] = field - field = data.get("deletion_scheduled", None) - if field is not None: - args["deletion_scheduled"] = field - - field = data.get("zone", None) - if field is not None: - args["zone"] = field - - field = data.get("delivered", None) - if field is not None: - args["delivered"] = field - - field = data.get("vpc_status", None) - if field is not None: - args["vpc_status"] = field - field = data.get("os", None) if field is not None: args["os"] = unmarshal_OS(field) @@ -379,6 +384,28 @@ def unmarshal_Server(data: Any) -> Server: else: args["deletable_at"] = None + field = data.get("deletion_scheduled", None) + if field is not None: + args["deletion_scheduled"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("delivered", None) + if field is not None: + args["delivered"] = field + + field = data.get("vpc_status", None) + if field is not None: + args["vpc_status"] = field + + field = data.get("commitment", None) + if field is not None: + args["commitment"] = unmarshal_Commitment(field) + else: + args["commitment"] = None + return Server(**args) @@ -605,6 +632,9 @@ def marshal_CreateServerRequest( if request.os_id is not None: output["os_id"] = request.os_id + if request.commitment_type is not None: + output["commitment_type"] = str(request.commitment_type) + return output @@ -661,6 +691,18 @@ def marshal_StartConnectivityDiagnosticRequest( return output +def marshal_CommitmentTypeValue( + request: CommitmentTypeValue, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.commitment_type is not None: + output["commitment_type"] = str(request.commitment_type) + + return output + + def marshal_UpdateServerRequest( request: UpdateServerRequest, defaults: ProfileDefaults, @@ -676,4 +718,9 @@ def marshal_UpdateServerRequest( if request.enable_vpc is not None: output["enable_vpc"] = request.enable_vpc + if request.commitment_type is not None: + output["commitment_type"] = marshal_CommitmentTypeValue( + request.commitment_type, defaults + ) + return output diff --git a/scaleway/scaleway/applesilicon/v1alpha1/types.py b/scaleway/scaleway/applesilicon/v1alpha1/types.py index 0fcedef7c..7826d2b8a 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/types.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/types.py @@ -15,6 +15,15 @@ ) +class CommitmentType(str, Enum, metaclass=StrEnumMeta): + DURATION_24H = "duration_24h" + RENEWED_MONTHLY = "renewed_monthly" + NONE = "none" + + def __str__(self) -> str: + return str(self.value) + + class ConnectivityDiagnosticActionType(str, Enum, metaclass=StrEnumMeta): REBOOT_SERVER = "reboot_server" REINSTALL_SERVER = "reinstall_server" @@ -181,6 +190,13 @@ class ServerTypeNetwork: public_bandwidth_bps: int +@dataclass +class Commitment: + type_: CommitmentType + + cancelled: bool + + @dataclass class ConnectivityDiagnosticServerHealth: is_server_alive: bool @@ -349,6 +365,26 @@ class Server: Current status of the server. """ + os: Optional[OS] + """ + Initially installed OS, this does not necessarily reflect the current OS version. + """ + + created_at: Optional[datetime] + """ + Date on which the server was created. + """ + + updated_at: Optional[datetime] + """ + Date on which the server was last updated. + """ + + deletable_at: Optional[datetime] + """ + Date from which the server can be deleted. + """ + deletion_scheduled: bool """ Set to true to mark the server for automatic deletion depending on `deletable_at` date. Set to false to cancel an existing deletion schedule. Leave unset otherwise. @@ -369,25 +405,15 @@ class Server: Activation status of optional Private Network feature support for this server. """ - os: Optional[OS] + commitment: Optional[Commitment] """ - Initially installed OS, this does not necessarily reflect the current OS version. + Commitment scheme applied to this server. """ - created_at: Optional[datetime] - """ - Date on which the server was created. - """ - updated_at: Optional[datetime] - """ - Date on which the server was last updated. - """ - - deletable_at: Optional[datetime] - """ - Date from which the server can be deleted. - """ +@dataclass +class CommitmentTypeValue: + commitment_type: CommitmentType @dataclass @@ -437,6 +463,11 @@ class CreateServerRequest: Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. """ + commitment_type: Optional[CommitmentType] + """ + Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing. It can be updated with the Update Server request. Available commitment depends on server type. + """ + @dataclass class DeleteServerRequest: @@ -806,3 +837,8 @@ class UpdateServerRequest: """ Activate or deactivate Private Network support for this server. """ + + commitment_type: Optional[CommitmentTypeValue] + """ + Change commitment. Use 'none' to automatically cancel a renewing commitment. + """ From 49b8bb10174576910dec6b2067e75d9cbb230921 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 18 Feb 2025 15:45:37 +0100 Subject: [PATCH 19/73] feat(cockpit): add support for `RegionalApiListAlertsRequest` (#857) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémy Léone --- .../scaleway_async/cockpit/v1/__init__.py | 8 ++ .../scaleway_async/cockpit/v1/api.py | 46 +++++++++++ .../scaleway_async/cockpit/v1/marshalling.py | 62 ++++++++++++++ .../scaleway_async/cockpit/v1/types.py | 82 ++++++++++++++++++- scaleway/scaleway/cockpit/v1/__init__.py | 8 ++ scaleway/scaleway/cockpit/v1/api.py | 46 +++++++++++ scaleway/scaleway/cockpit/v1/marshalling.py | 62 ++++++++++++++ scaleway/scaleway/cockpit/v1/types.py | 82 ++++++++++++++++++- 8 files changed, 394 insertions(+), 2 deletions(-) diff --git a/scaleway-async/scaleway_async/cockpit/v1/__init__.py b/scaleway-async/scaleway_async/cockpit/v1/__init__.py index a648fc794..5137711f8 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/__init__.py +++ b/scaleway-async/scaleway_async/cockpit/v1/__init__.py @@ -1,5 +1,6 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import AnyAlertState from .types import DataSourceOrigin from .types import DataSourceType from .types import GrafanaUserRole @@ -13,6 +14,7 @@ from .types import UsageUnit from .types import ContactPointEmail from .types import GetConfigResponseRetention +from .types import AnyAlert from .types import ContactPoint from .types import DataSource from .types import GrafanaProductDashboard @@ -35,6 +37,7 @@ from .types import GlobalApiSelectPlanRequest from .types import GlobalApiSyncGrafanaDataSourcesRequest from .types import Grafana +from .types import ListAlertsResponse from .types import ListContactPointsResponse from .types import ListDataSourcesResponse from .types import ListGrafanaProductDashboardsResponse @@ -57,6 +60,7 @@ from .types import RegionalApiGetDataSourceRequest from .types import RegionalApiGetTokenRequest from .types import RegionalApiGetUsageOverviewRequest +from .types import RegionalApiListAlertsRequest from .types import RegionalApiListContactPointsRequest from .types import RegionalApiListDataSourcesRequest from .types import RegionalApiListManagedAlertsRequest @@ -69,6 +73,7 @@ from .api import CockpitV1RegionalAPI __all__ = [ + "AnyAlertState", "DataSourceOrigin", "DataSourceType", "GrafanaUserRole", @@ -82,6 +87,7 @@ "UsageUnit", "ContactPointEmail", "GetConfigResponseRetention", + "AnyAlert", "ContactPoint", "DataSource", "GrafanaProductDashboard", @@ -104,6 +110,7 @@ "GlobalApiSelectPlanRequest", "GlobalApiSyncGrafanaDataSourcesRequest", "Grafana", + "ListAlertsResponse", "ListContactPointsResponse", "ListDataSourcesResponse", "ListGrafanaProductDashboardsResponse", @@ -126,6 +133,7 @@ "RegionalApiGetDataSourceRequest", "RegionalApiGetTokenRequest", "RegionalApiGetUsageOverviewRequest", + "RegionalApiListAlertsRequest", "RegionalApiListContactPointsRequest", "RegionalApiListDataSourcesRequest", "RegionalApiListManagedAlertsRequest", diff --git a/scaleway-async/scaleway_async/cockpit/v1/api.py b/scaleway-async/scaleway_async/cockpit/v1/api.py index 6833fdbf3..1d234dd48 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/api.py +++ b/scaleway-async/scaleway_async/cockpit/v1/api.py @@ -12,6 +12,7 @@ fetch_all_pages_async, ) from .types import ( + AnyAlertState, DataSourceOrigin, DataSourceType, GrafanaUserRole, @@ -35,6 +36,7 @@ Grafana, GrafanaProductDashboard, GrafanaUser, + ListAlertsResponse, ListContactPointsResponse, ListDataSourcesResponse, ListGrafanaProductDashboardsResponse, @@ -67,6 +69,7 @@ unmarshal_AlertManager, unmarshal_GetConfigResponse, unmarshal_Grafana, + unmarshal_ListAlertsResponse, unmarshal_ListContactPointsResponse, unmarshal_ListDataSourcesResponse, unmarshal_ListGrafanaProductDashboardsResponse, @@ -1512,6 +1515,49 @@ async def list_managed_alerts_all( }, ) + async def list_alerts( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + is_enabled: Optional[bool] = None, + is_preconfigured: Optional[bool] = None, + state: Optional[AnyAlertState] = None, + ) -> ListAlertsResponse: + """ + List alerts. + List preconfigured and/or custom alerts for the specified Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Project ID to filter for, only alerts from this Project will be returned. + :param is_enabled: True returns only enabled alerts. False returns only disabled alerts. If omitted, no alert filtering is applied. Other filters may still apply. + :param is_preconfigured: True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. + :param state: Valid values to filter on are `disabled`, `enabled`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. + :return: :class:`ListAlertsResponse ` + + Usage: + :: + + result = await api.list_alerts() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/alerts", + params={ + "is_enabled": is_enabled, + "is_preconfigured": is_preconfigured, + "project_id": project_id or self.client.default_project_id, + "state": state, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListAlertsResponse(res.json()) + async def enable_managed_alerts( self, *, diff --git a/scaleway-async/scaleway_async/cockpit/v1/marshalling.py b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py index 6739977d0..03b6090ff 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/marshalling.py +++ b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py @@ -22,6 +22,8 @@ GetConfigResponseRetention, GetConfigResponse, Grafana, + AnyAlert, + ListAlertsResponse, ListContactPointsResponse, ListDataSourcesResponse, ListGrafanaProductDashboardsResponse, @@ -415,6 +417,66 @@ def unmarshal_Grafana(data: Any) -> Grafana: return Grafana(**args) +def unmarshal_AnyAlert(data: Any) -> AnyAlert: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AnyAlert' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("preconfigured", None) + if field is not None: + args["preconfigured"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("rule", None) + if field is not None: + args["rule"] = field + + field = data.get("duration", None) + if field is not None: + args["duration"] = field + + field = data.get("state", None) + if field is not None: + args["state"] = field + + field = data.get("annotations", None) + if field is not None: + args["annotations"] = field + + return AnyAlert(**args) + + +def unmarshal_ListAlertsResponse(data: Any) -> ListAlertsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListAlertsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("alerts", None) + if field is not None: + args["alerts"] = ( + [unmarshal_AnyAlert(v) for v in field] if field is not None else None + ) + + return ListAlertsResponse(**args) + + def unmarshal_ListContactPointsResponse(data: Any) -> ListContactPointsResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway-async/scaleway_async/cockpit/v1/types.py b/scaleway-async/scaleway_async/cockpit/v1/types.py index d7363a866..7f50e6629 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/types.py +++ b/scaleway-async/scaleway_async/cockpit/v1/types.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import List, Optional +from typing import Dict, List, Optional from scaleway_core.bridge import ( Region as ScwRegion, @@ -15,6 +15,17 @@ ) +class AnyAlertState(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATE = "unknown_state" + DISABLED = "disabled" + ENABLED = "enabled" + PENDING = "pending" + FIRING = "firing" + + def __str__(self) -> str: + return str(self.value) + + class DataSourceOrigin(str, Enum, metaclass=StrEnumMeta): UNKNOWN_ORIGIN = "unknown_origin" SCALEWAY = "scaleway" @@ -143,6 +154,26 @@ class GetConfigResponseRetention: default_days: int +@dataclass +class AnyAlert: + region: ScwRegion + """ + Region to target. If none is passed will use default region from the config. + """ + + preconfigured: bool + + name: str + + rule: str + + duration: str + + state: AnyAlertState + + annotations: Dict[str, str] + + @dataclass class ContactPoint: """ @@ -707,6 +738,23 @@ class Grafana: """ +@dataclass +class ListAlertsResponse: + """ + Retrieve a list of alerts matching the request. + """ + + total_count: int + """ + Total count of alerts matching the request. + """ + + alerts: List[AnyAlert] + """ + List of alerts matching the applied filters. + """ + + @dataclass class ListContactPointsResponse: """ @@ -1115,6 +1163,38 @@ class RegionalApiGetUsageOverviewRequest: interval: Optional[str] +@dataclass +class RegionalApiListAlertsRequest: + """ + Retrieve a list of alerts. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only alerts from this Project will be returned. + """ + + is_enabled: Optional[bool] + """ + True returns only enabled alerts. False returns only disabled alerts. If omitted, no alert filtering is applied. Other filters may still apply. + """ + + is_preconfigured: Optional[bool] + """ + True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. + """ + + state: Optional[AnyAlertState] + """ + Valid values to filter on are `disabled`, `enabled`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. + """ + + @dataclass class RegionalApiListContactPointsRequest: """ diff --git a/scaleway/scaleway/cockpit/v1/__init__.py b/scaleway/scaleway/cockpit/v1/__init__.py index a648fc794..5137711f8 100644 --- a/scaleway/scaleway/cockpit/v1/__init__.py +++ b/scaleway/scaleway/cockpit/v1/__init__.py @@ -1,5 +1,6 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import AnyAlertState from .types import DataSourceOrigin from .types import DataSourceType from .types import GrafanaUserRole @@ -13,6 +14,7 @@ from .types import UsageUnit from .types import ContactPointEmail from .types import GetConfigResponseRetention +from .types import AnyAlert from .types import ContactPoint from .types import DataSource from .types import GrafanaProductDashboard @@ -35,6 +37,7 @@ from .types import GlobalApiSelectPlanRequest from .types import GlobalApiSyncGrafanaDataSourcesRequest from .types import Grafana +from .types import ListAlertsResponse from .types import ListContactPointsResponse from .types import ListDataSourcesResponse from .types import ListGrafanaProductDashboardsResponse @@ -57,6 +60,7 @@ from .types import RegionalApiGetDataSourceRequest from .types import RegionalApiGetTokenRequest from .types import RegionalApiGetUsageOverviewRequest +from .types import RegionalApiListAlertsRequest from .types import RegionalApiListContactPointsRequest from .types import RegionalApiListDataSourcesRequest from .types import RegionalApiListManagedAlertsRequest @@ -69,6 +73,7 @@ from .api import CockpitV1RegionalAPI __all__ = [ + "AnyAlertState", "DataSourceOrigin", "DataSourceType", "GrafanaUserRole", @@ -82,6 +87,7 @@ "UsageUnit", "ContactPointEmail", "GetConfigResponseRetention", + "AnyAlert", "ContactPoint", "DataSource", "GrafanaProductDashboard", @@ -104,6 +110,7 @@ "GlobalApiSelectPlanRequest", "GlobalApiSyncGrafanaDataSourcesRequest", "Grafana", + "ListAlertsResponse", "ListContactPointsResponse", "ListDataSourcesResponse", "ListGrafanaProductDashboardsResponse", @@ -126,6 +133,7 @@ "RegionalApiGetDataSourceRequest", "RegionalApiGetTokenRequest", "RegionalApiGetUsageOverviewRequest", + "RegionalApiListAlertsRequest", "RegionalApiListContactPointsRequest", "RegionalApiListDataSourcesRequest", "RegionalApiListManagedAlertsRequest", diff --git a/scaleway/scaleway/cockpit/v1/api.py b/scaleway/scaleway/cockpit/v1/api.py index 0be7b2ca2..9f19a0c7a 100644 --- a/scaleway/scaleway/cockpit/v1/api.py +++ b/scaleway/scaleway/cockpit/v1/api.py @@ -12,6 +12,7 @@ fetch_all_pages, ) from .types import ( + AnyAlertState, DataSourceOrigin, DataSourceType, GrafanaUserRole, @@ -35,6 +36,7 @@ Grafana, GrafanaProductDashboard, GrafanaUser, + ListAlertsResponse, ListContactPointsResponse, ListDataSourcesResponse, ListGrafanaProductDashboardsResponse, @@ -67,6 +69,7 @@ unmarshal_AlertManager, unmarshal_GetConfigResponse, unmarshal_Grafana, + unmarshal_ListAlertsResponse, unmarshal_ListContactPointsResponse, unmarshal_ListDataSourcesResponse, unmarshal_ListGrafanaProductDashboardsResponse, @@ -1512,6 +1515,49 @@ def list_managed_alerts_all( }, ) + def list_alerts( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + is_enabled: Optional[bool] = None, + is_preconfigured: Optional[bool] = None, + state: Optional[AnyAlertState] = None, + ) -> ListAlertsResponse: + """ + List alerts. + List preconfigured and/or custom alerts for the specified Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Project ID to filter for, only alerts from this Project will be returned. + :param is_enabled: True returns only enabled alerts. False returns only disabled alerts. If omitted, no alert filtering is applied. Other filters may still apply. + :param is_preconfigured: True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. + :param state: Valid values to filter on are `disabled`, `enabled`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. + :return: :class:`ListAlertsResponse ` + + Usage: + :: + + result = api.list_alerts() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/alerts", + params={ + "is_enabled": is_enabled, + "is_preconfigured": is_preconfigured, + "project_id": project_id or self.client.default_project_id, + "state": state, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListAlertsResponse(res.json()) + def enable_managed_alerts( self, *, diff --git a/scaleway/scaleway/cockpit/v1/marshalling.py b/scaleway/scaleway/cockpit/v1/marshalling.py index 6739977d0..03b6090ff 100644 --- a/scaleway/scaleway/cockpit/v1/marshalling.py +++ b/scaleway/scaleway/cockpit/v1/marshalling.py @@ -22,6 +22,8 @@ GetConfigResponseRetention, GetConfigResponse, Grafana, + AnyAlert, + ListAlertsResponse, ListContactPointsResponse, ListDataSourcesResponse, ListGrafanaProductDashboardsResponse, @@ -415,6 +417,66 @@ def unmarshal_Grafana(data: Any) -> Grafana: return Grafana(**args) +def unmarshal_AnyAlert(data: Any) -> AnyAlert: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AnyAlert' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("preconfigured", None) + if field is not None: + args["preconfigured"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("rule", None) + if field is not None: + args["rule"] = field + + field = data.get("duration", None) + if field is not None: + args["duration"] = field + + field = data.get("state", None) + if field is not None: + args["state"] = field + + field = data.get("annotations", None) + if field is not None: + args["annotations"] = field + + return AnyAlert(**args) + + +def unmarshal_ListAlertsResponse(data: Any) -> ListAlertsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListAlertsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("alerts", None) + if field is not None: + args["alerts"] = ( + [unmarshal_AnyAlert(v) for v in field] if field is not None else None + ) + + return ListAlertsResponse(**args) + + def unmarshal_ListContactPointsResponse(data: Any) -> ListContactPointsResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway/scaleway/cockpit/v1/types.py b/scaleway/scaleway/cockpit/v1/types.py index d7363a866..7f50e6629 100644 --- a/scaleway/scaleway/cockpit/v1/types.py +++ b/scaleway/scaleway/cockpit/v1/types.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import List, Optional +from typing import Dict, List, Optional from scaleway_core.bridge import ( Region as ScwRegion, @@ -15,6 +15,17 @@ ) +class AnyAlertState(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATE = "unknown_state" + DISABLED = "disabled" + ENABLED = "enabled" + PENDING = "pending" + FIRING = "firing" + + def __str__(self) -> str: + return str(self.value) + + class DataSourceOrigin(str, Enum, metaclass=StrEnumMeta): UNKNOWN_ORIGIN = "unknown_origin" SCALEWAY = "scaleway" @@ -143,6 +154,26 @@ class GetConfigResponseRetention: default_days: int +@dataclass +class AnyAlert: + region: ScwRegion + """ + Region to target. If none is passed will use default region from the config. + """ + + preconfigured: bool + + name: str + + rule: str + + duration: str + + state: AnyAlertState + + annotations: Dict[str, str] + + @dataclass class ContactPoint: """ @@ -707,6 +738,23 @@ class Grafana: """ +@dataclass +class ListAlertsResponse: + """ + Retrieve a list of alerts matching the request. + """ + + total_count: int + """ + Total count of alerts matching the request. + """ + + alerts: List[AnyAlert] + """ + List of alerts matching the applied filters. + """ + + @dataclass class ListContactPointsResponse: """ @@ -1115,6 +1163,38 @@ class RegionalApiGetUsageOverviewRequest: interval: Optional[str] +@dataclass +class RegionalApiListAlertsRequest: + """ + Retrieve a list of alerts. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only alerts from this Project will be returned. + """ + + is_enabled: Optional[bool] + """ + True returns only enabled alerts. False returns only disabled alerts. If omitted, no alert filtering is applied. Other filters may still apply. + """ + + is_preconfigured: Optional[bool] + """ + True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. + """ + + state: Optional[AnyAlertState] + """ + Valid values to filter on are `disabled`, `enabled`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. + """ + + @dataclass class RegionalApiListContactPointsRequest: """ From 6d499fa2b64970749164a94f90cabe5d04bc738d Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 18 Feb 2025 15:49:34 +0100 Subject: [PATCH 20/73] feat(lb): add support for `connection_rate_limit` (#858) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémy Léone --- scaleway-async/scaleway_async/lb/v1/api.py | 12 +++++++++ .../scaleway_async/lb/v1/marshalling.py | 18 +++++++++++++ scaleway-async/scaleway_async/lb/v1/types.py | 25 +++++++++++++++++++ scaleway/scaleway/lb/v1/api.py | 12 +++++++++ scaleway/scaleway/lb/v1/marshalling.py | 18 +++++++++++++ scaleway/scaleway/lb/v1/types.py | 25 +++++++++++++++++++ 6 files changed, 110 insertions(+) diff --git a/scaleway-async/scaleway_async/lb/v1/api.py b/scaleway-async/scaleway_async/lb/v1/api.py index 1929ba5ee..bd34829f7 100644 --- a/scaleway-async/scaleway_async/lb/v1/api.py +++ b/scaleway-async/scaleway_async/lb/v1/api.py @@ -1515,6 +1515,7 @@ async def create_frontend( timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Create a frontend in a given Load Balancer. @@ -1528,6 +1529,7 @@ async def create_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -1558,6 +1560,7 @@ async def create_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -1610,6 +1613,7 @@ async def update_frontend( timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Update a frontend. @@ -1623,6 +1627,7 @@ async def update_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -1654,6 +1659,7 @@ async def update_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -4549,6 +4555,7 @@ async def create_frontend( timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Create a frontend in a given load balancer. @@ -4561,6 +4568,7 @@ async def create_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -4593,6 +4601,7 @@ async def create_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -4646,6 +4655,7 @@ async def update_frontend( timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Update a frontend. @@ -4658,6 +4668,7 @@ async def update_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -4691,6 +4702,7 @@ async def update_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), diff --git a/scaleway-async/scaleway_async/lb/v1/marshalling.py b/scaleway-async/scaleway_async/lb/v1/marshalling.py index 126b14591..9a2e94fd0 100644 --- a/scaleway-async/scaleway_async/lb/v1/marshalling.py +++ b/scaleway-async/scaleway_async/lb/v1/marshalling.py @@ -855,6 +855,12 @@ def unmarshal_Frontend(data: Any) -> Frontend: else: args["updated_at"] = None + field = data.get("connection_rate_limit", None) + if field is not None: + args["connection_rate_limit"] = field + else: + args["connection_rate_limit"] = None + return Frontend(**args) @@ -1928,6 +1934,9 @@ def marshal_CreateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2283,6 +2292,9 @@ def marshal_UpdateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2576,6 +2588,9 @@ def marshal_ZonedApiCreateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2926,6 +2941,9 @@ def marshal_ZonedApiUpdateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output diff --git a/scaleway-async/scaleway_async/lb/v1/types.py b/scaleway-async/scaleway_async/lb/v1/types.py index 10556a962..51fadbc9c 100644 --- a/scaleway-async/scaleway_async/lb/v1/types.py +++ b/scaleway-async/scaleway_async/lb/v1/types.py @@ -944,6 +944,11 @@ class Frontend: Date on which the frontend was last updated. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class PrivateNetworkDHCPConfig: @@ -1476,6 +1481,11 @@ class CreateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class CreateIpRequest: @@ -2680,6 +2690,11 @@ class UpdateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class UpdateHealthCheckRequest: @@ -3120,6 +3135,11 @@ class ZonedApiCreateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class ZonedApiCreateIpRequest: @@ -4178,6 +4198,11 @@ class ZonedApiUpdateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class ZonedApiUpdateHealthCheckRequest: diff --git a/scaleway/scaleway/lb/v1/api.py b/scaleway/scaleway/lb/v1/api.py index 30becc0ad..038a93d88 100644 --- a/scaleway/scaleway/lb/v1/api.py +++ b/scaleway/scaleway/lb/v1/api.py @@ -1515,6 +1515,7 @@ def create_frontend( timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Create a frontend in a given Load Balancer. @@ -1528,6 +1529,7 @@ def create_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -1558,6 +1560,7 @@ def create_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -1610,6 +1613,7 @@ def update_frontend( timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Update a frontend. @@ -1623,6 +1627,7 @@ def update_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -1654,6 +1659,7 @@ def update_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -4547,6 +4553,7 @@ def create_frontend( timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Create a frontend in a given load balancer. @@ -4559,6 +4566,7 @@ def create_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -4591,6 +4599,7 @@ def create_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -4644,6 +4653,7 @@ def update_frontend( timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Update a frontend. @@ -4656,6 +4666,7 @@ def update_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -4689,6 +4700,7 @@ def update_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), diff --git a/scaleway/scaleway/lb/v1/marshalling.py b/scaleway/scaleway/lb/v1/marshalling.py index 126b14591..9a2e94fd0 100644 --- a/scaleway/scaleway/lb/v1/marshalling.py +++ b/scaleway/scaleway/lb/v1/marshalling.py @@ -855,6 +855,12 @@ def unmarshal_Frontend(data: Any) -> Frontend: else: args["updated_at"] = None + field = data.get("connection_rate_limit", None) + if field is not None: + args["connection_rate_limit"] = field + else: + args["connection_rate_limit"] = None + return Frontend(**args) @@ -1928,6 +1934,9 @@ def marshal_CreateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2283,6 +2292,9 @@ def marshal_UpdateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2576,6 +2588,9 @@ def marshal_ZonedApiCreateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2926,6 +2941,9 @@ def marshal_ZonedApiUpdateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output diff --git a/scaleway/scaleway/lb/v1/types.py b/scaleway/scaleway/lb/v1/types.py index 10556a962..51fadbc9c 100644 --- a/scaleway/scaleway/lb/v1/types.py +++ b/scaleway/scaleway/lb/v1/types.py @@ -944,6 +944,11 @@ class Frontend: Date on which the frontend was last updated. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class PrivateNetworkDHCPConfig: @@ -1476,6 +1481,11 @@ class CreateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class CreateIpRequest: @@ -2680,6 +2690,11 @@ class UpdateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class UpdateHealthCheckRequest: @@ -3120,6 +3135,11 @@ class ZonedApiCreateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class ZonedApiCreateIpRequest: @@ -4178,6 +4198,11 @@ class ZonedApiUpdateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class ZonedApiUpdateHealthCheckRequest: From 6581fd2973f8c9668e0c5e84132004b5f8cf2bb0 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Fri, 21 Feb 2025 10:35:18 +0100 Subject: [PATCH 21/73] feat(audit_trail): add IAM resources (#859) --- scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py | 6 ++++++ scaleway/scaleway/audit_trail/v1alpha1/types.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py index c81bfafbf..f604cf347 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py @@ -32,6 +32,12 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): KUBE_NODE = "kube_node" KUBE_ACL = "kube_acl" KEYM_KEY = "keym_key" + IAMX_USER = "iamx_user" + IAMX_APPLICATION = "iamx_application" + IAMX_GROUP = "iamx_group" + IAMX_POLICY = "iamx_policy" + IAMX_API_KEY = "iamx_api_key" + IAMX_SSH_KEY = "iamx_ssh_key" def __str__(self) -> str: return str(self.value) diff --git a/scaleway/scaleway/audit_trail/v1alpha1/types.py b/scaleway/scaleway/audit_trail/v1alpha1/types.py index c81bfafbf..f604cf347 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/types.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/types.py @@ -32,6 +32,12 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): KUBE_NODE = "kube_node" KUBE_ACL = "kube_acl" KEYM_KEY = "keym_key" + IAMX_USER = "iamx_user" + IAMX_APPLICATION = "iamx_application" + IAMX_GROUP = "iamx_group" + IAMX_POLICY = "iamx_policy" + IAMX_API_KEY = "iamx_api_key" + IAMX_SSH_KEY = "iamx_ssh_key" def __str__(self) -> str: return str(self.value) From 30d5e3074e5ccbb8bac092305b6d3f722c33a377 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Fri, 21 Feb 2025 10:36:08 +0100 Subject: [PATCH 22/73] chore(cockpit): remove `list_managed_alerts` (#860) --- .../scaleway_async/cockpit/v1/__init__.py | 16 +--- .../scaleway_async/cockpit/v1/api.py | 89 +------------------ .../scaleway_async/cockpit/v1/marshalling.py | 74 +++------------ .../scaleway_async/cockpit/v1/types.py | 89 ++----------------- scaleway/scaleway/cockpit/v1/__init__.py | 16 +--- scaleway/scaleway/cockpit/v1/api.py | 89 +------------------ scaleway/scaleway/cockpit/v1/marshalling.py | 74 +++------------ scaleway/scaleway/cockpit/v1/types.py | 89 ++----------------- 8 files changed, 54 insertions(+), 482 deletions(-) diff --git a/scaleway-async/scaleway_async/cockpit/v1/__init__.py b/scaleway-async/scaleway_async/cockpit/v1/__init__.py index 5137711f8..abac82780 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/__init__.py +++ b/scaleway-async/scaleway_async/cockpit/v1/__init__.py @@ -1,12 +1,11 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. -from .types import AnyAlertState +from .types import AlertState from .types import DataSourceOrigin from .types import DataSourceType from .types import GrafanaUserRole from .types import ListDataSourcesRequestOrderBy from .types import ListGrafanaUsersRequestOrderBy -from .types import ListManagedAlertsRequestOrderBy from .types import ListPlansRequestOrderBy from .types import ListTokensRequestOrderBy from .types import PlanName @@ -14,12 +13,11 @@ from .types import UsageUnit from .types import ContactPointEmail from .types import GetConfigResponseRetention -from .types import AnyAlert +from .types import Alert from .types import ContactPoint from .types import DataSource from .types import GrafanaProductDashboard from .types import GrafanaUser -from .types import Alert from .types import Plan from .types import Token from .types import Usage @@ -42,7 +40,6 @@ from .types import ListDataSourcesResponse from .types import ListGrafanaProductDashboardsResponse from .types import ListGrafanaUsersResponse -from .types import ListManagedAlertsResponse from .types import ListPlansResponse from .types import ListTokensResponse from .types import RegionalApiCreateContactPointRequest @@ -63,7 +60,6 @@ from .types import RegionalApiListAlertsRequest from .types import RegionalApiListContactPointsRequest from .types import RegionalApiListDataSourcesRequest -from .types import RegionalApiListManagedAlertsRequest from .types import RegionalApiListTokensRequest from .types import RegionalApiTriggerTestAlertRequest from .types import RegionalApiUpdateContactPointRequest @@ -73,13 +69,12 @@ from .api import CockpitV1RegionalAPI __all__ = [ - "AnyAlertState", + "AlertState", "DataSourceOrigin", "DataSourceType", "GrafanaUserRole", "ListDataSourcesRequestOrderBy", "ListGrafanaUsersRequestOrderBy", - "ListManagedAlertsRequestOrderBy", "ListPlansRequestOrderBy", "ListTokensRequestOrderBy", "PlanName", @@ -87,12 +82,11 @@ "UsageUnit", "ContactPointEmail", "GetConfigResponseRetention", - "AnyAlert", + "Alert", "ContactPoint", "DataSource", "GrafanaProductDashboard", "GrafanaUser", - "Alert", "Plan", "Token", "Usage", @@ -115,7 +109,6 @@ "ListDataSourcesResponse", "ListGrafanaProductDashboardsResponse", "ListGrafanaUsersResponse", - "ListManagedAlertsResponse", "ListPlansResponse", "ListTokensResponse", "RegionalApiCreateContactPointRequest", @@ -136,7 +129,6 @@ "RegionalApiListAlertsRequest", "RegionalApiListContactPointsRequest", "RegionalApiListDataSourcesRequest", - "RegionalApiListManagedAlertsRequest", "RegionalApiListTokensRequest", "RegionalApiTriggerTestAlertRequest", "RegionalApiUpdateContactPointRequest", diff --git a/scaleway-async/scaleway_async/cockpit/v1/api.py b/scaleway-async/scaleway_async/cockpit/v1/api.py index 1d234dd48..22bda241f 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/api.py +++ b/scaleway-async/scaleway_async/cockpit/v1/api.py @@ -12,18 +12,16 @@ fetch_all_pages_async, ) from .types import ( - AnyAlertState, + AlertState, DataSourceOrigin, DataSourceType, GrafanaUserRole, ListDataSourcesRequestOrderBy, ListGrafanaUsersRequestOrderBy, - ListManagedAlertsRequestOrderBy, ListPlansRequestOrderBy, ListTokensRequestOrderBy, PlanName, TokenScope, - Alert, AlertManager, ContactPoint, ContactPointEmail, @@ -41,7 +39,6 @@ ListDataSourcesResponse, ListGrafanaProductDashboardsResponse, ListGrafanaUsersResponse, - ListManagedAlertsResponse, ListPlansResponse, ListTokensResponse, Plan, @@ -74,7 +71,6 @@ unmarshal_ListDataSourcesResponse, unmarshal_ListGrafanaProductDashboardsResponse, unmarshal_ListGrafanaUsersResponse, - unmarshal_ListManagedAlertsResponse, unmarshal_ListPlansResponse, unmarshal_ListTokensResponse, unmarshal_UsageOverview, @@ -1434,87 +1430,6 @@ async def delete_contact_point( self._throw_on_error(res) - async def list_managed_alerts( - self, - *, - region: Optional[ScwRegion] = None, - page: Optional[int] = None, - page_size: Optional[int] = None, - order_by: Optional[ListManagedAlertsRequestOrderBy] = None, - project_id: Optional[str] = None, - ) -> ListManagedAlertsResponse: - """ - List managed alerts. - List all managed alerts for the specified Project. - :param region: Region to target. If none is passed will use default region from the config. - :param page: Page number to return, from the paginated results. - :param page_size: Number of data sources to return per page. - :param order_by: Sort order for data sources in the response. - :param project_id: Project ID to filter for, only data sources from this Project will be returned. - :return: :class:`ListManagedAlertsResponse ` - - Usage: - :: - - result = await api.list_managed_alerts() - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - - res = self._request( - "GET", - f"/cockpit/v1/regions/{param_region}/managed-alerts", - params={ - "order_by": order_by, - "page": page, - "page_size": page_size or self.client.default_page_size, - "project_id": project_id or self.client.default_project_id, - }, - ) - - self._throw_on_error(res) - return unmarshal_ListManagedAlertsResponse(res.json()) - - async def list_managed_alerts_all( - self, - *, - region: Optional[ScwRegion] = None, - page: Optional[int] = None, - page_size: Optional[int] = None, - order_by: Optional[ListManagedAlertsRequestOrderBy] = None, - project_id: Optional[str] = None, - ) -> List[Alert]: - """ - List managed alerts. - List all managed alerts for the specified Project. - :param region: Region to target. If none is passed will use default region from the config. - :param page: Page number to return, from the paginated results. - :param page_size: Number of data sources to return per page. - :param order_by: Sort order for data sources in the response. - :param project_id: Project ID to filter for, only data sources from this Project will be returned. - :return: :class:`List[Alert] ` - - Usage: - :: - - result = await api.list_managed_alerts_all() - """ - - return await fetch_all_pages_async( - type=ListManagedAlertsResponse, - key="alerts", - fetcher=self.list_managed_alerts, - args={ - "region": region, - "page": page, - "page_size": page_size, - "order_by": order_by, - "project_id": project_id, - }, - ) - async def list_alerts( self, *, @@ -1522,7 +1437,7 @@ async def list_alerts( project_id: Optional[str] = None, is_enabled: Optional[bool] = None, is_preconfigured: Optional[bool] = None, - state: Optional[AnyAlertState] = None, + state: Optional[AlertState] = None, ) -> ListAlertsResponse: """ List alerts. diff --git a/scaleway-async/scaleway_async/cockpit/v1/marshalling.py b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py index 03b6090ff..5a72373eb 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/marshalling.py +++ b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py @@ -22,14 +22,12 @@ GetConfigResponseRetention, GetConfigResponse, Grafana, - AnyAlert, + Alert, ListAlertsResponse, ListContactPointsResponse, ListDataSourcesResponse, ListGrafanaProductDashboardsResponse, ListGrafanaUsersResponse, - Alert, - ListManagedAlertsResponse, ListPlansResponse, ListTokensResponse, Usage, @@ -417,10 +415,10 @@ def unmarshal_Grafana(data: Any) -> Grafana: return Grafana(**args) -def unmarshal_AnyAlert(data: Any) -> AnyAlert: +def unmarshal_Alert(data: Any) -> Alert: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'AnyAlert' failed as data isn't a dictionary." + "Unmarshalling the type 'Alert' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} @@ -445,15 +443,21 @@ def unmarshal_AnyAlert(data: Any) -> AnyAlert: if field is not None: args["duration"] = field - field = data.get("state", None) + field = data.get("enabled", None) if field is not None: - args["state"] = field + args["enabled"] = field field = data.get("annotations", None) if field is not None: args["annotations"] = field - return AnyAlert(**args) + field = data.get("state", None) + if field is not None: + args["state"] = field + else: + args["state"] = None + + return Alert(**args) def unmarshal_ListAlertsResponse(data: Any) -> ListAlertsResponse: @@ -471,7 +475,7 @@ def unmarshal_ListAlertsResponse(data: Any) -> ListAlertsResponse: field = data.get("alerts", None) if field is not None: args["alerts"] = ( - [unmarshal_AnyAlert(v) for v in field] if field is not None else None + [unmarshal_Alert(v) for v in field] if field is not None else None ) return ListAlertsResponse(**args) @@ -573,58 +577,6 @@ def unmarshal_ListGrafanaUsersResponse(data: Any) -> ListGrafanaUsersResponse: return ListGrafanaUsersResponse(**args) -def unmarshal_Alert(data: Any) -> Alert: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'Alert' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("product_family", None) - if field is not None: - args["product_family"] = field - - field = data.get("product", None) - if field is not None: - args["product"] = field - - field = data.get("name", None) - if field is not None: - args["name"] = field - - field = data.get("rule", None) - if field is not None: - args["rule"] = field - - field = data.get("description", None) - if field is not None: - args["description"] = field - - return Alert(**args) - - -def unmarshal_ListManagedAlertsResponse(data: Any) -> ListManagedAlertsResponse: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListManagedAlertsResponse' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("total_count", None) - if field is not None: - args["total_count"] = field - - field = data.get("alerts", None) - if field is not None: - args["alerts"] = ( - [unmarshal_Alert(v) for v in field] if field is not None else None - ) - - return ListManagedAlertsResponse(**args) - - def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway-async/scaleway_async/cockpit/v1/types.py b/scaleway-async/scaleway_async/cockpit/v1/types.py index 7f50e6629..967fae25f 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/types.py +++ b/scaleway-async/scaleway_async/cockpit/v1/types.py @@ -15,10 +15,9 @@ ) -class AnyAlertState(str, Enum, metaclass=StrEnumMeta): +class AlertState(str, Enum, metaclass=StrEnumMeta): UNKNOWN_STATE = "unknown_state" - DISABLED = "disabled" - ENABLED = "enabled" + INACTIVE = "inactive" PENDING = "pending" FIRING = "firing" @@ -75,18 +74,6 @@ def __str__(self) -> str: return str(self.value) -class ListManagedAlertsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): - CREATED_AT_ASC = "created_at_asc" - CREATED_AT_DESC = "created_at_desc" - NAME_ASC = "name_asc" - NAME_DESC = "name_desc" - TYPE_ASC = "type_asc" - TYPE_DESC = "type_desc" - - def __str__(self) -> str: - return str(self.value) - - class ListPlansRequestOrderBy(str, Enum, metaclass=StrEnumMeta): NAME_ASC = "name_asc" NAME_DESC = "name_desc" @@ -155,7 +142,7 @@ class GetConfigResponseRetention: @dataclass -class AnyAlert: +class Alert: region: ScwRegion """ Region to target. If none is passed will use default region from the config. @@ -169,10 +156,12 @@ class AnyAlert: duration: str - state: AnyAlertState + enabled: bool annotations: Dict[str, str] + state: Optional[AlertState] + @dataclass class ContactPoint: @@ -314,19 +303,6 @@ class GrafanaUser: """ -@dataclass -class Alert: - product_family: str - - product: str - - name: str - - rule: str - - description: str - - @dataclass class Plan: """ @@ -749,7 +725,7 @@ class ListAlertsResponse: Total count of alerts matching the request. """ - alerts: List[AnyAlert] + alerts: List[Alert] """ List of alerts matching the applied filters. """ @@ -833,23 +809,6 @@ class ListGrafanaUsersResponse: """ -@dataclass -class ListManagedAlertsResponse: - """ - Response returned when listing data sources. - """ - - total_count: int - """ - Total count of data sources matching the request. - """ - - alerts: List[Alert] - """ - Alerts matching the request within the pagination. - """ - - @dataclass class ListPlansResponse: """ @@ -1189,7 +1148,7 @@ class RegionalApiListAlertsRequest: True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. """ - state: Optional[AnyAlertState] + state: Optional[AlertState] """ Valid values to filter on are `disabled`, `enabled`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. """ @@ -1264,38 +1223,6 @@ class RegionalApiListDataSourcesRequest: """ -@dataclass -class RegionalApiListManagedAlertsRequest: - """ - Enable the sending of managed alerts. - """ - - region: Optional[ScwRegion] - """ - Region to target. If none is passed will use default region from the config. - """ - - page: Optional[int] - """ - Page number to return, from the paginated results. - """ - - page_size: Optional[int] - """ - Number of data sources to return per page. - """ - - order_by: Optional[ListManagedAlertsRequestOrderBy] - """ - Sort order for data sources in the response. - """ - - project_id: Optional[str] - """ - Project ID to filter for, only data sources from this Project will be returned. - """ - - @dataclass class RegionalApiListTokensRequest: """ diff --git a/scaleway/scaleway/cockpit/v1/__init__.py b/scaleway/scaleway/cockpit/v1/__init__.py index 5137711f8..abac82780 100644 --- a/scaleway/scaleway/cockpit/v1/__init__.py +++ b/scaleway/scaleway/cockpit/v1/__init__.py @@ -1,12 +1,11 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. -from .types import AnyAlertState +from .types import AlertState from .types import DataSourceOrigin from .types import DataSourceType from .types import GrafanaUserRole from .types import ListDataSourcesRequestOrderBy from .types import ListGrafanaUsersRequestOrderBy -from .types import ListManagedAlertsRequestOrderBy from .types import ListPlansRequestOrderBy from .types import ListTokensRequestOrderBy from .types import PlanName @@ -14,12 +13,11 @@ from .types import UsageUnit from .types import ContactPointEmail from .types import GetConfigResponseRetention -from .types import AnyAlert +from .types import Alert from .types import ContactPoint from .types import DataSource from .types import GrafanaProductDashboard from .types import GrafanaUser -from .types import Alert from .types import Plan from .types import Token from .types import Usage @@ -42,7 +40,6 @@ from .types import ListDataSourcesResponse from .types import ListGrafanaProductDashboardsResponse from .types import ListGrafanaUsersResponse -from .types import ListManagedAlertsResponse from .types import ListPlansResponse from .types import ListTokensResponse from .types import RegionalApiCreateContactPointRequest @@ -63,7 +60,6 @@ from .types import RegionalApiListAlertsRequest from .types import RegionalApiListContactPointsRequest from .types import RegionalApiListDataSourcesRequest -from .types import RegionalApiListManagedAlertsRequest from .types import RegionalApiListTokensRequest from .types import RegionalApiTriggerTestAlertRequest from .types import RegionalApiUpdateContactPointRequest @@ -73,13 +69,12 @@ from .api import CockpitV1RegionalAPI __all__ = [ - "AnyAlertState", + "AlertState", "DataSourceOrigin", "DataSourceType", "GrafanaUserRole", "ListDataSourcesRequestOrderBy", "ListGrafanaUsersRequestOrderBy", - "ListManagedAlertsRequestOrderBy", "ListPlansRequestOrderBy", "ListTokensRequestOrderBy", "PlanName", @@ -87,12 +82,11 @@ "UsageUnit", "ContactPointEmail", "GetConfigResponseRetention", - "AnyAlert", + "Alert", "ContactPoint", "DataSource", "GrafanaProductDashboard", "GrafanaUser", - "Alert", "Plan", "Token", "Usage", @@ -115,7 +109,6 @@ "ListDataSourcesResponse", "ListGrafanaProductDashboardsResponse", "ListGrafanaUsersResponse", - "ListManagedAlertsResponse", "ListPlansResponse", "ListTokensResponse", "RegionalApiCreateContactPointRequest", @@ -136,7 +129,6 @@ "RegionalApiListAlertsRequest", "RegionalApiListContactPointsRequest", "RegionalApiListDataSourcesRequest", - "RegionalApiListManagedAlertsRequest", "RegionalApiListTokensRequest", "RegionalApiTriggerTestAlertRequest", "RegionalApiUpdateContactPointRequest", diff --git a/scaleway/scaleway/cockpit/v1/api.py b/scaleway/scaleway/cockpit/v1/api.py index 9f19a0c7a..e97de018e 100644 --- a/scaleway/scaleway/cockpit/v1/api.py +++ b/scaleway/scaleway/cockpit/v1/api.py @@ -12,18 +12,16 @@ fetch_all_pages, ) from .types import ( - AnyAlertState, + AlertState, DataSourceOrigin, DataSourceType, GrafanaUserRole, ListDataSourcesRequestOrderBy, ListGrafanaUsersRequestOrderBy, - ListManagedAlertsRequestOrderBy, ListPlansRequestOrderBy, ListTokensRequestOrderBy, PlanName, TokenScope, - Alert, AlertManager, ContactPoint, ContactPointEmail, @@ -41,7 +39,6 @@ ListDataSourcesResponse, ListGrafanaProductDashboardsResponse, ListGrafanaUsersResponse, - ListManagedAlertsResponse, ListPlansResponse, ListTokensResponse, Plan, @@ -74,7 +71,6 @@ unmarshal_ListDataSourcesResponse, unmarshal_ListGrafanaProductDashboardsResponse, unmarshal_ListGrafanaUsersResponse, - unmarshal_ListManagedAlertsResponse, unmarshal_ListPlansResponse, unmarshal_ListTokensResponse, unmarshal_UsageOverview, @@ -1434,87 +1430,6 @@ def delete_contact_point( self._throw_on_error(res) - def list_managed_alerts( - self, - *, - region: Optional[ScwRegion] = None, - page: Optional[int] = None, - page_size: Optional[int] = None, - order_by: Optional[ListManagedAlertsRequestOrderBy] = None, - project_id: Optional[str] = None, - ) -> ListManagedAlertsResponse: - """ - List managed alerts. - List all managed alerts for the specified Project. - :param region: Region to target. If none is passed will use default region from the config. - :param page: Page number to return, from the paginated results. - :param page_size: Number of data sources to return per page. - :param order_by: Sort order for data sources in the response. - :param project_id: Project ID to filter for, only data sources from this Project will be returned. - :return: :class:`ListManagedAlertsResponse ` - - Usage: - :: - - result = api.list_managed_alerts() - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - - res = self._request( - "GET", - f"/cockpit/v1/regions/{param_region}/managed-alerts", - params={ - "order_by": order_by, - "page": page, - "page_size": page_size or self.client.default_page_size, - "project_id": project_id or self.client.default_project_id, - }, - ) - - self._throw_on_error(res) - return unmarshal_ListManagedAlertsResponse(res.json()) - - def list_managed_alerts_all( - self, - *, - region: Optional[ScwRegion] = None, - page: Optional[int] = None, - page_size: Optional[int] = None, - order_by: Optional[ListManagedAlertsRequestOrderBy] = None, - project_id: Optional[str] = None, - ) -> List[Alert]: - """ - List managed alerts. - List all managed alerts for the specified Project. - :param region: Region to target. If none is passed will use default region from the config. - :param page: Page number to return, from the paginated results. - :param page_size: Number of data sources to return per page. - :param order_by: Sort order for data sources in the response. - :param project_id: Project ID to filter for, only data sources from this Project will be returned. - :return: :class:`List[Alert] ` - - Usage: - :: - - result = api.list_managed_alerts_all() - """ - - return fetch_all_pages( - type=ListManagedAlertsResponse, - key="alerts", - fetcher=self.list_managed_alerts, - args={ - "region": region, - "page": page, - "page_size": page_size, - "order_by": order_by, - "project_id": project_id, - }, - ) - def list_alerts( self, *, @@ -1522,7 +1437,7 @@ def list_alerts( project_id: Optional[str] = None, is_enabled: Optional[bool] = None, is_preconfigured: Optional[bool] = None, - state: Optional[AnyAlertState] = None, + state: Optional[AlertState] = None, ) -> ListAlertsResponse: """ List alerts. diff --git a/scaleway/scaleway/cockpit/v1/marshalling.py b/scaleway/scaleway/cockpit/v1/marshalling.py index 03b6090ff..5a72373eb 100644 --- a/scaleway/scaleway/cockpit/v1/marshalling.py +++ b/scaleway/scaleway/cockpit/v1/marshalling.py @@ -22,14 +22,12 @@ GetConfigResponseRetention, GetConfigResponse, Grafana, - AnyAlert, + Alert, ListAlertsResponse, ListContactPointsResponse, ListDataSourcesResponse, ListGrafanaProductDashboardsResponse, ListGrafanaUsersResponse, - Alert, - ListManagedAlertsResponse, ListPlansResponse, ListTokensResponse, Usage, @@ -417,10 +415,10 @@ def unmarshal_Grafana(data: Any) -> Grafana: return Grafana(**args) -def unmarshal_AnyAlert(data: Any) -> AnyAlert: +def unmarshal_Alert(data: Any) -> Alert: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'AnyAlert' failed as data isn't a dictionary." + "Unmarshalling the type 'Alert' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} @@ -445,15 +443,21 @@ def unmarshal_AnyAlert(data: Any) -> AnyAlert: if field is not None: args["duration"] = field - field = data.get("state", None) + field = data.get("enabled", None) if field is not None: - args["state"] = field + args["enabled"] = field field = data.get("annotations", None) if field is not None: args["annotations"] = field - return AnyAlert(**args) + field = data.get("state", None) + if field is not None: + args["state"] = field + else: + args["state"] = None + + return Alert(**args) def unmarshal_ListAlertsResponse(data: Any) -> ListAlertsResponse: @@ -471,7 +475,7 @@ def unmarshal_ListAlertsResponse(data: Any) -> ListAlertsResponse: field = data.get("alerts", None) if field is not None: args["alerts"] = ( - [unmarshal_AnyAlert(v) for v in field] if field is not None else None + [unmarshal_Alert(v) for v in field] if field is not None else None ) return ListAlertsResponse(**args) @@ -573,58 +577,6 @@ def unmarshal_ListGrafanaUsersResponse(data: Any) -> ListGrafanaUsersResponse: return ListGrafanaUsersResponse(**args) -def unmarshal_Alert(data: Any) -> Alert: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'Alert' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("product_family", None) - if field is not None: - args["product_family"] = field - - field = data.get("product", None) - if field is not None: - args["product"] = field - - field = data.get("name", None) - if field is not None: - args["name"] = field - - field = data.get("rule", None) - if field is not None: - args["rule"] = field - - field = data.get("description", None) - if field is not None: - args["description"] = field - - return Alert(**args) - - -def unmarshal_ListManagedAlertsResponse(data: Any) -> ListManagedAlertsResponse: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListManagedAlertsResponse' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("total_count", None) - if field is not None: - args["total_count"] = field - - field = data.get("alerts", None) - if field is not None: - args["alerts"] = ( - [unmarshal_Alert(v) for v in field] if field is not None else None - ) - - return ListManagedAlertsResponse(**args) - - def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway/scaleway/cockpit/v1/types.py b/scaleway/scaleway/cockpit/v1/types.py index 7f50e6629..967fae25f 100644 --- a/scaleway/scaleway/cockpit/v1/types.py +++ b/scaleway/scaleway/cockpit/v1/types.py @@ -15,10 +15,9 @@ ) -class AnyAlertState(str, Enum, metaclass=StrEnumMeta): +class AlertState(str, Enum, metaclass=StrEnumMeta): UNKNOWN_STATE = "unknown_state" - DISABLED = "disabled" - ENABLED = "enabled" + INACTIVE = "inactive" PENDING = "pending" FIRING = "firing" @@ -75,18 +74,6 @@ def __str__(self) -> str: return str(self.value) -class ListManagedAlertsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): - CREATED_AT_ASC = "created_at_asc" - CREATED_AT_DESC = "created_at_desc" - NAME_ASC = "name_asc" - NAME_DESC = "name_desc" - TYPE_ASC = "type_asc" - TYPE_DESC = "type_desc" - - def __str__(self) -> str: - return str(self.value) - - class ListPlansRequestOrderBy(str, Enum, metaclass=StrEnumMeta): NAME_ASC = "name_asc" NAME_DESC = "name_desc" @@ -155,7 +142,7 @@ class GetConfigResponseRetention: @dataclass -class AnyAlert: +class Alert: region: ScwRegion """ Region to target. If none is passed will use default region from the config. @@ -169,10 +156,12 @@ class AnyAlert: duration: str - state: AnyAlertState + enabled: bool annotations: Dict[str, str] + state: Optional[AlertState] + @dataclass class ContactPoint: @@ -314,19 +303,6 @@ class GrafanaUser: """ -@dataclass -class Alert: - product_family: str - - product: str - - name: str - - rule: str - - description: str - - @dataclass class Plan: """ @@ -749,7 +725,7 @@ class ListAlertsResponse: Total count of alerts matching the request. """ - alerts: List[AnyAlert] + alerts: List[Alert] """ List of alerts matching the applied filters. """ @@ -833,23 +809,6 @@ class ListGrafanaUsersResponse: """ -@dataclass -class ListManagedAlertsResponse: - """ - Response returned when listing data sources. - """ - - total_count: int - """ - Total count of data sources matching the request. - """ - - alerts: List[Alert] - """ - Alerts matching the request within the pagination. - """ - - @dataclass class ListPlansResponse: """ @@ -1189,7 +1148,7 @@ class RegionalApiListAlertsRequest: True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. """ - state: Optional[AnyAlertState] + state: Optional[AlertState] """ Valid values to filter on are `disabled`, `enabled`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. """ @@ -1264,38 +1223,6 @@ class RegionalApiListDataSourcesRequest: """ -@dataclass -class RegionalApiListManagedAlertsRequest: - """ - Enable the sending of managed alerts. - """ - - region: Optional[ScwRegion] - """ - Region to target. If none is passed will use default region from the config. - """ - - page: Optional[int] - """ - Page number to return, from the paginated results. - """ - - page_size: Optional[int] - """ - Number of data sources to return per page. - """ - - order_by: Optional[ListManagedAlertsRequestOrderBy] - """ - Sort order for data sources in the response. - """ - - project_id: Optional[str] - """ - Project ID to filter for, only data sources from this Project will be returned. - """ - - @dataclass class RegionalApiListTokensRequest: """ From dade83955ae1ddeb222268aab4b4eeb4f3687efe Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Fri, 21 Feb 2025 10:38:26 +0100 Subject: [PATCH 23/73] feat(secret): add support for `RestoreSecretRequest` and `RestoreSecretVersionRequest` (#861) --- .../scaleway_async/secret/v1beta1/__init__.py | 4 + .../scaleway_async/secret/v1beta1/api.py | 80 +++++++++++++++++++ .../secret/v1beta1/marshalling.py | 16 ++++ .../scaleway_async/secret/v1beta1/types.py | 39 +++++++++ scaleway/scaleway/secret/v1beta1/__init__.py | 4 + scaleway/scaleway/secret/v1beta1/api.py | 80 +++++++++++++++++++ .../scaleway/secret/v1beta1/marshalling.py | 16 ++++ scaleway/scaleway/secret/v1beta1/types.py | 39 +++++++++ 8 files changed, 278 insertions(+) diff --git a/scaleway-async/scaleway_async/secret/v1beta1/__init__.py b/scaleway-async/scaleway_async/secret/v1beta1/__init__.py index b55546b45..531ccc836 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/__init__.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/__init__.py @@ -39,6 +39,8 @@ from .types import ListTagsRequest from .types import ListTagsResponse from .types import ProtectSecretRequest +from .types import RestoreSecretRequest +from .types import RestoreSecretVersionRequest from .types import SSHKey from .types import UnprotectSecretRequest from .types import UpdateSecretRequest @@ -85,6 +87,8 @@ "ListTagsRequest", "ListTagsResponse", "ProtectSecretRequest", + "RestoreSecretRequest", + "RestoreSecretVersionRequest", "SSHKey", "UnprotectSecretRequest", "UpdateSecretRequest", diff --git a/scaleway-async/scaleway_async/secret/v1beta1/api.py b/scaleway-async/scaleway_async/secret/v1beta1/api.py index 43d9cc8dd..47fef12c0 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/api.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/api.py @@ -253,6 +253,7 @@ async def list_secrets( path: Optional[str] = None, ephemeral: Optional[bool] = None, type_: Optional[SecretType] = None, + scheduled_for_deletion: Optional[bool] = None, ) -> ListSecretsResponse: """ List secrets. @@ -268,6 +269,7 @@ async def list_secrets( :param path: Filter by exact path (optional). :param ephemeral: Filter by ephemeral / not ephemeral (optional). :param type_: Filter by secret type (optional). + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). :return: :class:`ListSecretsResponse ` Usage: @@ -293,6 +295,7 @@ async def list_secrets( "page_size": page_size or self.client.default_page_size, "path": path, "project_id": project_id or self.client.default_project_id, + "scheduled_for_deletion": scheduled_for_deletion, "tags": tags, "type": type_, }, @@ -315,6 +318,7 @@ async def list_secrets_all( path: Optional[str] = None, ephemeral: Optional[bool] = None, type_: Optional[SecretType] = None, + scheduled_for_deletion: Optional[bool] = None, ) -> List[Secret]: """ List secrets. @@ -330,6 +334,7 @@ async def list_secrets_all( :param path: Filter by exact path (optional). :param ephemeral: Filter by ephemeral / not ephemeral (optional). :param type_: Filter by secret type (optional). + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). :return: :class:`List[Secret] ` Usage: @@ -354,6 +359,7 @@ async def list_secrets_all( "path": path, "ephemeral": ephemeral, "type_": type_, + "scheduled_for_deletion": scheduled_for_deletion, }, ) @@ -1120,3 +1126,77 @@ async def list_secret_types_all( "page_size": page_size, }, ) + + async def restore_secret_version( + self, + *, + secret_id: str, + revision: str, + region: Optional[ScwRegion] = None, + ) -> SecretVersion: + """ + Restore a version. + Restore a secret's version specified by the `region`, `secret_id` and `revision` parameters. + :param secret_id: + :param revision: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SecretVersion ` + + Usage: + :: + + result = await api.restore_secret_version( + secret_id="example", + revision="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_secret_id = validate_path_param("secret_id", secret_id) + param_revision = validate_path_param("revision", revision) + + res = self._request( + "POST", + f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/versions/{param_revision}/restore", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_SecretVersion(res.json()) + + async def restore_secret( + self, + *, + secret_id: str, + region: Optional[ScwRegion] = None, + ) -> Secret: + """ + Restore a secret. + Restore a secret and all its versions scheduled for deletion specified by the `region` and `secret_id` parameters. + :param secret_id: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Secret ` + + Usage: + :: + + result = await api.restore_secret( + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "POST", + f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/restore", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Secret(res.json()) diff --git a/scaleway-async/scaleway_async/secret/v1beta1/marshalling.py b/scaleway-async/scaleway_async/secret/v1beta1/marshalling.py index 699110e53..bf3e70c02 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/marshalling.py @@ -110,6 +110,14 @@ def unmarshal_SecretVersion(data: Any) -> SecretVersion: else: args["ephemeral_properties"] = None + field = data.get("deletion_requested_at", None) + if field is not None: + args["deletion_requested_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["deletion_requested_at"] = None + return SecretVersion(**args) @@ -220,6 +228,14 @@ def unmarshal_Secret(data: Any) -> Secret: else: args["ephemeral_policy"] = None + field = data.get("deletion_requested_at", None) + if field is not None: + args["deletion_requested_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["deletion_requested_at"] = None + return Secret(**args) diff --git a/scaleway-async/scaleway_async/secret/v1beta1/types.py b/scaleway-async/scaleway_async/secret/v1beta1/types.py index 1b9fff0a7..338eaefd0 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/types.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/types.py @@ -83,6 +83,7 @@ class SecretVersionStatus(str, Enum, metaclass=StrEnumMeta): ENABLED = "enabled" DISABLED = "disabled" DELETED = "deleted" + SCHEDULED_FOR_DELETION = "scheduled_for_deletion" def __str__(self) -> str: return str(self.value) @@ -174,6 +175,7 @@ class SecretVersion: * `unknown_status`: the version is in an invalid state. * `enabled`: the version is accessible. * `disabled`: the version is not accessible but can be enabled. +* `scheduled_for_deletion`: the version is scheduled for deletion. It will be deleted in 7 days. * `deleted`: the version is permanently deleted. It is not possible to recover it. """ @@ -207,6 +209,11 @@ class SecretVersion: Returns the version's expiration date, whether it expires after being accessed once, and the action to perform (disable or delete) once the version expires. """ + deletion_requested_at: Optional[datetime] + """ + Returns the time at which deletion was requested. + """ + @dataclass class Secret: @@ -291,6 +298,11 @@ class Secret: (Optional.) Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions. """ + deletion_requested_at: Optional[datetime] + """ + Returns the time at which deletion was requested. + """ + @dataclass class AccessSecretVersionByPathRequest: @@ -792,6 +804,11 @@ class ListSecretsRequest: Filter by secret type (optional). """ + scheduled_for_deletion: Optional[bool] + """ + Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). + """ + @dataclass class ListSecretsResponse: @@ -849,6 +866,28 @@ class ProtectSecretRequest: """ +@dataclass +class RestoreSecretRequest: + secret_id: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RestoreSecretVersionRequest: + secret_id: str + + revision: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class SSHKey: ssh_private_key: str diff --git a/scaleway/scaleway/secret/v1beta1/__init__.py b/scaleway/scaleway/secret/v1beta1/__init__.py index b55546b45..531ccc836 100644 --- a/scaleway/scaleway/secret/v1beta1/__init__.py +++ b/scaleway/scaleway/secret/v1beta1/__init__.py @@ -39,6 +39,8 @@ from .types import ListTagsRequest from .types import ListTagsResponse from .types import ProtectSecretRequest +from .types import RestoreSecretRequest +from .types import RestoreSecretVersionRequest from .types import SSHKey from .types import UnprotectSecretRequest from .types import UpdateSecretRequest @@ -85,6 +87,8 @@ "ListTagsRequest", "ListTagsResponse", "ProtectSecretRequest", + "RestoreSecretRequest", + "RestoreSecretVersionRequest", "SSHKey", "UnprotectSecretRequest", "UpdateSecretRequest", diff --git a/scaleway/scaleway/secret/v1beta1/api.py b/scaleway/scaleway/secret/v1beta1/api.py index 894ae2ae9..9605f8654 100644 --- a/scaleway/scaleway/secret/v1beta1/api.py +++ b/scaleway/scaleway/secret/v1beta1/api.py @@ -253,6 +253,7 @@ def list_secrets( path: Optional[str] = None, ephemeral: Optional[bool] = None, type_: Optional[SecretType] = None, + scheduled_for_deletion: Optional[bool] = None, ) -> ListSecretsResponse: """ List secrets. @@ -268,6 +269,7 @@ def list_secrets( :param path: Filter by exact path (optional). :param ephemeral: Filter by ephemeral / not ephemeral (optional). :param type_: Filter by secret type (optional). + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). :return: :class:`ListSecretsResponse ` Usage: @@ -293,6 +295,7 @@ def list_secrets( "page_size": page_size or self.client.default_page_size, "path": path, "project_id": project_id or self.client.default_project_id, + "scheduled_for_deletion": scheduled_for_deletion, "tags": tags, "type": type_, }, @@ -315,6 +318,7 @@ def list_secrets_all( path: Optional[str] = None, ephemeral: Optional[bool] = None, type_: Optional[SecretType] = None, + scheduled_for_deletion: Optional[bool] = None, ) -> List[Secret]: """ List secrets. @@ -330,6 +334,7 @@ def list_secrets_all( :param path: Filter by exact path (optional). :param ephemeral: Filter by ephemeral / not ephemeral (optional). :param type_: Filter by secret type (optional). + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). :return: :class:`List[Secret] ` Usage: @@ -354,6 +359,7 @@ def list_secrets_all( "path": path, "ephemeral": ephemeral, "type_": type_, + "scheduled_for_deletion": scheduled_for_deletion, }, ) @@ -1120,3 +1126,77 @@ def list_secret_types_all( "page_size": page_size, }, ) + + def restore_secret_version( + self, + *, + secret_id: str, + revision: str, + region: Optional[ScwRegion] = None, + ) -> SecretVersion: + """ + Restore a version. + Restore a secret's version specified by the `region`, `secret_id` and `revision` parameters. + :param secret_id: + :param revision: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SecretVersion ` + + Usage: + :: + + result = api.restore_secret_version( + secret_id="example", + revision="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_secret_id = validate_path_param("secret_id", secret_id) + param_revision = validate_path_param("revision", revision) + + res = self._request( + "POST", + f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/versions/{param_revision}/restore", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_SecretVersion(res.json()) + + def restore_secret( + self, + *, + secret_id: str, + region: Optional[ScwRegion] = None, + ) -> Secret: + """ + Restore a secret. + Restore a secret and all its versions scheduled for deletion specified by the `region` and `secret_id` parameters. + :param secret_id: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Secret ` + + Usage: + :: + + result = api.restore_secret( + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "POST", + f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/restore", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Secret(res.json()) diff --git a/scaleway/scaleway/secret/v1beta1/marshalling.py b/scaleway/scaleway/secret/v1beta1/marshalling.py index 699110e53..bf3e70c02 100644 --- a/scaleway/scaleway/secret/v1beta1/marshalling.py +++ b/scaleway/scaleway/secret/v1beta1/marshalling.py @@ -110,6 +110,14 @@ def unmarshal_SecretVersion(data: Any) -> SecretVersion: else: args["ephemeral_properties"] = None + field = data.get("deletion_requested_at", None) + if field is not None: + args["deletion_requested_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["deletion_requested_at"] = None + return SecretVersion(**args) @@ -220,6 +228,14 @@ def unmarshal_Secret(data: Any) -> Secret: else: args["ephemeral_policy"] = None + field = data.get("deletion_requested_at", None) + if field is not None: + args["deletion_requested_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["deletion_requested_at"] = None + return Secret(**args) diff --git a/scaleway/scaleway/secret/v1beta1/types.py b/scaleway/scaleway/secret/v1beta1/types.py index 1b9fff0a7..338eaefd0 100644 --- a/scaleway/scaleway/secret/v1beta1/types.py +++ b/scaleway/scaleway/secret/v1beta1/types.py @@ -83,6 +83,7 @@ class SecretVersionStatus(str, Enum, metaclass=StrEnumMeta): ENABLED = "enabled" DISABLED = "disabled" DELETED = "deleted" + SCHEDULED_FOR_DELETION = "scheduled_for_deletion" def __str__(self) -> str: return str(self.value) @@ -174,6 +175,7 @@ class SecretVersion: * `unknown_status`: the version is in an invalid state. * `enabled`: the version is accessible. * `disabled`: the version is not accessible but can be enabled. +* `scheduled_for_deletion`: the version is scheduled for deletion. It will be deleted in 7 days. * `deleted`: the version is permanently deleted. It is not possible to recover it. """ @@ -207,6 +209,11 @@ class SecretVersion: Returns the version's expiration date, whether it expires after being accessed once, and the action to perform (disable or delete) once the version expires. """ + deletion_requested_at: Optional[datetime] + """ + Returns the time at which deletion was requested. + """ + @dataclass class Secret: @@ -291,6 +298,11 @@ class Secret: (Optional.) Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions. """ + deletion_requested_at: Optional[datetime] + """ + Returns the time at which deletion was requested. + """ + @dataclass class AccessSecretVersionByPathRequest: @@ -792,6 +804,11 @@ class ListSecretsRequest: Filter by secret type (optional). """ + scheduled_for_deletion: Optional[bool] + """ + Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). + """ + @dataclass class ListSecretsResponse: @@ -849,6 +866,28 @@ class ProtectSecretRequest: """ +@dataclass +class RestoreSecretRequest: + secret_id: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RestoreSecretVersionRequest: + secret_id: str + + revision: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class SSHKey: ssh_private_key: str From 2f2d13ce46025cb559c0c6b4c6defb7acbdd2631 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Fri, 21 Feb 2025 10:39:01 +0100 Subject: [PATCH 24/73] feat(vpc_gw): add a call to migrate a V1 gateway to V2 (#862) --- .../scaleway_async/vpcgw/v1/__init__.py | 2 ++ scaleway-async/scaleway_async/vpcgw/v1/api.py | 29 +++++++++++++++++++ .../scaleway_async/vpcgw/v1/types.py | 10 +++++++ scaleway/scaleway/vpcgw/v1/__init__.py | 2 ++ scaleway/scaleway/vpcgw/v1/api.py | 29 +++++++++++++++++++ scaleway/scaleway/vpcgw/v1/types.py | 10 +++++++ 6 files changed, 82 insertions(+) diff --git a/scaleway-async/scaleway_async/vpcgw/v1/__init__.py b/scaleway-async/scaleway_async/vpcgw/v1/__init__.py index d02eb8188..995252580 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/__init__.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/__init__.py @@ -57,6 +57,7 @@ from .types import ListIPsResponse from .types import ListPATRulesRequest from .types import ListPATRulesResponse +from .types import MigrateToV2Request from .types import RefreshSSHKeysRequest from .types import SetDHCPEntriesRequest from .types import SetDHCPEntriesResponse @@ -129,6 +130,7 @@ "ListIPsResponse", "ListPATRulesRequest", "ListPATRulesResponse", + "MigrateToV2Request", "RefreshSSHKeysRequest", "SetDHCPEntriesRequest", "SetDHCPEntriesResponse", diff --git a/scaleway-async/scaleway_async/vpcgw/v1/api.py b/scaleway-async/scaleway_async/vpcgw/v1/api.py index 828ad0fc5..b881fa2d5 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/api.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/api.py @@ -2080,3 +2080,32 @@ async def refresh_ssh_keys( self._throw_on_error(res) return unmarshal_Gateway(res.json()) + + async def migrate_to_v2( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + :param gateway_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.migrate_to_v2( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v1/zones/{param_zone}/gateways/{param_gateway_id}/migrate-to-v2", + body={}, + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/vpcgw/v1/types.py b/scaleway-async/scaleway_async/vpcgw/v1/types.py index cc8f5f0a7..ab3696792 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/types.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/types.py @@ -1440,6 +1440,16 @@ class ListPATRulesResponse: """ +@dataclass +class MigrateToV2Request: + gateway_id: str + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class RefreshSSHKeysRequest: gateway_id: str diff --git a/scaleway/scaleway/vpcgw/v1/__init__.py b/scaleway/scaleway/vpcgw/v1/__init__.py index d02eb8188..995252580 100644 --- a/scaleway/scaleway/vpcgw/v1/__init__.py +++ b/scaleway/scaleway/vpcgw/v1/__init__.py @@ -57,6 +57,7 @@ from .types import ListIPsResponse from .types import ListPATRulesRequest from .types import ListPATRulesResponse +from .types import MigrateToV2Request from .types import RefreshSSHKeysRequest from .types import SetDHCPEntriesRequest from .types import SetDHCPEntriesResponse @@ -129,6 +130,7 @@ "ListIPsResponse", "ListPATRulesRequest", "ListPATRulesResponse", + "MigrateToV2Request", "RefreshSSHKeysRequest", "SetDHCPEntriesRequest", "SetDHCPEntriesResponse", diff --git a/scaleway/scaleway/vpcgw/v1/api.py b/scaleway/scaleway/vpcgw/v1/api.py index a83573cb3..02cc47d33 100644 --- a/scaleway/scaleway/vpcgw/v1/api.py +++ b/scaleway/scaleway/vpcgw/v1/api.py @@ -2078,3 +2078,32 @@ def refresh_ssh_keys( self._throw_on_error(res) return unmarshal_Gateway(res.json()) + + def migrate_to_v2( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + :param gateway_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.migrate_to_v2( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v1/zones/{param_zone}/gateways/{param_gateway_id}/migrate-to-v2", + body={}, + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/vpcgw/v1/types.py b/scaleway/scaleway/vpcgw/v1/types.py index cc8f5f0a7..ab3696792 100644 --- a/scaleway/scaleway/vpcgw/v1/types.py +++ b/scaleway/scaleway/vpcgw/v1/types.py @@ -1440,6 +1440,16 @@ class ListPATRulesResponse: """ +@dataclass +class MigrateToV2Request: + gateway_id: str + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class RefreshSSHKeysRequest: gateway_id: str From 132d6919a09d8e3116c0dbb05f8e64625461f1a6 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Fri, 21 Feb 2025 10:39:32 +0100 Subject: [PATCH 25/73] fix(webhosting): add hosting domain status (#863) --- .../webhosting/v1/marshalling.py | 54 ++++++++++++------- .../scaleway_async/webhosting/v1/types.py | 49 +++++++++++------ .../scaleway/webhosting/v1/marshalling.py | 54 ++++++++++++------- scaleway/scaleway/webhosting/v1/types.py | 49 +++++++++++------ 4 files changed, 136 insertions(+), 70 deletions(-) diff --git a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py index 462a8ccbf..873ac7014 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py +++ b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py @@ -515,9 +515,9 @@ def unmarshal_Hosting(data: Any) -> Hosting: if field is not None: args["tags"] = field - field = data.get("dns_status", None) + field = data.get("ipv4", None) if field is not None: - args["dns_status"] = field + args["ipv4"] = field field = data.get("updated_at", None) if field is not None: @@ -525,23 +525,23 @@ def unmarshal_Hosting(data: Any) -> Hosting: else: args["updated_at"] = None - field = data.get("ipv4", None) + field = data.get("created_at", None) if field is not None: - args["ipv4"] = field + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("protected", None) if field is not None: args["protected"] = field - field = data.get("region", None) + field = data.get("domain_status", None) if field is not None: - args["region"] = field + args["domain_status"] = field - field = data.get("created_at", None) + field = data.get("region", None) if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field - else: - args["created_at"] = None + args["region"] = field field = data.get("offer", None) if field is not None: @@ -555,6 +555,12 @@ def unmarshal_Hosting(data: Any) -> Hosting: else: args["platform"] = None + field = data.get("dns_status", None) + if field is not None: + args["dns_status"] = field + else: + args["dns_status"] = None + field = data.get("user", None) if field is not None: args["user"] = unmarshal_HostingUser(field) @@ -693,10 +699,6 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: if field is not None: args["project_id"] = field - field = data.get("status", None) - if field is not None: - args["status"] = field - field = data.get("domain", None) if field is not None: args["domain"] = field @@ -705,14 +707,18 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: if field is not None: args["protected"] = field - field = data.get("dns_status", None) - if field is not None: - args["dns_status"] = field - field = data.get("offer_name", None) if field is not None: args["offer_name"] = field + field = data.get("hosting_status", None) + if field is not None: + args["hosting_status"] = field + + field = data.get("domain_status", None) + if field is not None: + args["domain_status"] = field + field = data.get("region", None) if field is not None: args["region"] = field @@ -729,6 +735,18 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: else: args["updated_at"] = None + field = data.get("status", None) + if field is not None: + args["status"] = field + else: + args["status"] = None + + field = data.get("dns_status", None) + if field is not None: + args["dns_status"] = field + else: + args["dns_status"] = None + return HostingSummary(**args) diff --git a/scaleway-async/scaleway_async/webhosting/v1/types.py b/scaleway-async/scaleway_async/webhosting/v1/types.py index ee610795d..480e1974a 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/types.py +++ b/scaleway-async/scaleway_async/webhosting/v1/types.py @@ -579,11 +579,6 @@ class HostingSummary: ID of the Scaleway Project the Web Hosting plan belongs to. """ - status: HostingSummaryStatus - """ - Status of the Web Hosting plan. - """ - domain: str """ Main domain associated with the Web Hosting plan. @@ -594,14 +589,19 @@ class HostingSummary: Whether the hosting is protected or not. """ - dns_status: DnsRecordsStatus + offer_name: str """ - DNS status of the Web Hosting plan. + Name of the active offer for the Web Hosting plan. """ - offer_name: str + hosting_status: HostingStatus """ - Name of the active offer for the Web Hosting plan. + Status of the Web Hosting plan. + """ + + domain_status: DomainStatus + """ + Main domain status of the Web Hosting plan. """ region: ScwRegion @@ -619,6 +619,16 @@ class HostingSummary: Date on which the Web Hosting plan was last updated. """ + status: Optional[HostingSummaryStatus] + """ + Status of the Web Hosting plan. + """ + + dns_status: Optional[DnsRecordsStatus] + """ + DNS status of the Web Hosting plan. + """ + @dataclass class MailAccount: @@ -1232,9 +1242,9 @@ class Hosting: List of tags associated with the Web Hosting plan. """ - dns_status: DnsRecordsStatus + ipv4: str """ - DNS status of the Web Hosting plan. + Current IPv4 address of the hosting. """ updated_at: Optional[datetime] @@ -1242,9 +1252,9 @@ class Hosting: Date on which the Web Hosting plan was last updated. """ - ipv4: str + created_at: Optional[datetime] """ - Current IPv4 address of the hosting. + Date on which the Web Hosting plan was created. """ protected: bool @@ -1252,14 +1262,14 @@ class Hosting: Whether the hosting is protected or not. """ - region: ScwRegion + domain_status: DomainStatus """ - Region where the Web Hosting plan is hosted. + Main domain status of the Web Hosting plan. """ - created_at: Optional[datetime] + region: ScwRegion """ - Date on which the Web Hosting plan was created. + Region where the Web Hosting plan is hosted. """ offer: Optional[Offer] @@ -1272,6 +1282,11 @@ class Hosting: Details of the hosting platform. """ + dns_status: Optional[DnsRecordsStatus] + """ + DNS status of the Web Hosting plan. + """ + user: Optional[HostingUser] """ Details of the hosting user. diff --git a/scaleway/scaleway/webhosting/v1/marshalling.py b/scaleway/scaleway/webhosting/v1/marshalling.py index 462a8ccbf..873ac7014 100644 --- a/scaleway/scaleway/webhosting/v1/marshalling.py +++ b/scaleway/scaleway/webhosting/v1/marshalling.py @@ -515,9 +515,9 @@ def unmarshal_Hosting(data: Any) -> Hosting: if field is not None: args["tags"] = field - field = data.get("dns_status", None) + field = data.get("ipv4", None) if field is not None: - args["dns_status"] = field + args["ipv4"] = field field = data.get("updated_at", None) if field is not None: @@ -525,23 +525,23 @@ def unmarshal_Hosting(data: Any) -> Hosting: else: args["updated_at"] = None - field = data.get("ipv4", None) + field = data.get("created_at", None) if field is not None: - args["ipv4"] = field + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("protected", None) if field is not None: args["protected"] = field - field = data.get("region", None) + field = data.get("domain_status", None) if field is not None: - args["region"] = field + args["domain_status"] = field - field = data.get("created_at", None) + field = data.get("region", None) if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field - else: - args["created_at"] = None + args["region"] = field field = data.get("offer", None) if field is not None: @@ -555,6 +555,12 @@ def unmarshal_Hosting(data: Any) -> Hosting: else: args["platform"] = None + field = data.get("dns_status", None) + if field is not None: + args["dns_status"] = field + else: + args["dns_status"] = None + field = data.get("user", None) if field is not None: args["user"] = unmarshal_HostingUser(field) @@ -693,10 +699,6 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: if field is not None: args["project_id"] = field - field = data.get("status", None) - if field is not None: - args["status"] = field - field = data.get("domain", None) if field is not None: args["domain"] = field @@ -705,14 +707,18 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: if field is not None: args["protected"] = field - field = data.get("dns_status", None) - if field is not None: - args["dns_status"] = field - field = data.get("offer_name", None) if field is not None: args["offer_name"] = field + field = data.get("hosting_status", None) + if field is not None: + args["hosting_status"] = field + + field = data.get("domain_status", None) + if field is not None: + args["domain_status"] = field + field = data.get("region", None) if field is not None: args["region"] = field @@ -729,6 +735,18 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: else: args["updated_at"] = None + field = data.get("status", None) + if field is not None: + args["status"] = field + else: + args["status"] = None + + field = data.get("dns_status", None) + if field is not None: + args["dns_status"] = field + else: + args["dns_status"] = None + return HostingSummary(**args) diff --git a/scaleway/scaleway/webhosting/v1/types.py b/scaleway/scaleway/webhosting/v1/types.py index ee610795d..480e1974a 100644 --- a/scaleway/scaleway/webhosting/v1/types.py +++ b/scaleway/scaleway/webhosting/v1/types.py @@ -579,11 +579,6 @@ class HostingSummary: ID of the Scaleway Project the Web Hosting plan belongs to. """ - status: HostingSummaryStatus - """ - Status of the Web Hosting plan. - """ - domain: str """ Main domain associated with the Web Hosting plan. @@ -594,14 +589,19 @@ class HostingSummary: Whether the hosting is protected or not. """ - dns_status: DnsRecordsStatus + offer_name: str """ - DNS status of the Web Hosting plan. + Name of the active offer for the Web Hosting plan. """ - offer_name: str + hosting_status: HostingStatus """ - Name of the active offer for the Web Hosting plan. + Status of the Web Hosting plan. + """ + + domain_status: DomainStatus + """ + Main domain status of the Web Hosting plan. """ region: ScwRegion @@ -619,6 +619,16 @@ class HostingSummary: Date on which the Web Hosting plan was last updated. """ + status: Optional[HostingSummaryStatus] + """ + Status of the Web Hosting plan. + """ + + dns_status: Optional[DnsRecordsStatus] + """ + DNS status of the Web Hosting plan. + """ + @dataclass class MailAccount: @@ -1232,9 +1242,9 @@ class Hosting: List of tags associated with the Web Hosting plan. """ - dns_status: DnsRecordsStatus + ipv4: str """ - DNS status of the Web Hosting plan. + Current IPv4 address of the hosting. """ updated_at: Optional[datetime] @@ -1242,9 +1252,9 @@ class Hosting: Date on which the Web Hosting plan was last updated. """ - ipv4: str + created_at: Optional[datetime] """ - Current IPv4 address of the hosting. + Date on which the Web Hosting plan was created. """ protected: bool @@ -1252,14 +1262,14 @@ class Hosting: Whether the hosting is protected or not. """ - region: ScwRegion + domain_status: DomainStatus """ - Region where the Web Hosting plan is hosted. + Main domain status of the Web Hosting plan. """ - created_at: Optional[datetime] + region: ScwRegion """ - Date on which the Web Hosting plan was created. + Region where the Web Hosting plan is hosted. """ offer: Optional[Offer] @@ -1272,6 +1282,11 @@ class Hosting: Details of the hosting platform. """ + dns_status: Optional[DnsRecordsStatus] + """ + DNS status of the Web Hosting plan. + """ + user: Optional[HostingUser] """ Details of the hosting user. From c49ff448e89317b621885b62e1c7c08c67296c7d Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Fri, 21 Feb 2025 17:31:48 +0100 Subject: [PATCH 26/73] feat(webhosting): add domain selected dns configuration (#864) --- scaleway-async/scaleway_async/webhosting/v1/marshalling.py | 6 ++++++ scaleway-async/scaleway_async/webhosting/v1/types.py | 5 +++++ scaleway/scaleway/webhosting/v1/marshalling.py | 6 ++++++ scaleway/scaleway/webhosting/v1/types.py | 5 +++++ 4 files changed, 22 insertions(+) diff --git a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py index 873ac7014..1b9f53550 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py +++ b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py @@ -251,6 +251,12 @@ def unmarshal_DnsRecords(data: Any) -> DnsRecords: if field is not None: args["status"] = field + field = data.get("dns_config", None) + if field is not None: + args["dns_config"] = ( + [DomainDnsAction(v) for v in field] if field is not None else None + ) + return DnsRecords(**args) diff --git a/scaleway-async/scaleway_async/webhosting/v1/types.py b/scaleway-async/scaleway_async/webhosting/v1/types.py index 480e1974a..2bf188a66 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/types.py +++ b/scaleway-async/scaleway_async/webhosting/v1/types.py @@ -1084,6 +1084,11 @@ class DnsRecords: Status of the records. """ + dns_config: List[DomainDnsAction] + """ + Records dns auto configuration settings. + """ + @dataclass class Domain: diff --git a/scaleway/scaleway/webhosting/v1/marshalling.py b/scaleway/scaleway/webhosting/v1/marshalling.py index 873ac7014..1b9f53550 100644 --- a/scaleway/scaleway/webhosting/v1/marshalling.py +++ b/scaleway/scaleway/webhosting/v1/marshalling.py @@ -251,6 +251,12 @@ def unmarshal_DnsRecords(data: Any) -> DnsRecords: if field is not None: args["status"] = field + field = data.get("dns_config", None) + if field is not None: + args["dns_config"] = ( + [DomainDnsAction(v) for v in field] if field is not None else None + ) + return DnsRecords(**args) diff --git a/scaleway/scaleway/webhosting/v1/types.py b/scaleway/scaleway/webhosting/v1/types.py index 480e1974a..2bf188a66 100644 --- a/scaleway/scaleway/webhosting/v1/types.py +++ b/scaleway/scaleway/webhosting/v1/types.py @@ -1084,6 +1084,11 @@ class DnsRecords: Status of the records. """ + dns_config: List[DomainDnsAction] + """ + Records dns auto configuration settings. + """ + @dataclass class Domain: From 4f19fecd691d339b68a898d5075c375a2335fe4f Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 25 Feb 2025 10:20:32 +0100 Subject: [PATCH 27/73] feat(block): add tags filter in list snapshots (#865) --- scaleway-async/scaleway_async/block/v1alpha1/api.py | 6 ++++++ scaleway-async/scaleway_async/block/v1alpha1/types.py | 5 +++++ scaleway/scaleway/block/v1alpha1/api.py | 6 ++++++ scaleway/scaleway/block/v1alpha1/types.py | 5 +++++ 4 files changed, 22 insertions(+) diff --git a/scaleway-async/scaleway_async/block/v1alpha1/api.py b/scaleway-async/scaleway_async/block/v1alpha1/api.py index c0c30012d..970ed99cf 100644 --- a/scaleway-async/scaleway_async/block/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/block/v1alpha1/api.py @@ -447,6 +447,7 @@ async def list_snapshots( page_size: Optional[int] = None, volume_id: Optional[str] = None, name: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> ListSnapshotsResponse: """ List all snapshots. @@ -459,6 +460,7 @@ async def list_snapshots( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param volume_id: Filter snapshots by the ID of the original volume. :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. :return: :class:`ListSnapshotsResponse ` Usage: @@ -480,6 +482,7 @@ async def list_snapshots( "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "tags": tags, "volume_id": volume_id, }, ) @@ -498,6 +501,7 @@ async def list_snapshots_all( page_size: Optional[int] = None, volume_id: Optional[str] = None, name: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> List[Snapshot]: """ List all snapshots. @@ -510,6 +514,7 @@ async def list_snapshots_all( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param volume_id: Filter snapshots by the ID of the original volume. :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. :return: :class:`List[Snapshot] ` Usage: @@ -531,6 +536,7 @@ async def list_snapshots_all( "page_size": page_size, "volume_id": volume_id, "name": name, + "tags": tags, }, ) diff --git a/scaleway-async/scaleway_async/block/v1alpha1/types.py b/scaleway-async/scaleway_async/block/v1alpha1/types.py index c0c884dd6..2f15d1ec0 100644 --- a/scaleway-async/scaleway_async/block/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/block/v1alpha1/types.py @@ -601,6 +601,11 @@ class ListSnapshotsRequest: Filter snapshots by their names. """ + tags: Optional[List[str]] + """ + Filter by tags. Only snapshots with one or more matching tags will be returned. + """ + @dataclass class ListSnapshotsResponse: diff --git a/scaleway/scaleway/block/v1alpha1/api.py b/scaleway/scaleway/block/v1alpha1/api.py index 266b25085..11058a608 100644 --- a/scaleway/scaleway/block/v1alpha1/api.py +++ b/scaleway/scaleway/block/v1alpha1/api.py @@ -447,6 +447,7 @@ def list_snapshots( page_size: Optional[int] = None, volume_id: Optional[str] = None, name: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> ListSnapshotsResponse: """ List all snapshots. @@ -459,6 +460,7 @@ def list_snapshots( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param volume_id: Filter snapshots by the ID of the original volume. :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. :return: :class:`ListSnapshotsResponse ` Usage: @@ -480,6 +482,7 @@ def list_snapshots( "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "tags": tags, "volume_id": volume_id, }, ) @@ -498,6 +501,7 @@ def list_snapshots_all( page_size: Optional[int] = None, volume_id: Optional[str] = None, name: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> List[Snapshot]: """ List all snapshots. @@ -510,6 +514,7 @@ def list_snapshots_all( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param volume_id: Filter snapshots by the ID of the original volume. :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. :return: :class:`List[Snapshot] ` Usage: @@ -531,6 +536,7 @@ def list_snapshots_all( "page_size": page_size, "volume_id": volume_id, "name": name, + "tags": tags, }, ) diff --git a/scaleway/scaleway/block/v1alpha1/types.py b/scaleway/scaleway/block/v1alpha1/types.py index c0c884dd6..2f15d1ec0 100644 --- a/scaleway/scaleway/block/v1alpha1/types.py +++ b/scaleway/scaleway/block/v1alpha1/types.py @@ -601,6 +601,11 @@ class ListSnapshotsRequest: Filter snapshots by their names. """ + tags: Optional[List[str]] + """ + Filter by tags. Only snapshots with one or more matching tags will be returned. + """ + @dataclass class ListSnapshotsResponse: From 64cdb42e28705cc5da338c367891974bd35058d9 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 25 Feb 2025 14:19:42 +0100 Subject: [PATCH 28/73] feat(audit_trail): migrate iamx to iam (#866) --- .../scaleway_async/audit_trail/v1alpha1/types.py | 12 ++++++------ scaleway/scaleway/audit_trail/v1alpha1/types.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py index f604cf347..3db3219ea 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py @@ -32,12 +32,12 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): KUBE_NODE = "kube_node" KUBE_ACL = "kube_acl" KEYM_KEY = "keym_key" - IAMX_USER = "iamx_user" - IAMX_APPLICATION = "iamx_application" - IAMX_GROUP = "iamx_group" - IAMX_POLICY = "iamx_policy" - IAMX_API_KEY = "iamx_api_key" - IAMX_SSH_KEY = "iamx_ssh_key" + IAM_USER = "iam_user" + IAM_APPLICATION = "iam_application" + IAM_GROUP = "iam_group" + IAM_POLICY = "iam_policy" + IAM_API_KEY = "iam_api_key" + IAM_SSH_KEY = "iam_ssh_key" def __str__(self) -> str: return str(self.value) diff --git a/scaleway/scaleway/audit_trail/v1alpha1/types.py b/scaleway/scaleway/audit_trail/v1alpha1/types.py index f604cf347..3db3219ea 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/types.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/types.py @@ -32,12 +32,12 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): KUBE_NODE = "kube_node" KUBE_ACL = "kube_acl" KEYM_KEY = "keym_key" - IAMX_USER = "iamx_user" - IAMX_APPLICATION = "iamx_application" - IAMX_GROUP = "iamx_group" - IAMX_POLICY = "iamx_policy" - IAMX_API_KEY = "iamx_api_key" - IAMX_SSH_KEY = "iamx_ssh_key" + IAM_USER = "iam_user" + IAM_APPLICATION = "iam_application" + IAM_GROUP = "iam_group" + IAM_POLICY = "iam_policy" + IAM_API_KEY = "iam_api_key" + IAM_SSH_KEY = "iam_ssh_key" def __str__(self) -> str: return str(self.value) From 0a00c586e3f72da4b8a9fd1c143fa03325a3f3e5 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Wed, 26 Feb 2025 15:05:12 +0100 Subject: [PATCH 29/73] feat(instance): add compatible types endpoint and end_of_service flag in ServerType (#867) --- .../scaleway_async/instance/v1/__init__.py | 4 ++ .../scaleway_async/instance/v1/api.py | 39 +++++++++++++++++++ .../scaleway_async/instance/v1/marshalling.py | 20 ++++++++++ .../scaleway_async/instance/v1/types.py | 26 +++++++++++++ scaleway/scaleway/instance/v1/__init__.py | 4 ++ scaleway/scaleway/instance/v1/api.py | 39 +++++++++++++++++++ scaleway/scaleway/instance/v1/marshalling.py | 20 ++++++++++ scaleway/scaleway/instance/v1/types.py | 26 +++++++++++++ 8 files changed, 178 insertions(+) diff --git a/scaleway-async/scaleway_async/instance/v1/__init__.py b/scaleway-async/scaleway_async/instance/v1/__init__.py index f6f393365..686123bd6 100644 --- a/scaleway-async/scaleway_async/instance/v1/__init__.py +++ b/scaleway-async/scaleway_async/instance/v1/__init__.py @@ -128,6 +128,7 @@ from .types import GetSecurityGroupResponse from .types import GetSecurityGroupRuleRequest from .types import GetSecurityGroupRuleResponse +from .types import GetServerCompatibleTypesRequest from .types import GetServerRequest from .types import GetServerResponse from .types import GetServerTypesAvailabilityRequest @@ -167,6 +168,7 @@ from .types import PlanBlockMigrationRequest from .types import ServerActionRequest from .types import ServerActionResponse +from .types import ServerCompatibleTypes from .types import SetImageRequest from .types import SetPlacementGroupRequest from .types import SetPlacementGroupResponse @@ -324,6 +326,7 @@ "GetSecurityGroupResponse", "GetSecurityGroupRuleRequest", "GetSecurityGroupRuleResponse", + "GetServerCompatibleTypesRequest", "GetServerRequest", "GetServerResponse", "GetServerTypesAvailabilityRequest", @@ -363,6 +366,7 @@ "PlanBlockMigrationRequest", "ServerActionRequest", "ServerActionResponse", + "ServerCompatibleTypes", "SetImageRequest", "SetPlacementGroupRequest", "SetPlacementGroupResponse", diff --git a/scaleway-async/scaleway_async/instance/v1/api.py b/scaleway-async/scaleway_async/instance/v1/api.py index e7da5e4b0..a651f234f 100644 --- a/scaleway-async/scaleway_async/instance/v1/api.py +++ b/scaleway-async/scaleway_async/instance/v1/api.py @@ -108,6 +108,7 @@ ServerActionRequest, ServerActionRequestVolumeBackupTemplate, ServerActionResponse, + ServerCompatibleTypes, ServerIp, ServerIpv6, ServerLocation, @@ -189,6 +190,7 @@ unmarshal_ListVolumesTypesResponse, unmarshal_MigrationPlan, unmarshal_ServerActionResponse, + unmarshal_ServerCompatibleTypes, unmarshal_SetPlacementGroupResponse, unmarshal_SetPlacementGroupServersResponse, unmarshal_SetSecurityGroupRulesResponse, @@ -1036,6 +1038,43 @@ async def delete_server_user_data( self._throw_on_error(res) + async def get_server_compatible_types( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> ServerCompatibleTypes: + """ + Get Instance compatible types. + Get compatible commercial types that can be used to update the Instance. The compatibility of an Instance offer is based on: + * the CPU architecture + * the OS type + * the required l_ssd storage size + * the required scratch storage size + If the specified Instance offer is flagged as end of service, the best compatible offer is the first returned. + :param server_id: UUID of the Instance you want to get. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerCompatibleTypes ` + + Usage: + :: + + result = await api.get_server_compatible_types( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/compatible-types", + ) + + self._throw_on_error(res) + return unmarshal_ServerCompatibleTypes(res.json()) + async def attach_server_volume( self, *, diff --git a/scaleway-async/scaleway_async/instance/v1/marshalling.py b/scaleway-async/scaleway_async/instance/v1/marshalling.py index 1995d5b6c..68deee034 100644 --- a/scaleway-async/scaleway_async/instance/v1/marshalling.py +++ b/scaleway-async/scaleway_async/instance/v1/marshalling.py @@ -94,6 +94,7 @@ ListVolumesTypesResponse, MigrationPlan, ServerActionResponse, + ServerCompatibleTypes, SetPlacementGroupResponse, SetPlacementGroupServersResponse, SetSecurityGroupRulesResponse, @@ -2151,6 +2152,10 @@ def unmarshal_ServerType(data: Any) -> ServerType: if field is not None: args["baremetal"] = field + field = data.get("end_of_service", None) + if field is not None: + args["end_of_service"] = field + field = data.get("per_volume_constraint", None) if field is not None: args["per_volume_constraint"] = unmarshal_ServerTypeVolumeConstraintsByType( @@ -2391,6 +2396,21 @@ def unmarshal_ServerActionResponse(data: Any) -> ServerActionResponse: return ServerActionResponse(**args) +def unmarshal_ServerCompatibleTypes(data: Any) -> ServerCompatibleTypes: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerCompatibleTypes' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("compatible_types", None) + if field is not None: + args["compatible_types"] = field + + return ServerCompatibleTypes(**args) + + def unmarshal_SetPlacementGroupResponse(data: Any) -> SetPlacementGroupResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway-async/scaleway_async/instance/v1/types.py b/scaleway-async/scaleway_async/instance/v1/types.py index c9c90e339..bac61a4c7 100644 --- a/scaleway-async/scaleway_async/instance/v1/types.py +++ b/scaleway-async/scaleway_async/instance/v1/types.py @@ -1342,6 +1342,11 @@ class ServerType: True if it is a baremetal Instance. """ + end_of_service: bool + """ + True if this Instance type has reached end of service. + """ + per_volume_constraint: Optional[ServerTypeVolumeConstraintsByType] """ Additional volume constraints. @@ -2277,6 +2282,19 @@ class GetSecurityGroupRuleResponse: rule: Optional[SecurityGroupRule] +@dataclass +class GetServerCompatibleTypesRequest: + server_id: str + """ + UUID of the Instance you want to get. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class GetServerRequest: server_id: str @@ -3005,6 +3023,14 @@ class ServerActionResponse: task: Optional[Task] +@dataclass +class ServerCompatibleTypes: + compatible_types: List[str] + """ + Instance compatible types. + """ + + @dataclass class SetImageRequest: zone: Optional[ScwZone] diff --git a/scaleway/scaleway/instance/v1/__init__.py b/scaleway/scaleway/instance/v1/__init__.py index f6f393365..686123bd6 100644 --- a/scaleway/scaleway/instance/v1/__init__.py +++ b/scaleway/scaleway/instance/v1/__init__.py @@ -128,6 +128,7 @@ from .types import GetSecurityGroupResponse from .types import GetSecurityGroupRuleRequest from .types import GetSecurityGroupRuleResponse +from .types import GetServerCompatibleTypesRequest from .types import GetServerRequest from .types import GetServerResponse from .types import GetServerTypesAvailabilityRequest @@ -167,6 +168,7 @@ from .types import PlanBlockMigrationRequest from .types import ServerActionRequest from .types import ServerActionResponse +from .types import ServerCompatibleTypes from .types import SetImageRequest from .types import SetPlacementGroupRequest from .types import SetPlacementGroupResponse @@ -324,6 +326,7 @@ "GetSecurityGroupResponse", "GetSecurityGroupRuleRequest", "GetSecurityGroupRuleResponse", + "GetServerCompatibleTypesRequest", "GetServerRequest", "GetServerResponse", "GetServerTypesAvailabilityRequest", @@ -363,6 +366,7 @@ "PlanBlockMigrationRequest", "ServerActionRequest", "ServerActionResponse", + "ServerCompatibleTypes", "SetImageRequest", "SetPlacementGroupRequest", "SetPlacementGroupResponse", diff --git a/scaleway/scaleway/instance/v1/api.py b/scaleway/scaleway/instance/v1/api.py index c3b81a028..cc496fbcc 100644 --- a/scaleway/scaleway/instance/v1/api.py +++ b/scaleway/scaleway/instance/v1/api.py @@ -108,6 +108,7 @@ ServerActionRequest, ServerActionRequestVolumeBackupTemplate, ServerActionResponse, + ServerCompatibleTypes, ServerIp, ServerIpv6, ServerLocation, @@ -189,6 +190,7 @@ unmarshal_ListVolumesTypesResponse, unmarshal_MigrationPlan, unmarshal_ServerActionResponse, + unmarshal_ServerCompatibleTypes, unmarshal_SetPlacementGroupResponse, unmarshal_SetPlacementGroupServersResponse, unmarshal_SetSecurityGroupRulesResponse, @@ -1036,6 +1038,43 @@ def delete_server_user_data( self._throw_on_error(res) + def get_server_compatible_types( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> ServerCompatibleTypes: + """ + Get Instance compatible types. + Get compatible commercial types that can be used to update the Instance. The compatibility of an Instance offer is based on: + * the CPU architecture + * the OS type + * the required l_ssd storage size + * the required scratch storage size + If the specified Instance offer is flagged as end of service, the best compatible offer is the first returned. + :param server_id: UUID of the Instance you want to get. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerCompatibleTypes ` + + Usage: + :: + + result = api.get_server_compatible_types( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/compatible-types", + ) + + self._throw_on_error(res) + return unmarshal_ServerCompatibleTypes(res.json()) + def attach_server_volume( self, *, diff --git a/scaleway/scaleway/instance/v1/marshalling.py b/scaleway/scaleway/instance/v1/marshalling.py index 1995d5b6c..68deee034 100644 --- a/scaleway/scaleway/instance/v1/marshalling.py +++ b/scaleway/scaleway/instance/v1/marshalling.py @@ -94,6 +94,7 @@ ListVolumesTypesResponse, MigrationPlan, ServerActionResponse, + ServerCompatibleTypes, SetPlacementGroupResponse, SetPlacementGroupServersResponse, SetSecurityGroupRulesResponse, @@ -2151,6 +2152,10 @@ def unmarshal_ServerType(data: Any) -> ServerType: if field is not None: args["baremetal"] = field + field = data.get("end_of_service", None) + if field is not None: + args["end_of_service"] = field + field = data.get("per_volume_constraint", None) if field is not None: args["per_volume_constraint"] = unmarshal_ServerTypeVolumeConstraintsByType( @@ -2391,6 +2396,21 @@ def unmarshal_ServerActionResponse(data: Any) -> ServerActionResponse: return ServerActionResponse(**args) +def unmarshal_ServerCompatibleTypes(data: Any) -> ServerCompatibleTypes: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerCompatibleTypes' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("compatible_types", None) + if field is not None: + args["compatible_types"] = field + + return ServerCompatibleTypes(**args) + + def unmarshal_SetPlacementGroupResponse(data: Any) -> SetPlacementGroupResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway/scaleway/instance/v1/types.py b/scaleway/scaleway/instance/v1/types.py index c9c90e339..bac61a4c7 100644 --- a/scaleway/scaleway/instance/v1/types.py +++ b/scaleway/scaleway/instance/v1/types.py @@ -1342,6 +1342,11 @@ class ServerType: True if it is a baremetal Instance. """ + end_of_service: bool + """ + True if this Instance type has reached end of service. + """ + per_volume_constraint: Optional[ServerTypeVolumeConstraintsByType] """ Additional volume constraints. @@ -2277,6 +2282,19 @@ class GetSecurityGroupRuleResponse: rule: Optional[SecurityGroupRule] +@dataclass +class GetServerCompatibleTypesRequest: + server_id: str + """ + UUID of the Instance you want to get. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class GetServerRequest: server_id: str @@ -3005,6 +3023,14 @@ class ServerActionResponse: task: Optional[Task] +@dataclass +class ServerCompatibleTypes: + compatible_types: List[str] + """ + Instance compatible types. + """ + + @dataclass class SetImageRequest: zone: Optional[ScwZone] From bd6d794c055503df5cd3d88e4aede1d941a95f2f Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Wed, 26 Feb 2025 15:06:54 +0100 Subject: [PATCH 30/73] feat(baremetal): add support for `MigrateServerToMonthlyOfferRequest` (#868) --- .../scaleway_async/baremetal/v1/__init__.py | 2 ++ .../scaleway_async/baremetal/v1/api.py | 32 +++++++++++++++++++ .../scaleway_async/baremetal/v1/content.py | 1 + .../baremetal/v1/marshalling.py | 6 ++++ .../scaleway_async/baremetal/v1/types.py | 19 +++++++++++ scaleway/scaleway/baremetal/v1/__init__.py | 2 ++ scaleway/scaleway/baremetal/v1/api.py | 32 +++++++++++++++++++ scaleway/scaleway/baremetal/v1/content.py | 1 + scaleway/scaleway/baremetal/v1/marshalling.py | 6 ++++ scaleway/scaleway/baremetal/v1/types.py | 19 +++++++++++ 10 files changed, 120 insertions(+) diff --git a/scaleway-async/scaleway_async/baremetal/v1/__init__.py b/scaleway-async/scaleway_async/baremetal/v1/__init__.py index 96db8523c..f1ec9f1e5 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/__init__.py +++ b/scaleway-async/scaleway_async/baremetal/v1/__init__.py @@ -81,6 +81,7 @@ from .types import ListServersResponse from .types import ListSettingsRequest from .types import ListSettingsResponse +from .types import MigrateServerToMonthlyOfferRequest from .types import PrivateNetworkApiAddServerPrivateNetworkRequest from .types import PrivateNetworkApiDeleteServerPrivateNetworkRequest from .types import PrivateNetworkApiListServerPrivateNetworksRequest @@ -180,6 +181,7 @@ "ListServersResponse", "ListSettingsRequest", "ListSettingsResponse", + "MigrateServerToMonthlyOfferRequest", "PrivateNetworkApiAddServerPrivateNetworkRequest", "PrivateNetworkApiDeleteServerPrivateNetworkRequest", "PrivateNetworkApiListServerPrivateNetworksRequest", diff --git a/scaleway-async/scaleway_async/baremetal/v1/api.py b/scaleway-async/scaleway_async/baremetal/v1/api.py index 204dd12f5..24f8f9163 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/api.py +++ b/scaleway-async/scaleway_async/baremetal/v1/api.py @@ -1035,6 +1035,38 @@ async def delete_option_server( self._throw_on_error(res) return unmarshal_Server(res.json()) + async def migrate_server_to_monthly_offer( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> Server: + """ + Migrate server offer. + Migrate server with hourly offer to monthly offer. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = await api.migrate_server_to_monthly_offer( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/baremetal/v1/zones/{param_zone}/servers/{param_server_id}/migrate-offer-monthly", + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + async def list_offers( self, *, diff --git a/scaleway-async/scaleway_async/baremetal/v1/content.py b/scaleway-async/scaleway_async/baremetal/v1/content.py index e0817ef45..cc244bae7 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/content.py +++ b/scaleway-async/scaleway_async/baremetal/v1/content.py @@ -29,6 +29,7 @@ ServerStatus.DELETING, ServerStatus.ORDERED, ServerStatus.RESETTING, + ServerStatus.MIGRATING, ] """ Lists transient statutes of the enum :class:`ServerStatus `. diff --git a/scaleway-async/scaleway_async/baremetal/v1/marshalling.py b/scaleway-async/scaleway_async/baremetal/v1/marshalling.py index f04179dda..e95766ac5 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/marshalling.py +++ b/scaleway-async/scaleway_async/baremetal/v1/marshalling.py @@ -781,6 +781,12 @@ def unmarshal_Offer(data: Any) -> Offer: else: args["fee"] = None + field = data.get("monthly_offer_id", None) + if field is not None: + args["monthly_offer_id"] = field + else: + args["monthly_offer_id"] = None + return Offer(**args) diff --git a/scaleway-async/scaleway_async/baremetal/v1/types.py b/scaleway-async/scaleway_async/baremetal/v1/types.py index d419bad2e..6f0a4468a 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/types.py +++ b/scaleway-async/scaleway_async/baremetal/v1/types.py @@ -203,6 +203,7 @@ class ServerStatus(str, Enum, metaclass=StrEnumMeta): OUT_OF_STOCK = "out_of_stock" ORDERED = "ordered" RESETTING = "resetting" + MIGRATING = "migrating" def __str__(self) -> str: return str(self.value) @@ -824,6 +825,11 @@ class Offer: One time fee invoiced by Scaleway for the setup and activation of the server. """ + monthly_offer_id: Optional[str] + """ + Exist only for hourly offers, to migrate to the monthly offer. + """ + @dataclass class Option: @@ -1589,6 +1595,19 @@ class ListSettingsResponse: """ +@dataclass +class MigrateServerToMonthlyOfferRequest: + server_id: str + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class PrivateNetworkApiAddServerPrivateNetworkRequest: server_id: str diff --git a/scaleway/scaleway/baremetal/v1/__init__.py b/scaleway/scaleway/baremetal/v1/__init__.py index 96db8523c..f1ec9f1e5 100644 --- a/scaleway/scaleway/baremetal/v1/__init__.py +++ b/scaleway/scaleway/baremetal/v1/__init__.py @@ -81,6 +81,7 @@ from .types import ListServersResponse from .types import ListSettingsRequest from .types import ListSettingsResponse +from .types import MigrateServerToMonthlyOfferRequest from .types import PrivateNetworkApiAddServerPrivateNetworkRequest from .types import PrivateNetworkApiDeleteServerPrivateNetworkRequest from .types import PrivateNetworkApiListServerPrivateNetworksRequest @@ -180,6 +181,7 @@ "ListServersResponse", "ListSettingsRequest", "ListSettingsResponse", + "MigrateServerToMonthlyOfferRequest", "PrivateNetworkApiAddServerPrivateNetworkRequest", "PrivateNetworkApiDeleteServerPrivateNetworkRequest", "PrivateNetworkApiListServerPrivateNetworksRequest", diff --git a/scaleway/scaleway/baremetal/v1/api.py b/scaleway/scaleway/baremetal/v1/api.py index d4e1bc217..d9b73a500 100644 --- a/scaleway/scaleway/baremetal/v1/api.py +++ b/scaleway/scaleway/baremetal/v1/api.py @@ -1035,6 +1035,38 @@ def delete_option_server( self._throw_on_error(res) return unmarshal_Server(res.json()) + def migrate_server_to_monthly_offer( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> Server: + """ + Migrate server offer. + Migrate server with hourly offer to monthly offer. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = api.migrate_server_to_monthly_offer( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/baremetal/v1/zones/{param_zone}/servers/{param_server_id}/migrate-offer-monthly", + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + def list_offers( self, *, diff --git a/scaleway/scaleway/baremetal/v1/content.py b/scaleway/scaleway/baremetal/v1/content.py index e0817ef45..cc244bae7 100644 --- a/scaleway/scaleway/baremetal/v1/content.py +++ b/scaleway/scaleway/baremetal/v1/content.py @@ -29,6 +29,7 @@ ServerStatus.DELETING, ServerStatus.ORDERED, ServerStatus.RESETTING, + ServerStatus.MIGRATING, ] """ Lists transient statutes of the enum :class:`ServerStatus `. diff --git a/scaleway/scaleway/baremetal/v1/marshalling.py b/scaleway/scaleway/baremetal/v1/marshalling.py index f04179dda..e95766ac5 100644 --- a/scaleway/scaleway/baremetal/v1/marshalling.py +++ b/scaleway/scaleway/baremetal/v1/marshalling.py @@ -781,6 +781,12 @@ def unmarshal_Offer(data: Any) -> Offer: else: args["fee"] = None + field = data.get("monthly_offer_id", None) + if field is not None: + args["monthly_offer_id"] = field + else: + args["monthly_offer_id"] = None + return Offer(**args) diff --git a/scaleway/scaleway/baremetal/v1/types.py b/scaleway/scaleway/baremetal/v1/types.py index d419bad2e..6f0a4468a 100644 --- a/scaleway/scaleway/baremetal/v1/types.py +++ b/scaleway/scaleway/baremetal/v1/types.py @@ -203,6 +203,7 @@ class ServerStatus(str, Enum, metaclass=StrEnumMeta): OUT_OF_STOCK = "out_of_stock" ORDERED = "ordered" RESETTING = "resetting" + MIGRATING = "migrating" def __str__(self) -> str: return str(self.value) @@ -824,6 +825,11 @@ class Offer: One time fee invoiced by Scaleway for the setup and activation of the server. """ + monthly_offer_id: Optional[str] + """ + Exist only for hourly offers, to migrate to the monthly offer. + """ + @dataclass class Option: @@ -1589,6 +1595,19 @@ class ListSettingsResponse: """ +@dataclass +class MigrateServerToMonthlyOfferRequest: + server_id: str + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class PrivateNetworkApiAddServerPrivateNetworkRequest: server_id: str From 99f4096e94435eb6a705a4cb3e0550c931b24147 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Wed, 26 Feb 2025 17:15:42 +0100 Subject: [PATCH 31/73] feat(audit_trail): add support for `Resources` (#870) --- .../audit_trail/v1alpha1/marshalling.py | 14 ++++++++++---- .../scaleway_async/audit_trail/v1alpha1/types.py | 15 ++++++++++----- .../scaleway/audit_trail/v1alpha1/marshalling.py | 14 ++++++++++---- scaleway/scaleway/audit_trail/v1alpha1/types.py | 15 ++++++++++----- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py index aecfda29e..53c8f9f9a 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py @@ -251,10 +251,6 @@ def unmarshal_Event(data: Any) -> Event: if field is not None: args["source_ip"] = field - field = data.get("product_name", None) - if field is not None: - args["product_name"] = field - field = data.get("recorded_at", None) if field is not None: args["recorded_at"] = ( @@ -281,6 +277,10 @@ def unmarshal_Event(data: Any) -> Event: else: args["user_agent"] = None + field = data.get("product_name", None) + if field is not None: + args["product_name"] = field + field = data.get("service_name", None) if field is not None: args["service_name"] = field @@ -289,6 +289,12 @@ def unmarshal_Event(data: Any) -> Event: if field is not None: args["method_name"] = field + field = data.get("resources", None) + if field is not None: + args["resources"] = ( + [unmarshal_Resource(v) for v in field] if field is not None else None + ) + field = data.get("request_id", None) if field is not None: args["request_id"] = field diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py index 3db3219ea..6f78c25be 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py @@ -145,11 +145,6 @@ class Event: IP address at the origin of the event. """ - product_name: str - """ - Product name of the resource attached to the event. - """ - recorded_at: Optional[datetime] """ Timestamp of the event. @@ -170,6 +165,11 @@ class Event: User Agent at the origin of the event. """ + product_name: str + """ + Product name of the resource attached to the event. + """ + service_name: str """ API name called to trigger the event. @@ -180,6 +180,11 @@ class Event: API method called to trigger the event. """ + resources: List[Resource] + """ + Resources attached to the event. + """ + request_id: str """ Unique identifier of the request at the origin of the event. diff --git a/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py b/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py index aecfda29e..53c8f9f9a 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py @@ -251,10 +251,6 @@ def unmarshal_Event(data: Any) -> Event: if field is not None: args["source_ip"] = field - field = data.get("product_name", None) - if field is not None: - args["product_name"] = field - field = data.get("recorded_at", None) if field is not None: args["recorded_at"] = ( @@ -281,6 +277,10 @@ def unmarshal_Event(data: Any) -> Event: else: args["user_agent"] = None + field = data.get("product_name", None) + if field is not None: + args["product_name"] = field + field = data.get("service_name", None) if field is not None: args["service_name"] = field @@ -289,6 +289,12 @@ def unmarshal_Event(data: Any) -> Event: if field is not None: args["method_name"] = field + field = data.get("resources", None) + if field is not None: + args["resources"] = ( + [unmarshal_Resource(v) for v in field] if field is not None else None + ) + field = data.get("request_id", None) if field is not None: args["request_id"] = field diff --git a/scaleway/scaleway/audit_trail/v1alpha1/types.py b/scaleway/scaleway/audit_trail/v1alpha1/types.py index 3db3219ea..6f78c25be 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/types.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/types.py @@ -145,11 +145,6 @@ class Event: IP address at the origin of the event. """ - product_name: str - """ - Product name of the resource attached to the event. - """ - recorded_at: Optional[datetime] """ Timestamp of the event. @@ -170,6 +165,11 @@ class Event: User Agent at the origin of the event. """ + product_name: str + """ + Product name of the resource attached to the event. + """ + service_name: str """ API name called to trigger the event. @@ -180,6 +180,11 @@ class Event: API method called to trigger the event. """ + resources: List[Resource] + """ + Resources attached to the event. + """ + request_id: str """ Unique identifier of the request at the origin of the event. From 6e6d3cd0a4fd6895e2f1dada422d252a037f52d0 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 27 Feb 2025 11:51:10 +0100 Subject: [PATCH 32/73] feat(audit_trail): add organization_id field to ListProducts (#871) --- scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py | 6 ++++++ scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py | 5 +++++ scaleway/scaleway/audit_trail/v1alpha1/api.py | 6 ++++++ scaleway/scaleway/audit_trail/v1alpha1/types.py | 5 +++++ 4 files changed, 22 insertions(+) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py index a7c4aae16..f881959b3 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py @@ -97,10 +97,12 @@ async def list_products( self, *, region: Optional[ScwRegion] = None, + organization_id: Optional[str] = None, ) -> ListProductsResponse: """ Retrieve the list of Scaleway resources for which you have Audit Trail events. :param region: Region to target. If none is passed will use default region from the config. + :param organization_id: ID of the Organization containing the Audit Trail events. :return: :class:`ListProductsResponse ` Usage: @@ -116,6 +118,10 @@ async def list_products( res = self._request( "GET", f"/audit-trail/v1alpha1/regions/{param_region}/products", + params={ + "organization_id": organization_id + or self.client.default_organization_id, + }, ) self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py index 6f78c25be..bad7d376b 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py @@ -298,6 +298,11 @@ class ListProductsRequest: Region to target. If none is passed will use default region from the config. """ + organization_id: Optional[str] + """ + ID of the Organization containing the Audit Trail events. + """ + @dataclass class ListProductsResponse: diff --git a/scaleway/scaleway/audit_trail/v1alpha1/api.py b/scaleway/scaleway/audit_trail/v1alpha1/api.py index fd41571b7..5b82ec892 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/api.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/api.py @@ -97,10 +97,12 @@ def list_products( self, *, region: Optional[ScwRegion] = None, + organization_id: Optional[str] = None, ) -> ListProductsResponse: """ Retrieve the list of Scaleway resources for which you have Audit Trail events. :param region: Region to target. If none is passed will use default region from the config. + :param organization_id: ID of the Organization containing the Audit Trail events. :return: :class:`ListProductsResponse ` Usage: @@ -116,6 +118,10 @@ def list_products( res = self._request( "GET", f"/audit-trail/v1alpha1/regions/{param_region}/products", + params={ + "organization_id": organization_id + or self.client.default_organization_id, + }, ) self._throw_on_error(res) diff --git a/scaleway/scaleway/audit_trail/v1alpha1/types.py b/scaleway/scaleway/audit_trail/v1alpha1/types.py index 6f78c25be..bad7d376b 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/types.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/types.py @@ -298,6 +298,11 @@ class ListProductsRequest: Region to target. If none is passed will use default region from the config. """ + organization_id: Optional[str] + """ + ID of the Organization containing the Audit Trail events. + """ + @dataclass class ListProductsResponse: From e74ccfbd971c9eac28242d9cd1a4c2d03fa34c5a Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 27 Feb 2025 17:04:32 +0100 Subject: [PATCH 33/73] feat(mongodb): implement roles permissions api (#873) --- .../mongodb/v1alpha1/__init__.py | 6 ++ .../scaleway_async/mongodb/v1alpha1/api.py | 49 +++++++++++++ .../mongodb/v1alpha1/marshalling.py | 70 +++++++++++++++++++ .../scaleway_async/mongodb/v1alpha1/types.py | 47 +++++++++++++ .../scaleway/mongodb/v1alpha1/__init__.py | 6 ++ scaleway/scaleway/mongodb/v1alpha1/api.py | 49 +++++++++++++ .../scaleway/mongodb/v1alpha1/marshalling.py | 70 +++++++++++++++++++ scaleway/scaleway/mongodb/v1alpha1/types.py | 47 +++++++++++++ 8 files changed, 344 insertions(+) diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/__init__.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/__init__.py index d1d42a9ed..697dc1694 100644 --- a/scaleway-async/scaleway_async/mongodb/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/__init__.py @@ -9,6 +9,7 @@ from .types import SettingPropertyType from .types import SnapshotStatus from .content import SNAPSHOT_TRANSIENT_STATUSES +from .types import UserRoleRole from .types import VolumeType from .types import EndpointPrivateNetworkDetails from .types import EndpointPublicDetails @@ -19,6 +20,7 @@ from .types import Volume from .types import NodeTypeVolumeType from .types import SnapshotVolumeType +from .types import UserRole from .types import Setting from .types import EndpointSpec from .types import CreateInstanceRequestVolumeDetails @@ -50,6 +52,7 @@ from .types import ListVersionsRequest from .types import ListVersionsResponse from .types import RestoreSnapshotRequest +from .types import SetUserRoleRequest from .types import UpdateInstanceRequest from .types import UpdateSnapshotRequest from .types import UpdateUserRequest @@ -66,6 +69,7 @@ "SettingPropertyType", "SnapshotStatus", "SNAPSHOT_TRANSIENT_STATUSES", + "UserRoleRole", "VolumeType", "EndpointPrivateNetworkDetails", "EndpointPublicDetails", @@ -76,6 +80,7 @@ "Volume", "NodeTypeVolumeType", "SnapshotVolumeType", + "UserRole", "Setting", "EndpointSpec", "CreateInstanceRequestVolumeDetails", @@ -107,6 +112,7 @@ "ListVersionsRequest", "ListVersionsResponse", "RestoreSnapshotRequest", + "SetUserRoleRequest", "UpdateInstanceRequest", "UpdateSnapshotRequest", "UpdateUserRequest", diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/api.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/api.py index b38b712f2..dc413e65a 100644 --- a/scaleway-async/scaleway_async/mongodb/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/api.py @@ -37,12 +37,14 @@ NodeType, RestoreSnapshotRequest, RestoreSnapshotRequestVolumeDetails, + SetUserRoleRequest, Snapshot, UpdateInstanceRequest, UpdateSnapshotRequest, UpdateUserRequest, UpgradeInstanceRequest, User, + UserRole, Version, ) from .content import ( @@ -64,6 +66,7 @@ marshal_CreateSnapshotRequest, marshal_CreateUserRequest, marshal_RestoreSnapshotRequest, + marshal_SetUserRoleRequest, marshal_UpdateInstanceRequest, marshal_UpdateSnapshotRequest, marshal_UpdateUserRequest, @@ -1211,6 +1214,52 @@ async def delete_user( self._throw_on_error(res) + async def set_user_role( + self, + *, + instance_id: str, + user_name: str, + region: Optional[ScwRegion] = None, + roles: Optional[List[UserRole]] = None, + ) -> User: + """ + :param instance_id: UUID of the Database Instance the user belongs to. + :param user_name: Name of the database user. + :param region: Region to target. If none is passed will use default region from the config. + :param roles: List of roles assigned to the user, along with the corresponding database where each role is granted. + :return: :class:`User ` + + Usage: + :: + + result = await api.set_user_role( + instance_id="example", + user_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "PUT", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/roles", + body=marshal_SetUserRoleRequest( + SetUserRoleRequest( + instance_id=instance_id, + user_name=user_name, + region=region, + roles=roles, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + async def delete_endpoint( self, *, diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/marshalling.py index d491bab89..9b267ac13 100644 --- a/scaleway-async/scaleway_async/mongodb/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/marshalling.py @@ -18,6 +18,7 @@ Instance, SnapshotVolumeType, Snapshot, + UserRole, User, ListInstancesResponse, NodeTypeVolumeType, @@ -38,6 +39,7 @@ CreateUserRequest, RestoreSnapshotRequestVolumeDetails, RestoreSnapshotRequest, + SetUserRoleRequest, UpdateInstanceRequest, UpdateSnapshotRequest, UpdateUserRequest, @@ -301,6 +303,33 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: return Snapshot(**args) +def unmarshal_UserRole(data: Any) -> UserRole: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'UserRole' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("role", None) + if field is not None: + args["role"] = field + + field = data.get("database", None) + if field is not None: + args["database"] = field + else: + args["database"] = None + + field = data.get("any_database", None) + if field is not None: + args["any_database"] = field + else: + args["any_database"] = None + + return UserRole(**args) + + def unmarshal_User(data: Any) -> User: if not isinstance(data, dict): raise TypeError( @@ -313,6 +342,12 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["name"] = field + field = data.get("roles", None) + if field is not None: + args["roles"] = ( + [unmarshal_UserRole(v) for v in field] if field is not None else None + ) + return User(**args) @@ -775,6 +810,41 @@ def marshal_RestoreSnapshotRequest( return output +def marshal_UserRole( + request: UserRole, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("database", request.database), + OneOfPossibility("any_database", request.any_database), + ] + ), + ) + + if request.role is not None: + output["role"] = str(request.role) + + return output + + +def marshal_SetUserRoleRequest( + request: SetUserRoleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.user_name is not None: + output["user_name"] = request.user_name + + if request.roles is not None: + output["roles"] = [marshal_UserRole(item, defaults) for item in request.roles] + + return output + + def marshal_UpdateInstanceRequest( request: UpdateInstanceRequest, defaults: ProfileDefaults, diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py index a1ee32000..422e5431a 100644 --- a/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py @@ -95,6 +95,16 @@ def __str__(self) -> str: return str(self.value) +class UserRoleRole(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ROLE = "unknown_role" + READ = "read" + READ_WRITE = "read_write" + DB_ADMIN = "db_admin" + + def __str__(self) -> str: + return str(self.value) + + class VolumeType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_TYPE = "unknown_type" SBS_5K = "sbs_5k" @@ -220,6 +230,15 @@ class SnapshotVolumeType: type_: VolumeType +@dataclass +class UserRole: + role: UserRoleRole + + database: Optional[str] + + any_database: Optional[bool] + + @dataclass class Setting: name: str @@ -484,6 +503,11 @@ class User: Name of the user (Length must be between 1 and 63 characters. First character must be an alphabet character (a-zA-Z). Only a-zA-Z0-9_$- characters are accepted). """ + roles: List[UserRole] + """ + List of roles assigned to the user, along with the corresponding database where each role is granted. + """ + @dataclass class Version: @@ -959,6 +983,29 @@ class RestoreSnapshotRequest: """ +@dataclass +class SetUserRoleRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + user_name: str + """ + Name of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + roles: Optional[List[UserRole]] + """ + List of roles assigned to the user, along with the corresponding database where each role is granted. + """ + + @dataclass class UpdateInstanceRequest: instance_id: str diff --git a/scaleway/scaleway/mongodb/v1alpha1/__init__.py b/scaleway/scaleway/mongodb/v1alpha1/__init__.py index d1d42a9ed..697dc1694 100644 --- a/scaleway/scaleway/mongodb/v1alpha1/__init__.py +++ b/scaleway/scaleway/mongodb/v1alpha1/__init__.py @@ -9,6 +9,7 @@ from .types import SettingPropertyType from .types import SnapshotStatus from .content import SNAPSHOT_TRANSIENT_STATUSES +from .types import UserRoleRole from .types import VolumeType from .types import EndpointPrivateNetworkDetails from .types import EndpointPublicDetails @@ -19,6 +20,7 @@ from .types import Volume from .types import NodeTypeVolumeType from .types import SnapshotVolumeType +from .types import UserRole from .types import Setting from .types import EndpointSpec from .types import CreateInstanceRequestVolumeDetails @@ -50,6 +52,7 @@ from .types import ListVersionsRequest from .types import ListVersionsResponse from .types import RestoreSnapshotRequest +from .types import SetUserRoleRequest from .types import UpdateInstanceRequest from .types import UpdateSnapshotRequest from .types import UpdateUserRequest @@ -66,6 +69,7 @@ "SettingPropertyType", "SnapshotStatus", "SNAPSHOT_TRANSIENT_STATUSES", + "UserRoleRole", "VolumeType", "EndpointPrivateNetworkDetails", "EndpointPublicDetails", @@ -76,6 +80,7 @@ "Volume", "NodeTypeVolumeType", "SnapshotVolumeType", + "UserRole", "Setting", "EndpointSpec", "CreateInstanceRequestVolumeDetails", @@ -107,6 +112,7 @@ "ListVersionsRequest", "ListVersionsResponse", "RestoreSnapshotRequest", + "SetUserRoleRequest", "UpdateInstanceRequest", "UpdateSnapshotRequest", "UpdateUserRequest", diff --git a/scaleway/scaleway/mongodb/v1alpha1/api.py b/scaleway/scaleway/mongodb/v1alpha1/api.py index 6745175a0..1af856560 100644 --- a/scaleway/scaleway/mongodb/v1alpha1/api.py +++ b/scaleway/scaleway/mongodb/v1alpha1/api.py @@ -37,12 +37,14 @@ NodeType, RestoreSnapshotRequest, RestoreSnapshotRequestVolumeDetails, + SetUserRoleRequest, Snapshot, UpdateInstanceRequest, UpdateSnapshotRequest, UpdateUserRequest, UpgradeInstanceRequest, User, + UserRole, Version, ) from .content import ( @@ -64,6 +66,7 @@ marshal_CreateSnapshotRequest, marshal_CreateUserRequest, marshal_RestoreSnapshotRequest, + marshal_SetUserRoleRequest, marshal_UpdateInstanceRequest, marshal_UpdateSnapshotRequest, marshal_UpdateUserRequest, @@ -1207,6 +1210,52 @@ def delete_user( self._throw_on_error(res) + def set_user_role( + self, + *, + instance_id: str, + user_name: str, + region: Optional[ScwRegion] = None, + roles: Optional[List[UserRole]] = None, + ) -> User: + """ + :param instance_id: UUID of the Database Instance the user belongs to. + :param user_name: Name of the database user. + :param region: Region to target. If none is passed will use default region from the config. + :param roles: List of roles assigned to the user, along with the corresponding database where each role is granted. + :return: :class:`User ` + + Usage: + :: + + result = api.set_user_role( + instance_id="example", + user_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "PUT", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/roles", + body=marshal_SetUserRoleRequest( + SetUserRoleRequest( + instance_id=instance_id, + user_name=user_name, + region=region, + roles=roles, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + def delete_endpoint( self, *, diff --git a/scaleway/scaleway/mongodb/v1alpha1/marshalling.py b/scaleway/scaleway/mongodb/v1alpha1/marshalling.py index d491bab89..9b267ac13 100644 --- a/scaleway/scaleway/mongodb/v1alpha1/marshalling.py +++ b/scaleway/scaleway/mongodb/v1alpha1/marshalling.py @@ -18,6 +18,7 @@ Instance, SnapshotVolumeType, Snapshot, + UserRole, User, ListInstancesResponse, NodeTypeVolumeType, @@ -38,6 +39,7 @@ CreateUserRequest, RestoreSnapshotRequestVolumeDetails, RestoreSnapshotRequest, + SetUserRoleRequest, UpdateInstanceRequest, UpdateSnapshotRequest, UpdateUserRequest, @@ -301,6 +303,33 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: return Snapshot(**args) +def unmarshal_UserRole(data: Any) -> UserRole: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'UserRole' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("role", None) + if field is not None: + args["role"] = field + + field = data.get("database", None) + if field is not None: + args["database"] = field + else: + args["database"] = None + + field = data.get("any_database", None) + if field is not None: + args["any_database"] = field + else: + args["any_database"] = None + + return UserRole(**args) + + def unmarshal_User(data: Any) -> User: if not isinstance(data, dict): raise TypeError( @@ -313,6 +342,12 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["name"] = field + field = data.get("roles", None) + if field is not None: + args["roles"] = ( + [unmarshal_UserRole(v) for v in field] if field is not None else None + ) + return User(**args) @@ -775,6 +810,41 @@ def marshal_RestoreSnapshotRequest( return output +def marshal_UserRole( + request: UserRole, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("database", request.database), + OneOfPossibility("any_database", request.any_database), + ] + ), + ) + + if request.role is not None: + output["role"] = str(request.role) + + return output + + +def marshal_SetUserRoleRequest( + request: SetUserRoleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.user_name is not None: + output["user_name"] = request.user_name + + if request.roles is not None: + output["roles"] = [marshal_UserRole(item, defaults) for item in request.roles] + + return output + + def marshal_UpdateInstanceRequest( request: UpdateInstanceRequest, defaults: ProfileDefaults, diff --git a/scaleway/scaleway/mongodb/v1alpha1/types.py b/scaleway/scaleway/mongodb/v1alpha1/types.py index a1ee32000..422e5431a 100644 --- a/scaleway/scaleway/mongodb/v1alpha1/types.py +++ b/scaleway/scaleway/mongodb/v1alpha1/types.py @@ -95,6 +95,16 @@ def __str__(self) -> str: return str(self.value) +class UserRoleRole(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ROLE = "unknown_role" + READ = "read" + READ_WRITE = "read_write" + DB_ADMIN = "db_admin" + + def __str__(self) -> str: + return str(self.value) + + class VolumeType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_TYPE = "unknown_type" SBS_5K = "sbs_5k" @@ -220,6 +230,15 @@ class SnapshotVolumeType: type_: VolumeType +@dataclass +class UserRole: + role: UserRoleRole + + database: Optional[str] + + any_database: Optional[bool] + + @dataclass class Setting: name: str @@ -484,6 +503,11 @@ class User: Name of the user (Length must be between 1 and 63 characters. First character must be an alphabet character (a-zA-Z). Only a-zA-Z0-9_$- characters are accepted). """ + roles: List[UserRole] + """ + List of roles assigned to the user, along with the corresponding database where each role is granted. + """ + @dataclass class Version: @@ -959,6 +983,29 @@ class RestoreSnapshotRequest: """ +@dataclass +class SetUserRoleRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + user_name: str + """ + Name of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + roles: Optional[List[UserRole]] + """ + List of roles assigned to the user, along with the corresponding database where each role is granted. + """ + + @dataclass class UpdateInstanceRequest: instance_id: str From 52424e9710d967cfebfe70b642612d57bbe81316 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 27 Feb 2025 17:05:18 +0100 Subject: [PATCH 34/73] fix(webhosting): add hosting status naming (#875) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémy Léone --- .../scaleway_async/webhosting/v1/__init__.py | 4 --- .../scaleway_async/webhosting/v1/content.py | 9 ------ .../webhosting/v1/marshalling.py | 14 +++------ .../scaleway_async/webhosting/v1/types.py | 29 ++++--------------- scaleway/scaleway/webhosting/v1/__init__.py | 4 --- scaleway/scaleway/webhosting/v1/content.py | 9 ------ .../scaleway/webhosting/v1/marshalling.py | 14 +++------ scaleway/scaleway/webhosting/v1/types.py | 29 ++++--------------- 8 files changed, 20 insertions(+), 92 deletions(-) diff --git a/scaleway-async/scaleway_async/webhosting/v1/__init__.py b/scaleway-async/scaleway_async/webhosting/v1/__init__.py index 467720f2b..8c351383b 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/__init__.py +++ b/scaleway-async/scaleway_async/webhosting/v1/__init__.py @@ -13,8 +13,6 @@ from .types import DomainZoneOwner from .types import HostingStatus from .content import HOSTING_TRANSIENT_STATUSES -from .types import HostingSummaryStatus -from .content import HOSTING_SUMMARY_TRANSIENT_STATUSES from .types import ListDatabaseUsersRequestOrderBy from .types import ListDatabasesRequestOrderBy from .types import ListFtpAccountsRequestOrderBy @@ -120,8 +118,6 @@ "DomainZoneOwner", "HostingStatus", "HOSTING_TRANSIENT_STATUSES", - "HostingSummaryStatus", - "HOSTING_SUMMARY_TRANSIENT_STATUSES", "ListDatabaseUsersRequestOrderBy", "ListDatabasesRequestOrderBy", "ListFtpAccountsRequestOrderBy", diff --git a/scaleway-async/scaleway_async/webhosting/v1/content.py b/scaleway-async/scaleway_async/webhosting/v1/content.py index 7c429cec5..9c1b79cff 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/content.py +++ b/scaleway-async/scaleway_async/webhosting/v1/content.py @@ -6,7 +6,6 @@ DomainAvailabilityStatus, DomainStatus, HostingStatus, - HostingSummaryStatus, ) DOMAIN_AVAILABILITY_TRANSIENT_STATUSES: List[DomainAvailabilityStatus] = [ @@ -29,11 +28,3 @@ """ Lists transient statutes of the enum :class:`HostingStatus `. """ -HOSTING_SUMMARY_TRANSIENT_STATUSES: List[HostingSummaryStatus] = [ - HostingSummaryStatus.DELIVERING, - HostingSummaryStatus.DELETING, - HostingSummaryStatus.MIGRATING, -] -""" -Lists transient statutes of the enum :class:`HostingSummaryStatus `. -""" diff --git a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py index 1b9f53550..f5882871e 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py +++ b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py @@ -705,6 +705,10 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: if field is not None: args["project_id"] = field + field = data.get("status", None) + if field is not None: + args["status"] = field + field = data.get("domain", None) if field is not None: args["domain"] = field @@ -717,10 +721,6 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: if field is not None: args["offer_name"] = field - field = data.get("hosting_status", None) - if field is not None: - args["hosting_status"] = field - field = data.get("domain_status", None) if field is not None: args["domain_status"] = field @@ -741,12 +741,6 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: else: args["updated_at"] = None - field = data.get("status", None) - if field is not None: - args["status"] = field - else: - args["status"] = None - field = data.get("dns_status", None) if field is not None: args["dns_status"] = field diff --git a/scaleway-async/scaleway_async/webhosting/v1/types.py b/scaleway-async/scaleway_async/webhosting/v1/types.py index 2bf188a66..cf37b2064 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/types.py +++ b/scaleway-async/scaleway_async/webhosting/v1/types.py @@ -89,6 +89,7 @@ class DomainDnsAction(str, Enum, metaclass=StrEnumMeta): AUTO_CONFIG_WEB_RECORDS = "auto_config_web_records" AUTO_CONFIG_MAIL_RECORDS = "auto_config_mail_records" AUTO_CONFIG_NAMESERVERS = "auto_config_nameservers" + AUTO_CONFIG_NONE = "auto_config_none" def __str__(self) -> str: return str(self.value) @@ -129,19 +130,6 @@ def __str__(self) -> str: return str(self.value) -class HostingSummaryStatus(str, Enum, metaclass=StrEnumMeta): - UNKNOWN_STATUS = "unknown_status" - DELIVERING = "delivering" - READY = "ready" - DELETING = "deleting" - ERROR = "error" - LOCKED = "locked" - MIGRATING = "migrating" - - def __str__(self) -> str: - return str(self.value) - - class ListDatabaseUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): USERNAME_ASC = "username_asc" USERNAME_DESC = "username_desc" @@ -579,6 +567,11 @@ class HostingSummary: ID of the Scaleway Project the Web Hosting plan belongs to. """ + status: HostingStatus + """ + Status of the Web Hosting plan. + """ + domain: str """ Main domain associated with the Web Hosting plan. @@ -594,11 +587,6 @@ class HostingSummary: Name of the active offer for the Web Hosting plan. """ - hosting_status: HostingStatus - """ - Status of the Web Hosting plan. - """ - domain_status: DomainStatus """ Main domain status of the Web Hosting plan. @@ -619,11 +607,6 @@ class HostingSummary: Date on which the Web Hosting plan was last updated. """ - status: Optional[HostingSummaryStatus] - """ - Status of the Web Hosting plan. - """ - dns_status: Optional[DnsRecordsStatus] """ DNS status of the Web Hosting plan. diff --git a/scaleway/scaleway/webhosting/v1/__init__.py b/scaleway/scaleway/webhosting/v1/__init__.py index 467720f2b..8c351383b 100644 --- a/scaleway/scaleway/webhosting/v1/__init__.py +++ b/scaleway/scaleway/webhosting/v1/__init__.py @@ -13,8 +13,6 @@ from .types import DomainZoneOwner from .types import HostingStatus from .content import HOSTING_TRANSIENT_STATUSES -from .types import HostingSummaryStatus -from .content import HOSTING_SUMMARY_TRANSIENT_STATUSES from .types import ListDatabaseUsersRequestOrderBy from .types import ListDatabasesRequestOrderBy from .types import ListFtpAccountsRequestOrderBy @@ -120,8 +118,6 @@ "DomainZoneOwner", "HostingStatus", "HOSTING_TRANSIENT_STATUSES", - "HostingSummaryStatus", - "HOSTING_SUMMARY_TRANSIENT_STATUSES", "ListDatabaseUsersRequestOrderBy", "ListDatabasesRequestOrderBy", "ListFtpAccountsRequestOrderBy", diff --git a/scaleway/scaleway/webhosting/v1/content.py b/scaleway/scaleway/webhosting/v1/content.py index 7c429cec5..9c1b79cff 100644 --- a/scaleway/scaleway/webhosting/v1/content.py +++ b/scaleway/scaleway/webhosting/v1/content.py @@ -6,7 +6,6 @@ DomainAvailabilityStatus, DomainStatus, HostingStatus, - HostingSummaryStatus, ) DOMAIN_AVAILABILITY_TRANSIENT_STATUSES: List[DomainAvailabilityStatus] = [ @@ -29,11 +28,3 @@ """ Lists transient statutes of the enum :class:`HostingStatus `. """ -HOSTING_SUMMARY_TRANSIENT_STATUSES: List[HostingSummaryStatus] = [ - HostingSummaryStatus.DELIVERING, - HostingSummaryStatus.DELETING, - HostingSummaryStatus.MIGRATING, -] -""" -Lists transient statutes of the enum :class:`HostingSummaryStatus `. -""" diff --git a/scaleway/scaleway/webhosting/v1/marshalling.py b/scaleway/scaleway/webhosting/v1/marshalling.py index 1b9f53550..f5882871e 100644 --- a/scaleway/scaleway/webhosting/v1/marshalling.py +++ b/scaleway/scaleway/webhosting/v1/marshalling.py @@ -705,6 +705,10 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: if field is not None: args["project_id"] = field + field = data.get("status", None) + if field is not None: + args["status"] = field + field = data.get("domain", None) if field is not None: args["domain"] = field @@ -717,10 +721,6 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: if field is not None: args["offer_name"] = field - field = data.get("hosting_status", None) - if field is not None: - args["hosting_status"] = field - field = data.get("domain_status", None) if field is not None: args["domain_status"] = field @@ -741,12 +741,6 @@ def unmarshal_HostingSummary(data: Any) -> HostingSummary: else: args["updated_at"] = None - field = data.get("status", None) - if field is not None: - args["status"] = field - else: - args["status"] = None - field = data.get("dns_status", None) if field is not None: args["dns_status"] = field diff --git a/scaleway/scaleway/webhosting/v1/types.py b/scaleway/scaleway/webhosting/v1/types.py index 2bf188a66..cf37b2064 100644 --- a/scaleway/scaleway/webhosting/v1/types.py +++ b/scaleway/scaleway/webhosting/v1/types.py @@ -89,6 +89,7 @@ class DomainDnsAction(str, Enum, metaclass=StrEnumMeta): AUTO_CONFIG_WEB_RECORDS = "auto_config_web_records" AUTO_CONFIG_MAIL_RECORDS = "auto_config_mail_records" AUTO_CONFIG_NAMESERVERS = "auto_config_nameservers" + AUTO_CONFIG_NONE = "auto_config_none" def __str__(self) -> str: return str(self.value) @@ -129,19 +130,6 @@ def __str__(self) -> str: return str(self.value) -class HostingSummaryStatus(str, Enum, metaclass=StrEnumMeta): - UNKNOWN_STATUS = "unknown_status" - DELIVERING = "delivering" - READY = "ready" - DELETING = "deleting" - ERROR = "error" - LOCKED = "locked" - MIGRATING = "migrating" - - def __str__(self) -> str: - return str(self.value) - - class ListDatabaseUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): USERNAME_ASC = "username_asc" USERNAME_DESC = "username_desc" @@ -579,6 +567,11 @@ class HostingSummary: ID of the Scaleway Project the Web Hosting plan belongs to. """ + status: HostingStatus + """ + Status of the Web Hosting plan. + """ + domain: str """ Main domain associated with the Web Hosting plan. @@ -594,11 +587,6 @@ class HostingSummary: Name of the active offer for the Web Hosting plan. """ - hosting_status: HostingStatus - """ - Status of the Web Hosting plan. - """ - domain_status: DomainStatus """ Main domain status of the Web Hosting plan. @@ -619,11 +607,6 @@ class HostingSummary: Date on which the Web Hosting plan was last updated. """ - status: Optional[HostingSummaryStatus] - """ - Status of the Web Hosting plan. - """ - dns_status: Optional[DnsRecordsStatus] """ DNS status of the Web Hosting plan. From a36d8bd61b6177018e2c5fbec408927a8132993f Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 27 Feb 2025 17:24:33 +0100 Subject: [PATCH 35/73] feat(edge_services): add support for v1beta1 (#874) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémy Léone Co-authored-by: devtools-ci-cd --- .../edge_services/v1beta1/__init__.py | 253 ++ .../edge_services/v1beta1/api.py | 2614 +++++++++++++++++ .../edge_services/v1beta1/content.py | 21 + .../edge_services/v1beta1/marshalling.py | 1901 ++++++++++++ .../edge_services/v1beta1/types.py | 1780 +++++++++++ .../edge_services/v1beta1/__init__.py | 253 ++ .../scaleway/edge_services/v1beta1/api.py | 2610 ++++++++++++++++ .../scaleway/edge_services/v1beta1/content.py | 21 + .../edge_services/v1beta1/marshalling.py | 1901 ++++++++++++ .../scaleway/edge_services/v1beta1/types.py | 1780 +++++++++++ 10 files changed, 13134 insertions(+) create mode 100644 scaleway-async/scaleway_async/edge_services/v1beta1/__init__.py create mode 100644 scaleway-async/scaleway_async/edge_services/v1beta1/api.py create mode 100644 scaleway-async/scaleway_async/edge_services/v1beta1/content.py create mode 100644 scaleway-async/scaleway_async/edge_services/v1beta1/marshalling.py create mode 100644 scaleway-async/scaleway_async/edge_services/v1beta1/types.py create mode 100644 scaleway/scaleway/edge_services/v1beta1/__init__.py create mode 100644 scaleway/scaleway/edge_services/v1beta1/api.py create mode 100644 scaleway/scaleway/edge_services/v1beta1/content.py create mode 100644 scaleway/scaleway/edge_services/v1beta1/marshalling.py create mode 100644 scaleway/scaleway/edge_services/v1beta1/types.py diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/__init__.py b/scaleway-async/scaleway_async/edge_services/v1beta1/__init__.py new file mode 100644 index 000000000..88bf53a51 --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/__init__.py @@ -0,0 +1,253 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DNSStageType +from .types import LbOriginError +from .types import ListBackendStagesRequestOrderBy +from .types import ListCacheStagesRequestOrderBy +from .types import ListDNSStagesRequestOrderBy +from .types import ListPipelinesRequestOrderBy +from .types import ListPipelinesWithStagesRequestOrderBy +from .types import ListPurgeRequestsRequestOrderBy +from .types import ListRouteStagesRequestOrderBy +from .types import ListTLSStagesRequestOrderBy +from .types import ListWafStagesRequestOrderBy +from .types import PipelineErrorCode +from .types import PipelineErrorSeverity +from .types import PipelineErrorStage +from .types import PipelineErrorType +from .types import PipelineStatus +from .content import PIPELINE_TRANSIENT_STATUSES +from .types import PlanName +from .types import PurgeRequestStatus +from .content import PURGE_REQUEST_TRANSIENT_STATUSES +from .types import RuleHttpMatchMethodFilter +from .types import RuleHttpMatchPathFilterPathFilterType +from .types import SearchBackendStagesRequestOrderBy +from .types import WafStageMode +from .types import ScalewayLb +from .types import RuleHttpMatchPathFilter +from .types import ScalewayLbBackendConfig +from .types import ScalewayS3BackendConfig +from .types import PipelineError +from .types import TLSSecret +from .types import RuleHttpMatch +from .types import BackendStage +from .types import CacheStage +from .types import DNSStage +from .types import Pipeline +from .types import RouteStage +from .types import TLSStage +from .types import WafStage +from .types import SetRouteRulesRequestRouteRule +from .types import RouteRule +from .types import CheckPEMChainRequestSecretChain +from .types import PlanDetails +from .types import PlanUsageDetails +from .types import HeadStageResponseHeadStage +from .types import ListHeadStagesResponseHeadStage +from .types import PipelineStages +from .types import PurgeRequest +from .types import SetHeadStageRequestAddNewHeadStage +from .types import SetHeadStageRequestRemoveHeadStage +from .types import SetHeadStageRequestSwapHeadStage +from .types import TLSSecretsConfig +from .types import AddRouteRulesRequest +from .types import AddRouteRulesResponse +from .types import CheckDomainRequest +from .types import CheckDomainResponse +from .types import CheckLbOriginRequest +from .types import CheckLbOriginResponse +from .types import CheckPEMChainRequest +from .types import CheckPEMChainResponse +from .types import CreateBackendStageRequest +from .types import CreateCacheStageRequest +from .types import CreateDNSStageRequest +from .types import CreatePipelineRequest +from .types import CreatePurgeRequestRequest +from .types import CreateRouteStageRequest +from .types import CreateTLSStageRequest +from .types import CreateWafStageRequest +from .types import DeleteBackendStageRequest +from .types import DeleteCacheStageRequest +from .types import DeleteCurrentPlanRequest +from .types import DeleteDNSStageRequest +from .types import DeletePipelineRequest +from .types import DeleteRouteStageRequest +from .types import DeleteTLSStageRequest +from .types import DeleteWafStageRequest +from .types import GetBackendStageRequest +from .types import GetBillingRequest +from .types import GetBillingResponse +from .types import GetCacheStageRequest +from .types import GetCurrentPlanRequest +from .types import GetDNSStageRequest +from .types import GetPipelineRequest +from .types import GetPurgeRequestRequest +from .types import GetRouteStageRequest +from .types import GetTLSStageRequest +from .types import GetWafStageRequest +from .types import HeadStageResponse +from .types import ListBackendStagesRequest +from .types import ListBackendStagesResponse +from .types import ListCacheStagesRequest +from .types import ListCacheStagesResponse +from .types import ListDNSStagesRequest +from .types import ListDNSStagesResponse +from .types import ListHeadStagesRequest +from .types import ListHeadStagesResponse +from .types import ListPipelinesRequest +from .types import ListPipelinesResponse +from .types import ListPipelinesWithStagesRequest +from .types import ListPipelinesWithStagesResponse +from .types import ListPlansResponse +from .types import ListPurgeRequestsRequest +from .types import ListPurgeRequestsResponse +from .types import ListRouteRulesRequest +from .types import ListRouteRulesResponse +from .types import ListRouteStagesRequest +from .types import ListRouteStagesResponse +from .types import ListTLSStagesRequest +from .types import ListTLSStagesResponse +from .types import ListWafStagesRequest +from .types import ListWafStagesResponse +from .types import Plan +from .types import SearchBackendStagesRequest +from .types import SelectPlanRequest +from .types import SetHeadStageRequest +from .types import SetRouteRulesRequest +from .types import SetRouteRulesResponse +from .types import UpdateBackendStageRequest +from .types import UpdateCacheStageRequest +from .types import UpdateDNSStageRequest +from .types import UpdatePipelineRequest +from .types import UpdateRouteStageRequest +from .types import UpdateTLSStageRequest +from .types import UpdateWafStageRequest +from .api import EdgeServicesV1Beta1API + +__all__ = [ + "DNSStageType", + "LbOriginError", + "ListBackendStagesRequestOrderBy", + "ListCacheStagesRequestOrderBy", + "ListDNSStagesRequestOrderBy", + "ListPipelinesRequestOrderBy", + "ListPipelinesWithStagesRequestOrderBy", + "ListPurgeRequestsRequestOrderBy", + "ListRouteStagesRequestOrderBy", + "ListTLSStagesRequestOrderBy", + "ListWafStagesRequestOrderBy", + "PipelineErrorCode", + "PipelineErrorSeverity", + "PipelineErrorStage", + "PipelineErrorType", + "PipelineStatus", + "PIPELINE_TRANSIENT_STATUSES", + "PlanName", + "PurgeRequestStatus", + "PURGE_REQUEST_TRANSIENT_STATUSES", + "RuleHttpMatchMethodFilter", + "RuleHttpMatchPathFilterPathFilterType", + "SearchBackendStagesRequestOrderBy", + "WafStageMode", + "ScalewayLb", + "RuleHttpMatchPathFilter", + "ScalewayLbBackendConfig", + "ScalewayS3BackendConfig", + "PipelineError", + "TLSSecret", + "RuleHttpMatch", + "BackendStage", + "CacheStage", + "DNSStage", + "Pipeline", + "RouteStage", + "TLSStage", + "WafStage", + "SetRouteRulesRequestRouteRule", + "RouteRule", + "CheckPEMChainRequestSecretChain", + "PlanDetails", + "PlanUsageDetails", + "HeadStageResponseHeadStage", + "ListHeadStagesResponseHeadStage", + "PipelineStages", + "PurgeRequest", + "SetHeadStageRequestAddNewHeadStage", + "SetHeadStageRequestRemoveHeadStage", + "SetHeadStageRequestSwapHeadStage", + "TLSSecretsConfig", + "AddRouteRulesRequest", + "AddRouteRulesResponse", + "CheckDomainRequest", + "CheckDomainResponse", + "CheckLbOriginRequest", + "CheckLbOriginResponse", + "CheckPEMChainRequest", + "CheckPEMChainResponse", + "CreateBackendStageRequest", + "CreateCacheStageRequest", + "CreateDNSStageRequest", + "CreatePipelineRequest", + "CreatePurgeRequestRequest", + "CreateRouteStageRequest", + "CreateTLSStageRequest", + "CreateWafStageRequest", + "DeleteBackendStageRequest", + "DeleteCacheStageRequest", + "DeleteCurrentPlanRequest", + "DeleteDNSStageRequest", + "DeletePipelineRequest", + "DeleteRouteStageRequest", + "DeleteTLSStageRequest", + "DeleteWafStageRequest", + "GetBackendStageRequest", + "GetBillingRequest", + "GetBillingResponse", + "GetCacheStageRequest", + "GetCurrentPlanRequest", + "GetDNSStageRequest", + "GetPipelineRequest", + "GetPurgeRequestRequest", + "GetRouteStageRequest", + "GetTLSStageRequest", + "GetWafStageRequest", + "HeadStageResponse", + "ListBackendStagesRequest", + "ListBackendStagesResponse", + "ListCacheStagesRequest", + "ListCacheStagesResponse", + "ListDNSStagesRequest", + "ListDNSStagesResponse", + "ListHeadStagesRequest", + "ListHeadStagesResponse", + "ListPipelinesRequest", + "ListPipelinesResponse", + "ListPipelinesWithStagesRequest", + "ListPipelinesWithStagesResponse", + "ListPlansResponse", + "ListPurgeRequestsRequest", + "ListPurgeRequestsResponse", + "ListRouteRulesRequest", + "ListRouteRulesResponse", + "ListRouteStagesRequest", + "ListRouteStagesResponse", + "ListTLSStagesRequest", + "ListTLSStagesResponse", + "ListWafStagesRequest", + "ListWafStagesResponse", + "Plan", + "SearchBackendStagesRequest", + "SelectPlanRequest", + "SetHeadStageRequest", + "SetRouteRulesRequest", + "SetRouteRulesResponse", + "UpdateBackendStageRequest", + "UpdateCacheStageRequest", + "UpdateDNSStageRequest", + "UpdatePipelineRequest", + "UpdateRouteStageRequest", + "UpdateTLSStageRequest", + "UpdateWafStageRequest", + "EdgeServicesV1Beta1API", +] diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/api.py b/scaleway-async/scaleway_async/edge_services/v1beta1/api.py new file mode 100644 index 000000000..045850ee2 --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/api.py @@ -0,0 +1,2614 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + ListBackendStagesRequestOrderBy, + ListCacheStagesRequestOrderBy, + ListDNSStagesRequestOrderBy, + ListPipelinesRequestOrderBy, + ListPipelinesWithStagesRequestOrderBy, + ListPurgeRequestsRequestOrderBy, + ListRouteStagesRequestOrderBy, + ListTLSStagesRequestOrderBy, + ListWafStagesRequestOrderBy, + PlanName, + SearchBackendStagesRequestOrderBy, + WafStageMode, + AddRouteRulesRequest, + AddRouteRulesResponse, + BackendStage, + CacheStage, + CheckDomainRequest, + CheckDomainResponse, + CheckLbOriginRequest, + CheckLbOriginResponse, + CheckPEMChainRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainResponse, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateRouteStageRequest, + CreateTLSStageRequest, + CreateWafStageRequest, + DNSStage, + GetBillingResponse, + HeadStageResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListHeadStagesResponse, + ListHeadStagesResponseHeadStage, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListRouteRulesResponse, + ListRouteStagesResponse, + ListTLSStagesResponse, + ListWafStagesResponse, + Pipeline, + PipelineStages, + Plan, + PurgeRequest, + RouteStage, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + SelectPlanRequest, + SetHeadStageRequest, + SetHeadStageRequestAddNewHeadStage, + SetHeadStageRequestRemoveHeadStage, + SetHeadStageRequestSwapHeadStage, + SetRouteRulesRequest, + SetRouteRulesRequestRouteRule, + SetRouteRulesResponse, + TLSSecret, + TLSSecretsConfig, + TLSStage, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateRouteStageRequest, + UpdateTLSStageRequest, + UpdateWafStageRequest, + WafStage, +) +from .content import ( + PIPELINE_TRANSIENT_STATUSES, + PURGE_REQUEST_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_BackendStage, + unmarshal_CacheStage, + unmarshal_DNSStage, + unmarshal_Pipeline, + unmarshal_RouteStage, + unmarshal_TLSStage, + unmarshal_WafStage, + unmarshal_PurgeRequest, + unmarshal_AddRouteRulesResponse, + unmarshal_CheckDomainResponse, + unmarshal_CheckLbOriginResponse, + unmarshal_CheckPEMChainResponse, + unmarshal_GetBillingResponse, + unmarshal_HeadStageResponse, + unmarshal_ListBackendStagesResponse, + unmarshal_ListCacheStagesResponse, + unmarshal_ListDNSStagesResponse, + unmarshal_ListHeadStagesResponse, + unmarshal_ListPipelinesResponse, + unmarshal_ListPipelinesWithStagesResponse, + unmarshal_ListPlansResponse, + unmarshal_ListPurgeRequestsResponse, + unmarshal_ListRouteRulesResponse, + unmarshal_ListRouteStagesResponse, + unmarshal_ListTLSStagesResponse, + unmarshal_ListWafStagesResponse, + unmarshal_Plan, + unmarshal_SetRouteRulesResponse, + marshal_AddRouteRulesRequest, + marshal_CheckDomainRequest, + marshal_CheckLbOriginRequest, + marshal_CheckPEMChainRequest, + marshal_CreateBackendStageRequest, + marshal_CreateCacheStageRequest, + marshal_CreateDNSStageRequest, + marshal_CreatePipelineRequest, + marshal_CreatePurgeRequestRequest, + marshal_CreateRouteStageRequest, + marshal_CreateTLSStageRequest, + marshal_CreateWafStageRequest, + marshal_SelectPlanRequest, + marshal_SetHeadStageRequest, + marshal_SetRouteRulesRequest, + marshal_UpdateBackendStageRequest, + marshal_UpdateCacheStageRequest, + marshal_UpdateDNSStageRequest, + marshal_UpdatePipelineRequest, + marshal_UpdateRouteStageRequest, + marshal_UpdateTLSStageRequest, + marshal_UpdateWafStageRequest, +) + + +class EdgeServicesV1Beta1API(API): + """ """ + + async def list_pipelines( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> ListPipelinesResponse: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for. Only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for. Only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for. Only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + :return: :class:`ListPipelinesResponse ` + + Usage: + :: + + result = await api.list_pipelines() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/pipelines", + params={ + "has_backend_stage_lb": has_backend_stage_lb, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesResponse(res.json()) + + async def list_pipelines_all( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> List[Pipeline]: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for. Only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for. Only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for. Only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + :return: :class:`List[Pipeline] ` + + Usage: + :: + + result = await api.list_pipelines_all() + """ + + return await fetch_all_pages_async( + type=ListPipelinesResponse, + key="pipelines", + fetcher=self.list_pipelines, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + "has_backend_stage_lb": has_backend_stage_lb, + }, + ) + + async def create_pipeline( + self, + *, + name: str, + description: str, + project_id: Optional[str] = None, + ) -> Pipeline: + """ + Create pipeline. + Create a new pipeline. You must specify a `dns_stage_id` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :param project_id: Project ID in which the pipeline will be created. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.create_pipeline( + name="example", + description="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/pipelines", + body=marshal_CreatePipelineRequest( + CreatePipelineRequest( + name=name, + description=description, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + async def get_pipeline( + self, + *, + pipeline_id: str, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.get_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + async def wait_for_pipeline( + self, + *, + pipeline_id: str, + options: Optional[ + WaitForOptions[Pipeline, Union[bool, Awaitable[bool]]] + ] = None, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.get_pipeline( + pipeline_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in PIPELINE_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_pipeline, + options=options, + args={ + "pipeline_id": pipeline_id, + }, + ) + + async def list_pipelines_with_stages( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> ListPipelinesWithStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`ListPipelinesWithStagesResponse ` + + Usage: + :: + + result = await api.list_pipelines_with_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/pipelines-stages", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesWithStagesResponse(res.json()) + + async def list_pipelines_with_stages_all( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> List[PipelineStages]: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`List[PipelineStages] ` + + Usage: + :: + + result = await api.list_pipelines_with_stages_all() + """ + + return await fetch_all_pages_async( + type=ListPipelinesWithStagesResponse, + key="pipelines", + fetcher=self.list_pipelines_with_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + }, + ) + + async def update_pipeline( + self, + *, + pipeline_id: str, + name: Optional[str] = None, + description: Optional[str] = None, + ) -> Pipeline: + """ + Update pipeline. + Update the parameters of an existing pipeline, specified by its `pipeline_id`. Parameters which can be updated include the `name`, `description` and `dns_stage_id`. + :param pipeline_id: ID of the pipeline to update. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.update_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + body=marshal_UpdatePipelineRequest( + UpdatePipelineRequest( + pipeline_id=pipeline_id, + name=name, + description=description, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + async def delete_pipeline( + self, + *, + pipeline_id: str, + ) -> None: + """ + Delete pipeline. + Delete an existing pipeline, specified by its `pipeline_id`. Deleting a pipeline is permanent, and cannot be undone. Note that all stages linked to the pipeline are also deleted. + :param pipeline_id: ID of the pipeline to delete. + + Usage: + :: + + result = await api.delete_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + + async def list_head_stages( + self, + *, + pipeline_id: str, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListHeadStagesResponse: + """ + :param pipeline_id: ID of the pipeline to update. + :param page: Page number to return, from the paginated results. + :param page_size: Number of head stages to return per page. + :return: :class:`ListHeadStagesResponse ` + + Usage: + :: + + result = await api.list_head_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/head-stages", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListHeadStagesResponse(res.json()) + + async def list_head_stages_all( + self, + *, + pipeline_id: str, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[ListHeadStagesResponseHeadStage]: + """ + :param pipeline_id: ID of the pipeline to update. + :param page: Page number to return, from the paginated results. + :param page_size: Number of head stages to return per page. + :return: :class:`List[ListHeadStagesResponseHeadStage] ` + + Usage: + :: + + result = await api.list_head_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListHeadStagesResponse, + key="head_stages", + fetcher=self.list_head_stages, + args={ + "pipeline_id": pipeline_id, + "page": page, + "page_size": page_size, + }, + ) + + async def set_head_stage( + self, + *, + pipeline_id: str, + add_new_head_stage: Optional[SetHeadStageRequestAddNewHeadStage] = None, + remove_head_stage: Optional[SetHeadStageRequestRemoveHeadStage] = None, + swap_head_stage: Optional[SetHeadStageRequestSwapHeadStage] = None, + ) -> HeadStageResponse: + """ + Configure a entry point to your pipeline. You must specify a `head stage` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + You must specify either a `add_new_head_stage` (to add a new head stage), `remove_head_stage` (to remove a head stage) or `swap_head_stage` (to replace a head stage). + :param pipeline_id: ID of the pipeline to update. + :param add_new_head_stage: Add a new head stage. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :param remove_head_stage: Remove a head stage. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :param swap_head_stage: Replace a head stage with a new one. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :return: :class:`HeadStageResponse ` + + Usage: + :: + + result = await api.set_head_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/set-head-stage", + body=marshal_SetHeadStageRequest( + SetHeadStageRequest( + pipeline_id=pipeline_id, + add_new_head_stage=add_new_head_stage, + remove_head_stage=remove_head_stage, + swap_head_stage=swap_head_stage, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_HeadStageResponse(res.json()) + + async def list_dns_stages( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + fqdn: Optional[str] = None, + ) -> ListDNSStagesResponse: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + :return: :class:`ListDNSStagesResponse ` + + Usage: + :: + + result = await api.list_dns_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/dns-stages", + params={ + "fqdn": fqdn, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDNSStagesResponse(res.json()) + + async def list_dns_stages_all( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + fqdn: Optional[str] = None, + ) -> List[DNSStage]: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + :return: :class:`List[DNSStage] ` + + Usage: + :: + + result = await api.list_dns_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListDNSStagesResponse, + key="stages", + fetcher=self.list_dns_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "fqdn": fqdn, + }, + ) + + async def create_dns_stage( + self, + *, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + ) -> DNSStage: + """ + Create DNS stage. + Create a new DNS stage. You must specify the `fqdns` field to customize the domain endpoint, using a domain you already own. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param pipeline_id: Pipeline ID the DNS stage belongs to. + :return: :class:`DNSStage ` + + Usage: + :: + + result = await api.create_dns_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/dns-stages", + body=marshal_CreateDNSStageRequest( + CreateDNSStageRequest( + fqdns=fqdns, + pipeline_id=pipeline_id, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + async def get_dns_stage( + self, + *, + dns_stage_id: str, + ) -> DNSStage: + """ + Get DNS stage. + Retrieve information about an existing DNS stage, specified by its `dns_stage_id`. Its full details, including FQDNs, are returned in the response object. + :param dns_stage_id: ID of the requested DNS stage. + :return: :class:`DNSStage ` + + Usage: + :: + + result = await api.get_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + async def update_dns_stage( + self, + *, + dns_stage_id: str, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> DNSStage: + """ + Update DNS stage. + Update the parameters of an existing DNS stage, specified by its `dns_stage_id`. + :param dns_stage_id: ID of the DNS stage to update. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`DNSStage ` + + Usage: + :: + + result = await api.update_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + body=marshal_UpdateDNSStageRequest( + UpdateDNSStageRequest( + dns_stage_id=dns_stage_id, + fqdns=fqdns, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + async def delete_dns_stage( + self, + *, + dns_stage_id: str, + ) -> None: + """ + Delete DNS stage. + Delete an existing DNS stage, specified by its `dns_stage_id`. Deleting a DNS stage is permanent, and cannot be undone. + :param dns_stage_id: ID of the DNS stage to delete. + + Usage: + :: + + result = await api.delete_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + + async def list_tls_stages( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> ListTLSStagesResponse: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + :param secret_id: Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + :return: :class:`ListTLSStagesResponse ` + + Usage: + :: + + result = await api.list_tls_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/tls-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTLSStagesResponse(res.json()) + + async def list_tls_stages_all( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> List[TLSStage]: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + :param secret_id: Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + :return: :class:`List[TLSStage] ` + + Usage: + :: + + result = await api.list_tls_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListTLSStagesResponse, + key="stages", + fetcher=self.list_tls_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + async def create_tls_stage( + self, + *, + secrets: Optional[List[TLSSecret]] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + route_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Create TLS stage. + Create a new TLS stage. You must specify either the `secrets` or `managed_certificate` fields to customize the SSL/TLS certificate of your endpoint. Choose `secrets` if you are using a pre-existing certificate held in Scaleway Secret Manager, or `managed_certificate` to let Scaleway generate and manage a Let's Encrypt certificate for your customized endpoint. + :param secrets: Secret (from Scaleway Secret Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param pipeline_id: Pipeline ID the TLS stage belongs to. + :param route_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = await api.create_tls_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/tls-stages", + body=marshal_CreateTLSStageRequest( + CreateTLSStageRequest( + secrets=secrets, + managed_certificate=managed_certificate, + pipeline_id=pipeline_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + async def get_tls_stage( + self, + *, + tls_stage_id: str, + ) -> TLSStage: + """ + Get TLS stage. + Retrieve information about an existing TLS stage, specified by its `tls_stage_id`. Its full details, including secrets and certificate expiration date are returned in the response object. + :param tls_stage_id: ID of the requested TLS stage. + :return: :class:`TLSStage ` + + Usage: + :: + + result = await api.get_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + async def update_tls_stage( + self, + *, + tls_stage_id: str, + tls_secrets_config: Optional[TLSSecretsConfig] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Update TLS stage. + Update the parameters of an existing TLS stage, specified by its `tls_stage_id`. Both `tls_secrets_config` and `managed_certificate` parameters can be updated. + :param tls_stage_id: ID of the TLS stage to update. + :param tls_secrets_config: Secret (from Scaleway Secret-Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = await api.update_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + body=marshal_UpdateTLSStageRequest( + UpdateTLSStageRequest( + tls_stage_id=tls_stage_id, + tls_secrets_config=tls_secrets_config, + managed_certificate=managed_certificate, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + async def delete_tls_stage( + self, + *, + tls_stage_id: str, + ) -> None: + """ + Delete TLS stage. + Delete an existing TLS stage, specified by its `tls_stage_id`. Deleting a TLS stage is permanent, and cannot be undone. + :param tls_stage_id: ID of the TLS stage to delete. + + Usage: + :: + + result = await api.delete_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + + async def list_cache_stages( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListCacheStagesResponse: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + :return: :class:`ListCacheStagesResponse ` + + Usage: + :: + + result = await api.list_cache_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/cache-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListCacheStagesResponse(res.json()) + + async def list_cache_stages_all( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[CacheStage]: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + :return: :class:`List[CacheStage] ` + + Usage: + :: + + result = await api.list_cache_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListCacheStagesResponse, + key="stages", + fetcher=self.list_cache_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + async def create_cache_stage( + self, + *, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + waf_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Create cache stage. + Create a new cache stage. You must specify the `fallback_ttl` field to customize the TTL of the cache. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param pipeline_id: Pipeline ID the Cache stage belongs to. + :param waf_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = await api.create_cache_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/cache-stages", + body=marshal_CreateCacheStageRequest( + CreateCacheStageRequest( + fallback_ttl=fallback_ttl, + pipeline_id=pipeline_id, + backend_stage_id=backend_stage_id, + waf_stage_id=waf_stage_id, + route_stage_id=route_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + async def get_cache_stage( + self, + *, + cache_stage_id: str, + ) -> CacheStage: + """ + Get cache stage. + Retrieve information about an existing cache stage, specified by its `cache_stage_id`. Its full details, including Time To Live (TTL), are returned in the response object. + :param cache_stage_id: ID of the requested cache stage. + :return: :class:`CacheStage ` + + Usage: + :: + + result = await api.get_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + async def update_cache_stage( + self, + *, + cache_stage_id: str, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Update cache stage. + Update the parameters of an existing cache stage, specified by its `cache_stage_id`. Parameters which can be updated include the `fallback_ttl` and `backend_stage_id`. + :param cache_stage_id: ID of the cache stage to update. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = await api.update_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + body=marshal_UpdateCacheStageRequest( + UpdateCacheStageRequest( + cache_stage_id=cache_stage_id, + fallback_ttl=fallback_ttl, + backend_stage_id=backend_stage_id, + waf_stage_id=waf_stage_id, + route_stage_id=route_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + async def delete_cache_stage( + self, + *, + cache_stage_id: str, + ) -> None: + """ + Delete cache stage. + Delete an existing cache stage, specified by its `cache_stage_id`. Deleting a cache stage is permanent, and cannot be undone. + :param cache_stage_id: ID of the cache stage to delete. + + Usage: + :: + + result = await api.delete_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + + async def list_backend_stages( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + :param bucket_name: Bucket name to filter for. Only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for. Only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = await api.list_backend_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + async def list_backend_stages_all( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> List[BackendStage]: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + :param bucket_name: Bucket name to filter for. Only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for. Only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + :return: :class:`List[BackendStage] ` + + Usage: + :: + + result = await api.list_backend_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListBackendStagesResponse, + key="stages", + fetcher=self.list_backend_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + }, + ) + + async def create_backend_stage( + self, + *, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + pipeline_id: str, + ) -> BackendStage: + """ + Create backend stage. + Create a new backend stage. You must specify either a `scaleway_s3` (for a Scaleway Object Storage bucket) or `scaleway_lb` (for a Scaleway Load Balancer) field to configure the origin. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param pipeline_id: Pipeline ID the Backend stage belongs to. + :return: :class:`BackendStage ` + + Usage: + :: + + result = await api.create_backend_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/backend-stages", + body=marshal_CreateBackendStageRequest( + CreateBackendStageRequest( + pipeline_id=pipeline_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + async def get_backend_stage( + self, + *, + backend_stage_id: str, + ) -> BackendStage: + """ + Get backend stage. + Retrieve information about an existing backend stage, specified by its `backend_stage_id`. Its full details, including `scaleway_s3` or `scaleway_lb`, are returned in the response object. + :param backend_stage_id: ID of the requested backend stage. + :return: :class:`BackendStage ` + + Usage: + :: + + result = await api.get_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + async def update_backend_stage( + self, + *, + backend_stage_id: str, + pipeline_id: str, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + ) -> BackendStage: + """ + Update backend stage. + Update the parameters of an existing backend stage, specified by its `backend_stage_id`. + :param backend_stage_id: ID of the backend stage to update. + :param pipeline_id: Pipeline ID the Backend stage belongs to. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :return: :class:`BackendStage ` + + Usage: + :: + + result = await api.update_backend_stage( + backend_stage_id="example", + pipeline_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + body=marshal_UpdateBackendStageRequest( + UpdateBackendStageRequest( + backend_stage_id=backend_stage_id, + pipeline_id=pipeline_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + async def delete_backend_stage( + self, + *, + backend_stage_id: str, + ) -> None: + """ + Delete backend stage. + Delete an existing backend stage, specified by its `backend_stage_id`. Deleting a backend stage is permanent, and cannot be undone. + :param backend_stage_id: ID of the backend stage to delete. + + Usage: + :: + + result = await api.delete_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + + async def list_waf_stages( + self, + *, + order_by: Optional[ListWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListWafStagesResponse: + """ + List WAF stages. + List all WAF stages, for a Scaleway Organization or Scaleway Project. By default, the WAF stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of WAF stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of WAF stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + :return: :class:`ListWafStagesResponse ` + + Usage: + :: + + result = await api.list_waf_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/waf-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWafStagesResponse(res.json()) + + async def list_waf_stages_all( + self, + *, + order_by: Optional[ListWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[WafStage]: + """ + List WAF stages. + List all WAF stages, for a Scaleway Organization or Scaleway Project. By default, the WAF stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of WAF stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of WAF stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + :return: :class:`List[WafStage] ` + + Usage: + :: + + result = await api.list_waf_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListWafStagesResponse, + key="stages", + fetcher=self.list_waf_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + async def create_waf_stage( + self, + *, + pipeline_id: str, + paranoia_level: int, + mode: Optional[WafStageMode] = None, + backend_stage_id: Optional[str] = None, + ) -> WafStage: + """ + Create WAF stage. + Create a new WAF stage. You must specify the `mode` and `paranoia_level` fields to customize the WAF. + :param pipeline_id: Pipeline ID the WAF stage belongs to. + :param paranoia_level: Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + :param mode: Mode defining WAF behavior (`disable`/`log_only`/`enable`). + :param backend_stage_id: ID of the backend stage to forward requests to after the WAF stage. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`WafStage ` + + Usage: + :: + + result = await api.create_waf_stage( + pipeline_id="example", + paranoia_level=1, + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/waf-stages", + body=marshal_CreateWafStageRequest( + CreateWafStageRequest( + pipeline_id=pipeline_id, + paranoia_level=paranoia_level, + mode=mode, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + async def get_waf_stage( + self, + *, + waf_stage_id: str, + ) -> WafStage: + """ + Get WAF stage. + Retrieve information about an existing WAF stage, specified by its `waf_stage_id`. Its full details are returned in the response object. + :param waf_stage_id: ID of the requested WAF stage. + :return: :class:`WafStage ` + + Usage: + :: + + result = await api.get_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + async def update_waf_stage( + self, + *, + waf_stage_id: str, + mode: Optional[WafStageMode] = None, + paranoia_level: Optional[int] = None, + backend_stage_id: Optional[str] = None, + ) -> WafStage: + """ + Update WAF stage. + Update the parameters of an existing WAF stage, specified by its `waf_stage_id`. Both `mode` and `paranoia_level` parameters can be updated. + :param waf_stage_id: ID of the WAF stage to update. + :param mode: Mode defining WAF behavior (`disable`/`log_only`/`enable`). + :param paranoia_level: Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + :param backend_stage_id: ID of the backend stage to forward requests to after the WAF stage. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`WafStage ` + + Usage: + :: + + result = await api.update_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + body=marshal_UpdateWafStageRequest( + UpdateWafStageRequest( + waf_stage_id=waf_stage_id, + mode=mode, + paranoia_level=paranoia_level, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + async def delete_waf_stage( + self, + *, + waf_stage_id: str, + ) -> None: + """ + Delete WAF stage. + Delete an existing WAF stage, specified by its `waf_stage_id`. Deleting a WAF stage is permanent, and cannot be undone. + :param waf_stage_id: ID of the WAF stage to delete. + + Usage: + :: + + result = await api.delete_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + ) + + self._throw_on_error(res) + + async def list_route_stages( + self, + *, + order_by: Optional[ListRouteStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListRouteStagesResponse: + """ + List route stages. + List all route stages, for a given pipeline. By default, the route stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of route stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of route stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only route stages from this pipeline will be returned. + :return: :class:`ListRouteStagesResponse ` + + Usage: + :: + + result = await api.list_route_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/route-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRouteStagesResponse(res.json()) + + async def list_route_stages_all( + self, + *, + order_by: Optional[ListRouteStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[RouteStage]: + """ + List route stages. + List all route stages, for a given pipeline. By default, the route stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of route stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of route stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only route stages from this pipeline will be returned. + :return: :class:`List[RouteStage] ` + + Usage: + :: + + result = await api.list_route_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListRouteStagesResponse, + key="stages", + fetcher=self.list_route_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + async def create_route_stage( + self, + *, + pipeline_id: str, + waf_stage_id: Optional[str] = None, + ) -> RouteStage: + """ + Create route stage. + Create a new route stage. You must specify the `waf_stage_id` field to customize the route. + :param pipeline_id: Pipeline ID the route stage belongs to. + :param waf_stage_id: ID of the WAF stage HTTP requests should be forwarded to when no rules are matched. + One-Of ('next'): at most one of 'waf_stage_id' could be set. + :return: :class:`RouteStage ` + + Usage: + :: + + result = await api.create_route_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/route-stages", + body=marshal_CreateRouteStageRequest( + CreateRouteStageRequest( + pipeline_id=pipeline_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + async def get_route_stage( + self, + *, + route_stage_id: str, + ) -> RouteStage: + """ + Get route stage. + Retrieve information about an existing route stage, specified by its `route_stage_id`. The summary of the route stage (without route rules) is returned in the response object. + :param route_stage_id: ID of the requested route stage. + :return: :class:`RouteStage ` + + Usage: + :: + + result = await api.get_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + async def update_route_stage( + self, + *, + route_stage_id: str, + waf_stage_id: Optional[str] = None, + ) -> RouteStage: + """ + Update route stage. + Update the parameters of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param waf_stage_id: ID of the WAF stage HTTP requests should be forwarded to when no rules are matched. + One-Of ('next'): at most one of 'waf_stage_id' could be set. + :return: :class:`RouteStage ` + + Usage: + :: + + result = await api.update_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + body=marshal_UpdateRouteStageRequest( + UpdateRouteStageRequest( + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + async def delete_route_stage( + self, + *, + route_stage_id: str, + ) -> None: + """ + Delete route stage. + Delete an existing route stage, specified by its `route_stage_id`. Deleting a route stage is permanent, and cannot be undone. + :param route_stage_id: ID of the route stage to delete. + + Usage: + :: + + result = await api.delete_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + ) + + self._throw_on_error(res) + + async def list_route_rules( + self, + *, + route_stage_id: str, + ) -> ListRouteRulesResponse: + """ + List route rules. + List all route rules of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: Route stage ID to filter for. Only route rules from this route stage will be returned. + :return: :class:`ListRouteRulesResponse ` + + Usage: + :: + + result = await api.list_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/{param_route_stage_id}/route-rules", + ) + + self._throw_on_error(res) + return unmarshal_ListRouteRulesResponse(res.json()) + + async def set_route_rules( + self, + *, + route_stage_id: str, + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] = None, + ) -> SetRouteRulesResponse: + """ + Set route rules. + Set the rules of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param route_rules: List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + :return: :class:`SetRouteRulesResponse ` + + Usage: + :: + + result = await api.set_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "PUT", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + body=marshal_SetRouteRulesRequest( + SetRouteRulesRequest( + route_stage_id=route_stage_id, + route_rules=route_rules, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetRouteRulesResponse(res.json()) + + async def add_route_rules( + self, + *, + route_stage_id: str, + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] = None, + after_position: Optional[int] = None, + before_position: Optional[int] = None, + ) -> AddRouteRulesResponse: + """ + Add route rules. + Add route rules to an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param route_rules: List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + :param after_position: Add rules after the given position. + One-Of ('position'): at most one of 'after_position', 'before_position' could be set. + :param before_position: Add rules before the given position. + One-Of ('position'): at most one of 'after_position', 'before_position' could be set. + :return: :class:`AddRouteRulesResponse ` + + Usage: + :: + + result = await api.add_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + body=marshal_AddRouteRulesRequest( + AddRouteRulesRequest( + route_stage_id=route_stage_id, + route_rules=route_rules, + after_position=after_position, + before_position=before_position, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AddRouteRulesResponse(res.json()) + + async def check_domain( + self, + *, + fqdn: str, + cname: str, + project_id: Optional[str] = None, + ) -> CheckDomainResponse: + """ + :param fqdn: + :param cname: + :param project_id: + :return: :class:`CheckDomainResponse ` + + Usage: + :: + + result = await api.check_domain( + fqdn="example", + cname="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-domain", + body=marshal_CheckDomainRequest( + CheckDomainRequest( + fqdn=fqdn, + cname=cname, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckDomainResponse(res.json()) + + async def check_pem_chain( + self, + *, + fqdn: str, + project_id: Optional[str] = None, + secret: Optional[CheckPEMChainRequestSecretChain] = None, + raw: Optional[str] = None, + ) -> CheckPEMChainResponse: + """ + :param fqdn: + :param project_id: + :param secret: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :param raw: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :return: :class:`CheckPEMChainResponse ` + + Usage: + :: + + result = await api.check_pem_chain( + fqdn="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-pem-chain", + body=marshal_CheckPEMChainRequest( + CheckPEMChainRequest( + fqdn=fqdn, + project_id=project_id, + secret=secret, + raw=raw, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckPEMChainResponse(res.json()) + + async def search_backend_stages( + self, + *, + order_by: Optional[SearchBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param project_id: + :param bucket_name: + :param bucket_region: + :param lb_id: + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = await api.search_backend_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/search-backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + async def list_purge_requests( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> ListPurgeRequestsResponse: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for. Only purge requests from this Project will be returned. + :param project_id: Project ID to filter for. Only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + :return: :class:`ListPurgeRequestsResponse ` + + Usage: + :: + + result = await api.list_purge_requests() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/purge-requests", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPurgeRequestsResponse(res.json()) + + async def list_purge_requests_all( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> List[PurgeRequest]: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for. Only purge requests from this Project will be returned. + :param project_id: Project ID to filter for. Only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + :return: :class:`List[PurgeRequest] ` + + Usage: + :: + + result = await api.list_purge_requests_all() + """ + + return await fetch_all_pages_async( + type=ListPurgeRequestsResponse, + key="purge_requests", + fetcher=self.list_purge_requests, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "pipeline_id": pipeline_id, + }, + ) + + async def create_purge_request( + self, + *, + pipeline_id: str, + assets: Optional[List[str]] = None, + all: Optional[bool] = None, + ) -> PurgeRequest: + """ + Create purge request. + Create a new purge request. You must specify either the `all` field (to purge all content) or a list of `assets` (to define the precise assets to purge). + :param pipeline_id: Pipeline ID in which the purge request will be created. + :param assets: List of asserts to purge. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :param all: Defines whether to purge all content. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = await api.create_purge_request( + pipeline_id="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/purge-requests", + body=marshal_CreatePurgeRequestRequest( + CreatePurgeRequestRequest( + pipeline_id=pipeline_id, + assets=assets, + all=all, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + async def get_purge_request( + self, + *, + purge_request_id: str, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = await api.get_purge_request( + purge_request_id="example", + ) + """ + + param_purge_request_id = validate_path_param( + "purge_request_id", purge_request_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/purge-requests/{param_purge_request_id}", + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + async def wait_for_purge_request( + self, + *, + purge_request_id: str, + options: Optional[ + WaitForOptions[PurgeRequest, Union[bool, Awaitable[bool]]] + ] = None, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = await api.get_purge_request( + purge_request_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in PURGE_REQUEST_TRANSIENT_STATUSES + ) + + return await wait_for_resource_async( + fetcher=self.get_purge_request, + options=options, + args={ + "purge_request_id": purge_request_id, + }, + ) + + async def check_lb_origin( + self, + *, + lb: Optional[ScalewayLb] = None, + ) -> CheckLbOriginResponse: + """ + :param lb: + :return: :class:`CheckLbOriginResponse ` + + Usage: + :: + + result = await api.check_lb_origin() + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-lb-origin", + body=marshal_CheckLbOriginRequest( + CheckLbOriginRequest( + lb=lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckLbOriginResponse(res.json()) + + async def list_plans( + self, + ) -> ListPlansResponse: + """ + + :return: :class:`ListPlansResponse ` + + Usage: + :: + + result = await api.list_plans() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/plans", + ) + + self._throw_on_error(res) + return unmarshal_ListPlansResponse(res.json()) + + async def select_plan( + self, + *, + project_id: Optional[str] = None, + plan_name: Optional[PlanName] = None, + ) -> Plan: + """ + :param project_id: + :param plan_name: + :return: :class:`Plan ` + + Usage: + :: + + result = await api.select_plan() + """ + + res = self._request( + "PATCH", + "/edge-services/v1beta1/current-plan", + body=marshal_SelectPlanRequest( + SelectPlanRequest( + project_id=project_id, + plan_name=plan_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + async def get_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> Plan: + """ + :param project_id: + :return: :class:`Plan ` + + Usage: + :: + + result = await api.get_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + async def delete_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> None: + """ + :param project_id: + + Usage: + :: + + result = await api.delete_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + + async def get_billing( + self, + *, + project_id: Optional[str] = None, + ) -> GetBillingResponse: + """ + Gives information on the currently selected Edge Services subscription plan, resource usage and associated billing information for this calendar month (including whether consumption falls within or exceeds the currently selected subscription plan.). + :param project_id: + :return: :class:`GetBillingResponse ` + + Usage: + :: + + result = await api.get_billing() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/billing/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_GetBillingResponse(res.json()) diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/content.py b/scaleway-async/scaleway_async/edge_services/v1beta1/content.py new file mode 100644 index 000000000..ad1b5e0e6 --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/content.py @@ -0,0 +1,21 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + PipelineStatus, + PurgeRequestStatus, +) + +PIPELINE_TRANSIENT_STATUSES: List[PipelineStatus] = [ + PipelineStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PipelineStatus `. +""" +PURGE_REQUEST_TRANSIENT_STATUSES: List[PurgeRequestStatus] = [ + PurgeRequestStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PurgeRequestStatus `. +""" diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/marshalling.py b/scaleway-async/scaleway_async/edge_services/v1beta1/marshalling.py new file mode 100644 index 000000000..b01c7d7cf --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/marshalling.py @@ -0,0 +1,1901 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + RuleHttpMatchMethodFilter, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + BackendStage, + CacheStage, + DNSStage, + PipelineError, + Pipeline, + RouteStage, + TLSSecret, + TLSStage, + WafStage, + PipelineStages, + PurgeRequest, + RuleHttpMatchPathFilter, + RuleHttpMatch, + RouteRule, + AddRouteRulesResponse, + CheckDomainResponse, + CheckLbOriginResponse, + CheckPEMChainResponse, + PlanDetails, + PlanUsageDetails, + GetBillingResponse, + HeadStageResponseHeadStage, + HeadStageResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListHeadStagesResponseHeadStage, + ListHeadStagesResponse, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListRouteRulesResponse, + ListRouteStagesResponse, + ListTLSStagesResponse, + ListWafStagesResponse, + Plan, + SetRouteRulesResponse, + SetRouteRulesRequestRouteRule, + AddRouteRulesRequest, + CheckDomainRequest, + CheckLbOriginRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainRequest, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateRouteStageRequest, + CreateTLSStageRequest, + CreateWafStageRequest, + SelectPlanRequest, + SetHeadStageRequestAddNewHeadStage, + SetHeadStageRequestRemoveHeadStage, + SetHeadStageRequestSwapHeadStage, + SetHeadStageRequest, + SetRouteRulesRequest, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateRouteStageRequest, + TLSSecretsConfig, + UpdateTLSStageRequest, + UpdateWafStageRequest, +) + + +def unmarshal_ScalewayLb(data: Any) -> ScalewayLb: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLb' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("frontend_id", None) + if field is not None: + args["frontend_id"] = field + + field = data.get("is_ssl", None) + if field is not None: + args["is_ssl"] = field + else: + args["is_ssl"] = None + + field = data.get("domain_name", None) + if field is not None: + args["domain_name"] = field + else: + args["domain_name"] = None + + return ScalewayLb(**args) + + +def unmarshal_ScalewayLbBackendConfig(data: Any) -> ScalewayLbBackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLbBackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("lbs", None) + if field is not None: + args["lbs"] = ( + [unmarshal_ScalewayLb(v) for v in field] if field is not None else None + ) + + return ScalewayLbBackendConfig(**args) + + +def unmarshal_ScalewayS3BackendConfig(data: Any) -> ScalewayS3BackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayS3BackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bucket_name", None) + if field is not None: + args["bucket_name"] = field + else: + args["bucket_name"] = None + + field = data.get("bucket_region", None) + if field is not None: + args["bucket_region"] = field + else: + args["bucket_region"] = None + + field = data.get("is_website", None) + if field is not None: + args["is_website"] = field + else: + args["is_website"] = None + + return ScalewayS3BackendConfig(**args) + + +def unmarshal_BackendStage(data: Any) -> BackendStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BackendStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("scaleway_s3", None) + if field is not None: + args["scaleway_s3"] = unmarshal_ScalewayS3BackendConfig(field) + else: + args["scaleway_s3"] = None + + field = data.get("scaleway_lb", None) + if field is not None: + args["scaleway_lb"] = unmarshal_ScalewayLbBackendConfig(field) + else: + args["scaleway_lb"] = None + + return BackendStage(**args) + + +def unmarshal_CacheStage(data: Any) -> CacheStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CacheStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("fallback_ttl", None) + if field is not None: + args["fallback_ttl"] = field + else: + args["fallback_ttl"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + else: + args["route_stage_id"] = None + + return CacheStage(**args) + + +def unmarshal_DNSStage(data: Any) -> DNSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DNSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("fqdns", None) + if field is not None: + args["fqdns"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("tls_stage_id", None) + if field is not None: + args["tls_stage_id"] = field + else: + args["tls_stage_id"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return DNSStage(**args) + + +def unmarshal_PipelineError(data: Any) -> PipelineError: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineError' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stage", None) + if field is not None: + args["stage"] = field + + field = data.get("code", None) + if field is not None: + args["code"] = field + + field = data.get("severity", None) + if field is not None: + args["severity"] = field + + field = data.get("message", None) + if field is not None: + args["message"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PipelineError(**args) + + +def unmarshal_Pipeline(data: Any) -> Pipeline: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pipeline' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("errors", None) + if field is not None: + args["errors"] = ( + [unmarshal_PipelineError(v) for v in field] if field is not None else None + ) + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Pipeline(**args) + + +def unmarshal_RouteStage(data: Any) -> RouteStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RouteStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return RouteStage(**args) + + +def unmarshal_TLSSecret(data: Any) -> TLSSecret: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSSecret' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret_id", None) + if field is not None: + args["secret_id"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + return TLSSecret(**args) + + +def unmarshal_TLSStage(data: Any) -> TLSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_TLSSecret(v) for v in field] if field is not None else None + ) + + field = data.get("managed_certificate", None) + if field is not None: + args["managed_certificate"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("certificate_expires_at", None) + if field is not None: + args["certificate_expires_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["certificate_expires_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + else: + args["route_stage_id"] = None + + return TLSStage(**args) + + +def unmarshal_WafStage(data: Any) -> WafStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'WafStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("mode", None) + if field is not None: + args["mode"] = field + + field = data.get("paranoia_level", None) + if field is not None: + args["paranoia_level"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return WafStage(**args) + + +def unmarshal_PipelineStages(data: Any) -> PipelineStages: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineStages' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stages", None) + if field is not None: + args["dns_stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("tls_stages", None) + if field is not None: + args["tls_stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("cache_stages", None) + if field is not None: + args["cache_stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("backend_stages", None) + if field is not None: + args["backend_stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("waf_stages", None) + if field is not None: + args["waf_stages"] = ( + [unmarshal_WafStage(v) for v in field] if field is not None else None + ) + + field = data.get("route_stages", None) + if field is not None: + args["route_stages"] = ( + [unmarshal_RouteStage(v) for v in field] if field is not None else None + ) + + field = data.get("pipeline", None) + if field is not None: + args["pipeline"] = unmarshal_Pipeline(field) + else: + args["pipeline"] = None + + return PipelineStages(**args) + + +def unmarshal_PurgeRequest(data: Any) -> PurgeRequest: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PurgeRequest' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("assets", None) + if field is not None: + args["assets"] = field + else: + args["assets"] = None + + field = data.get("all", None) + if field is not None: + args["all"] = field + else: + args["all"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return PurgeRequest(**args) + + +def unmarshal_RuleHttpMatchPathFilter(data: Any) -> RuleHttpMatchPathFilter: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RuleHttpMatchPathFilter' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path_filter_type", None) + if field is not None: + args["path_filter_type"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + return RuleHttpMatchPathFilter(**args) + + +def unmarshal_RuleHttpMatch(data: Any) -> RuleHttpMatch: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RuleHttpMatch' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("method_filters", None) + if field is not None: + args["method_filters"] = ( + [RuleHttpMatchMethodFilter(v) for v in field] if field is not None else None + ) + + field = data.get("path_filter", None) + if field is not None: + args["path_filter"] = unmarshal_RuleHttpMatchPathFilter(field) + else: + args["path_filter"] = None + + return RuleHttpMatch(**args) + + +def unmarshal_RouteRule(data: Any) -> RouteRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RouteRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("position", None) + if field is not None: + args["position"] = field + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + + field = data.get("rule_http_match", None) + if field is not None: + args["rule_http_match"] = unmarshal_RuleHttpMatch(field) + else: + args["rule_http_match"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return RouteRule(**args) + + +def unmarshal_AddRouteRulesResponse(data: Any) -> AddRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AddRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return AddRouteRulesResponse(**args) + + +def unmarshal_CheckDomainResponse(data: Any) -> CheckDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckDomainResponse(**args) + + +def unmarshal_CheckLbOriginResponse(data: Any) -> CheckLbOriginResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckLbOriginResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + field = data.get("error_type", None) + if field is not None: + args["error_type"] = field + + return CheckLbOriginResponse(**args) + + +def unmarshal_CheckPEMChainResponse(data: Any) -> CheckPEMChainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckPEMChainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckPEMChainResponse(**args) + + +def unmarshal_PlanDetails(data: Any) -> PlanDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + field = data.get("package_gb", None) + if field is not None: + args["package_gb"] = field + + field = data.get("pipeline_limit", None) + if field is not None: + args["pipeline_limit"] = field + + field = data.get("waf_requests", None) + if field is not None: + args["waf_requests"] = field + + return PlanDetails(**args) + + +def unmarshal_PlanUsageDetails(data: Any) -> PlanUsageDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanUsageDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + return PlanUsageDetails(**args) + + +def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetBillingResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("current_plan", None) + if field is not None: + args["current_plan"] = unmarshal_PlanDetails(field) + else: + args["current_plan"] = None + + field = data.get("pipeline_number", None) + if field is not None: + args["pipeline_number"] = field + + field = data.get("current_plan_cache_usage", None) + if field is not None: + args["current_plan_cache_usage"] = field + + field = data.get("extra_cache_usage", None) + if field is not None: + args["extra_cache_usage"] = field + + field = data.get("current_plan_waf_usage", None) + if field is not None: + args["current_plan_waf_usage"] = field + + field = data.get("extra_waf_usage", None) + if field is not None: + args["extra_waf_usage"] = field + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + field = data.get("extra_pipelines_cost", None) + if field is not None: + args["extra_pipelines_cost"] = unmarshal_Money(field) + else: + args["extra_pipelines_cost"] = None + + field = data.get("plans_usage_details", None) + if field is not None: + args["plans_usage_details"] = ( + {key: unmarshal_PlanUsageDetails(value) for key, value in field.items()} + if field is not None + else None + ) + + field = data.get("extra_cache_cost", None) + if field is not None: + args["extra_cache_cost"] = unmarshal_Money(field) + else: + args["extra_cache_cost"] = None + + field = data.get("extra_waf_cost", None) + if field is not None: + args["extra_waf_cost"] = unmarshal_Money(field) + else: + args["extra_waf_cost"] = None + + field = data.get("waf_add_on", None) + if field is not None: + args["waf_add_on"] = unmarshal_Money(field) + else: + args["waf_add_on"] = None + + field = data.get("total_cost", None) + if field is not None: + args["total_cost"] = unmarshal_Money(field) + else: + args["total_cost"] = None + + return GetBillingResponse(**args) + + +def unmarshal_HeadStageResponseHeadStage(data: Any) -> HeadStageResponseHeadStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HeadStageResponseHeadStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return HeadStageResponseHeadStage(**args) + + +def unmarshal_HeadStageResponse(data: Any) -> HeadStageResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HeadStageResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("head_stage", None) + if field is not None: + args["head_stage"] = unmarshal_HeadStageResponseHeadStage(field) + else: + args["head_stage"] = None + + return HeadStageResponse(**args) + + +def unmarshal_ListBackendStagesResponse(data: Any) -> ListBackendStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListBackendStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListBackendStagesResponse(**args) + + +def unmarshal_ListCacheStagesResponse(data: Any) -> ListCacheStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListCacheStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListCacheStagesResponse(**args) + + +def unmarshal_ListDNSStagesResponse(data: Any) -> ListDNSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDNSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDNSStagesResponse(**args) + + +def unmarshal_ListHeadStagesResponseHeadStage( + data: Any, +) -> ListHeadStagesResponseHeadStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHeadStagesResponseHeadStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return ListHeadStagesResponseHeadStage(**args) + + +def unmarshal_ListHeadStagesResponse(data: Any) -> ListHeadStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHeadStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("head_stages", None) + if field is not None: + args["head_stages"] = ( + [unmarshal_ListHeadStagesResponseHeadStage(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListHeadStagesResponse(**args) + + +def unmarshal_ListPipelinesResponse(data: Any) -> ListPipelinesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_Pipeline(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesResponse(**args) + + +def unmarshal_ListPipelinesWithStagesResponse( + data: Any, +) -> ListPipelinesWithStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesWithStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_PipelineStages(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesWithStagesResponse(**args) + + +def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPlansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("plans", None) + if field is not None: + args["plans"] = ( + [unmarshal_PlanDetails(v) for v in field] if field is not None else None + ) + + return ListPlansResponse(**args) + + +def unmarshal_ListPurgeRequestsResponse(data: Any) -> ListPurgeRequestsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPurgeRequestsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("purge_requests", None) + if field is not None: + args["purge_requests"] = ( + [unmarshal_PurgeRequest(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPurgeRequestsResponse(**args) + + +def unmarshal_ListRouteRulesResponse(data: Any) -> ListRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return ListRouteRulesResponse(**args) + + +def unmarshal_ListRouteStagesResponse(data: Any) -> ListRouteStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRouteStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_RouteStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListRouteStagesResponse(**args) + + +def unmarshal_ListTLSStagesResponse(data: Any) -> ListTLSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTLSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListTLSStagesResponse(**args) + + +def unmarshal_ListWafStagesResponse(data: Any) -> ListWafStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWafStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_WafStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListWafStagesResponse(**args) + + +def unmarshal_Plan(data: Any) -> Plan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Plan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + return Plan(**args) + + +def unmarshal_SetRouteRulesResponse(data: Any) -> SetRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return SetRouteRulesResponse(**args) + + +def marshal_RuleHttpMatchPathFilter( + request: RuleHttpMatchPathFilter, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.path_filter_type is not None: + output["path_filter_type"] = str(request.path_filter_type) + + if request.value is not None: + output["value"] = request.value + + return output + + +def marshal_RuleHttpMatch( + request: RuleHttpMatch, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.method_filters is not None: + output["method_filters"] = [str(item) for item in request.method_filters] + + if request.path_filter is not None: + output["path_filter"] = marshal_RuleHttpMatchPathFilter( + request.path_filter, defaults + ) + + return output + + +def marshal_SetRouteRulesRequestRouteRule( + request: SetRouteRulesRequestRouteRule, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("rule_http_match", request.rule_http_match), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + return output + + +def marshal_AddRouteRulesRequest( + request: AddRouteRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("after_position", request.after_position), + OneOfPossibility("before_position", request.before_position), + ] + ), + ) + + if request.route_rules is not None: + output["route_rules"] = [ + marshal_SetRouteRulesRequestRouteRule(item, defaults) + for item in request.route_rules + ] + + return output + + +def marshal_CheckDomainRequest( + request: CheckDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.cname is not None: + output["cname"] = request.cname + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLb( + request: ScalewayLb, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.zone is not None: + output["zone"] = request.zone or defaults.default_zone + + if request.frontend_id is not None: + output["frontend_id"] = request.frontend_id + + if request.is_ssl is not None: + output["is_ssl"] = request.is_ssl + + if request.domain_name is not None: + output["domain_name"] = request.domain_name + + return output + + +def marshal_CheckLbOriginRequest( + request: CheckLbOriginRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lb is not None: + output["lb"] = marshal_ScalewayLb(request.lb, defaults) + + return output + + +def marshal_CheckPEMChainRequestSecretChain( + request: CheckPEMChainRequestSecretChain, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.secret_region is not None: + output["secret_region"] = request.secret_region + + return output + + +def marshal_CheckPEMChainRequest( + request: CheckPEMChainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + OneOfPossibility("raw", request.raw), + ] + ), + ) + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLbBackendConfig( + request: ScalewayLbBackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lbs is not None: + output["lbs"] = [marshal_ScalewayLb(item, defaults) for item in request.lbs] + + return output + + +def marshal_ScalewayS3BackendConfig( + request: ScalewayS3BackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket_name is not None: + output["bucket_name"] = request.bucket_name + + if request.bucket_region is not None: + output["bucket_region"] = request.bucket_region + + if request.is_website is not None: + output["is_website"] = request.is_website + + return output + + +def marshal_CreateBackendStageRequest( + request: CreateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + return output + + +def marshal_CreateCacheStageRequest( + request: CreateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_CreateDNSStageRequest( + request: CreateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_CreatePipelineRequest( + request: CreatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreatePurgeRequestRequest( + request: CreatePurgeRequestRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("assets", request.assets), + OneOfPossibility("all", request.all), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_CreateRouteStageRequest( + request: CreateRouteStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + return output + + +def marshal_TLSSecret( + request: TLSSecret, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.region is not None: + output["region"] = request.region or defaults.default_region + + return output + + +def marshal_CreateTLSStageRequest( + request: CreateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + if request.secrets is not None: + output["secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.secrets + ] + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_CreateWafStageRequest( + request: CreateWafStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.paranoia_level is not None: + output["paranoia_level"] = request.paranoia_level + + if request.mode is not None: + output["mode"] = str(request.mode) + + return output + + +def marshal_SelectPlanRequest( + request: SelectPlanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.plan_name is not None: + output["plan_name"] = str(request.plan_name) + + return output + + +def marshal_SetHeadStageRequestAddNewHeadStage( + request: SetHeadStageRequestAddNewHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.new_stage_id is not None: + output["new_stage_id"] = request.new_stage_id + + return output + + +def marshal_SetHeadStageRequestRemoveHeadStage( + request: SetHeadStageRequestRemoveHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.remove_stage_id is not None: + output["remove_stage_id"] = request.remove_stage_id + + return output + + +def marshal_SetHeadStageRequestSwapHeadStage( + request: SetHeadStageRequestSwapHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.new_stage_id is not None: + output["new_stage_id"] = request.new_stage_id + + if request.current_stage_id is not None: + output["current_stage_id"] = request.current_stage_id + + return output + + +def marshal_SetHeadStageRequest( + request: SetHeadStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("add_new_head_stage", request.add_new_head_stage), + OneOfPossibility("remove_head_stage", request.remove_head_stage), + OneOfPossibility("swap_head_stage", request.swap_head_stage), + ] + ), + ) + + return output + + +def marshal_SetRouteRulesRequest( + request: SetRouteRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.route_rules is not None: + output["route_rules"] = [ + marshal_SetRouteRulesRequestRouteRule(item, defaults) + for item in request.route_rules + ] + + return output + + +def marshal_UpdateBackendStageRequest( + request: UpdateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_UpdateCacheStageRequest( + request: UpdateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_UpdateDNSStageRequest( + request: UpdateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_UpdatePipelineRequest( + request: UpdatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_UpdateRouteStageRequest( + request: UpdateRouteStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + return output + + +def marshal_TLSSecretsConfig( + request: TLSSecretsConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tls_secrets is not None: + output["tls_secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.tls_secrets + ] + + return output + + +def marshal_UpdateTLSStageRequest( + request: UpdateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + if request.tls_secrets_config is not None: + output["tls_secrets_config"] = marshal_TLSSecretsConfig( + request.tls_secrets_config, defaults + ) + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_UpdateWafStageRequest( + request: UpdateWafStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.mode is not None: + output["mode"] = str(request.mode) + + if request.paranoia_level is not None: + output["paranoia_level"] = request.paranoia_level + + return output diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/types.py b/scaleway-async/scaleway_async/edge_services/v1beta1/types.py new file mode 100644 index 000000000..424d86ece --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/types.py @@ -0,0 +1,1780 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DNSStageType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + AUTO = "auto" + MANAGED = "managed" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class LbOriginError(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + TIMEOUT = "timeout" + CONNECTION_REFUSED = "connection_refused" + TLS_ERROR = "tls_error" + + def __str__(self) -> str: + return str(self.value) + + +class ListBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListCacheStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListDNSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesWithStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPurgeRequestsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRouteStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListTLSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListWafStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorCode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_CODE = "unknown_code" + DNS_INVALID_FORMAT = "dns_invalid_format" + DNS_INVALID_TLD = "dns_invalid_tld" + DNS_FORBIDDEN_ROOT_DOMAIN = "dns_forbidden_root_domain" + DNS_FORBIDDEN_SCW_CLOUD = "dns_forbidden_scw_cloud" + DNS_DOMAIN_DONT_EXIST = "dns_domain_dont_exist" + DNS_CNAME_DONT_EXIST = "dns_cname_dont_exist" + DNS_CNAME_RESOLVE = "dns_cname_resolve" + DNS_FQDN_ALREADY_EXISTS = "dns_fqdn_already_exists" + DNS_FQDN_ALREADY_IN_USE = "dns_fqdn_already_in_use" + TLS_CERT_DELETED = "tls_cert_deleted" + TLS_CERT_DISABLED = "tls_cert_disabled" + TLS_CERT_EXPIRED = "tls_cert_expired" + TLS_CERT_INVALID_FORMAT = "tls_cert_invalid_format" + TLS_CERT_MISSING = "tls_cert_missing" + TLS_CHAIN_ORDER = "tls_chain_order" + TLS_KEY_INVALID_FORMAT = "tls_key_invalid_format" + TLS_KEY_MISSING = "tls_key_missing" + TLS_KEY_TOO_MANY = "tls_key_too_many" + TLS_MANAGED_DOMAIN_RATE_LIMIT = "tls_managed_domain_rate_limit" + TLS_MANAGED_INTERNAL = "tls_managed_internal" + TLS_PAIR_MISMATCH = "tls_pair_mismatch" + TLS_ROOT_INCONSISTENT = "tls_root_inconsistent" + TLS_ROOT_INCORRECT = "tls_root_incorrect" + TLS_ROOT_MISSING = "tls_root_missing" + TLS_SAN_MISMATCH = "tls_san_mismatch" + TLS_SELF_SIGNED = "tls_self_signed" + PIPELINE_INVALID_WORKFLOW = "pipeline_invalid_workflow" + PIPELINE_MISSING_HEAD_STAGE = "pipeline_missing_head_stage" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorSeverity(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SEVERITY = "unknown_severity" + WARNING = "warning" + CRITICAL = "critical" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorStage(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STAGE = "unknown_stage" + DNS = "dns" + TLS = "tls" + CACHE = "cache" + BACKEND = "backend" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + RUNTIME = "runtime" + CONFIG = "config" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + ERROR = "error" + PENDING = "pending" + WARNING = "warning" + + def __str__(self) -> str: + return str(self.value) + + +class PlanName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + STARTER = "starter" + PROFESSIONAL = "professional" + ADVANCED = "advanced" + + def __str__(self) -> str: + return str(self.value) + + +class PurgeRequestStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DONE = "done" + ERROR = "error" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) + + +class RuleHttpMatchMethodFilter(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_METHOD_FILTER = "unknown_method_filter" + GET = "get" + POST = "post" + PUT = "put" + PATCH = "patch" + DELETE = "delete" + HEAD = "head" + OPTIONS = "options" + + def __str__(self) -> str: + return str(self.value) + + +class RuleHttpMatchPathFilterPathFilterType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PATH_FILTER = "unknown_path_filter" + REGEX = "regex" + + def __str__(self) -> str: + return str(self.value) + + +class SearchBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class WafStageMode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_MODE = "unknown_mode" + DISABLE = "disable" + LOG_ONLY = "log_only" + ENABLE = "enable" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ScalewayLb: + id: str + """ + ID of the Load Balancer. + """ + + zone: ScwZone + """ + Zone of the Load Balancer. + """ + + frontend_id: str + """ + ID of the frontend linked to the Load Balancer. + """ + + is_ssl: Optional[bool] + """ + Defines whether the Load Balancer's frontend handles SSL connections. + """ + + domain_name: Optional[str] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to use in HTTP requests sent towards your Load Balancer. + """ + + +@dataclass +class RuleHttpMatchPathFilter: + path_filter_type: RuleHttpMatchPathFilterPathFilterType + """ + Type of filter to match for the HTTP URL path. For now, all path filters must be written in regex and use the `regex` type. + """ + + value: str + """ + Value to be matched for the HTTP URL path. + """ + + +@dataclass +class ScalewayLbBackendConfig: + lbs: List[ScalewayLb] + """ + Load Balancer information. + """ + + +@dataclass +class ScalewayS3BackendConfig: + bucket_name: Optional[str] + """ + Name of the Bucket. + """ + + bucket_region: Optional[str] + """ + Region of the Bucket. + """ + + is_website: Optional[bool] + """ + Defines whether the bucket website feature is enabled. + """ + + +@dataclass +class PipelineError: + stage: PipelineErrorStage + + code: PipelineErrorCode + + severity: PipelineErrorSeverity + + message: str + + type_: PipelineErrorType + + +@dataclass +class TLSSecret: + secret_id: str + """ + ID of the Secret. + """ + + region: ScwRegion + """ + Region of the Secret. + """ + + +@dataclass +class RuleHttpMatch: + method_filters: List[RuleHttpMatchMethodFilter] + """ + HTTP methods to filter for. A request using any of these methods will be considered to match the rule. Possible values are `get`, `post`, `put`, `patch`, `delete`, `head`, `options`. All methods will match if none is provided. + """ + + path_filter: Optional[RuleHttpMatchPathFilter] + """ + HTTP URL path to filter for. A request whose path matches the given filter will be considered to match the rule. All paths will match if none is provided. + """ + + +@dataclass +class BackendStage: + id: str + """ + ID of the backend stage. + """ + + pipeline_id: str + """ + Pipeline ID the backend stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the backend stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the backend stage was last updated. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CacheStage: + id: str + """ + ID of the cache stage. + """ + + pipeline_id: str + """ + Pipeline ID the cache stage belongs to. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + created_at: Optional[datetime] + """ + Date the cache stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the cache stage was last updated. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class DNSStage: + id: str + """ + ID of the DNS stage. + """ + + fqdns: List[str] + """ + List of Fully Qualified Domain Names attached to the stage. + """ + + type_: DNSStageType + """ + Type of the stage. + """ + + pipeline_id: str + """ + Pipeline ID the DNS stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the DNS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the DNS stage was last updated. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class Pipeline: + id: str + """ + ID of the pipeline. + """ + + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + status: PipelineStatus + """ + Status of the pipeline. + """ + + errors: List[PipelineError] + """ + Errors of the pipeline. + """ + + project_id: str + """ + Project ID of the pipeline. + """ + + organization_id: str + """ + Organization ID of the pipeline. + """ + + created_at: Optional[datetime] + """ + Date the pipeline was created. + """ + + updated_at: Optional[datetime] + """ + Date the pipeline was last updated. + """ + + +@dataclass +class RouteStage: + id: str + """ + ID of the route stage. + """ + + pipeline_id: str + """ + Pipeline ID the route stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the route stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the route stage was last updated. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class TLSStage: + id: str + """ + ID of the TLS stage. + """ + + secrets: List[TLSSecret] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: bool + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + pipeline_id: str + """ + Pipeline ID the TLS stage belongs to. + """ + + certificate_expires_at: Optional[datetime] + """ + Expiration date of the certificate. + """ + + created_at: Optional[datetime] + """ + Date the TLS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the TLS stage was last updated. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class WafStage: + id: str + """ + ID of the WAF stage. + """ + + pipeline_id: str + """ + Pipeline ID the WAF stage belongs to. + """ + + mode: WafStageMode + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + paranoia_level: int + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + created_at: Optional[datetime] + """ + Date the WAF stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the WAF stage was last updated. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class SetRouteRulesRequestRouteRule: + rule_http_match: Optional[RuleHttpMatch] + + backend_stage_id: Optional[str] + + +@dataclass +class RouteRule: + position: int + """ + Position of the rule which determines the order of processing within the route stage. + """ + + route_stage_id: str + """ + Route stage ID the route rule belongs to. + """ + + rule_http_match: Optional[RuleHttpMatch] + + backend_stage_id: Optional[str] + + +@dataclass +class CheckPEMChainRequestSecretChain: + secret_id: str + + secret_region: str + + +@dataclass +class PlanDetails: + plan_name: PlanName + """ + Subscription plan name. + """ + + package_gb: int + """ + Amount of egress data from cache included in subscription plan. + """ + + pipeline_limit: int + """ + Number of pipelines included in subscription plan. + """ + + waf_requests: int + """ + Number of WAF requests included in subscription plan. + """ + + +@dataclass +class PlanUsageDetails: + plan_cost: Optional[Money] + """ + Cost to date (this month) for the corresponding Edge Services subscription plan. + """ + + +@dataclass +class HeadStageResponseHeadStage: + dns_stage_id: Optional[str] + + +@dataclass +class ListHeadStagesResponseHeadStage: + dns_stage_id: Optional[str] + + +@dataclass +class PipelineStages: + dns_stages: List[DNSStage] + + tls_stages: List[TLSStage] + + cache_stages: List[CacheStage] + + backend_stages: List[BackendStage] + + waf_stages: List[WafStage] + + route_stages: List[RouteStage] + + pipeline: Optional[Pipeline] + + +@dataclass +class PurgeRequest: + id: str + """ + ID of the purge request. + """ + + pipeline_id: str + """ + Pipeline ID the purge request belongs to. + """ + + status: PurgeRequestStatus + """ + Status of the purge request. + """ + + created_at: Optional[datetime] + """ + Date the purge request was created. + """ + + updated_at: Optional[datetime] + """ + Date the purge request was last updated. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class SetHeadStageRequestAddNewHeadStage: + new_stage_id: str + + +@dataclass +class SetHeadStageRequestRemoveHeadStage: + remove_stage_id: str + + +@dataclass +class SetHeadStageRequestSwapHeadStage: + new_stage_id: str + + current_stage_id: str + + +@dataclass +class TLSSecretsConfig: + tls_secrets: List[TLSSecret] + """ + Secret information (from Secret Manager). + """ + + +@dataclass +class AddRouteRulesRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + after_position: Optional[int] + + before_position: Optional[int] + + +@dataclass +class AddRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class CheckDomainRequest: + fqdn: str + + cname: str + + project_id: Optional[str] + + +@dataclass +class CheckDomainResponse: + is_valid: bool + + +@dataclass +class CheckLbOriginRequest: + lb: Optional[ScalewayLb] + + +@dataclass +class CheckLbOriginResponse: + is_valid: bool + + error_type: LbOriginError + + +@dataclass +class CheckPEMChainRequest: + fqdn: str + + project_id: Optional[str] + + secret: Optional[CheckPEMChainRequestSecretChain] + + raw: Optional[str] + + +@dataclass +class CheckPEMChainResponse: + is_valid: bool + + +@dataclass +class CreateBackendStageRequest: + pipeline_id: str + """ + Pipeline ID the Backend stage belongs to. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CreateCacheStageRequest: + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + pipeline_id: str + """ + Pipeline ID the Cache stage belongs to. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class CreateDNSStageRequest: + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + """ + + pipeline_id: str + """ + Pipeline ID the DNS stage belongs to. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class CreatePipelineRequest: + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + project_id: Optional[str] + """ + Project ID in which the pipeline will be created. + """ + + +@dataclass +class CreatePurgeRequestRequest: + pipeline_id: str + """ + Pipeline ID in which the purge request will be created. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class CreateRouteStageRequest: + pipeline_id: str + """ + Pipeline ID the route stage belongs to. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class CreateTLSStageRequest: + secrets: Optional[List[TLSSecret]] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + pipeline_id: str + """ + Pipeline ID the TLS stage belongs to. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + route_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + +@dataclass +class CreateWafStageRequest: + pipeline_id: str + """ + Pipeline ID the WAF stage belongs to. + """ + + paranoia_level: int + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + mode: Optional[WafStageMode] + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + backend_stage_id: Optional[str] + + +@dataclass +class DeleteBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to delete. + """ + + +@dataclass +class DeleteCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to delete. + """ + + +@dataclass +class DeleteCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class DeleteDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to delete. + """ + + +@dataclass +class DeletePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to delete. + """ + + +@dataclass +class DeleteRouteStageRequest: + route_stage_id: str + """ + ID of the route stage to delete. + """ + + +@dataclass +class DeleteTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to delete. + """ + + +@dataclass +class DeleteWafStageRequest: + waf_stage_id: str + """ + ID of the WAF stage to delete. + """ + + +@dataclass +class GetBackendStageRequest: + backend_stage_id: str + """ + ID of the requested backend stage. + """ + + +@dataclass +class GetBillingRequest: + project_id: Optional[str] + + +@dataclass +class GetBillingResponse: + current_plan: Optional[PlanDetails] + """ + Information on the currently-selected, active Edge Services subscription plan. + """ + + pipeline_number: int + """ + Total number of pipelines currently configured. + """ + + current_plan_cache_usage: int + """ + Total amount of data egressed from the cache in gigabytes from the beginning of the month, for the active subscription plan. + """ + + extra_cache_usage: int + """ + Total amount of extra data egressed from cache in gigabytes from the beginning of the month, not included in the subscription plans. + """ + + current_plan_waf_usage: int + """ + Total number of requests processed by the WAF since the beginning of the current month, for the active subscription plan. + """ + + extra_waf_usage: int + """ + Total number of extra requests processed by the WAF from the beginning of the month, not included in the subscription plans. + """ + + plan_cost: Optional[Money] + """ + Cost to date (this month) for Edge Service subscription plans. This comprises the pro-rata cost of the current subscription plan, and any previous subscription plans that were active earlier in the month. + """ + + extra_pipelines_cost: Optional[Money] + """ + Cost to date (this month) of pipelines not included in the subscription plans. + """ + + plans_usage_details: Dict[str, PlanUsageDetails] + """ + Detailed costs and usage for all Edge Services subscription plans that were activated during the month. + """ + + extra_cache_cost: Optional[Money] + """ + Cost to date (this month) of the data egressed from the cache that is not included in the subscription plans. + """ + + extra_waf_cost: Optional[Money] + """ + Cost to date (this month) of the extra requests processed by the WAF that were not included in the subscription plans. + """ + + waf_add_on: Optional[Money] + """ + Cost of activating WAF add-on (where subscription plan does not include WAF). + """ + + total_cost: Optional[Money] + """ + Total cost to date (this month) of all Edge Services resources including active subscription plan, previously active plans, extra pipelines and extra egress cache data. + """ + + +@dataclass +class GetCacheStageRequest: + cache_stage_id: str + """ + ID of the requested cache stage. + """ + + +@dataclass +class GetCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class GetDNSStageRequest: + dns_stage_id: str + """ + ID of the requested DNS stage. + """ + + +@dataclass +class GetPipelineRequest: + pipeline_id: str + """ + ID of the requested pipeline. + """ + + +@dataclass +class GetPurgeRequestRequest: + purge_request_id: str + """ + ID of the requested purge request. + """ + + +@dataclass +class GetRouteStageRequest: + route_stage_id: str + """ + ID of the requested route stage. + """ + + +@dataclass +class GetTLSStageRequest: + tls_stage_id: str + """ + ID of the requested TLS stage. + """ + + +@dataclass +class GetWafStageRequest: + waf_stage_id: str + """ + ID of the requested WAF stage. + """ + + +@dataclass +class HeadStageResponse: + head_stage: Optional[HeadStageResponseHeadStage] + """ + Modified or created head stage. + """ + + +@dataclass +class ListBackendStagesRequest: + order_by: Optional[ListBackendStagesRequestOrderBy] + """ + Sort order of backend stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of backend stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + """ + + bucket_name: Optional[str] + """ + Bucket name to filter for. Only backend stages from this Bucket will be returned. + """ + + bucket_region: Optional[str] + """ + Bucket region to filter for. Only backend stages with buckets in this region will be returned. + """ + + lb_id: Optional[str] + """ + Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + """ + + +@dataclass +class ListBackendStagesResponse: + stages: List[BackendStage] + """ + Paginated list of backend stages. + """ + + total_count: int + """ + Count of all backend stages matching the requested criteria. + """ + + +@dataclass +class ListCacheStagesRequest: + order_by: Optional[ListCacheStagesRequestOrderBy] + """ + Sort order of cache stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of cache stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + """ + + +@dataclass +class ListCacheStagesResponse: + stages: List[CacheStage] + """ + Paginated list of cache stages. + """ + + total_count: int + """ + Count of all cache stages matching the requested criteria. + """ + + +@dataclass +class ListDNSStagesRequest: + order_by: Optional[ListDNSStagesRequestOrderBy] + """ + Sort order of DNS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of DNS stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + """ + + fqdn: Optional[str] + """ + Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + """ + + +@dataclass +class ListDNSStagesResponse: + stages: List[DNSStage] + """ + Paginated list of DNS stages. + """ + + total_count: int + """ + Count of all DNS stages matching the requested criteria. + """ + + +@dataclass +class ListHeadStagesRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of head stages to return per page. + """ + + +@dataclass +class ListHeadStagesResponse: + head_stages: List[ListHeadStagesResponseHeadStage] + """ + Number of head stages to return per page. + """ + + total_count: int + """ + Count of all head stages matching the requested pipeline_id. + """ + + +@dataclass +class ListPipelinesRequest: + order_by: Optional[ListPipelinesRequestOrderBy] + """ + Sort order of pipelines in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of pipelines to return per page. + """ + + name: Optional[str] + """ + Pipeline name to filter for. Only pipelines with this string within their name will be returned. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only pipelines from this Organization will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only pipelines from this Project will be returned. + """ + + has_backend_stage_lb: Optional[bool] + """ + Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + """ + + +@dataclass +class ListPipelinesResponse: + pipelines: List[Pipeline] + """ + Paginated list of pipelines. + """ + + total_count: int + """ + Count of all pipelines matching the requested criteria. + """ + + +@dataclass +class ListPipelinesWithStagesRequest: + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + name: Optional[str] + + organization_id: Optional[str] + + project_id: Optional[str] + + +@dataclass +class ListPipelinesWithStagesResponse: + pipelines: List[PipelineStages] + + total_count: int + + +@dataclass +class ListPlansResponse: + total_count: int + + plans: List[PlanDetails] + + +@dataclass +class ListPurgeRequestsRequest: + order_by: Optional[ListPurgeRequestsRequestOrderBy] + """ + Sort order of purge requests in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of purge requests to return per page. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only purge requests from this Project will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only purge requests from this Project will be returned. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + """ + + +@dataclass +class ListPurgeRequestsResponse: + purge_requests: List[PurgeRequest] + """ + Paginated list of purge requests. + """ + + total_count: int + """ + Count of all purge requests matching the requested criteria. + """ + + +@dataclass +class ListRouteRulesRequest: + route_stage_id: str + """ + Route stage ID to filter for. Only route rules from this route stage will be returned. + """ + + +@dataclass +class ListRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class ListRouteStagesRequest: + order_by: Optional[ListRouteStagesRequestOrderBy] + """ + Sort order of route stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of route stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only route stages from this pipeline will be returned. + """ + + +@dataclass +class ListRouteStagesResponse: + stages: List[RouteStage] + """ + Paginated list of summarized route stages. + """ + + total_count: int + """ + Count of all route stages matching the requested criteria. + """ + + +@dataclass +class ListTLSStagesRequest: + order_by: Optional[ListTLSStagesRequestOrderBy] + """ + Sort order of TLS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of TLS stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + """ + + secret_id: Optional[str] + """ + Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + """ + + secret_region: Optional[str] + """ + Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + """ + + +@dataclass +class ListTLSStagesResponse: + stages: List[TLSStage] + """ + Paginated list of TLS stages. + """ + + total_count: int + """ + Count of all TLS stages matching the requested criteria. + """ + + +@dataclass +class ListWafStagesRequest: + order_by: Optional[ListWafStagesRequestOrderBy] + """ + Sort order of WAF stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of WAF stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + """ + + +@dataclass +class ListWafStagesResponse: + stages: List[WafStage] + """ + Paginated list of WAF stages. + """ + + total_count: int + """ + Count of all WAF stages matching the requested criteria. + """ + + +@dataclass +class Plan: + plan_name: PlanName + + +@dataclass +class SearchBackendStagesRequest: + order_by: Optional[SearchBackendStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + project_id: Optional[str] + + bucket_name: Optional[str] + + bucket_region: Optional[str] + + lb_id: Optional[str] + + +@dataclass +class SelectPlanRequest: + project_id: Optional[str] + + plan_name: Optional[PlanName] + + +@dataclass +class SetHeadStageRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + add_new_head_stage: Optional[SetHeadStageRequestAddNewHeadStage] + + remove_head_stage: Optional[SetHeadStageRequestRemoveHeadStage] + + swap_head_stage: Optional[SetHeadStageRequestSwapHeadStage] + + +@dataclass +class SetRouteRulesRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class SetRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class UpdateBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to update. + """ + + pipeline_id: str + """ + Pipeline ID the Backend stage belongs to. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class UpdateCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to update. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class UpdateDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to update. + """ + + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class UpdatePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + name: Optional[str] + """ + Name of the pipeline. + """ + + description: Optional[str] + """ + Description of the pipeline. + """ + + +@dataclass +class UpdateRouteStageRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class UpdateTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to update. + """ + + tls_secrets_config: Optional[TLSSecretsConfig] + """ + Secret (from Scaleway Secret-Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + route_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + +@dataclass +class UpdateWafStageRequest: + waf_stage_id: str + """ + ID of the WAF stage to update. + """ + + mode: Optional[WafStageMode] + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + paranoia_level: Optional[int] + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + backend_stage_id: Optional[str] diff --git a/scaleway/scaleway/edge_services/v1beta1/__init__.py b/scaleway/scaleway/edge_services/v1beta1/__init__.py new file mode 100644 index 000000000..88bf53a51 --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/__init__.py @@ -0,0 +1,253 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DNSStageType +from .types import LbOriginError +from .types import ListBackendStagesRequestOrderBy +from .types import ListCacheStagesRequestOrderBy +from .types import ListDNSStagesRequestOrderBy +from .types import ListPipelinesRequestOrderBy +from .types import ListPipelinesWithStagesRequestOrderBy +from .types import ListPurgeRequestsRequestOrderBy +from .types import ListRouteStagesRequestOrderBy +from .types import ListTLSStagesRequestOrderBy +from .types import ListWafStagesRequestOrderBy +from .types import PipelineErrorCode +from .types import PipelineErrorSeverity +from .types import PipelineErrorStage +from .types import PipelineErrorType +from .types import PipelineStatus +from .content import PIPELINE_TRANSIENT_STATUSES +from .types import PlanName +from .types import PurgeRequestStatus +from .content import PURGE_REQUEST_TRANSIENT_STATUSES +from .types import RuleHttpMatchMethodFilter +from .types import RuleHttpMatchPathFilterPathFilterType +from .types import SearchBackendStagesRequestOrderBy +from .types import WafStageMode +from .types import ScalewayLb +from .types import RuleHttpMatchPathFilter +from .types import ScalewayLbBackendConfig +from .types import ScalewayS3BackendConfig +from .types import PipelineError +from .types import TLSSecret +from .types import RuleHttpMatch +from .types import BackendStage +from .types import CacheStage +from .types import DNSStage +from .types import Pipeline +from .types import RouteStage +from .types import TLSStage +from .types import WafStage +from .types import SetRouteRulesRequestRouteRule +from .types import RouteRule +from .types import CheckPEMChainRequestSecretChain +from .types import PlanDetails +from .types import PlanUsageDetails +from .types import HeadStageResponseHeadStage +from .types import ListHeadStagesResponseHeadStage +from .types import PipelineStages +from .types import PurgeRequest +from .types import SetHeadStageRequestAddNewHeadStage +from .types import SetHeadStageRequestRemoveHeadStage +from .types import SetHeadStageRequestSwapHeadStage +from .types import TLSSecretsConfig +from .types import AddRouteRulesRequest +from .types import AddRouteRulesResponse +from .types import CheckDomainRequest +from .types import CheckDomainResponse +from .types import CheckLbOriginRequest +from .types import CheckLbOriginResponse +from .types import CheckPEMChainRequest +from .types import CheckPEMChainResponse +from .types import CreateBackendStageRequest +from .types import CreateCacheStageRequest +from .types import CreateDNSStageRequest +from .types import CreatePipelineRequest +from .types import CreatePurgeRequestRequest +from .types import CreateRouteStageRequest +from .types import CreateTLSStageRequest +from .types import CreateWafStageRequest +from .types import DeleteBackendStageRequest +from .types import DeleteCacheStageRequest +from .types import DeleteCurrentPlanRequest +from .types import DeleteDNSStageRequest +from .types import DeletePipelineRequest +from .types import DeleteRouteStageRequest +from .types import DeleteTLSStageRequest +from .types import DeleteWafStageRequest +from .types import GetBackendStageRequest +from .types import GetBillingRequest +from .types import GetBillingResponse +from .types import GetCacheStageRequest +from .types import GetCurrentPlanRequest +from .types import GetDNSStageRequest +from .types import GetPipelineRequest +from .types import GetPurgeRequestRequest +from .types import GetRouteStageRequest +from .types import GetTLSStageRequest +from .types import GetWafStageRequest +from .types import HeadStageResponse +from .types import ListBackendStagesRequest +from .types import ListBackendStagesResponse +from .types import ListCacheStagesRequest +from .types import ListCacheStagesResponse +from .types import ListDNSStagesRequest +from .types import ListDNSStagesResponse +from .types import ListHeadStagesRequest +from .types import ListHeadStagesResponse +from .types import ListPipelinesRequest +from .types import ListPipelinesResponse +from .types import ListPipelinesWithStagesRequest +from .types import ListPipelinesWithStagesResponse +from .types import ListPlansResponse +from .types import ListPurgeRequestsRequest +from .types import ListPurgeRequestsResponse +from .types import ListRouteRulesRequest +from .types import ListRouteRulesResponse +from .types import ListRouteStagesRequest +from .types import ListRouteStagesResponse +from .types import ListTLSStagesRequest +from .types import ListTLSStagesResponse +from .types import ListWafStagesRequest +from .types import ListWafStagesResponse +from .types import Plan +from .types import SearchBackendStagesRequest +from .types import SelectPlanRequest +from .types import SetHeadStageRequest +from .types import SetRouteRulesRequest +from .types import SetRouteRulesResponse +from .types import UpdateBackendStageRequest +from .types import UpdateCacheStageRequest +from .types import UpdateDNSStageRequest +from .types import UpdatePipelineRequest +from .types import UpdateRouteStageRequest +from .types import UpdateTLSStageRequest +from .types import UpdateWafStageRequest +from .api import EdgeServicesV1Beta1API + +__all__ = [ + "DNSStageType", + "LbOriginError", + "ListBackendStagesRequestOrderBy", + "ListCacheStagesRequestOrderBy", + "ListDNSStagesRequestOrderBy", + "ListPipelinesRequestOrderBy", + "ListPipelinesWithStagesRequestOrderBy", + "ListPurgeRequestsRequestOrderBy", + "ListRouteStagesRequestOrderBy", + "ListTLSStagesRequestOrderBy", + "ListWafStagesRequestOrderBy", + "PipelineErrorCode", + "PipelineErrorSeverity", + "PipelineErrorStage", + "PipelineErrorType", + "PipelineStatus", + "PIPELINE_TRANSIENT_STATUSES", + "PlanName", + "PurgeRequestStatus", + "PURGE_REQUEST_TRANSIENT_STATUSES", + "RuleHttpMatchMethodFilter", + "RuleHttpMatchPathFilterPathFilterType", + "SearchBackendStagesRequestOrderBy", + "WafStageMode", + "ScalewayLb", + "RuleHttpMatchPathFilter", + "ScalewayLbBackendConfig", + "ScalewayS3BackendConfig", + "PipelineError", + "TLSSecret", + "RuleHttpMatch", + "BackendStage", + "CacheStage", + "DNSStage", + "Pipeline", + "RouteStage", + "TLSStage", + "WafStage", + "SetRouteRulesRequestRouteRule", + "RouteRule", + "CheckPEMChainRequestSecretChain", + "PlanDetails", + "PlanUsageDetails", + "HeadStageResponseHeadStage", + "ListHeadStagesResponseHeadStage", + "PipelineStages", + "PurgeRequest", + "SetHeadStageRequestAddNewHeadStage", + "SetHeadStageRequestRemoveHeadStage", + "SetHeadStageRequestSwapHeadStage", + "TLSSecretsConfig", + "AddRouteRulesRequest", + "AddRouteRulesResponse", + "CheckDomainRequest", + "CheckDomainResponse", + "CheckLbOriginRequest", + "CheckLbOriginResponse", + "CheckPEMChainRequest", + "CheckPEMChainResponse", + "CreateBackendStageRequest", + "CreateCacheStageRequest", + "CreateDNSStageRequest", + "CreatePipelineRequest", + "CreatePurgeRequestRequest", + "CreateRouteStageRequest", + "CreateTLSStageRequest", + "CreateWafStageRequest", + "DeleteBackendStageRequest", + "DeleteCacheStageRequest", + "DeleteCurrentPlanRequest", + "DeleteDNSStageRequest", + "DeletePipelineRequest", + "DeleteRouteStageRequest", + "DeleteTLSStageRequest", + "DeleteWafStageRequest", + "GetBackendStageRequest", + "GetBillingRequest", + "GetBillingResponse", + "GetCacheStageRequest", + "GetCurrentPlanRequest", + "GetDNSStageRequest", + "GetPipelineRequest", + "GetPurgeRequestRequest", + "GetRouteStageRequest", + "GetTLSStageRequest", + "GetWafStageRequest", + "HeadStageResponse", + "ListBackendStagesRequest", + "ListBackendStagesResponse", + "ListCacheStagesRequest", + "ListCacheStagesResponse", + "ListDNSStagesRequest", + "ListDNSStagesResponse", + "ListHeadStagesRequest", + "ListHeadStagesResponse", + "ListPipelinesRequest", + "ListPipelinesResponse", + "ListPipelinesWithStagesRequest", + "ListPipelinesWithStagesResponse", + "ListPlansResponse", + "ListPurgeRequestsRequest", + "ListPurgeRequestsResponse", + "ListRouteRulesRequest", + "ListRouteRulesResponse", + "ListRouteStagesRequest", + "ListRouteStagesResponse", + "ListTLSStagesRequest", + "ListTLSStagesResponse", + "ListWafStagesRequest", + "ListWafStagesResponse", + "Plan", + "SearchBackendStagesRequest", + "SelectPlanRequest", + "SetHeadStageRequest", + "SetRouteRulesRequest", + "SetRouteRulesResponse", + "UpdateBackendStageRequest", + "UpdateCacheStageRequest", + "UpdateDNSStageRequest", + "UpdatePipelineRequest", + "UpdateRouteStageRequest", + "UpdateTLSStageRequest", + "UpdateWafStageRequest", + "EdgeServicesV1Beta1API", +] diff --git a/scaleway/scaleway/edge_services/v1beta1/api.py b/scaleway/scaleway/edge_services/v1beta1/api.py new file mode 100644 index 000000000..06c92a1c4 --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/api.py @@ -0,0 +1,2610 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + ListBackendStagesRequestOrderBy, + ListCacheStagesRequestOrderBy, + ListDNSStagesRequestOrderBy, + ListPipelinesRequestOrderBy, + ListPipelinesWithStagesRequestOrderBy, + ListPurgeRequestsRequestOrderBy, + ListRouteStagesRequestOrderBy, + ListTLSStagesRequestOrderBy, + ListWafStagesRequestOrderBy, + PlanName, + SearchBackendStagesRequestOrderBy, + WafStageMode, + AddRouteRulesRequest, + AddRouteRulesResponse, + BackendStage, + CacheStage, + CheckDomainRequest, + CheckDomainResponse, + CheckLbOriginRequest, + CheckLbOriginResponse, + CheckPEMChainRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainResponse, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateRouteStageRequest, + CreateTLSStageRequest, + CreateWafStageRequest, + DNSStage, + GetBillingResponse, + HeadStageResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListHeadStagesResponse, + ListHeadStagesResponseHeadStage, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListRouteRulesResponse, + ListRouteStagesResponse, + ListTLSStagesResponse, + ListWafStagesResponse, + Pipeline, + PipelineStages, + Plan, + PurgeRequest, + RouteStage, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + SelectPlanRequest, + SetHeadStageRequest, + SetHeadStageRequestAddNewHeadStage, + SetHeadStageRequestRemoveHeadStage, + SetHeadStageRequestSwapHeadStage, + SetRouteRulesRequest, + SetRouteRulesRequestRouteRule, + SetRouteRulesResponse, + TLSSecret, + TLSSecretsConfig, + TLSStage, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateRouteStageRequest, + UpdateTLSStageRequest, + UpdateWafStageRequest, + WafStage, +) +from .content import ( + PIPELINE_TRANSIENT_STATUSES, + PURGE_REQUEST_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_BackendStage, + unmarshal_CacheStage, + unmarshal_DNSStage, + unmarshal_Pipeline, + unmarshal_RouteStage, + unmarshal_TLSStage, + unmarshal_WafStage, + unmarshal_PurgeRequest, + unmarshal_AddRouteRulesResponse, + unmarshal_CheckDomainResponse, + unmarshal_CheckLbOriginResponse, + unmarshal_CheckPEMChainResponse, + unmarshal_GetBillingResponse, + unmarshal_HeadStageResponse, + unmarshal_ListBackendStagesResponse, + unmarshal_ListCacheStagesResponse, + unmarshal_ListDNSStagesResponse, + unmarshal_ListHeadStagesResponse, + unmarshal_ListPipelinesResponse, + unmarshal_ListPipelinesWithStagesResponse, + unmarshal_ListPlansResponse, + unmarshal_ListPurgeRequestsResponse, + unmarshal_ListRouteRulesResponse, + unmarshal_ListRouteStagesResponse, + unmarshal_ListTLSStagesResponse, + unmarshal_ListWafStagesResponse, + unmarshal_Plan, + unmarshal_SetRouteRulesResponse, + marshal_AddRouteRulesRequest, + marshal_CheckDomainRequest, + marshal_CheckLbOriginRequest, + marshal_CheckPEMChainRequest, + marshal_CreateBackendStageRequest, + marshal_CreateCacheStageRequest, + marshal_CreateDNSStageRequest, + marshal_CreatePipelineRequest, + marshal_CreatePurgeRequestRequest, + marshal_CreateRouteStageRequest, + marshal_CreateTLSStageRequest, + marshal_CreateWafStageRequest, + marshal_SelectPlanRequest, + marshal_SetHeadStageRequest, + marshal_SetRouteRulesRequest, + marshal_UpdateBackendStageRequest, + marshal_UpdateCacheStageRequest, + marshal_UpdateDNSStageRequest, + marshal_UpdatePipelineRequest, + marshal_UpdateRouteStageRequest, + marshal_UpdateTLSStageRequest, + marshal_UpdateWafStageRequest, +) + + +class EdgeServicesV1Beta1API(API): + """ """ + + def list_pipelines( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> ListPipelinesResponse: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for. Only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for. Only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for. Only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + :return: :class:`ListPipelinesResponse ` + + Usage: + :: + + result = api.list_pipelines() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/pipelines", + params={ + "has_backend_stage_lb": has_backend_stage_lb, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesResponse(res.json()) + + def list_pipelines_all( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> List[Pipeline]: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for. Only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for. Only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for. Only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + :return: :class:`List[Pipeline] ` + + Usage: + :: + + result = api.list_pipelines_all() + """ + + return fetch_all_pages( + type=ListPipelinesResponse, + key="pipelines", + fetcher=self.list_pipelines, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + "has_backend_stage_lb": has_backend_stage_lb, + }, + ) + + def create_pipeline( + self, + *, + name: str, + description: str, + project_id: Optional[str] = None, + ) -> Pipeline: + """ + Create pipeline. + Create a new pipeline. You must specify a `dns_stage_id` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :param project_id: Project ID in which the pipeline will be created. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.create_pipeline( + name="example", + description="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/pipelines", + body=marshal_CreatePipelineRequest( + CreatePipelineRequest( + name=name, + description=description, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + def get_pipeline( + self, + *, + pipeline_id: str, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.get_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + def wait_for_pipeline( + self, + *, + pipeline_id: str, + options: Optional[WaitForOptions[Pipeline, bool]] = None, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.get_pipeline( + pipeline_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in PIPELINE_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_pipeline, + options=options, + args={ + "pipeline_id": pipeline_id, + }, + ) + + def list_pipelines_with_stages( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> ListPipelinesWithStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`ListPipelinesWithStagesResponse ` + + Usage: + :: + + result = api.list_pipelines_with_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/pipelines-stages", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesWithStagesResponse(res.json()) + + def list_pipelines_with_stages_all( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> List[PipelineStages]: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`List[PipelineStages] ` + + Usage: + :: + + result = api.list_pipelines_with_stages_all() + """ + + return fetch_all_pages( + type=ListPipelinesWithStagesResponse, + key="pipelines", + fetcher=self.list_pipelines_with_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + }, + ) + + def update_pipeline( + self, + *, + pipeline_id: str, + name: Optional[str] = None, + description: Optional[str] = None, + ) -> Pipeline: + """ + Update pipeline. + Update the parameters of an existing pipeline, specified by its `pipeline_id`. Parameters which can be updated include the `name`, `description` and `dns_stage_id`. + :param pipeline_id: ID of the pipeline to update. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.update_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + body=marshal_UpdatePipelineRequest( + UpdatePipelineRequest( + pipeline_id=pipeline_id, + name=name, + description=description, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + def delete_pipeline( + self, + *, + pipeline_id: str, + ) -> None: + """ + Delete pipeline. + Delete an existing pipeline, specified by its `pipeline_id`. Deleting a pipeline is permanent, and cannot be undone. Note that all stages linked to the pipeline are also deleted. + :param pipeline_id: ID of the pipeline to delete. + + Usage: + :: + + result = api.delete_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + + def list_head_stages( + self, + *, + pipeline_id: str, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListHeadStagesResponse: + """ + :param pipeline_id: ID of the pipeline to update. + :param page: Page number to return, from the paginated results. + :param page_size: Number of head stages to return per page. + :return: :class:`ListHeadStagesResponse ` + + Usage: + :: + + result = api.list_head_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/head-stages", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListHeadStagesResponse(res.json()) + + def list_head_stages_all( + self, + *, + pipeline_id: str, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[ListHeadStagesResponseHeadStage]: + """ + :param pipeline_id: ID of the pipeline to update. + :param page: Page number to return, from the paginated results. + :param page_size: Number of head stages to return per page. + :return: :class:`List[ListHeadStagesResponseHeadStage] ` + + Usage: + :: + + result = api.list_head_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListHeadStagesResponse, + key="head_stages", + fetcher=self.list_head_stages, + args={ + "pipeline_id": pipeline_id, + "page": page, + "page_size": page_size, + }, + ) + + def set_head_stage( + self, + *, + pipeline_id: str, + add_new_head_stage: Optional[SetHeadStageRequestAddNewHeadStage] = None, + remove_head_stage: Optional[SetHeadStageRequestRemoveHeadStage] = None, + swap_head_stage: Optional[SetHeadStageRequestSwapHeadStage] = None, + ) -> HeadStageResponse: + """ + Configure a entry point to your pipeline. You must specify a `head stage` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + You must specify either a `add_new_head_stage` (to add a new head stage), `remove_head_stage` (to remove a head stage) or `swap_head_stage` (to replace a head stage). + :param pipeline_id: ID of the pipeline to update. + :param add_new_head_stage: Add a new head stage. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :param remove_head_stage: Remove a head stage. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :param swap_head_stage: Replace a head stage with a new one. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :return: :class:`HeadStageResponse ` + + Usage: + :: + + result = api.set_head_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/set-head-stage", + body=marshal_SetHeadStageRequest( + SetHeadStageRequest( + pipeline_id=pipeline_id, + add_new_head_stage=add_new_head_stage, + remove_head_stage=remove_head_stage, + swap_head_stage=swap_head_stage, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_HeadStageResponse(res.json()) + + def list_dns_stages( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + fqdn: Optional[str] = None, + ) -> ListDNSStagesResponse: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + :return: :class:`ListDNSStagesResponse ` + + Usage: + :: + + result = api.list_dns_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/dns-stages", + params={ + "fqdn": fqdn, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDNSStagesResponse(res.json()) + + def list_dns_stages_all( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + fqdn: Optional[str] = None, + ) -> List[DNSStage]: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + :return: :class:`List[DNSStage] ` + + Usage: + :: + + result = api.list_dns_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListDNSStagesResponse, + key="stages", + fetcher=self.list_dns_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "fqdn": fqdn, + }, + ) + + def create_dns_stage( + self, + *, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + ) -> DNSStage: + """ + Create DNS stage. + Create a new DNS stage. You must specify the `fqdns` field to customize the domain endpoint, using a domain you already own. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param pipeline_id: Pipeline ID the DNS stage belongs to. + :return: :class:`DNSStage ` + + Usage: + :: + + result = api.create_dns_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/dns-stages", + body=marshal_CreateDNSStageRequest( + CreateDNSStageRequest( + fqdns=fqdns, + pipeline_id=pipeline_id, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + def get_dns_stage( + self, + *, + dns_stage_id: str, + ) -> DNSStage: + """ + Get DNS stage. + Retrieve information about an existing DNS stage, specified by its `dns_stage_id`. Its full details, including FQDNs, are returned in the response object. + :param dns_stage_id: ID of the requested DNS stage. + :return: :class:`DNSStage ` + + Usage: + :: + + result = api.get_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + def update_dns_stage( + self, + *, + dns_stage_id: str, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> DNSStage: + """ + Update DNS stage. + Update the parameters of an existing DNS stage, specified by its `dns_stage_id`. + :param dns_stage_id: ID of the DNS stage to update. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`DNSStage ` + + Usage: + :: + + result = api.update_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + body=marshal_UpdateDNSStageRequest( + UpdateDNSStageRequest( + dns_stage_id=dns_stage_id, + fqdns=fqdns, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + def delete_dns_stage( + self, + *, + dns_stage_id: str, + ) -> None: + """ + Delete DNS stage. + Delete an existing DNS stage, specified by its `dns_stage_id`. Deleting a DNS stage is permanent, and cannot be undone. + :param dns_stage_id: ID of the DNS stage to delete. + + Usage: + :: + + result = api.delete_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + + def list_tls_stages( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> ListTLSStagesResponse: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + :param secret_id: Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + :return: :class:`ListTLSStagesResponse ` + + Usage: + :: + + result = api.list_tls_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/tls-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTLSStagesResponse(res.json()) + + def list_tls_stages_all( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> List[TLSStage]: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + :param secret_id: Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + :return: :class:`List[TLSStage] ` + + Usage: + :: + + result = api.list_tls_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListTLSStagesResponse, + key="stages", + fetcher=self.list_tls_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + def create_tls_stage( + self, + *, + secrets: Optional[List[TLSSecret]] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + route_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Create TLS stage. + Create a new TLS stage. You must specify either the `secrets` or `managed_certificate` fields to customize the SSL/TLS certificate of your endpoint. Choose `secrets` if you are using a pre-existing certificate held in Scaleway Secret Manager, or `managed_certificate` to let Scaleway generate and manage a Let's Encrypt certificate for your customized endpoint. + :param secrets: Secret (from Scaleway Secret Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param pipeline_id: Pipeline ID the TLS stage belongs to. + :param route_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = api.create_tls_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/tls-stages", + body=marshal_CreateTLSStageRequest( + CreateTLSStageRequest( + secrets=secrets, + managed_certificate=managed_certificate, + pipeline_id=pipeline_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + def get_tls_stage( + self, + *, + tls_stage_id: str, + ) -> TLSStage: + """ + Get TLS stage. + Retrieve information about an existing TLS stage, specified by its `tls_stage_id`. Its full details, including secrets and certificate expiration date are returned in the response object. + :param tls_stage_id: ID of the requested TLS stage. + :return: :class:`TLSStage ` + + Usage: + :: + + result = api.get_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + def update_tls_stage( + self, + *, + tls_stage_id: str, + tls_secrets_config: Optional[TLSSecretsConfig] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Update TLS stage. + Update the parameters of an existing TLS stage, specified by its `tls_stage_id`. Both `tls_secrets_config` and `managed_certificate` parameters can be updated. + :param tls_stage_id: ID of the TLS stage to update. + :param tls_secrets_config: Secret (from Scaleway Secret-Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = api.update_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + body=marshal_UpdateTLSStageRequest( + UpdateTLSStageRequest( + tls_stage_id=tls_stage_id, + tls_secrets_config=tls_secrets_config, + managed_certificate=managed_certificate, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + def delete_tls_stage( + self, + *, + tls_stage_id: str, + ) -> None: + """ + Delete TLS stage. + Delete an existing TLS stage, specified by its `tls_stage_id`. Deleting a TLS stage is permanent, and cannot be undone. + :param tls_stage_id: ID of the TLS stage to delete. + + Usage: + :: + + result = api.delete_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + + def list_cache_stages( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListCacheStagesResponse: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + :return: :class:`ListCacheStagesResponse ` + + Usage: + :: + + result = api.list_cache_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/cache-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListCacheStagesResponse(res.json()) + + def list_cache_stages_all( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[CacheStage]: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + :return: :class:`List[CacheStage] ` + + Usage: + :: + + result = api.list_cache_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListCacheStagesResponse, + key="stages", + fetcher=self.list_cache_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + def create_cache_stage( + self, + *, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + waf_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Create cache stage. + Create a new cache stage. You must specify the `fallback_ttl` field to customize the TTL of the cache. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param pipeline_id: Pipeline ID the Cache stage belongs to. + :param waf_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = api.create_cache_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/cache-stages", + body=marshal_CreateCacheStageRequest( + CreateCacheStageRequest( + fallback_ttl=fallback_ttl, + pipeline_id=pipeline_id, + backend_stage_id=backend_stage_id, + waf_stage_id=waf_stage_id, + route_stage_id=route_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + def get_cache_stage( + self, + *, + cache_stage_id: str, + ) -> CacheStage: + """ + Get cache stage. + Retrieve information about an existing cache stage, specified by its `cache_stage_id`. Its full details, including Time To Live (TTL), are returned in the response object. + :param cache_stage_id: ID of the requested cache stage. + :return: :class:`CacheStage ` + + Usage: + :: + + result = api.get_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + def update_cache_stage( + self, + *, + cache_stage_id: str, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Update cache stage. + Update the parameters of an existing cache stage, specified by its `cache_stage_id`. Parameters which can be updated include the `fallback_ttl` and `backend_stage_id`. + :param cache_stage_id: ID of the cache stage to update. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = api.update_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + body=marshal_UpdateCacheStageRequest( + UpdateCacheStageRequest( + cache_stage_id=cache_stage_id, + fallback_ttl=fallback_ttl, + backend_stage_id=backend_stage_id, + waf_stage_id=waf_stage_id, + route_stage_id=route_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + def delete_cache_stage( + self, + *, + cache_stage_id: str, + ) -> None: + """ + Delete cache stage. + Delete an existing cache stage, specified by its `cache_stage_id`. Deleting a cache stage is permanent, and cannot be undone. + :param cache_stage_id: ID of the cache stage to delete. + + Usage: + :: + + result = api.delete_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + + def list_backend_stages( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + :param bucket_name: Bucket name to filter for. Only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for. Only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = api.list_backend_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + def list_backend_stages_all( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> List[BackendStage]: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + :param bucket_name: Bucket name to filter for. Only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for. Only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + :return: :class:`List[BackendStage] ` + + Usage: + :: + + result = api.list_backend_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListBackendStagesResponse, + key="stages", + fetcher=self.list_backend_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + }, + ) + + def create_backend_stage( + self, + *, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + pipeline_id: str, + ) -> BackendStage: + """ + Create backend stage. + Create a new backend stage. You must specify either a `scaleway_s3` (for a Scaleway Object Storage bucket) or `scaleway_lb` (for a Scaleway Load Balancer) field to configure the origin. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param pipeline_id: Pipeline ID the Backend stage belongs to. + :return: :class:`BackendStage ` + + Usage: + :: + + result = api.create_backend_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/backend-stages", + body=marshal_CreateBackendStageRequest( + CreateBackendStageRequest( + pipeline_id=pipeline_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + def get_backend_stage( + self, + *, + backend_stage_id: str, + ) -> BackendStage: + """ + Get backend stage. + Retrieve information about an existing backend stage, specified by its `backend_stage_id`. Its full details, including `scaleway_s3` or `scaleway_lb`, are returned in the response object. + :param backend_stage_id: ID of the requested backend stage. + :return: :class:`BackendStage ` + + Usage: + :: + + result = api.get_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + def update_backend_stage( + self, + *, + backend_stage_id: str, + pipeline_id: str, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + ) -> BackendStage: + """ + Update backend stage. + Update the parameters of an existing backend stage, specified by its `backend_stage_id`. + :param backend_stage_id: ID of the backend stage to update. + :param pipeline_id: Pipeline ID the Backend stage belongs to. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :return: :class:`BackendStage ` + + Usage: + :: + + result = api.update_backend_stage( + backend_stage_id="example", + pipeline_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + body=marshal_UpdateBackendStageRequest( + UpdateBackendStageRequest( + backend_stage_id=backend_stage_id, + pipeline_id=pipeline_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + def delete_backend_stage( + self, + *, + backend_stage_id: str, + ) -> None: + """ + Delete backend stage. + Delete an existing backend stage, specified by its `backend_stage_id`. Deleting a backend stage is permanent, and cannot be undone. + :param backend_stage_id: ID of the backend stage to delete. + + Usage: + :: + + result = api.delete_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + + def list_waf_stages( + self, + *, + order_by: Optional[ListWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListWafStagesResponse: + """ + List WAF stages. + List all WAF stages, for a Scaleway Organization or Scaleway Project. By default, the WAF stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of WAF stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of WAF stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + :return: :class:`ListWafStagesResponse ` + + Usage: + :: + + result = api.list_waf_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/waf-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWafStagesResponse(res.json()) + + def list_waf_stages_all( + self, + *, + order_by: Optional[ListWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[WafStage]: + """ + List WAF stages. + List all WAF stages, for a Scaleway Organization or Scaleway Project. By default, the WAF stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of WAF stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of WAF stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + :return: :class:`List[WafStage] ` + + Usage: + :: + + result = api.list_waf_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListWafStagesResponse, + key="stages", + fetcher=self.list_waf_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + def create_waf_stage( + self, + *, + pipeline_id: str, + paranoia_level: int, + mode: Optional[WafStageMode] = None, + backend_stage_id: Optional[str] = None, + ) -> WafStage: + """ + Create WAF stage. + Create a new WAF stage. You must specify the `mode` and `paranoia_level` fields to customize the WAF. + :param pipeline_id: Pipeline ID the WAF stage belongs to. + :param paranoia_level: Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + :param mode: Mode defining WAF behavior (`disable`/`log_only`/`enable`). + :param backend_stage_id: ID of the backend stage to forward requests to after the WAF stage. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`WafStage ` + + Usage: + :: + + result = api.create_waf_stage( + pipeline_id="example", + paranoia_level=1, + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/waf-stages", + body=marshal_CreateWafStageRequest( + CreateWafStageRequest( + pipeline_id=pipeline_id, + paranoia_level=paranoia_level, + mode=mode, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + def get_waf_stage( + self, + *, + waf_stage_id: str, + ) -> WafStage: + """ + Get WAF stage. + Retrieve information about an existing WAF stage, specified by its `waf_stage_id`. Its full details are returned in the response object. + :param waf_stage_id: ID of the requested WAF stage. + :return: :class:`WafStage ` + + Usage: + :: + + result = api.get_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + def update_waf_stage( + self, + *, + waf_stage_id: str, + mode: Optional[WafStageMode] = None, + paranoia_level: Optional[int] = None, + backend_stage_id: Optional[str] = None, + ) -> WafStage: + """ + Update WAF stage. + Update the parameters of an existing WAF stage, specified by its `waf_stage_id`. Both `mode` and `paranoia_level` parameters can be updated. + :param waf_stage_id: ID of the WAF stage to update. + :param mode: Mode defining WAF behavior (`disable`/`log_only`/`enable`). + :param paranoia_level: Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + :param backend_stage_id: ID of the backend stage to forward requests to after the WAF stage. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`WafStage ` + + Usage: + :: + + result = api.update_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + body=marshal_UpdateWafStageRequest( + UpdateWafStageRequest( + waf_stage_id=waf_stage_id, + mode=mode, + paranoia_level=paranoia_level, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + def delete_waf_stage( + self, + *, + waf_stage_id: str, + ) -> None: + """ + Delete WAF stage. + Delete an existing WAF stage, specified by its `waf_stage_id`. Deleting a WAF stage is permanent, and cannot be undone. + :param waf_stage_id: ID of the WAF stage to delete. + + Usage: + :: + + result = api.delete_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + ) + + self._throw_on_error(res) + + def list_route_stages( + self, + *, + order_by: Optional[ListRouteStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListRouteStagesResponse: + """ + List route stages. + List all route stages, for a given pipeline. By default, the route stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of route stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of route stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only route stages from this pipeline will be returned. + :return: :class:`ListRouteStagesResponse ` + + Usage: + :: + + result = api.list_route_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/route-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRouteStagesResponse(res.json()) + + def list_route_stages_all( + self, + *, + order_by: Optional[ListRouteStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[RouteStage]: + """ + List route stages. + List all route stages, for a given pipeline. By default, the route stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of route stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of route stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only route stages from this pipeline will be returned. + :return: :class:`List[RouteStage] ` + + Usage: + :: + + result = api.list_route_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListRouteStagesResponse, + key="stages", + fetcher=self.list_route_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + def create_route_stage( + self, + *, + pipeline_id: str, + waf_stage_id: Optional[str] = None, + ) -> RouteStage: + """ + Create route stage. + Create a new route stage. You must specify the `waf_stage_id` field to customize the route. + :param pipeline_id: Pipeline ID the route stage belongs to. + :param waf_stage_id: ID of the WAF stage HTTP requests should be forwarded to when no rules are matched. + One-Of ('next'): at most one of 'waf_stage_id' could be set. + :return: :class:`RouteStage ` + + Usage: + :: + + result = api.create_route_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/route-stages", + body=marshal_CreateRouteStageRequest( + CreateRouteStageRequest( + pipeline_id=pipeline_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + def get_route_stage( + self, + *, + route_stage_id: str, + ) -> RouteStage: + """ + Get route stage. + Retrieve information about an existing route stage, specified by its `route_stage_id`. The summary of the route stage (without route rules) is returned in the response object. + :param route_stage_id: ID of the requested route stage. + :return: :class:`RouteStage ` + + Usage: + :: + + result = api.get_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + def update_route_stage( + self, + *, + route_stage_id: str, + waf_stage_id: Optional[str] = None, + ) -> RouteStage: + """ + Update route stage. + Update the parameters of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param waf_stage_id: ID of the WAF stage HTTP requests should be forwarded to when no rules are matched. + One-Of ('next'): at most one of 'waf_stage_id' could be set. + :return: :class:`RouteStage ` + + Usage: + :: + + result = api.update_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + body=marshal_UpdateRouteStageRequest( + UpdateRouteStageRequest( + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + def delete_route_stage( + self, + *, + route_stage_id: str, + ) -> None: + """ + Delete route stage. + Delete an existing route stage, specified by its `route_stage_id`. Deleting a route stage is permanent, and cannot be undone. + :param route_stage_id: ID of the route stage to delete. + + Usage: + :: + + result = api.delete_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + ) + + self._throw_on_error(res) + + def list_route_rules( + self, + *, + route_stage_id: str, + ) -> ListRouteRulesResponse: + """ + List route rules. + List all route rules of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: Route stage ID to filter for. Only route rules from this route stage will be returned. + :return: :class:`ListRouteRulesResponse ` + + Usage: + :: + + result = api.list_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/{param_route_stage_id}/route-rules", + ) + + self._throw_on_error(res) + return unmarshal_ListRouteRulesResponse(res.json()) + + def set_route_rules( + self, + *, + route_stage_id: str, + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] = None, + ) -> SetRouteRulesResponse: + """ + Set route rules. + Set the rules of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param route_rules: List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + :return: :class:`SetRouteRulesResponse ` + + Usage: + :: + + result = api.set_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "PUT", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + body=marshal_SetRouteRulesRequest( + SetRouteRulesRequest( + route_stage_id=route_stage_id, + route_rules=route_rules, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetRouteRulesResponse(res.json()) + + def add_route_rules( + self, + *, + route_stage_id: str, + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] = None, + after_position: Optional[int] = None, + before_position: Optional[int] = None, + ) -> AddRouteRulesResponse: + """ + Add route rules. + Add route rules to an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param route_rules: List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + :param after_position: Add rules after the given position. + One-Of ('position'): at most one of 'after_position', 'before_position' could be set. + :param before_position: Add rules before the given position. + One-Of ('position'): at most one of 'after_position', 'before_position' could be set. + :return: :class:`AddRouteRulesResponse ` + + Usage: + :: + + result = api.add_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + body=marshal_AddRouteRulesRequest( + AddRouteRulesRequest( + route_stage_id=route_stage_id, + route_rules=route_rules, + after_position=after_position, + before_position=before_position, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AddRouteRulesResponse(res.json()) + + def check_domain( + self, + *, + fqdn: str, + cname: str, + project_id: Optional[str] = None, + ) -> CheckDomainResponse: + """ + :param fqdn: + :param cname: + :param project_id: + :return: :class:`CheckDomainResponse ` + + Usage: + :: + + result = api.check_domain( + fqdn="example", + cname="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-domain", + body=marshal_CheckDomainRequest( + CheckDomainRequest( + fqdn=fqdn, + cname=cname, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckDomainResponse(res.json()) + + def check_pem_chain( + self, + *, + fqdn: str, + project_id: Optional[str] = None, + secret: Optional[CheckPEMChainRequestSecretChain] = None, + raw: Optional[str] = None, + ) -> CheckPEMChainResponse: + """ + :param fqdn: + :param project_id: + :param secret: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :param raw: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :return: :class:`CheckPEMChainResponse ` + + Usage: + :: + + result = api.check_pem_chain( + fqdn="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-pem-chain", + body=marshal_CheckPEMChainRequest( + CheckPEMChainRequest( + fqdn=fqdn, + project_id=project_id, + secret=secret, + raw=raw, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckPEMChainResponse(res.json()) + + def search_backend_stages( + self, + *, + order_by: Optional[SearchBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param project_id: + :param bucket_name: + :param bucket_region: + :param lb_id: + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = api.search_backend_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/search-backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + def list_purge_requests( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> ListPurgeRequestsResponse: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for. Only purge requests from this Project will be returned. + :param project_id: Project ID to filter for. Only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + :return: :class:`ListPurgeRequestsResponse ` + + Usage: + :: + + result = api.list_purge_requests() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/purge-requests", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPurgeRequestsResponse(res.json()) + + def list_purge_requests_all( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> List[PurgeRequest]: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for. Only purge requests from this Project will be returned. + :param project_id: Project ID to filter for. Only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + :return: :class:`List[PurgeRequest] ` + + Usage: + :: + + result = api.list_purge_requests_all() + """ + + return fetch_all_pages( + type=ListPurgeRequestsResponse, + key="purge_requests", + fetcher=self.list_purge_requests, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "pipeline_id": pipeline_id, + }, + ) + + def create_purge_request( + self, + *, + pipeline_id: str, + assets: Optional[List[str]] = None, + all: Optional[bool] = None, + ) -> PurgeRequest: + """ + Create purge request. + Create a new purge request. You must specify either the `all` field (to purge all content) or a list of `assets` (to define the precise assets to purge). + :param pipeline_id: Pipeline ID in which the purge request will be created. + :param assets: List of asserts to purge. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :param all: Defines whether to purge all content. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = api.create_purge_request( + pipeline_id="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/purge-requests", + body=marshal_CreatePurgeRequestRequest( + CreatePurgeRequestRequest( + pipeline_id=pipeline_id, + assets=assets, + all=all, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + def get_purge_request( + self, + *, + purge_request_id: str, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = api.get_purge_request( + purge_request_id="example", + ) + """ + + param_purge_request_id = validate_path_param( + "purge_request_id", purge_request_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/purge-requests/{param_purge_request_id}", + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + def wait_for_purge_request( + self, + *, + purge_request_id: str, + options: Optional[WaitForOptions[PurgeRequest, bool]] = None, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = api.get_purge_request( + purge_request_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in PURGE_REQUEST_TRANSIENT_STATUSES + ) + + return wait_for_resource( + fetcher=self.get_purge_request, + options=options, + args={ + "purge_request_id": purge_request_id, + }, + ) + + def check_lb_origin( + self, + *, + lb: Optional[ScalewayLb] = None, + ) -> CheckLbOriginResponse: + """ + :param lb: + :return: :class:`CheckLbOriginResponse ` + + Usage: + :: + + result = api.check_lb_origin() + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-lb-origin", + body=marshal_CheckLbOriginRequest( + CheckLbOriginRequest( + lb=lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckLbOriginResponse(res.json()) + + def list_plans( + self, + ) -> ListPlansResponse: + """ + + :return: :class:`ListPlansResponse ` + + Usage: + :: + + result = api.list_plans() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/plans", + ) + + self._throw_on_error(res) + return unmarshal_ListPlansResponse(res.json()) + + def select_plan( + self, + *, + project_id: Optional[str] = None, + plan_name: Optional[PlanName] = None, + ) -> Plan: + """ + :param project_id: + :param plan_name: + :return: :class:`Plan ` + + Usage: + :: + + result = api.select_plan() + """ + + res = self._request( + "PATCH", + "/edge-services/v1beta1/current-plan", + body=marshal_SelectPlanRequest( + SelectPlanRequest( + project_id=project_id, + plan_name=plan_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + def get_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> Plan: + """ + :param project_id: + :return: :class:`Plan ` + + Usage: + :: + + result = api.get_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + def delete_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> None: + """ + :param project_id: + + Usage: + :: + + result = api.delete_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + + def get_billing( + self, + *, + project_id: Optional[str] = None, + ) -> GetBillingResponse: + """ + Gives information on the currently selected Edge Services subscription plan, resource usage and associated billing information for this calendar month (including whether consumption falls within or exceeds the currently selected subscription plan.). + :param project_id: + :return: :class:`GetBillingResponse ` + + Usage: + :: + + result = api.get_billing() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/billing/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_GetBillingResponse(res.json()) diff --git a/scaleway/scaleway/edge_services/v1beta1/content.py b/scaleway/scaleway/edge_services/v1beta1/content.py new file mode 100644 index 000000000..ad1b5e0e6 --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/content.py @@ -0,0 +1,21 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + PipelineStatus, + PurgeRequestStatus, +) + +PIPELINE_TRANSIENT_STATUSES: List[PipelineStatus] = [ + PipelineStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PipelineStatus `. +""" +PURGE_REQUEST_TRANSIENT_STATUSES: List[PurgeRequestStatus] = [ + PurgeRequestStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PurgeRequestStatus `. +""" diff --git a/scaleway/scaleway/edge_services/v1beta1/marshalling.py b/scaleway/scaleway/edge_services/v1beta1/marshalling.py new file mode 100644 index 000000000..b01c7d7cf --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/marshalling.py @@ -0,0 +1,1901 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + RuleHttpMatchMethodFilter, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + BackendStage, + CacheStage, + DNSStage, + PipelineError, + Pipeline, + RouteStage, + TLSSecret, + TLSStage, + WafStage, + PipelineStages, + PurgeRequest, + RuleHttpMatchPathFilter, + RuleHttpMatch, + RouteRule, + AddRouteRulesResponse, + CheckDomainResponse, + CheckLbOriginResponse, + CheckPEMChainResponse, + PlanDetails, + PlanUsageDetails, + GetBillingResponse, + HeadStageResponseHeadStage, + HeadStageResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListHeadStagesResponseHeadStage, + ListHeadStagesResponse, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListRouteRulesResponse, + ListRouteStagesResponse, + ListTLSStagesResponse, + ListWafStagesResponse, + Plan, + SetRouteRulesResponse, + SetRouteRulesRequestRouteRule, + AddRouteRulesRequest, + CheckDomainRequest, + CheckLbOriginRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainRequest, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateRouteStageRequest, + CreateTLSStageRequest, + CreateWafStageRequest, + SelectPlanRequest, + SetHeadStageRequestAddNewHeadStage, + SetHeadStageRequestRemoveHeadStage, + SetHeadStageRequestSwapHeadStage, + SetHeadStageRequest, + SetRouteRulesRequest, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateRouteStageRequest, + TLSSecretsConfig, + UpdateTLSStageRequest, + UpdateWafStageRequest, +) + + +def unmarshal_ScalewayLb(data: Any) -> ScalewayLb: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLb' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("frontend_id", None) + if field is not None: + args["frontend_id"] = field + + field = data.get("is_ssl", None) + if field is not None: + args["is_ssl"] = field + else: + args["is_ssl"] = None + + field = data.get("domain_name", None) + if field is not None: + args["domain_name"] = field + else: + args["domain_name"] = None + + return ScalewayLb(**args) + + +def unmarshal_ScalewayLbBackendConfig(data: Any) -> ScalewayLbBackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLbBackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("lbs", None) + if field is not None: + args["lbs"] = ( + [unmarshal_ScalewayLb(v) for v in field] if field is not None else None + ) + + return ScalewayLbBackendConfig(**args) + + +def unmarshal_ScalewayS3BackendConfig(data: Any) -> ScalewayS3BackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayS3BackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bucket_name", None) + if field is not None: + args["bucket_name"] = field + else: + args["bucket_name"] = None + + field = data.get("bucket_region", None) + if field is not None: + args["bucket_region"] = field + else: + args["bucket_region"] = None + + field = data.get("is_website", None) + if field is not None: + args["is_website"] = field + else: + args["is_website"] = None + + return ScalewayS3BackendConfig(**args) + + +def unmarshal_BackendStage(data: Any) -> BackendStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BackendStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("scaleway_s3", None) + if field is not None: + args["scaleway_s3"] = unmarshal_ScalewayS3BackendConfig(field) + else: + args["scaleway_s3"] = None + + field = data.get("scaleway_lb", None) + if field is not None: + args["scaleway_lb"] = unmarshal_ScalewayLbBackendConfig(field) + else: + args["scaleway_lb"] = None + + return BackendStage(**args) + + +def unmarshal_CacheStage(data: Any) -> CacheStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CacheStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("fallback_ttl", None) + if field is not None: + args["fallback_ttl"] = field + else: + args["fallback_ttl"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + else: + args["route_stage_id"] = None + + return CacheStage(**args) + + +def unmarshal_DNSStage(data: Any) -> DNSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DNSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("fqdns", None) + if field is not None: + args["fqdns"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("tls_stage_id", None) + if field is not None: + args["tls_stage_id"] = field + else: + args["tls_stage_id"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return DNSStage(**args) + + +def unmarshal_PipelineError(data: Any) -> PipelineError: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineError' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stage", None) + if field is not None: + args["stage"] = field + + field = data.get("code", None) + if field is not None: + args["code"] = field + + field = data.get("severity", None) + if field is not None: + args["severity"] = field + + field = data.get("message", None) + if field is not None: + args["message"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PipelineError(**args) + + +def unmarshal_Pipeline(data: Any) -> Pipeline: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pipeline' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("errors", None) + if field is not None: + args["errors"] = ( + [unmarshal_PipelineError(v) for v in field] if field is not None else None + ) + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Pipeline(**args) + + +def unmarshal_RouteStage(data: Any) -> RouteStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RouteStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return RouteStage(**args) + + +def unmarshal_TLSSecret(data: Any) -> TLSSecret: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSSecret' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret_id", None) + if field is not None: + args["secret_id"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + return TLSSecret(**args) + + +def unmarshal_TLSStage(data: Any) -> TLSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_TLSSecret(v) for v in field] if field is not None else None + ) + + field = data.get("managed_certificate", None) + if field is not None: + args["managed_certificate"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("certificate_expires_at", None) + if field is not None: + args["certificate_expires_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["certificate_expires_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + else: + args["route_stage_id"] = None + + return TLSStage(**args) + + +def unmarshal_WafStage(data: Any) -> WafStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'WafStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("mode", None) + if field is not None: + args["mode"] = field + + field = data.get("paranoia_level", None) + if field is not None: + args["paranoia_level"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return WafStage(**args) + + +def unmarshal_PipelineStages(data: Any) -> PipelineStages: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineStages' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stages", None) + if field is not None: + args["dns_stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("tls_stages", None) + if field is not None: + args["tls_stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("cache_stages", None) + if field is not None: + args["cache_stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("backend_stages", None) + if field is not None: + args["backend_stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("waf_stages", None) + if field is not None: + args["waf_stages"] = ( + [unmarshal_WafStage(v) for v in field] if field is not None else None + ) + + field = data.get("route_stages", None) + if field is not None: + args["route_stages"] = ( + [unmarshal_RouteStage(v) for v in field] if field is not None else None + ) + + field = data.get("pipeline", None) + if field is not None: + args["pipeline"] = unmarshal_Pipeline(field) + else: + args["pipeline"] = None + + return PipelineStages(**args) + + +def unmarshal_PurgeRequest(data: Any) -> PurgeRequest: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PurgeRequest' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("assets", None) + if field is not None: + args["assets"] = field + else: + args["assets"] = None + + field = data.get("all", None) + if field is not None: + args["all"] = field + else: + args["all"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return PurgeRequest(**args) + + +def unmarshal_RuleHttpMatchPathFilter(data: Any) -> RuleHttpMatchPathFilter: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RuleHttpMatchPathFilter' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path_filter_type", None) + if field is not None: + args["path_filter_type"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + return RuleHttpMatchPathFilter(**args) + + +def unmarshal_RuleHttpMatch(data: Any) -> RuleHttpMatch: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RuleHttpMatch' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("method_filters", None) + if field is not None: + args["method_filters"] = ( + [RuleHttpMatchMethodFilter(v) for v in field] if field is not None else None + ) + + field = data.get("path_filter", None) + if field is not None: + args["path_filter"] = unmarshal_RuleHttpMatchPathFilter(field) + else: + args["path_filter"] = None + + return RuleHttpMatch(**args) + + +def unmarshal_RouteRule(data: Any) -> RouteRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RouteRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("position", None) + if field is not None: + args["position"] = field + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + + field = data.get("rule_http_match", None) + if field is not None: + args["rule_http_match"] = unmarshal_RuleHttpMatch(field) + else: + args["rule_http_match"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return RouteRule(**args) + + +def unmarshal_AddRouteRulesResponse(data: Any) -> AddRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AddRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return AddRouteRulesResponse(**args) + + +def unmarshal_CheckDomainResponse(data: Any) -> CheckDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckDomainResponse(**args) + + +def unmarshal_CheckLbOriginResponse(data: Any) -> CheckLbOriginResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckLbOriginResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + field = data.get("error_type", None) + if field is not None: + args["error_type"] = field + + return CheckLbOriginResponse(**args) + + +def unmarshal_CheckPEMChainResponse(data: Any) -> CheckPEMChainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckPEMChainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckPEMChainResponse(**args) + + +def unmarshal_PlanDetails(data: Any) -> PlanDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + field = data.get("package_gb", None) + if field is not None: + args["package_gb"] = field + + field = data.get("pipeline_limit", None) + if field is not None: + args["pipeline_limit"] = field + + field = data.get("waf_requests", None) + if field is not None: + args["waf_requests"] = field + + return PlanDetails(**args) + + +def unmarshal_PlanUsageDetails(data: Any) -> PlanUsageDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanUsageDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + return PlanUsageDetails(**args) + + +def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetBillingResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("current_plan", None) + if field is not None: + args["current_plan"] = unmarshal_PlanDetails(field) + else: + args["current_plan"] = None + + field = data.get("pipeline_number", None) + if field is not None: + args["pipeline_number"] = field + + field = data.get("current_plan_cache_usage", None) + if field is not None: + args["current_plan_cache_usage"] = field + + field = data.get("extra_cache_usage", None) + if field is not None: + args["extra_cache_usage"] = field + + field = data.get("current_plan_waf_usage", None) + if field is not None: + args["current_plan_waf_usage"] = field + + field = data.get("extra_waf_usage", None) + if field is not None: + args["extra_waf_usage"] = field + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + field = data.get("extra_pipelines_cost", None) + if field is not None: + args["extra_pipelines_cost"] = unmarshal_Money(field) + else: + args["extra_pipelines_cost"] = None + + field = data.get("plans_usage_details", None) + if field is not None: + args["plans_usage_details"] = ( + {key: unmarshal_PlanUsageDetails(value) for key, value in field.items()} + if field is not None + else None + ) + + field = data.get("extra_cache_cost", None) + if field is not None: + args["extra_cache_cost"] = unmarshal_Money(field) + else: + args["extra_cache_cost"] = None + + field = data.get("extra_waf_cost", None) + if field is not None: + args["extra_waf_cost"] = unmarshal_Money(field) + else: + args["extra_waf_cost"] = None + + field = data.get("waf_add_on", None) + if field is not None: + args["waf_add_on"] = unmarshal_Money(field) + else: + args["waf_add_on"] = None + + field = data.get("total_cost", None) + if field is not None: + args["total_cost"] = unmarshal_Money(field) + else: + args["total_cost"] = None + + return GetBillingResponse(**args) + + +def unmarshal_HeadStageResponseHeadStage(data: Any) -> HeadStageResponseHeadStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HeadStageResponseHeadStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return HeadStageResponseHeadStage(**args) + + +def unmarshal_HeadStageResponse(data: Any) -> HeadStageResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HeadStageResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("head_stage", None) + if field is not None: + args["head_stage"] = unmarshal_HeadStageResponseHeadStage(field) + else: + args["head_stage"] = None + + return HeadStageResponse(**args) + + +def unmarshal_ListBackendStagesResponse(data: Any) -> ListBackendStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListBackendStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListBackendStagesResponse(**args) + + +def unmarshal_ListCacheStagesResponse(data: Any) -> ListCacheStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListCacheStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListCacheStagesResponse(**args) + + +def unmarshal_ListDNSStagesResponse(data: Any) -> ListDNSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDNSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDNSStagesResponse(**args) + + +def unmarshal_ListHeadStagesResponseHeadStage( + data: Any, +) -> ListHeadStagesResponseHeadStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHeadStagesResponseHeadStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return ListHeadStagesResponseHeadStage(**args) + + +def unmarshal_ListHeadStagesResponse(data: Any) -> ListHeadStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHeadStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("head_stages", None) + if field is not None: + args["head_stages"] = ( + [unmarshal_ListHeadStagesResponseHeadStage(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListHeadStagesResponse(**args) + + +def unmarshal_ListPipelinesResponse(data: Any) -> ListPipelinesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_Pipeline(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesResponse(**args) + + +def unmarshal_ListPipelinesWithStagesResponse( + data: Any, +) -> ListPipelinesWithStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesWithStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_PipelineStages(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesWithStagesResponse(**args) + + +def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPlansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("plans", None) + if field is not None: + args["plans"] = ( + [unmarshal_PlanDetails(v) for v in field] if field is not None else None + ) + + return ListPlansResponse(**args) + + +def unmarshal_ListPurgeRequestsResponse(data: Any) -> ListPurgeRequestsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPurgeRequestsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("purge_requests", None) + if field is not None: + args["purge_requests"] = ( + [unmarshal_PurgeRequest(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPurgeRequestsResponse(**args) + + +def unmarshal_ListRouteRulesResponse(data: Any) -> ListRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return ListRouteRulesResponse(**args) + + +def unmarshal_ListRouteStagesResponse(data: Any) -> ListRouteStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRouteStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_RouteStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListRouteStagesResponse(**args) + + +def unmarshal_ListTLSStagesResponse(data: Any) -> ListTLSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTLSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListTLSStagesResponse(**args) + + +def unmarshal_ListWafStagesResponse(data: Any) -> ListWafStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWafStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_WafStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListWafStagesResponse(**args) + + +def unmarshal_Plan(data: Any) -> Plan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Plan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + return Plan(**args) + + +def unmarshal_SetRouteRulesResponse(data: Any) -> SetRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return SetRouteRulesResponse(**args) + + +def marshal_RuleHttpMatchPathFilter( + request: RuleHttpMatchPathFilter, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.path_filter_type is not None: + output["path_filter_type"] = str(request.path_filter_type) + + if request.value is not None: + output["value"] = request.value + + return output + + +def marshal_RuleHttpMatch( + request: RuleHttpMatch, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.method_filters is not None: + output["method_filters"] = [str(item) for item in request.method_filters] + + if request.path_filter is not None: + output["path_filter"] = marshal_RuleHttpMatchPathFilter( + request.path_filter, defaults + ) + + return output + + +def marshal_SetRouteRulesRequestRouteRule( + request: SetRouteRulesRequestRouteRule, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("rule_http_match", request.rule_http_match), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + return output + + +def marshal_AddRouteRulesRequest( + request: AddRouteRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("after_position", request.after_position), + OneOfPossibility("before_position", request.before_position), + ] + ), + ) + + if request.route_rules is not None: + output["route_rules"] = [ + marshal_SetRouteRulesRequestRouteRule(item, defaults) + for item in request.route_rules + ] + + return output + + +def marshal_CheckDomainRequest( + request: CheckDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.cname is not None: + output["cname"] = request.cname + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLb( + request: ScalewayLb, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.zone is not None: + output["zone"] = request.zone or defaults.default_zone + + if request.frontend_id is not None: + output["frontend_id"] = request.frontend_id + + if request.is_ssl is not None: + output["is_ssl"] = request.is_ssl + + if request.domain_name is not None: + output["domain_name"] = request.domain_name + + return output + + +def marshal_CheckLbOriginRequest( + request: CheckLbOriginRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lb is not None: + output["lb"] = marshal_ScalewayLb(request.lb, defaults) + + return output + + +def marshal_CheckPEMChainRequestSecretChain( + request: CheckPEMChainRequestSecretChain, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.secret_region is not None: + output["secret_region"] = request.secret_region + + return output + + +def marshal_CheckPEMChainRequest( + request: CheckPEMChainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + OneOfPossibility("raw", request.raw), + ] + ), + ) + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLbBackendConfig( + request: ScalewayLbBackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lbs is not None: + output["lbs"] = [marshal_ScalewayLb(item, defaults) for item in request.lbs] + + return output + + +def marshal_ScalewayS3BackendConfig( + request: ScalewayS3BackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket_name is not None: + output["bucket_name"] = request.bucket_name + + if request.bucket_region is not None: + output["bucket_region"] = request.bucket_region + + if request.is_website is not None: + output["is_website"] = request.is_website + + return output + + +def marshal_CreateBackendStageRequest( + request: CreateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + return output + + +def marshal_CreateCacheStageRequest( + request: CreateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_CreateDNSStageRequest( + request: CreateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_CreatePipelineRequest( + request: CreatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreatePurgeRequestRequest( + request: CreatePurgeRequestRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("assets", request.assets), + OneOfPossibility("all", request.all), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_CreateRouteStageRequest( + request: CreateRouteStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + return output + + +def marshal_TLSSecret( + request: TLSSecret, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.region is not None: + output["region"] = request.region or defaults.default_region + + return output + + +def marshal_CreateTLSStageRequest( + request: CreateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + if request.secrets is not None: + output["secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.secrets + ] + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_CreateWafStageRequest( + request: CreateWafStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.paranoia_level is not None: + output["paranoia_level"] = request.paranoia_level + + if request.mode is not None: + output["mode"] = str(request.mode) + + return output + + +def marshal_SelectPlanRequest( + request: SelectPlanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.plan_name is not None: + output["plan_name"] = str(request.plan_name) + + return output + + +def marshal_SetHeadStageRequestAddNewHeadStage( + request: SetHeadStageRequestAddNewHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.new_stage_id is not None: + output["new_stage_id"] = request.new_stage_id + + return output + + +def marshal_SetHeadStageRequestRemoveHeadStage( + request: SetHeadStageRequestRemoveHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.remove_stage_id is not None: + output["remove_stage_id"] = request.remove_stage_id + + return output + + +def marshal_SetHeadStageRequestSwapHeadStage( + request: SetHeadStageRequestSwapHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.new_stage_id is not None: + output["new_stage_id"] = request.new_stage_id + + if request.current_stage_id is not None: + output["current_stage_id"] = request.current_stage_id + + return output + + +def marshal_SetHeadStageRequest( + request: SetHeadStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("add_new_head_stage", request.add_new_head_stage), + OneOfPossibility("remove_head_stage", request.remove_head_stage), + OneOfPossibility("swap_head_stage", request.swap_head_stage), + ] + ), + ) + + return output + + +def marshal_SetRouteRulesRequest( + request: SetRouteRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.route_rules is not None: + output["route_rules"] = [ + marshal_SetRouteRulesRequestRouteRule(item, defaults) + for item in request.route_rules + ] + + return output + + +def marshal_UpdateBackendStageRequest( + request: UpdateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_UpdateCacheStageRequest( + request: UpdateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_UpdateDNSStageRequest( + request: UpdateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_UpdatePipelineRequest( + request: UpdatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_UpdateRouteStageRequest( + request: UpdateRouteStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + return output + + +def marshal_TLSSecretsConfig( + request: TLSSecretsConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tls_secrets is not None: + output["tls_secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.tls_secrets + ] + + return output + + +def marshal_UpdateTLSStageRequest( + request: UpdateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + if request.tls_secrets_config is not None: + output["tls_secrets_config"] = marshal_TLSSecretsConfig( + request.tls_secrets_config, defaults + ) + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_UpdateWafStageRequest( + request: UpdateWafStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.mode is not None: + output["mode"] = str(request.mode) + + if request.paranoia_level is not None: + output["paranoia_level"] = request.paranoia_level + + return output diff --git a/scaleway/scaleway/edge_services/v1beta1/types.py b/scaleway/scaleway/edge_services/v1beta1/types.py new file mode 100644 index 000000000..424d86ece --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/types.py @@ -0,0 +1,1780 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DNSStageType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + AUTO = "auto" + MANAGED = "managed" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class LbOriginError(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + TIMEOUT = "timeout" + CONNECTION_REFUSED = "connection_refused" + TLS_ERROR = "tls_error" + + def __str__(self) -> str: + return str(self.value) + + +class ListBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListCacheStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListDNSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesWithStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPurgeRequestsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRouteStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListTLSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListWafStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorCode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_CODE = "unknown_code" + DNS_INVALID_FORMAT = "dns_invalid_format" + DNS_INVALID_TLD = "dns_invalid_tld" + DNS_FORBIDDEN_ROOT_DOMAIN = "dns_forbidden_root_domain" + DNS_FORBIDDEN_SCW_CLOUD = "dns_forbidden_scw_cloud" + DNS_DOMAIN_DONT_EXIST = "dns_domain_dont_exist" + DNS_CNAME_DONT_EXIST = "dns_cname_dont_exist" + DNS_CNAME_RESOLVE = "dns_cname_resolve" + DNS_FQDN_ALREADY_EXISTS = "dns_fqdn_already_exists" + DNS_FQDN_ALREADY_IN_USE = "dns_fqdn_already_in_use" + TLS_CERT_DELETED = "tls_cert_deleted" + TLS_CERT_DISABLED = "tls_cert_disabled" + TLS_CERT_EXPIRED = "tls_cert_expired" + TLS_CERT_INVALID_FORMAT = "tls_cert_invalid_format" + TLS_CERT_MISSING = "tls_cert_missing" + TLS_CHAIN_ORDER = "tls_chain_order" + TLS_KEY_INVALID_FORMAT = "tls_key_invalid_format" + TLS_KEY_MISSING = "tls_key_missing" + TLS_KEY_TOO_MANY = "tls_key_too_many" + TLS_MANAGED_DOMAIN_RATE_LIMIT = "tls_managed_domain_rate_limit" + TLS_MANAGED_INTERNAL = "tls_managed_internal" + TLS_PAIR_MISMATCH = "tls_pair_mismatch" + TLS_ROOT_INCONSISTENT = "tls_root_inconsistent" + TLS_ROOT_INCORRECT = "tls_root_incorrect" + TLS_ROOT_MISSING = "tls_root_missing" + TLS_SAN_MISMATCH = "tls_san_mismatch" + TLS_SELF_SIGNED = "tls_self_signed" + PIPELINE_INVALID_WORKFLOW = "pipeline_invalid_workflow" + PIPELINE_MISSING_HEAD_STAGE = "pipeline_missing_head_stage" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorSeverity(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SEVERITY = "unknown_severity" + WARNING = "warning" + CRITICAL = "critical" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorStage(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STAGE = "unknown_stage" + DNS = "dns" + TLS = "tls" + CACHE = "cache" + BACKEND = "backend" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + RUNTIME = "runtime" + CONFIG = "config" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + ERROR = "error" + PENDING = "pending" + WARNING = "warning" + + def __str__(self) -> str: + return str(self.value) + + +class PlanName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + STARTER = "starter" + PROFESSIONAL = "professional" + ADVANCED = "advanced" + + def __str__(self) -> str: + return str(self.value) + + +class PurgeRequestStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DONE = "done" + ERROR = "error" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) + + +class RuleHttpMatchMethodFilter(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_METHOD_FILTER = "unknown_method_filter" + GET = "get" + POST = "post" + PUT = "put" + PATCH = "patch" + DELETE = "delete" + HEAD = "head" + OPTIONS = "options" + + def __str__(self) -> str: + return str(self.value) + + +class RuleHttpMatchPathFilterPathFilterType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PATH_FILTER = "unknown_path_filter" + REGEX = "regex" + + def __str__(self) -> str: + return str(self.value) + + +class SearchBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class WafStageMode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_MODE = "unknown_mode" + DISABLE = "disable" + LOG_ONLY = "log_only" + ENABLE = "enable" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ScalewayLb: + id: str + """ + ID of the Load Balancer. + """ + + zone: ScwZone + """ + Zone of the Load Balancer. + """ + + frontend_id: str + """ + ID of the frontend linked to the Load Balancer. + """ + + is_ssl: Optional[bool] + """ + Defines whether the Load Balancer's frontend handles SSL connections. + """ + + domain_name: Optional[str] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to use in HTTP requests sent towards your Load Balancer. + """ + + +@dataclass +class RuleHttpMatchPathFilter: + path_filter_type: RuleHttpMatchPathFilterPathFilterType + """ + Type of filter to match for the HTTP URL path. For now, all path filters must be written in regex and use the `regex` type. + """ + + value: str + """ + Value to be matched for the HTTP URL path. + """ + + +@dataclass +class ScalewayLbBackendConfig: + lbs: List[ScalewayLb] + """ + Load Balancer information. + """ + + +@dataclass +class ScalewayS3BackendConfig: + bucket_name: Optional[str] + """ + Name of the Bucket. + """ + + bucket_region: Optional[str] + """ + Region of the Bucket. + """ + + is_website: Optional[bool] + """ + Defines whether the bucket website feature is enabled. + """ + + +@dataclass +class PipelineError: + stage: PipelineErrorStage + + code: PipelineErrorCode + + severity: PipelineErrorSeverity + + message: str + + type_: PipelineErrorType + + +@dataclass +class TLSSecret: + secret_id: str + """ + ID of the Secret. + """ + + region: ScwRegion + """ + Region of the Secret. + """ + + +@dataclass +class RuleHttpMatch: + method_filters: List[RuleHttpMatchMethodFilter] + """ + HTTP methods to filter for. A request using any of these methods will be considered to match the rule. Possible values are `get`, `post`, `put`, `patch`, `delete`, `head`, `options`. All methods will match if none is provided. + """ + + path_filter: Optional[RuleHttpMatchPathFilter] + """ + HTTP URL path to filter for. A request whose path matches the given filter will be considered to match the rule. All paths will match if none is provided. + """ + + +@dataclass +class BackendStage: + id: str + """ + ID of the backend stage. + """ + + pipeline_id: str + """ + Pipeline ID the backend stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the backend stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the backend stage was last updated. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CacheStage: + id: str + """ + ID of the cache stage. + """ + + pipeline_id: str + """ + Pipeline ID the cache stage belongs to. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + created_at: Optional[datetime] + """ + Date the cache stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the cache stage was last updated. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class DNSStage: + id: str + """ + ID of the DNS stage. + """ + + fqdns: List[str] + """ + List of Fully Qualified Domain Names attached to the stage. + """ + + type_: DNSStageType + """ + Type of the stage. + """ + + pipeline_id: str + """ + Pipeline ID the DNS stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the DNS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the DNS stage was last updated. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class Pipeline: + id: str + """ + ID of the pipeline. + """ + + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + status: PipelineStatus + """ + Status of the pipeline. + """ + + errors: List[PipelineError] + """ + Errors of the pipeline. + """ + + project_id: str + """ + Project ID of the pipeline. + """ + + organization_id: str + """ + Organization ID of the pipeline. + """ + + created_at: Optional[datetime] + """ + Date the pipeline was created. + """ + + updated_at: Optional[datetime] + """ + Date the pipeline was last updated. + """ + + +@dataclass +class RouteStage: + id: str + """ + ID of the route stage. + """ + + pipeline_id: str + """ + Pipeline ID the route stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the route stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the route stage was last updated. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class TLSStage: + id: str + """ + ID of the TLS stage. + """ + + secrets: List[TLSSecret] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: bool + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + pipeline_id: str + """ + Pipeline ID the TLS stage belongs to. + """ + + certificate_expires_at: Optional[datetime] + """ + Expiration date of the certificate. + """ + + created_at: Optional[datetime] + """ + Date the TLS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the TLS stage was last updated. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class WafStage: + id: str + """ + ID of the WAF stage. + """ + + pipeline_id: str + """ + Pipeline ID the WAF stage belongs to. + """ + + mode: WafStageMode + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + paranoia_level: int + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + created_at: Optional[datetime] + """ + Date the WAF stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the WAF stage was last updated. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class SetRouteRulesRequestRouteRule: + rule_http_match: Optional[RuleHttpMatch] + + backend_stage_id: Optional[str] + + +@dataclass +class RouteRule: + position: int + """ + Position of the rule which determines the order of processing within the route stage. + """ + + route_stage_id: str + """ + Route stage ID the route rule belongs to. + """ + + rule_http_match: Optional[RuleHttpMatch] + + backend_stage_id: Optional[str] + + +@dataclass +class CheckPEMChainRequestSecretChain: + secret_id: str + + secret_region: str + + +@dataclass +class PlanDetails: + plan_name: PlanName + """ + Subscription plan name. + """ + + package_gb: int + """ + Amount of egress data from cache included in subscription plan. + """ + + pipeline_limit: int + """ + Number of pipelines included in subscription plan. + """ + + waf_requests: int + """ + Number of WAF requests included in subscription plan. + """ + + +@dataclass +class PlanUsageDetails: + plan_cost: Optional[Money] + """ + Cost to date (this month) for the corresponding Edge Services subscription plan. + """ + + +@dataclass +class HeadStageResponseHeadStage: + dns_stage_id: Optional[str] + + +@dataclass +class ListHeadStagesResponseHeadStage: + dns_stage_id: Optional[str] + + +@dataclass +class PipelineStages: + dns_stages: List[DNSStage] + + tls_stages: List[TLSStage] + + cache_stages: List[CacheStage] + + backend_stages: List[BackendStage] + + waf_stages: List[WafStage] + + route_stages: List[RouteStage] + + pipeline: Optional[Pipeline] + + +@dataclass +class PurgeRequest: + id: str + """ + ID of the purge request. + """ + + pipeline_id: str + """ + Pipeline ID the purge request belongs to. + """ + + status: PurgeRequestStatus + """ + Status of the purge request. + """ + + created_at: Optional[datetime] + """ + Date the purge request was created. + """ + + updated_at: Optional[datetime] + """ + Date the purge request was last updated. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class SetHeadStageRequestAddNewHeadStage: + new_stage_id: str + + +@dataclass +class SetHeadStageRequestRemoveHeadStage: + remove_stage_id: str + + +@dataclass +class SetHeadStageRequestSwapHeadStage: + new_stage_id: str + + current_stage_id: str + + +@dataclass +class TLSSecretsConfig: + tls_secrets: List[TLSSecret] + """ + Secret information (from Secret Manager). + """ + + +@dataclass +class AddRouteRulesRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + after_position: Optional[int] + + before_position: Optional[int] + + +@dataclass +class AddRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class CheckDomainRequest: + fqdn: str + + cname: str + + project_id: Optional[str] + + +@dataclass +class CheckDomainResponse: + is_valid: bool + + +@dataclass +class CheckLbOriginRequest: + lb: Optional[ScalewayLb] + + +@dataclass +class CheckLbOriginResponse: + is_valid: bool + + error_type: LbOriginError + + +@dataclass +class CheckPEMChainRequest: + fqdn: str + + project_id: Optional[str] + + secret: Optional[CheckPEMChainRequestSecretChain] + + raw: Optional[str] + + +@dataclass +class CheckPEMChainResponse: + is_valid: bool + + +@dataclass +class CreateBackendStageRequest: + pipeline_id: str + """ + Pipeline ID the Backend stage belongs to. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CreateCacheStageRequest: + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + pipeline_id: str + """ + Pipeline ID the Cache stage belongs to. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class CreateDNSStageRequest: + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + """ + + pipeline_id: str + """ + Pipeline ID the DNS stage belongs to. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class CreatePipelineRequest: + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + project_id: Optional[str] + """ + Project ID in which the pipeline will be created. + """ + + +@dataclass +class CreatePurgeRequestRequest: + pipeline_id: str + """ + Pipeline ID in which the purge request will be created. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class CreateRouteStageRequest: + pipeline_id: str + """ + Pipeline ID the route stage belongs to. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class CreateTLSStageRequest: + secrets: Optional[List[TLSSecret]] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + pipeline_id: str + """ + Pipeline ID the TLS stage belongs to. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + route_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + +@dataclass +class CreateWafStageRequest: + pipeline_id: str + """ + Pipeline ID the WAF stage belongs to. + """ + + paranoia_level: int + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + mode: Optional[WafStageMode] + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + backend_stage_id: Optional[str] + + +@dataclass +class DeleteBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to delete. + """ + + +@dataclass +class DeleteCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to delete. + """ + + +@dataclass +class DeleteCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class DeleteDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to delete. + """ + + +@dataclass +class DeletePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to delete. + """ + + +@dataclass +class DeleteRouteStageRequest: + route_stage_id: str + """ + ID of the route stage to delete. + """ + + +@dataclass +class DeleteTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to delete. + """ + + +@dataclass +class DeleteWafStageRequest: + waf_stage_id: str + """ + ID of the WAF stage to delete. + """ + + +@dataclass +class GetBackendStageRequest: + backend_stage_id: str + """ + ID of the requested backend stage. + """ + + +@dataclass +class GetBillingRequest: + project_id: Optional[str] + + +@dataclass +class GetBillingResponse: + current_plan: Optional[PlanDetails] + """ + Information on the currently-selected, active Edge Services subscription plan. + """ + + pipeline_number: int + """ + Total number of pipelines currently configured. + """ + + current_plan_cache_usage: int + """ + Total amount of data egressed from the cache in gigabytes from the beginning of the month, for the active subscription plan. + """ + + extra_cache_usage: int + """ + Total amount of extra data egressed from cache in gigabytes from the beginning of the month, not included in the subscription plans. + """ + + current_plan_waf_usage: int + """ + Total number of requests processed by the WAF since the beginning of the current month, for the active subscription plan. + """ + + extra_waf_usage: int + """ + Total number of extra requests processed by the WAF from the beginning of the month, not included in the subscription plans. + """ + + plan_cost: Optional[Money] + """ + Cost to date (this month) for Edge Service subscription plans. This comprises the pro-rata cost of the current subscription plan, and any previous subscription plans that were active earlier in the month. + """ + + extra_pipelines_cost: Optional[Money] + """ + Cost to date (this month) of pipelines not included in the subscription plans. + """ + + plans_usage_details: Dict[str, PlanUsageDetails] + """ + Detailed costs and usage for all Edge Services subscription plans that were activated during the month. + """ + + extra_cache_cost: Optional[Money] + """ + Cost to date (this month) of the data egressed from the cache that is not included in the subscription plans. + """ + + extra_waf_cost: Optional[Money] + """ + Cost to date (this month) of the extra requests processed by the WAF that were not included in the subscription plans. + """ + + waf_add_on: Optional[Money] + """ + Cost of activating WAF add-on (where subscription plan does not include WAF). + """ + + total_cost: Optional[Money] + """ + Total cost to date (this month) of all Edge Services resources including active subscription plan, previously active plans, extra pipelines and extra egress cache data. + """ + + +@dataclass +class GetCacheStageRequest: + cache_stage_id: str + """ + ID of the requested cache stage. + """ + + +@dataclass +class GetCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class GetDNSStageRequest: + dns_stage_id: str + """ + ID of the requested DNS stage. + """ + + +@dataclass +class GetPipelineRequest: + pipeline_id: str + """ + ID of the requested pipeline. + """ + + +@dataclass +class GetPurgeRequestRequest: + purge_request_id: str + """ + ID of the requested purge request. + """ + + +@dataclass +class GetRouteStageRequest: + route_stage_id: str + """ + ID of the requested route stage. + """ + + +@dataclass +class GetTLSStageRequest: + tls_stage_id: str + """ + ID of the requested TLS stage. + """ + + +@dataclass +class GetWafStageRequest: + waf_stage_id: str + """ + ID of the requested WAF stage. + """ + + +@dataclass +class HeadStageResponse: + head_stage: Optional[HeadStageResponseHeadStage] + """ + Modified or created head stage. + """ + + +@dataclass +class ListBackendStagesRequest: + order_by: Optional[ListBackendStagesRequestOrderBy] + """ + Sort order of backend stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of backend stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + """ + + bucket_name: Optional[str] + """ + Bucket name to filter for. Only backend stages from this Bucket will be returned. + """ + + bucket_region: Optional[str] + """ + Bucket region to filter for. Only backend stages with buckets in this region will be returned. + """ + + lb_id: Optional[str] + """ + Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + """ + + +@dataclass +class ListBackendStagesResponse: + stages: List[BackendStage] + """ + Paginated list of backend stages. + """ + + total_count: int + """ + Count of all backend stages matching the requested criteria. + """ + + +@dataclass +class ListCacheStagesRequest: + order_by: Optional[ListCacheStagesRequestOrderBy] + """ + Sort order of cache stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of cache stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + """ + + +@dataclass +class ListCacheStagesResponse: + stages: List[CacheStage] + """ + Paginated list of cache stages. + """ + + total_count: int + """ + Count of all cache stages matching the requested criteria. + """ + + +@dataclass +class ListDNSStagesRequest: + order_by: Optional[ListDNSStagesRequestOrderBy] + """ + Sort order of DNS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of DNS stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + """ + + fqdn: Optional[str] + """ + Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + """ + + +@dataclass +class ListDNSStagesResponse: + stages: List[DNSStage] + """ + Paginated list of DNS stages. + """ + + total_count: int + """ + Count of all DNS stages matching the requested criteria. + """ + + +@dataclass +class ListHeadStagesRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of head stages to return per page. + """ + + +@dataclass +class ListHeadStagesResponse: + head_stages: List[ListHeadStagesResponseHeadStage] + """ + Number of head stages to return per page. + """ + + total_count: int + """ + Count of all head stages matching the requested pipeline_id. + """ + + +@dataclass +class ListPipelinesRequest: + order_by: Optional[ListPipelinesRequestOrderBy] + """ + Sort order of pipelines in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of pipelines to return per page. + """ + + name: Optional[str] + """ + Pipeline name to filter for. Only pipelines with this string within their name will be returned. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only pipelines from this Organization will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only pipelines from this Project will be returned. + """ + + has_backend_stage_lb: Optional[bool] + """ + Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + """ + + +@dataclass +class ListPipelinesResponse: + pipelines: List[Pipeline] + """ + Paginated list of pipelines. + """ + + total_count: int + """ + Count of all pipelines matching the requested criteria. + """ + + +@dataclass +class ListPipelinesWithStagesRequest: + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + name: Optional[str] + + organization_id: Optional[str] + + project_id: Optional[str] + + +@dataclass +class ListPipelinesWithStagesResponse: + pipelines: List[PipelineStages] + + total_count: int + + +@dataclass +class ListPlansResponse: + total_count: int + + plans: List[PlanDetails] + + +@dataclass +class ListPurgeRequestsRequest: + order_by: Optional[ListPurgeRequestsRequestOrderBy] + """ + Sort order of purge requests in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of purge requests to return per page. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only purge requests from this Project will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only purge requests from this Project will be returned. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + """ + + +@dataclass +class ListPurgeRequestsResponse: + purge_requests: List[PurgeRequest] + """ + Paginated list of purge requests. + """ + + total_count: int + """ + Count of all purge requests matching the requested criteria. + """ + + +@dataclass +class ListRouteRulesRequest: + route_stage_id: str + """ + Route stage ID to filter for. Only route rules from this route stage will be returned. + """ + + +@dataclass +class ListRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class ListRouteStagesRequest: + order_by: Optional[ListRouteStagesRequestOrderBy] + """ + Sort order of route stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of route stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only route stages from this pipeline will be returned. + """ + + +@dataclass +class ListRouteStagesResponse: + stages: List[RouteStage] + """ + Paginated list of summarized route stages. + """ + + total_count: int + """ + Count of all route stages matching the requested criteria. + """ + + +@dataclass +class ListTLSStagesRequest: + order_by: Optional[ListTLSStagesRequestOrderBy] + """ + Sort order of TLS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of TLS stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + """ + + secret_id: Optional[str] + """ + Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + """ + + secret_region: Optional[str] + """ + Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + """ + + +@dataclass +class ListTLSStagesResponse: + stages: List[TLSStage] + """ + Paginated list of TLS stages. + """ + + total_count: int + """ + Count of all TLS stages matching the requested criteria. + """ + + +@dataclass +class ListWafStagesRequest: + order_by: Optional[ListWafStagesRequestOrderBy] + """ + Sort order of WAF stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of WAF stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + """ + + +@dataclass +class ListWafStagesResponse: + stages: List[WafStage] + """ + Paginated list of WAF stages. + """ + + total_count: int + """ + Count of all WAF stages matching the requested criteria. + """ + + +@dataclass +class Plan: + plan_name: PlanName + + +@dataclass +class SearchBackendStagesRequest: + order_by: Optional[SearchBackendStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + project_id: Optional[str] + + bucket_name: Optional[str] + + bucket_region: Optional[str] + + lb_id: Optional[str] + + +@dataclass +class SelectPlanRequest: + project_id: Optional[str] + + plan_name: Optional[PlanName] + + +@dataclass +class SetHeadStageRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + add_new_head_stage: Optional[SetHeadStageRequestAddNewHeadStage] + + remove_head_stage: Optional[SetHeadStageRequestRemoveHeadStage] + + swap_head_stage: Optional[SetHeadStageRequestSwapHeadStage] + + +@dataclass +class SetRouteRulesRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class SetRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class UpdateBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to update. + """ + + pipeline_id: str + """ + Pipeline ID the Backend stage belongs to. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class UpdateCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to update. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class UpdateDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to update. + """ + + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class UpdatePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + name: Optional[str] + """ + Name of the pipeline. + """ + + description: Optional[str] + """ + Description of the pipeline. + """ + + +@dataclass +class UpdateRouteStageRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class UpdateTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to update. + """ + + tls_secrets_config: Optional[TLSSecretsConfig] + """ + Secret (from Scaleway Secret-Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + route_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + +@dataclass +class UpdateWafStageRequest: + waf_stage_id: str + """ + ID of the WAF stage to update. + """ + + mode: Optional[WafStageMode] + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + paranoia_level: Optional[int] + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + backend_stage_id: Optional[str] From 946c57abde1a97fee3b594adb66f2c792437ede4 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 27 Feb 2025 17:26:43 +0100 Subject: [PATCH 36/73] feat(block): add support for v1 (#876) --- .../scaleway_async/block/v1/__init__.py | 75 ++ scaleway-async/scaleway_async/block/v1/api.py | 837 ++++++++++++++++++ .../scaleway_async/block/v1/content.py | 36 + .../scaleway_async/block/v1/marshalling.py | 521 +++++++++++ .../scaleway_async/block/v1/types.py | 731 +++++++++++++++ scaleway/scaleway/block/v1/__init__.py | 75 ++ scaleway/scaleway/block/v1/api.py | 835 +++++++++++++++++ scaleway/scaleway/block/v1/content.py | 36 + scaleway/scaleway/block/v1/marshalling.py | 521 +++++++++++ scaleway/scaleway/block/v1/types.py | 731 +++++++++++++++ 10 files changed, 4398 insertions(+) create mode 100644 scaleway-async/scaleway_async/block/v1/__init__.py create mode 100644 scaleway-async/scaleway_async/block/v1/api.py create mode 100644 scaleway-async/scaleway_async/block/v1/content.py create mode 100644 scaleway-async/scaleway_async/block/v1/marshalling.py create mode 100644 scaleway-async/scaleway_async/block/v1/types.py create mode 100644 scaleway/scaleway/block/v1/__init__.py create mode 100644 scaleway/scaleway/block/v1/api.py create mode 100644 scaleway/scaleway/block/v1/content.py create mode 100644 scaleway/scaleway/block/v1/marshalling.py create mode 100644 scaleway/scaleway/block/v1/types.py diff --git a/scaleway-async/scaleway_async/block/v1/__init__.py b/scaleway-async/scaleway_async/block/v1/__init__.py new file mode 100644 index 000000000..1e48ec134 --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/__init__.py @@ -0,0 +1,75 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ListSnapshotsRequestOrderBy +from .types import ListVolumesRequestOrderBy +from .types import ReferenceStatus +from .content import REFERENCE_TRANSIENT_STATUSES +from .types import ReferenceType +from .types import SnapshotStatus +from .content import SNAPSHOT_TRANSIENT_STATUSES +from .types import StorageClass +from .types import VolumeStatus +from .content import VOLUME_TRANSIENT_STATUSES +from .types import Reference +from .types import SnapshotParentVolume +from .types import VolumeSpecifications +from .types import CreateVolumeRequestFromEmpty +from .types import CreateVolumeRequestFromSnapshot +from .types import Snapshot +from .types import VolumeType +from .types import Volume +from .types import CreateSnapshotRequest +from .types import CreateVolumeRequest +from .types import DeleteSnapshotRequest +from .types import DeleteVolumeRequest +from .types import ExportSnapshotToObjectStorageRequest +from .types import GetSnapshotRequest +from .types import GetVolumeRequest +from .types import ImportSnapshotFromObjectStorageRequest +from .types import ListSnapshotsRequest +from .types import ListSnapshotsResponse +from .types import ListVolumeTypesRequest +from .types import ListVolumeTypesResponse +from .types import ListVolumesRequest +from .types import ListVolumesResponse +from .types import UpdateSnapshotRequest +from .types import UpdateVolumeRequest +from .api import BlockV1API + +__all__ = [ + "ListSnapshotsRequestOrderBy", + "ListVolumesRequestOrderBy", + "ReferenceStatus", + "REFERENCE_TRANSIENT_STATUSES", + "ReferenceType", + "SnapshotStatus", + "SNAPSHOT_TRANSIENT_STATUSES", + "StorageClass", + "VolumeStatus", + "VOLUME_TRANSIENT_STATUSES", + "Reference", + "SnapshotParentVolume", + "VolumeSpecifications", + "CreateVolumeRequestFromEmpty", + "CreateVolumeRequestFromSnapshot", + "Snapshot", + "VolumeType", + "Volume", + "CreateSnapshotRequest", + "CreateVolumeRequest", + "DeleteSnapshotRequest", + "DeleteVolumeRequest", + "ExportSnapshotToObjectStorageRequest", + "GetSnapshotRequest", + "GetVolumeRequest", + "ImportSnapshotFromObjectStorageRequest", + "ListSnapshotsRequest", + "ListSnapshotsResponse", + "ListVolumeTypesRequest", + "ListVolumeTypesResponse", + "ListVolumesRequest", + "ListVolumesResponse", + "UpdateSnapshotRequest", + "UpdateVolumeRequest", + "BlockV1API", +] diff --git a/scaleway-async/scaleway_async/block/v1/api.py b/scaleway-async/scaleway_async/block/v1/api.py new file mode 100644 index 000000000..da4caa99d --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/api.py @@ -0,0 +1,837 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + ListSnapshotsRequestOrderBy, + ListVolumesRequestOrderBy, + CreateSnapshotRequest, + CreateVolumeRequest, + CreateVolumeRequestFromEmpty, + CreateVolumeRequestFromSnapshot, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + ListSnapshotsResponse, + ListVolumeTypesResponse, + ListVolumesResponse, + Snapshot, + UpdateSnapshotRequest, + UpdateVolumeRequest, + Volume, + VolumeType, +) +from .content import ( + SNAPSHOT_TRANSIENT_STATUSES, + VOLUME_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Snapshot, + unmarshal_Volume, + unmarshal_ListSnapshotsResponse, + unmarshal_ListVolumeTypesResponse, + unmarshal_ListVolumesResponse, + marshal_CreateSnapshotRequest, + marshal_CreateVolumeRequest, + marshal_ExportSnapshotToObjectStorageRequest, + marshal_ImportSnapshotFromObjectStorageRequest, + marshal_UpdateSnapshotRequest, + marshal_UpdateVolumeRequest, +) + + +class BlockV1API(API): + """ + This API allows you to manage your Block Storage volumes. + """ + + async def list_volume_types( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListVolumeTypesResponse: + """ + List volume types. + List all available volume types in a specified zone. The volume types listed are ordered by name in ascending order. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :return: :class:`ListVolumeTypesResponse ` + + Usage: + :: + + result = await api.list_volume_types() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volume-types", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVolumeTypesResponse(res.json()) + + async def list_volume_types_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[VolumeType]: + """ + List volume types. + List all available volume types in a specified zone. The volume types listed are ordered by name in ascending order. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :return: :class:`List[VolumeType] ` + + Usage: + :: + + result = await api.list_volume_types_all() + """ + + return await fetch_all_pages_async( + type=ListVolumeTypesResponse, + key="volume_types", + fetcher=self.list_volume_types, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + }, + ) + + async def list_volumes( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListVolumesRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListVolumesResponse: + """ + List volumes. + List all existing volumes in a specified zone. By default, the volumes listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param name: Filter the return volumes by their names. + :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. + :return: :class:`ListVolumesResponse ` + + Usage: + :: + + result = await api.list_volumes() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volumes", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "product_resource_id": product_resource_id, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVolumesResponse(res.json()) + + async def list_volumes_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListVolumesRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Volume]: + """ + List volumes. + List all existing volumes in a specified zone. By default, the volumes listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param name: Filter the return volumes by their names. + :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. + :return: :class:`List[Volume] ` + + Usage: + :: + + result = await api.list_volumes_all() + """ + + return await fetch_all_pages_async( + type=ListVolumesResponse, + key="volumes", + fetcher=self.list_volumes, + args={ + "zone": zone, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "page": page, + "page_size": page_size, + "name": name, + "product_resource_id": product_resource_id, + "tags": tags, + }, + ) + + async def create_volume( + self, + *, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + perf_iops: Optional[int] = None, + project_id: Optional[str] = None, + from_empty: Optional[CreateVolumeRequestFromEmpty] = None, + from_snapshot: Optional[CreateVolumeRequestFromSnapshot] = None, + tags: Optional[List[str]] = None, + ) -> Volume: + """ + Create a volume. + To create a new volume from scratch, you must specify `from_empty` and the `size`. + To create a volume from an existing snapshot, specify `from_snapshot` and the `snapshot_id` in the request payload instead, size is optional and can be specified if you need to extend the original size. The volume will take on the same volume class and underlying IOPS limitations as the original snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the volume. + :param perf_iops: The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). + One-Of ('requirements'): at most one of 'perf_iops' could be set. + :param project_id: UUID of the project the volume belongs to. + :param from_empty: Specify the size of the new volume if creating a new one from scratch. + One-Of ('from'): at most one of 'from_empty', 'from_snapshot' could be set. + :param from_snapshot: Specify the snapshot ID of the original snapshot. + One-Of ('from'): at most one of 'from_empty', 'from_snapshot' could be set. + :param tags: List of tags assigned to the volume. + :return: :class:`Volume ` + + Usage: + :: + + result = await api.create_volume() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/volumes", + body=marshal_CreateVolumeRequest( + CreateVolumeRequest( + zone=zone, + name=name or random_name(prefix="vol"), + project_id=project_id, + tags=tags, + from_empty=from_empty, + from_snapshot=from_snapshot, + perf_iops=perf_iops, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + async def get_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + ) -> Volume: + """ + Get a volume. + Retrieve technical information about a specific volume. Details such as size, type, and status are returned in the response. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Volume ` + + Usage: + :: + + result = await api.get_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + async def wait_for_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Volume, Union[bool, Awaitable[bool]]]] = None, + ) -> Volume: + """ + Get a volume. + Retrieve technical information about a specific volume. Details such as size, type, and status are returned in the response. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Volume ` + + Usage: + :: + + result = await api.get_volume( + volume_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in VOLUME_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_volume, + options=options, + args={ + "volume_id": volume_id, + "zone": zone, + }, + ) + + async def delete_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a detached volume. + You must specify the `volume_id` of the volume you want to delete. The volume must not be in the `in_use` status. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "DELETE", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + ) + + self._throw_on_error(res) + + async def update_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + size: Optional[int] = None, + tags: Optional[List[str]] = None, + perf_iops: Optional[int] = None, + ) -> Volume: + """ + Update a volume. + Update the technical details of a volume, such as its name, tags, or its new size and `volume_type` (within the same Block Storage class). + You can only resize a volume to a larger size. It is currently not possible to change your Block Storage Class. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: When defined, is the new name of the volume. + :param size: Size in bytes of the volume, with a granularity of 1 GB (10^9 bytes). + Must be compliant with the minimum (1GB) and maximum (10TB) allowed size. + :param tags: List of tags assigned to the volume. + :param perf_iops: The selected value must be available for the volume's current storage class. + :return: :class:`Volume ` + + Usage: + :: + + result = await api.update_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "PATCH", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + body=marshal_UpdateVolumeRequest( + UpdateVolumeRequest( + volume_id=volume_id, + zone=zone, + name=name, + size=size, + tags=tags, + perf_iops=perf_iops, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + async def list_snapshots( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + volume_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListSnapshotsResponse: + """ + List all snapshots. + List all available snapshots in a specified zone. By default, the snapshots listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param volume_id: Filter snapshots by the ID of the original volume. + :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. + :return: :class:`ListSnapshotsResponse ` + + Usage: + :: + + result = await api.list_snapshots() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/snapshots", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + "volume_id": volume_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSnapshotsResponse(res.json()) + + async def list_snapshots_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + volume_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Snapshot]: + """ + List all snapshots. + List all available snapshots in a specified zone. By default, the snapshots listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param volume_id: Filter snapshots by the ID of the original volume. + :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. + :return: :class:`List[Snapshot] ` + + Usage: + :: + + result = await api.list_snapshots_all() + """ + + return await fetch_all_pages_async( + type=ListSnapshotsResponse, + key="snapshots", + fetcher=self.list_snapshots, + args={ + "zone": zone, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "page": page, + "page_size": page_size, + "volume_id": volume_id, + "name": name, + "tags": tags, + }, + ) + + async def get_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Get a snapshot. + Retrieve technical information about a specific snapshot. Details such as size, volume type, and status are returned in the response. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.get_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def wait_for_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + options: Optional[ + WaitForOptions[Snapshot, Union[bool, Awaitable[bool]]] + ] = None, + ) -> Snapshot: + """ + Get a snapshot. + Retrieve technical information about a specific snapshot. Details such as size, volume type, and status are returned in the response. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.get_snapshot( + snapshot_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in SNAPSHOT_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_snapshot, + options=options, + args={ + "snapshot_id": snapshot_id, + "zone": zone, + }, + ) + + async def create_snapshot( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Snapshot: + """ + Create a snapshot of a volume. + To create a snapshot, the volume must be in the `in_use` or the `available` status. + If your volume is in a transient state, you need to wait until the end of the current operation. + :param volume_id: UUID of the volume to snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the snapshot. + :param project_id: UUID of the project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.create_snapshot( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots", + body=marshal_CreateSnapshotRequest( + CreateSnapshotRequest( + volume_id=volume_id, + zone=zone, + name=name or random_name(prefix="snp"), + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def import_snapshot_from_object_storage( + self, + *, + bucket: str, + key: str, + name: str, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + size: Optional[int] = None, + ) -> Snapshot: + """ + Import a snapshot from a Scaleway Object Storage bucket. + The bucket must contain a QCOW2 image. + The bucket can be imported into any Availability Zone as long as it is in the same region as the bucket. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param name: Name of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: UUID of the Project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :param size: Size of the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.import_snapshot_from_object_storage( + bucket="example", + key="example", + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots/import-from-object-storage", + body=marshal_ImportSnapshotFromObjectStorageRequest( + ImportSnapshotFromObjectStorageRequest( + bucket=bucket, + key=key, + name=name, + zone=zone, + project_id=project_id, + tags=tags, + size=size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def export_snapshot_to_object_storage( + self, + *, + snapshot_id: str, + bucket: str, + key: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Export a snapshot to a Scaleway Object Storage bucket. + The snapshot is exported in QCOW2 format. + The snapshot must not be in transient state. + :param snapshot_id: UUID of the snapshot. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.export_snapshot_to_object_storage( + snapshot_id="example", + bucket="example", + key="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}/export-to-object-storage", + body=marshal_ExportSnapshotToObjectStorageRequest( + ExportSnapshotToObjectStorageRequest( + snapshot_id=snapshot_id, + bucket=bucket, + key=key, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def delete_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a snapshot. + You must specify the `snapshot_id` of the snapshot you want to delete. The snapshot must not be in use. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "DELETE", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + + async def update_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Snapshot: + """ + Update a snapshot. + Update the name or tags of the snapshot. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: When defined, is the name of the snapshot. + :param tags: List of tags assigned to the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.update_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "PATCH", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + body=marshal_UpdateSnapshotRequest( + UpdateSnapshotRequest( + snapshot_id=snapshot_id, + zone=zone, + name=name, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) diff --git a/scaleway-async/scaleway_async/block/v1/content.py b/scaleway-async/scaleway_async/block/v1/content.py new file mode 100644 index 000000000..a6cf1ee67 --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/content.py @@ -0,0 +1,36 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + ReferenceStatus, + SnapshotStatus, + VolumeStatus, +) + +REFERENCE_TRANSIENT_STATUSES: List[ReferenceStatus] = [ + ReferenceStatus.ATTACHING, + ReferenceStatus.DETACHING, + ReferenceStatus.CREATING, +] +""" +Lists transient statutes of the enum :class:`ReferenceStatus `. +""" +SNAPSHOT_TRANSIENT_STATUSES: List[SnapshotStatus] = [ + SnapshotStatus.CREATING, + SnapshotStatus.DELETING, + SnapshotStatus.EXPORTING, +] +""" +Lists transient statutes of the enum :class:`SnapshotStatus `. +""" +VOLUME_TRANSIENT_STATUSES: List[VolumeStatus] = [ + VolumeStatus.CREATING, + VolumeStatus.DELETING, + VolumeStatus.RESIZING, + VolumeStatus.SNAPSHOTTING, + VolumeStatus.UPDATING, +] +""" +Lists transient statutes of the enum :class:`VolumeStatus `. +""" diff --git a/scaleway-async/scaleway_async/block/v1/marshalling.py b/scaleway-async/scaleway_async/block/v1/marshalling.py new file mode 100644 index 000000000..d1aef6680 --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/marshalling.py @@ -0,0 +1,521 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + Reference, + SnapshotParentVolume, + Snapshot, + VolumeSpecifications, + Volume, + ListSnapshotsResponse, + VolumeType, + ListVolumeTypesResponse, + ListVolumesResponse, + CreateSnapshotRequest, + CreateVolumeRequestFromEmpty, + CreateVolumeRequestFromSnapshot, + CreateVolumeRequest, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + UpdateSnapshotRequest, + UpdateVolumeRequest, +) + + +def unmarshal_Reference(data: Any) -> Reference: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Reference' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("product_resource_type", None) + if field is not None: + args["product_resource_type"] = field + + field = data.get("product_resource_id", None) + if field is not None: + args["product_resource_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return Reference(**args) + + +def unmarshal_SnapshotParentVolume(data: Any) -> SnapshotParentVolume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SnapshotParentVolume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + return SnapshotParentVolume(**args) + + +def unmarshal_Snapshot(data: Any) -> Snapshot: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Snapshot' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("references", None) + if field is not None: + args["references"] = ( + [unmarshal_Reference(v) for v in field] if field is not None else None + ) + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("class", None) + if field is not None: + args["class_"] = field + + field = data.get("parent_volume", None) + if field is not None: + args["parent_volume"] = unmarshal_SnapshotParentVolume(field) + else: + args["parent_volume"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Snapshot(**args) + + +def unmarshal_VolumeSpecifications(data: Any) -> VolumeSpecifications: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeSpecifications' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("class", None) + if field is not None: + args["class_"] = field + + field = data.get("perf_iops", None) + if field is not None: + args["perf_iops"] = field + else: + args["perf_iops"] = None + + return VolumeSpecifications(**args) + + +def unmarshal_Volume(data: Any) -> Volume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Volume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("references", None) + if field is not None: + args["references"] = ( + [unmarshal_Reference(v) for v in field] if field is not None else None + ) + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("parent_snapshot_id", None) + if field is not None: + args["parent_snapshot_id"] = field + else: + args["parent_snapshot_id"] = None + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("specs", None) + if field is not None: + args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None + + field = data.get("last_detached_at", None) + if field is not None: + args["last_detached_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["last_detached_at"] = None + + return Volume(**args) + + +def unmarshal_ListSnapshotsResponse(data: Any) -> ListSnapshotsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSnapshotsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("snapshots", None) + if field is not None: + args["snapshots"] = ( + [unmarshal_Snapshot(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSnapshotsResponse(**args) + + +def unmarshal_VolumeType(data: Any) -> VolumeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("pricing", None) + if field is not None: + args["pricing"] = unmarshal_Money(field) + else: + args["pricing"] = None + + field = data.get("snapshot_pricing", None) + if field is not None: + args["snapshot_pricing"] = unmarshal_Money(field) + else: + args["snapshot_pricing"] = None + + field = data.get("specs", None) + if field is not None: + args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None + + return VolumeType(**args) + + +def unmarshal_ListVolumeTypesResponse(data: Any) -> ListVolumeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVolumeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("volume_types", None) + if field is not None: + args["volume_types"] = ( + [unmarshal_VolumeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVolumeTypesResponse(**args) + + +def unmarshal_ListVolumesResponse(data: Any) -> ListVolumesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVolumesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("volumes", None) + if field is not None: + args["volumes"] = ( + [unmarshal_Volume(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVolumesResponse(**args) + + +def marshal_CreateSnapshotRequest( + request: CreateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.volume_id is not None: + output["volume_id"] = request.volume_id + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_CreateVolumeRequestFromEmpty( + request: CreateVolumeRequestFromEmpty, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_CreateVolumeRequestFromSnapshot( + request: CreateVolumeRequestFromSnapshot, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.snapshot_id is not None: + output["snapshot_id"] = request.snapshot_id + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_CreateVolumeRequest( + request: CreateVolumeRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("from_empty", request.from_empty), + OneOfPossibility("from_snapshot", request.from_snapshot), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("perf_iops", request.perf_iops), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_ExportSnapshotToObjectStorageRequest( + request: ExportSnapshotToObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + return output + + +def marshal_ImportSnapshotFromObjectStorageRequest( + request: ImportSnapshotFromObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_UpdateSnapshotRequest( + request: UpdateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_UpdateVolumeRequest( + request: UpdateVolumeRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.size is not None: + output["size"] = request.size + + if request.tags is not None: + output["tags"] = request.tags + + if request.perf_iops is not None: + output["perf_iops"] = request.perf_iops + + return output diff --git a/scaleway-async/scaleway_async/block/v1/types.py b/scaleway-async/scaleway_async/block/v1/types.py new file mode 100644 index 000000000..d666ce94c --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/types.py @@ -0,0 +1,731 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Money, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ListSnapshotsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListVolumesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ReferenceStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + ATTACHING = "attaching" + ATTACHED = "attached" + DETACHING = "detaching" + DETACHED = "detached" + CREATING = "creating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class ReferenceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + LINK = "link" + EXCLUSIVE = "exclusive" + READ_ONLY = "read_only" + + def __str__(self) -> str: + return str(self.value) + + +class SnapshotStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + AVAILABLE = "available" + ERROR = "error" + DELETING = "deleting" + DELETED = "deleted" + IN_USE = "in_use" + LOCKED = "locked" + EXPORTING = "exporting" + + def __str__(self) -> str: + return str(self.value) + + +class StorageClass(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STORAGE_CLASS = "unknown_storage_class" + UNSPECIFIED = "unspecified" + BSSD = "bssd" + SBS = "sbs" + + def __str__(self) -> str: + return str(self.value) + + +class VolumeStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + AVAILABLE = "available" + IN_USE = "in_use" + DELETING = "deleting" + DELETED = "deleted" + RESIZING = "resizing" + ERROR = "error" + SNAPSHOTTING = "snapshotting" + LOCKED = "locked" + UPDATING = "updating" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class Reference: + id: str + """ + UUID of the reference. + """ + + product_resource_type: str + """ + Type of resource to which the reference is associated. + """ + + product_resource_id: str + """ + UUID of the product resource it refers to (according to the product_resource_type). + """ + + type_: ReferenceType + """ + Type of reference (link, exclusive, read_only). + """ + + status: ReferenceStatus + """ + Status of the reference. Statuses include `attaching`, `attached`, and `detaching`. + """ + + created_at: Optional[datetime] + """ + Creation date of the reference. + """ + + +@dataclass +class SnapshotParentVolume: + id: str + """ + Parent volume UUID (volume from which the snapshot originates). + """ + + name: str + """ + Name of the parent volume. + """ + + type_: str + """ + Volume type of the parent volume. + """ + + status: VolumeStatus + """ + Current status the parent volume. + """ + + +@dataclass +class VolumeSpecifications: + class_: StorageClass + """ + The storage class of the volume. + """ + + perf_iops: Optional[int] + """ + The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). + """ + + +@dataclass +class CreateVolumeRequestFromEmpty: + size: int + """ + Must be compliant with the minimum (1 GB) and maximum (10 TB) allowed size. + """ + + +@dataclass +class CreateVolumeRequestFromSnapshot: + snapshot_id: str + """ + Source snapshot from which volume will be created. + """ + + size: Optional[int] + """ + Must be compliant with the minimum (1 GB) and maximum (10 TB) allowed size. +Size is optional and is used only if a resize of the volume is requested, otherwise original snapshot size will be used. + """ + + +@dataclass +class Snapshot: + id: str + """ + UUID of the snapshot. + """ + + name: str + """ + Name of the snapshot. + """ + + size: int + """ + Size in bytes of the snapshot. + """ + + project_id: str + """ + UUID of the project the snapshot belongs to. + """ + + references: List[Reference] + """ + List of the references to the snapshot. + """ + + status: SnapshotStatus + """ + Current status of the snapshot (available, in_use, ...). + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + zone: ScwZone + """ + Snapshot zone. + """ + + class_: StorageClass + """ + Storage class of the snapshot. + """ + + parent_volume: Optional[SnapshotParentVolume] + """ + If the parent volume was deleted, value is null. + """ + + created_at: Optional[datetime] + """ + Creation date of the snapshot. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the properties of a snapshot. + """ + + +@dataclass +class VolumeType: + type_: str + """ + Volume type. + """ + + pricing: Optional[Money] + """ + Price of the volume billed in GB/hour. + """ + + snapshot_pricing: Optional[Money] + """ + Price of the snapshot billed in GB/hour. + """ + + specs: Optional[VolumeSpecifications] + """ + Volume specifications of the volume type. + """ + + +@dataclass +class Volume: + id: str + """ + UUID of the volume. + """ + + name: str + """ + Name of the volume. + """ + + type_: str + """ + Volume type. + """ + + size: int + """ + Volume size in bytes. + """ + + project_id: str + """ + UUID of the project to which the volume belongs. + """ + + references: List[Reference] + """ + List of the references to the volume. + """ + + created_at: Optional[datetime] + """ + Creation date of the volume. + """ + + updated_at: Optional[datetime] + """ + Last update of the properties of a volume. + """ + + parent_snapshot_id: Optional[str] + """ + When a volume is created from a snapshot, is the UUID of the snapshot from which the volume has been created. + """ + + status: VolumeStatus + """ + Current status of the volume (available, in_use, ...). + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + zone: ScwZone + """ + Volume zone. + """ + + specs: Optional[VolumeSpecifications] + """ + Specifications of the volume. + """ + + last_detached_at: Optional[datetime] + """ + Last time the volume was detached. + """ + + +@dataclass +class CreateSnapshotRequest: + volume_id: str + """ + UUID of the volume to snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of the snapshot. + """ + + project_id: Optional[str] + """ + UUID of the project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + +@dataclass +class CreateVolumeRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of the volume. + """ + + project_id: Optional[str] + """ + UUID of the project the volume belongs to. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the volume. + """ + + from_empty: Optional[CreateVolumeRequestFromEmpty] + + from_snapshot: Optional[CreateVolumeRequestFromSnapshot] + + perf_iops: Optional[int] + + +@dataclass +class DeleteSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ExportSnapshotToObjectStorageRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ImportSnapshotFromObjectStorageRequest: + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + name: str + """ + Name of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + UUID of the Project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + size: Optional[int] + """ + Size of the snapshot. + """ + + +@dataclass +class ListSnapshotsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListSnapshotsRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + volume_id: Optional[str] + """ + Filter snapshots by the ID of the original volume. + """ + + name: Optional[str] + """ + Filter snapshots by their names. + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only snapshots with one or more matching tags will be returned. + """ + + +@dataclass +class ListSnapshotsResponse: + snapshots: List[Snapshot] + """ + Paginated returned list of snapshots. + """ + + total_count: int + """ + Total number of snpashots in the project. + """ + + +@dataclass +class ListVolumeTypesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + +@dataclass +class ListVolumeTypesResponse: + volume_types: List[VolumeType] + """ + Returns paginated list of volume-types. + """ + + total_count: int + """ + Total number of volume-types currently available in stock. + """ + + +@dataclass +class ListVolumesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListVolumesRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + name: Optional[str] + """ + Filter the return volumes by their names. + """ + + product_resource_id: Optional[str] + """ + Filter by a product resource ID linked to this volume (such as an Instance ID). + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only volumes with one or more matching tags will be returned. + """ + + +@dataclass +class ListVolumesResponse: + volumes: List[Volume] + """ + Paginated returned list of volumes. + """ + + total_count: int + """ + Total number of volumes in the project. + """ + + +@dataclass +class UpdateSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + When defined, is the name of the snapshot. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + +@dataclass +class UpdateVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + When defined, is the new name of the volume. + """ + + size: Optional[int] + """ + Size in bytes of the volume, with a granularity of 1 GB (10^9 bytes). +Must be compliant with the minimum (1GB) and maximum (10TB) allowed size. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the volume. + """ + + perf_iops: Optional[int] + """ + The selected value must be available for the volume's current storage class. + """ diff --git a/scaleway/scaleway/block/v1/__init__.py b/scaleway/scaleway/block/v1/__init__.py new file mode 100644 index 000000000..1e48ec134 --- /dev/null +++ b/scaleway/scaleway/block/v1/__init__.py @@ -0,0 +1,75 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ListSnapshotsRequestOrderBy +from .types import ListVolumesRequestOrderBy +from .types import ReferenceStatus +from .content import REFERENCE_TRANSIENT_STATUSES +from .types import ReferenceType +from .types import SnapshotStatus +from .content import SNAPSHOT_TRANSIENT_STATUSES +from .types import StorageClass +from .types import VolumeStatus +from .content import VOLUME_TRANSIENT_STATUSES +from .types import Reference +from .types import SnapshotParentVolume +from .types import VolumeSpecifications +from .types import CreateVolumeRequestFromEmpty +from .types import CreateVolumeRequestFromSnapshot +from .types import Snapshot +from .types import VolumeType +from .types import Volume +from .types import CreateSnapshotRequest +from .types import CreateVolumeRequest +from .types import DeleteSnapshotRequest +from .types import DeleteVolumeRequest +from .types import ExportSnapshotToObjectStorageRequest +from .types import GetSnapshotRequest +from .types import GetVolumeRequest +from .types import ImportSnapshotFromObjectStorageRequest +from .types import ListSnapshotsRequest +from .types import ListSnapshotsResponse +from .types import ListVolumeTypesRequest +from .types import ListVolumeTypesResponse +from .types import ListVolumesRequest +from .types import ListVolumesResponse +from .types import UpdateSnapshotRequest +from .types import UpdateVolumeRequest +from .api import BlockV1API + +__all__ = [ + "ListSnapshotsRequestOrderBy", + "ListVolumesRequestOrderBy", + "ReferenceStatus", + "REFERENCE_TRANSIENT_STATUSES", + "ReferenceType", + "SnapshotStatus", + "SNAPSHOT_TRANSIENT_STATUSES", + "StorageClass", + "VolumeStatus", + "VOLUME_TRANSIENT_STATUSES", + "Reference", + "SnapshotParentVolume", + "VolumeSpecifications", + "CreateVolumeRequestFromEmpty", + "CreateVolumeRequestFromSnapshot", + "Snapshot", + "VolumeType", + "Volume", + "CreateSnapshotRequest", + "CreateVolumeRequest", + "DeleteSnapshotRequest", + "DeleteVolumeRequest", + "ExportSnapshotToObjectStorageRequest", + "GetSnapshotRequest", + "GetVolumeRequest", + "ImportSnapshotFromObjectStorageRequest", + "ListSnapshotsRequest", + "ListSnapshotsResponse", + "ListVolumeTypesRequest", + "ListVolumeTypesResponse", + "ListVolumesRequest", + "ListVolumesResponse", + "UpdateSnapshotRequest", + "UpdateVolumeRequest", + "BlockV1API", +] diff --git a/scaleway/scaleway/block/v1/api.py b/scaleway/scaleway/block/v1/api.py new file mode 100644 index 000000000..508e9d164 --- /dev/null +++ b/scaleway/scaleway/block/v1/api.py @@ -0,0 +1,835 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + ListSnapshotsRequestOrderBy, + ListVolumesRequestOrderBy, + CreateSnapshotRequest, + CreateVolumeRequest, + CreateVolumeRequestFromEmpty, + CreateVolumeRequestFromSnapshot, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + ListSnapshotsResponse, + ListVolumeTypesResponse, + ListVolumesResponse, + Snapshot, + UpdateSnapshotRequest, + UpdateVolumeRequest, + Volume, + VolumeType, +) +from .content import ( + SNAPSHOT_TRANSIENT_STATUSES, + VOLUME_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Snapshot, + unmarshal_Volume, + unmarshal_ListSnapshotsResponse, + unmarshal_ListVolumeTypesResponse, + unmarshal_ListVolumesResponse, + marshal_CreateSnapshotRequest, + marshal_CreateVolumeRequest, + marshal_ExportSnapshotToObjectStorageRequest, + marshal_ImportSnapshotFromObjectStorageRequest, + marshal_UpdateSnapshotRequest, + marshal_UpdateVolumeRequest, +) + + +class BlockV1API(API): + """ + This API allows you to manage your Block Storage volumes. + """ + + def list_volume_types( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListVolumeTypesResponse: + """ + List volume types. + List all available volume types in a specified zone. The volume types listed are ordered by name in ascending order. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :return: :class:`ListVolumeTypesResponse ` + + Usage: + :: + + result = api.list_volume_types() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volume-types", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVolumeTypesResponse(res.json()) + + def list_volume_types_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[VolumeType]: + """ + List volume types. + List all available volume types in a specified zone. The volume types listed are ordered by name in ascending order. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :return: :class:`List[VolumeType] ` + + Usage: + :: + + result = api.list_volume_types_all() + """ + + return fetch_all_pages( + type=ListVolumeTypesResponse, + key="volume_types", + fetcher=self.list_volume_types, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + }, + ) + + def list_volumes( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListVolumesRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListVolumesResponse: + """ + List volumes. + List all existing volumes in a specified zone. By default, the volumes listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param name: Filter the return volumes by their names. + :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. + :return: :class:`ListVolumesResponse ` + + Usage: + :: + + result = api.list_volumes() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volumes", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "product_resource_id": product_resource_id, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVolumesResponse(res.json()) + + def list_volumes_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListVolumesRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Volume]: + """ + List volumes. + List all existing volumes in a specified zone. By default, the volumes listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param name: Filter the return volumes by their names. + :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. + :return: :class:`List[Volume] ` + + Usage: + :: + + result = api.list_volumes_all() + """ + + return fetch_all_pages( + type=ListVolumesResponse, + key="volumes", + fetcher=self.list_volumes, + args={ + "zone": zone, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "page": page, + "page_size": page_size, + "name": name, + "product_resource_id": product_resource_id, + "tags": tags, + }, + ) + + def create_volume( + self, + *, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + perf_iops: Optional[int] = None, + project_id: Optional[str] = None, + from_empty: Optional[CreateVolumeRequestFromEmpty] = None, + from_snapshot: Optional[CreateVolumeRequestFromSnapshot] = None, + tags: Optional[List[str]] = None, + ) -> Volume: + """ + Create a volume. + To create a new volume from scratch, you must specify `from_empty` and the `size`. + To create a volume from an existing snapshot, specify `from_snapshot` and the `snapshot_id` in the request payload instead, size is optional and can be specified if you need to extend the original size. The volume will take on the same volume class and underlying IOPS limitations as the original snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the volume. + :param perf_iops: The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). + One-Of ('requirements'): at most one of 'perf_iops' could be set. + :param project_id: UUID of the project the volume belongs to. + :param from_empty: Specify the size of the new volume if creating a new one from scratch. + One-Of ('from'): at most one of 'from_empty', 'from_snapshot' could be set. + :param from_snapshot: Specify the snapshot ID of the original snapshot. + One-Of ('from'): at most one of 'from_empty', 'from_snapshot' could be set. + :param tags: List of tags assigned to the volume. + :return: :class:`Volume ` + + Usage: + :: + + result = api.create_volume() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/volumes", + body=marshal_CreateVolumeRequest( + CreateVolumeRequest( + zone=zone, + name=name or random_name(prefix="vol"), + project_id=project_id, + tags=tags, + from_empty=from_empty, + from_snapshot=from_snapshot, + perf_iops=perf_iops, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + def get_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + ) -> Volume: + """ + Get a volume. + Retrieve technical information about a specific volume. Details such as size, type, and status are returned in the response. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Volume ` + + Usage: + :: + + result = api.get_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + def wait_for_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Volume, bool]] = None, + ) -> Volume: + """ + Get a volume. + Retrieve technical information about a specific volume. Details such as size, type, and status are returned in the response. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Volume ` + + Usage: + :: + + result = api.get_volume( + volume_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in VOLUME_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_volume, + options=options, + args={ + "volume_id": volume_id, + "zone": zone, + }, + ) + + def delete_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a detached volume. + You must specify the `volume_id` of the volume you want to delete. The volume must not be in the `in_use` status. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "DELETE", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + ) + + self._throw_on_error(res) + + def update_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + size: Optional[int] = None, + tags: Optional[List[str]] = None, + perf_iops: Optional[int] = None, + ) -> Volume: + """ + Update a volume. + Update the technical details of a volume, such as its name, tags, or its new size and `volume_type` (within the same Block Storage class). + You can only resize a volume to a larger size. It is currently not possible to change your Block Storage Class. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: When defined, is the new name of the volume. + :param size: Size in bytes of the volume, with a granularity of 1 GB (10^9 bytes). + Must be compliant with the minimum (1GB) and maximum (10TB) allowed size. + :param tags: List of tags assigned to the volume. + :param perf_iops: The selected value must be available for the volume's current storage class. + :return: :class:`Volume ` + + Usage: + :: + + result = api.update_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "PATCH", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + body=marshal_UpdateVolumeRequest( + UpdateVolumeRequest( + volume_id=volume_id, + zone=zone, + name=name, + size=size, + tags=tags, + perf_iops=perf_iops, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + def list_snapshots( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + volume_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListSnapshotsResponse: + """ + List all snapshots. + List all available snapshots in a specified zone. By default, the snapshots listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param volume_id: Filter snapshots by the ID of the original volume. + :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. + :return: :class:`ListSnapshotsResponse ` + + Usage: + :: + + result = api.list_snapshots() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/snapshots", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + "volume_id": volume_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSnapshotsResponse(res.json()) + + def list_snapshots_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + volume_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Snapshot]: + """ + List all snapshots. + List all available snapshots in a specified zone. By default, the snapshots listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param volume_id: Filter snapshots by the ID of the original volume. + :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. + :return: :class:`List[Snapshot] ` + + Usage: + :: + + result = api.list_snapshots_all() + """ + + return fetch_all_pages( + type=ListSnapshotsResponse, + key="snapshots", + fetcher=self.list_snapshots, + args={ + "zone": zone, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "page": page, + "page_size": page_size, + "volume_id": volume_id, + "name": name, + "tags": tags, + }, + ) + + def get_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Get a snapshot. + Retrieve technical information about a specific snapshot. Details such as size, volume type, and status are returned in the response. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.get_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def wait_for_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Snapshot, bool]] = None, + ) -> Snapshot: + """ + Get a snapshot. + Retrieve technical information about a specific snapshot. Details such as size, volume type, and status are returned in the response. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.get_snapshot( + snapshot_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in SNAPSHOT_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_snapshot, + options=options, + args={ + "snapshot_id": snapshot_id, + "zone": zone, + }, + ) + + def create_snapshot( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Snapshot: + """ + Create a snapshot of a volume. + To create a snapshot, the volume must be in the `in_use` or the `available` status. + If your volume is in a transient state, you need to wait until the end of the current operation. + :param volume_id: UUID of the volume to snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the snapshot. + :param project_id: UUID of the project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.create_snapshot( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots", + body=marshal_CreateSnapshotRequest( + CreateSnapshotRequest( + volume_id=volume_id, + zone=zone, + name=name or random_name(prefix="snp"), + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def import_snapshot_from_object_storage( + self, + *, + bucket: str, + key: str, + name: str, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + size: Optional[int] = None, + ) -> Snapshot: + """ + Import a snapshot from a Scaleway Object Storage bucket. + The bucket must contain a QCOW2 image. + The bucket can be imported into any Availability Zone as long as it is in the same region as the bucket. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param name: Name of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: UUID of the Project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :param size: Size of the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.import_snapshot_from_object_storage( + bucket="example", + key="example", + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots/import-from-object-storage", + body=marshal_ImportSnapshotFromObjectStorageRequest( + ImportSnapshotFromObjectStorageRequest( + bucket=bucket, + key=key, + name=name, + zone=zone, + project_id=project_id, + tags=tags, + size=size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def export_snapshot_to_object_storage( + self, + *, + snapshot_id: str, + bucket: str, + key: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Export a snapshot to a Scaleway Object Storage bucket. + The snapshot is exported in QCOW2 format. + The snapshot must not be in transient state. + :param snapshot_id: UUID of the snapshot. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.export_snapshot_to_object_storage( + snapshot_id="example", + bucket="example", + key="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}/export-to-object-storage", + body=marshal_ExportSnapshotToObjectStorageRequest( + ExportSnapshotToObjectStorageRequest( + snapshot_id=snapshot_id, + bucket=bucket, + key=key, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def delete_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a snapshot. + You must specify the `snapshot_id` of the snapshot you want to delete. The snapshot must not be in use. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "DELETE", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + + def update_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Snapshot: + """ + Update a snapshot. + Update the name or tags of the snapshot. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: When defined, is the name of the snapshot. + :param tags: List of tags assigned to the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.update_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "PATCH", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + body=marshal_UpdateSnapshotRequest( + UpdateSnapshotRequest( + snapshot_id=snapshot_id, + zone=zone, + name=name, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) diff --git a/scaleway/scaleway/block/v1/content.py b/scaleway/scaleway/block/v1/content.py new file mode 100644 index 000000000..a6cf1ee67 --- /dev/null +++ b/scaleway/scaleway/block/v1/content.py @@ -0,0 +1,36 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + ReferenceStatus, + SnapshotStatus, + VolumeStatus, +) + +REFERENCE_TRANSIENT_STATUSES: List[ReferenceStatus] = [ + ReferenceStatus.ATTACHING, + ReferenceStatus.DETACHING, + ReferenceStatus.CREATING, +] +""" +Lists transient statutes of the enum :class:`ReferenceStatus `. +""" +SNAPSHOT_TRANSIENT_STATUSES: List[SnapshotStatus] = [ + SnapshotStatus.CREATING, + SnapshotStatus.DELETING, + SnapshotStatus.EXPORTING, +] +""" +Lists transient statutes of the enum :class:`SnapshotStatus `. +""" +VOLUME_TRANSIENT_STATUSES: List[VolumeStatus] = [ + VolumeStatus.CREATING, + VolumeStatus.DELETING, + VolumeStatus.RESIZING, + VolumeStatus.SNAPSHOTTING, + VolumeStatus.UPDATING, +] +""" +Lists transient statutes of the enum :class:`VolumeStatus `. +""" diff --git a/scaleway/scaleway/block/v1/marshalling.py b/scaleway/scaleway/block/v1/marshalling.py new file mode 100644 index 000000000..d1aef6680 --- /dev/null +++ b/scaleway/scaleway/block/v1/marshalling.py @@ -0,0 +1,521 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + Reference, + SnapshotParentVolume, + Snapshot, + VolumeSpecifications, + Volume, + ListSnapshotsResponse, + VolumeType, + ListVolumeTypesResponse, + ListVolumesResponse, + CreateSnapshotRequest, + CreateVolumeRequestFromEmpty, + CreateVolumeRequestFromSnapshot, + CreateVolumeRequest, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + UpdateSnapshotRequest, + UpdateVolumeRequest, +) + + +def unmarshal_Reference(data: Any) -> Reference: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Reference' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("product_resource_type", None) + if field is not None: + args["product_resource_type"] = field + + field = data.get("product_resource_id", None) + if field is not None: + args["product_resource_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return Reference(**args) + + +def unmarshal_SnapshotParentVolume(data: Any) -> SnapshotParentVolume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SnapshotParentVolume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + return SnapshotParentVolume(**args) + + +def unmarshal_Snapshot(data: Any) -> Snapshot: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Snapshot' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("references", None) + if field is not None: + args["references"] = ( + [unmarshal_Reference(v) for v in field] if field is not None else None + ) + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("class", None) + if field is not None: + args["class_"] = field + + field = data.get("parent_volume", None) + if field is not None: + args["parent_volume"] = unmarshal_SnapshotParentVolume(field) + else: + args["parent_volume"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Snapshot(**args) + + +def unmarshal_VolumeSpecifications(data: Any) -> VolumeSpecifications: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeSpecifications' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("class", None) + if field is not None: + args["class_"] = field + + field = data.get("perf_iops", None) + if field is not None: + args["perf_iops"] = field + else: + args["perf_iops"] = None + + return VolumeSpecifications(**args) + + +def unmarshal_Volume(data: Any) -> Volume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Volume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("references", None) + if field is not None: + args["references"] = ( + [unmarshal_Reference(v) for v in field] if field is not None else None + ) + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("parent_snapshot_id", None) + if field is not None: + args["parent_snapshot_id"] = field + else: + args["parent_snapshot_id"] = None + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("specs", None) + if field is not None: + args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None + + field = data.get("last_detached_at", None) + if field is not None: + args["last_detached_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["last_detached_at"] = None + + return Volume(**args) + + +def unmarshal_ListSnapshotsResponse(data: Any) -> ListSnapshotsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSnapshotsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("snapshots", None) + if field is not None: + args["snapshots"] = ( + [unmarshal_Snapshot(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSnapshotsResponse(**args) + + +def unmarshal_VolumeType(data: Any) -> VolumeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("pricing", None) + if field is not None: + args["pricing"] = unmarshal_Money(field) + else: + args["pricing"] = None + + field = data.get("snapshot_pricing", None) + if field is not None: + args["snapshot_pricing"] = unmarshal_Money(field) + else: + args["snapshot_pricing"] = None + + field = data.get("specs", None) + if field is not None: + args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None + + return VolumeType(**args) + + +def unmarshal_ListVolumeTypesResponse(data: Any) -> ListVolumeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVolumeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("volume_types", None) + if field is not None: + args["volume_types"] = ( + [unmarshal_VolumeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVolumeTypesResponse(**args) + + +def unmarshal_ListVolumesResponse(data: Any) -> ListVolumesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVolumesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("volumes", None) + if field is not None: + args["volumes"] = ( + [unmarshal_Volume(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVolumesResponse(**args) + + +def marshal_CreateSnapshotRequest( + request: CreateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.volume_id is not None: + output["volume_id"] = request.volume_id + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_CreateVolumeRequestFromEmpty( + request: CreateVolumeRequestFromEmpty, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_CreateVolumeRequestFromSnapshot( + request: CreateVolumeRequestFromSnapshot, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.snapshot_id is not None: + output["snapshot_id"] = request.snapshot_id + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_CreateVolumeRequest( + request: CreateVolumeRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("from_empty", request.from_empty), + OneOfPossibility("from_snapshot", request.from_snapshot), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("perf_iops", request.perf_iops), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_ExportSnapshotToObjectStorageRequest( + request: ExportSnapshotToObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + return output + + +def marshal_ImportSnapshotFromObjectStorageRequest( + request: ImportSnapshotFromObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_UpdateSnapshotRequest( + request: UpdateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_UpdateVolumeRequest( + request: UpdateVolumeRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.size is not None: + output["size"] = request.size + + if request.tags is not None: + output["tags"] = request.tags + + if request.perf_iops is not None: + output["perf_iops"] = request.perf_iops + + return output diff --git a/scaleway/scaleway/block/v1/types.py b/scaleway/scaleway/block/v1/types.py new file mode 100644 index 000000000..d666ce94c --- /dev/null +++ b/scaleway/scaleway/block/v1/types.py @@ -0,0 +1,731 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Money, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ListSnapshotsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListVolumesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ReferenceStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + ATTACHING = "attaching" + ATTACHED = "attached" + DETACHING = "detaching" + DETACHED = "detached" + CREATING = "creating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class ReferenceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + LINK = "link" + EXCLUSIVE = "exclusive" + READ_ONLY = "read_only" + + def __str__(self) -> str: + return str(self.value) + + +class SnapshotStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + AVAILABLE = "available" + ERROR = "error" + DELETING = "deleting" + DELETED = "deleted" + IN_USE = "in_use" + LOCKED = "locked" + EXPORTING = "exporting" + + def __str__(self) -> str: + return str(self.value) + + +class StorageClass(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STORAGE_CLASS = "unknown_storage_class" + UNSPECIFIED = "unspecified" + BSSD = "bssd" + SBS = "sbs" + + def __str__(self) -> str: + return str(self.value) + + +class VolumeStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + AVAILABLE = "available" + IN_USE = "in_use" + DELETING = "deleting" + DELETED = "deleted" + RESIZING = "resizing" + ERROR = "error" + SNAPSHOTTING = "snapshotting" + LOCKED = "locked" + UPDATING = "updating" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class Reference: + id: str + """ + UUID of the reference. + """ + + product_resource_type: str + """ + Type of resource to which the reference is associated. + """ + + product_resource_id: str + """ + UUID of the product resource it refers to (according to the product_resource_type). + """ + + type_: ReferenceType + """ + Type of reference (link, exclusive, read_only). + """ + + status: ReferenceStatus + """ + Status of the reference. Statuses include `attaching`, `attached`, and `detaching`. + """ + + created_at: Optional[datetime] + """ + Creation date of the reference. + """ + + +@dataclass +class SnapshotParentVolume: + id: str + """ + Parent volume UUID (volume from which the snapshot originates). + """ + + name: str + """ + Name of the parent volume. + """ + + type_: str + """ + Volume type of the parent volume. + """ + + status: VolumeStatus + """ + Current status the parent volume. + """ + + +@dataclass +class VolumeSpecifications: + class_: StorageClass + """ + The storage class of the volume. + """ + + perf_iops: Optional[int] + """ + The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). + """ + + +@dataclass +class CreateVolumeRequestFromEmpty: + size: int + """ + Must be compliant with the minimum (1 GB) and maximum (10 TB) allowed size. + """ + + +@dataclass +class CreateVolumeRequestFromSnapshot: + snapshot_id: str + """ + Source snapshot from which volume will be created. + """ + + size: Optional[int] + """ + Must be compliant with the minimum (1 GB) and maximum (10 TB) allowed size. +Size is optional and is used only if a resize of the volume is requested, otherwise original snapshot size will be used. + """ + + +@dataclass +class Snapshot: + id: str + """ + UUID of the snapshot. + """ + + name: str + """ + Name of the snapshot. + """ + + size: int + """ + Size in bytes of the snapshot. + """ + + project_id: str + """ + UUID of the project the snapshot belongs to. + """ + + references: List[Reference] + """ + List of the references to the snapshot. + """ + + status: SnapshotStatus + """ + Current status of the snapshot (available, in_use, ...). + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + zone: ScwZone + """ + Snapshot zone. + """ + + class_: StorageClass + """ + Storage class of the snapshot. + """ + + parent_volume: Optional[SnapshotParentVolume] + """ + If the parent volume was deleted, value is null. + """ + + created_at: Optional[datetime] + """ + Creation date of the snapshot. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the properties of a snapshot. + """ + + +@dataclass +class VolumeType: + type_: str + """ + Volume type. + """ + + pricing: Optional[Money] + """ + Price of the volume billed in GB/hour. + """ + + snapshot_pricing: Optional[Money] + """ + Price of the snapshot billed in GB/hour. + """ + + specs: Optional[VolumeSpecifications] + """ + Volume specifications of the volume type. + """ + + +@dataclass +class Volume: + id: str + """ + UUID of the volume. + """ + + name: str + """ + Name of the volume. + """ + + type_: str + """ + Volume type. + """ + + size: int + """ + Volume size in bytes. + """ + + project_id: str + """ + UUID of the project to which the volume belongs. + """ + + references: List[Reference] + """ + List of the references to the volume. + """ + + created_at: Optional[datetime] + """ + Creation date of the volume. + """ + + updated_at: Optional[datetime] + """ + Last update of the properties of a volume. + """ + + parent_snapshot_id: Optional[str] + """ + When a volume is created from a snapshot, is the UUID of the snapshot from which the volume has been created. + """ + + status: VolumeStatus + """ + Current status of the volume (available, in_use, ...). + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + zone: ScwZone + """ + Volume zone. + """ + + specs: Optional[VolumeSpecifications] + """ + Specifications of the volume. + """ + + last_detached_at: Optional[datetime] + """ + Last time the volume was detached. + """ + + +@dataclass +class CreateSnapshotRequest: + volume_id: str + """ + UUID of the volume to snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of the snapshot. + """ + + project_id: Optional[str] + """ + UUID of the project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + +@dataclass +class CreateVolumeRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of the volume. + """ + + project_id: Optional[str] + """ + UUID of the project the volume belongs to. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the volume. + """ + + from_empty: Optional[CreateVolumeRequestFromEmpty] + + from_snapshot: Optional[CreateVolumeRequestFromSnapshot] + + perf_iops: Optional[int] + + +@dataclass +class DeleteSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ExportSnapshotToObjectStorageRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ImportSnapshotFromObjectStorageRequest: + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + name: str + """ + Name of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + UUID of the Project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + size: Optional[int] + """ + Size of the snapshot. + """ + + +@dataclass +class ListSnapshotsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListSnapshotsRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + volume_id: Optional[str] + """ + Filter snapshots by the ID of the original volume. + """ + + name: Optional[str] + """ + Filter snapshots by their names. + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only snapshots with one or more matching tags will be returned. + """ + + +@dataclass +class ListSnapshotsResponse: + snapshots: List[Snapshot] + """ + Paginated returned list of snapshots. + """ + + total_count: int + """ + Total number of snpashots in the project. + """ + + +@dataclass +class ListVolumeTypesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + +@dataclass +class ListVolumeTypesResponse: + volume_types: List[VolumeType] + """ + Returns paginated list of volume-types. + """ + + total_count: int + """ + Total number of volume-types currently available in stock. + """ + + +@dataclass +class ListVolumesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListVolumesRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + name: Optional[str] + """ + Filter the return volumes by their names. + """ + + product_resource_id: Optional[str] + """ + Filter by a product resource ID linked to this volume (such as an Instance ID). + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only volumes with one or more matching tags will be returned. + """ + + +@dataclass +class ListVolumesResponse: + volumes: List[Volume] + """ + Paginated returned list of volumes. + """ + + total_count: int + """ + Total number of volumes in the project. + """ + + +@dataclass +class UpdateSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + When defined, is the name of the snapshot. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + +@dataclass +class UpdateVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + When defined, is the new name of the volume. + """ + + size: Optional[int] + """ + Size in bytes of the volume, with a granularity of 1 GB (10^9 bytes). +Must be compliant with the minimum (1GB) and maximum (10TB) allowed size. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the volume. + """ + + perf_iops: Optional[int] + """ + The selected value must be available for the volume's current storage class. + """ From 14df9d27b5d1c8f195cdda63d06ae1e142a94b50 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Fri, 28 Feb 2025 17:27:40 +0100 Subject: [PATCH 37/73] feat(lb): add support for `match_subdomains` (#877) --- scaleway-async/scaleway_async/lb/v1/marshalling.py | 7 +++++++ scaleway-async/scaleway_async/lb/v1/types.py | 5 +++++ scaleway/scaleway/lb/v1/marshalling.py | 7 +++++++ scaleway/scaleway/lb/v1/types.py | 5 +++++ 4 files changed, 24 insertions(+) diff --git a/scaleway-async/scaleway_async/lb/v1/marshalling.py b/scaleway-async/scaleway_async/lb/v1/marshalling.py index 9a2e94fd0..73c9ae049 100644 --- a/scaleway-async/scaleway_async/lb/v1/marshalling.py +++ b/scaleway-async/scaleway_async/lb/v1/marshalling.py @@ -1112,6 +1112,10 @@ def unmarshal_RouteMatch(data: Any) -> RouteMatch: args: Dict[str, Any] = {} + field = data.get("match_subdomains", None) + if field is not None: + args["match_subdomains"] = field + field = data.get("sni", None) if field is not None: args["sni"] = field @@ -2036,6 +2040,9 @@ def marshal_RouteMatch( ), ) + if request.match_subdomains is not None: + output["match_subdomains"] = request.match_subdomains + return output diff --git a/scaleway-async/scaleway_async/lb/v1/types.py b/scaleway-async/scaleway_async/lb/v1/types.py index 51fadbc9c..f21a1befc 100644 --- a/scaleway-async/scaleway_async/lb/v1/types.py +++ b/scaleway-async/scaleway_async/lb/v1/types.py @@ -970,6 +970,11 @@ class PrivateNetworkStaticConfig: @dataclass class RouteMatch: + match_subdomains: bool + """ + If true, all subdomains will match. + """ + sni: Optional[str] host_header: Optional[str] diff --git a/scaleway/scaleway/lb/v1/marshalling.py b/scaleway/scaleway/lb/v1/marshalling.py index 9a2e94fd0..73c9ae049 100644 --- a/scaleway/scaleway/lb/v1/marshalling.py +++ b/scaleway/scaleway/lb/v1/marshalling.py @@ -1112,6 +1112,10 @@ def unmarshal_RouteMatch(data: Any) -> RouteMatch: args: Dict[str, Any] = {} + field = data.get("match_subdomains", None) + if field is not None: + args["match_subdomains"] = field + field = data.get("sni", None) if field is not None: args["sni"] = field @@ -2036,6 +2040,9 @@ def marshal_RouteMatch( ), ) + if request.match_subdomains is not None: + output["match_subdomains"] = request.match_subdomains + return output diff --git a/scaleway/scaleway/lb/v1/types.py b/scaleway/scaleway/lb/v1/types.py index 51fadbc9c..f21a1befc 100644 --- a/scaleway/scaleway/lb/v1/types.py +++ b/scaleway/scaleway/lb/v1/types.py @@ -970,6 +970,11 @@ class PrivateNetworkStaticConfig: @dataclass class RouteMatch: + match_subdomains: bool + """ + If true, all subdomains will match. + """ + sni: Optional[str] host_header: Optional[str] From 2aed8b064d76eb6fafa90521b3d44d1b88a15b27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 11:01:43 +0100 Subject: [PATCH 38/73] chore(deps-dev): bump mypy from 1.14.1 to 1.15.0 in /scaleway (#878) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scaleway/poetry.lock | 74 ++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/scaleway/poetry.lock b/scaleway/poetry.lock index 4becc0599..58f8b71bf 100644 --- a/scaleway/poetry.lock +++ b/scaleway/poetry.lock @@ -128,49 +128,43 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "mypy" -version = "1.14.1" +version = "1.15.0" description = "Optional static typing for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, - {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"}, - {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"}, - {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"}, - {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"}, - {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"}, - {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"}, - {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"}, - {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"}, - {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"}, - {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"}, - {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"}, - {file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"}, - {file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"}, - {file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"}, - {file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, + {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, + {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, + {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, + {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, + {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, + {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, + {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, + {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, + {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, + {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, + {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, + {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, ] [package.dependencies] From c188c995c9307e167111bf5d13e95475a1272863 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 10:02:06 +0000 Subject: [PATCH 39/73] chore(deps-dev): bump ruff from 0.9.4 to 0.9.9 in /scaleway (#879) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scaleway/poetry.lock | 40 ++++++++++++++++++++-------------------- scaleway/pyproject.toml | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/scaleway/poetry.lock b/scaleway/poetry.lock index 58f8b71bf..50256b85e 100644 --- a/scaleway/poetry.lock +++ b/scaleway/poetry.lock @@ -289,29 +289,29 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.9.4" +version = "0.9.9" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.9.4-py3-none-linux_armv6l.whl", hash = "sha256:64e73d25b954f71ff100bb70f39f1ee09e880728efb4250c632ceed4e4cdf706"}, - {file = "ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6ce6743ed64d9afab4fafeaea70d3631b4d4b28b592db21a5c2d1f0ef52934bf"}, - {file = "ruff-0.9.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54499fb08408e32b57360f6f9de7157a5fec24ad79cb3f42ef2c3f3f728dfe2b"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37c892540108314a6f01f105040b5106aeb829fa5fb0561d2dcaf71485021137"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de9edf2ce4b9ddf43fd93e20ef635a900e25f622f87ed6e3047a664d0e8f810e"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87c90c32357c74f11deb7fbb065126d91771b207bf9bfaaee01277ca59b574ec"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56acd6c694da3695a7461cc55775f3a409c3815ac467279dfa126061d84b314b"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0c93e7d47ed951b9394cf352d6695b31498e68fd5782d6cbc282425655f687a"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d4c8772670aecf037d1bf7a07c39106574d143b26cfe5ed1787d2f31e800214"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfc5f1d7afeda8d5d37660eeca6d389b142d7f2b5a1ab659d9214ebd0e025231"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:faa935fc00ae854d8b638c16a5f1ce881bc3f67446957dd6f2af440a5fc8526b"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6c634fc6f5a0ceae1ab3e13c58183978185d131a29c425e4eaa9f40afe1e6d6"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:433dedf6ddfdec7f1ac7575ec1eb9844fa60c4c8c2f8887a070672b8d353d34c"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d612dbd0f3a919a8cc1d12037168bfa536862066808960e0cc901404b77968f0"}, - {file = "ruff-0.9.4-py3-none-win32.whl", hash = "sha256:db1192ddda2200671f9ef61d9597fcef89d934f5d1705e571a93a67fb13a4402"}, - {file = "ruff-0.9.4-py3-none-win_amd64.whl", hash = "sha256:05bebf4cdbe3ef75430d26c375773978950bbf4ee3c95ccb5448940dc092408e"}, - {file = "ruff-0.9.4-py3-none-win_arm64.whl", hash = "sha256:585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41"}, - {file = "ruff-0.9.4.tar.gz", hash = "sha256:6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7"}, + {file = "ruff-0.9.9-py3-none-linux_armv6l.whl", hash = "sha256:628abb5ea10345e53dff55b167595a159d3e174d6720bf19761f5e467e68d367"}, + {file = "ruff-0.9.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6cd1428e834b35d7493354723543b28cc11dc14d1ce19b685f6e68e07c05ec7"}, + {file = "ruff-0.9.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5ee162652869120ad260670706f3cd36cd3f32b0c651f02b6da142652c54941d"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3aa0f6b75082c9be1ec5a1db78c6d4b02e2375c3068438241dc19c7c306cc61a"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:584cc66e89fb5f80f84b05133dd677a17cdd86901d6479712c96597a3f28e7fe"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf3369325761a35aba75cd5c55ba1b5eb17d772f12ab168fbfac54be85cf18c"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3403a53a32a90ce929aa2f758542aca9234befa133e29f4933dcef28a24317be"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18454e7fa4e4d72cffe28a37cf6a73cb2594f81ec9f4eca31a0aaa9ccdfb1590"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fadfe2c88724c9617339f62319ed40dcdadadf2888d5afb88bf3adee7b35bfb"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6df104d08c442a1aabcfd254279b8cc1e2cbf41a605aa3e26610ba1ec4acf0b0"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d7c62939daf5b2a15af48abbd23bea1efdd38c312d6e7c4cedf5a24e03207e17"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9494ba82a37a4b81b6a798076e4a3251c13243fc37967e998efe4cce58c8a8d1"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4efd7a96ed6d36ef011ae798bf794c5501a514be369296c672dab7921087fa57"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ab90a7944c5a1296f3ecb08d1cbf8c2da34c7e68114b1271a431a3ad30cb660e"}, + {file = "ruff-0.9.9-py3-none-win32.whl", hash = "sha256:6b4c376d929c25ecd6d87e182a230fa4377b8e5125a4ff52d506ee8c087153c1"}, + {file = "ruff-0.9.9-py3-none-win_amd64.whl", hash = "sha256:837982ea24091d4c1700ddb2f63b7070e5baec508e43b01de013dc7eff974ff1"}, + {file = "ruff-0.9.9-py3-none-win_arm64.whl", hash = "sha256:3ac78f127517209fe6d96ab00f3ba97cafe38718b23b1db3e96d8b2d39e37ddf"}, + {file = "ruff-0.9.9.tar.gz", hash = "sha256:0062ed13f22173e85f8f7056f9a24016e692efeea8704d1a5e8011b8aa850933"}, ] [[package]] @@ -415,4 +415,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = ">=3.10" -content-hash = "4f889abfd75a3d01edf436c44008a6e0adf7a5442f9fa02870e693751444211c" +content-hash = "1b578c9907f883acb2f89dddb57645028384aeefd8b4e8c483cfe8b2fde32fe4" diff --git a/scaleway/pyproject.toml b/scaleway/pyproject.toml index 5e70af020..9ecb0493a 100644 --- a/scaleway/pyproject.toml +++ b/scaleway/pyproject.toml @@ -28,7 +28,7 @@ scaleway-core = "*" [tool.poetry.group.dev.dependencies] scaleway-core = { path = "../scaleway-core", develop = true } -ruff = ">=0.5.0,<0.9.5" +ruff = ">=0.5.0,<0.9.10" mypy = "^1.5.1" [build-system] From 1b57ba2098a961a7d2567adc015fb5b460077a31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 10:02:22 +0000 Subject: [PATCH 40/73] chore(deps-dev): bump ruff from 0.9.4 to 0.9.9 in /scaleway-core (#880) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scaleway-core/poetry.lock | 40 ++++++++++++++++++------------------ scaleway-core/pyproject.toml | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/scaleway-core/poetry.lock b/scaleway-core/poetry.lock index b78913605..ada26a736 100644 --- a/scaleway-core/poetry.lock +++ b/scaleway-core/poetry.lock @@ -295,29 +295,29 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.9.4" +version = "0.9.9" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.9.4-py3-none-linux_armv6l.whl", hash = "sha256:64e73d25b954f71ff100bb70f39f1ee09e880728efb4250c632ceed4e4cdf706"}, - {file = "ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6ce6743ed64d9afab4fafeaea70d3631b4d4b28b592db21a5c2d1f0ef52934bf"}, - {file = "ruff-0.9.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54499fb08408e32b57360f6f9de7157a5fec24ad79cb3f42ef2c3f3f728dfe2b"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37c892540108314a6f01f105040b5106aeb829fa5fb0561d2dcaf71485021137"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de9edf2ce4b9ddf43fd93e20ef635a900e25f622f87ed6e3047a664d0e8f810e"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87c90c32357c74f11deb7fbb065126d91771b207bf9bfaaee01277ca59b574ec"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56acd6c694da3695a7461cc55775f3a409c3815ac467279dfa126061d84b314b"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0c93e7d47ed951b9394cf352d6695b31498e68fd5782d6cbc282425655f687a"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d4c8772670aecf037d1bf7a07c39106574d143b26cfe5ed1787d2f31e800214"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfc5f1d7afeda8d5d37660eeca6d389b142d7f2b5a1ab659d9214ebd0e025231"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:faa935fc00ae854d8b638c16a5f1ce881bc3f67446957dd6f2af440a5fc8526b"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6c634fc6f5a0ceae1ab3e13c58183978185d131a29c425e4eaa9f40afe1e6d6"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:433dedf6ddfdec7f1ac7575ec1eb9844fa60c4c8c2f8887a070672b8d353d34c"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d612dbd0f3a919a8cc1d12037168bfa536862066808960e0cc901404b77968f0"}, - {file = "ruff-0.9.4-py3-none-win32.whl", hash = "sha256:db1192ddda2200671f9ef61d9597fcef89d934f5d1705e571a93a67fb13a4402"}, - {file = "ruff-0.9.4-py3-none-win_amd64.whl", hash = "sha256:05bebf4cdbe3ef75430d26c375773978950bbf4ee3c95ccb5448940dc092408e"}, - {file = "ruff-0.9.4-py3-none-win_arm64.whl", hash = "sha256:585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41"}, - {file = "ruff-0.9.4.tar.gz", hash = "sha256:6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7"}, + {file = "ruff-0.9.9-py3-none-linux_armv6l.whl", hash = "sha256:628abb5ea10345e53dff55b167595a159d3e174d6720bf19761f5e467e68d367"}, + {file = "ruff-0.9.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6cd1428e834b35d7493354723543b28cc11dc14d1ce19b685f6e68e07c05ec7"}, + {file = "ruff-0.9.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5ee162652869120ad260670706f3cd36cd3f32b0c651f02b6da142652c54941d"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3aa0f6b75082c9be1ec5a1db78c6d4b02e2375c3068438241dc19c7c306cc61a"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:584cc66e89fb5f80f84b05133dd677a17cdd86901d6479712c96597a3f28e7fe"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf3369325761a35aba75cd5c55ba1b5eb17d772f12ab168fbfac54be85cf18c"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3403a53a32a90ce929aa2f758542aca9234befa133e29f4933dcef28a24317be"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18454e7fa4e4d72cffe28a37cf6a73cb2594f81ec9f4eca31a0aaa9ccdfb1590"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fadfe2c88724c9617339f62319ed40dcdadadf2888d5afb88bf3adee7b35bfb"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6df104d08c442a1aabcfd254279b8cc1e2cbf41a605aa3e26610ba1ec4acf0b0"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d7c62939daf5b2a15af48abbd23bea1efdd38c312d6e7c4cedf5a24e03207e17"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9494ba82a37a4b81b6a798076e4a3251c13243fc37967e998efe4cce58c8a8d1"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4efd7a96ed6d36ef011ae798bf794c5501a514be369296c672dab7921087fa57"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ab90a7944c5a1296f3ecb08d1cbf8c2da34c7e68114b1271a431a3ad30cb660e"}, + {file = "ruff-0.9.9-py3-none-win32.whl", hash = "sha256:6b4c376d929c25ecd6d87e182a230fa4377b8e5125a4ff52d506ee8c087153c1"}, + {file = "ruff-0.9.9-py3-none-win_amd64.whl", hash = "sha256:837982ea24091d4c1700ddb2f63b7070e5baec508e43b01de013dc7eff974ff1"}, + {file = "ruff-0.9.9-py3-none-win_arm64.whl", hash = "sha256:3ac78f127517209fe6d96ab00f3ba97cafe38718b23b1db3e96d8b2d39e37ddf"}, + {file = "ruff-0.9.9.tar.gz", hash = "sha256:0062ed13f22173e85f8f7056f9a24016e692efeea8704d1a5e8011b8aa850933"}, ] [[package]] @@ -414,4 +414,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = ">=3.10" -content-hash = "8e35e388293ecef04cfd670afdbb275aeb8f4a4563b0706902e76a70f1dae669" +content-hash = "05c0f86ed95110f1e335d126cdd46a86b751c5bb355b9dd2c62a5bfe29f6b24b" diff --git a/scaleway-core/pyproject.toml b/scaleway-core/pyproject.toml index c9a0bd39b..30e565ad5 100644 --- a/scaleway-core/pyproject.toml +++ b/scaleway-core/pyproject.toml @@ -30,7 +30,7 @@ python-dateutil = "^2.8.2" [tool.poetry.group.dev.dependencies] types-python-dateutil = "^2.8.19" -ruff = ">=0.5.0,<0.9.5" +ruff = ">=0.5.0,<0.9.10" mypy = "^1.5.1" [build-system] From 6301fbf0cf8017f6e063b657c2fdca6c1938484b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 10:02:45 +0000 Subject: [PATCH 41/73] chore(deps-dev): bump mypy from 1.14.1 to 1.15.0 in /scaleway-core (#881) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scaleway-core/poetry.lock | 74 ++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/scaleway-core/poetry.lock b/scaleway-core/poetry.lock index ada26a736..f00f5e72e 100644 --- a/scaleway-core/poetry.lock +++ b/scaleway-core/poetry.lock @@ -128,49 +128,43 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "mypy" -version = "1.14.1" +version = "1.15.0" description = "Optional static typing for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, - {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"}, - {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"}, - {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"}, - {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"}, - {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"}, - {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"}, - {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"}, - {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"}, - {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"}, - {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"}, - {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"}, - {file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"}, - {file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"}, - {file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"}, - {file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, + {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, + {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, + {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, + {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, + {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, + {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, + {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, + {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, + {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, + {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, + {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, + {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, ] [package.dependencies] From 75782cafa7f155e96722100c143c45465043ddc4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 10:03:02 +0000 Subject: [PATCH 42/73] chore(deps-dev): bump ruff from 0.9.4 to 0.9.9 in /scaleway-async (#882) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scaleway-async/poetry.lock | 40 +++++++++++++++++------------------ scaleway-async/pyproject.toml | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/scaleway-async/poetry.lock b/scaleway-async/poetry.lock index 4becc0599..45b43c423 100644 --- a/scaleway-async/poetry.lock +++ b/scaleway-async/poetry.lock @@ -295,29 +295,29 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.9.4" +version = "0.9.9" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.9.4-py3-none-linux_armv6l.whl", hash = "sha256:64e73d25b954f71ff100bb70f39f1ee09e880728efb4250c632ceed4e4cdf706"}, - {file = "ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6ce6743ed64d9afab4fafeaea70d3631b4d4b28b592db21a5c2d1f0ef52934bf"}, - {file = "ruff-0.9.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54499fb08408e32b57360f6f9de7157a5fec24ad79cb3f42ef2c3f3f728dfe2b"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37c892540108314a6f01f105040b5106aeb829fa5fb0561d2dcaf71485021137"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de9edf2ce4b9ddf43fd93e20ef635a900e25f622f87ed6e3047a664d0e8f810e"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87c90c32357c74f11deb7fbb065126d91771b207bf9bfaaee01277ca59b574ec"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56acd6c694da3695a7461cc55775f3a409c3815ac467279dfa126061d84b314b"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0c93e7d47ed951b9394cf352d6695b31498e68fd5782d6cbc282425655f687a"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d4c8772670aecf037d1bf7a07c39106574d143b26cfe5ed1787d2f31e800214"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfc5f1d7afeda8d5d37660eeca6d389b142d7f2b5a1ab659d9214ebd0e025231"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:faa935fc00ae854d8b638c16a5f1ce881bc3f67446957dd6f2af440a5fc8526b"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6c634fc6f5a0ceae1ab3e13c58183978185d131a29c425e4eaa9f40afe1e6d6"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:433dedf6ddfdec7f1ac7575ec1eb9844fa60c4c8c2f8887a070672b8d353d34c"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d612dbd0f3a919a8cc1d12037168bfa536862066808960e0cc901404b77968f0"}, - {file = "ruff-0.9.4-py3-none-win32.whl", hash = "sha256:db1192ddda2200671f9ef61d9597fcef89d934f5d1705e571a93a67fb13a4402"}, - {file = "ruff-0.9.4-py3-none-win_amd64.whl", hash = "sha256:05bebf4cdbe3ef75430d26c375773978950bbf4ee3c95ccb5448940dc092408e"}, - {file = "ruff-0.9.4-py3-none-win_arm64.whl", hash = "sha256:585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41"}, - {file = "ruff-0.9.4.tar.gz", hash = "sha256:6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7"}, + {file = "ruff-0.9.9-py3-none-linux_armv6l.whl", hash = "sha256:628abb5ea10345e53dff55b167595a159d3e174d6720bf19761f5e467e68d367"}, + {file = "ruff-0.9.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6cd1428e834b35d7493354723543b28cc11dc14d1ce19b685f6e68e07c05ec7"}, + {file = "ruff-0.9.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5ee162652869120ad260670706f3cd36cd3f32b0c651f02b6da142652c54941d"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3aa0f6b75082c9be1ec5a1db78c6d4b02e2375c3068438241dc19c7c306cc61a"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:584cc66e89fb5f80f84b05133dd677a17cdd86901d6479712c96597a3f28e7fe"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf3369325761a35aba75cd5c55ba1b5eb17d772f12ab168fbfac54be85cf18c"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3403a53a32a90ce929aa2f758542aca9234befa133e29f4933dcef28a24317be"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18454e7fa4e4d72cffe28a37cf6a73cb2594f81ec9f4eca31a0aaa9ccdfb1590"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fadfe2c88724c9617339f62319ed40dcdadadf2888d5afb88bf3adee7b35bfb"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6df104d08c442a1aabcfd254279b8cc1e2cbf41a605aa3e26610ba1ec4acf0b0"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d7c62939daf5b2a15af48abbd23bea1efdd38c312d6e7c4cedf5a24e03207e17"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9494ba82a37a4b81b6a798076e4a3251c13243fc37967e998efe4cce58c8a8d1"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4efd7a96ed6d36ef011ae798bf794c5501a514be369296c672dab7921087fa57"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ab90a7944c5a1296f3ecb08d1cbf8c2da34c7e68114b1271a431a3ad30cb660e"}, + {file = "ruff-0.9.9-py3-none-win32.whl", hash = "sha256:6b4c376d929c25ecd6d87e182a230fa4377b8e5125a4ff52d506ee8c087153c1"}, + {file = "ruff-0.9.9-py3-none-win_amd64.whl", hash = "sha256:837982ea24091d4c1700ddb2f63b7070e5baec508e43b01de013dc7eff974ff1"}, + {file = "ruff-0.9.9-py3-none-win_arm64.whl", hash = "sha256:3ac78f127517209fe6d96ab00f3ba97cafe38718b23b1db3e96d8b2d39e37ddf"}, + {file = "ruff-0.9.9.tar.gz", hash = "sha256:0062ed13f22173e85f8f7056f9a24016e692efeea8704d1a5e8011b8aa850933"}, ] [[package]] @@ -421,4 +421,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = ">=3.10" -content-hash = "4f889abfd75a3d01edf436c44008a6e0adf7a5442f9fa02870e693751444211c" +content-hash = "1b578c9907f883acb2f89dddb57645028384aeefd8b4e8c483cfe8b2fde32fe4" diff --git a/scaleway-async/pyproject.toml b/scaleway-async/pyproject.toml index 8375e9e33..9441a9d08 100644 --- a/scaleway-async/pyproject.toml +++ b/scaleway-async/pyproject.toml @@ -28,7 +28,7 @@ scaleway-core = "*" [tool.poetry.group.dev.dependencies] scaleway-core = { path = "../scaleway-core", develop = true } -ruff = ">=0.5.0,<0.9.5" +ruff = ">=0.5.0,<0.9.10" mypy = "^1.5.1" [build-system] From a7e5afcc0b0e924ca272d9b9f8ee8d7a26f20c2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 10:03:16 +0000 Subject: [PATCH 43/73] chore(deps-dev): bump mypy from 1.14.1 to 1.15.0 in /scaleway-async (#883) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scaleway-async/poetry.lock | 74 ++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/scaleway-async/poetry.lock b/scaleway-async/poetry.lock index 45b43c423..50256b85e 100644 --- a/scaleway-async/poetry.lock +++ b/scaleway-async/poetry.lock @@ -128,49 +128,43 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "mypy" -version = "1.14.1" +version = "1.15.0" description = "Optional static typing for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, - {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"}, - {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"}, - {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"}, - {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"}, - {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"}, - {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"}, - {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"}, - {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"}, - {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"}, - {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"}, - {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"}, - {file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"}, - {file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"}, - {file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"}, - {file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, + {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, + {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, + {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, + {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, + {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, + {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, + {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, + {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, + {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, + {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, + {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, + {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, ] [package.dependencies] From 208b71e5098b65fcbc792fe14394dc084f24bf38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20L=C3=A9one?= Date: Thu, 6 Mar 2025 14:14:07 +0100 Subject: [PATCH 44/73] chore: migrate to devtools sub-teams for CODEOWNERS (#884) Co-authored-by: devtools-ci-cd --- .github/CODEOWNERS | 124 ++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 17fdcf4ea..20d51bc8f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,95 +2,95 @@ # the repo. Unless a later match takes precedence, * @remyleone -/scaleway/scaleway/account/ @tbellavia -/scaleway-async/scaleway_async/account/ @tbellavia +/scaleway/scaleway/account/ @scaleway/devtools-core +/scaleway-async/scaleway_async/account/ @scaleway/devtools-core -/scaleway/scaleway/applesilicon/ @Laure-di -/scaleway-async/scaleway_async/applesilicon/ @Laure-di +/scaleway/scaleway/applesilicon/ @scaleway/devtools-compute-foundation +/scaleway-async/scaleway_async/applesilicon/ @scaleway/devtools-compute-foundation -/scaleway/scaleway/baremetal/ @Laure-di -/scaleway-async/scaleway_async/baremetal/ @Laure-di +/scaleway/scaleway/baremetal/ @scaleway/devtools-compute-foundation +/scaleway-async/scaleway_async/baremetal/ @scaleway/devtools-compute-foundation -/scaleway/scaleway/billing/ @tbellavia -/scaleway-async/scaleway_async/billing/ @tbellavia +/scaleway/scaleway/billing/ @scaleway/devtools-core +/scaleway-async/scaleway_async/billing/ @scaleway/devtools-core -/scaleway/scaleway/block/ @Codelax -/scaleway-async/scaleway_async/block/ @Codelax +/scaleway/scaleway/block/ @scaleway/devtools-storage +/scaleway-async/scaleway_async/block/ @scaleway/devtools-storage -/scaleway/scaleway/cockpit/ @jremy42 -/scaleway-async/scaleway_async/cockpit/ @jremy42 +/scaleway/scaleway/cockpit/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/cockpit/ @scaleway/devtools-dms -/scaleway/scaleway/container/ @Codelax -/scaleway-async/scaleway_async/container/ @Codelax +/scaleway/scaleway/container/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/container/ @scaleway/devtools-compute -/scaleway/scaleway/dedibox/ @Laure-di -/scaleway-async/scaleway_async/dedibox/ @Laure-di +/scaleway/scaleway/dedibox/ @scaleway/devtools-compute-foundation +/scaleway-async/scaleway_async/dedibox/ @scaleway/devtools-compute-foundation -/scaleway/scaleway/domain/ @jremy42 -/scaleway-async/scaleway_async/domain/ @jremy42 +/scaleway/scaleway/domain/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/domain/ @scaleway/devtools-dms -/scaleway/scaleway/edge_services/ @yfodil -/scaleway-async/scaleway_async/edge_services/ @yfodil +/scaleway/scaleway/edge_services/ @scaleway/devtools-network +/scaleway-async/scaleway_async/edge_services/ @scaleway/devtools-network -/scaleway/scaleway/flexibleip/ @yfodil -/scaleway-async/scaleway_async/flexibleip/ @yfodil +/scaleway/scaleway/flexibleip/ @scaleway/devtools-network +/scaleway-async/scaleway_async/flexibleip/ @scaleway/devtools-network -/scaleway/scaleway/function/ @Codelax -/scaleway-async/scaleway_async/function/ @Codelax +/scaleway/scaleway/function/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/function/ @scaleway/devtools-compute -/scaleway/scaleway/iam/ @tbellavia -/scaleway-async/scaleway_async/iam/ @tbellavia +/scaleway/scaleway/iam/ @scaleway/devtools-core +/scaleway-async/scaleway_async/iam/ @scaleway/devtools-core -/scaleway/scaleway/instance/ @Codelax -/scaleway-async/scaleway_async/instance/ @Codelax +/scaleway/scaleway/instance/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/instance/ @scaleway/devtools-compute -/scaleway/scaleway/iot/ @jremy42 -/scaleway-async/scaleway_async/iot/ @jremy42 +/scaleway/scaleway/iot/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/iot/ @scaleway/devtools-dms -/scaleway/scaleway/ipam/ @yfodil -/scaleway-async/scaleway_async/ipam/ @yfodil +/scaleway/scaleway/ipam/ @scaleway/devtools-network +/scaleway-async/scaleway_async/ipam/ @scaleway/devtools-network -/scaleway/scaleway/jobs/ @Codelax -/scaleway-async/scaleway_async/jobs/ @Codelax +/scaleway/scaleway/jobs/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/jobs/ @scaleway/devtools-compute -/scaleway/scaleway/k8s/ @Codelax -/scaleway-async/scaleway_async/k8s/ @Codelax +/scaleway/scaleway/k8s/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/k8s/ @scaleway/devtools-compute -/scaleway/scaleway/key_manager/ @tbellavia -/scaleway-async/scaleway_async/key_manager/ @tbellavia +/scaleway/scaleway/key_manager/ @scaleway/devtools-core +/scaleway-async/scaleway_async/key_manager/ @scaleway/devtools-core -/scaleway/scaleway/lb/ @yfodil -/scaleway-async/scaleway_async/lb/ @yfodil +/scaleway/scaleway/lb/ @scaleway/devtools-network +/scaleway-async/scaleway_async/lb/ @scaleway/devtools-network -/scaleway/scaleway/marketplace/ @Codelax -/scaleway-async/scaleway_async/marketplace/ @Codelax +/scaleway/scaleway/marketplace/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/marketplace/ @scaleway/devtools-compute -/scaleway/scaleway/mnq/ @jremy42 -/scaleway-async/scaleway_async/mnq/ @jremy42 +/scaleway/scaleway/mnq/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/mnq/ @scaleway/devtools-dms -/scaleway/scaleway/rdb/ @jremy42 -/scaleway-async/scaleway_async/rdb/ @jremy42 +/scaleway/scaleway/rdb/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/rdb/ @scaleway/devtools-dms -/scaleway/scaleway/redis/ @jremy42 -/scaleway-async/scaleway_async/redis/ @jremy42 +/scaleway/scaleway/redis/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/redis/ @scaleway/devtools-dms -/scaleway/scaleway/registry/ @Codelax -/scaleway-async/scaleway_async/registry/ @Codelax +/scaleway/scaleway/registry/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/registry/ @scaleway/devtools-compute -/scaleway/scaleway/secret/ @tbellavia -/scaleway-async/scaleway_async/secret/ @tbellavia +/scaleway/scaleway/secret/ @scaleway/devtools-core +/scaleway-async/scaleway_async/secret/ @scaleway/devtools-core -/scaleway/scaleway/serverless_sqldb/ @jremy42 -/scaleway-async/scaleway_async/serverless_sqldb/ @jremy42 +/scaleway/scaleway/serverless_sqldb/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/serverless_sqldb/ @scaleway/devtools-dms -/scaleway/scaleway/tem/ @jremy42 -/scaleway-async/scaleway_async/tem/ @jremy42 +/scaleway/scaleway/tem/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/tem/ @scaleway/devtools-dms -/scaleway/scaleway/vpc/ @yfodil -/scaleway-async/scaleway_async/vpc/ @yfodil +/scaleway/scaleway/vpc/ @scaleway/devtools-network +/scaleway-async/scaleway_async/vpc/ @scaleway/devtools-network -/scaleway/scaleway/vpcgw/ @yfodil -/scaleway-async/scaleway_async/vpcgw/ @yfodil +/scaleway/scaleway/vpcgw/ @scaleway/devtools-network +/scaleway-async/scaleway_async/vpcgw/ @scaleway/devtools-network -/scaleway/scaleway/webhosting/ @jremy42 -/scaleway-async/scaleway_async/webhosting/ @jremy42 +/scaleway/scaleway/webhosting/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/webhosting/ @scaleway/devtools-dms From 6b9c211530c42e4928a0bf8d53b8060a7cac8bb1 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Mar 2025 14:17:06 +0100 Subject: [PATCH 45/73] feat(audit_trail): use explicit name for resource prefix instead of quadrigram (#886) --- .../audit_trail/v1alpha1/marshalling.py | 20 +++++++++++++++++++ .../audit_trail/v1alpha1/types.py | 9 +++++++++ .../audit_trail/v1alpha1/marshalling.py | 20 +++++++++++++++++++ .../scaleway/audit_trail/v1alpha1/types.py | 9 +++++++++ 4 files changed, 58 insertions(+) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py index 53c8f9f9a..f55b63503 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py @@ -224,6 +224,26 @@ def unmarshal_Resource(data: Any) -> Resource: else: args["keym_key_info"] = None + field = data.get("secret_manager_secret_info", None) + if field is not None: + args["secret_manager_secret_info"] = unmarshal_SecretManagerSecretInfo(field) + else: + args["secret_manager_secret_info"] = None + + field = data.get("secret_manager_version_info", None) + if field is not None: + args["secret_manager_version_info"] = unmarshal_SecretManagerSecretVersionInfo( + field + ) + else: + args["secret_manager_version_info"] = None + + field = data.get("key_manager_key_info", None) + if field is not None: + args["key_manager_key_info"] = unmarshal_KeyManagerKeyInfo(field) + else: + args["key_manager_key_info"] = None + return Resource(**args) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py index bad7d376b..f58c9ff5d 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py @@ -38,6 +38,9 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): IAM_POLICY = "iam_policy" IAM_API_KEY = "iam_api_key" IAM_SSH_KEY = "iam_ssh_key" + SECRET_MANAGER_SECRET = "secret_manager_secret" + SECRET_MANAGER_VERSION = "secret_manager_version" + KEY_MANAGER_KEY = "key_manager_key" def __str__(self) -> str: return str(self.value) @@ -115,6 +118,12 @@ class Resource: keym_key_info: Optional[KeyManagerKeyInfo] + secret_manager_secret_info: Optional[SecretManagerSecretInfo] + + secret_manager_version_info: Optional[SecretManagerSecretVersionInfo] + + key_manager_key_info: Optional[KeyManagerKeyInfo] + @dataclass class ProductService: diff --git a/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py b/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py index 53c8f9f9a..f55b63503 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py @@ -224,6 +224,26 @@ def unmarshal_Resource(data: Any) -> Resource: else: args["keym_key_info"] = None + field = data.get("secret_manager_secret_info", None) + if field is not None: + args["secret_manager_secret_info"] = unmarshal_SecretManagerSecretInfo(field) + else: + args["secret_manager_secret_info"] = None + + field = data.get("secret_manager_version_info", None) + if field is not None: + args["secret_manager_version_info"] = unmarshal_SecretManagerSecretVersionInfo( + field + ) + else: + args["secret_manager_version_info"] = None + + field = data.get("key_manager_key_info", None) + if field is not None: + args["key_manager_key_info"] = unmarshal_KeyManagerKeyInfo(field) + else: + args["key_manager_key_info"] = None + return Resource(**args) diff --git a/scaleway/scaleway/audit_trail/v1alpha1/types.py b/scaleway/scaleway/audit_trail/v1alpha1/types.py index bad7d376b..f58c9ff5d 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/types.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/types.py @@ -38,6 +38,9 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): IAM_POLICY = "iam_policy" IAM_API_KEY = "iam_api_key" IAM_SSH_KEY = "iam_ssh_key" + SECRET_MANAGER_SECRET = "secret_manager_secret" + SECRET_MANAGER_VERSION = "secret_manager_version" + KEY_MANAGER_KEY = "key_manager_key" def __str__(self) -> str: return str(self.value) @@ -115,6 +118,12 @@ class Resource: keym_key_info: Optional[KeyManagerKeyInfo] + secret_manager_secret_info: Optional[SecretManagerSecretInfo] + + secret_manager_version_info: Optional[SecretManagerSecretVersionInfo] + + key_manager_key_info: Optional[KeyManagerKeyInfo] + @dataclass class ProductService: From 065b97b583f286511c294fe950d535787119ba9d Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Mar 2025 14:17:44 +0100 Subject: [PATCH 46/73] feat(iam): add listing of user connections (#887) --- .../scaleway_async/iam/v1alpha1/__init__.py | 10 ++ .../scaleway_async/iam/v1alpha1/api.py | 29 +++++ .../iam/v1alpha1/marshalling.py | 102 ++++++++++++++++++ .../scaleway_async/iam/v1alpha1/types.py | 47 ++++++++ scaleway/scaleway/iam/v1alpha1/__init__.py | 10 ++ scaleway/scaleway/iam/v1alpha1/api.py | 29 +++++ scaleway/scaleway/iam/v1alpha1/marshalling.py | 102 ++++++++++++++++++ scaleway/scaleway/iam/v1alpha1/types.py | 47 ++++++++ 8 files changed, 376 insertions(+) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py index edb257bad..d4e328316 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py @@ -19,6 +19,8 @@ from .types import UserStatus from .types import UserType from .types import QuotumLimit +from .types import ListUserConnectionsResponseConnectionConnectedOrganization +from .types import ListUserConnectionsResponseConnectionConnectedUser from .types import JWT from .types import RuleSpecs from .types import CreateUserRequestMember @@ -32,6 +34,7 @@ from .types import Quotum from .types import Rule from .types import SSHKey +from .types import ListUserConnectionsResponseConnection from .types import User from .types import AddGroupMemberRequest from .types import AddGroupMembersRequest @@ -85,6 +88,8 @@ from .types import ListRulesResponse from .types import ListSSHKeysRequest from .types import ListSSHKeysResponse +from .types import ListUserConnectionsRequest +from .types import ListUserConnectionsResponse from .types import ListUsersRequest from .types import ListUsersResponse from .types import LockUserRequest @@ -128,6 +133,8 @@ "UserStatus", "UserType", "QuotumLimit", + "ListUserConnectionsResponseConnectionConnectedOrganization", + "ListUserConnectionsResponseConnectionConnectedUser", "JWT", "RuleSpecs", "CreateUserRequestMember", @@ -141,6 +148,7 @@ "Quotum", "Rule", "SSHKey", + "ListUserConnectionsResponseConnection", "User", "AddGroupMemberRequest", "AddGroupMembersRequest", @@ -194,6 +202,8 @@ "ListRulesResponse", "ListSSHKeysRequest", "ListSSHKeysResponse", + "ListUserConnectionsRequest", + "ListUserConnectionsResponse", "ListUsersRequest", "ListUsersResponse", "LockUserRequest", diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/api.py b/scaleway-async/scaleway_async/iam/v1alpha1/api.py index 24fc6a492..335ed3bc2 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/api.py @@ -52,6 +52,7 @@ ListQuotaResponse, ListRulesResponse, ListSSHKeysResponse, + ListUserConnectionsResponse, ListUsersResponse, Log, MFAOTP, @@ -101,6 +102,7 @@ unmarshal_ListQuotaResponse, unmarshal_ListRulesResponse, unmarshal_ListSSHKeysResponse, + unmarshal_ListUserConnectionsResponse, unmarshal_ListUsersResponse, unmarshal_MFAOTP, unmarshal_OrganizationSecuritySettings, @@ -851,6 +853,33 @@ async def list_grace_periods( self._throw_on_error(res) return unmarshal_ListGracePeriodsResponse(res.json()) + async def list_user_connections( + self, + *, + user_id: str, + ) -> ListUserConnectionsResponse: + """ + :param user_id: ID of the user to list connections for. + :return: :class:`ListUserConnectionsResponse ` + + Usage: + :: + + result = await api.list_user_connections( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "GET", + f"/iam/v1alpha1/users/{param_user_id}/connections", + ) + + self._throw_on_error(res) + return unmarshal_ListUserConnectionsResponse(res.json()) + async def list_applications( self, *, diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py index c6a9ef1eb..a02759f70 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py @@ -35,6 +35,10 @@ Rule, ListRulesResponse, ListSSHKeysResponse, + ListUserConnectionsResponseConnectionConnectedOrganization, + ListUserConnectionsResponseConnectionConnectedUser, + ListUserConnectionsResponseConnection, + ListUserConnectionsResponse, ListUsersResponse, MFAOTP, OrganizationSecuritySettings, @@ -1030,6 +1034,104 @@ def unmarshal_ListSSHKeysResponse(data: Any) -> ListSSHKeysResponse: return ListSSHKeysResponse(**args) +def unmarshal_ListUserConnectionsResponseConnectionConnectedOrganization( + data: Any, +) -> ListUserConnectionsResponseConnectionConnectedOrganization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUserConnectionsResponseConnectionConnectedOrganization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("locked", None) + if field is not None: + args["locked"] = field + + return ListUserConnectionsResponseConnectionConnectedOrganization(**args) + + +def unmarshal_ListUserConnectionsResponseConnectionConnectedUser( + data: Any, +) -> ListUserConnectionsResponseConnectionConnectedUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUserConnectionsResponseConnectionConnectedUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return ListUserConnectionsResponseConnectionConnectedUser(**args) + + +def unmarshal_ListUserConnectionsResponseConnection( + data: Any, +) -> ListUserConnectionsResponseConnection: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUserConnectionsResponseConnection' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization", None) + if field is not None: + args["organization"] = ( + unmarshal_ListUserConnectionsResponseConnectionConnectedOrganization(field) + ) + else: + args["organization"] = None + + field = data.get("user", None) + if field is not None: + args["user"] = unmarshal_ListUserConnectionsResponseConnectionConnectedUser( + field + ) + else: + args["user"] = None + + return ListUserConnectionsResponseConnection(**args) + + +def unmarshal_ListUserConnectionsResponse(data: Any) -> ListUserConnectionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUserConnectionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connections", None) + if field is not None: + args["connections"] = ( + [unmarshal_ListUserConnectionsResponseConnection(v) for v in field] + if field is not None + else None + ) + + return ListUserConnectionsResponse(**args) + + def unmarshal_ListUsersResponse(data: Any) -> ListUsersResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/types.py b/scaleway-async/scaleway_async/iam/v1alpha1/types.py index 571ee9ac8..6d0a559a7 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/types.py @@ -219,6 +219,24 @@ class QuotumLimit: unlimited: Optional[bool] +@dataclass +class ListUserConnectionsResponseConnectionConnectedOrganization: + id: str + + name: str + + locked: bool + + +@dataclass +class ListUserConnectionsResponseConnectionConnectedUser: + id: str + + username: str + + type_: UserType + + @dataclass class JWT: jti: str @@ -774,6 +792,19 @@ class SSHKey: """ +@dataclass +class ListUserConnectionsResponseConnection: + organization: Optional[ListUserConnectionsResponseConnectionConnectedOrganization] + """ + Information about the connected organization. + """ + + user: Optional[ListUserConnectionsResponseConnectionConnectedUser] + """ + Information about the connected user. + """ + + @dataclass class User: id: str @@ -1750,6 +1781,22 @@ class ListSSHKeysResponse: """ +@dataclass +class ListUserConnectionsRequest: + user_id: str + """ + ID of the user to list connections for. + """ + + +@dataclass +class ListUserConnectionsResponse: + connections: List[ListUserConnectionsResponseConnection] + """ + List of connections. + """ + + @dataclass class ListUsersRequest: order_by: Optional[ListUsersRequestOrderBy] diff --git a/scaleway/scaleway/iam/v1alpha1/__init__.py b/scaleway/scaleway/iam/v1alpha1/__init__.py index edb257bad..d4e328316 100644 --- a/scaleway/scaleway/iam/v1alpha1/__init__.py +++ b/scaleway/scaleway/iam/v1alpha1/__init__.py @@ -19,6 +19,8 @@ from .types import UserStatus from .types import UserType from .types import QuotumLimit +from .types import ListUserConnectionsResponseConnectionConnectedOrganization +from .types import ListUserConnectionsResponseConnectionConnectedUser from .types import JWT from .types import RuleSpecs from .types import CreateUserRequestMember @@ -32,6 +34,7 @@ from .types import Quotum from .types import Rule from .types import SSHKey +from .types import ListUserConnectionsResponseConnection from .types import User from .types import AddGroupMemberRequest from .types import AddGroupMembersRequest @@ -85,6 +88,8 @@ from .types import ListRulesResponse from .types import ListSSHKeysRequest from .types import ListSSHKeysResponse +from .types import ListUserConnectionsRequest +from .types import ListUserConnectionsResponse from .types import ListUsersRequest from .types import ListUsersResponse from .types import LockUserRequest @@ -128,6 +133,8 @@ "UserStatus", "UserType", "QuotumLimit", + "ListUserConnectionsResponseConnectionConnectedOrganization", + "ListUserConnectionsResponseConnectionConnectedUser", "JWT", "RuleSpecs", "CreateUserRequestMember", @@ -141,6 +148,7 @@ "Quotum", "Rule", "SSHKey", + "ListUserConnectionsResponseConnection", "User", "AddGroupMemberRequest", "AddGroupMembersRequest", @@ -194,6 +202,8 @@ "ListRulesResponse", "ListSSHKeysRequest", "ListSSHKeysResponse", + "ListUserConnectionsRequest", + "ListUserConnectionsResponse", "ListUsersRequest", "ListUsersResponse", "LockUserRequest", diff --git a/scaleway/scaleway/iam/v1alpha1/api.py b/scaleway/scaleway/iam/v1alpha1/api.py index 11364cf41..4284181ef 100644 --- a/scaleway/scaleway/iam/v1alpha1/api.py +++ b/scaleway/scaleway/iam/v1alpha1/api.py @@ -52,6 +52,7 @@ ListQuotaResponse, ListRulesResponse, ListSSHKeysResponse, + ListUserConnectionsResponse, ListUsersResponse, Log, MFAOTP, @@ -101,6 +102,7 @@ unmarshal_ListQuotaResponse, unmarshal_ListRulesResponse, unmarshal_ListSSHKeysResponse, + unmarshal_ListUserConnectionsResponse, unmarshal_ListUsersResponse, unmarshal_MFAOTP, unmarshal_OrganizationSecuritySettings, @@ -851,6 +853,33 @@ def list_grace_periods( self._throw_on_error(res) return unmarshal_ListGracePeriodsResponse(res.json()) + def list_user_connections( + self, + *, + user_id: str, + ) -> ListUserConnectionsResponse: + """ + :param user_id: ID of the user to list connections for. + :return: :class:`ListUserConnectionsResponse ` + + Usage: + :: + + result = api.list_user_connections( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "GET", + f"/iam/v1alpha1/users/{param_user_id}/connections", + ) + + self._throw_on_error(res) + return unmarshal_ListUserConnectionsResponse(res.json()) + def list_applications( self, *, diff --git a/scaleway/scaleway/iam/v1alpha1/marshalling.py b/scaleway/scaleway/iam/v1alpha1/marshalling.py index c6a9ef1eb..a02759f70 100644 --- a/scaleway/scaleway/iam/v1alpha1/marshalling.py +++ b/scaleway/scaleway/iam/v1alpha1/marshalling.py @@ -35,6 +35,10 @@ Rule, ListRulesResponse, ListSSHKeysResponse, + ListUserConnectionsResponseConnectionConnectedOrganization, + ListUserConnectionsResponseConnectionConnectedUser, + ListUserConnectionsResponseConnection, + ListUserConnectionsResponse, ListUsersResponse, MFAOTP, OrganizationSecuritySettings, @@ -1030,6 +1034,104 @@ def unmarshal_ListSSHKeysResponse(data: Any) -> ListSSHKeysResponse: return ListSSHKeysResponse(**args) +def unmarshal_ListUserConnectionsResponseConnectionConnectedOrganization( + data: Any, +) -> ListUserConnectionsResponseConnectionConnectedOrganization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUserConnectionsResponseConnectionConnectedOrganization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("locked", None) + if field is not None: + args["locked"] = field + + return ListUserConnectionsResponseConnectionConnectedOrganization(**args) + + +def unmarshal_ListUserConnectionsResponseConnectionConnectedUser( + data: Any, +) -> ListUserConnectionsResponseConnectionConnectedUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUserConnectionsResponseConnectionConnectedUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return ListUserConnectionsResponseConnectionConnectedUser(**args) + + +def unmarshal_ListUserConnectionsResponseConnection( + data: Any, +) -> ListUserConnectionsResponseConnection: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUserConnectionsResponseConnection' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization", None) + if field is not None: + args["organization"] = ( + unmarshal_ListUserConnectionsResponseConnectionConnectedOrganization(field) + ) + else: + args["organization"] = None + + field = data.get("user", None) + if field is not None: + args["user"] = unmarshal_ListUserConnectionsResponseConnectionConnectedUser( + field + ) + else: + args["user"] = None + + return ListUserConnectionsResponseConnection(**args) + + +def unmarshal_ListUserConnectionsResponse(data: Any) -> ListUserConnectionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUserConnectionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connections", None) + if field is not None: + args["connections"] = ( + [unmarshal_ListUserConnectionsResponseConnection(v) for v in field] + if field is not None + else None + ) + + return ListUserConnectionsResponse(**args) + + def unmarshal_ListUsersResponse(data: Any) -> ListUsersResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway/scaleway/iam/v1alpha1/types.py b/scaleway/scaleway/iam/v1alpha1/types.py index 571ee9ac8..6d0a559a7 100644 --- a/scaleway/scaleway/iam/v1alpha1/types.py +++ b/scaleway/scaleway/iam/v1alpha1/types.py @@ -219,6 +219,24 @@ class QuotumLimit: unlimited: Optional[bool] +@dataclass +class ListUserConnectionsResponseConnectionConnectedOrganization: + id: str + + name: str + + locked: bool + + +@dataclass +class ListUserConnectionsResponseConnectionConnectedUser: + id: str + + username: str + + type_: UserType + + @dataclass class JWT: jti: str @@ -774,6 +792,19 @@ class SSHKey: """ +@dataclass +class ListUserConnectionsResponseConnection: + organization: Optional[ListUserConnectionsResponseConnectionConnectedOrganization] + """ + Information about the connected organization. + """ + + user: Optional[ListUserConnectionsResponseConnectionConnectedUser] + """ + Information about the connected user. + """ + + @dataclass class User: id: str @@ -1750,6 +1781,22 @@ class ListSSHKeysResponse: """ +@dataclass +class ListUserConnectionsRequest: + user_id: str + """ + ID of the user to list connections for. + """ + + +@dataclass +class ListUserConnectionsResponse: + connections: List[ListUserConnectionsResponseConnection] + """ + List of connections. + """ + + @dataclass class ListUsersRequest: order_by: Optional[ListUsersRequestOrderBy] From ad6a67afcf4e769d8b2b345a3bc2a22e26cece5b Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Mar 2025 14:18:32 +0100 Subject: [PATCH 47/73] docs(secret_manager): change documentation for scheduled deletion (#885) --- .../scaleway_async/secret/v1beta1/api.py | 18 +++++++++++------- .../scaleway_async/secret/v1beta1/types.py | 10 +++++----- scaleway/scaleway/secret/v1beta1/api.py | 18 +++++++++++------- scaleway/scaleway/secret/v1beta1/types.py | 10 +++++----- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/scaleway-async/scaleway_async/secret/v1beta1/api.py b/scaleway-async/scaleway_async/secret/v1beta1/api.py index 47fef12c0..ba9e33d19 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/api.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/api.py @@ -242,6 +242,7 @@ async def delete_secret( async def list_secrets( self, *, + scheduled_for_deletion: bool, region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, @@ -253,11 +254,11 @@ async def list_secrets( path: Optional[str] = None, ephemeral: Optional[bool] = None, type_: Optional[SecretType] = None, - scheduled_for_deletion: Optional[bool] = None, ) -> ListSecretsResponse: """ List secrets. Retrieve the list of secrets created within an Organization and/or Project. You must specify either the `organization_id` or the `project_id` and the `region`. + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by Organization ID (optional). :param project_id: Filter by Project ID (optional). @@ -269,13 +270,14 @@ async def list_secrets( :param path: Filter by exact path (optional). :param ephemeral: Filter by ephemeral / not ephemeral (optional). :param type_: Filter by secret type (optional). - :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). :return: :class:`ListSecretsResponse ` Usage: :: - result = await api.list_secrets() + result = await api.list_secrets( + scheduled_for_deletion=False, + ) """ param_region = validate_path_param( @@ -307,6 +309,7 @@ async def list_secrets( async def list_secrets_all( self, *, + scheduled_for_deletion: bool, region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, @@ -318,11 +321,11 @@ async def list_secrets_all( path: Optional[str] = None, ephemeral: Optional[bool] = None, type_: Optional[SecretType] = None, - scheduled_for_deletion: Optional[bool] = None, ) -> List[Secret]: """ List secrets. Retrieve the list of secrets created within an Organization and/or Project. You must specify either the `organization_id` or the `project_id` and the `region`. + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by Organization ID (optional). :param project_id: Filter by Project ID (optional). @@ -334,13 +337,14 @@ async def list_secrets_all( :param path: Filter by exact path (optional). :param ephemeral: Filter by ephemeral / not ephemeral (optional). :param type_: Filter by secret type (optional). - :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). :return: :class:`List[Secret] ` Usage: :: - result = await api.list_secrets_all() + result = await api.list_secrets_all( + scheduled_for_deletion=False, + ) """ return await fetch_all_pages_async( @@ -348,6 +352,7 @@ async def list_secrets_all( key="secrets", fetcher=self.list_secrets, args={ + "scheduled_for_deletion": scheduled_for_deletion, "region": region, "organization_id": organization_id, "project_id": project_id, @@ -359,7 +364,6 @@ async def list_secrets_all( "path": path, "ephemeral": ephemeral, "type_": type_, - "scheduled_for_deletion": scheduled_for_deletion, }, ) diff --git a/scaleway-async/scaleway_async/secret/v1beta1/types.py b/scaleway-async/scaleway_async/secret/v1beta1/types.py index 338eaefd0..fe66cfee0 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/types.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/types.py @@ -758,6 +758,11 @@ class ListSecretVersionsResponse: @dataclass class ListSecretsRequest: + scheduled_for_deletion: bool + """ + Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. + """ + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. @@ -804,11 +809,6 @@ class ListSecretsRequest: Filter by secret type (optional). """ - scheduled_for_deletion: Optional[bool] - """ - Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). - """ - @dataclass class ListSecretsResponse: diff --git a/scaleway/scaleway/secret/v1beta1/api.py b/scaleway/scaleway/secret/v1beta1/api.py index 9605f8654..bbe3bce8a 100644 --- a/scaleway/scaleway/secret/v1beta1/api.py +++ b/scaleway/scaleway/secret/v1beta1/api.py @@ -242,6 +242,7 @@ def delete_secret( def list_secrets( self, *, + scheduled_for_deletion: bool, region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, @@ -253,11 +254,11 @@ def list_secrets( path: Optional[str] = None, ephemeral: Optional[bool] = None, type_: Optional[SecretType] = None, - scheduled_for_deletion: Optional[bool] = None, ) -> ListSecretsResponse: """ List secrets. Retrieve the list of secrets created within an Organization and/or Project. You must specify either the `organization_id` or the `project_id` and the `region`. + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by Organization ID (optional). :param project_id: Filter by Project ID (optional). @@ -269,13 +270,14 @@ def list_secrets( :param path: Filter by exact path (optional). :param ephemeral: Filter by ephemeral / not ephemeral (optional). :param type_: Filter by secret type (optional). - :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). :return: :class:`ListSecretsResponse ` Usage: :: - result = api.list_secrets() + result = api.list_secrets( + scheduled_for_deletion=False, + ) """ param_region = validate_path_param( @@ -307,6 +309,7 @@ def list_secrets( def list_secrets_all( self, *, + scheduled_for_deletion: bool, region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, @@ -318,11 +321,11 @@ def list_secrets_all( path: Optional[str] = None, ephemeral: Optional[bool] = None, type_: Optional[SecretType] = None, - scheduled_for_deletion: Optional[bool] = None, ) -> List[Secret]: """ List secrets. Retrieve the list of secrets created within an Organization and/or Project. You must specify either the `organization_id` or the `project_id` and the `region`. + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by Organization ID (optional). :param project_id: Filter by Project ID (optional). @@ -334,13 +337,14 @@ def list_secrets_all( :param path: Filter by exact path (optional). :param ephemeral: Filter by ephemeral / not ephemeral (optional). :param type_: Filter by secret type (optional). - :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). :return: :class:`List[Secret] ` Usage: :: - result = api.list_secrets_all() + result = api.list_secrets_all( + scheduled_for_deletion=False, + ) """ return fetch_all_pages( @@ -348,6 +352,7 @@ def list_secrets_all( key="secrets", fetcher=self.list_secrets, args={ + "scheduled_for_deletion": scheduled_for_deletion, "region": region, "organization_id": organization_id, "project_id": project_id, @@ -359,7 +364,6 @@ def list_secrets_all( "path": path, "ephemeral": ephemeral, "type_": type_, - "scheduled_for_deletion": scheduled_for_deletion, }, ) diff --git a/scaleway/scaleway/secret/v1beta1/types.py b/scaleway/scaleway/secret/v1beta1/types.py index 338eaefd0..fe66cfee0 100644 --- a/scaleway/scaleway/secret/v1beta1/types.py +++ b/scaleway/scaleway/secret/v1beta1/types.py @@ -758,6 +758,11 @@ class ListSecretVersionsResponse: @dataclass class ListSecretsRequest: + scheduled_for_deletion: bool + """ + Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. + """ + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. @@ -804,11 +809,6 @@ class ListSecretsRequest: Filter by secret type (optional). """ - scheduled_for_deletion: Optional[bool] - """ - Filter by whether the secret was scheduled for deletion / not scheduled for deletion (optional). - """ - @dataclass class ListSecretsResponse: From a79fe4876d58c64240acf39573ddbce37b8bda7f Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Mar 2025 14:35:45 +0100 Subject: [PATCH 48/73] fix(iam): rename ListUserConnections to GetUserConnections to be clear this isn't paginated (#889) --- .../scaleway_async/iam/v1alpha1/__init__.py | 20 +- .../scaleway_async/iam/v1alpha1/api.py | 14 +- .../iam/v1alpha1/marshalling.py | 204 +++++++++--------- .../scaleway_async/iam/v1alpha1/types.py | 88 ++++---- scaleway/scaleway/iam/v1alpha1/__init__.py | 20 +- scaleway/scaleway/iam/v1alpha1/api.py | 14 +- scaleway/scaleway/iam/v1alpha1/marshalling.py | 204 +++++++++--------- scaleway/scaleway/iam/v1alpha1/types.py | 88 ++++---- 8 files changed, 326 insertions(+), 326 deletions(-) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py index d4e328316..385a286af 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py @@ -18,12 +18,13 @@ from .types import PermissionSetScopeType from .types import UserStatus from .types import UserType +from .types import GetUserConnectionsResponseConnectionConnectedOrganization +from .types import GetUserConnectionsResponseConnectionConnectedUser from .types import QuotumLimit -from .types import ListUserConnectionsResponseConnectionConnectedOrganization -from .types import ListUserConnectionsResponseConnectionConnectedUser from .types import JWT from .types import RuleSpecs from .types import CreateUserRequestMember +from .types import GetUserConnectionsResponseConnection from .types import APIKey from .types import Application from .types import GracePeriod @@ -34,7 +35,6 @@ from .types import Quotum from .types import Rule from .types import SSHKey -from .types import ListUserConnectionsResponseConnection from .types import User from .types import AddGroupMemberRequest from .types import AddGroupMembersRequest @@ -65,6 +65,8 @@ from .types import GetPolicyRequest from .types import GetQuotumRequest from .types import GetSSHKeyRequest +from .types import GetUserConnectionsRequest +from .types import GetUserConnectionsResponse from .types import GetUserRequest from .types import ListAPIKeysRequest from .types import ListAPIKeysResponse @@ -88,8 +90,6 @@ from .types import ListRulesResponse from .types import ListSSHKeysRequest from .types import ListSSHKeysResponse -from .types import ListUserConnectionsRequest -from .types import ListUserConnectionsResponse from .types import ListUsersRequest from .types import ListUsersResponse from .types import LockUserRequest @@ -132,12 +132,13 @@ "PermissionSetScopeType", "UserStatus", "UserType", + "GetUserConnectionsResponseConnectionConnectedOrganization", + "GetUserConnectionsResponseConnectionConnectedUser", "QuotumLimit", - "ListUserConnectionsResponseConnectionConnectedOrganization", - "ListUserConnectionsResponseConnectionConnectedUser", "JWT", "RuleSpecs", "CreateUserRequestMember", + "GetUserConnectionsResponseConnection", "APIKey", "Application", "GracePeriod", @@ -148,7 +149,6 @@ "Quotum", "Rule", "SSHKey", - "ListUserConnectionsResponseConnection", "User", "AddGroupMemberRequest", "AddGroupMembersRequest", @@ -179,6 +179,8 @@ "GetPolicyRequest", "GetQuotumRequest", "GetSSHKeyRequest", + "GetUserConnectionsRequest", + "GetUserConnectionsResponse", "GetUserRequest", "ListAPIKeysRequest", "ListAPIKeysResponse", @@ -202,8 +204,6 @@ "ListRulesResponse", "ListSSHKeysRequest", "ListSSHKeysResponse", - "ListUserConnectionsRequest", - "ListUserConnectionsResponse", "ListUsersRequest", "ListUsersResponse", "LockUserRequest", diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/api.py b/scaleway-async/scaleway_async/iam/v1alpha1/api.py index 335ed3bc2..b09424baf 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/api.py @@ -39,6 +39,7 @@ CreateUserRequest, CreateUserRequestMember, EncodedJWT, + GetUserConnectionsResponse, Group, JWT, ListAPIKeysResponse, @@ -52,7 +53,6 @@ ListQuotaResponse, ListRulesResponse, ListSSHKeysResponse, - ListUserConnectionsResponse, ListUsersResponse, Log, MFAOTP, @@ -91,6 +91,7 @@ unmarshal_SSHKey, unmarshal_User, unmarshal_EncodedJWT, + unmarshal_GetUserConnectionsResponse, unmarshal_ListAPIKeysResponse, unmarshal_ListApplicationsResponse, unmarshal_ListGracePeriodsResponse, @@ -102,7 +103,6 @@ unmarshal_ListQuotaResponse, unmarshal_ListRulesResponse, unmarshal_ListSSHKeysResponse, - unmarshal_ListUserConnectionsResponse, unmarshal_ListUsersResponse, unmarshal_MFAOTP, unmarshal_OrganizationSecuritySettings, @@ -853,19 +853,19 @@ async def list_grace_periods( self._throw_on_error(res) return unmarshal_ListGracePeriodsResponse(res.json()) - async def list_user_connections( + async def get_user_connections( self, *, user_id: str, - ) -> ListUserConnectionsResponse: + ) -> GetUserConnectionsResponse: """ :param user_id: ID of the user to list connections for. - :return: :class:`ListUserConnectionsResponse ` + :return: :class:`GetUserConnectionsResponse ` Usage: :: - result = await api.list_user_connections( + result = await api.get_user_connections( user_id="example", ) """ @@ -878,7 +878,7 @@ async def list_user_connections( ) self._throw_on_error(res) - return unmarshal_ListUserConnectionsResponse(res.json()) + return unmarshal_GetUserConnectionsResponse(res.json()) async def list_applications( self, diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py index a02759f70..4b35ea99c 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py @@ -21,6 +21,10 @@ SSHKey, User, EncodedJWT, + GetUserConnectionsResponseConnectionConnectedOrganization, + GetUserConnectionsResponseConnectionConnectedUser, + GetUserConnectionsResponseConnection, + GetUserConnectionsResponse, ListAPIKeysResponse, ListApplicationsResponse, GracePeriod, @@ -35,10 +39,6 @@ Rule, ListRulesResponse, ListSSHKeysResponse, - ListUserConnectionsResponseConnectionConnectedOrganization, - ListUserConnectionsResponseConnectionConnectedUser, - ListUserConnectionsResponseConnection, - ListUserConnectionsResponse, ListUsersResponse, MFAOTP, OrganizationSecuritySettings, @@ -704,6 +704,104 @@ def unmarshal_EncodedJWT(data: Any) -> EncodedJWT: return EncodedJWT(**args) +def unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization( + data: Any, +) -> GetUserConnectionsResponseConnectionConnectedOrganization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponseConnectionConnectedOrganization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("locked", None) + if field is not None: + args["locked"] = field + + return GetUserConnectionsResponseConnectionConnectedOrganization(**args) + + +def unmarshal_GetUserConnectionsResponseConnectionConnectedUser( + data: Any, +) -> GetUserConnectionsResponseConnectionConnectedUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponseConnectionConnectedUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return GetUserConnectionsResponseConnectionConnectedUser(**args) + + +def unmarshal_GetUserConnectionsResponseConnection( + data: Any, +) -> GetUserConnectionsResponseConnection: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponseConnection' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization", None) + if field is not None: + args["organization"] = ( + unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization(field) + ) + else: + args["organization"] = None + + field = data.get("user", None) + if field is not None: + args["user"] = unmarshal_GetUserConnectionsResponseConnectionConnectedUser( + field + ) + else: + args["user"] = None + + return GetUserConnectionsResponseConnection(**args) + + +def unmarshal_GetUserConnectionsResponse(data: Any) -> GetUserConnectionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connections", None) + if field is not None: + args["connections"] = ( + [unmarshal_GetUserConnectionsResponseConnection(v) for v in field] + if field is not None + else None + ) + + return GetUserConnectionsResponse(**args) + + def unmarshal_ListAPIKeysResponse(data: Any) -> ListAPIKeysResponse: if not isinstance(data, dict): raise TypeError( @@ -1034,104 +1132,6 @@ def unmarshal_ListSSHKeysResponse(data: Any) -> ListSSHKeysResponse: return ListSSHKeysResponse(**args) -def unmarshal_ListUserConnectionsResponseConnectionConnectedOrganization( - data: Any, -) -> ListUserConnectionsResponseConnectionConnectedOrganization: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListUserConnectionsResponseConnectionConnectedOrganization' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("id", None) - if field is not None: - args["id"] = field - - field = data.get("name", None) - if field is not None: - args["name"] = field - - field = data.get("locked", None) - if field is not None: - args["locked"] = field - - return ListUserConnectionsResponseConnectionConnectedOrganization(**args) - - -def unmarshal_ListUserConnectionsResponseConnectionConnectedUser( - data: Any, -) -> ListUserConnectionsResponseConnectionConnectedUser: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListUserConnectionsResponseConnectionConnectedUser' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("id", None) - if field is not None: - args["id"] = field - - field = data.get("username", None) - if field is not None: - args["username"] = field - - field = data.get("type", None) - if field is not None: - args["type_"] = field - - return ListUserConnectionsResponseConnectionConnectedUser(**args) - - -def unmarshal_ListUserConnectionsResponseConnection( - data: Any, -) -> ListUserConnectionsResponseConnection: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListUserConnectionsResponseConnection' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("organization", None) - if field is not None: - args["organization"] = ( - unmarshal_ListUserConnectionsResponseConnectionConnectedOrganization(field) - ) - else: - args["organization"] = None - - field = data.get("user", None) - if field is not None: - args["user"] = unmarshal_ListUserConnectionsResponseConnectionConnectedUser( - field - ) - else: - args["user"] = None - - return ListUserConnectionsResponseConnection(**args) - - -def unmarshal_ListUserConnectionsResponse(data: Any) -> ListUserConnectionsResponse: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListUserConnectionsResponse' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("connections", None) - if field is not None: - args["connections"] = ( - [unmarshal_ListUserConnectionsResponseConnection(v) for v in field] - if field is not None - else None - ) - - return ListUserConnectionsResponse(**args) - - def unmarshal_ListUsersResponse(data: Any) -> ListUsersResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/types.py b/scaleway-async/scaleway_async/iam/v1alpha1/types.py index 6d0a559a7..3d5b67aa2 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/types.py @@ -207,20 +207,7 @@ def __str__(self) -> str: @dataclass -class QuotumLimit: - global_: Optional[bool] - - region: Optional[ScwRegion] - - zone: Optional[ScwZone] - - limit: Optional[int] - - unlimited: Optional[bool] - - -@dataclass -class ListUserConnectionsResponseConnectionConnectedOrganization: +class GetUserConnectionsResponseConnectionConnectedOrganization: id: str name: str @@ -229,7 +216,7 @@ class ListUserConnectionsResponseConnectionConnectedOrganization: @dataclass -class ListUserConnectionsResponseConnectionConnectedUser: +class GetUserConnectionsResponseConnectionConnectedUser: id: str username: str @@ -237,6 +224,19 @@ class ListUserConnectionsResponseConnectionConnectedUser: type_: UserType +@dataclass +class QuotumLimit: + global_: Optional[bool] + + region: Optional[ScwRegion] + + zone: Optional[ScwZone] + + limit: Optional[int] + + unlimited: Optional[bool] + + @dataclass class JWT: jti: str @@ -325,6 +325,19 @@ class CreateUserRequestMember: """ +@dataclass +class GetUserConnectionsResponseConnection: + organization: Optional[GetUserConnectionsResponseConnectionConnectedOrganization] + """ + Information about the connected organization. + """ + + user: Optional[GetUserConnectionsResponseConnectionConnectedUser] + """ + Information about the connected user. + """ + + @dataclass class APIKey: access_key: str @@ -792,19 +805,6 @@ class SSHKey: """ -@dataclass -class ListUserConnectionsResponseConnection: - organization: Optional[ListUserConnectionsResponseConnectionConnectedOrganization] - """ - Information about the connected organization. - """ - - user: Optional[ListUserConnectionsResponseConnectionConnectedUser] - """ - Information about the connected user. - """ - - @dataclass class User: id: str @@ -1234,6 +1234,22 @@ class GetSSHKeyRequest: """ +@dataclass +class GetUserConnectionsRequest: + user_id: str + """ + ID of the user to list connections for. + """ + + +@dataclass +class GetUserConnectionsResponse: + connections: List[GetUserConnectionsResponseConnection] + """ + List of connections. + """ + + @dataclass class GetUserRequest: user_id: str @@ -1781,22 +1797,6 @@ class ListSSHKeysResponse: """ -@dataclass -class ListUserConnectionsRequest: - user_id: str - """ - ID of the user to list connections for. - """ - - -@dataclass -class ListUserConnectionsResponse: - connections: List[ListUserConnectionsResponseConnection] - """ - List of connections. - """ - - @dataclass class ListUsersRequest: order_by: Optional[ListUsersRequestOrderBy] diff --git a/scaleway/scaleway/iam/v1alpha1/__init__.py b/scaleway/scaleway/iam/v1alpha1/__init__.py index d4e328316..385a286af 100644 --- a/scaleway/scaleway/iam/v1alpha1/__init__.py +++ b/scaleway/scaleway/iam/v1alpha1/__init__.py @@ -18,12 +18,13 @@ from .types import PermissionSetScopeType from .types import UserStatus from .types import UserType +from .types import GetUserConnectionsResponseConnectionConnectedOrganization +from .types import GetUserConnectionsResponseConnectionConnectedUser from .types import QuotumLimit -from .types import ListUserConnectionsResponseConnectionConnectedOrganization -from .types import ListUserConnectionsResponseConnectionConnectedUser from .types import JWT from .types import RuleSpecs from .types import CreateUserRequestMember +from .types import GetUserConnectionsResponseConnection from .types import APIKey from .types import Application from .types import GracePeriod @@ -34,7 +35,6 @@ from .types import Quotum from .types import Rule from .types import SSHKey -from .types import ListUserConnectionsResponseConnection from .types import User from .types import AddGroupMemberRequest from .types import AddGroupMembersRequest @@ -65,6 +65,8 @@ from .types import GetPolicyRequest from .types import GetQuotumRequest from .types import GetSSHKeyRequest +from .types import GetUserConnectionsRequest +from .types import GetUserConnectionsResponse from .types import GetUserRequest from .types import ListAPIKeysRequest from .types import ListAPIKeysResponse @@ -88,8 +90,6 @@ from .types import ListRulesResponse from .types import ListSSHKeysRequest from .types import ListSSHKeysResponse -from .types import ListUserConnectionsRequest -from .types import ListUserConnectionsResponse from .types import ListUsersRequest from .types import ListUsersResponse from .types import LockUserRequest @@ -132,12 +132,13 @@ "PermissionSetScopeType", "UserStatus", "UserType", + "GetUserConnectionsResponseConnectionConnectedOrganization", + "GetUserConnectionsResponseConnectionConnectedUser", "QuotumLimit", - "ListUserConnectionsResponseConnectionConnectedOrganization", - "ListUserConnectionsResponseConnectionConnectedUser", "JWT", "RuleSpecs", "CreateUserRequestMember", + "GetUserConnectionsResponseConnection", "APIKey", "Application", "GracePeriod", @@ -148,7 +149,6 @@ "Quotum", "Rule", "SSHKey", - "ListUserConnectionsResponseConnection", "User", "AddGroupMemberRequest", "AddGroupMembersRequest", @@ -179,6 +179,8 @@ "GetPolicyRequest", "GetQuotumRequest", "GetSSHKeyRequest", + "GetUserConnectionsRequest", + "GetUserConnectionsResponse", "GetUserRequest", "ListAPIKeysRequest", "ListAPIKeysResponse", @@ -202,8 +204,6 @@ "ListRulesResponse", "ListSSHKeysRequest", "ListSSHKeysResponse", - "ListUserConnectionsRequest", - "ListUserConnectionsResponse", "ListUsersRequest", "ListUsersResponse", "LockUserRequest", diff --git a/scaleway/scaleway/iam/v1alpha1/api.py b/scaleway/scaleway/iam/v1alpha1/api.py index 4284181ef..fdb229a5a 100644 --- a/scaleway/scaleway/iam/v1alpha1/api.py +++ b/scaleway/scaleway/iam/v1alpha1/api.py @@ -39,6 +39,7 @@ CreateUserRequest, CreateUserRequestMember, EncodedJWT, + GetUserConnectionsResponse, Group, JWT, ListAPIKeysResponse, @@ -52,7 +53,6 @@ ListQuotaResponse, ListRulesResponse, ListSSHKeysResponse, - ListUserConnectionsResponse, ListUsersResponse, Log, MFAOTP, @@ -91,6 +91,7 @@ unmarshal_SSHKey, unmarshal_User, unmarshal_EncodedJWT, + unmarshal_GetUserConnectionsResponse, unmarshal_ListAPIKeysResponse, unmarshal_ListApplicationsResponse, unmarshal_ListGracePeriodsResponse, @@ -102,7 +103,6 @@ unmarshal_ListQuotaResponse, unmarshal_ListRulesResponse, unmarshal_ListSSHKeysResponse, - unmarshal_ListUserConnectionsResponse, unmarshal_ListUsersResponse, unmarshal_MFAOTP, unmarshal_OrganizationSecuritySettings, @@ -853,19 +853,19 @@ def list_grace_periods( self._throw_on_error(res) return unmarshal_ListGracePeriodsResponse(res.json()) - def list_user_connections( + def get_user_connections( self, *, user_id: str, - ) -> ListUserConnectionsResponse: + ) -> GetUserConnectionsResponse: """ :param user_id: ID of the user to list connections for. - :return: :class:`ListUserConnectionsResponse ` + :return: :class:`GetUserConnectionsResponse ` Usage: :: - result = api.list_user_connections( + result = api.get_user_connections( user_id="example", ) """ @@ -878,7 +878,7 @@ def list_user_connections( ) self._throw_on_error(res) - return unmarshal_ListUserConnectionsResponse(res.json()) + return unmarshal_GetUserConnectionsResponse(res.json()) def list_applications( self, diff --git a/scaleway/scaleway/iam/v1alpha1/marshalling.py b/scaleway/scaleway/iam/v1alpha1/marshalling.py index a02759f70..4b35ea99c 100644 --- a/scaleway/scaleway/iam/v1alpha1/marshalling.py +++ b/scaleway/scaleway/iam/v1alpha1/marshalling.py @@ -21,6 +21,10 @@ SSHKey, User, EncodedJWT, + GetUserConnectionsResponseConnectionConnectedOrganization, + GetUserConnectionsResponseConnectionConnectedUser, + GetUserConnectionsResponseConnection, + GetUserConnectionsResponse, ListAPIKeysResponse, ListApplicationsResponse, GracePeriod, @@ -35,10 +39,6 @@ Rule, ListRulesResponse, ListSSHKeysResponse, - ListUserConnectionsResponseConnectionConnectedOrganization, - ListUserConnectionsResponseConnectionConnectedUser, - ListUserConnectionsResponseConnection, - ListUserConnectionsResponse, ListUsersResponse, MFAOTP, OrganizationSecuritySettings, @@ -704,6 +704,104 @@ def unmarshal_EncodedJWT(data: Any) -> EncodedJWT: return EncodedJWT(**args) +def unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization( + data: Any, +) -> GetUserConnectionsResponseConnectionConnectedOrganization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponseConnectionConnectedOrganization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("locked", None) + if field is not None: + args["locked"] = field + + return GetUserConnectionsResponseConnectionConnectedOrganization(**args) + + +def unmarshal_GetUserConnectionsResponseConnectionConnectedUser( + data: Any, +) -> GetUserConnectionsResponseConnectionConnectedUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponseConnectionConnectedUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return GetUserConnectionsResponseConnectionConnectedUser(**args) + + +def unmarshal_GetUserConnectionsResponseConnection( + data: Any, +) -> GetUserConnectionsResponseConnection: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponseConnection' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization", None) + if field is not None: + args["organization"] = ( + unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization(field) + ) + else: + args["organization"] = None + + field = data.get("user", None) + if field is not None: + args["user"] = unmarshal_GetUserConnectionsResponseConnectionConnectedUser( + field + ) + else: + args["user"] = None + + return GetUserConnectionsResponseConnection(**args) + + +def unmarshal_GetUserConnectionsResponse(data: Any) -> GetUserConnectionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connections", None) + if field is not None: + args["connections"] = ( + [unmarshal_GetUserConnectionsResponseConnection(v) for v in field] + if field is not None + else None + ) + + return GetUserConnectionsResponse(**args) + + def unmarshal_ListAPIKeysResponse(data: Any) -> ListAPIKeysResponse: if not isinstance(data, dict): raise TypeError( @@ -1034,104 +1132,6 @@ def unmarshal_ListSSHKeysResponse(data: Any) -> ListSSHKeysResponse: return ListSSHKeysResponse(**args) -def unmarshal_ListUserConnectionsResponseConnectionConnectedOrganization( - data: Any, -) -> ListUserConnectionsResponseConnectionConnectedOrganization: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListUserConnectionsResponseConnectionConnectedOrganization' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("id", None) - if field is not None: - args["id"] = field - - field = data.get("name", None) - if field is not None: - args["name"] = field - - field = data.get("locked", None) - if field is not None: - args["locked"] = field - - return ListUserConnectionsResponseConnectionConnectedOrganization(**args) - - -def unmarshal_ListUserConnectionsResponseConnectionConnectedUser( - data: Any, -) -> ListUserConnectionsResponseConnectionConnectedUser: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListUserConnectionsResponseConnectionConnectedUser' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("id", None) - if field is not None: - args["id"] = field - - field = data.get("username", None) - if field is not None: - args["username"] = field - - field = data.get("type", None) - if field is not None: - args["type_"] = field - - return ListUserConnectionsResponseConnectionConnectedUser(**args) - - -def unmarshal_ListUserConnectionsResponseConnection( - data: Any, -) -> ListUserConnectionsResponseConnection: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListUserConnectionsResponseConnection' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("organization", None) - if field is not None: - args["organization"] = ( - unmarshal_ListUserConnectionsResponseConnectionConnectedOrganization(field) - ) - else: - args["organization"] = None - - field = data.get("user", None) - if field is not None: - args["user"] = unmarshal_ListUserConnectionsResponseConnectionConnectedUser( - field - ) - else: - args["user"] = None - - return ListUserConnectionsResponseConnection(**args) - - -def unmarshal_ListUserConnectionsResponse(data: Any) -> ListUserConnectionsResponse: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListUserConnectionsResponse' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("connections", None) - if field is not None: - args["connections"] = ( - [unmarshal_ListUserConnectionsResponseConnection(v) for v in field] - if field is not None - else None - ) - - return ListUserConnectionsResponse(**args) - - def unmarshal_ListUsersResponse(data: Any) -> ListUsersResponse: if not isinstance(data, dict): raise TypeError( diff --git a/scaleway/scaleway/iam/v1alpha1/types.py b/scaleway/scaleway/iam/v1alpha1/types.py index 6d0a559a7..3d5b67aa2 100644 --- a/scaleway/scaleway/iam/v1alpha1/types.py +++ b/scaleway/scaleway/iam/v1alpha1/types.py @@ -207,20 +207,7 @@ def __str__(self) -> str: @dataclass -class QuotumLimit: - global_: Optional[bool] - - region: Optional[ScwRegion] - - zone: Optional[ScwZone] - - limit: Optional[int] - - unlimited: Optional[bool] - - -@dataclass -class ListUserConnectionsResponseConnectionConnectedOrganization: +class GetUserConnectionsResponseConnectionConnectedOrganization: id: str name: str @@ -229,7 +216,7 @@ class ListUserConnectionsResponseConnectionConnectedOrganization: @dataclass -class ListUserConnectionsResponseConnectionConnectedUser: +class GetUserConnectionsResponseConnectionConnectedUser: id: str username: str @@ -237,6 +224,19 @@ class ListUserConnectionsResponseConnectionConnectedUser: type_: UserType +@dataclass +class QuotumLimit: + global_: Optional[bool] + + region: Optional[ScwRegion] + + zone: Optional[ScwZone] + + limit: Optional[int] + + unlimited: Optional[bool] + + @dataclass class JWT: jti: str @@ -325,6 +325,19 @@ class CreateUserRequestMember: """ +@dataclass +class GetUserConnectionsResponseConnection: + organization: Optional[GetUserConnectionsResponseConnectionConnectedOrganization] + """ + Information about the connected organization. + """ + + user: Optional[GetUserConnectionsResponseConnectionConnectedUser] + """ + Information about the connected user. + """ + + @dataclass class APIKey: access_key: str @@ -792,19 +805,6 @@ class SSHKey: """ -@dataclass -class ListUserConnectionsResponseConnection: - organization: Optional[ListUserConnectionsResponseConnectionConnectedOrganization] - """ - Information about the connected organization. - """ - - user: Optional[ListUserConnectionsResponseConnectionConnectedUser] - """ - Information about the connected user. - """ - - @dataclass class User: id: str @@ -1234,6 +1234,22 @@ class GetSSHKeyRequest: """ +@dataclass +class GetUserConnectionsRequest: + user_id: str + """ + ID of the user to list connections for. + """ + + +@dataclass +class GetUserConnectionsResponse: + connections: List[GetUserConnectionsResponseConnection] + """ + List of connections. + """ + + @dataclass class GetUserRequest: user_id: str @@ -1781,22 +1797,6 @@ class ListSSHKeysResponse: """ -@dataclass -class ListUserConnectionsRequest: - user_id: str - """ - ID of the user to list connections for. - """ - - -@dataclass -class ListUserConnectionsResponse: - connections: List[ListUserConnectionsResponseConnection] - """ - List of connections. - """ - - @dataclass class ListUsersRequest: order_by: Optional[ListUsersRequestOrderBy] From b22de82204bc93b9fe02b4777d1b5425acff0c72 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Mar 2025 17:31:42 +0100 Subject: [PATCH 49/73] docs(billing): add info about resellers (#890) --- scaleway-async/scaleway_async/billing/v2beta1/api.py | 10 ++++++++-- scaleway-async/scaleway_async/billing/v2beta1/types.py | 2 +- scaleway/scaleway/billing/v2beta1/api.py | 10 ++++++++-- scaleway/scaleway/billing/v2beta1/types.py | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/scaleway-async/scaleway_async/billing/v2beta1/api.py b/scaleway-async/scaleway_async/billing/v2beta1/api.py index 3992ded4f..3b1e1350f 100644 --- a/scaleway-async/scaleway_async/billing/v2beta1/api.py +++ b/scaleway-async/scaleway_async/billing/v2beta1/api.py @@ -438,7 +438,10 @@ async def list_discounts( ) -> ListDiscountsResponse: """ List discounts. - List all discounts for your organization and usable categories, products, offers, references, regions and zones where the discount can be applied. + List all discounts for your Organization and usable categories, products, offers, references, regions and zones where the discount can be applied. As a reseller: + - If you do not specify an `organization_id` you will list the discounts applied to your own Organization and your customers + - If you indicate your `organization_id` you will list only the discounts applied to your Organization + - If you indicate `the organization_id` of one of your customers, you will list the discounts applied to their Organization. :param order_by: Order discounts in the response by their description. :param page: Positive integer to choose the page to return. :param page_size: Positive integer lower or equal to 100 to select the number of items to return. @@ -476,7 +479,10 @@ async def list_discounts_all( ) -> List[Discount]: """ List discounts. - List all discounts for your organization and usable categories, products, offers, references, regions and zones where the discount can be applied. + List all discounts for your Organization and usable categories, products, offers, references, regions and zones where the discount can be applied. As a reseller: + - If you do not specify an `organization_id` you will list the discounts applied to your own Organization and your customers + - If you indicate your `organization_id` you will list only the discounts applied to your Organization + - If you indicate `the organization_id` of one of your customers, you will list the discounts applied to their Organization. :param order_by: Order discounts in the response by their description. :param page: Positive integer to choose the page to return. :param page_size: Positive integer lower or equal to 100 to select the number of items to return. diff --git a/scaleway-async/scaleway_async/billing/v2beta1/types.py b/scaleway-async/scaleway_async/billing/v2beta1/types.py index 6db2ab66d..3bb5b5d25 100644 --- a/scaleway-async/scaleway_async/billing/v2beta1/types.py +++ b/scaleway-async/scaleway_async/billing/v2beta1/types.py @@ -211,7 +211,7 @@ class Discount: organization_id: str """ - The organization ID of the discount. + The Organization ID of the discount. """ description: str diff --git a/scaleway/scaleway/billing/v2beta1/api.py b/scaleway/scaleway/billing/v2beta1/api.py index bff464ff5..268bf0327 100644 --- a/scaleway/scaleway/billing/v2beta1/api.py +++ b/scaleway/scaleway/billing/v2beta1/api.py @@ -438,7 +438,10 @@ def list_discounts( ) -> ListDiscountsResponse: """ List discounts. - List all discounts for your organization and usable categories, products, offers, references, regions and zones where the discount can be applied. + List all discounts for your Organization and usable categories, products, offers, references, regions and zones where the discount can be applied. As a reseller: + - If you do not specify an `organization_id` you will list the discounts applied to your own Organization and your customers + - If you indicate your `organization_id` you will list only the discounts applied to your Organization + - If you indicate `the organization_id` of one of your customers, you will list the discounts applied to their Organization. :param order_by: Order discounts in the response by their description. :param page: Positive integer to choose the page to return. :param page_size: Positive integer lower or equal to 100 to select the number of items to return. @@ -476,7 +479,10 @@ def list_discounts_all( ) -> List[Discount]: """ List discounts. - List all discounts for your organization and usable categories, products, offers, references, regions and zones where the discount can be applied. + List all discounts for your Organization and usable categories, products, offers, references, regions and zones where the discount can be applied. As a reseller: + - If you do not specify an `organization_id` you will list the discounts applied to your own Organization and your customers + - If you indicate your `organization_id` you will list only the discounts applied to your Organization + - If you indicate `the organization_id` of one of your customers, you will list the discounts applied to their Organization. :param order_by: Order discounts in the response by their description. :param page: Positive integer to choose the page to return. :param page_size: Positive integer lower or equal to 100 to select the number of items to return. diff --git a/scaleway/scaleway/billing/v2beta1/types.py b/scaleway/scaleway/billing/v2beta1/types.py index 6db2ab66d..3bb5b5d25 100644 --- a/scaleway/scaleway/billing/v2beta1/types.py +++ b/scaleway/scaleway/billing/v2beta1/types.py @@ -211,7 +211,7 @@ class Discount: organization_id: str """ - The organization ID of the discount. + The Organization ID of the discount. """ description: str From c571b7aaeda475402f92e7f3f33ee5dafc00a118 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Mar 2025 17:39:46 +0100 Subject: [PATCH 50/73] docs(vpc_gw): document MigrateToV2 (#894) --- scaleway-async/scaleway_async/vpcgw/v1/api.py | 4 +++- scaleway-async/scaleway_async/vpcgw/v1/types.py | 3 +++ scaleway/scaleway/vpcgw/v1/api.py | 4 +++- scaleway/scaleway/vpcgw/v1/types.py | 3 +++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/scaleway-async/scaleway_async/vpcgw/v1/api.py b/scaleway-async/scaleway_async/vpcgw/v1/api.py index b881fa2d5..0300c0f74 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/api.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/api.py @@ -2088,7 +2088,9 @@ async def migrate_to_v2( zone: Optional[ScwZone] = None, ) -> None: """ - :param gateway_id: + Put a Public Gateway in IPAM mode. + Put a Public Gateway in IPAM mode, so that it can be used with the Public Gateways API v2. This call is idempotent. + :param gateway_id: ID of the gateway to put into IPAM mode. :param zone: Zone to target. If none is passed will use default zone from the config. Usage: diff --git a/scaleway-async/scaleway_async/vpcgw/v1/types.py b/scaleway-async/scaleway_async/vpcgw/v1/types.py index ab3696792..bb1c21bdc 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/types.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/types.py @@ -1443,6 +1443,9 @@ class ListPATRulesResponse: @dataclass class MigrateToV2Request: gateway_id: str + """ + ID of the gateway to put into IPAM mode. + """ zone: Optional[ScwZone] """ diff --git a/scaleway/scaleway/vpcgw/v1/api.py b/scaleway/scaleway/vpcgw/v1/api.py index 02cc47d33..732fe41c2 100644 --- a/scaleway/scaleway/vpcgw/v1/api.py +++ b/scaleway/scaleway/vpcgw/v1/api.py @@ -2086,7 +2086,9 @@ def migrate_to_v2( zone: Optional[ScwZone] = None, ) -> None: """ - :param gateway_id: + Put a Public Gateway in IPAM mode. + Put a Public Gateway in IPAM mode, so that it can be used with the Public Gateways API v2. This call is idempotent. + :param gateway_id: ID of the gateway to put into IPAM mode. :param zone: Zone to target. If none is passed will use default zone from the config. Usage: diff --git a/scaleway/scaleway/vpcgw/v1/types.py b/scaleway/scaleway/vpcgw/v1/types.py index ab3696792..bb1c21bdc 100644 --- a/scaleway/scaleway/vpcgw/v1/types.py +++ b/scaleway/scaleway/vpcgw/v1/types.py @@ -1443,6 +1443,9 @@ class ListPATRulesResponse: @dataclass class MigrateToV2Request: gateway_id: str + """ + ID of the gateway to put into IPAM mode. + """ zone: Optional[ScwZone] """ From db3d85c5fd510283cccb49ecebfc8a957005bd66 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Mar 2025 17:55:08 +0100 Subject: [PATCH 51/73] feat(mongodb): add sync role (#893) --- scaleway-async/scaleway_async/mongodb/v1alpha1/types.py | 1 + scaleway/scaleway/mongodb/v1alpha1/types.py | 1 + 2 files changed, 2 insertions(+) diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py index 422e5431a..6dec8aa41 100644 --- a/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py @@ -100,6 +100,7 @@ class UserRoleRole(str, Enum, metaclass=StrEnumMeta): READ = "read" READ_WRITE = "read_write" DB_ADMIN = "db_admin" + SYNC = "sync" def __str__(self) -> str: return str(self.value) diff --git a/scaleway/scaleway/mongodb/v1alpha1/types.py b/scaleway/scaleway/mongodb/v1alpha1/types.py index 422e5431a..6dec8aa41 100644 --- a/scaleway/scaleway/mongodb/v1alpha1/types.py +++ b/scaleway/scaleway/mongodb/v1alpha1/types.py @@ -100,6 +100,7 @@ class UserRoleRole(str, Enum, metaclass=StrEnumMeta): READ = "read" READ_WRITE = "read_write" DB_ADMIN = "db_admin" + SYNC = "sync" def __str__(self) -> str: return str(self.value) From cfd074e4f48567f3cd10407820b9abca184d74b8 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Mar 2025 17:57:40 +0100 Subject: [PATCH 52/73] feat(secret_manager): remove restore methods (#892) --- .../scaleway_async/secret/v1beta1/__init__.py | 4 - .../scaleway_async/secret/v1beta1/api.py | 74 ------------------- .../scaleway_async/secret/v1beta1/types.py | 22 ------ scaleway/scaleway/secret/v1beta1/__init__.py | 4 - scaleway/scaleway/secret/v1beta1/api.py | 74 ------------------- scaleway/scaleway/secret/v1beta1/types.py | 22 ------ 6 files changed, 200 deletions(-) diff --git a/scaleway-async/scaleway_async/secret/v1beta1/__init__.py b/scaleway-async/scaleway_async/secret/v1beta1/__init__.py index 531ccc836..b55546b45 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/__init__.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/__init__.py @@ -39,8 +39,6 @@ from .types import ListTagsRequest from .types import ListTagsResponse from .types import ProtectSecretRequest -from .types import RestoreSecretRequest -from .types import RestoreSecretVersionRequest from .types import SSHKey from .types import UnprotectSecretRequest from .types import UpdateSecretRequest @@ -87,8 +85,6 @@ "ListTagsRequest", "ListTagsResponse", "ProtectSecretRequest", - "RestoreSecretRequest", - "RestoreSecretVersionRequest", "SSHKey", "UnprotectSecretRequest", "UpdateSecretRequest", diff --git a/scaleway-async/scaleway_async/secret/v1beta1/api.py b/scaleway-async/scaleway_async/secret/v1beta1/api.py index ba9e33d19..212f05d92 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/api.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/api.py @@ -1130,77 +1130,3 @@ async def list_secret_types_all( "page_size": page_size, }, ) - - async def restore_secret_version( - self, - *, - secret_id: str, - revision: str, - region: Optional[ScwRegion] = None, - ) -> SecretVersion: - """ - Restore a version. - Restore a secret's version specified by the `region`, `secret_id` and `revision` parameters. - :param secret_id: - :param revision: - :param region: Region to target. If none is passed will use default region from the config. - :return: :class:`SecretVersion ` - - Usage: - :: - - result = await api.restore_secret_version( - secret_id="example", - revision="example", - ) - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - param_secret_id = validate_path_param("secret_id", secret_id) - param_revision = validate_path_param("revision", revision) - - res = self._request( - "POST", - f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/versions/{param_revision}/restore", - body={}, - ) - - self._throw_on_error(res) - return unmarshal_SecretVersion(res.json()) - - async def restore_secret( - self, - *, - secret_id: str, - region: Optional[ScwRegion] = None, - ) -> Secret: - """ - Restore a secret. - Restore a secret and all its versions scheduled for deletion specified by the `region` and `secret_id` parameters. - :param secret_id: - :param region: Region to target. If none is passed will use default region from the config. - :return: :class:`Secret ` - - Usage: - :: - - result = await api.restore_secret( - secret_id="example", - ) - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - param_secret_id = validate_path_param("secret_id", secret_id) - - res = self._request( - "POST", - f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/restore", - body={}, - ) - - self._throw_on_error(res) - return unmarshal_Secret(res.json()) diff --git a/scaleway-async/scaleway_async/secret/v1beta1/types.py b/scaleway-async/scaleway_async/secret/v1beta1/types.py index fe66cfee0..a151422ed 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/types.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/types.py @@ -866,28 +866,6 @@ class ProtectSecretRequest: """ -@dataclass -class RestoreSecretRequest: - secret_id: str - - region: Optional[ScwRegion] - """ - Region to target. If none is passed will use default region from the config. - """ - - -@dataclass -class RestoreSecretVersionRequest: - secret_id: str - - revision: str - - region: Optional[ScwRegion] - """ - Region to target. If none is passed will use default region from the config. - """ - - @dataclass class SSHKey: ssh_private_key: str diff --git a/scaleway/scaleway/secret/v1beta1/__init__.py b/scaleway/scaleway/secret/v1beta1/__init__.py index 531ccc836..b55546b45 100644 --- a/scaleway/scaleway/secret/v1beta1/__init__.py +++ b/scaleway/scaleway/secret/v1beta1/__init__.py @@ -39,8 +39,6 @@ from .types import ListTagsRequest from .types import ListTagsResponse from .types import ProtectSecretRequest -from .types import RestoreSecretRequest -from .types import RestoreSecretVersionRequest from .types import SSHKey from .types import UnprotectSecretRequest from .types import UpdateSecretRequest @@ -87,8 +85,6 @@ "ListTagsRequest", "ListTagsResponse", "ProtectSecretRequest", - "RestoreSecretRequest", - "RestoreSecretVersionRequest", "SSHKey", "UnprotectSecretRequest", "UpdateSecretRequest", diff --git a/scaleway/scaleway/secret/v1beta1/api.py b/scaleway/scaleway/secret/v1beta1/api.py index bbe3bce8a..4f393f4a9 100644 --- a/scaleway/scaleway/secret/v1beta1/api.py +++ b/scaleway/scaleway/secret/v1beta1/api.py @@ -1130,77 +1130,3 @@ def list_secret_types_all( "page_size": page_size, }, ) - - def restore_secret_version( - self, - *, - secret_id: str, - revision: str, - region: Optional[ScwRegion] = None, - ) -> SecretVersion: - """ - Restore a version. - Restore a secret's version specified by the `region`, `secret_id` and `revision` parameters. - :param secret_id: - :param revision: - :param region: Region to target. If none is passed will use default region from the config. - :return: :class:`SecretVersion ` - - Usage: - :: - - result = api.restore_secret_version( - secret_id="example", - revision="example", - ) - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - param_secret_id = validate_path_param("secret_id", secret_id) - param_revision = validate_path_param("revision", revision) - - res = self._request( - "POST", - f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/versions/{param_revision}/restore", - body={}, - ) - - self._throw_on_error(res) - return unmarshal_SecretVersion(res.json()) - - def restore_secret( - self, - *, - secret_id: str, - region: Optional[ScwRegion] = None, - ) -> Secret: - """ - Restore a secret. - Restore a secret and all its versions scheduled for deletion specified by the `region` and `secret_id` parameters. - :param secret_id: - :param region: Region to target. If none is passed will use default region from the config. - :return: :class:`Secret ` - - Usage: - :: - - result = api.restore_secret( - secret_id="example", - ) - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - param_secret_id = validate_path_param("secret_id", secret_id) - - res = self._request( - "POST", - f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/restore", - body={}, - ) - - self._throw_on_error(res) - return unmarshal_Secret(res.json()) diff --git a/scaleway/scaleway/secret/v1beta1/types.py b/scaleway/scaleway/secret/v1beta1/types.py index fe66cfee0..a151422ed 100644 --- a/scaleway/scaleway/secret/v1beta1/types.py +++ b/scaleway/scaleway/secret/v1beta1/types.py @@ -866,28 +866,6 @@ class ProtectSecretRequest: """ -@dataclass -class RestoreSecretRequest: - secret_id: str - - region: Optional[ScwRegion] - """ - Region to target. If none is passed will use default region from the config. - """ - - -@dataclass -class RestoreSecretVersionRequest: - secret_id: str - - revision: str - - region: Optional[ScwRegion] - """ - Region to target. If none is passed will use default region from the config. - """ - - @dataclass class SSHKey: ssh_private_key: str From 2fcc599345ea560265b8431da8700dc64952573b Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 6 Mar 2025 18:12:25 +0100 Subject: [PATCH 53/73] feat(audit_trail): add support for service_name (#891) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémy Léone --- scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py | 5 ++++- .../scaleway_async/audit_trail/v1alpha1/types.py | 7 ++++++- scaleway/scaleway/audit_trail/v1alpha1/api.py | 5 ++++- scaleway/scaleway/audit_trail/v1alpha1/types.py | 7 ++++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py index f881959b3..143a8da7c 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py @@ -43,6 +43,7 @@ async def list_events( page_size: Optional[int] = None, page_token: Optional[str] = None, product_name: Optional[str] = None, + service_name: Optional[str] = None, ) -> ListEventsResponse: """ List events. @@ -51,7 +52,7 @@ async def list_events( :param project_id: (Optional) ID of the Project containing the Audit Trail events. :param organization_id: ID of the Organization containing the Audit Trail events. :param resource_type: (Optional) Returns a paginated list of Scaleway resources' features. - :param method_name: (Optional) Name of the method or the API call performed. + :param method_name: (Optional) Name of the method of the API call performed. :param status: (Optional) HTTP status code of the request. Returns either `200` if the request was successful or `403` if the permission was denied. :param recorded_after: (Optional) The `recorded_after` parameter defines the earliest timestamp from which Audit Trail events are retrieved. Returns `one hour ago` by default. :param recorded_before: (Optional) The `recorded_before` parameter defines the latest timestamp up to which Audit Trail events are retrieved. Returns `now` by default. @@ -59,6 +60,7 @@ async def list_events( :param page_size: :param page_token: :param product_name: (Optional) Name of the Scaleway resource in a hyphenated format. + :param service_name: (Optional) Name of the service of the API call performed. :return: :class:`ListEventsResponse ` Usage: @@ -86,6 +88,7 @@ async def list_events( "recorded_after": recorded_after, "recorded_before": recorded_before, "resource_type": resource_type, + "service_name": service_name, "status": status, }, ) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py index f58c9ff5d..f38912960 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py @@ -257,7 +257,7 @@ class ListEventsRequest: method_name: Optional[str] """ - (Optional) Name of the method or the API call performed. + (Optional) Name of the method of the API call performed. """ status: Optional[int] @@ -286,6 +286,11 @@ class ListEventsRequest: (Optional) Name of the Scaleway resource in a hyphenated format. """ + service_name: Optional[str] + """ + (Optional) Name of the service of the API call performed. + """ + @dataclass class ListEventsResponse: diff --git a/scaleway/scaleway/audit_trail/v1alpha1/api.py b/scaleway/scaleway/audit_trail/v1alpha1/api.py index 5b82ec892..f2e593c99 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/api.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/api.py @@ -43,6 +43,7 @@ def list_events( page_size: Optional[int] = None, page_token: Optional[str] = None, product_name: Optional[str] = None, + service_name: Optional[str] = None, ) -> ListEventsResponse: """ List events. @@ -51,7 +52,7 @@ def list_events( :param project_id: (Optional) ID of the Project containing the Audit Trail events. :param organization_id: ID of the Organization containing the Audit Trail events. :param resource_type: (Optional) Returns a paginated list of Scaleway resources' features. - :param method_name: (Optional) Name of the method or the API call performed. + :param method_name: (Optional) Name of the method of the API call performed. :param status: (Optional) HTTP status code of the request. Returns either `200` if the request was successful or `403` if the permission was denied. :param recorded_after: (Optional) The `recorded_after` parameter defines the earliest timestamp from which Audit Trail events are retrieved. Returns `one hour ago` by default. :param recorded_before: (Optional) The `recorded_before` parameter defines the latest timestamp up to which Audit Trail events are retrieved. Returns `now` by default. @@ -59,6 +60,7 @@ def list_events( :param page_size: :param page_token: :param product_name: (Optional) Name of the Scaleway resource in a hyphenated format. + :param service_name: (Optional) Name of the service of the API call performed. :return: :class:`ListEventsResponse ` Usage: @@ -86,6 +88,7 @@ def list_events( "recorded_after": recorded_after, "recorded_before": recorded_before, "resource_type": resource_type, + "service_name": service_name, "status": status, }, ) diff --git a/scaleway/scaleway/audit_trail/v1alpha1/types.py b/scaleway/scaleway/audit_trail/v1alpha1/types.py index f58c9ff5d..f38912960 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/types.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/types.py @@ -257,7 +257,7 @@ class ListEventsRequest: method_name: Optional[str] """ - (Optional) Name of the method or the API call performed. + (Optional) Name of the method of the API call performed. """ status: Optional[int] @@ -286,6 +286,11 @@ class ListEventsRequest: (Optional) Name of the Scaleway resource in a hyphenated format. """ + service_name: Optional[str] + """ + (Optional) Name of the service of the API call performed. + """ + @dataclass class ListEventsResponse: From da597ef24a81180948a24d46a593b6487b4371ba Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 10 Mar 2025 10:48:07 +0100 Subject: [PATCH 54/73] feat(tem): deprecate accept tos on create domain (#896) --- .../scaleway_async/tem/v1alpha1/api.py | 11 +++++------ .../scaleway_async/tem/v1alpha1/marshalling.py | 6 +++--- .../scaleway_async/tem/v1alpha1/types.py | 16 ++++++++-------- scaleway/scaleway/tem/v1alpha1/api.py | 11 +++++------ scaleway/scaleway/tem/v1alpha1/marshalling.py | 6 +++--- scaleway/scaleway/tem/v1alpha1/types.py | 16 ++++++++-------- 6 files changed, 32 insertions(+), 34 deletions(-) diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/api.py b/scaleway-async/scaleway_async/tem/v1alpha1/api.py index db7166175..30e91467b 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/api.py @@ -261,7 +261,7 @@ async def list_emails( :param since: (Optional) List emails created after this date. :param until: (Optional) List emails created before this date. :param mail_from: (Optional) List emails sent with this sender's email address. - :param mail_to: List emails sent to this recipient's email address. + :param mail_to: Deprecated. List emails sent to this recipient's email address. :param mail_rcpt: (Optional) List emails sent to this recipient's email address. :param statuses: (Optional) List emails with any of these statuses. :param subject: (Optional) List emails with this subject. @@ -337,7 +337,7 @@ async def list_emails_all( :param since: (Optional) List emails created after this date. :param until: (Optional) List emails created before this date. :param mail_from: (Optional) List emails sent with this sender's email address. - :param mail_to: List emails sent to this recipient's email address. + :param mail_to: Deprecated. List emails sent to this recipient's email address. :param mail_rcpt: (Optional) List emails sent to this recipient's email address. :param statuses: (Optional) List emails with any of these statuses. :param subject: (Optional) List emails with this subject. @@ -461,19 +461,19 @@ async def create_domain( self, *, domain_name: str, - accept_tos: bool, autoconfig: bool, region: Optional[ScwRegion] = None, project_id: Optional[str] = None, + accept_tos: Optional[bool] = None, ) -> Domain: """ Register a domain in a project. You must specify the `region`, `project_id` and `domain_name` to register a domain in a specific Project. :param domain_name: Fully qualified domain dame. - :param accept_tos: Accept Scaleway's Terms of Service. :param autoconfig: Activate auto-configuration of the domain's DNS zone. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the project to which the domain belongs. + :param accept_tos: Deprecated. Accept Scaleway's Terms of Service. :return: :class:`Domain ` Usage: @@ -481,7 +481,6 @@ async def create_domain( result = await api.create_domain( domain_name="example", - accept_tos=False, autoconfig=False, ) """ @@ -496,10 +495,10 @@ async def create_domain( body=marshal_CreateDomainRequest( CreateDomainRequest( domain_name=domain_name, - accept_tos=accept_tos, autoconfig=autoconfig, region=region, project_id=project_id, + accept_tos=accept_tos, ), self.client, ), diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py index 9d454d9d4..453356bb7 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py @@ -930,15 +930,15 @@ def marshal_CreateDomainRequest( if request.domain_name is not None: output["domain_name"] = request.domain_name - if request.accept_tos is not None: - output["accept_tos"] = request.accept_tos - if request.autoconfig is not None: output["autoconfig"] = request.autoconfig if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id + if request.accept_tos is not None: + output["accept_tos"] = request.accept_tos + return output diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/types.py b/scaleway-async/scaleway_async/tem/v1alpha1/types.py index 8c14d630f..dc7a8a3e3 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/types.py @@ -388,7 +388,7 @@ class Email: rcpt_to: Optional[str] """ - Email address of the recipient. + Deprecated. Email address of the recipient. """ rcpt_type: EmailRcptType @@ -578,7 +578,7 @@ class Domain: last_error: Optional[str] """ - Error message returned if the last check failed. + Deprecated. Error message returned if the last check failed. """ statistics: Optional[DomainStatistics] @@ -818,11 +818,6 @@ class CreateDomainRequest: Fully qualified domain dame. """ - accept_tos: bool - """ - Accept Scaleway's Terms of Service. - """ - autoconfig: bool """ Activate auto-configuration of the domain's DNS zone. @@ -838,6 +833,11 @@ class CreateDomainRequest: ID of the project to which the domain belongs. """ + accept_tos: Optional[bool] + """ + Deprecated. Accept Scaleway's Terms of Service. + """ + @dataclass class CreateEmailRequest: @@ -1250,7 +1250,7 @@ class ListEmailsRequest: mail_to: Optional[str] """ - List emails sent to this recipient's email address. + Deprecated. List emails sent to this recipient's email address. """ mail_rcpt: Optional[str] diff --git a/scaleway/scaleway/tem/v1alpha1/api.py b/scaleway/scaleway/tem/v1alpha1/api.py index 390cb9dd5..b3aefea5c 100644 --- a/scaleway/scaleway/tem/v1alpha1/api.py +++ b/scaleway/scaleway/tem/v1alpha1/api.py @@ -261,7 +261,7 @@ def list_emails( :param since: (Optional) List emails created after this date. :param until: (Optional) List emails created before this date. :param mail_from: (Optional) List emails sent with this sender's email address. - :param mail_to: List emails sent to this recipient's email address. + :param mail_to: Deprecated. List emails sent to this recipient's email address. :param mail_rcpt: (Optional) List emails sent to this recipient's email address. :param statuses: (Optional) List emails with any of these statuses. :param subject: (Optional) List emails with this subject. @@ -337,7 +337,7 @@ def list_emails_all( :param since: (Optional) List emails created after this date. :param until: (Optional) List emails created before this date. :param mail_from: (Optional) List emails sent with this sender's email address. - :param mail_to: List emails sent to this recipient's email address. + :param mail_to: Deprecated. List emails sent to this recipient's email address. :param mail_rcpt: (Optional) List emails sent to this recipient's email address. :param statuses: (Optional) List emails with any of these statuses. :param subject: (Optional) List emails with this subject. @@ -461,19 +461,19 @@ def create_domain( self, *, domain_name: str, - accept_tos: bool, autoconfig: bool, region: Optional[ScwRegion] = None, project_id: Optional[str] = None, + accept_tos: Optional[bool] = None, ) -> Domain: """ Register a domain in a project. You must specify the `region`, `project_id` and `domain_name` to register a domain in a specific Project. :param domain_name: Fully qualified domain dame. - :param accept_tos: Accept Scaleway's Terms of Service. :param autoconfig: Activate auto-configuration of the domain's DNS zone. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the project to which the domain belongs. + :param accept_tos: Deprecated. Accept Scaleway's Terms of Service. :return: :class:`Domain ` Usage: @@ -481,7 +481,6 @@ def create_domain( result = api.create_domain( domain_name="example", - accept_tos=False, autoconfig=False, ) """ @@ -496,10 +495,10 @@ def create_domain( body=marshal_CreateDomainRequest( CreateDomainRequest( domain_name=domain_name, - accept_tos=accept_tos, autoconfig=autoconfig, region=region, project_id=project_id, + accept_tos=accept_tos, ), self.client, ), diff --git a/scaleway/scaleway/tem/v1alpha1/marshalling.py b/scaleway/scaleway/tem/v1alpha1/marshalling.py index 9d454d9d4..453356bb7 100644 --- a/scaleway/scaleway/tem/v1alpha1/marshalling.py +++ b/scaleway/scaleway/tem/v1alpha1/marshalling.py @@ -930,15 +930,15 @@ def marshal_CreateDomainRequest( if request.domain_name is not None: output["domain_name"] = request.domain_name - if request.accept_tos is not None: - output["accept_tos"] = request.accept_tos - if request.autoconfig is not None: output["autoconfig"] = request.autoconfig if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id + if request.accept_tos is not None: + output["accept_tos"] = request.accept_tos + return output diff --git a/scaleway/scaleway/tem/v1alpha1/types.py b/scaleway/scaleway/tem/v1alpha1/types.py index 8c14d630f..dc7a8a3e3 100644 --- a/scaleway/scaleway/tem/v1alpha1/types.py +++ b/scaleway/scaleway/tem/v1alpha1/types.py @@ -388,7 +388,7 @@ class Email: rcpt_to: Optional[str] """ - Email address of the recipient. + Deprecated. Email address of the recipient. """ rcpt_type: EmailRcptType @@ -578,7 +578,7 @@ class Domain: last_error: Optional[str] """ - Error message returned if the last check failed. + Deprecated. Error message returned if the last check failed. """ statistics: Optional[DomainStatistics] @@ -818,11 +818,6 @@ class CreateDomainRequest: Fully qualified domain dame. """ - accept_tos: bool - """ - Accept Scaleway's Terms of Service. - """ - autoconfig: bool """ Activate auto-configuration of the domain's DNS zone. @@ -838,6 +833,11 @@ class CreateDomainRequest: ID of the project to which the domain belongs. """ + accept_tos: Optional[bool] + """ + Deprecated. Accept Scaleway's Terms of Service. + """ + @dataclass class CreateEmailRequest: @@ -1250,7 +1250,7 @@ class ListEmailsRequest: mail_to: Optional[str] """ - List emails sent to this recipient's email address. + Deprecated. List emails sent to this recipient's email address. """ mail_rcpt: Optional[str] From 181fab3c2d33e1364341c0183277d8d25d325398 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 10 Mar 2025 10:50:55 +0100 Subject: [PATCH 55/73] fix(edge_services): miss route-stages on httprule of ListRouteRules (#897) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> --- scaleway-async/scaleway_async/edge_services/v1beta1/api.py | 2 +- scaleway/scaleway/edge_services/v1beta1/api.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/api.py b/scaleway-async/scaleway_async/edge_services/v1beta1/api.py index 045850ee2..752b0aecf 100644 --- a/scaleway-async/scaleway_async/edge_services/v1beta1/api.py +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/api.py @@ -2042,7 +2042,7 @@ async def list_route_rules( res = self._request( "GET", - f"/edge-services/v1beta1/{param_route_stage_id}/route-rules", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", ) self._throw_on_error(res) diff --git a/scaleway/scaleway/edge_services/v1beta1/api.py b/scaleway/scaleway/edge_services/v1beta1/api.py index 06c92a1c4..106a0a4df 100644 --- a/scaleway/scaleway/edge_services/v1beta1/api.py +++ b/scaleway/scaleway/edge_services/v1beta1/api.py @@ -2040,7 +2040,7 @@ def list_route_rules( res = self._request( "GET", - f"/edge-services/v1beta1/{param_route_stage_id}/route-rules", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", ) self._throw_on_error(res) From 64be3c65c766929e14d2ab47efdf4d994f61efcf Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 10 Mar 2025 11:10:42 +0100 Subject: [PATCH 56/73] feat(audit_trail): add missing iam_rule type (#898) --- scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py | 1 + scaleway/scaleway/audit_trail/v1alpha1/types.py | 1 + 2 files changed, 2 insertions(+) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py index f38912960..ddbcc1424 100644 --- a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py @@ -38,6 +38,7 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): IAM_POLICY = "iam_policy" IAM_API_KEY = "iam_api_key" IAM_SSH_KEY = "iam_ssh_key" + IAM_RULE = "iam_rule" SECRET_MANAGER_SECRET = "secret_manager_secret" SECRET_MANAGER_VERSION = "secret_manager_version" KEY_MANAGER_KEY = "key_manager_key" diff --git a/scaleway/scaleway/audit_trail/v1alpha1/types.py b/scaleway/scaleway/audit_trail/v1alpha1/types.py index f38912960..ddbcc1424 100644 --- a/scaleway/scaleway/audit_trail/v1alpha1/types.py +++ b/scaleway/scaleway/audit_trail/v1alpha1/types.py @@ -38,6 +38,7 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): IAM_POLICY = "iam_policy" IAM_API_KEY = "iam_api_key" IAM_SSH_KEY = "iam_ssh_key" + IAM_RULE = "iam_rule" SECRET_MANAGER_SECRET = "secret_manager_secret" SECRET_MANAGER_VERSION = "secret_manager_version" KEY_MANAGER_KEY = "key_manager_key" From d95674fb2d0a360017a32308378cfdbefe3167b5 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 10 Mar 2025 16:48:41 +0100 Subject: [PATCH 57/73] fix(apple_silicon): document commitment type values and usage (#899) --- scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py | 2 +- scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py | 2 +- scaleway/scaleway/applesilicon/v1alpha1/api.py | 2 +- scaleway/scaleway/applesilicon/v1alpha1/types.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py index d6d3c829b..15711479a 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py @@ -146,7 +146,7 @@ async def create_server( :param name: Create a server with this given name. :param project_id: Create a server in the given project ID. :param os_id: Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. - :param commitment_type: Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing. It can be updated with the Update Server request. Available commitment depends on server type. + :param commitment_type: Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing (commitment_type `duration_24h`). It can be updated with the Update Server request. Available commitment depends on server type. :return: :class:`Server ` Usage: diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py index 7826d2b8a..692f3e59d 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py @@ -465,7 +465,7 @@ class CreateServerRequest: commitment_type: Optional[CommitmentType] """ - Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing. It can be updated with the Update Server request. Available commitment depends on server type. + Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing (commitment_type `duration_24h`). It can be updated with the Update Server request. Available commitment depends on server type. """ diff --git a/scaleway/scaleway/applesilicon/v1alpha1/api.py b/scaleway/scaleway/applesilicon/v1alpha1/api.py index 2ed357428..8a0fc312e 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/api.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/api.py @@ -146,7 +146,7 @@ def create_server( :param name: Create a server with this given name. :param project_id: Create a server in the given project ID. :param os_id: Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. - :param commitment_type: Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing. It can be updated with the Update Server request. Available commitment depends on server type. + :param commitment_type: Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing (commitment_type `duration_24h`). It can be updated with the Update Server request. Available commitment depends on server type. :return: :class:`Server ` Usage: diff --git a/scaleway/scaleway/applesilicon/v1alpha1/types.py b/scaleway/scaleway/applesilicon/v1alpha1/types.py index 7826d2b8a..692f3e59d 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/types.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/types.py @@ -465,7 +465,7 @@ class CreateServerRequest: commitment_type: Optional[CommitmentType] """ - Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing. It can be updated with the Update Server request. Available commitment depends on server type. + Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing (commitment_type `duration_24h`). It can be updated with the Update Server request. Available commitment depends on server type. """ From 0abb8a9a783c4a7c82b40cce0b010077c502486f Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 10 Mar 2025 16:50:36 +0100 Subject: [PATCH 58/73] feat(iam): add status filter to ListUsersRequest (#900) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> --- scaleway-async/scaleway_async/iam/v1alpha1/api.py | 7 +++++++ scaleway-async/scaleway_async/iam/v1alpha1/types.py | 5 +++++ scaleway/scaleway/iam/v1alpha1/api.py | 7 +++++++ scaleway/scaleway/iam/v1alpha1/types.py | 5 +++++ 4 files changed, 24 insertions(+) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/api.py b/scaleway-async/scaleway_async/iam/v1alpha1/api.py index b09424baf..c857a1ab6 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/api.py @@ -26,6 +26,7 @@ ListUsersRequestOrderBy, LogAction, LogResourceType, + UserStatus, APIKey, AddGroupMemberRequest, AddGroupMembersRequest, @@ -375,6 +376,7 @@ async def list_users( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, + status: Optional[UserStatus] = None, ) -> ListUsersResponse: """ List users of an Organization. @@ -386,6 +388,7 @@ async def list_users( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. + :param status: Filter by user status. :return: :class:`ListUsersResponse ` Usage: @@ -404,6 +407,7 @@ async def list_users( or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, + "status": status, "tag": tag, "user_ids": user_ids, }, @@ -422,6 +426,7 @@ async def list_users_all( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, + status: Optional[UserStatus] = None, ) -> List[User]: """ List users of an Organization. @@ -433,6 +438,7 @@ async def list_users_all( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. + :param status: Filter by user status. :return: :class:`List[User] ` Usage: @@ -453,6 +459,7 @@ async def list_users_all( "user_ids": user_ids, "mfa": mfa, "tag": tag, + "status": status, }, ) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/types.py b/scaleway-async/scaleway_async/iam/v1alpha1/types.py index 3d5b67aa2..3c32d3ebe 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/types.py @@ -1834,6 +1834,11 @@ class ListUsersRequest: Filter by tags containing a given string. """ + status: Optional[UserStatus] + """ + Filter by user status. + """ + @dataclass class ListUsersResponse: diff --git a/scaleway/scaleway/iam/v1alpha1/api.py b/scaleway/scaleway/iam/v1alpha1/api.py index fdb229a5a..30a1cbd90 100644 --- a/scaleway/scaleway/iam/v1alpha1/api.py +++ b/scaleway/scaleway/iam/v1alpha1/api.py @@ -26,6 +26,7 @@ ListUsersRequestOrderBy, LogAction, LogResourceType, + UserStatus, APIKey, AddGroupMemberRequest, AddGroupMembersRequest, @@ -375,6 +376,7 @@ def list_users( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, + status: Optional[UserStatus] = None, ) -> ListUsersResponse: """ List users of an Organization. @@ -386,6 +388,7 @@ def list_users( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. + :param status: Filter by user status. :return: :class:`ListUsersResponse ` Usage: @@ -404,6 +407,7 @@ def list_users( or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, + "status": status, "tag": tag, "user_ids": user_ids, }, @@ -422,6 +426,7 @@ def list_users_all( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, + status: Optional[UserStatus] = None, ) -> List[User]: """ List users of an Organization. @@ -433,6 +438,7 @@ def list_users_all( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. + :param status: Filter by user status. :return: :class:`List[User] ` Usage: @@ -453,6 +459,7 @@ def list_users_all( "user_ids": user_ids, "mfa": mfa, "tag": tag, + "status": status, }, ) diff --git a/scaleway/scaleway/iam/v1alpha1/types.py b/scaleway/scaleway/iam/v1alpha1/types.py index 3d5b67aa2..3c32d3ebe 100644 --- a/scaleway/scaleway/iam/v1alpha1/types.py +++ b/scaleway/scaleway/iam/v1alpha1/types.py @@ -1834,6 +1834,11 @@ class ListUsersRequest: Filter by tags containing a given string. """ + status: Optional[UserStatus] + """ + Filter by user status. + """ + @dataclass class ListUsersResponse: From f929891c3aa88465fc2024792ed66ab06b79cc52 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 10 Mar 2025 16:54:00 +0100 Subject: [PATCH 59/73] feat(instance): add GPU information in ServerType (#901) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> --- .../scaleway_async/instance/v1/__init__.py | 2 + .../scaleway_async/instance/v1/marshalling.py | 38 +++++++++++++++++-- .../scaleway_async/instance/v1/types.py | 33 +++++++++++++--- scaleway/scaleway/instance/v1/__init__.py | 2 + scaleway/scaleway/instance/v1/marshalling.py | 38 +++++++++++++++++-- scaleway/scaleway/instance/v1/types.py | 33 +++++++++++++--- 6 files changed, 128 insertions(+), 18 deletions(-) diff --git a/scaleway-async/scaleway_async/instance/v1/__init__.py b/scaleway-async/scaleway_async/instance/v1/__init__.py index 686123bd6..a1bdc97a9 100644 --- a/scaleway-async/scaleway_async/instance/v1/__init__.py +++ b/scaleway-async/scaleway_async/instance/v1/__init__.py @@ -55,6 +55,7 @@ from .types import VolumeServer from .types import SnapshotBaseVolume from .types import ServerTypeCapabilities +from .types import ServerTypeGPUInfo from .types import ServerTypeNetwork from .types import ServerTypeVolumeConstraintsByType from .types import VolumeTypeCapabilities @@ -253,6 +254,7 @@ "VolumeServer", "SnapshotBaseVolume", "ServerTypeCapabilities", + "ServerTypeGPUInfo", "ServerTypeNetwork", "ServerTypeVolumeConstraintsByType", "VolumeTypeCapabilities", diff --git a/scaleway-async/scaleway_async/instance/v1/marshalling.py b/scaleway-async/scaleway_async/instance/v1/marshalling.py index 68deee034..419fa1dda 100644 --- a/scaleway-async/scaleway_async/instance/v1/marshalling.py +++ b/scaleway-async/scaleway_async/instance/v1/marshalling.py @@ -82,6 +82,7 @@ ServerTypeNetworkInterface, ServerTypeVolumeConstraintSizes, ServerTypeCapabilities, + ServerTypeGPUInfo, ServerTypeNetwork, ServerTypeVolumeConstraintsByType, ServerType, @@ -2060,6 +2061,29 @@ def unmarshal_ServerTypeCapabilities(data: Any) -> ServerTypeCapabilities: return ServerTypeCapabilities(**args) +def unmarshal_ServerTypeGPUInfo(data: Any) -> ServerTypeGPUInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeGPUInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("gpu_manufacturer", None) + if field is not None: + args["gpu_manufacturer"] = field + + field = data.get("gpu_name", None) + if field is not None: + args["gpu_name"] = field + + field = data.get("gpu_memory", None) + if field is not None: + args["gpu_memory"] = field + + return ServerTypeGPUInfo(**args) + + def unmarshal_ServerTypeNetwork(data: Any) -> ServerTypeNetwork: if not isinstance(data, dict): raise TypeError( @@ -2152,10 +2176,6 @@ def unmarshal_ServerType(data: Any) -> ServerType: if field is not None: args["baremetal"] = field - field = data.get("end_of_service", None) - if field is not None: - args["end_of_service"] = field - field = data.get("per_volume_constraint", None) if field is not None: args["per_volume_constraint"] = unmarshal_ServerTypeVolumeConstraintsByType( @@ -2176,6 +2196,16 @@ def unmarshal_ServerType(data: Any) -> ServerType: else: args["gpu"] = None + field = data.get("end_of_service", None) + if field is not None: + args["end_of_service"] = field + + field = data.get("gpu_info", None) + if field is not None: + args["gpu_info"] = unmarshal_ServerTypeGPUInfo(field) + else: + args["gpu_info"] = None + field = data.get("network", None) if field is not None: args["network"] = unmarshal_ServerTypeNetwork(field) diff --git a/scaleway-async/scaleway_async/instance/v1/types.py b/scaleway-async/scaleway_async/instance/v1/types.py index bac61a4c7..fef8846e8 100644 --- a/scaleway-async/scaleway_async/instance/v1/types.py +++ b/scaleway-async/scaleway_async/instance/v1/types.py @@ -714,6 +714,24 @@ class ServerTypeCapabilities: """ +@dataclass +class ServerTypeGPUInfo: + gpu_manufacturer: str + """ + GPU manufacturer. + """ + + gpu_name: str + """ + GPU model name. + """ + + gpu_memory: int + """ + RAM of a single GPU, in bytes. + """ + + @dataclass class ServerTypeNetwork: interfaces: List[ServerTypeNetworkInterface] @@ -1342,11 +1360,6 @@ class ServerType: True if it is a baremetal Instance. """ - end_of_service: bool - """ - True if this Instance type has reached end of service. - """ - per_volume_constraint: Optional[ServerTypeVolumeConstraintsByType] """ Additional volume constraints. @@ -1362,6 +1375,16 @@ class ServerType: Number of GPU. """ + end_of_service: bool + """ + True if this Instance type has reached end of service. + """ + + gpu_info: Optional[ServerTypeGPUInfo] + """ + GPU information. + """ + network: Optional[ServerTypeNetwork] """ Network available for the Instance. diff --git a/scaleway/scaleway/instance/v1/__init__.py b/scaleway/scaleway/instance/v1/__init__.py index 686123bd6..a1bdc97a9 100644 --- a/scaleway/scaleway/instance/v1/__init__.py +++ b/scaleway/scaleway/instance/v1/__init__.py @@ -55,6 +55,7 @@ from .types import VolumeServer from .types import SnapshotBaseVolume from .types import ServerTypeCapabilities +from .types import ServerTypeGPUInfo from .types import ServerTypeNetwork from .types import ServerTypeVolumeConstraintsByType from .types import VolumeTypeCapabilities @@ -253,6 +254,7 @@ "VolumeServer", "SnapshotBaseVolume", "ServerTypeCapabilities", + "ServerTypeGPUInfo", "ServerTypeNetwork", "ServerTypeVolumeConstraintsByType", "VolumeTypeCapabilities", diff --git a/scaleway/scaleway/instance/v1/marshalling.py b/scaleway/scaleway/instance/v1/marshalling.py index 68deee034..419fa1dda 100644 --- a/scaleway/scaleway/instance/v1/marshalling.py +++ b/scaleway/scaleway/instance/v1/marshalling.py @@ -82,6 +82,7 @@ ServerTypeNetworkInterface, ServerTypeVolumeConstraintSizes, ServerTypeCapabilities, + ServerTypeGPUInfo, ServerTypeNetwork, ServerTypeVolumeConstraintsByType, ServerType, @@ -2060,6 +2061,29 @@ def unmarshal_ServerTypeCapabilities(data: Any) -> ServerTypeCapabilities: return ServerTypeCapabilities(**args) +def unmarshal_ServerTypeGPUInfo(data: Any) -> ServerTypeGPUInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeGPUInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("gpu_manufacturer", None) + if field is not None: + args["gpu_manufacturer"] = field + + field = data.get("gpu_name", None) + if field is not None: + args["gpu_name"] = field + + field = data.get("gpu_memory", None) + if field is not None: + args["gpu_memory"] = field + + return ServerTypeGPUInfo(**args) + + def unmarshal_ServerTypeNetwork(data: Any) -> ServerTypeNetwork: if not isinstance(data, dict): raise TypeError( @@ -2152,10 +2176,6 @@ def unmarshal_ServerType(data: Any) -> ServerType: if field is not None: args["baremetal"] = field - field = data.get("end_of_service", None) - if field is not None: - args["end_of_service"] = field - field = data.get("per_volume_constraint", None) if field is not None: args["per_volume_constraint"] = unmarshal_ServerTypeVolumeConstraintsByType( @@ -2176,6 +2196,16 @@ def unmarshal_ServerType(data: Any) -> ServerType: else: args["gpu"] = None + field = data.get("end_of_service", None) + if field is not None: + args["end_of_service"] = field + + field = data.get("gpu_info", None) + if field is not None: + args["gpu_info"] = unmarshal_ServerTypeGPUInfo(field) + else: + args["gpu_info"] = None + field = data.get("network", None) if field is not None: args["network"] = unmarshal_ServerTypeNetwork(field) diff --git a/scaleway/scaleway/instance/v1/types.py b/scaleway/scaleway/instance/v1/types.py index bac61a4c7..fef8846e8 100644 --- a/scaleway/scaleway/instance/v1/types.py +++ b/scaleway/scaleway/instance/v1/types.py @@ -714,6 +714,24 @@ class ServerTypeCapabilities: """ +@dataclass +class ServerTypeGPUInfo: + gpu_manufacturer: str + """ + GPU manufacturer. + """ + + gpu_name: str + """ + GPU model name. + """ + + gpu_memory: int + """ + RAM of a single GPU, in bytes. + """ + + @dataclass class ServerTypeNetwork: interfaces: List[ServerTypeNetworkInterface] @@ -1342,11 +1360,6 @@ class ServerType: True if it is a baremetal Instance. """ - end_of_service: bool - """ - True if this Instance type has reached end of service. - """ - per_volume_constraint: Optional[ServerTypeVolumeConstraintsByType] """ Additional volume constraints. @@ -1362,6 +1375,16 @@ class ServerType: Number of GPU. """ + end_of_service: bool + """ + True if this Instance type has reached end of service. + """ + + gpu_info: Optional[ServerTypeGPUInfo] + """ + GPU information. + """ + network: Optional[ServerTypeNetwork] """ Network available for the Instance. From fb4f28db24e65f84b3a0d0423b878aa2ba4e02d2 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Wed, 12 Mar 2025 09:32:13 +0100 Subject: [PATCH 60/73] fix(iam): move Connection out of GetUserConnectionResponse (#902) --- .../scaleway_async/iam/v1alpha1/__init__.py | 12 +++--- .../iam/v1alpha1/marshalling.py | 42 +++++++------------ .../scaleway_async/iam/v1alpha1/types.py | 12 +++--- scaleway/scaleway/iam/v1alpha1/__init__.py | 12 +++--- scaleway/scaleway/iam/v1alpha1/marshalling.py | 42 +++++++------------ scaleway/scaleway/iam/v1alpha1/types.py | 12 +++--- 6 files changed, 56 insertions(+), 76 deletions(-) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py index 385a286af..4f3af8cf3 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py @@ -18,13 +18,13 @@ from .types import PermissionSetScopeType from .types import UserStatus from .types import UserType -from .types import GetUserConnectionsResponseConnectionConnectedOrganization -from .types import GetUserConnectionsResponseConnectionConnectedUser +from .types import ConnectionConnectedOrganization +from .types import ConnectionConnectedUser from .types import QuotumLimit from .types import JWT from .types import RuleSpecs from .types import CreateUserRequestMember -from .types import GetUserConnectionsResponseConnection +from .types import Connection from .types import APIKey from .types import Application from .types import GracePeriod @@ -132,13 +132,13 @@ "PermissionSetScopeType", "UserStatus", "UserType", - "GetUserConnectionsResponseConnectionConnectedOrganization", - "GetUserConnectionsResponseConnectionConnectedUser", + "ConnectionConnectedOrganization", + "ConnectionConnectedUser", "QuotumLimit", "JWT", "RuleSpecs", "CreateUserRequestMember", - "GetUserConnectionsResponseConnection", + "Connection", "APIKey", "Application", "GracePeriod", diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py index 4b35ea99c..5dbb80eb5 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py @@ -21,9 +21,9 @@ SSHKey, User, EncodedJWT, - GetUserConnectionsResponseConnectionConnectedOrganization, - GetUserConnectionsResponseConnectionConnectedUser, - GetUserConnectionsResponseConnection, + ConnectionConnectedOrganization, + ConnectionConnectedUser, + Connection, GetUserConnectionsResponse, ListAPIKeysResponse, ListApplicationsResponse, @@ -704,12 +704,12 @@ def unmarshal_EncodedJWT(data: Any) -> EncodedJWT: return EncodedJWT(**args) -def unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization( +def unmarshal_ConnectionConnectedOrganization( data: Any, -) -> GetUserConnectionsResponseConnectionConnectedOrganization: +) -> ConnectionConnectedOrganization: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'GetUserConnectionsResponseConnectionConnectedOrganization' failed as data isn't a dictionary." + "Unmarshalling the type 'ConnectionConnectedOrganization' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} @@ -726,15 +726,13 @@ def unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization( if field is not None: args["locked"] = field - return GetUserConnectionsResponseConnectionConnectedOrganization(**args) + return ConnectionConnectedOrganization(**args) -def unmarshal_GetUserConnectionsResponseConnectionConnectedUser( - data: Any, -) -> GetUserConnectionsResponseConnectionConnectedUser: +def unmarshal_ConnectionConnectedUser(data: Any) -> ConnectionConnectedUser: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'GetUserConnectionsResponseConnectionConnectedUser' failed as data isn't a dictionary." + "Unmarshalling the type 'ConnectionConnectedUser' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} @@ -751,36 +749,30 @@ def unmarshal_GetUserConnectionsResponseConnectionConnectedUser( if field is not None: args["type_"] = field - return GetUserConnectionsResponseConnectionConnectedUser(**args) + return ConnectionConnectedUser(**args) -def unmarshal_GetUserConnectionsResponseConnection( - data: Any, -) -> GetUserConnectionsResponseConnection: +def unmarshal_Connection(data: Any) -> Connection: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'GetUserConnectionsResponseConnection' failed as data isn't a dictionary." + "Unmarshalling the type 'Connection' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} field = data.get("organization", None) if field is not None: - args["organization"] = ( - unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization(field) - ) + args["organization"] = unmarshal_ConnectionConnectedOrganization(field) else: args["organization"] = None field = data.get("user", None) if field is not None: - args["user"] = unmarshal_GetUserConnectionsResponseConnectionConnectedUser( - field - ) + args["user"] = unmarshal_ConnectionConnectedUser(field) else: args["user"] = None - return GetUserConnectionsResponseConnection(**args) + return Connection(**args) def unmarshal_GetUserConnectionsResponse(data: Any) -> GetUserConnectionsResponse: @@ -794,9 +786,7 @@ def unmarshal_GetUserConnectionsResponse(data: Any) -> GetUserConnectionsRespons field = data.get("connections", None) if field is not None: args["connections"] = ( - [unmarshal_GetUserConnectionsResponseConnection(v) for v in field] - if field is not None - else None + [unmarshal_Connection(v) for v in field] if field is not None else None ) return GetUserConnectionsResponse(**args) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/types.py b/scaleway-async/scaleway_async/iam/v1alpha1/types.py index 3c32d3ebe..8df9525f8 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/types.py @@ -207,7 +207,7 @@ def __str__(self) -> str: @dataclass -class GetUserConnectionsResponseConnectionConnectedOrganization: +class ConnectionConnectedOrganization: id: str name: str @@ -216,7 +216,7 @@ class GetUserConnectionsResponseConnectionConnectedOrganization: @dataclass -class GetUserConnectionsResponseConnectionConnectedUser: +class ConnectionConnectedUser: id: str username: str @@ -326,13 +326,13 @@ class CreateUserRequestMember: @dataclass -class GetUserConnectionsResponseConnection: - organization: Optional[GetUserConnectionsResponseConnectionConnectedOrganization] +class Connection: + organization: Optional[ConnectionConnectedOrganization] """ Information about the connected organization. """ - user: Optional[GetUserConnectionsResponseConnectionConnectedUser] + user: Optional[ConnectionConnectedUser] """ Information about the connected user. """ @@ -1244,7 +1244,7 @@ class GetUserConnectionsRequest: @dataclass class GetUserConnectionsResponse: - connections: List[GetUserConnectionsResponseConnection] + connections: List[Connection] """ List of connections. """ diff --git a/scaleway/scaleway/iam/v1alpha1/__init__.py b/scaleway/scaleway/iam/v1alpha1/__init__.py index 385a286af..4f3af8cf3 100644 --- a/scaleway/scaleway/iam/v1alpha1/__init__.py +++ b/scaleway/scaleway/iam/v1alpha1/__init__.py @@ -18,13 +18,13 @@ from .types import PermissionSetScopeType from .types import UserStatus from .types import UserType -from .types import GetUserConnectionsResponseConnectionConnectedOrganization -from .types import GetUserConnectionsResponseConnectionConnectedUser +from .types import ConnectionConnectedOrganization +from .types import ConnectionConnectedUser from .types import QuotumLimit from .types import JWT from .types import RuleSpecs from .types import CreateUserRequestMember -from .types import GetUserConnectionsResponseConnection +from .types import Connection from .types import APIKey from .types import Application from .types import GracePeriod @@ -132,13 +132,13 @@ "PermissionSetScopeType", "UserStatus", "UserType", - "GetUserConnectionsResponseConnectionConnectedOrganization", - "GetUserConnectionsResponseConnectionConnectedUser", + "ConnectionConnectedOrganization", + "ConnectionConnectedUser", "QuotumLimit", "JWT", "RuleSpecs", "CreateUserRequestMember", - "GetUserConnectionsResponseConnection", + "Connection", "APIKey", "Application", "GracePeriod", diff --git a/scaleway/scaleway/iam/v1alpha1/marshalling.py b/scaleway/scaleway/iam/v1alpha1/marshalling.py index 4b35ea99c..5dbb80eb5 100644 --- a/scaleway/scaleway/iam/v1alpha1/marshalling.py +++ b/scaleway/scaleway/iam/v1alpha1/marshalling.py @@ -21,9 +21,9 @@ SSHKey, User, EncodedJWT, - GetUserConnectionsResponseConnectionConnectedOrganization, - GetUserConnectionsResponseConnectionConnectedUser, - GetUserConnectionsResponseConnection, + ConnectionConnectedOrganization, + ConnectionConnectedUser, + Connection, GetUserConnectionsResponse, ListAPIKeysResponse, ListApplicationsResponse, @@ -704,12 +704,12 @@ def unmarshal_EncodedJWT(data: Any) -> EncodedJWT: return EncodedJWT(**args) -def unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization( +def unmarshal_ConnectionConnectedOrganization( data: Any, -) -> GetUserConnectionsResponseConnectionConnectedOrganization: +) -> ConnectionConnectedOrganization: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'GetUserConnectionsResponseConnectionConnectedOrganization' failed as data isn't a dictionary." + "Unmarshalling the type 'ConnectionConnectedOrganization' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} @@ -726,15 +726,13 @@ def unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization( if field is not None: args["locked"] = field - return GetUserConnectionsResponseConnectionConnectedOrganization(**args) + return ConnectionConnectedOrganization(**args) -def unmarshal_GetUserConnectionsResponseConnectionConnectedUser( - data: Any, -) -> GetUserConnectionsResponseConnectionConnectedUser: +def unmarshal_ConnectionConnectedUser(data: Any) -> ConnectionConnectedUser: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'GetUserConnectionsResponseConnectionConnectedUser' failed as data isn't a dictionary." + "Unmarshalling the type 'ConnectionConnectedUser' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} @@ -751,36 +749,30 @@ def unmarshal_GetUserConnectionsResponseConnectionConnectedUser( if field is not None: args["type_"] = field - return GetUserConnectionsResponseConnectionConnectedUser(**args) + return ConnectionConnectedUser(**args) -def unmarshal_GetUserConnectionsResponseConnection( - data: Any, -) -> GetUserConnectionsResponseConnection: +def unmarshal_Connection(data: Any) -> Connection: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'GetUserConnectionsResponseConnection' failed as data isn't a dictionary." + "Unmarshalling the type 'Connection' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} field = data.get("organization", None) if field is not None: - args["organization"] = ( - unmarshal_GetUserConnectionsResponseConnectionConnectedOrganization(field) - ) + args["organization"] = unmarshal_ConnectionConnectedOrganization(field) else: args["organization"] = None field = data.get("user", None) if field is not None: - args["user"] = unmarshal_GetUserConnectionsResponseConnectionConnectedUser( - field - ) + args["user"] = unmarshal_ConnectionConnectedUser(field) else: args["user"] = None - return GetUserConnectionsResponseConnection(**args) + return Connection(**args) def unmarshal_GetUserConnectionsResponse(data: Any) -> GetUserConnectionsResponse: @@ -794,9 +786,7 @@ def unmarshal_GetUserConnectionsResponse(data: Any) -> GetUserConnectionsRespons field = data.get("connections", None) if field is not None: args["connections"] = ( - [unmarshal_GetUserConnectionsResponseConnection(v) for v in field] - if field is not None - else None + [unmarshal_Connection(v) for v in field] if field is not None else None ) return GetUserConnectionsResponse(**args) diff --git a/scaleway/scaleway/iam/v1alpha1/types.py b/scaleway/scaleway/iam/v1alpha1/types.py index 3c32d3ebe..8df9525f8 100644 --- a/scaleway/scaleway/iam/v1alpha1/types.py +++ b/scaleway/scaleway/iam/v1alpha1/types.py @@ -207,7 +207,7 @@ def __str__(self) -> str: @dataclass -class GetUserConnectionsResponseConnectionConnectedOrganization: +class ConnectionConnectedOrganization: id: str name: str @@ -216,7 +216,7 @@ class GetUserConnectionsResponseConnectionConnectedOrganization: @dataclass -class GetUserConnectionsResponseConnectionConnectedUser: +class ConnectionConnectedUser: id: str username: str @@ -326,13 +326,13 @@ class CreateUserRequestMember: @dataclass -class GetUserConnectionsResponseConnection: - organization: Optional[GetUserConnectionsResponseConnectionConnectedOrganization] +class Connection: + organization: Optional[ConnectionConnectedOrganization] """ Information about the connected organization. """ - user: Optional[GetUserConnectionsResponseConnectionConnectedUser] + user: Optional[ConnectionConnectedUser] """ Information about the connected user. """ @@ -1244,7 +1244,7 @@ class GetUserConnectionsRequest: @dataclass class GetUserConnectionsResponse: - connections: List[GetUserConnectionsResponseConnection] + connections: List[Connection] """ List of connections. """ From 0606e4df07907fe9c79efcf3163c21c4819b8f50 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Wed, 12 Mar 2025 10:27:24 +0100 Subject: [PATCH 61/73] feat(inference): add support for v1 (#903) --- .../scaleway_async/inference/v1/__init__.py | 79 ++ .../scaleway_async/inference/v1/api.py | 867 ++++++++++++++++++ .../scaleway_async/inference/v1/content.py | 24 + .../inference/v1/marshalling.py | 654 +++++++++++++ .../scaleway_async/inference/v1/types.py | 770 ++++++++++++++++ scaleway/scaleway/inference/v1/__init__.py | 79 ++ scaleway/scaleway/inference/v1/api.py | 865 +++++++++++++++++ scaleway/scaleway/inference/v1/content.py | 24 + scaleway/scaleway/inference/v1/marshalling.py | 654 +++++++++++++ scaleway/scaleway/inference/v1/types.py | 770 ++++++++++++++++ 10 files changed, 4786 insertions(+) create mode 100644 scaleway-async/scaleway_async/inference/v1/__init__.py create mode 100644 scaleway-async/scaleway_async/inference/v1/api.py create mode 100644 scaleway-async/scaleway_async/inference/v1/content.py create mode 100644 scaleway-async/scaleway_async/inference/v1/marshalling.py create mode 100644 scaleway-async/scaleway_async/inference/v1/types.py create mode 100644 scaleway/scaleway/inference/v1/__init__.py create mode 100644 scaleway/scaleway/inference/v1/api.py create mode 100644 scaleway/scaleway/inference/v1/content.py create mode 100644 scaleway/scaleway/inference/v1/marshalling.py create mode 100644 scaleway/scaleway/inference/v1/types.py diff --git a/scaleway-async/scaleway_async/inference/v1/__init__.py b/scaleway-async/scaleway_async/inference/v1/__init__.py new file mode 100644 index 000000000..526e0c63a --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/__init__.py @@ -0,0 +1,79 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DeploymentStatus +from .content import DEPLOYMENT_TRANSIENT_STATUSES +from .types import ListDeploymentsRequestOrderBy +from .types import ListModelsRequestOrderBy +from .types import ModelStatus +from .content import MODEL_TRANSIENT_STATUSES +from .types import NodeTypeStock +from .types import ModelSupportedQuantization +from .types import EndpointPrivateNetworkDetails +from .types import EndpointPublicNetworkDetails +from .types import ModelSupportedNode +from .types import DeploymentQuantization +from .types import Endpoint +from .types import ModelSupportInfo +from .types import EndpointSpec +from .types import ModelSource +from .types import Deployment +from .types import Model +from .types import NodeType +from .types import CreateDeploymentRequest +from .types import CreateEndpointRequest +from .types import CreateModelRequest +from .types import DeleteDeploymentRequest +from .types import DeleteEndpointRequest +from .types import DeleteModelRequest +from .types import GetDeploymentCertificateRequest +from .types import GetDeploymentRequest +from .types import GetModelRequest +from .types import ListDeploymentsRequest +from .types import ListDeploymentsResponse +from .types import ListModelsRequest +from .types import ListModelsResponse +from .types import ListNodeTypesRequest +from .types import ListNodeTypesResponse +from .types import UpdateDeploymentRequest +from .types import UpdateEndpointRequest +from .api import InferenceV1API + +__all__ = [ + "DeploymentStatus", + "DEPLOYMENT_TRANSIENT_STATUSES", + "ListDeploymentsRequestOrderBy", + "ListModelsRequestOrderBy", + "ModelStatus", + "MODEL_TRANSIENT_STATUSES", + "NodeTypeStock", + "ModelSupportedQuantization", + "EndpointPrivateNetworkDetails", + "EndpointPublicNetworkDetails", + "ModelSupportedNode", + "DeploymentQuantization", + "Endpoint", + "ModelSupportInfo", + "EndpointSpec", + "ModelSource", + "Deployment", + "Model", + "NodeType", + "CreateDeploymentRequest", + "CreateEndpointRequest", + "CreateModelRequest", + "DeleteDeploymentRequest", + "DeleteEndpointRequest", + "DeleteModelRequest", + "GetDeploymentCertificateRequest", + "GetDeploymentRequest", + "GetModelRequest", + "ListDeploymentsRequest", + "ListDeploymentsResponse", + "ListModelsRequest", + "ListModelsResponse", + "ListNodeTypesRequest", + "ListNodeTypesResponse", + "UpdateDeploymentRequest", + "UpdateEndpointRequest", + "InferenceV1API", +] diff --git a/scaleway-async/scaleway_async/inference/v1/api.py b/scaleway-async/scaleway_async/inference/v1/api.py new file mode 100644 index 000000000..4a25975a8 --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/api.py @@ -0,0 +1,867 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, + ScwFile, + unmarshal_ScwFile, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + ListDeploymentsRequestOrderBy, + ListModelsRequestOrderBy, + CreateDeploymentRequest, + CreateEndpointRequest, + CreateModelRequest, + Deployment, + DeploymentQuantization, + Endpoint, + EndpointSpec, + ListDeploymentsResponse, + ListModelsResponse, + ListNodeTypesResponse, + Model, + ModelSource, + NodeType, + UpdateDeploymentRequest, + UpdateEndpointRequest, +) +from .content import ( + DEPLOYMENT_TRANSIENT_STATUSES, + MODEL_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Endpoint, + unmarshal_Deployment, + unmarshal_Model, + unmarshal_ListDeploymentsResponse, + unmarshal_ListModelsResponse, + unmarshal_ListNodeTypesResponse, + marshal_CreateDeploymentRequest, + marshal_CreateEndpointRequest, + marshal_CreateModelRequest, + marshal_UpdateDeploymentRequest, + marshal_UpdateEndpointRequest, +) + + +class InferenceV1API(API): + """ + This API allows you to handle your Managed Inference services. + """ + + async def list_deployments( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDeploymentsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListDeploymentsResponse: + """ + List inference deployments. + List all your inference deployments. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of deployments to return per page. + :param order_by: Order in which to return results. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param name: Filter by deployment name. + :param tags: Filter by tags. + :return: :class:`ListDeploymentsResponse ` + + Usage: + :: + + result = await api.list_deployments() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDeploymentsResponse(res.json()) + + async def list_deployments_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDeploymentsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Deployment]: + """ + List inference deployments. + List all your inference deployments. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of deployments to return per page. + :param order_by: Order in which to return results. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param name: Filter by deployment name. + :param tags: Filter by tags. + :return: :class:`List[Deployment] ` + + Usage: + :: + + result = await api.list_deployments_all() + """ + + return await fetch_all_pages_async( + type=ListDeploymentsResponse, + key="deployments", + fetcher=self.list_deployments, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + }, + ) + + async def get_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> Deployment: + """ + Get a deployment. + Get the deployment for the given ID. + :param deployment_id: ID of the deployment to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.get_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + async def wait_for_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + options: Optional[ + WaitForOptions[Deployment, Union[bool, Awaitable[bool]]] + ] = None, + ) -> Deployment: + """ + Get a deployment. + Get the deployment for the given ID. + :param deployment_id: ID of the deployment to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.get_deployment( + deployment_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in DEPLOYMENT_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_deployment, + options=options, + args={ + "deployment_id": deployment_id, + "region": region, + }, + ) + + async def create_deployment( + self, + *, + model_id: str, + node_type_name: str, + endpoints: List[EndpointSpec], + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + accept_eula: Optional[bool] = None, + tags: Optional[List[str]] = None, + min_size: Optional[int] = None, + max_size: Optional[int] = None, + quantization: Optional[DeploymentQuantization] = None, + ) -> Deployment: + """ + Create a deployment. + Create a new inference deployment related to a specific model. + :param model_id: ID of the model to use. + :param node_type_name: Name of the node type to use. + :param endpoints: List of endpoints to create. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the deployment. + :param project_id: ID of the Project to create the deployment in. + :param accept_eula: If the model has an EULA, you must accept it before proceeding. + The terms of the EULA can be retrieved using the `GetModelEula` API call. + :param tags: List of tags to apply to the deployment. + :param min_size: Defines the minimum size of the pool. + :param max_size: Defines the maximum size of the pool. + :param quantization: Quantization settings to apply to this deployment. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.create_deployment( + model_id="example", + node_type_name="example", + endpoints=[], + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/deployments", + body=marshal_CreateDeploymentRequest( + CreateDeploymentRequest( + model_id=model_id, + node_type_name=node_type_name, + endpoints=endpoints, + region=region, + name=name or random_name(prefix="inference"), + project_id=project_id, + accept_eula=accept_eula, + tags=tags, + min_size=min_size, + max_size=max_size, + quantization=quantization, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + async def update_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + min_size: Optional[int] = None, + max_size: Optional[int] = None, + ) -> Deployment: + """ + Update a deployment. + Update an existing inference deployment. + :param deployment_id: ID of the deployment to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the deployment. + :param tags: List of tags to apply to the deployment. + :param min_size: Defines the new minimum size of the pool. + :param max_size: Defines the new maximum size of the pool. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.update_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "PATCH", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + body=marshal_UpdateDeploymentRequest( + UpdateDeploymentRequest( + deployment_id=deployment_id, + region=region, + name=name, + tags=tags, + min_size=min_size, + max_size=max_size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + async def delete_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> Deployment: + """ + Delete a deployment. + Delete an existing inference deployment. + :param deployment_id: ID of the deployment to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.delete_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + async def get_deployment_certificate( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> ScwFile: + """ + Get the CA certificate. + Get the CA certificate used for the deployment of private endpoints. + The CA certificate will be returned as a PEM file. + :param deployment_id: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ScwFile ` + + Usage: + :: + + result = await api.get_deployment_certificate( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}/certificate", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + async def create_endpoint( + self, + *, + deployment_id: str, + endpoint: EndpointSpec, + region: Optional[ScwRegion] = None, + ) -> Endpoint: + """ + Create an endpoint. + Create a new Endpoint related to a specific deployment. + :param deployment_id: ID of the deployment to create the endpoint for. + :param endpoint: Specification of the endpoint. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Endpoint ` + + Usage: + :: + + result = await api.create_endpoint( + deployment_id="example", + endpoint=EndpointSpec(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/endpoints", + body=marshal_CreateEndpointRequest( + CreateEndpointRequest( + deployment_id=deployment_id, + endpoint=endpoint, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) + + async def update_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + disable_auth: Optional[bool] = None, + ) -> Endpoint: + """ + Update an endpoint. + Update an existing Endpoint. + :param endpoint_id: ID of the endpoint to update. + :param region: Region to target. If none is passed will use default region from the config. + :param disable_auth: By default, deployments are protected by IAM authentication. + When setting this field to true, the authentication will be disabled. + :return: :class:`Endpoint ` + + Usage: + :: + + result = await api.update_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "PATCH", + f"/inference/v1/regions/{param_region}/endpoints/{param_endpoint_id}", + body=marshal_UpdateEndpointRequest( + UpdateEndpointRequest( + endpoint_id=endpoint_id, + region=region, + disable_auth=disable_auth, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) + + async def delete_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete an endpoint. + Delete an existing Endpoint. + :param endpoint_id: ID of the endpoint to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/endpoints/{param_endpoint_id}", + ) + + self._throw_on_error(res) + + async def list_models( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListModelsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListModelsResponse: + """ + List models. + List all available models. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of models to return per page. + :param project_id: Filter by Project ID. + :param name: Filter by model name. + :param tags: Filter by tags. + :return: :class:`ListModelsResponse ` + + Usage: + :: + + result = await api.list_models() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/models", + params={ + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListModelsResponse(res.json()) + + async def list_models_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListModelsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Model]: + """ + List models. + List all available models. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of models to return per page. + :param project_id: Filter by Project ID. + :param name: Filter by model name. + :param tags: Filter by tags. + :return: :class:`List[Model] ` + + Usage: + :: + + result = await api.list_models_all() + """ + + return await fetch_all_pages_async( + type=ListModelsResponse, + key="models", + fetcher=self.list_models, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "name": name, + "tags": tags, + }, + ) + + async def get_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + ) -> Model: + """ + Get a model. + Get the model for the given ID. + :param model_id: ID of the model to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Model ` + + Usage: + :: + + result = await api.get_model( + model_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_model_id = validate_path_param("model_id", model_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/models/{param_model_id}", + ) + + self._throw_on_error(res) + return unmarshal_Model(res.json()) + + async def wait_for_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Model, Union[bool, Awaitable[bool]]]] = None, + ) -> Model: + """ + Get a model. + Get the model for the given ID. + :param model_id: ID of the model to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Model ` + + Usage: + :: + + result = await api.get_model( + model_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in MODEL_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_model, + options=options, + args={ + "model_id": model_id, + "region": region, + }, + ) + + async def create_model( + self, + *, + source: ModelSource, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + ) -> Model: + """ + Import a model. + Import a new model to your model library. + :param source: Where to import the model from. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the model. + :param project_id: ID of the Project to import the model in. + :return: :class:`Model ` + + Usage: + :: + + result = await api.create_model( + source=ModelSource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/models", + body=marshal_CreateModelRequest( + CreateModelRequest( + source=source, + region=region, + name=name or random_name(prefix="model"), + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Model(res.json()) + + async def delete_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a model. + Delete an existing model from your model library. + :param model_id: ID of the model to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_model( + model_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_model_id = validate_path_param("model_id", model_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/models/{param_model_id}", + ) + + self._throw_on_error(res) + + async def list_node_types( + self, + *, + include_disabled_types: bool, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListNodeTypesResponse: + """ + List available node types. + List all available node types. By default, the node types returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param include_disabled_types: Include disabled node types in the response. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of node types to return per page. + :return: :class:`ListNodeTypesResponse ` + + Usage: + :: + + result = await api.list_node_types( + include_disabled_types=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/node-types", + params={ + "include_disabled_types": include_disabled_types, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListNodeTypesResponse(res.json()) + + async def list_node_types_all( + self, + *, + include_disabled_types: bool, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[NodeType]: + """ + List available node types. + List all available node types. By default, the node types returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param include_disabled_types: Include disabled node types in the response. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of node types to return per page. + :return: :class:`List[NodeType] ` + + Usage: + :: + + result = await api.list_node_types_all( + include_disabled_types=False, + ) + """ + + return await fetch_all_pages_async( + type=ListNodeTypesResponse, + key="node_types", + fetcher=self.list_node_types, + args={ + "include_disabled_types": include_disabled_types, + "region": region, + "page": page, + "page_size": page_size, + }, + ) diff --git a/scaleway-async/scaleway_async/inference/v1/content.py b/scaleway-async/scaleway_async/inference/v1/content.py new file mode 100644 index 000000000..887e0b7ec --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/content.py @@ -0,0 +1,24 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + DeploymentStatus, + ModelStatus, +) + +DEPLOYMENT_TRANSIENT_STATUSES: List[DeploymentStatus] = [ + DeploymentStatus.CREATING, + DeploymentStatus.DEPLOYING, + DeploymentStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`DeploymentStatus `. +""" +MODEL_TRANSIENT_STATUSES: List[ModelStatus] = [ + ModelStatus.PREPARING, + ModelStatus.DOWNLOADING, +] +""" +Lists transient statutes of the enum :class:`ModelStatus `. +""" diff --git a/scaleway-async/scaleway_async/inference/v1/marshalling.py b/scaleway-async/scaleway_async/inference/v1/marshalling.py new file mode 100644 index 000000000..9f10b88e1 --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/marshalling.py @@ -0,0 +1,654 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + EndpointPrivateNetworkDetails, + EndpointPublicNetworkDetails, + Endpoint, + ModelSupportedQuantization, + ModelSupportedNode, + ModelSupportInfo, + DeploymentQuantization, + Deployment, + Model, + ListDeploymentsResponse, + ListModelsResponse, + NodeType, + ListNodeTypesResponse, + EndpointSpec, + CreateDeploymentRequest, + CreateEndpointRequest, + ModelSource, + CreateModelRequest, + UpdateDeploymentRequest, + UpdateEndpointRequest, +) + + +def unmarshal_EndpointPrivateNetworkDetails(data: Any) -> EndpointPrivateNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPrivateNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + return EndpointPrivateNetworkDetails(**args) + + +def unmarshal_EndpointPublicNetworkDetails(data: Any) -> EndpointPublicNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPublicNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return EndpointPublicNetworkDetails(**args) + + +def unmarshal_Endpoint(data: Any) -> Endpoint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Endpoint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("disable_auth", None) + if field is not None: + args["disable_auth"] = field + + field = data.get("public_network", None) + if field is not None: + args["public_network"] = unmarshal_EndpointPublicNetworkDetails(field) + else: + args["public_network"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None + + return Endpoint(**args) + + +def unmarshal_ModelSupportedQuantization(data: Any) -> ModelSupportedQuantization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportedQuantization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("quantization_bits", None) + if field is not None: + args["quantization_bits"] = field + + field = data.get("allowed", None) + if field is not None: + args["allowed"] = field + + field = data.get("max_context_size", None) + if field is not None: + args["max_context_size"] = field + + return ModelSupportedQuantization(**args) + + +def unmarshal_ModelSupportedNode(data: Any) -> ModelSupportedNode: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportedNode' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_type_name", None) + if field is not None: + args["node_type_name"] = field + + field = data.get("quantizations", None) + if field is not None: + args["quantizations"] = ( + [unmarshal_ModelSupportedQuantization(v) for v in field] + if field is not None + else None + ) + + return ModelSupportedNode(**args) + + +def unmarshal_ModelSupportInfo(data: Any) -> ModelSupportInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("nodes", None) + if field is not None: + args["nodes"] = ( + [unmarshal_ModelSupportedNode(v) for v in field] + if field is not None + else None + ) + + return ModelSupportInfo(**args) + + +def unmarshal_DeploymentQuantization(data: Any) -> DeploymentQuantization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DeploymentQuantization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("bits", None) + if field is not None: + args["bits"] = field + + return DeploymentQuantization(**args) + + +def unmarshal_Deployment(data: Any) -> Deployment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Deployment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("node_type_name", None) + if field is not None: + args["node_type_name"] = field + + field = data.get("endpoints", None) + if field is not None: + args["endpoints"] = ( + [unmarshal_Endpoint(v) for v in field] if field is not None else None + ) + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("min_size", None) + if field is not None: + args["min_size"] = field + + field = data.get("max_size", None) + if field is not None: + args["max_size"] = field + + field = data.get("model_id", None) + if field is not None: + args["model_id"] = field + + field = data.get("model_name", None) + if field is not None: + args["model_name"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("quantization", None) + if field is not None: + args["quantization"] = unmarshal_DeploymentQuantization(field) + else: + args["quantization"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Deployment(**args) + + +def unmarshal_Model(data: Any) -> Model: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Model' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("has_eula", None) + if field is not None: + args["has_eula"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("nodes_support", None) + if field is not None: + args["nodes_support"] = ( + [unmarshal_ModelSupportInfo(v) for v in field] + if field is not None + else None + ) + + field = data.get("parameter_size_bits", None) + if field is not None: + args["parameter_size_bits"] = field + + field = data.get("size_bytes", None) + if field is not None: + args["size_bytes"] = field + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Model(**args) + + +def unmarshal_ListDeploymentsResponse(data: Any) -> ListDeploymentsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDeploymentsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("deployments", None) + if field is not None: + args["deployments"] = ( + [unmarshal_Deployment(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDeploymentsResponse(**args) + + +def unmarshal_ListModelsResponse(data: Any) -> ListModelsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListModelsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("models", None) + if field is not None: + args["models"] = ( + [unmarshal_Model(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListModelsResponse(**args) + + +def unmarshal_NodeType(data: Any) -> NodeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("stock_status", None) + if field is not None: + args["stock_status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("vcpus", None) + if field is not None: + args["vcpus"] = field + + field = data.get("memory", None) + if field is not None: + args["memory"] = field + + field = data.get("vram", None) + if field is not None: + args["vram"] = field + + field = data.get("disabled", None) + if field is not None: + args["disabled"] = field + + field = data.get("beta", None) + if field is not None: + args["beta"] = field + + field = data.get("gpus", None) + if field is not None: + args["gpus"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return NodeType(**args) + + +def unmarshal_ListNodeTypesResponse(data: Any) -> ListNodeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListNodeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_types", None) + if field is not None: + args["node_types"] = ( + [unmarshal_NodeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListNodeTypesResponse(**args) + + +def marshal_EndpointPrivateNetworkDetails( + request: EndpointPrivateNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + +def marshal_EndpointPublicNetworkDetails( + request: EndpointPublicNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_DeploymentQuantization( + request: DeploymentQuantization, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enabled is not None: + output["enabled"] = request.enabled + + if request.bits is not None: + output["bits"] = request.bits + + return output + + +def marshal_EndpointSpec( + request: EndpointSpec, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("public_network", request.public_network), + OneOfPossibility("private_network", request.private_network), + ] + ), + ) + + if request.disable_auth is not None: + output["disable_auth"] = request.disable_auth + + return output + + +def marshal_CreateDeploymentRequest( + request: CreateDeploymentRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.model_id is not None: + output["model_id"] = request.model_id + + if request.node_type_name is not None: + output["node_type_name"] = request.node_type_name + + if request.endpoints is not None: + output["endpoints"] = [ + marshal_EndpointSpec(item, defaults) for item in request.endpoints + ] + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.accept_eula is not None: + output["accept_eula"] = request.accept_eula + + if request.tags is not None: + output["tags"] = request.tags + + if request.min_size is not None: + output["min_size"] = request.min_size + + if request.max_size is not None: + output["max_size"] = request.max_size + + if request.quantization is not None: + output["quantization"] = marshal_DeploymentQuantization( + request.quantization, defaults + ) + + return output + + +def marshal_CreateEndpointRequest( + request: CreateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.deployment_id is not None: + output["deployment_id"] = request.deployment_id + + if request.endpoint is not None: + output["endpoint"] = marshal_EndpointSpec(request.endpoint, defaults) + + return output + + +def marshal_ModelSource( + request: ModelSource, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + ] + ), + ) + + if request.url is not None: + output["url"] = request.url + + return output + + +def marshal_CreateModelRequest( + request: CreateModelRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.source is not None: + output["source"] = marshal_ModelSource(request.source, defaults) + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_UpdateDeploymentRequest( + request: UpdateDeploymentRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.min_size is not None: + output["min_size"] = request.min_size + + if request.max_size is not None: + output["max_size"] = request.max_size + + return output + + +def marshal_UpdateEndpointRequest( + request: UpdateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.disable_auth is not None: + output["disable_auth"] = request.disable_auth + + return output diff --git a/scaleway-async/scaleway_async/inference/v1/types.py b/scaleway-async/scaleway_async/inference/v1/types.py new file mode 100644 index 000000000..9dd6fce4b --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/types.py @@ -0,0 +1,770 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DeploymentStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + DEPLOYING = "deploying" + READY = "ready" + ERROR = "error" + DELETING = "deleting" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ListDeploymentsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListModelsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DISPLAY_RANK_ASC = "display_rank_asc" + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ModelStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + PREPARING = "preparing" + DOWNLOADING = "downloading" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class NodeTypeStock(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STOCK = "unknown_stock" + LOW_STOCK = "low_stock" + OUT_OF_STOCK = "out_of_stock" + AVAILABLE = "available" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ModelSupportedQuantization: + quantization_bits: int + """ + Number of bits for this supported quantization. + """ + + allowed: bool + """ + Tells whether this quantization is allowed for this node type. + """ + + max_context_size: int + """ + Maximum inference context size available for this node type and quantization. + """ + + +@dataclass +class EndpointPrivateNetworkDetails: + private_network_id: str + + +@dataclass +class EndpointPublicNetworkDetails: + pass + + +@dataclass +class ModelSupportedNode: + node_type_name: str + """ + Supported node type. + """ + + quantizations: List[ModelSupportedQuantization] + """ + Supported quantizations. + """ + + +@dataclass +class DeploymentQuantization: + enabled: bool + """ + Whether to enable quantization for this deployment. + """ + + bits: int + """ + The number of bits each model parameter should be quantized to. The quantization method is chosen based on this value. + """ + + +@dataclass +class Endpoint: + id: str + """ + Unique identifier. + """ + + url: str + """ + For private endpoints, the URL will be accessible only from the Private Network. +In addition, private endpoints will expose a CA certificate that can be used to verify the server's identity. +This CA certificate can be retrieved using the `GetDeploymentCertificate` API call. + """ + + disable_auth: bool + """ + Defines whether the authentication is disabled. + """ + + public_network: Optional[EndpointPublicNetworkDetails] + + private_network: Optional[EndpointPrivateNetworkDetails] + + +@dataclass +class ModelSupportInfo: + nodes: List[ModelSupportedNode] + """ + List of supported node types. + """ + + +@dataclass +class EndpointSpec: + disable_auth: bool + """ + By default, deployments are protected by IAM authentication. +When setting this field to true, the authentication will be disabled. + """ + + public_network: Optional[EndpointPublicNetworkDetails] + + private_network: Optional[EndpointPrivateNetworkDetails] + + +@dataclass +class ModelSource: + url: str + + secret: Optional[str] + + +@dataclass +class Deployment: + id: str + """ + Unique identifier. + """ + + name: str + """ + Name of the deployment. + """ + + project_id: str + """ + Project ID. + """ + + status: DeploymentStatus + """ + Status of the deployment. + """ + + tags: List[str] + """ + List of tags applied to the deployment. + """ + + node_type_name: str + """ + Node type of the deployment. + """ + + endpoints: List[Endpoint] + """ + List of endpoints. + """ + + size: int + """ + Current size of the pool. + """ + + min_size: int + """ + Defines the minimum size of the pool. + """ + + max_size: int + """ + Defines the maximum size of the pool. + """ + + model_id: str + """ + ID of the model used for the deployment. + """ + + model_name: str + """ + Name of the deployed model. + """ + + region: ScwRegion + """ + Region of the deployment. + """ + + error_message: Optional[str] + """ + Displays information if your deployment is in error state. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization parameters for this deployment. + """ + + created_at: Optional[datetime] + """ + Creation date of the deployment. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the deployment. + """ + + +@dataclass +class Model: + id: str + """ + Unique identifier. + """ + + name: str + """ + Unique Name identifier. + """ + + project_id: str + """ + Project ID. + """ + + tags: List[str] + """ + List of tags applied to the model. + """ + + status: ModelStatus + """ + Status of the model. + """ + + description: str + """ + Purpose of the model. + """ + + has_eula: bool + """ + Defines whether the model has an end user license agreement. + """ + + region: ScwRegion + """ + Region of the model. + """ + + nodes_support: List[ModelSupportInfo] + """ + Supported nodes types with quantization options and context lengths. + """ + + parameter_size_bits: int + """ + Size, in bits, of the model parameters. + """ + + size_bytes: int + """ + Total size, in bytes, of the model files. + """ + + error_message: Optional[str] + """ + Displays information if your model is in error state. + """ + + created_at: Optional[datetime] + """ + Creation date of the model. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the model. + """ + + +@dataclass +class NodeType: + name: str + """ + Name of the node type. + """ + + stock_status: NodeTypeStock + """ + Current stock status for the node type. + """ + + description: str + """ + Current specs of the offer. + """ + + vcpus: int + """ + Number of virtual CPUs. + """ + + memory: int + """ + Quantity of RAM. + """ + + vram: int + """ + Quantity of GPU RAM. + """ + + disabled: bool + """ + The node type is currently disabled. + """ + + beta: bool + """ + The node type is currently in beta. + """ + + gpus: int + """ + Number of GPUs. + """ + + region: ScwRegion + """ + Region of the node type. + """ + + created_at: Optional[datetime] + """ + Creation date of the node type. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the node type. + """ + + +@dataclass +class CreateDeploymentRequest: + model_id: str + """ + ID of the model to use. + """ + + node_type_name: str + """ + Name of the node type to use. + """ + + endpoints: List[EndpointSpec] + """ + List of endpoints to create. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the deployment. + """ + + project_id: Optional[str] + """ + ID of the Project to create the deployment in. + """ + + accept_eula: Optional[bool] + """ + If the model has an EULA, you must accept it before proceeding. +The terms of the EULA can be retrieved using the `GetModelEula` API call. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the deployment. + """ + + min_size: Optional[int] + """ + Defines the minimum size of the pool. + """ + + max_size: Optional[int] + """ + Defines the maximum size of the pool. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization settings to apply to this deployment. + """ + + +@dataclass +class CreateEndpointRequest: + deployment_id: str + """ + ID of the deployment to create the endpoint for. + """ + + endpoint: EndpointSpec + """ + Specification of the endpoint. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateModelRequest: + source: ModelSource + """ + Where to import the model from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the model. + """ + + project_id: Optional[str] + """ + ID of the Project to import the model in. + """ + + +@dataclass +class DeleteDeploymentRequest: + deployment_id: str + """ + ID of the deployment to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteEndpointRequest: + endpoint_id: str + """ + ID of the endpoint to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteModelRequest: + model_id: str + """ + ID of the model to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDeploymentCertificateRequest: + deployment_id: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDeploymentRequest: + deployment_id: str + """ + ID of the deployment to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetModelRequest: + model_id: str + """ + ID of the model to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListDeploymentsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of deployments to return per page. + """ + + order_by: Optional[ListDeploymentsRequestOrderBy] + """ + Order in which to return results. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + name: Optional[str] + """ + Filter by deployment name. + """ + + tags: Optional[List[str]] + """ + Filter by tags. + """ + + +@dataclass +class ListDeploymentsResponse: + deployments: List[Deployment] + """ + List of deployments on the current page. + """ + + total_count: int + """ + Total number of deployments. + """ + + +@dataclass +class ListModelsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListModelsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of models to return per page. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + name: Optional[str] + """ + Filter by model name. + """ + + tags: Optional[List[str]] + """ + Filter by tags. + """ + + +@dataclass +class ListModelsResponse: + models: List[Model] + """ + List of models on the current page. + """ + + total_count: int + """ + Total number of models. + """ + + +@dataclass +class ListNodeTypesRequest: + include_disabled_types: bool + """ + Include disabled node types in the response. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of node types to return per page. + """ + + +@dataclass +class ListNodeTypesResponse: + node_types: List[NodeType] + """ + List of node types. + """ + + total_count: int + """ + Total number of node types. + """ + + +@dataclass +class UpdateDeploymentRequest: + deployment_id: str + """ + ID of the deployment to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the deployment. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the deployment. + """ + + min_size: Optional[int] + """ + Defines the new minimum size of the pool. + """ + + max_size: Optional[int] + """ + Defines the new maximum size of the pool. + """ + + +@dataclass +class UpdateEndpointRequest: + endpoint_id: str + """ + ID of the endpoint to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + disable_auth: Optional[bool] + """ + By default, deployments are protected by IAM authentication. +When setting this field to true, the authentication will be disabled. + """ diff --git a/scaleway/scaleway/inference/v1/__init__.py b/scaleway/scaleway/inference/v1/__init__.py new file mode 100644 index 000000000..526e0c63a --- /dev/null +++ b/scaleway/scaleway/inference/v1/__init__.py @@ -0,0 +1,79 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DeploymentStatus +from .content import DEPLOYMENT_TRANSIENT_STATUSES +from .types import ListDeploymentsRequestOrderBy +from .types import ListModelsRequestOrderBy +from .types import ModelStatus +from .content import MODEL_TRANSIENT_STATUSES +from .types import NodeTypeStock +from .types import ModelSupportedQuantization +from .types import EndpointPrivateNetworkDetails +from .types import EndpointPublicNetworkDetails +from .types import ModelSupportedNode +from .types import DeploymentQuantization +from .types import Endpoint +from .types import ModelSupportInfo +from .types import EndpointSpec +from .types import ModelSource +from .types import Deployment +from .types import Model +from .types import NodeType +from .types import CreateDeploymentRequest +from .types import CreateEndpointRequest +from .types import CreateModelRequest +from .types import DeleteDeploymentRequest +from .types import DeleteEndpointRequest +from .types import DeleteModelRequest +from .types import GetDeploymentCertificateRequest +from .types import GetDeploymentRequest +from .types import GetModelRequest +from .types import ListDeploymentsRequest +from .types import ListDeploymentsResponse +from .types import ListModelsRequest +from .types import ListModelsResponse +from .types import ListNodeTypesRequest +from .types import ListNodeTypesResponse +from .types import UpdateDeploymentRequest +from .types import UpdateEndpointRequest +from .api import InferenceV1API + +__all__ = [ + "DeploymentStatus", + "DEPLOYMENT_TRANSIENT_STATUSES", + "ListDeploymentsRequestOrderBy", + "ListModelsRequestOrderBy", + "ModelStatus", + "MODEL_TRANSIENT_STATUSES", + "NodeTypeStock", + "ModelSupportedQuantization", + "EndpointPrivateNetworkDetails", + "EndpointPublicNetworkDetails", + "ModelSupportedNode", + "DeploymentQuantization", + "Endpoint", + "ModelSupportInfo", + "EndpointSpec", + "ModelSource", + "Deployment", + "Model", + "NodeType", + "CreateDeploymentRequest", + "CreateEndpointRequest", + "CreateModelRequest", + "DeleteDeploymentRequest", + "DeleteEndpointRequest", + "DeleteModelRequest", + "GetDeploymentCertificateRequest", + "GetDeploymentRequest", + "GetModelRequest", + "ListDeploymentsRequest", + "ListDeploymentsResponse", + "ListModelsRequest", + "ListModelsResponse", + "ListNodeTypesRequest", + "ListNodeTypesResponse", + "UpdateDeploymentRequest", + "UpdateEndpointRequest", + "InferenceV1API", +] diff --git a/scaleway/scaleway/inference/v1/api.py b/scaleway/scaleway/inference/v1/api.py new file mode 100644 index 000000000..4cecd31cd --- /dev/null +++ b/scaleway/scaleway/inference/v1/api.py @@ -0,0 +1,865 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, + ScwFile, + unmarshal_ScwFile, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + ListDeploymentsRequestOrderBy, + ListModelsRequestOrderBy, + CreateDeploymentRequest, + CreateEndpointRequest, + CreateModelRequest, + Deployment, + DeploymentQuantization, + Endpoint, + EndpointSpec, + ListDeploymentsResponse, + ListModelsResponse, + ListNodeTypesResponse, + Model, + ModelSource, + NodeType, + UpdateDeploymentRequest, + UpdateEndpointRequest, +) +from .content import ( + DEPLOYMENT_TRANSIENT_STATUSES, + MODEL_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Endpoint, + unmarshal_Deployment, + unmarshal_Model, + unmarshal_ListDeploymentsResponse, + unmarshal_ListModelsResponse, + unmarshal_ListNodeTypesResponse, + marshal_CreateDeploymentRequest, + marshal_CreateEndpointRequest, + marshal_CreateModelRequest, + marshal_UpdateDeploymentRequest, + marshal_UpdateEndpointRequest, +) + + +class InferenceV1API(API): + """ + This API allows you to handle your Managed Inference services. + """ + + def list_deployments( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDeploymentsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListDeploymentsResponse: + """ + List inference deployments. + List all your inference deployments. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of deployments to return per page. + :param order_by: Order in which to return results. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param name: Filter by deployment name. + :param tags: Filter by tags. + :return: :class:`ListDeploymentsResponse ` + + Usage: + :: + + result = api.list_deployments() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDeploymentsResponse(res.json()) + + def list_deployments_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDeploymentsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Deployment]: + """ + List inference deployments. + List all your inference deployments. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of deployments to return per page. + :param order_by: Order in which to return results. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param name: Filter by deployment name. + :param tags: Filter by tags. + :return: :class:`List[Deployment] ` + + Usage: + :: + + result = api.list_deployments_all() + """ + + return fetch_all_pages( + type=ListDeploymentsResponse, + key="deployments", + fetcher=self.list_deployments, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + }, + ) + + def get_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> Deployment: + """ + Get a deployment. + Get the deployment for the given ID. + :param deployment_id: ID of the deployment to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.get_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + def wait_for_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Deployment, bool]] = None, + ) -> Deployment: + """ + Get a deployment. + Get the deployment for the given ID. + :param deployment_id: ID of the deployment to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.get_deployment( + deployment_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in DEPLOYMENT_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_deployment, + options=options, + args={ + "deployment_id": deployment_id, + "region": region, + }, + ) + + def create_deployment( + self, + *, + model_id: str, + node_type_name: str, + endpoints: List[EndpointSpec], + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + accept_eula: Optional[bool] = None, + tags: Optional[List[str]] = None, + min_size: Optional[int] = None, + max_size: Optional[int] = None, + quantization: Optional[DeploymentQuantization] = None, + ) -> Deployment: + """ + Create a deployment. + Create a new inference deployment related to a specific model. + :param model_id: ID of the model to use. + :param node_type_name: Name of the node type to use. + :param endpoints: List of endpoints to create. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the deployment. + :param project_id: ID of the Project to create the deployment in. + :param accept_eula: If the model has an EULA, you must accept it before proceeding. + The terms of the EULA can be retrieved using the `GetModelEula` API call. + :param tags: List of tags to apply to the deployment. + :param min_size: Defines the minimum size of the pool. + :param max_size: Defines the maximum size of the pool. + :param quantization: Quantization settings to apply to this deployment. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.create_deployment( + model_id="example", + node_type_name="example", + endpoints=[], + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/deployments", + body=marshal_CreateDeploymentRequest( + CreateDeploymentRequest( + model_id=model_id, + node_type_name=node_type_name, + endpoints=endpoints, + region=region, + name=name or random_name(prefix="inference"), + project_id=project_id, + accept_eula=accept_eula, + tags=tags, + min_size=min_size, + max_size=max_size, + quantization=quantization, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + def update_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + min_size: Optional[int] = None, + max_size: Optional[int] = None, + ) -> Deployment: + """ + Update a deployment. + Update an existing inference deployment. + :param deployment_id: ID of the deployment to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the deployment. + :param tags: List of tags to apply to the deployment. + :param min_size: Defines the new minimum size of the pool. + :param max_size: Defines the new maximum size of the pool. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.update_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "PATCH", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + body=marshal_UpdateDeploymentRequest( + UpdateDeploymentRequest( + deployment_id=deployment_id, + region=region, + name=name, + tags=tags, + min_size=min_size, + max_size=max_size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + def delete_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> Deployment: + """ + Delete a deployment. + Delete an existing inference deployment. + :param deployment_id: ID of the deployment to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.delete_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + def get_deployment_certificate( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> ScwFile: + """ + Get the CA certificate. + Get the CA certificate used for the deployment of private endpoints. + The CA certificate will be returned as a PEM file. + :param deployment_id: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ScwFile ` + + Usage: + :: + + result = api.get_deployment_certificate( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}/certificate", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + def create_endpoint( + self, + *, + deployment_id: str, + endpoint: EndpointSpec, + region: Optional[ScwRegion] = None, + ) -> Endpoint: + """ + Create an endpoint. + Create a new Endpoint related to a specific deployment. + :param deployment_id: ID of the deployment to create the endpoint for. + :param endpoint: Specification of the endpoint. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Endpoint ` + + Usage: + :: + + result = api.create_endpoint( + deployment_id="example", + endpoint=EndpointSpec(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/endpoints", + body=marshal_CreateEndpointRequest( + CreateEndpointRequest( + deployment_id=deployment_id, + endpoint=endpoint, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) + + def update_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + disable_auth: Optional[bool] = None, + ) -> Endpoint: + """ + Update an endpoint. + Update an existing Endpoint. + :param endpoint_id: ID of the endpoint to update. + :param region: Region to target. If none is passed will use default region from the config. + :param disable_auth: By default, deployments are protected by IAM authentication. + When setting this field to true, the authentication will be disabled. + :return: :class:`Endpoint ` + + Usage: + :: + + result = api.update_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "PATCH", + f"/inference/v1/regions/{param_region}/endpoints/{param_endpoint_id}", + body=marshal_UpdateEndpointRequest( + UpdateEndpointRequest( + endpoint_id=endpoint_id, + region=region, + disable_auth=disable_auth, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) + + def delete_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete an endpoint. + Delete an existing Endpoint. + :param endpoint_id: ID of the endpoint to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/endpoints/{param_endpoint_id}", + ) + + self._throw_on_error(res) + + def list_models( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListModelsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListModelsResponse: + """ + List models. + List all available models. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of models to return per page. + :param project_id: Filter by Project ID. + :param name: Filter by model name. + :param tags: Filter by tags. + :return: :class:`ListModelsResponse ` + + Usage: + :: + + result = api.list_models() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/models", + params={ + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListModelsResponse(res.json()) + + def list_models_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListModelsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Model]: + """ + List models. + List all available models. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of models to return per page. + :param project_id: Filter by Project ID. + :param name: Filter by model name. + :param tags: Filter by tags. + :return: :class:`List[Model] ` + + Usage: + :: + + result = api.list_models_all() + """ + + return fetch_all_pages( + type=ListModelsResponse, + key="models", + fetcher=self.list_models, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "name": name, + "tags": tags, + }, + ) + + def get_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + ) -> Model: + """ + Get a model. + Get the model for the given ID. + :param model_id: ID of the model to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Model ` + + Usage: + :: + + result = api.get_model( + model_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_model_id = validate_path_param("model_id", model_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/models/{param_model_id}", + ) + + self._throw_on_error(res) + return unmarshal_Model(res.json()) + + def wait_for_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Model, bool]] = None, + ) -> Model: + """ + Get a model. + Get the model for the given ID. + :param model_id: ID of the model to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Model ` + + Usage: + :: + + result = api.get_model( + model_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in MODEL_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_model, + options=options, + args={ + "model_id": model_id, + "region": region, + }, + ) + + def create_model( + self, + *, + source: ModelSource, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + ) -> Model: + """ + Import a model. + Import a new model to your model library. + :param source: Where to import the model from. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the model. + :param project_id: ID of the Project to import the model in. + :return: :class:`Model ` + + Usage: + :: + + result = api.create_model( + source=ModelSource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/models", + body=marshal_CreateModelRequest( + CreateModelRequest( + source=source, + region=region, + name=name or random_name(prefix="model"), + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Model(res.json()) + + def delete_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a model. + Delete an existing model from your model library. + :param model_id: ID of the model to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_model( + model_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_model_id = validate_path_param("model_id", model_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/models/{param_model_id}", + ) + + self._throw_on_error(res) + + def list_node_types( + self, + *, + include_disabled_types: bool, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListNodeTypesResponse: + """ + List available node types. + List all available node types. By default, the node types returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param include_disabled_types: Include disabled node types in the response. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of node types to return per page. + :return: :class:`ListNodeTypesResponse ` + + Usage: + :: + + result = api.list_node_types( + include_disabled_types=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/node-types", + params={ + "include_disabled_types": include_disabled_types, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListNodeTypesResponse(res.json()) + + def list_node_types_all( + self, + *, + include_disabled_types: bool, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[NodeType]: + """ + List available node types. + List all available node types. By default, the node types returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param include_disabled_types: Include disabled node types in the response. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of node types to return per page. + :return: :class:`List[NodeType] ` + + Usage: + :: + + result = api.list_node_types_all( + include_disabled_types=False, + ) + """ + + return fetch_all_pages( + type=ListNodeTypesResponse, + key="node_types", + fetcher=self.list_node_types, + args={ + "include_disabled_types": include_disabled_types, + "region": region, + "page": page, + "page_size": page_size, + }, + ) diff --git a/scaleway/scaleway/inference/v1/content.py b/scaleway/scaleway/inference/v1/content.py new file mode 100644 index 000000000..887e0b7ec --- /dev/null +++ b/scaleway/scaleway/inference/v1/content.py @@ -0,0 +1,24 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + DeploymentStatus, + ModelStatus, +) + +DEPLOYMENT_TRANSIENT_STATUSES: List[DeploymentStatus] = [ + DeploymentStatus.CREATING, + DeploymentStatus.DEPLOYING, + DeploymentStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`DeploymentStatus `. +""" +MODEL_TRANSIENT_STATUSES: List[ModelStatus] = [ + ModelStatus.PREPARING, + ModelStatus.DOWNLOADING, +] +""" +Lists transient statutes of the enum :class:`ModelStatus `. +""" diff --git a/scaleway/scaleway/inference/v1/marshalling.py b/scaleway/scaleway/inference/v1/marshalling.py new file mode 100644 index 000000000..9f10b88e1 --- /dev/null +++ b/scaleway/scaleway/inference/v1/marshalling.py @@ -0,0 +1,654 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + EndpointPrivateNetworkDetails, + EndpointPublicNetworkDetails, + Endpoint, + ModelSupportedQuantization, + ModelSupportedNode, + ModelSupportInfo, + DeploymentQuantization, + Deployment, + Model, + ListDeploymentsResponse, + ListModelsResponse, + NodeType, + ListNodeTypesResponse, + EndpointSpec, + CreateDeploymentRequest, + CreateEndpointRequest, + ModelSource, + CreateModelRequest, + UpdateDeploymentRequest, + UpdateEndpointRequest, +) + + +def unmarshal_EndpointPrivateNetworkDetails(data: Any) -> EndpointPrivateNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPrivateNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + return EndpointPrivateNetworkDetails(**args) + + +def unmarshal_EndpointPublicNetworkDetails(data: Any) -> EndpointPublicNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPublicNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return EndpointPublicNetworkDetails(**args) + + +def unmarshal_Endpoint(data: Any) -> Endpoint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Endpoint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("disable_auth", None) + if field is not None: + args["disable_auth"] = field + + field = data.get("public_network", None) + if field is not None: + args["public_network"] = unmarshal_EndpointPublicNetworkDetails(field) + else: + args["public_network"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None + + return Endpoint(**args) + + +def unmarshal_ModelSupportedQuantization(data: Any) -> ModelSupportedQuantization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportedQuantization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("quantization_bits", None) + if field is not None: + args["quantization_bits"] = field + + field = data.get("allowed", None) + if field is not None: + args["allowed"] = field + + field = data.get("max_context_size", None) + if field is not None: + args["max_context_size"] = field + + return ModelSupportedQuantization(**args) + + +def unmarshal_ModelSupportedNode(data: Any) -> ModelSupportedNode: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportedNode' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_type_name", None) + if field is not None: + args["node_type_name"] = field + + field = data.get("quantizations", None) + if field is not None: + args["quantizations"] = ( + [unmarshal_ModelSupportedQuantization(v) for v in field] + if field is not None + else None + ) + + return ModelSupportedNode(**args) + + +def unmarshal_ModelSupportInfo(data: Any) -> ModelSupportInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("nodes", None) + if field is not None: + args["nodes"] = ( + [unmarshal_ModelSupportedNode(v) for v in field] + if field is not None + else None + ) + + return ModelSupportInfo(**args) + + +def unmarshal_DeploymentQuantization(data: Any) -> DeploymentQuantization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DeploymentQuantization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("bits", None) + if field is not None: + args["bits"] = field + + return DeploymentQuantization(**args) + + +def unmarshal_Deployment(data: Any) -> Deployment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Deployment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("node_type_name", None) + if field is not None: + args["node_type_name"] = field + + field = data.get("endpoints", None) + if field is not None: + args["endpoints"] = ( + [unmarshal_Endpoint(v) for v in field] if field is not None else None + ) + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("min_size", None) + if field is not None: + args["min_size"] = field + + field = data.get("max_size", None) + if field is not None: + args["max_size"] = field + + field = data.get("model_id", None) + if field is not None: + args["model_id"] = field + + field = data.get("model_name", None) + if field is not None: + args["model_name"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("quantization", None) + if field is not None: + args["quantization"] = unmarshal_DeploymentQuantization(field) + else: + args["quantization"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Deployment(**args) + + +def unmarshal_Model(data: Any) -> Model: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Model' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("has_eula", None) + if field is not None: + args["has_eula"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("nodes_support", None) + if field is not None: + args["nodes_support"] = ( + [unmarshal_ModelSupportInfo(v) for v in field] + if field is not None + else None + ) + + field = data.get("parameter_size_bits", None) + if field is not None: + args["parameter_size_bits"] = field + + field = data.get("size_bytes", None) + if field is not None: + args["size_bytes"] = field + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Model(**args) + + +def unmarshal_ListDeploymentsResponse(data: Any) -> ListDeploymentsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDeploymentsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("deployments", None) + if field is not None: + args["deployments"] = ( + [unmarshal_Deployment(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDeploymentsResponse(**args) + + +def unmarshal_ListModelsResponse(data: Any) -> ListModelsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListModelsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("models", None) + if field is not None: + args["models"] = ( + [unmarshal_Model(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListModelsResponse(**args) + + +def unmarshal_NodeType(data: Any) -> NodeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("stock_status", None) + if field is not None: + args["stock_status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("vcpus", None) + if field is not None: + args["vcpus"] = field + + field = data.get("memory", None) + if field is not None: + args["memory"] = field + + field = data.get("vram", None) + if field is not None: + args["vram"] = field + + field = data.get("disabled", None) + if field is not None: + args["disabled"] = field + + field = data.get("beta", None) + if field is not None: + args["beta"] = field + + field = data.get("gpus", None) + if field is not None: + args["gpus"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return NodeType(**args) + + +def unmarshal_ListNodeTypesResponse(data: Any) -> ListNodeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListNodeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_types", None) + if field is not None: + args["node_types"] = ( + [unmarshal_NodeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListNodeTypesResponse(**args) + + +def marshal_EndpointPrivateNetworkDetails( + request: EndpointPrivateNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + +def marshal_EndpointPublicNetworkDetails( + request: EndpointPublicNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_DeploymentQuantization( + request: DeploymentQuantization, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enabled is not None: + output["enabled"] = request.enabled + + if request.bits is not None: + output["bits"] = request.bits + + return output + + +def marshal_EndpointSpec( + request: EndpointSpec, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("public_network", request.public_network), + OneOfPossibility("private_network", request.private_network), + ] + ), + ) + + if request.disable_auth is not None: + output["disable_auth"] = request.disable_auth + + return output + + +def marshal_CreateDeploymentRequest( + request: CreateDeploymentRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.model_id is not None: + output["model_id"] = request.model_id + + if request.node_type_name is not None: + output["node_type_name"] = request.node_type_name + + if request.endpoints is not None: + output["endpoints"] = [ + marshal_EndpointSpec(item, defaults) for item in request.endpoints + ] + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.accept_eula is not None: + output["accept_eula"] = request.accept_eula + + if request.tags is not None: + output["tags"] = request.tags + + if request.min_size is not None: + output["min_size"] = request.min_size + + if request.max_size is not None: + output["max_size"] = request.max_size + + if request.quantization is not None: + output["quantization"] = marshal_DeploymentQuantization( + request.quantization, defaults + ) + + return output + + +def marshal_CreateEndpointRequest( + request: CreateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.deployment_id is not None: + output["deployment_id"] = request.deployment_id + + if request.endpoint is not None: + output["endpoint"] = marshal_EndpointSpec(request.endpoint, defaults) + + return output + + +def marshal_ModelSource( + request: ModelSource, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + ] + ), + ) + + if request.url is not None: + output["url"] = request.url + + return output + + +def marshal_CreateModelRequest( + request: CreateModelRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.source is not None: + output["source"] = marshal_ModelSource(request.source, defaults) + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_UpdateDeploymentRequest( + request: UpdateDeploymentRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.min_size is not None: + output["min_size"] = request.min_size + + if request.max_size is not None: + output["max_size"] = request.max_size + + return output + + +def marshal_UpdateEndpointRequest( + request: UpdateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.disable_auth is not None: + output["disable_auth"] = request.disable_auth + + return output diff --git a/scaleway/scaleway/inference/v1/types.py b/scaleway/scaleway/inference/v1/types.py new file mode 100644 index 000000000..9dd6fce4b --- /dev/null +++ b/scaleway/scaleway/inference/v1/types.py @@ -0,0 +1,770 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DeploymentStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + DEPLOYING = "deploying" + READY = "ready" + ERROR = "error" + DELETING = "deleting" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ListDeploymentsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListModelsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DISPLAY_RANK_ASC = "display_rank_asc" + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ModelStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + PREPARING = "preparing" + DOWNLOADING = "downloading" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class NodeTypeStock(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STOCK = "unknown_stock" + LOW_STOCK = "low_stock" + OUT_OF_STOCK = "out_of_stock" + AVAILABLE = "available" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ModelSupportedQuantization: + quantization_bits: int + """ + Number of bits for this supported quantization. + """ + + allowed: bool + """ + Tells whether this quantization is allowed for this node type. + """ + + max_context_size: int + """ + Maximum inference context size available for this node type and quantization. + """ + + +@dataclass +class EndpointPrivateNetworkDetails: + private_network_id: str + + +@dataclass +class EndpointPublicNetworkDetails: + pass + + +@dataclass +class ModelSupportedNode: + node_type_name: str + """ + Supported node type. + """ + + quantizations: List[ModelSupportedQuantization] + """ + Supported quantizations. + """ + + +@dataclass +class DeploymentQuantization: + enabled: bool + """ + Whether to enable quantization for this deployment. + """ + + bits: int + """ + The number of bits each model parameter should be quantized to. The quantization method is chosen based on this value. + """ + + +@dataclass +class Endpoint: + id: str + """ + Unique identifier. + """ + + url: str + """ + For private endpoints, the URL will be accessible only from the Private Network. +In addition, private endpoints will expose a CA certificate that can be used to verify the server's identity. +This CA certificate can be retrieved using the `GetDeploymentCertificate` API call. + """ + + disable_auth: bool + """ + Defines whether the authentication is disabled. + """ + + public_network: Optional[EndpointPublicNetworkDetails] + + private_network: Optional[EndpointPrivateNetworkDetails] + + +@dataclass +class ModelSupportInfo: + nodes: List[ModelSupportedNode] + """ + List of supported node types. + """ + + +@dataclass +class EndpointSpec: + disable_auth: bool + """ + By default, deployments are protected by IAM authentication. +When setting this field to true, the authentication will be disabled. + """ + + public_network: Optional[EndpointPublicNetworkDetails] + + private_network: Optional[EndpointPrivateNetworkDetails] + + +@dataclass +class ModelSource: + url: str + + secret: Optional[str] + + +@dataclass +class Deployment: + id: str + """ + Unique identifier. + """ + + name: str + """ + Name of the deployment. + """ + + project_id: str + """ + Project ID. + """ + + status: DeploymentStatus + """ + Status of the deployment. + """ + + tags: List[str] + """ + List of tags applied to the deployment. + """ + + node_type_name: str + """ + Node type of the deployment. + """ + + endpoints: List[Endpoint] + """ + List of endpoints. + """ + + size: int + """ + Current size of the pool. + """ + + min_size: int + """ + Defines the minimum size of the pool. + """ + + max_size: int + """ + Defines the maximum size of the pool. + """ + + model_id: str + """ + ID of the model used for the deployment. + """ + + model_name: str + """ + Name of the deployed model. + """ + + region: ScwRegion + """ + Region of the deployment. + """ + + error_message: Optional[str] + """ + Displays information if your deployment is in error state. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization parameters for this deployment. + """ + + created_at: Optional[datetime] + """ + Creation date of the deployment. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the deployment. + """ + + +@dataclass +class Model: + id: str + """ + Unique identifier. + """ + + name: str + """ + Unique Name identifier. + """ + + project_id: str + """ + Project ID. + """ + + tags: List[str] + """ + List of tags applied to the model. + """ + + status: ModelStatus + """ + Status of the model. + """ + + description: str + """ + Purpose of the model. + """ + + has_eula: bool + """ + Defines whether the model has an end user license agreement. + """ + + region: ScwRegion + """ + Region of the model. + """ + + nodes_support: List[ModelSupportInfo] + """ + Supported nodes types with quantization options and context lengths. + """ + + parameter_size_bits: int + """ + Size, in bits, of the model parameters. + """ + + size_bytes: int + """ + Total size, in bytes, of the model files. + """ + + error_message: Optional[str] + """ + Displays information if your model is in error state. + """ + + created_at: Optional[datetime] + """ + Creation date of the model. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the model. + """ + + +@dataclass +class NodeType: + name: str + """ + Name of the node type. + """ + + stock_status: NodeTypeStock + """ + Current stock status for the node type. + """ + + description: str + """ + Current specs of the offer. + """ + + vcpus: int + """ + Number of virtual CPUs. + """ + + memory: int + """ + Quantity of RAM. + """ + + vram: int + """ + Quantity of GPU RAM. + """ + + disabled: bool + """ + The node type is currently disabled. + """ + + beta: bool + """ + The node type is currently in beta. + """ + + gpus: int + """ + Number of GPUs. + """ + + region: ScwRegion + """ + Region of the node type. + """ + + created_at: Optional[datetime] + """ + Creation date of the node type. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the node type. + """ + + +@dataclass +class CreateDeploymentRequest: + model_id: str + """ + ID of the model to use. + """ + + node_type_name: str + """ + Name of the node type to use. + """ + + endpoints: List[EndpointSpec] + """ + List of endpoints to create. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the deployment. + """ + + project_id: Optional[str] + """ + ID of the Project to create the deployment in. + """ + + accept_eula: Optional[bool] + """ + If the model has an EULA, you must accept it before proceeding. +The terms of the EULA can be retrieved using the `GetModelEula` API call. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the deployment. + """ + + min_size: Optional[int] + """ + Defines the minimum size of the pool. + """ + + max_size: Optional[int] + """ + Defines the maximum size of the pool. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization settings to apply to this deployment. + """ + + +@dataclass +class CreateEndpointRequest: + deployment_id: str + """ + ID of the deployment to create the endpoint for. + """ + + endpoint: EndpointSpec + """ + Specification of the endpoint. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateModelRequest: + source: ModelSource + """ + Where to import the model from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the model. + """ + + project_id: Optional[str] + """ + ID of the Project to import the model in. + """ + + +@dataclass +class DeleteDeploymentRequest: + deployment_id: str + """ + ID of the deployment to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteEndpointRequest: + endpoint_id: str + """ + ID of the endpoint to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteModelRequest: + model_id: str + """ + ID of the model to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDeploymentCertificateRequest: + deployment_id: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDeploymentRequest: + deployment_id: str + """ + ID of the deployment to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetModelRequest: + model_id: str + """ + ID of the model to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListDeploymentsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of deployments to return per page. + """ + + order_by: Optional[ListDeploymentsRequestOrderBy] + """ + Order in which to return results. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + name: Optional[str] + """ + Filter by deployment name. + """ + + tags: Optional[List[str]] + """ + Filter by tags. + """ + + +@dataclass +class ListDeploymentsResponse: + deployments: List[Deployment] + """ + List of deployments on the current page. + """ + + total_count: int + """ + Total number of deployments. + """ + + +@dataclass +class ListModelsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListModelsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of models to return per page. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + name: Optional[str] + """ + Filter by model name. + """ + + tags: Optional[List[str]] + """ + Filter by tags. + """ + + +@dataclass +class ListModelsResponse: + models: List[Model] + """ + List of models on the current page. + """ + + total_count: int + """ + Total number of models. + """ + + +@dataclass +class ListNodeTypesRequest: + include_disabled_types: bool + """ + Include disabled node types in the response. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of node types to return per page. + """ + + +@dataclass +class ListNodeTypesResponse: + node_types: List[NodeType] + """ + List of node types. + """ + + total_count: int + """ + Total number of node types. + """ + + +@dataclass +class UpdateDeploymentRequest: + deployment_id: str + """ + ID of the deployment to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the deployment. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the deployment. + """ + + min_size: Optional[int] + """ + Defines the new minimum size of the pool. + """ + + max_size: Optional[int] + """ + Defines the new maximum size of the pool. + """ + + +@dataclass +class UpdateEndpointRequest: + endpoint_id: str + """ + ID of the endpoint to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + disable_auth: Optional[bool] + """ + By default, deployments are protected by IAM authentication. +When setting this field to true, the authentication will be disabled. + """ From badb5c7787a013d79affe263bf2f181a5958cbf1 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Wed, 12 Mar 2025 15:44:33 +0100 Subject: [PATCH 62/73] feat(iam): add type filter to ListUsersRequest (#905) --- scaleway-async/scaleway_async/iam/v1alpha1/api.py | 14 +++++++------- .../scaleway_async/iam/v1alpha1/types.py | 4 ++-- scaleway/scaleway/iam/v1alpha1/api.py | 14 +++++++------- scaleway/scaleway/iam/v1alpha1/types.py | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/api.py b/scaleway-async/scaleway_async/iam/v1alpha1/api.py index c857a1ab6..7198e8168 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/api.py @@ -26,7 +26,7 @@ ListUsersRequestOrderBy, LogAction, LogResourceType, - UserStatus, + UserType, APIKey, AddGroupMemberRequest, AddGroupMembersRequest, @@ -376,7 +376,7 @@ async def list_users( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, - status: Optional[UserStatus] = None, + type_: Optional[UserType] = None, ) -> ListUsersResponse: """ List users of an Organization. @@ -388,7 +388,7 @@ async def list_users( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. - :param status: Filter by user status. + :param type_: Filter by user type. :return: :class:`ListUsersResponse ` Usage: @@ -407,8 +407,8 @@ async def list_users( or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, - "status": status, "tag": tag, + "type": type_, "user_ids": user_ids, }, ) @@ -426,7 +426,7 @@ async def list_users_all( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, - status: Optional[UserStatus] = None, + type_: Optional[UserType] = None, ) -> List[User]: """ List users of an Organization. @@ -438,7 +438,7 @@ async def list_users_all( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. - :param status: Filter by user status. + :param type_: Filter by user type. :return: :class:`List[User] ` Usage: @@ -459,7 +459,7 @@ async def list_users_all( "user_ids": user_ids, "mfa": mfa, "tag": tag, - "status": status, + "type_": type_, }, ) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/types.py b/scaleway-async/scaleway_async/iam/v1alpha1/types.py index 8df9525f8..63d5a38e7 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/types.py @@ -1834,9 +1834,9 @@ class ListUsersRequest: Filter by tags containing a given string. """ - status: Optional[UserStatus] + type_: Optional[UserType] """ - Filter by user status. + Filter by user type. """ diff --git a/scaleway/scaleway/iam/v1alpha1/api.py b/scaleway/scaleway/iam/v1alpha1/api.py index 30a1cbd90..e35098b39 100644 --- a/scaleway/scaleway/iam/v1alpha1/api.py +++ b/scaleway/scaleway/iam/v1alpha1/api.py @@ -26,7 +26,7 @@ ListUsersRequestOrderBy, LogAction, LogResourceType, - UserStatus, + UserType, APIKey, AddGroupMemberRequest, AddGroupMembersRequest, @@ -376,7 +376,7 @@ def list_users( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, - status: Optional[UserStatus] = None, + type_: Optional[UserType] = None, ) -> ListUsersResponse: """ List users of an Organization. @@ -388,7 +388,7 @@ def list_users( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. - :param status: Filter by user status. + :param type_: Filter by user type. :return: :class:`ListUsersResponse ` Usage: @@ -407,8 +407,8 @@ def list_users( or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, - "status": status, "tag": tag, + "type": type_, "user_ids": user_ids, }, ) @@ -426,7 +426,7 @@ def list_users_all( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, - status: Optional[UserStatus] = None, + type_: Optional[UserType] = None, ) -> List[User]: """ List users of an Organization. @@ -438,7 +438,7 @@ def list_users_all( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. - :param status: Filter by user status. + :param type_: Filter by user type. :return: :class:`List[User] ` Usage: @@ -459,7 +459,7 @@ def list_users_all( "user_ids": user_ids, "mfa": mfa, "tag": tag, - "status": status, + "type_": type_, }, ) diff --git a/scaleway/scaleway/iam/v1alpha1/types.py b/scaleway/scaleway/iam/v1alpha1/types.py index 8df9525f8..63d5a38e7 100644 --- a/scaleway/scaleway/iam/v1alpha1/types.py +++ b/scaleway/scaleway/iam/v1alpha1/types.py @@ -1834,9 +1834,9 @@ class ListUsersRequest: Filter by tags containing a given string. """ - status: Optional[UserStatus] + type_: Optional[UserType] """ - Filter by user status. + Filter by user type. """ From 6d48f6e06e56cf4aea6ba3663b4ce376af7c2e46 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Thu, 13 Mar 2025 10:02:30 +0100 Subject: [PATCH 63/73] feat(webhosting): replace domain conf options (#906) --- .../scaleway_async/webhosting/v1/__init__.py | 2 + .../scaleway_async/webhosting/v1/api.py | 31 +++++---- .../webhosting/v1/marshalling.py | 67 +++++++++++++++++++ .../scaleway_async/webhosting/v1/types.py | 64 ++++++++++++++---- scaleway/scaleway/webhosting/v1/__init__.py | 2 + scaleway/scaleway/webhosting/v1/api.py | 31 +++++---- .../scaleway/webhosting/v1/marshalling.py | 67 +++++++++++++++++++ scaleway/scaleway/webhosting/v1/types.py | 64 ++++++++++++++---- 8 files changed, 274 insertions(+), 54 deletions(-) diff --git a/scaleway-async/scaleway_async/webhosting/v1/__init__.py b/scaleway-async/scaleway_async/webhosting/v1/__init__.py index 8c351383b..43df2e816 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/__init__.py +++ b/scaleway-async/scaleway_async/webhosting/v1/__init__.py @@ -28,6 +28,7 @@ from .types import OfferOption from .types import PlatformControlPanel from .types import CreateDatabaseRequestUser +from .types import AutoConfigDomainDns from .types import CreateHostingRequestDomainConfiguration from .types import OfferOptionRequest from .types import SyncDomainDnsRecordsRequestRecord @@ -133,6 +134,7 @@ "OfferOption", "PlatformControlPanel", "CreateDatabaseRequestUser", + "AutoConfigDomainDns", "CreateHostingRequestDomainConfiguration", "OfferOptionRequest", "SyncDomainDnsRecordsRequestRecord", diff --git a/scaleway-async/scaleway_async/webhosting/v1/api.py b/scaleway-async/scaleway_async/webhosting/v1/api.py index a32da410b..0988b7377 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/api.py +++ b/scaleway-async/scaleway_async/webhosting/v1/api.py @@ -22,6 +22,7 @@ ListMailAccountsRequestOrderBy, ListOffersRequestOrderBy, ListWebsitesRequestOrderBy, + AutoConfigDomainDns, CheckUserOwnsDomainResponse, ControlPanel, CreateDatabaseRequestUser, @@ -836,22 +837,24 @@ async def sync_domain_dns_records( self, *, domain: str, - update_web_records: bool, - update_mail_records: bool, - update_all_records: bool, - update_nameservers: bool, region: Optional[ScwRegion] = None, + update_web_records: Optional[bool] = None, + update_mail_records: Optional[bool] = None, + update_all_records: Optional[bool] = None, + update_nameservers: Optional[bool] = None, custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] = None, + auto_config_domain_dns: Optional[AutoConfigDomainDns] = None, ) -> DnsRecords: """ Synchronize your DNS records on the Elements Console and on cPanel. :param domain: Domain for which the DNS records will be synchronized. - :param update_web_records: Whether or not to synchronize the web records. - :param update_mail_records: Whether or not to synchronize the mail records. - :param update_all_records: Whether or not to synchronize all types of records. This one has priority. - :param update_nameservers: Whether or not to synchronize domain nameservers. :param region: Region to target. If none is passed will use default region from the config. + :param update_web_records: Whether or not to synchronize the web records (deprecated, use auto_config_domain_dns). + :param update_mail_records: Whether or not to synchronize the mail records (deprecated, use auto_config_domain_dns). + :param update_all_records: Whether or not to synchronize all types of records. This one has priority (deprecated, use auto_config_domain_dns). + :param update_nameservers: Whether or not to synchronize domain nameservers (deprecated, use auto_config_domain_dns). :param custom_records: Custom records to synchronize. + :param auto_config_domain_dns: Whether or not to synchronize each types of records. :return: :class:`DnsRecords ` Usage: @@ -859,10 +862,6 @@ async def sync_domain_dns_records( result = await api.sync_domain_dns_records( domain="example", - update_web_records=False, - update_mail_records=False, - update_all_records=False, - update_nameservers=False, ) """ @@ -877,12 +876,13 @@ async def sync_domain_dns_records( body=marshal_DnsApiSyncDomainDnsRecordsRequest( DnsApiSyncDomainDnsRecordsRequest( domain=domain, + region=region, update_web_records=update_web_records, update_mail_records=update_mail_records, update_all_records=update_all_records, update_nameservers=update_nameservers, - region=region, custom_records=custom_records, + auto_config_domain_dns=auto_config_domain_dns, ), self.client, ), @@ -1116,6 +1116,7 @@ async def create_hosting( language: Optional[StdLanguageCode] = None, domain_configuration: Optional[CreateHostingRequestDomainConfiguration] = None, skip_welcome_email: Optional[bool] = None, + auto_config_domain_dns: Optional[AutoConfigDomainDns] = None, ) -> Hosting: """ Order a Web Hosting plan. @@ -1128,8 +1129,9 @@ async def create_hosting( :param tags: List of tags for the Web Hosting plan. :param offer_options: List of the Web Hosting plan options IDs with their quantities. :param language: Default language for the control panel interface. - :param domain_configuration: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements. + :param domain_configuration: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_config_domain_dns instead). :param skip_welcome_email: Indicates whether to skip a welcome email to the contact email containing hosting info. + :param auto_config_domain_dns: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_update_* fields instead). :return: :class:`Hosting ` Usage: @@ -1161,6 +1163,7 @@ async def create_hosting( language=language, domain_configuration=domain_configuration, skip_welcome_email=skip_welcome_email, + auto_config_domain_dns=auto_config_domain_dns, ), self.client, ), diff --git a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py index f5882871e..0a78257ee 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py +++ b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py @@ -24,6 +24,7 @@ DnsRecord, Nameserver, DnsRecords, + AutoConfigDomainDns, Domain, PlatformControlPanelUrls, OfferOption, @@ -260,6 +261,33 @@ def unmarshal_DnsRecords(data: Any) -> DnsRecords: return DnsRecords(**args) +def unmarshal_AutoConfigDomainDns(data: Any) -> AutoConfigDomainDns: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AutoConfigDomainDns' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("nameservers", None) + if field is not None: + args["nameservers"] = field + + field = data.get("web_records", None) + if field is not None: + args["web_records"] = field + + field = data.get("mail_records", None) + if field is not None: + args["mail_records"] = field + + field = data.get("all_records", None) + if field is not None: + args["all_records"] = field + + return AutoConfigDomainDns(**args) + + def unmarshal_Domain(data: Any) -> Domain: if not isinstance(data, dict): raise TypeError( @@ -291,6 +319,14 @@ def unmarshal_Domain(data: Any) -> Domain: args["available_dns_actions"] = ( [DomainDnsAction(v) for v in field] if field is not None else None ) + else: + args["available_dns_actions"] = None + + field = data.get("auto_config_domain_dns", None) + if field is not None: + args["auto_config_domain_dns"] = unmarshal_AutoConfigDomainDns(field) + else: + args["auto_config_domain_dns"] = None return Domain(**args) @@ -1070,6 +1106,27 @@ def marshal_DnsApiCheckUserOwnsDomainRequest( return output +def marshal_AutoConfigDomainDns( + request: AutoConfigDomainDns, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.nameservers is not None: + output["nameservers"] = request.nameservers + + if request.web_records is not None: + output["web_records"] = request.web_records + + if request.mail_records is not None: + output["mail_records"] = request.mail_records + + if request.all_records is not None: + output["all_records"] = request.all_records + + return output + + def marshal_SyncDomainDnsRecordsRequestRecord( request: SyncDomainDnsRecordsRequestRecord, defaults: ProfileDefaults, @@ -1109,6 +1166,11 @@ def marshal_DnsApiSyncDomainDnsRecordsRequest( for item in request.custom_records ] + if request.auto_config_domain_dns is not None: + output["auto_config_domain_dns"] = marshal_AutoConfigDomainDns( + request.auto_config_domain_dns, defaults + ) + return output @@ -1217,6 +1279,11 @@ def marshal_HostingApiCreateHostingRequest( if request.skip_welcome_email is not None: output["skip_welcome_email"] = request.skip_welcome_email + if request.auto_config_domain_dns is not None: + output["auto_config_domain_dns"] = marshal_AutoConfigDomainDns( + request.auto_config_domain_dns, defaults + ) + return output diff --git a/scaleway-async/scaleway_async/webhosting/v1/types.py b/scaleway-async/scaleway_async/webhosting/v1/types.py index cf37b2064..6bf9257c4 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/types.py +++ b/scaleway-async/scaleway_async/webhosting/v1/types.py @@ -307,6 +307,29 @@ class CreateDatabaseRequestUser: password: str +@dataclass +class AutoConfigDomainDns: + nameservers: bool + """ + Whether or not to synchronize domain nameservers. + """ + + web_records: bool + """ + Whether or not to synchronize web records. + """ + + mail_records: bool + """ + Whether or not to synchronize mail records. + """ + + all_records: bool + """ + Whether or not to synchronize all types of records. Takes priority over the other fields. + """ + + @dataclass class CreateHostingRequestDomainConfiguration: update_nameservers: bool @@ -1019,29 +1042,29 @@ class DnsApiSyncDomainDnsRecordsRequest: Domain for which the DNS records will be synchronized. """ - update_web_records: bool + region: Optional[ScwRegion] """ - Whether or not to synchronize the web records. + Region to target. If none is passed will use default region from the config. """ - update_mail_records: bool + update_web_records: Optional[bool] """ - Whether or not to synchronize the mail records. + Whether or not to synchronize the web records (deprecated, use auto_config_domain_dns). """ - update_all_records: bool + update_mail_records: Optional[bool] """ - Whether or not to synchronize all types of records. This one has priority. + Whether or not to synchronize the mail records (deprecated, use auto_config_domain_dns). """ - update_nameservers: bool + update_all_records: Optional[bool] """ - Whether or not to synchronize domain nameservers. + Whether or not to synchronize all types of records. This one has priority (deprecated, use auto_config_domain_dns). """ - region: Optional[ScwRegion] + update_nameservers: Optional[bool] """ - Region to target. If none is passed will use default region from the config. + Whether or not to synchronize domain nameservers (deprecated, use auto_config_domain_dns). """ custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] @@ -1049,6 +1072,11 @@ class DnsApiSyncDomainDnsRecordsRequest: Custom records to synchronize. """ + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Whether or not to synchronize each types of records. + """ + @dataclass class DnsRecords: @@ -1095,9 +1123,14 @@ class Domain: A list of actions that can be performed on the domain. """ - available_dns_actions: List[DomainDnsAction] + available_dns_actions: Optional[List[DomainDnsAction]] + """ + A list of DNS-related actions that can be auto configured for the domain (deprecated, use auto_config_domain_dns instead). + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] """ - A list of DNS-related actions that can be auto configured for the domain. + Whether or not to synchronize each type of record. """ @@ -1325,7 +1358,7 @@ class HostingApiCreateHostingRequest: domain_configuration: Optional[CreateHostingRequestDomainConfiguration] """ - Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements. + Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_config_domain_dns instead). """ skip_welcome_email: Optional[bool] @@ -1333,6 +1366,11 @@ class HostingApiCreateHostingRequest: Indicates whether to skip a welcome email to the contact email containing hosting info. """ + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_update_* fields instead). + """ + @dataclass class HostingApiCreateSessionRequest: diff --git a/scaleway/scaleway/webhosting/v1/__init__.py b/scaleway/scaleway/webhosting/v1/__init__.py index 8c351383b..43df2e816 100644 --- a/scaleway/scaleway/webhosting/v1/__init__.py +++ b/scaleway/scaleway/webhosting/v1/__init__.py @@ -28,6 +28,7 @@ from .types import OfferOption from .types import PlatformControlPanel from .types import CreateDatabaseRequestUser +from .types import AutoConfigDomainDns from .types import CreateHostingRequestDomainConfiguration from .types import OfferOptionRequest from .types import SyncDomainDnsRecordsRequestRecord @@ -133,6 +134,7 @@ "OfferOption", "PlatformControlPanel", "CreateDatabaseRequestUser", + "AutoConfigDomainDns", "CreateHostingRequestDomainConfiguration", "OfferOptionRequest", "SyncDomainDnsRecordsRequestRecord", diff --git a/scaleway/scaleway/webhosting/v1/api.py b/scaleway/scaleway/webhosting/v1/api.py index d613fc2aa..7c925ee6e 100644 --- a/scaleway/scaleway/webhosting/v1/api.py +++ b/scaleway/scaleway/webhosting/v1/api.py @@ -22,6 +22,7 @@ ListMailAccountsRequestOrderBy, ListOffersRequestOrderBy, ListWebsitesRequestOrderBy, + AutoConfigDomainDns, CheckUserOwnsDomainResponse, ControlPanel, CreateDatabaseRequestUser, @@ -836,22 +837,24 @@ def sync_domain_dns_records( self, *, domain: str, - update_web_records: bool, - update_mail_records: bool, - update_all_records: bool, - update_nameservers: bool, region: Optional[ScwRegion] = None, + update_web_records: Optional[bool] = None, + update_mail_records: Optional[bool] = None, + update_all_records: Optional[bool] = None, + update_nameservers: Optional[bool] = None, custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] = None, + auto_config_domain_dns: Optional[AutoConfigDomainDns] = None, ) -> DnsRecords: """ Synchronize your DNS records on the Elements Console and on cPanel. :param domain: Domain for which the DNS records will be synchronized. - :param update_web_records: Whether or not to synchronize the web records. - :param update_mail_records: Whether or not to synchronize the mail records. - :param update_all_records: Whether or not to synchronize all types of records. This one has priority. - :param update_nameservers: Whether or not to synchronize domain nameservers. :param region: Region to target. If none is passed will use default region from the config. + :param update_web_records: Whether or not to synchronize the web records (deprecated, use auto_config_domain_dns). + :param update_mail_records: Whether or not to synchronize the mail records (deprecated, use auto_config_domain_dns). + :param update_all_records: Whether or not to synchronize all types of records. This one has priority (deprecated, use auto_config_domain_dns). + :param update_nameservers: Whether or not to synchronize domain nameservers (deprecated, use auto_config_domain_dns). :param custom_records: Custom records to synchronize. + :param auto_config_domain_dns: Whether or not to synchronize each types of records. :return: :class:`DnsRecords ` Usage: @@ -859,10 +862,6 @@ def sync_domain_dns_records( result = api.sync_domain_dns_records( domain="example", - update_web_records=False, - update_mail_records=False, - update_all_records=False, - update_nameservers=False, ) """ @@ -877,12 +876,13 @@ def sync_domain_dns_records( body=marshal_DnsApiSyncDomainDnsRecordsRequest( DnsApiSyncDomainDnsRecordsRequest( domain=domain, + region=region, update_web_records=update_web_records, update_mail_records=update_mail_records, update_all_records=update_all_records, update_nameservers=update_nameservers, - region=region, custom_records=custom_records, + auto_config_domain_dns=auto_config_domain_dns, ), self.client, ), @@ -1116,6 +1116,7 @@ def create_hosting( language: Optional[StdLanguageCode] = None, domain_configuration: Optional[CreateHostingRequestDomainConfiguration] = None, skip_welcome_email: Optional[bool] = None, + auto_config_domain_dns: Optional[AutoConfigDomainDns] = None, ) -> Hosting: """ Order a Web Hosting plan. @@ -1128,8 +1129,9 @@ def create_hosting( :param tags: List of tags for the Web Hosting plan. :param offer_options: List of the Web Hosting plan options IDs with their quantities. :param language: Default language for the control panel interface. - :param domain_configuration: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements. + :param domain_configuration: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_config_domain_dns instead). :param skip_welcome_email: Indicates whether to skip a welcome email to the contact email containing hosting info. + :param auto_config_domain_dns: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_update_* fields instead). :return: :class:`Hosting ` Usage: @@ -1161,6 +1163,7 @@ def create_hosting( language=language, domain_configuration=domain_configuration, skip_welcome_email=skip_welcome_email, + auto_config_domain_dns=auto_config_domain_dns, ), self.client, ), diff --git a/scaleway/scaleway/webhosting/v1/marshalling.py b/scaleway/scaleway/webhosting/v1/marshalling.py index f5882871e..0a78257ee 100644 --- a/scaleway/scaleway/webhosting/v1/marshalling.py +++ b/scaleway/scaleway/webhosting/v1/marshalling.py @@ -24,6 +24,7 @@ DnsRecord, Nameserver, DnsRecords, + AutoConfigDomainDns, Domain, PlatformControlPanelUrls, OfferOption, @@ -260,6 +261,33 @@ def unmarshal_DnsRecords(data: Any) -> DnsRecords: return DnsRecords(**args) +def unmarshal_AutoConfigDomainDns(data: Any) -> AutoConfigDomainDns: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AutoConfigDomainDns' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("nameservers", None) + if field is not None: + args["nameservers"] = field + + field = data.get("web_records", None) + if field is not None: + args["web_records"] = field + + field = data.get("mail_records", None) + if field is not None: + args["mail_records"] = field + + field = data.get("all_records", None) + if field is not None: + args["all_records"] = field + + return AutoConfigDomainDns(**args) + + def unmarshal_Domain(data: Any) -> Domain: if not isinstance(data, dict): raise TypeError( @@ -291,6 +319,14 @@ def unmarshal_Domain(data: Any) -> Domain: args["available_dns_actions"] = ( [DomainDnsAction(v) for v in field] if field is not None else None ) + else: + args["available_dns_actions"] = None + + field = data.get("auto_config_domain_dns", None) + if field is not None: + args["auto_config_domain_dns"] = unmarshal_AutoConfigDomainDns(field) + else: + args["auto_config_domain_dns"] = None return Domain(**args) @@ -1070,6 +1106,27 @@ def marshal_DnsApiCheckUserOwnsDomainRequest( return output +def marshal_AutoConfigDomainDns( + request: AutoConfigDomainDns, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.nameservers is not None: + output["nameservers"] = request.nameservers + + if request.web_records is not None: + output["web_records"] = request.web_records + + if request.mail_records is not None: + output["mail_records"] = request.mail_records + + if request.all_records is not None: + output["all_records"] = request.all_records + + return output + + def marshal_SyncDomainDnsRecordsRequestRecord( request: SyncDomainDnsRecordsRequestRecord, defaults: ProfileDefaults, @@ -1109,6 +1166,11 @@ def marshal_DnsApiSyncDomainDnsRecordsRequest( for item in request.custom_records ] + if request.auto_config_domain_dns is not None: + output["auto_config_domain_dns"] = marshal_AutoConfigDomainDns( + request.auto_config_domain_dns, defaults + ) + return output @@ -1217,6 +1279,11 @@ def marshal_HostingApiCreateHostingRequest( if request.skip_welcome_email is not None: output["skip_welcome_email"] = request.skip_welcome_email + if request.auto_config_domain_dns is not None: + output["auto_config_domain_dns"] = marshal_AutoConfigDomainDns( + request.auto_config_domain_dns, defaults + ) + return output diff --git a/scaleway/scaleway/webhosting/v1/types.py b/scaleway/scaleway/webhosting/v1/types.py index cf37b2064..6bf9257c4 100644 --- a/scaleway/scaleway/webhosting/v1/types.py +++ b/scaleway/scaleway/webhosting/v1/types.py @@ -307,6 +307,29 @@ class CreateDatabaseRequestUser: password: str +@dataclass +class AutoConfigDomainDns: + nameservers: bool + """ + Whether or not to synchronize domain nameservers. + """ + + web_records: bool + """ + Whether or not to synchronize web records. + """ + + mail_records: bool + """ + Whether or not to synchronize mail records. + """ + + all_records: bool + """ + Whether or not to synchronize all types of records. Takes priority over the other fields. + """ + + @dataclass class CreateHostingRequestDomainConfiguration: update_nameservers: bool @@ -1019,29 +1042,29 @@ class DnsApiSyncDomainDnsRecordsRequest: Domain for which the DNS records will be synchronized. """ - update_web_records: bool + region: Optional[ScwRegion] """ - Whether or not to synchronize the web records. + Region to target. If none is passed will use default region from the config. """ - update_mail_records: bool + update_web_records: Optional[bool] """ - Whether or not to synchronize the mail records. + Whether or not to synchronize the web records (deprecated, use auto_config_domain_dns). """ - update_all_records: bool + update_mail_records: Optional[bool] """ - Whether or not to synchronize all types of records. This one has priority. + Whether or not to synchronize the mail records (deprecated, use auto_config_domain_dns). """ - update_nameservers: bool + update_all_records: Optional[bool] """ - Whether or not to synchronize domain nameservers. + Whether or not to synchronize all types of records. This one has priority (deprecated, use auto_config_domain_dns). """ - region: Optional[ScwRegion] + update_nameservers: Optional[bool] """ - Region to target. If none is passed will use default region from the config. + Whether or not to synchronize domain nameservers (deprecated, use auto_config_domain_dns). """ custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] @@ -1049,6 +1072,11 @@ class DnsApiSyncDomainDnsRecordsRequest: Custom records to synchronize. """ + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Whether or not to synchronize each types of records. + """ + @dataclass class DnsRecords: @@ -1095,9 +1123,14 @@ class Domain: A list of actions that can be performed on the domain. """ - available_dns_actions: List[DomainDnsAction] + available_dns_actions: Optional[List[DomainDnsAction]] + """ + A list of DNS-related actions that can be auto configured for the domain (deprecated, use auto_config_domain_dns instead). + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] """ - A list of DNS-related actions that can be auto configured for the domain. + Whether or not to synchronize each type of record. """ @@ -1325,7 +1358,7 @@ class HostingApiCreateHostingRequest: domain_configuration: Optional[CreateHostingRequestDomainConfiguration] """ - Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements. + Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_config_domain_dns instead). """ skip_welcome_email: Optional[bool] @@ -1333,6 +1366,11 @@ class HostingApiCreateHostingRequest: Indicates whether to skip a welcome email to the contact email containing hosting info. """ + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_update_* fields instead). + """ + @dataclass class HostingApiCreateSessionRequest: From cc4254402b57016c3cbe144fa7053423d1ef797c Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Fri, 14 Mar 2025 14:20:21 +0100 Subject: [PATCH 64/73] feat(cockpit): update naming OB-276 (#907) --- scaleway-async/scaleway_async/cockpit/v1/api.py | 12 ++++++------ .../scaleway_async/cockpit/v1/marshalling.py | 16 ++++++---------- .../scaleway_async/cockpit/v1/types.py | 6 +++--- scaleway/scaleway/cockpit/v1/api.py | 12 ++++++------ scaleway/scaleway/cockpit/v1/marshalling.py | 16 ++++++---------- scaleway/scaleway/cockpit/v1/types.py | 6 +++--- 6 files changed, 30 insertions(+), 38 deletions(-) diff --git a/scaleway-async/scaleway_async/cockpit/v1/api.py b/scaleway-async/scaleway_async/cockpit/v1/api.py index 22bda241f..61c8fb4b0 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/api.py +++ b/scaleway-async/scaleway_async/cockpit/v1/api.py @@ -1231,7 +1231,7 @@ async def create_contact_point( region: Optional[ScwRegion] = None, project_id: Optional[str] = None, email: Optional[ContactPointEmail] = None, - receive_resolved_notifications: Optional[bool] = None, + send_resolved_notifications: Optional[bool] = None, ) -> ContactPoint: """ Create a contact point. @@ -1242,7 +1242,7 @@ async def create_contact_point( :param project_id: ID of the Project to create the contact point in. :param email: Email address of the contact point to create. One-Of ('configuration'): at most one of 'email' could be set. - :param receive_resolved_notifications: Send an email notification when an alert is marked as resolved. + :param send_resolved_notifications: Send an email notification when an alert is marked as resolved. :return: :class:`ContactPoint ` Usage: @@ -1262,7 +1262,7 @@ async def create_contact_point( RegionalApiCreateContactPointRequest( region=region, project_id=project_id, - receive_resolved_notifications=receive_resolved_notifications, + send_resolved_notifications=send_resolved_notifications, email=email, ), self.client, @@ -1353,14 +1353,14 @@ async def update_contact_point( region: Optional[ScwRegion] = None, project_id: Optional[str] = None, email: Optional[ContactPointEmail] = None, - receive_resolved_notifications: Optional[bool] = None, + send_resolved_notifications: Optional[bool] = None, ) -> ContactPoint: """ :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the Project containing the contact point to update. :param email: Email address of the contact point to update. One-Of ('configuration'): at most one of 'email' could be set. - :param receive_resolved_notifications: Enable or disable notifications when alert is resolved. + :param send_resolved_notifications: Enable or disable notifications when alert is resolved. :return: :class:`ContactPoint ` Usage: @@ -1380,7 +1380,7 @@ async def update_contact_point( RegionalApiUpdateContactPointRequest( region=region, project_id=project_id, - receive_resolved_notifications=receive_resolved_notifications, + send_resolved_notifications=send_resolved_notifications, email=email, ), self.client, diff --git a/scaleway-async/scaleway_async/cockpit/v1/marshalling.py b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py index 5a72373eb..65c895435 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/marshalling.py +++ b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py @@ -77,9 +77,9 @@ def unmarshal_ContactPoint(data: Any) -> ContactPoint: if field is not None: args["region"] = field - field = data.get("receive_resolved_notifications", None) + field = data.get("send_resolved_notifications", None) if field is not None: - args["receive_resolved_notifications"] = field + args["send_resolved_notifications"] = field field = data.get("email", None) if field is not None: @@ -792,10 +792,8 @@ def marshal_RegionalApiCreateContactPointRequest( if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id - if request.receive_resolved_notifications is not None: - output["receive_resolved_notifications"] = ( - request.receive_resolved_notifications - ) + if request.send_resolved_notifications is not None: + output["send_resolved_notifications"] = request.send_resolved_notifications return output @@ -934,10 +932,8 @@ def marshal_RegionalApiUpdateContactPointRequest( if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id - if request.receive_resolved_notifications is not None: - output["receive_resolved_notifications"] = ( - request.receive_resolved_notifications - ) + if request.send_resolved_notifications is not None: + output["send_resolved_notifications"] = request.send_resolved_notifications return output diff --git a/scaleway-async/scaleway_async/cockpit/v1/types.py b/scaleway-async/scaleway_async/cockpit/v1/types.py index 967fae25f..21885a85d 100644 --- a/scaleway-async/scaleway_async/cockpit/v1/types.py +++ b/scaleway-async/scaleway_async/cockpit/v1/types.py @@ -174,7 +174,7 @@ class ContactPoint: Region. """ - receive_resolved_notifications: bool + send_resolved_notifications: bool """ Send an email notification when an alert is marked as resolved. """ @@ -859,7 +859,7 @@ class RegionalApiCreateContactPointRequest: ID of the Project to create the contact point in. """ - receive_resolved_notifications: Optional[bool] + send_resolved_notifications: Optional[bool] """ Send an email notification when an alert is marked as resolved. """ @@ -1293,7 +1293,7 @@ class RegionalApiUpdateContactPointRequest: ID of the Project containing the contact point to update. """ - receive_resolved_notifications: Optional[bool] + send_resolved_notifications: Optional[bool] """ Enable or disable notifications when alert is resolved. """ diff --git a/scaleway/scaleway/cockpit/v1/api.py b/scaleway/scaleway/cockpit/v1/api.py index e97de018e..0e522b8cd 100644 --- a/scaleway/scaleway/cockpit/v1/api.py +++ b/scaleway/scaleway/cockpit/v1/api.py @@ -1231,7 +1231,7 @@ def create_contact_point( region: Optional[ScwRegion] = None, project_id: Optional[str] = None, email: Optional[ContactPointEmail] = None, - receive_resolved_notifications: Optional[bool] = None, + send_resolved_notifications: Optional[bool] = None, ) -> ContactPoint: """ Create a contact point. @@ -1242,7 +1242,7 @@ def create_contact_point( :param project_id: ID of the Project to create the contact point in. :param email: Email address of the contact point to create. One-Of ('configuration'): at most one of 'email' could be set. - :param receive_resolved_notifications: Send an email notification when an alert is marked as resolved. + :param send_resolved_notifications: Send an email notification when an alert is marked as resolved. :return: :class:`ContactPoint ` Usage: @@ -1262,7 +1262,7 @@ def create_contact_point( RegionalApiCreateContactPointRequest( region=region, project_id=project_id, - receive_resolved_notifications=receive_resolved_notifications, + send_resolved_notifications=send_resolved_notifications, email=email, ), self.client, @@ -1353,14 +1353,14 @@ def update_contact_point( region: Optional[ScwRegion] = None, project_id: Optional[str] = None, email: Optional[ContactPointEmail] = None, - receive_resolved_notifications: Optional[bool] = None, + send_resolved_notifications: Optional[bool] = None, ) -> ContactPoint: """ :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the Project containing the contact point to update. :param email: Email address of the contact point to update. One-Of ('configuration'): at most one of 'email' could be set. - :param receive_resolved_notifications: Enable or disable notifications when alert is resolved. + :param send_resolved_notifications: Enable or disable notifications when alert is resolved. :return: :class:`ContactPoint ` Usage: @@ -1380,7 +1380,7 @@ def update_contact_point( RegionalApiUpdateContactPointRequest( region=region, project_id=project_id, - receive_resolved_notifications=receive_resolved_notifications, + send_resolved_notifications=send_resolved_notifications, email=email, ), self.client, diff --git a/scaleway/scaleway/cockpit/v1/marshalling.py b/scaleway/scaleway/cockpit/v1/marshalling.py index 5a72373eb..65c895435 100644 --- a/scaleway/scaleway/cockpit/v1/marshalling.py +++ b/scaleway/scaleway/cockpit/v1/marshalling.py @@ -77,9 +77,9 @@ def unmarshal_ContactPoint(data: Any) -> ContactPoint: if field is not None: args["region"] = field - field = data.get("receive_resolved_notifications", None) + field = data.get("send_resolved_notifications", None) if field is not None: - args["receive_resolved_notifications"] = field + args["send_resolved_notifications"] = field field = data.get("email", None) if field is not None: @@ -792,10 +792,8 @@ def marshal_RegionalApiCreateContactPointRequest( if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id - if request.receive_resolved_notifications is not None: - output["receive_resolved_notifications"] = ( - request.receive_resolved_notifications - ) + if request.send_resolved_notifications is not None: + output["send_resolved_notifications"] = request.send_resolved_notifications return output @@ -934,10 +932,8 @@ def marshal_RegionalApiUpdateContactPointRequest( if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id - if request.receive_resolved_notifications is not None: - output["receive_resolved_notifications"] = ( - request.receive_resolved_notifications - ) + if request.send_resolved_notifications is not None: + output["send_resolved_notifications"] = request.send_resolved_notifications return output diff --git a/scaleway/scaleway/cockpit/v1/types.py b/scaleway/scaleway/cockpit/v1/types.py index 967fae25f..21885a85d 100644 --- a/scaleway/scaleway/cockpit/v1/types.py +++ b/scaleway/scaleway/cockpit/v1/types.py @@ -174,7 +174,7 @@ class ContactPoint: Region. """ - receive_resolved_notifications: bool + send_resolved_notifications: bool """ Send an email notification when an alert is marked as resolved. """ @@ -859,7 +859,7 @@ class RegionalApiCreateContactPointRequest: ID of the Project to create the contact point in. """ - receive_resolved_notifications: Optional[bool] + send_resolved_notifications: Optional[bool] """ Send an email notification when an alert is marked as resolved. """ @@ -1293,7 +1293,7 @@ class RegionalApiUpdateContactPointRequest: ID of the Project containing the contact point to update. """ - receive_resolved_notifications: Optional[bool] + send_resolved_notifications: Optional[bool] """ Enable or disable notifications when alert is resolved. """ From 121fe1f3e13b0fc54643553a7d1ce1558397d56a Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Fri, 14 Mar 2025 14:21:04 +0100 Subject: [PATCH 65/73] feat(baremetal): add max_size instead of specific size for partitioning (#908) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> --- scaleway-async/scaleway_async/baremetal/v1/marshalling.py | 7 +++++++ scaleway-async/scaleway_async/baremetal/v1/types.py | 2 ++ scaleway/scaleway/baremetal/v1/marshalling.py | 7 +++++++ scaleway/scaleway/baremetal/v1/types.py | 2 ++ 4 files changed, 18 insertions(+) diff --git a/scaleway-async/scaleway_async/baremetal/v1/marshalling.py b/scaleway-async/scaleway_async/baremetal/v1/marshalling.py index e95766ac5..594312c7d 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/marshalling.py +++ b/scaleway-async/scaleway_async/baremetal/v1/marshalling.py @@ -91,6 +91,10 @@ def unmarshal_SchemaPartition(data: Any) -> SchemaPartition: if field is not None: args["size"] = field + field = data.get("use_all_available_space", None) + if field is not None: + args["use_all_available_space"] = field + return SchemaPartition(**args) @@ -1417,6 +1421,9 @@ def marshal_SchemaPartition( if request.size is not None: output["size"] = request.size + if request.use_all_available_space is not None: + output["use_all_available_space"] = request.use_all_available_space + return output diff --git a/scaleway-async/scaleway_async/baremetal/v1/types.py b/scaleway-async/scaleway_async/baremetal/v1/types.py index 6f0a4468a..66ff27256 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/types.py +++ b/scaleway-async/scaleway_async/baremetal/v1/types.py @@ -225,6 +225,8 @@ class SchemaPartition: size: int + use_all_available_space: bool + @dataclass class SchemaPool: diff --git a/scaleway/scaleway/baremetal/v1/marshalling.py b/scaleway/scaleway/baremetal/v1/marshalling.py index e95766ac5..594312c7d 100644 --- a/scaleway/scaleway/baremetal/v1/marshalling.py +++ b/scaleway/scaleway/baremetal/v1/marshalling.py @@ -91,6 +91,10 @@ def unmarshal_SchemaPartition(data: Any) -> SchemaPartition: if field is not None: args["size"] = field + field = data.get("use_all_available_space", None) + if field is not None: + args["use_all_available_space"] = field + return SchemaPartition(**args) @@ -1417,6 +1421,9 @@ def marshal_SchemaPartition( if request.size is not None: output["size"] = request.size + if request.use_all_available_space is not None: + output["use_all_available_space"] = request.use_all_available_space + return output diff --git a/scaleway/scaleway/baremetal/v1/types.py b/scaleway/scaleway/baremetal/v1/types.py index 6f0a4468a..66ff27256 100644 --- a/scaleway/scaleway/baremetal/v1/types.py +++ b/scaleway/scaleway/baremetal/v1/types.py @@ -225,6 +225,8 @@ class SchemaPartition: size: int + use_all_available_space: bool + @dataclass class SchemaPool: From 4373720cc8253780f8851b6f4a31a986858a5a84 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 17 Mar 2025 09:12:28 +0100 Subject: [PATCH 66/73] feat(tem): generate offers cli (#910) --- .../scaleway_async/tem/v1alpha1/__init__.py | 28 ++ .../scaleway_async/tem/v1alpha1/api.py | 225 +++++++++++++ .../tem/v1alpha1/marshalling.py | 280 ++++++++++++++++ .../scaleway_async/tem/v1alpha1/types.py | 307 ++++++++++++++++++ scaleway/scaleway/tem/v1alpha1/__init__.py | 28 ++ scaleway/scaleway/tem/v1alpha1/api.py | 225 +++++++++++++ scaleway/scaleway/tem/v1alpha1/marshalling.py | 280 ++++++++++++++++ scaleway/scaleway/tem/v1alpha1/types.py | 307 ++++++++++++++++++ 8 files changed, 1680 insertions(+) diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/__init__.py b/scaleway-async/scaleway_async/tem/v1alpha1/__init__.py index 805d56c4a..53ba0d7cd 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/__init__.py @@ -14,6 +14,8 @@ from .types import ListEmailsRequestOrderBy from .types import ListWebhookEventsRequestOrderBy from .types import ListWebhooksRequestOrderBy +from .types import OfferName +from .types import PoolStatus from .types import ProjectSettingsPeriodicReportFrequency from .types import WebhookEventStatus from .types import WebhookEventType @@ -32,6 +34,9 @@ from .types import DomainLastStatusDmarcRecord from .types import DomainLastStatusSpfRecord from .types import Domain +from .types import OfferSubscription +from .types import Offer +from .types import Pool from .types import WebhookEvent from .types import Webhook from .types import ProjectSettingsPeriodicReport @@ -50,6 +55,7 @@ from .types import GetDomainLastStatusRequest from .types import GetDomainRequest from .types import GetEmailRequest +from .types import GetProjectConsumptionRequest from .types import GetProjectSettingsRequest from .types import GetStatisticsRequest from .types import GetWebhookRequest @@ -59,14 +65,22 @@ from .types import ListDomainsResponse from .types import ListEmailsRequest from .types import ListEmailsResponse +from .types import ListOfferSubscriptionsRequest +from .types import ListOfferSubscriptionsResponse +from .types import ListOffersRequest +from .types import ListOffersResponse +from .types import ListPoolsRequest +from .types import ListPoolsResponse from .types import ListWebhookEventsRequest from .types import ListWebhookEventsResponse from .types import ListWebhooksRequest from .types import ListWebhooksResponse +from .types import ProjectConsumption from .types import ProjectSettings from .types import RevokeDomainRequest from .types import Statistics from .types import UpdateDomainRequest +from .types import UpdateOfferSubscriptionRequest from .types import UpdateProjectSettingsRequest from .types import UpdateWebhookRequest from .api import TemV1Alpha1API @@ -86,6 +100,8 @@ "ListEmailsRequestOrderBy", "ListWebhookEventsRequestOrderBy", "ListWebhooksRequestOrderBy", + "OfferName", + "PoolStatus", "ProjectSettingsPeriodicReportFrequency", "WebhookEventStatus", "WebhookEventType", @@ -104,6 +120,9 @@ "DomainLastStatusDmarcRecord", "DomainLastStatusSpfRecord", "Domain", + "OfferSubscription", + "Offer", + "Pool", "WebhookEvent", "Webhook", "ProjectSettingsPeriodicReport", @@ -122,6 +141,7 @@ "GetDomainLastStatusRequest", "GetDomainRequest", "GetEmailRequest", + "GetProjectConsumptionRequest", "GetProjectSettingsRequest", "GetStatisticsRequest", "GetWebhookRequest", @@ -131,14 +151,22 @@ "ListDomainsResponse", "ListEmailsRequest", "ListEmailsResponse", + "ListOfferSubscriptionsRequest", + "ListOfferSubscriptionsResponse", + "ListOffersRequest", + "ListOffersResponse", + "ListPoolsRequest", + "ListPoolsResponse", "ListWebhookEventsRequest", "ListWebhookEventsResponse", "ListWebhooksRequest", "ListWebhooksResponse", + "ProjectConsumption", "ProjectSettings", "RevokeDomainRequest", "Statistics", "UpdateDomainRequest", + "UpdateOfferSubscriptionRequest", "UpdateProjectSettingsRequest", "UpdateWebhookRequest", "TemV1Alpha1API", diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/api.py b/scaleway-async/scaleway_async/tem/v1alpha1/api.py index 30e91467b..5d2f82691 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/api.py @@ -23,6 +23,7 @@ ListEmailsRequestOrderBy, ListWebhookEventsRequestOrderBy, ListWebhooksRequestOrderBy, + OfferName, WebhookEventStatus, WebhookEventType, Blocklist, @@ -41,11 +42,18 @@ ListBlocklistsResponse, ListDomainsResponse, ListEmailsResponse, + ListOfferSubscriptionsResponse, + ListOffersResponse, + ListPoolsResponse, ListWebhookEventsResponse, ListWebhooksResponse, + OfferSubscription, + Pool, + ProjectConsumption, ProjectSettings, Statistics, UpdateDomainRequest, + UpdateOfferSubscriptionRequest, UpdateProjectSettingsRequest, UpdateProjectSettingsRequestUpdatePeriodicReport, UpdateWebhookRequest, @@ -59,6 +67,7 @@ from .marshalling import ( unmarshal_Email, unmarshal_Domain, + unmarshal_OfferSubscription, unmarshal_Webhook, unmarshal_BulkCreateBlocklistsResponse, unmarshal_CreateEmailResponse, @@ -66,8 +75,12 @@ unmarshal_ListBlocklistsResponse, unmarshal_ListDomainsResponse, unmarshal_ListEmailsResponse, + unmarshal_ListOfferSubscriptionsResponse, + unmarshal_ListOffersResponse, + unmarshal_ListPoolsResponse, unmarshal_ListWebhookEventsResponse, unmarshal_ListWebhooksResponse, + unmarshal_ProjectConsumption, unmarshal_ProjectSettings, unmarshal_Statistics, marshal_BulkCreateBlocklistsRequest, @@ -75,6 +88,7 @@ marshal_CreateEmailRequest, marshal_CreateWebhookRequest, marshal_UpdateDomainRequest, + marshal_UpdateOfferSubscriptionRequest, marshal_UpdateProjectSettingsRequest, marshal_UpdateWebhookRequest, ) @@ -1469,3 +1483,214 @@ async def delete_blocklist( ) self._throw_on_error(res) + + async def list_offer_subscriptions( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ListOfferSubscriptionsResponse: + """ + Get information about subscribed offers. + Retrieve information about the offers you are subscribed to using the `project_id` and `region` parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :return: :class:`ListOfferSubscriptionsResponse ` + + Usage: + :: + + result = await api.list_offer_subscriptions() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/offer-subscriptions", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOfferSubscriptionsResponse(res.json()) + + async def update_offer_subscription( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + name: Optional[OfferName] = None, + ) -> OfferSubscription: + """ + Update a subscribed offer. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :param name: Name of the offer-subscription. + :return: :class:`OfferSubscription ` + + Usage: + :: + + result = await api.update_offer_subscription() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/offer-subscriptions", + body=marshal_UpdateOfferSubscriptionRequest( + UpdateOfferSubscriptionRequest( + region=region, + project_id=project_id, + name=name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_OfferSubscription(res.json()) + + async def list_offers( + self, + *, + region: Optional[ScwRegion] = None, + ) -> ListOffersResponse: + """ + List the available offers. + Retrieve the list of the available and free-of-charge offers you can subscribe to. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ListOffersResponse ` + + Usage: + :: + + result = await api.list_offers() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/offers", + ) + + self._throw_on_error(res) + return unmarshal_ListOffersResponse(res.json()) + + async def list_pools( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> ListPoolsResponse: + """ + Get information about a sending pool. + Retrieve information about a sending pool, including its creation status and configuration parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: ID of the Project. + :return: :class:`ListPoolsResponse ` + + Usage: + :: + + result = await api.list_pools() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/pools", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPoolsResponse(res.json()) + + async def list_pools_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> List[Pool]: + """ + Get information about a sending pool. + Retrieve information about a sending pool, including its creation status and configuration parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: ID of the Project. + :return: :class:`List[Pool] ` + + Usage: + :: + + result = await api.list_pools_all() + """ + + return await fetch_all_pages_async( + type=ListPoolsResponse, + key="pools", + fetcher=self.list_pools, + args={ + "region": region, + "page": page, + "page_size": page_size, + "project_id": project_id, + }, + ) + + async def get_project_consumption( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ProjectConsumption: + """ + Get project resource consumption. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project. + :return: :class:`ProjectConsumption ` + + Usage: + :: + + result = await api.get_project_consumption() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/project-consumption", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ProjectConsumption(res.json()) diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py index 453356bb7..522b5dec8 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py @@ -15,6 +15,7 @@ DomainReputation, DomainStatistics, Domain, + OfferSubscription, Webhook, Blocklist, BulkCreateBlocklistsResponse, @@ -27,9 +28,15 @@ ListBlocklistsResponse, ListDomainsResponse, ListEmailsResponse, + ListOfferSubscriptionsResponse, + Offer, + ListOffersResponse, + Pool, + ListPoolsResponse, WebhookEvent, ListWebhookEventsResponse, ListWebhooksResponse, + ProjectConsumption, ProjectSettingsPeriodicReport, ProjectSettings, Statistics, @@ -41,6 +48,7 @@ CreateEmailRequest, CreateWebhookRequest, UpdateDomainRequest, + UpdateOfferSubscriptionRequest, UpdateProjectSettingsRequestUpdatePeriodicReport, UpdateProjectSettingsRequest, UpdateWebhookRequest, @@ -358,6 +366,69 @@ def unmarshal_Domain(data: Any) -> Domain: return Domain(**args) +def unmarshal_OfferSubscription(data: Any) -> OfferSubscription: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferSubscription' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("max_domains", None) + if field is not None: + args["max_domains"] = field + + field = data.get("max_dedicated_ips", None) + if field is not None: + args["max_dedicated_ips"] = field + + field = data.get("max_webhooks_per_domain", None) + if field is not None: + args["max_webhooks_per_domain"] = field + + field = data.get("max_custom_blocklists_per_domain", None) + if field is not None: + args["max_custom_blocklists_per_domain"] = field + + field = data.get("included_monthly_emails", None) + if field is not None: + args["included_monthly_emails"] = field + + field = data.get("subscribed_at", None) + if field is not None: + args["subscribed_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["subscribed_at"] = None + + field = data.get("cancellation_available_at", None) + if field is not None: + args["cancellation_available_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["cancellation_available_at"] = None + + return OfferSubscription(**args) + + def unmarshal_Webhook(data: Any) -> Webhook: if not isinstance(data, dict): raise TypeError( @@ -718,6 +789,165 @@ def unmarshal_ListEmailsResponse(data: Any) -> ListEmailsResponse: return ListEmailsResponse(**args) +def unmarshal_ListOfferSubscriptionsResponse( + data: Any, +) -> ListOfferSubscriptionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOfferSubscriptionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offer_subscriptions", None) + if field is not None: + args["offer_subscriptions"] = ( + [unmarshal_OfferSubscription(v) for v in field] + if field is not None + else None + ) + + return ListOfferSubscriptionsResponse(**args) + + +def unmarshal_Offer(data: Any) -> Offer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Offer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("max_domains", None) + if field is not None: + args["max_domains"] = field + + field = data.get("max_dedicated_ips", None) + if field is not None: + args["max_dedicated_ips"] = field + + field = data.get("included_monthly_emails", None) + if field is not None: + args["included_monthly_emails"] = field + + field = data.get("max_webhooks_per_domain", None) + if field is not None: + args["max_webhooks_per_domain"] = field + + field = data.get("max_custom_blocklists_per_domain", None) + if field is not None: + args["max_custom_blocklists_per_domain"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("commitment_period", None) + if field is not None: + args["commitment_period"] = field + else: + args["commitment_period"] = None + + return Offer(**args) + + +def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOffersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offers", None) + if field is not None: + args["offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListOffersResponse(**args) + + +def unmarshal_Pool(data: Any) -> Pool: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pool' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = field + + field = data.get("details", None) + if field is not None: + args["details"] = field + else: + args["details"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + else: + args["reverse"] = None + + return Pool(**args) + + +def unmarshal_ListPoolsResponse(data: Any) -> ListPoolsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPoolsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("pools", None) + if field is not None: + args["pools"] = ( + [unmarshal_Pool(v) for v in field] if field is not None else None + ) + + return ListPoolsResponse(**args) + + def unmarshal_WebhookEvent(data: Any) -> WebhookEvent: if not isinstance(data, dict): raise TypeError( @@ -821,6 +1051,41 @@ def unmarshal_ListWebhooksResponse(data: Any) -> ListWebhooksResponse: return ListWebhooksResponse(**args) +def unmarshal_ProjectConsumption(data: Any) -> ProjectConsumption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectConsumption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("domains_count", None) + if field is not None: + args["domains_count"] = field + + field = data.get("dedicated_ips_count", None) + if field is not None: + args["dedicated_ips_count"] = field + + field = data.get("monthly_emails_count", None) + if field is not None: + args["monthly_emails_count"] = field + + field = data.get("webhooks_count", None) + if field is not None: + args["webhooks_count"] = field + + field = data.get("custom_blocklists_count", None) + if field is not None: + args["custom_blocklists_count"] = field + + return ProjectConsumption(**args) + + def unmarshal_ProjectSettingsPeriodicReport(data: Any) -> ProjectSettingsPeriodicReport: if not isinstance(data, dict): raise TypeError( @@ -1080,6 +1345,21 @@ def marshal_UpdateDomainRequest( return output +def marshal_UpdateOfferSubscriptionRequest( + request: UpdateOfferSubscriptionRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = str(request.name) + + return output + + def marshal_UpdateProjectSettingsRequestUpdatePeriodicReport( request: UpdateProjectSettingsRequestUpdatePeriodicReport, defaults: ProfileDefaults, diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/types.py b/scaleway-async/scaleway_async/tem/v1alpha1/types.py index dc7a8a3e3..0f40682c4 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/types.py @@ -9,6 +9,7 @@ from scaleway_core.bridge import ( Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -149,6 +150,26 @@ def __str__(self) -> str: return str(self.value) +class OfferName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + ESSENTIAL = "essential" + SCALE = "scale" + + def __str__(self) -> str: + return str(self.value) + + +class PoolStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DISABLED = "disabled" + CREATING = "creating" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + class ProjectSettingsPeriodicReportFrequency(str, Enum, metaclass=StrEnumMeta): UNKNOWN_FREQUENCY = "unknown_frequency" MONTHLY = "monthly" @@ -597,6 +618,145 @@ class Domain: """ +@dataclass +class OfferSubscription: + organization_id: str + """ + ID of the offer-subscription Organization. + """ + + project_id: str + """ + ID of the offer-subscription Project. + """ + + offer_name: OfferName + """ + Name of the offer associated with the Project. + """ + + sla: float + """ + Service Level Agreement percentage of the offer-subscription. + """ + + max_domains: int + """ + Max number of domains that can be associated with the offer-subscription for a particular Project. + """ + + max_dedicated_ips: int + """ + Max number of dedicated IPs that can be associated with the offer-subscription for a particular Project. + """ + + max_webhooks_per_domain: int + """ + Max number of webhooks that can be associated with the offer-subscription for a particular Project. + """ + + max_custom_blocklists_per_domain: int + """ + Max number of custom blocklists that can be associated with the offer-subscription for a particular Project. + """ + + included_monthly_emails: int + """ + Number of emails included in the offer-subscription per month. + """ + + subscribed_at: Optional[datetime] + """ + Date and time of the subscription. + """ + + cancellation_available_at: Optional[datetime] + """ + Date and time of the end of the offer-subscription commitment. + """ + + +@dataclass +class Offer: + name: OfferName + """ + Name of the offer. + """ + + sla: float + """ + Service Level Agreement percentage of the offer. + """ + + max_domains: int + """ + Max number of checked domains that can be associated with the offer. + """ + + max_dedicated_ips: int + """ + Max number of dedicated IPs that can be associated with the offer. + """ + + included_monthly_emails: int + """ + Number of emails included in the offer per month. + """ + + max_webhooks_per_domain: int + """ + Max number of webhooks that can be associated with the offer. + """ + + max_custom_blocklists_per_domain: int + """ + Max number of active custom blocklists that can be associated with the offer. + """ + + created_at: Optional[datetime] + """ + Date and time of the offer creation. + """ + + commitment_period: Optional[str] + """ + Period of commitment. + """ + + +@dataclass +class Pool: + project_id: str + """ + ID of the Project. + """ + + status: PoolStatus + """ + Status of the pool. + """ + + ips: List[str] + """ + IPs of the pool. + """ + + details: Optional[str] + """ + Details of the pool. + """ + + zone: Optional[ScwZone] + """ + Zone of the pool. + """ + + reverse: Optional[str] + """ + Reverse hostname of all IPs of the pool. + """ + + @dataclass class WebhookEvent: id: str @@ -1041,6 +1201,19 @@ class GetEmailRequest: """ +@dataclass +class GetProjectConsumptionRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project. + """ + + @dataclass class GetProjectSettingsRequest: region: Optional[ScwRegion] @@ -1297,6 +1470,89 @@ class ListEmailsResponse: """ +@dataclass +class ListOfferSubscriptionsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class ListOfferSubscriptionsResponse: + total_count: int + """ + Number of offer-subscriptions matching the requested criteria. + """ + + offer_subscriptions: List[OfferSubscription] + """ + Single page of offer-subscriptions matching the requested criteria. + """ + + +@dataclass +class ListOffersRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListOffersResponse: + total_count: int + """ + Number of offers matching the requested criteria. + """ + + offers: List[Offer] + """ + Single page of offers matching the requested criteria. + """ + + +@dataclass +class ListPoolsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + Requested page size. Value must be between 1 and 1000. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class ListPoolsResponse: + total_count: int + """ + Number of pools matching the requested criteria. + """ + + pools: List[Pool] + """ + Single page of pools matching the requested criteria. + """ + + @dataclass class ListWebhookEventsRequest: webhook_id: str @@ -1419,6 +1675,39 @@ class ListWebhooksResponse: """ +@dataclass +class ProjectConsumption: + project_id: str + """ + ID of the project. + """ + + domains_count: int + """ + Number of domains in the project. + """ + + dedicated_ips_count: int + """ + Number of dedicated IP in the project. + """ + + monthly_emails_count: int + """ + Number of emails sent during the current month in the project. + """ + + webhooks_count: int + """ + Number of webhooks in the project. + """ + + custom_blocklists_count: int + """ + Number of custom blocklists in the project. + """ + + @dataclass class ProjectSettings: periodic_report: Optional[ProjectSettingsPeriodicReport] @@ -1491,6 +1780,24 @@ class UpdateDomainRequest: """ +@dataclass +class UpdateOfferSubscriptionRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + name: Optional[OfferName] + """ + Name of the offer-subscription. + """ + + @dataclass class UpdateProjectSettingsRequest: region: Optional[ScwRegion] diff --git a/scaleway/scaleway/tem/v1alpha1/__init__.py b/scaleway/scaleway/tem/v1alpha1/__init__.py index 805d56c4a..53ba0d7cd 100644 --- a/scaleway/scaleway/tem/v1alpha1/__init__.py +++ b/scaleway/scaleway/tem/v1alpha1/__init__.py @@ -14,6 +14,8 @@ from .types import ListEmailsRequestOrderBy from .types import ListWebhookEventsRequestOrderBy from .types import ListWebhooksRequestOrderBy +from .types import OfferName +from .types import PoolStatus from .types import ProjectSettingsPeriodicReportFrequency from .types import WebhookEventStatus from .types import WebhookEventType @@ -32,6 +34,9 @@ from .types import DomainLastStatusDmarcRecord from .types import DomainLastStatusSpfRecord from .types import Domain +from .types import OfferSubscription +from .types import Offer +from .types import Pool from .types import WebhookEvent from .types import Webhook from .types import ProjectSettingsPeriodicReport @@ -50,6 +55,7 @@ from .types import GetDomainLastStatusRequest from .types import GetDomainRequest from .types import GetEmailRequest +from .types import GetProjectConsumptionRequest from .types import GetProjectSettingsRequest from .types import GetStatisticsRequest from .types import GetWebhookRequest @@ -59,14 +65,22 @@ from .types import ListDomainsResponse from .types import ListEmailsRequest from .types import ListEmailsResponse +from .types import ListOfferSubscriptionsRequest +from .types import ListOfferSubscriptionsResponse +from .types import ListOffersRequest +from .types import ListOffersResponse +from .types import ListPoolsRequest +from .types import ListPoolsResponse from .types import ListWebhookEventsRequest from .types import ListWebhookEventsResponse from .types import ListWebhooksRequest from .types import ListWebhooksResponse +from .types import ProjectConsumption from .types import ProjectSettings from .types import RevokeDomainRequest from .types import Statistics from .types import UpdateDomainRequest +from .types import UpdateOfferSubscriptionRequest from .types import UpdateProjectSettingsRequest from .types import UpdateWebhookRequest from .api import TemV1Alpha1API @@ -86,6 +100,8 @@ "ListEmailsRequestOrderBy", "ListWebhookEventsRequestOrderBy", "ListWebhooksRequestOrderBy", + "OfferName", + "PoolStatus", "ProjectSettingsPeriodicReportFrequency", "WebhookEventStatus", "WebhookEventType", @@ -104,6 +120,9 @@ "DomainLastStatusDmarcRecord", "DomainLastStatusSpfRecord", "Domain", + "OfferSubscription", + "Offer", + "Pool", "WebhookEvent", "Webhook", "ProjectSettingsPeriodicReport", @@ -122,6 +141,7 @@ "GetDomainLastStatusRequest", "GetDomainRequest", "GetEmailRequest", + "GetProjectConsumptionRequest", "GetProjectSettingsRequest", "GetStatisticsRequest", "GetWebhookRequest", @@ -131,14 +151,22 @@ "ListDomainsResponse", "ListEmailsRequest", "ListEmailsResponse", + "ListOfferSubscriptionsRequest", + "ListOfferSubscriptionsResponse", + "ListOffersRequest", + "ListOffersResponse", + "ListPoolsRequest", + "ListPoolsResponse", "ListWebhookEventsRequest", "ListWebhookEventsResponse", "ListWebhooksRequest", "ListWebhooksResponse", + "ProjectConsumption", "ProjectSettings", "RevokeDomainRequest", "Statistics", "UpdateDomainRequest", + "UpdateOfferSubscriptionRequest", "UpdateProjectSettingsRequest", "UpdateWebhookRequest", "TemV1Alpha1API", diff --git a/scaleway/scaleway/tem/v1alpha1/api.py b/scaleway/scaleway/tem/v1alpha1/api.py index b3aefea5c..3c6e7d778 100644 --- a/scaleway/scaleway/tem/v1alpha1/api.py +++ b/scaleway/scaleway/tem/v1alpha1/api.py @@ -23,6 +23,7 @@ ListEmailsRequestOrderBy, ListWebhookEventsRequestOrderBy, ListWebhooksRequestOrderBy, + OfferName, WebhookEventStatus, WebhookEventType, Blocklist, @@ -41,11 +42,18 @@ ListBlocklistsResponse, ListDomainsResponse, ListEmailsResponse, + ListOfferSubscriptionsResponse, + ListOffersResponse, + ListPoolsResponse, ListWebhookEventsResponse, ListWebhooksResponse, + OfferSubscription, + Pool, + ProjectConsumption, ProjectSettings, Statistics, UpdateDomainRequest, + UpdateOfferSubscriptionRequest, UpdateProjectSettingsRequest, UpdateProjectSettingsRequestUpdatePeriodicReport, UpdateWebhookRequest, @@ -59,6 +67,7 @@ from .marshalling import ( unmarshal_Email, unmarshal_Domain, + unmarshal_OfferSubscription, unmarshal_Webhook, unmarshal_BulkCreateBlocklistsResponse, unmarshal_CreateEmailResponse, @@ -66,8 +75,12 @@ unmarshal_ListBlocklistsResponse, unmarshal_ListDomainsResponse, unmarshal_ListEmailsResponse, + unmarshal_ListOfferSubscriptionsResponse, + unmarshal_ListOffersResponse, + unmarshal_ListPoolsResponse, unmarshal_ListWebhookEventsResponse, unmarshal_ListWebhooksResponse, + unmarshal_ProjectConsumption, unmarshal_ProjectSettings, unmarshal_Statistics, marshal_BulkCreateBlocklistsRequest, @@ -75,6 +88,7 @@ marshal_CreateEmailRequest, marshal_CreateWebhookRequest, marshal_UpdateDomainRequest, + marshal_UpdateOfferSubscriptionRequest, marshal_UpdateProjectSettingsRequest, marshal_UpdateWebhookRequest, ) @@ -1469,3 +1483,214 @@ def delete_blocklist( ) self._throw_on_error(res) + + def list_offer_subscriptions( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ListOfferSubscriptionsResponse: + """ + Get information about subscribed offers. + Retrieve information about the offers you are subscribed to using the `project_id` and `region` parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :return: :class:`ListOfferSubscriptionsResponse ` + + Usage: + :: + + result = api.list_offer_subscriptions() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/offer-subscriptions", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOfferSubscriptionsResponse(res.json()) + + def update_offer_subscription( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + name: Optional[OfferName] = None, + ) -> OfferSubscription: + """ + Update a subscribed offer. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :param name: Name of the offer-subscription. + :return: :class:`OfferSubscription ` + + Usage: + :: + + result = api.update_offer_subscription() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/offer-subscriptions", + body=marshal_UpdateOfferSubscriptionRequest( + UpdateOfferSubscriptionRequest( + region=region, + project_id=project_id, + name=name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_OfferSubscription(res.json()) + + def list_offers( + self, + *, + region: Optional[ScwRegion] = None, + ) -> ListOffersResponse: + """ + List the available offers. + Retrieve the list of the available and free-of-charge offers you can subscribe to. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ListOffersResponse ` + + Usage: + :: + + result = api.list_offers() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/offers", + ) + + self._throw_on_error(res) + return unmarshal_ListOffersResponse(res.json()) + + def list_pools( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> ListPoolsResponse: + """ + Get information about a sending pool. + Retrieve information about a sending pool, including its creation status and configuration parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: ID of the Project. + :return: :class:`ListPoolsResponse ` + + Usage: + :: + + result = api.list_pools() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/pools", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPoolsResponse(res.json()) + + def list_pools_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> List[Pool]: + """ + Get information about a sending pool. + Retrieve information about a sending pool, including its creation status and configuration parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: ID of the Project. + :return: :class:`List[Pool] ` + + Usage: + :: + + result = api.list_pools_all() + """ + + return fetch_all_pages( + type=ListPoolsResponse, + key="pools", + fetcher=self.list_pools, + args={ + "region": region, + "page": page, + "page_size": page_size, + "project_id": project_id, + }, + ) + + def get_project_consumption( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ProjectConsumption: + """ + Get project resource consumption. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project. + :return: :class:`ProjectConsumption ` + + Usage: + :: + + result = api.get_project_consumption() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/project-consumption", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ProjectConsumption(res.json()) diff --git a/scaleway/scaleway/tem/v1alpha1/marshalling.py b/scaleway/scaleway/tem/v1alpha1/marshalling.py index 453356bb7..522b5dec8 100644 --- a/scaleway/scaleway/tem/v1alpha1/marshalling.py +++ b/scaleway/scaleway/tem/v1alpha1/marshalling.py @@ -15,6 +15,7 @@ DomainReputation, DomainStatistics, Domain, + OfferSubscription, Webhook, Blocklist, BulkCreateBlocklistsResponse, @@ -27,9 +28,15 @@ ListBlocklistsResponse, ListDomainsResponse, ListEmailsResponse, + ListOfferSubscriptionsResponse, + Offer, + ListOffersResponse, + Pool, + ListPoolsResponse, WebhookEvent, ListWebhookEventsResponse, ListWebhooksResponse, + ProjectConsumption, ProjectSettingsPeriodicReport, ProjectSettings, Statistics, @@ -41,6 +48,7 @@ CreateEmailRequest, CreateWebhookRequest, UpdateDomainRequest, + UpdateOfferSubscriptionRequest, UpdateProjectSettingsRequestUpdatePeriodicReport, UpdateProjectSettingsRequest, UpdateWebhookRequest, @@ -358,6 +366,69 @@ def unmarshal_Domain(data: Any) -> Domain: return Domain(**args) +def unmarshal_OfferSubscription(data: Any) -> OfferSubscription: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferSubscription' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("max_domains", None) + if field is not None: + args["max_domains"] = field + + field = data.get("max_dedicated_ips", None) + if field is not None: + args["max_dedicated_ips"] = field + + field = data.get("max_webhooks_per_domain", None) + if field is not None: + args["max_webhooks_per_domain"] = field + + field = data.get("max_custom_blocklists_per_domain", None) + if field is not None: + args["max_custom_blocklists_per_domain"] = field + + field = data.get("included_monthly_emails", None) + if field is not None: + args["included_monthly_emails"] = field + + field = data.get("subscribed_at", None) + if field is not None: + args["subscribed_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["subscribed_at"] = None + + field = data.get("cancellation_available_at", None) + if field is not None: + args["cancellation_available_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["cancellation_available_at"] = None + + return OfferSubscription(**args) + + def unmarshal_Webhook(data: Any) -> Webhook: if not isinstance(data, dict): raise TypeError( @@ -718,6 +789,165 @@ def unmarshal_ListEmailsResponse(data: Any) -> ListEmailsResponse: return ListEmailsResponse(**args) +def unmarshal_ListOfferSubscriptionsResponse( + data: Any, +) -> ListOfferSubscriptionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOfferSubscriptionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offer_subscriptions", None) + if field is not None: + args["offer_subscriptions"] = ( + [unmarshal_OfferSubscription(v) for v in field] + if field is not None + else None + ) + + return ListOfferSubscriptionsResponse(**args) + + +def unmarshal_Offer(data: Any) -> Offer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Offer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("max_domains", None) + if field is not None: + args["max_domains"] = field + + field = data.get("max_dedicated_ips", None) + if field is not None: + args["max_dedicated_ips"] = field + + field = data.get("included_monthly_emails", None) + if field is not None: + args["included_monthly_emails"] = field + + field = data.get("max_webhooks_per_domain", None) + if field is not None: + args["max_webhooks_per_domain"] = field + + field = data.get("max_custom_blocklists_per_domain", None) + if field is not None: + args["max_custom_blocklists_per_domain"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("commitment_period", None) + if field is not None: + args["commitment_period"] = field + else: + args["commitment_period"] = None + + return Offer(**args) + + +def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOffersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offers", None) + if field is not None: + args["offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListOffersResponse(**args) + + +def unmarshal_Pool(data: Any) -> Pool: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pool' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = field + + field = data.get("details", None) + if field is not None: + args["details"] = field + else: + args["details"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + else: + args["reverse"] = None + + return Pool(**args) + + +def unmarshal_ListPoolsResponse(data: Any) -> ListPoolsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPoolsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("pools", None) + if field is not None: + args["pools"] = ( + [unmarshal_Pool(v) for v in field] if field is not None else None + ) + + return ListPoolsResponse(**args) + + def unmarshal_WebhookEvent(data: Any) -> WebhookEvent: if not isinstance(data, dict): raise TypeError( @@ -821,6 +1051,41 @@ def unmarshal_ListWebhooksResponse(data: Any) -> ListWebhooksResponse: return ListWebhooksResponse(**args) +def unmarshal_ProjectConsumption(data: Any) -> ProjectConsumption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectConsumption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("domains_count", None) + if field is not None: + args["domains_count"] = field + + field = data.get("dedicated_ips_count", None) + if field is not None: + args["dedicated_ips_count"] = field + + field = data.get("monthly_emails_count", None) + if field is not None: + args["monthly_emails_count"] = field + + field = data.get("webhooks_count", None) + if field is not None: + args["webhooks_count"] = field + + field = data.get("custom_blocklists_count", None) + if field is not None: + args["custom_blocklists_count"] = field + + return ProjectConsumption(**args) + + def unmarshal_ProjectSettingsPeriodicReport(data: Any) -> ProjectSettingsPeriodicReport: if not isinstance(data, dict): raise TypeError( @@ -1080,6 +1345,21 @@ def marshal_UpdateDomainRequest( return output +def marshal_UpdateOfferSubscriptionRequest( + request: UpdateOfferSubscriptionRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = str(request.name) + + return output + + def marshal_UpdateProjectSettingsRequestUpdatePeriodicReport( request: UpdateProjectSettingsRequestUpdatePeriodicReport, defaults: ProfileDefaults, diff --git a/scaleway/scaleway/tem/v1alpha1/types.py b/scaleway/scaleway/tem/v1alpha1/types.py index dc7a8a3e3..0f40682c4 100644 --- a/scaleway/scaleway/tem/v1alpha1/types.py +++ b/scaleway/scaleway/tem/v1alpha1/types.py @@ -9,6 +9,7 @@ from scaleway_core.bridge import ( Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -149,6 +150,26 @@ def __str__(self) -> str: return str(self.value) +class OfferName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + ESSENTIAL = "essential" + SCALE = "scale" + + def __str__(self) -> str: + return str(self.value) + + +class PoolStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DISABLED = "disabled" + CREATING = "creating" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + class ProjectSettingsPeriodicReportFrequency(str, Enum, metaclass=StrEnumMeta): UNKNOWN_FREQUENCY = "unknown_frequency" MONTHLY = "monthly" @@ -597,6 +618,145 @@ class Domain: """ +@dataclass +class OfferSubscription: + organization_id: str + """ + ID of the offer-subscription Organization. + """ + + project_id: str + """ + ID of the offer-subscription Project. + """ + + offer_name: OfferName + """ + Name of the offer associated with the Project. + """ + + sla: float + """ + Service Level Agreement percentage of the offer-subscription. + """ + + max_domains: int + """ + Max number of domains that can be associated with the offer-subscription for a particular Project. + """ + + max_dedicated_ips: int + """ + Max number of dedicated IPs that can be associated with the offer-subscription for a particular Project. + """ + + max_webhooks_per_domain: int + """ + Max number of webhooks that can be associated with the offer-subscription for a particular Project. + """ + + max_custom_blocklists_per_domain: int + """ + Max number of custom blocklists that can be associated with the offer-subscription for a particular Project. + """ + + included_monthly_emails: int + """ + Number of emails included in the offer-subscription per month. + """ + + subscribed_at: Optional[datetime] + """ + Date and time of the subscription. + """ + + cancellation_available_at: Optional[datetime] + """ + Date and time of the end of the offer-subscription commitment. + """ + + +@dataclass +class Offer: + name: OfferName + """ + Name of the offer. + """ + + sla: float + """ + Service Level Agreement percentage of the offer. + """ + + max_domains: int + """ + Max number of checked domains that can be associated with the offer. + """ + + max_dedicated_ips: int + """ + Max number of dedicated IPs that can be associated with the offer. + """ + + included_monthly_emails: int + """ + Number of emails included in the offer per month. + """ + + max_webhooks_per_domain: int + """ + Max number of webhooks that can be associated with the offer. + """ + + max_custom_blocklists_per_domain: int + """ + Max number of active custom blocklists that can be associated with the offer. + """ + + created_at: Optional[datetime] + """ + Date and time of the offer creation. + """ + + commitment_period: Optional[str] + """ + Period of commitment. + """ + + +@dataclass +class Pool: + project_id: str + """ + ID of the Project. + """ + + status: PoolStatus + """ + Status of the pool. + """ + + ips: List[str] + """ + IPs of the pool. + """ + + details: Optional[str] + """ + Details of the pool. + """ + + zone: Optional[ScwZone] + """ + Zone of the pool. + """ + + reverse: Optional[str] + """ + Reverse hostname of all IPs of the pool. + """ + + @dataclass class WebhookEvent: id: str @@ -1041,6 +1201,19 @@ class GetEmailRequest: """ +@dataclass +class GetProjectConsumptionRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project. + """ + + @dataclass class GetProjectSettingsRequest: region: Optional[ScwRegion] @@ -1297,6 +1470,89 @@ class ListEmailsResponse: """ +@dataclass +class ListOfferSubscriptionsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class ListOfferSubscriptionsResponse: + total_count: int + """ + Number of offer-subscriptions matching the requested criteria. + """ + + offer_subscriptions: List[OfferSubscription] + """ + Single page of offer-subscriptions matching the requested criteria. + """ + + +@dataclass +class ListOffersRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListOffersResponse: + total_count: int + """ + Number of offers matching the requested criteria. + """ + + offers: List[Offer] + """ + Single page of offers matching the requested criteria. + """ + + +@dataclass +class ListPoolsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + Requested page size. Value must be between 1 and 1000. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class ListPoolsResponse: + total_count: int + """ + Number of pools matching the requested criteria. + """ + + pools: List[Pool] + """ + Single page of pools matching the requested criteria. + """ + + @dataclass class ListWebhookEventsRequest: webhook_id: str @@ -1419,6 +1675,39 @@ class ListWebhooksResponse: """ +@dataclass +class ProjectConsumption: + project_id: str + """ + ID of the project. + """ + + domains_count: int + """ + Number of domains in the project. + """ + + dedicated_ips_count: int + """ + Number of dedicated IP in the project. + """ + + monthly_emails_count: int + """ + Number of emails sent during the current month in the project. + """ + + webhooks_count: int + """ + Number of webhooks in the project. + """ + + custom_blocklists_count: int + """ + Number of custom blocklists in the project. + """ + + @dataclass class ProjectSettings: periodic_report: Optional[ProjectSettingsPeriodicReport] @@ -1491,6 +1780,24 @@ class UpdateDomainRequest: """ +@dataclass +class UpdateOfferSubscriptionRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + name: Optional[OfferName] + """ + Name of the offer-subscription. + """ + + @dataclass class UpdateProjectSettingsRequest: region: Optional[ScwRegion] From e1246c1cc8528821c7a3c718262ee502977f6e77 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 17 Mar 2025 09:13:16 +0100 Subject: [PATCH 67/73] feat(tem): make scale offer endpoint public (#909) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> From 98688fc460f9803a51839761b76c45a7beb48e00 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Mon, 17 Mar 2025 09:14:23 +0100 Subject: [PATCH 68/73] feat(account): add project customization endpoint (#911) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> --- .../scaleway_async/account/v3/__init__.py | 30 ++ .../scaleway_async/account/v3/api.py | 43 +++ .../scaleway_async/account/v3/marshalling.py | 345 ++++++++++++++++++ .../scaleway_async/account/v3/types.py | 132 +++++++ scaleway/scaleway/account/v3/__init__.py | 30 ++ scaleway/scaleway/account/v3/api.py | 43 +++ scaleway/scaleway/account/v3/marshalling.py | 345 ++++++++++++++++++ scaleway/scaleway/account/v3/types.py | 132 +++++++ 8 files changed, 1100 insertions(+) diff --git a/scaleway-async/scaleway_async/account/v3/__init__.py b/scaleway-async/scaleway_async/account/v3/__init__.py index 1d357a35a..f1f5a5ccc 100644 --- a/scaleway-async/scaleway_async/account/v3/__init__.py +++ b/scaleway-async/scaleway_async/account/v3/__init__.py @@ -3,9 +3,22 @@ from .types import ContractType from .types import ListContractSignaturesRequestOrderBy from .types import ListProjectsRequestOrderBy +from .types import QualificationArchitectureType +from .types import QualificationHostApplicationSubUseCase +from .types import QualificationHostWebsiteSubUseCase from .types import Contract +from .types import QualificationAiMachine +from .types import QualificationArchiveData +from .types import QualificationContainer +from .types import QualificationDeploySoftware +from .types import QualificationHostApplication +from .types import QualificationHostWebsite +from .types import QualificationOtherUseCase +from .types import QualificationSetScalewayEnvironment +from .types import QualificationShareData from .types import ContractSignature from .types import Project +from .types import Qualification from .types import CheckContractSignatureResponse from .types import ContractApiCheckContractSignatureRequest from .types import ContractApiCreateContractSignatureRequest @@ -18,7 +31,9 @@ from .types import ProjectApiDeleteProjectRequest from .types import ProjectApiGetProjectRequest from .types import ProjectApiListProjectsRequest +from .types import ProjectApiSetProjectQualificationRequest from .types import ProjectApiUpdateProjectRequest +from .types import ProjectQualification from .api import AccountV3ContractAPI from .api import AccountV3ProjectAPI @@ -26,9 +41,22 @@ "ContractType", "ListContractSignaturesRequestOrderBy", "ListProjectsRequestOrderBy", + "QualificationArchitectureType", + "QualificationHostApplicationSubUseCase", + "QualificationHostWebsiteSubUseCase", "Contract", + "QualificationAiMachine", + "QualificationArchiveData", + "QualificationContainer", + "QualificationDeploySoftware", + "QualificationHostApplication", + "QualificationHostWebsite", + "QualificationOtherUseCase", + "QualificationSetScalewayEnvironment", + "QualificationShareData", "ContractSignature", "Project", + "Qualification", "CheckContractSignatureResponse", "ContractApiCheckContractSignatureRequest", "ContractApiCreateContractSignatureRequest", @@ -41,7 +69,9 @@ "ProjectApiDeleteProjectRequest", "ProjectApiGetProjectRequest", "ProjectApiListProjectsRequest", + "ProjectApiSetProjectQualificationRequest", "ProjectApiUpdateProjectRequest", + "ProjectQualification", "AccountV3ContractAPI", "AccountV3ProjectAPI", ] diff --git a/scaleway-async/scaleway_async/account/v3/api.py b/scaleway-async/scaleway_async/account/v3/api.py index 05626874f..98d728b3a 100644 --- a/scaleway-async/scaleway_async/account/v3/api.py +++ b/scaleway-async/scaleway_async/account/v3/api.py @@ -25,7 +25,10 @@ ListProjectsResponse, Project, ProjectApiCreateProjectRequest, + ProjectApiSetProjectQualificationRequest, ProjectApiUpdateProjectRequest, + ProjectQualification, + Qualification, ) from .marshalling import ( unmarshal_ContractSignature, @@ -33,9 +36,11 @@ unmarshal_CheckContractSignatureResponse, unmarshal_ListContractSignaturesResponse, unmarshal_ListProjectsResponse, + unmarshal_ProjectQualification, marshal_ContractApiCheckContractSignatureRequest, marshal_ContractApiCreateContractSignatureRequest, marshal_ProjectApiCreateProjectRequest, + marshal_ProjectApiSetProjectQualificationRequest, marshal_ProjectApiUpdateProjectRequest, ) from ...std.types import ( @@ -491,3 +496,41 @@ async def update_project( self._throw_on_error(res) return unmarshal_Project(res.json()) + + async def set_project_qualification( + self, + *, + project_id: Optional[str] = None, + qualification: Optional[Qualification] = None, + ) -> ProjectQualification: + """ + Set project use case. + Set the project use case for a new or existing Project, specified by its Project ID. You can customize the use case, sub use case, and architecture type you want to use in the Project. + :param project_id: Project ID. + :param qualification: Use case chosen for the Project. + :return: :class:`ProjectQualification ` + + Usage: + :: + + result = await api.set_project_qualification() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "POST", + f"/account/v3/projects/{param_project_id}/project-qualification", + body=marshal_ProjectApiSetProjectQualificationRequest( + ProjectApiSetProjectQualificationRequest( + project_id=project_id, + qualification=qualification, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ProjectQualification(res.json()) diff --git a/scaleway-async/scaleway_async/account/v3/marshalling.py b/scaleway-async/scaleway_async/account/v3/marshalling.py index f6e3445a6..755e37779 100644 --- a/scaleway-async/scaleway_async/account/v3/marshalling.py +++ b/scaleway-async/scaleway_async/account/v3/marshalling.py @@ -5,6 +5,10 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) from .types import ( Contract, ContractSignature, @@ -12,9 +16,21 @@ CheckContractSignatureResponse, ListContractSignaturesResponse, ListProjectsResponse, + QualificationAiMachine, + QualificationArchiveData, + QualificationContainer, + QualificationDeploySoftware, + QualificationHostApplication, + QualificationHostWebsite, + QualificationOtherUseCase, + QualificationSetScalewayEnvironment, + QualificationShareData, + Qualification, + ProjectQualification, ContractApiCheckContractSignatureRequest, ContractApiCreateContractSignatureRequest, ProjectApiCreateProjectRequest, + ProjectApiSetProjectQualificationRequest, ProjectApiUpdateProjectRequest, ) @@ -207,6 +223,207 @@ def unmarshal_ListProjectsResponse(data: Any) -> ListProjectsResponse: return ListProjectsResponse(**args) +def unmarshal_QualificationAiMachine(data: Any) -> QualificationAiMachine: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationAiMachine' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationAiMachine(**args) + + +def unmarshal_QualificationArchiveData(data: Any) -> QualificationArchiveData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationArchiveData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationArchiveData(**args) + + +def unmarshal_QualificationContainer(data: Any) -> QualificationContainer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationContainer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationContainer(**args) + + +def unmarshal_QualificationDeploySoftware(data: Any) -> QualificationDeploySoftware: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationDeploySoftware' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationDeploySoftware(**args) + + +def unmarshal_QualificationHostApplication(data: Any) -> QualificationHostApplication: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationHostApplication' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationHostApplication(**args) + + +def unmarshal_QualificationHostWebsite(data: Any) -> QualificationHostWebsite: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationHostWebsite' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationHostWebsite(**args) + + +def unmarshal_QualificationOtherUseCase(data: Any) -> QualificationOtherUseCase: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationOtherUseCase' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationOtherUseCase(**args) + + +def unmarshal_QualificationSetScalewayEnvironment( + data: Any, +) -> QualificationSetScalewayEnvironment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationSetScalewayEnvironment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationSetScalewayEnvironment(**args) + + +def unmarshal_QualificationShareData(data: Any) -> QualificationShareData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationShareData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationShareData(**args) + + +def unmarshal_Qualification(data: Any) -> Qualification: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Qualification' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("architecture_type", None) + if field is not None: + args["architecture_type"] = field + + field = data.get("host_website", None) + if field is not None: + args["host_website"] = unmarshal_QualificationHostWebsite(field) + else: + args["host_website"] = None + + field = data.get("host_application", None) + if field is not None: + args["host_application"] = unmarshal_QualificationHostApplication(field) + else: + args["host_application"] = None + + field = data.get("deploy_software", None) + if field is not None: + args["deploy_software"] = unmarshal_QualificationDeploySoftware(field) + else: + args["deploy_software"] = None + + field = data.get("set_scaleway_environment", None) + if field is not None: + args["set_scaleway_environment"] = ( + unmarshal_QualificationSetScalewayEnvironment(field) + ) + else: + args["set_scaleway_environment"] = None + + field = data.get("ai_machine", None) + if field is not None: + args["ai_machine"] = unmarshal_QualificationAiMachine(field) + else: + args["ai_machine"] = None + + field = data.get("container", None) + if field is not None: + args["container"] = unmarshal_QualificationContainer(field) + else: + args["container"] = None + + field = data.get("archive_data", None) + if field is not None: + args["archive_data"] = unmarshal_QualificationArchiveData(field) + else: + args["archive_data"] = None + + field = data.get("share_data", None) + if field is not None: + args["share_data"] = unmarshal_QualificationShareData(field) + else: + args["share_data"] = None + + field = data.get("other_use_case", None) + if field is not None: + args["other_use_case"] = unmarshal_QualificationOtherUseCase(field) + else: + args["other_use_case"] = None + + return Qualification(**args) + + +def unmarshal_ProjectQualification(data: Any) -> ProjectQualification: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectQualification' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("qualification", None) + if field is not None: + args["qualification"] = unmarshal_Qualification(field) + else: + args["qualification"] = None + + return ProjectQualification(**args) + + def marshal_ContractApiCheckContractSignatureRequest( request: ContractApiCheckContractSignatureRequest, defaults: ProfileDefaults, @@ -270,6 +487,134 @@ def marshal_ProjectApiCreateProjectRequest( return output +def marshal_QualificationAiMachine( + request: QualificationAiMachine, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationArchiveData( + request: QualificationArchiveData, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationContainer( + request: QualificationContainer, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationDeploySoftware( + request: QualificationDeploySoftware, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationHostApplication( + request: QualificationHostApplication, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationHostWebsite( + request: QualificationHostWebsite, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationOtherUseCase( + request: QualificationOtherUseCase, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationSetScalewayEnvironment( + request: QualificationSetScalewayEnvironment, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationShareData( + request: QualificationShareData, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_Qualification( + request: Qualification, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("host_website", request.host_website), + OneOfPossibility("host_application", request.host_application), + OneOfPossibility("deploy_software", request.deploy_software), + OneOfPossibility( + "set_scaleway_environment", request.set_scaleway_environment + ), + OneOfPossibility("ai_machine", request.ai_machine), + OneOfPossibility("container", request.container), + OneOfPossibility("archive_data", request.archive_data), + OneOfPossibility("share_data", request.share_data), + OneOfPossibility("other_use_case", request.other_use_case), + ] + ), + ) + + if request.architecture_type is not None: + output["architecture_type"] = str(request.architecture_type) + + return output + + +def marshal_ProjectApiSetProjectQualificationRequest( + request: ProjectApiSetProjectQualificationRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.qualification is not None: + output["qualification"] = marshal_Qualification(request.qualification, defaults) + + return output + + def marshal_ProjectApiUpdateProjectRequest( request: ProjectApiUpdateProjectRequest, defaults: ProfileDefaults, diff --git a/scaleway-async/scaleway_async/account/v3/types.py b/scaleway-async/scaleway_async/account/v3/types.py index 9973bf316..f89f0b828 100644 --- a/scaleway-async/scaleway_async/account/v3/types.py +++ b/scaleway-async/scaleway_async/account/v3/types.py @@ -50,6 +50,41 @@ def __str__(self) -> str: return str(self.value) +class QualificationArchitectureType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ARCHITECTURE_TYPE = "unknown_architecture_type" + OBJECT_STORAGE = "object_storage" + WEB_HOSTING = "web_hosting" + INSTANCE = "instance" + ELASTIC = "elastic" + KUBERNETES = "kubernetes" + SERVERLESS = "serverless" + DEDICATED_SERVER = "dedicated_server" + OTHER_ARCHITECTURE_TYPE = "other_architecture_type" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationHostApplicationSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + SAAS_APP = "saas_app" + GOVERNMENT_APP = "government_app" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationHostWebsiteSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + INFORMATION_WEBSITE = "information_website" + ECOMMERCE_WEBSITE = "ecommerce_website" + HIGH_WEBSITE = "high_website" + OTHER_SUB_USE_CASE = "other_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + @dataclass class Contract: id: str @@ -83,6 +118,51 @@ class Contract: """ +@dataclass +class QualificationAiMachine: + pass + + +@dataclass +class QualificationArchiveData: + pass + + +@dataclass +class QualificationContainer: + pass + + +@dataclass +class QualificationDeploySoftware: + pass + + +@dataclass +class QualificationHostApplication: + sub_use_case: QualificationHostApplicationSubUseCase + + +@dataclass +class QualificationHostWebsite: + sub_use_case: QualificationHostWebsiteSubUseCase + + +@dataclass +class QualificationOtherUseCase: + pass + + +@dataclass +class QualificationSetScalewayEnvironment: + pass + + +@dataclass +class QualificationShareData: + pass + + @dataclass class ContractSignature: id: str @@ -149,6 +229,32 @@ class Project: """ +@dataclass +class Qualification: + architecture_type: QualificationArchitectureType + """ + Architecture type of the qualification. + """ + + host_website: Optional[QualificationHostWebsite] + + host_application: Optional[QualificationHostApplication] + + deploy_software: Optional[QualificationDeploySoftware] + + set_scaleway_environment: Optional[QualificationSetScalewayEnvironment] + + ai_machine: Optional[QualificationAiMachine] + + container: Optional[QualificationContainer] + + archive_data: Optional[QualificationArchiveData] + + share_data: Optional[QualificationShareData] + + other_use_case: Optional[QualificationOtherUseCase] + + @dataclass class CheckContractSignatureResponse: created: bool @@ -340,6 +446,19 @@ class ProjectApiListProjectsRequest: """ +@dataclass +class ProjectApiSetProjectQualificationRequest: + project_id: Optional[str] + """ + Project ID. + """ + + qualification: Optional[Qualification] + """ + Use case chosen for the Project. + """ + + @dataclass class ProjectApiUpdateProjectRequest: project_id: Optional[str] @@ -356,3 +475,16 @@ class ProjectApiUpdateProjectRequest: """ Description of the Project. """ + + +@dataclass +class ProjectQualification: + project_id: str + """ + Project ID. + """ + + qualification: Optional[Qualification] + """ + Qualification of the Project. + """ diff --git a/scaleway/scaleway/account/v3/__init__.py b/scaleway/scaleway/account/v3/__init__.py index 1d357a35a..f1f5a5ccc 100644 --- a/scaleway/scaleway/account/v3/__init__.py +++ b/scaleway/scaleway/account/v3/__init__.py @@ -3,9 +3,22 @@ from .types import ContractType from .types import ListContractSignaturesRequestOrderBy from .types import ListProjectsRequestOrderBy +from .types import QualificationArchitectureType +from .types import QualificationHostApplicationSubUseCase +from .types import QualificationHostWebsiteSubUseCase from .types import Contract +from .types import QualificationAiMachine +from .types import QualificationArchiveData +from .types import QualificationContainer +from .types import QualificationDeploySoftware +from .types import QualificationHostApplication +from .types import QualificationHostWebsite +from .types import QualificationOtherUseCase +from .types import QualificationSetScalewayEnvironment +from .types import QualificationShareData from .types import ContractSignature from .types import Project +from .types import Qualification from .types import CheckContractSignatureResponse from .types import ContractApiCheckContractSignatureRequest from .types import ContractApiCreateContractSignatureRequest @@ -18,7 +31,9 @@ from .types import ProjectApiDeleteProjectRequest from .types import ProjectApiGetProjectRequest from .types import ProjectApiListProjectsRequest +from .types import ProjectApiSetProjectQualificationRequest from .types import ProjectApiUpdateProjectRequest +from .types import ProjectQualification from .api import AccountV3ContractAPI from .api import AccountV3ProjectAPI @@ -26,9 +41,22 @@ "ContractType", "ListContractSignaturesRequestOrderBy", "ListProjectsRequestOrderBy", + "QualificationArchitectureType", + "QualificationHostApplicationSubUseCase", + "QualificationHostWebsiteSubUseCase", "Contract", + "QualificationAiMachine", + "QualificationArchiveData", + "QualificationContainer", + "QualificationDeploySoftware", + "QualificationHostApplication", + "QualificationHostWebsite", + "QualificationOtherUseCase", + "QualificationSetScalewayEnvironment", + "QualificationShareData", "ContractSignature", "Project", + "Qualification", "CheckContractSignatureResponse", "ContractApiCheckContractSignatureRequest", "ContractApiCreateContractSignatureRequest", @@ -41,7 +69,9 @@ "ProjectApiDeleteProjectRequest", "ProjectApiGetProjectRequest", "ProjectApiListProjectsRequest", + "ProjectApiSetProjectQualificationRequest", "ProjectApiUpdateProjectRequest", + "ProjectQualification", "AccountV3ContractAPI", "AccountV3ProjectAPI", ] diff --git a/scaleway/scaleway/account/v3/api.py b/scaleway/scaleway/account/v3/api.py index 5619ae907..0631e5376 100644 --- a/scaleway/scaleway/account/v3/api.py +++ b/scaleway/scaleway/account/v3/api.py @@ -25,7 +25,10 @@ ListProjectsResponse, Project, ProjectApiCreateProjectRequest, + ProjectApiSetProjectQualificationRequest, ProjectApiUpdateProjectRequest, + ProjectQualification, + Qualification, ) from .marshalling import ( unmarshal_ContractSignature, @@ -33,9 +36,11 @@ unmarshal_CheckContractSignatureResponse, unmarshal_ListContractSignaturesResponse, unmarshal_ListProjectsResponse, + unmarshal_ProjectQualification, marshal_ContractApiCheckContractSignatureRequest, marshal_ContractApiCreateContractSignatureRequest, marshal_ProjectApiCreateProjectRequest, + marshal_ProjectApiSetProjectQualificationRequest, marshal_ProjectApiUpdateProjectRequest, ) from ...std.types import ( @@ -491,3 +496,41 @@ def update_project( self._throw_on_error(res) return unmarshal_Project(res.json()) + + def set_project_qualification( + self, + *, + project_id: Optional[str] = None, + qualification: Optional[Qualification] = None, + ) -> ProjectQualification: + """ + Set project use case. + Set the project use case for a new or existing Project, specified by its Project ID. You can customize the use case, sub use case, and architecture type you want to use in the Project. + :param project_id: Project ID. + :param qualification: Use case chosen for the Project. + :return: :class:`ProjectQualification ` + + Usage: + :: + + result = api.set_project_qualification() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "POST", + f"/account/v3/projects/{param_project_id}/project-qualification", + body=marshal_ProjectApiSetProjectQualificationRequest( + ProjectApiSetProjectQualificationRequest( + project_id=project_id, + qualification=qualification, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ProjectQualification(res.json()) diff --git a/scaleway/scaleway/account/v3/marshalling.py b/scaleway/scaleway/account/v3/marshalling.py index f6e3445a6..755e37779 100644 --- a/scaleway/scaleway/account/v3/marshalling.py +++ b/scaleway/scaleway/account/v3/marshalling.py @@ -5,6 +5,10 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) from .types import ( Contract, ContractSignature, @@ -12,9 +16,21 @@ CheckContractSignatureResponse, ListContractSignaturesResponse, ListProjectsResponse, + QualificationAiMachine, + QualificationArchiveData, + QualificationContainer, + QualificationDeploySoftware, + QualificationHostApplication, + QualificationHostWebsite, + QualificationOtherUseCase, + QualificationSetScalewayEnvironment, + QualificationShareData, + Qualification, + ProjectQualification, ContractApiCheckContractSignatureRequest, ContractApiCreateContractSignatureRequest, ProjectApiCreateProjectRequest, + ProjectApiSetProjectQualificationRequest, ProjectApiUpdateProjectRequest, ) @@ -207,6 +223,207 @@ def unmarshal_ListProjectsResponse(data: Any) -> ListProjectsResponse: return ListProjectsResponse(**args) +def unmarshal_QualificationAiMachine(data: Any) -> QualificationAiMachine: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationAiMachine' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationAiMachine(**args) + + +def unmarshal_QualificationArchiveData(data: Any) -> QualificationArchiveData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationArchiveData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationArchiveData(**args) + + +def unmarshal_QualificationContainer(data: Any) -> QualificationContainer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationContainer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationContainer(**args) + + +def unmarshal_QualificationDeploySoftware(data: Any) -> QualificationDeploySoftware: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationDeploySoftware' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationDeploySoftware(**args) + + +def unmarshal_QualificationHostApplication(data: Any) -> QualificationHostApplication: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationHostApplication' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationHostApplication(**args) + + +def unmarshal_QualificationHostWebsite(data: Any) -> QualificationHostWebsite: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationHostWebsite' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationHostWebsite(**args) + + +def unmarshal_QualificationOtherUseCase(data: Any) -> QualificationOtherUseCase: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationOtherUseCase' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationOtherUseCase(**args) + + +def unmarshal_QualificationSetScalewayEnvironment( + data: Any, +) -> QualificationSetScalewayEnvironment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationSetScalewayEnvironment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationSetScalewayEnvironment(**args) + + +def unmarshal_QualificationShareData(data: Any) -> QualificationShareData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationShareData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return QualificationShareData(**args) + + +def unmarshal_Qualification(data: Any) -> Qualification: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Qualification' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("architecture_type", None) + if field is not None: + args["architecture_type"] = field + + field = data.get("host_website", None) + if field is not None: + args["host_website"] = unmarshal_QualificationHostWebsite(field) + else: + args["host_website"] = None + + field = data.get("host_application", None) + if field is not None: + args["host_application"] = unmarshal_QualificationHostApplication(field) + else: + args["host_application"] = None + + field = data.get("deploy_software", None) + if field is not None: + args["deploy_software"] = unmarshal_QualificationDeploySoftware(field) + else: + args["deploy_software"] = None + + field = data.get("set_scaleway_environment", None) + if field is not None: + args["set_scaleway_environment"] = ( + unmarshal_QualificationSetScalewayEnvironment(field) + ) + else: + args["set_scaleway_environment"] = None + + field = data.get("ai_machine", None) + if field is not None: + args["ai_machine"] = unmarshal_QualificationAiMachine(field) + else: + args["ai_machine"] = None + + field = data.get("container", None) + if field is not None: + args["container"] = unmarshal_QualificationContainer(field) + else: + args["container"] = None + + field = data.get("archive_data", None) + if field is not None: + args["archive_data"] = unmarshal_QualificationArchiveData(field) + else: + args["archive_data"] = None + + field = data.get("share_data", None) + if field is not None: + args["share_data"] = unmarshal_QualificationShareData(field) + else: + args["share_data"] = None + + field = data.get("other_use_case", None) + if field is not None: + args["other_use_case"] = unmarshal_QualificationOtherUseCase(field) + else: + args["other_use_case"] = None + + return Qualification(**args) + + +def unmarshal_ProjectQualification(data: Any) -> ProjectQualification: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectQualification' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("qualification", None) + if field is not None: + args["qualification"] = unmarshal_Qualification(field) + else: + args["qualification"] = None + + return ProjectQualification(**args) + + def marshal_ContractApiCheckContractSignatureRequest( request: ContractApiCheckContractSignatureRequest, defaults: ProfileDefaults, @@ -270,6 +487,134 @@ def marshal_ProjectApiCreateProjectRequest( return output +def marshal_QualificationAiMachine( + request: QualificationAiMachine, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationArchiveData( + request: QualificationArchiveData, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationContainer( + request: QualificationContainer, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationDeploySoftware( + request: QualificationDeploySoftware, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationHostApplication( + request: QualificationHostApplication, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationHostWebsite( + request: QualificationHostWebsite, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationOtherUseCase( + request: QualificationOtherUseCase, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationSetScalewayEnvironment( + request: QualificationSetScalewayEnvironment, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_QualificationShareData( + request: QualificationShareData, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_Qualification( + request: Qualification, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("host_website", request.host_website), + OneOfPossibility("host_application", request.host_application), + OneOfPossibility("deploy_software", request.deploy_software), + OneOfPossibility( + "set_scaleway_environment", request.set_scaleway_environment + ), + OneOfPossibility("ai_machine", request.ai_machine), + OneOfPossibility("container", request.container), + OneOfPossibility("archive_data", request.archive_data), + OneOfPossibility("share_data", request.share_data), + OneOfPossibility("other_use_case", request.other_use_case), + ] + ), + ) + + if request.architecture_type is not None: + output["architecture_type"] = str(request.architecture_type) + + return output + + +def marshal_ProjectApiSetProjectQualificationRequest( + request: ProjectApiSetProjectQualificationRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.qualification is not None: + output["qualification"] = marshal_Qualification(request.qualification, defaults) + + return output + + def marshal_ProjectApiUpdateProjectRequest( request: ProjectApiUpdateProjectRequest, defaults: ProfileDefaults, diff --git a/scaleway/scaleway/account/v3/types.py b/scaleway/scaleway/account/v3/types.py index 9973bf316..f89f0b828 100644 --- a/scaleway/scaleway/account/v3/types.py +++ b/scaleway/scaleway/account/v3/types.py @@ -50,6 +50,41 @@ def __str__(self) -> str: return str(self.value) +class QualificationArchitectureType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ARCHITECTURE_TYPE = "unknown_architecture_type" + OBJECT_STORAGE = "object_storage" + WEB_HOSTING = "web_hosting" + INSTANCE = "instance" + ELASTIC = "elastic" + KUBERNETES = "kubernetes" + SERVERLESS = "serverless" + DEDICATED_SERVER = "dedicated_server" + OTHER_ARCHITECTURE_TYPE = "other_architecture_type" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationHostApplicationSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + SAAS_APP = "saas_app" + GOVERNMENT_APP = "government_app" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationHostWebsiteSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + INFORMATION_WEBSITE = "information_website" + ECOMMERCE_WEBSITE = "ecommerce_website" + HIGH_WEBSITE = "high_website" + OTHER_SUB_USE_CASE = "other_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + @dataclass class Contract: id: str @@ -83,6 +118,51 @@ class Contract: """ +@dataclass +class QualificationAiMachine: + pass + + +@dataclass +class QualificationArchiveData: + pass + + +@dataclass +class QualificationContainer: + pass + + +@dataclass +class QualificationDeploySoftware: + pass + + +@dataclass +class QualificationHostApplication: + sub_use_case: QualificationHostApplicationSubUseCase + + +@dataclass +class QualificationHostWebsite: + sub_use_case: QualificationHostWebsiteSubUseCase + + +@dataclass +class QualificationOtherUseCase: + pass + + +@dataclass +class QualificationSetScalewayEnvironment: + pass + + +@dataclass +class QualificationShareData: + pass + + @dataclass class ContractSignature: id: str @@ -149,6 +229,32 @@ class Project: """ +@dataclass +class Qualification: + architecture_type: QualificationArchitectureType + """ + Architecture type of the qualification. + """ + + host_website: Optional[QualificationHostWebsite] + + host_application: Optional[QualificationHostApplication] + + deploy_software: Optional[QualificationDeploySoftware] + + set_scaleway_environment: Optional[QualificationSetScalewayEnvironment] + + ai_machine: Optional[QualificationAiMachine] + + container: Optional[QualificationContainer] + + archive_data: Optional[QualificationArchiveData] + + share_data: Optional[QualificationShareData] + + other_use_case: Optional[QualificationOtherUseCase] + + @dataclass class CheckContractSignatureResponse: created: bool @@ -340,6 +446,19 @@ class ProjectApiListProjectsRequest: """ +@dataclass +class ProjectApiSetProjectQualificationRequest: + project_id: Optional[str] + """ + Project ID. + """ + + qualification: Optional[Qualification] + """ + Use case chosen for the Project. + """ + + @dataclass class ProjectApiUpdateProjectRequest: project_id: Optional[str] @@ -356,3 +475,16 @@ class ProjectApiUpdateProjectRequest: """ Description of the Project. """ + + +@dataclass +class ProjectQualification: + project_id: str + """ + Project ID. + """ + + qualification: Optional[Qualification] + """ + Qualification of the Project. + """ From c96da693670eeffdf828f507c7dc451c1b10e6e7 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 18 Mar 2025 11:28:39 +0100 Subject: [PATCH 69/73] feat(inference): add modelId and quantization to updateDeploymentRequest (#912) --- scaleway-async/scaleway_async/inference/v1/api.py | 6 ++++++ .../scaleway_async/inference/v1/marshalling.py | 8 ++++++++ scaleway-async/scaleway_async/inference/v1/types.py | 10 ++++++++++ scaleway/scaleway/inference/v1/api.py | 6 ++++++ scaleway/scaleway/inference/v1/marshalling.py | 8 ++++++++ scaleway/scaleway/inference/v1/types.py | 10 ++++++++++ 6 files changed, 48 insertions(+) diff --git a/scaleway-async/scaleway_async/inference/v1/api.py b/scaleway-async/scaleway_async/inference/v1/api.py index 4a25975a8..e6d86e580 100644 --- a/scaleway-async/scaleway_async/inference/v1/api.py +++ b/scaleway-async/scaleway_async/inference/v1/api.py @@ -311,6 +311,8 @@ async def update_deployment( tags: Optional[List[str]] = None, min_size: Optional[int] = None, max_size: Optional[int] = None, + model_id: Optional[str] = None, + quantization: Optional[DeploymentQuantization] = None, ) -> Deployment: """ Update a deployment. @@ -321,6 +323,8 @@ async def update_deployment( :param tags: List of tags to apply to the deployment. :param min_size: Defines the new minimum size of the pool. :param max_size: Defines the new maximum size of the pool. + :param model_id: Id of the model to set to the deployment. + :param quantization: Quantization to use to the deployment. :return: :class:`Deployment ` Usage: @@ -347,6 +351,8 @@ async def update_deployment( tags=tags, min_size=min_size, max_size=max_size, + model_id=model_id, + quantization=quantization, ), self.client, ), diff --git a/scaleway-async/scaleway_async/inference/v1/marshalling.py b/scaleway-async/scaleway_async/inference/v1/marshalling.py index 9f10b88e1..d314f97c0 100644 --- a/scaleway-async/scaleway_async/inference/v1/marshalling.py +++ b/scaleway-async/scaleway_async/inference/v1/marshalling.py @@ -639,6 +639,14 @@ def marshal_UpdateDeploymentRequest( if request.max_size is not None: output["max_size"] = request.max_size + if request.model_id is not None: + output["model_id"] = request.model_id + + if request.quantization is not None: + output["quantization"] = marshal_DeploymentQuantization( + request.quantization, defaults + ) + return output diff --git a/scaleway-async/scaleway_async/inference/v1/types.py b/scaleway-async/scaleway_async/inference/v1/types.py index 9dd6fce4b..7278dc37c 100644 --- a/scaleway-async/scaleway_async/inference/v1/types.py +++ b/scaleway-async/scaleway_async/inference/v1/types.py @@ -750,6 +750,16 @@ class UpdateDeploymentRequest: Defines the new maximum size of the pool. """ + model_id: Optional[str] + """ + Id of the model to set to the deployment. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization to use to the deployment. + """ + @dataclass class UpdateEndpointRequest: diff --git a/scaleway/scaleway/inference/v1/api.py b/scaleway/scaleway/inference/v1/api.py index 4cecd31cd..9088a7835 100644 --- a/scaleway/scaleway/inference/v1/api.py +++ b/scaleway/scaleway/inference/v1/api.py @@ -309,6 +309,8 @@ def update_deployment( tags: Optional[List[str]] = None, min_size: Optional[int] = None, max_size: Optional[int] = None, + model_id: Optional[str] = None, + quantization: Optional[DeploymentQuantization] = None, ) -> Deployment: """ Update a deployment. @@ -319,6 +321,8 @@ def update_deployment( :param tags: List of tags to apply to the deployment. :param min_size: Defines the new minimum size of the pool. :param max_size: Defines the new maximum size of the pool. + :param model_id: Id of the model to set to the deployment. + :param quantization: Quantization to use to the deployment. :return: :class:`Deployment ` Usage: @@ -345,6 +349,8 @@ def update_deployment( tags=tags, min_size=min_size, max_size=max_size, + model_id=model_id, + quantization=quantization, ), self.client, ), diff --git a/scaleway/scaleway/inference/v1/marshalling.py b/scaleway/scaleway/inference/v1/marshalling.py index 9f10b88e1..d314f97c0 100644 --- a/scaleway/scaleway/inference/v1/marshalling.py +++ b/scaleway/scaleway/inference/v1/marshalling.py @@ -639,6 +639,14 @@ def marshal_UpdateDeploymentRequest( if request.max_size is not None: output["max_size"] = request.max_size + if request.model_id is not None: + output["model_id"] = request.model_id + + if request.quantization is not None: + output["quantization"] = marshal_DeploymentQuantization( + request.quantization, defaults + ) + return output diff --git a/scaleway/scaleway/inference/v1/types.py b/scaleway/scaleway/inference/v1/types.py index 9dd6fce4b..7278dc37c 100644 --- a/scaleway/scaleway/inference/v1/types.py +++ b/scaleway/scaleway/inference/v1/types.py @@ -750,6 +750,16 @@ class UpdateDeploymentRequest: Defines the new maximum size of the pool. """ + model_id: Optional[str] + """ + Id of the model to set to the deployment. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization to use to the deployment. + """ + @dataclass class UpdateEndpointRequest: From e3062c086fe6d1ad6a3cbefdd3f5f671f82fc5f8 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 18 Mar 2025 11:39:04 +0100 Subject: [PATCH 70/73] feat(vpc): set acl calls to public visibility (#913) Co-authored-by: Jonathan R. --- .../scaleway_async/vpc/v2/__init__.py | 14 ++ scaleway-async/scaleway_async/vpc/v2/api.py | 101 ++++++++++++ .../scaleway_async/vpc/v2/marshalling.py | 149 ++++++++++++++++++ scaleway-async/scaleway_async/vpc/v2/types.py | 127 +++++++++++++++ scaleway/scaleway/vpc/v2/__init__.py | 14 ++ scaleway/scaleway/vpc/v2/api.py | 101 ++++++++++++ scaleway/scaleway/vpc/v2/marshalling.py | 149 ++++++++++++++++++ scaleway/scaleway/vpc/v2/types.py | 127 +++++++++++++++ 8 files changed, 782 insertions(+) diff --git a/scaleway-async/scaleway_async/vpc/v2/__init__.py b/scaleway-async/scaleway_async/vpc/v2/__init__.py index 6d334b94c..e256f249c 100644 --- a/scaleway-async/scaleway_async/vpc/v2/__init__.py +++ b/scaleway-async/scaleway_async/vpc/v2/__init__.py @@ -1,11 +1,14 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import AclRuleProtocol +from .types import Action from .types import ListPrivateNetworksRequestOrderBy from .types import ListSubnetsRequestOrderBy from .types import ListVPCsRequestOrderBy from .types import Subnet from .types import PrivateNetwork from .types import Route +from .types import AclRule from .types import VPC from .types import AddSubnetsRequest from .types import AddSubnetsResponse @@ -19,6 +22,8 @@ from .types import DeleteVPCRequest from .types import EnableDHCPRequest from .types import EnableRoutingRequest +from .types import GetAclRequest +from .types import GetAclResponse from .types import GetPrivateNetworkRequest from .types import GetRouteRequest from .types import GetVPCRequest @@ -28,6 +33,8 @@ from .types import ListSubnetsResponse from .types import ListVPCsRequest from .types import ListVPCsResponse +from .types import SetAclRequest +from .types import SetAclResponse from .types import SetSubnetsRequest from .types import SetSubnetsResponse from .types import UpdatePrivateNetworkRequest @@ -36,12 +43,15 @@ from .api import VpcV2API __all__ = [ + "AclRuleProtocol", + "Action", "ListPrivateNetworksRequestOrderBy", "ListSubnetsRequestOrderBy", "ListVPCsRequestOrderBy", "Subnet", "PrivateNetwork", "Route", + "AclRule", "VPC", "AddSubnetsRequest", "AddSubnetsResponse", @@ -55,6 +65,8 @@ "DeleteVPCRequest", "EnableDHCPRequest", "EnableRoutingRequest", + "GetAclRequest", + "GetAclResponse", "GetPrivateNetworkRequest", "GetRouteRequest", "GetVPCRequest", @@ -64,6 +76,8 @@ "ListSubnetsResponse", "ListVPCsRequest", "ListVPCsResponse", + "SetAclRequest", + "SetAclResponse", "SetSubnetsRequest", "SetSubnetsResponse", "UpdatePrivateNetworkRequest", diff --git a/scaleway-async/scaleway_async/vpc/v2/api.py b/scaleway-async/scaleway_async/vpc/v2/api.py index fb3b7fdff..49a460d68 100644 --- a/scaleway-async/scaleway_async/vpc/v2/api.py +++ b/scaleway-async/scaleway_async/vpc/v2/api.py @@ -13,9 +13,11 @@ fetch_all_pages_async, ) from .types import ( + Action, ListPrivateNetworksRequestOrderBy, ListSubnetsRequestOrderBy, ListVPCsRequestOrderBy, + AclRule, AddSubnetsRequest, AddSubnetsResponse, CreatePrivateNetworkRequest, @@ -23,11 +25,14 @@ CreateVPCRequest, DeleteSubnetsRequest, DeleteSubnetsResponse, + GetAclResponse, ListPrivateNetworksResponse, ListSubnetsResponse, ListVPCsResponse, PrivateNetwork, Route, + SetAclRequest, + SetAclResponse, SetSubnetsRequest, SetSubnetsResponse, Subnet, @@ -42,15 +47,18 @@ unmarshal_VPC, unmarshal_AddSubnetsResponse, unmarshal_DeleteSubnetsResponse, + unmarshal_GetAclResponse, unmarshal_ListPrivateNetworksResponse, unmarshal_ListSubnetsResponse, unmarshal_ListVPCsResponse, + unmarshal_SetAclResponse, unmarshal_SetSubnetsResponse, marshal_AddSubnetsRequest, marshal_CreatePrivateNetworkRequest, marshal_CreateRouteRequest, marshal_CreateVPCRequest, marshal_DeleteSubnetsRequest, + marshal_SetAclRequest, marshal_SetSubnetsRequest, marshal_UpdatePrivateNetworkRequest, marshal_UpdateRouteRequest, @@ -1112,3 +1120,96 @@ async def delete_route( ) self._throw_on_error(res) + + async def get_acl( + self, + *, + vpc_id: str, + is_ipv6: bool, + region: Optional[ScwRegion] = None, + ) -> GetAclResponse: + """ + Get Acl Rules for VPC. + Retrieve a list of ACL rules for a VPC, specified by its VPC ID. + :param vpc_id: ID of the Network ACL's VPC. + :param is_ipv6: Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`GetAclResponse ` + + Usage: + :: + + result = await api.get_acl( + vpc_id="example", + is_ipv6=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) + + res = self._request( + "GET", + f"/vpc/v2/regions/{param_region}/vpc/{param_vpc_id}/acl-rules", + params={ + "is_ipv6": is_ipv6, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetAclResponse(res.json()) + + async def set_acl( + self, + *, + vpc_id: str, + rules: List[AclRule], + is_ipv6: bool, + default_policy: Action, + region: Optional[ScwRegion] = None, + ) -> SetAclResponse: + """ + Set VPC ACL rules. + Set the list of ACL rules and the default routing policy for a VPC. + :param vpc_id: ID of the Network ACL's VPC. + :param rules: List of Network ACL rules. + :param is_ipv6: Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + :param default_policy: Action to take for packets which do not match any rules. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SetAclResponse ` + + Usage: + :: + + result = await api.set_acl( + vpc_id="example", + rules=[], + is_ipv6=False, + default_policy=Action.unknown_action, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) + + res = self._request( + "PUT", + f"/vpc/v2/regions/{param_region}/vpc/{param_vpc_id}/acl-rules", + body=marshal_SetAclRequest( + SetAclRequest( + vpc_id=vpc_id, + rules=rules, + is_ipv6=is_ipv6, + default_policy=default_policy, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetAclResponse(res.json()) diff --git a/scaleway-async/scaleway_async/vpc/v2/marshalling.py b/scaleway-async/scaleway_async/vpc/v2/marshalling.py index 2d8334fa0..ce426cbe4 100644 --- a/scaleway-async/scaleway_async/vpc/v2/marshalling.py +++ b/scaleway-async/scaleway_async/vpc/v2/marshalling.py @@ -12,15 +12,19 @@ VPC, AddSubnetsResponse, DeleteSubnetsResponse, + AclRule, + GetAclResponse, ListPrivateNetworksResponse, ListSubnetsResponse, ListVPCsResponse, + SetAclResponse, SetSubnetsResponse, AddSubnetsRequest, CreatePrivateNetworkRequest, CreateRouteRequest, CreateVPCRequest, DeleteSubnetsRequest, + SetAclRequest, SetSubnetsRequest, UpdatePrivateNetworkRequest, UpdateRouteRequest, @@ -284,6 +288,76 @@ def unmarshal_DeleteSubnetsResponse(data: Any) -> DeleteSubnetsResponse: return DeleteSubnetsResponse(**args) +def unmarshal_AclRule(data: Any) -> AclRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AclRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("protocol", None) + if field is not None: + args["protocol"] = field + + field = data.get("source", None) + if field is not None: + args["source"] = field + + field = data.get("src_port_low", None) + if field is not None: + args["src_port_low"] = field + + field = data.get("src_port_high", None) + if field is not None: + args["src_port_high"] = field + + field = data.get("destination", None) + if field is not None: + args["destination"] = field + + field = data.get("dst_port_low", None) + if field is not None: + args["dst_port_low"] = field + + field = data.get("dst_port_high", None) + if field is not None: + args["dst_port_high"] = field + + field = data.get("action", None) + if field is not None: + args["action"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + else: + args["description"] = None + + return AclRule(**args) + + +def unmarshal_GetAclResponse(data: Any) -> GetAclResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetAclResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_AclRule(v) for v in field] if field is not None else None + ) + + field = data.get("default_policy", None) + if field is not None: + args["default_policy"] = field + + return GetAclResponse(**args) + + def unmarshal_ListPrivateNetworksResponse(data: Any) -> ListPrivateNetworksResponse: if not isinstance(data, dict): raise TypeError( @@ -345,6 +419,27 @@ def unmarshal_ListVPCsResponse(data: Any) -> ListVPCsResponse: return ListVPCsResponse(**args) +def unmarshal_SetAclResponse(data: Any) -> SetAclResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetAclResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_AclRule(v) for v in field] if field is not None else None + ) + + field = data.get("default_policy", None) + if field is not None: + args["default_policy"] = field + + return SetAclResponse(**args) + + def unmarshal_SetSubnetsResponse(data: Any) -> SetSubnetsResponse: if not isinstance(data, dict): raise TypeError( @@ -456,6 +551,60 @@ def marshal_DeleteSubnetsRequest( return output +def marshal_AclRule( + request: AclRule, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + if request.source is not None: + output["source"] = request.source + + if request.src_port_low is not None: + output["src_port_low"] = request.src_port_low + + if request.src_port_high is not None: + output["src_port_high"] = request.src_port_high + + if request.destination is not None: + output["destination"] = request.destination + + if request.dst_port_low is not None: + output["dst_port_low"] = request.dst_port_low + + if request.dst_port_high is not None: + output["dst_port_high"] = request.dst_port_high + + if request.action is not None: + output["action"] = str(request.action) + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_SetAclRequest( + request: SetAclRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.rules is not None: + output["rules"] = [marshal_AclRule(item, defaults) for item in request.rules] + + if request.is_ipv6 is not None: + output["is_ipv6"] = request.is_ipv6 + + if request.default_policy is not None: + output["default_policy"] = str(request.default_policy) + + return output + + def marshal_SetSubnetsRequest( request: SetSubnetsRequest, defaults: ProfileDefaults, diff --git a/scaleway-async/scaleway_async/vpc/v2/types.py b/scaleway-async/scaleway_async/vpc/v2/types.py index c74bcc528..3021592d8 100644 --- a/scaleway-async/scaleway_async/vpc/v2/types.py +++ b/scaleway-async/scaleway_async/vpc/v2/types.py @@ -15,6 +15,25 @@ ) +class AclRuleProtocol(str, Enum, metaclass=StrEnumMeta): + ANY = "any" + TCP = "tcp" + UDP = "udp" + ICMP = "icmp" + + def __str__(self) -> str: + return str(self.value) + + +class Action(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + ACCEPT = "accept" + DROP = "drop" + + def __str__(self) -> str: + return str(self.value) + + class ListPrivateNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -197,6 +216,54 @@ class Route: """ +@dataclass +class AclRule: + protocol: AclRuleProtocol + """ + Protocol to which this rule applies. + """ + + source: str + """ + Source IP range to which this rule applies (CIDR notation with subnet mask). + """ + + src_port_low: int + """ + Starting port of the source port range to which this rule applies (inclusive). + """ + + src_port_high: int + """ + Ending port of the source port range to which this rule applies (inclusive). + """ + + destination: str + """ + Destination IP range to which this rule applies (CIDR notation with subnet mask). + """ + + dst_port_low: int + """ + Starting port of the destination port range to which this rule applies (inclusive). + """ + + dst_port_high: int + """ + Ending port of the destination port range to which this rule applies (inclusive). + """ + + action: Action + """ + Policy to apply to the packet. + """ + + description: Optional[str] + """ + Rule description. + """ + + @dataclass class VPC: id: str @@ -465,6 +532,31 @@ class EnableRoutingRequest: """ +@dataclass +class GetAclRequest: + vpc_id: str + """ + ID of the Network ACL's VPC. + """ + + is_ipv6: bool + """ + Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetAclResponse: + rules: List[AclRule] + + default_policy: Action + + @dataclass class GetPrivateNetworkRequest: private_network_id: str @@ -679,6 +771,41 @@ class ListVPCsResponse: total_count: int +@dataclass +class SetAclRequest: + vpc_id: str + """ + ID of the Network ACL's VPC. + """ + + rules: List[AclRule] + """ + List of Network ACL rules. + """ + + is_ipv6: bool + """ + Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + """ + + default_policy: Action + """ + Action to take for packets which do not match any rules. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SetAclResponse: + rules: List[AclRule] + + default_policy: Action + + @dataclass class SetSubnetsRequest: private_network_id: str diff --git a/scaleway/scaleway/vpc/v2/__init__.py b/scaleway/scaleway/vpc/v2/__init__.py index 6d334b94c..e256f249c 100644 --- a/scaleway/scaleway/vpc/v2/__init__.py +++ b/scaleway/scaleway/vpc/v2/__init__.py @@ -1,11 +1,14 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import AclRuleProtocol +from .types import Action from .types import ListPrivateNetworksRequestOrderBy from .types import ListSubnetsRequestOrderBy from .types import ListVPCsRequestOrderBy from .types import Subnet from .types import PrivateNetwork from .types import Route +from .types import AclRule from .types import VPC from .types import AddSubnetsRequest from .types import AddSubnetsResponse @@ -19,6 +22,8 @@ from .types import DeleteVPCRequest from .types import EnableDHCPRequest from .types import EnableRoutingRequest +from .types import GetAclRequest +from .types import GetAclResponse from .types import GetPrivateNetworkRequest from .types import GetRouteRequest from .types import GetVPCRequest @@ -28,6 +33,8 @@ from .types import ListSubnetsResponse from .types import ListVPCsRequest from .types import ListVPCsResponse +from .types import SetAclRequest +from .types import SetAclResponse from .types import SetSubnetsRequest from .types import SetSubnetsResponse from .types import UpdatePrivateNetworkRequest @@ -36,12 +43,15 @@ from .api import VpcV2API __all__ = [ + "AclRuleProtocol", + "Action", "ListPrivateNetworksRequestOrderBy", "ListSubnetsRequestOrderBy", "ListVPCsRequestOrderBy", "Subnet", "PrivateNetwork", "Route", + "AclRule", "VPC", "AddSubnetsRequest", "AddSubnetsResponse", @@ -55,6 +65,8 @@ "DeleteVPCRequest", "EnableDHCPRequest", "EnableRoutingRequest", + "GetAclRequest", + "GetAclResponse", "GetPrivateNetworkRequest", "GetRouteRequest", "GetVPCRequest", @@ -64,6 +76,8 @@ "ListSubnetsResponse", "ListVPCsRequest", "ListVPCsResponse", + "SetAclRequest", + "SetAclResponse", "SetSubnetsRequest", "SetSubnetsResponse", "UpdatePrivateNetworkRequest", diff --git a/scaleway/scaleway/vpc/v2/api.py b/scaleway/scaleway/vpc/v2/api.py index 2932decbe..476feff39 100644 --- a/scaleway/scaleway/vpc/v2/api.py +++ b/scaleway/scaleway/vpc/v2/api.py @@ -13,9 +13,11 @@ fetch_all_pages, ) from .types import ( + Action, ListPrivateNetworksRequestOrderBy, ListSubnetsRequestOrderBy, ListVPCsRequestOrderBy, + AclRule, AddSubnetsRequest, AddSubnetsResponse, CreatePrivateNetworkRequest, @@ -23,11 +25,14 @@ CreateVPCRequest, DeleteSubnetsRequest, DeleteSubnetsResponse, + GetAclResponse, ListPrivateNetworksResponse, ListSubnetsResponse, ListVPCsResponse, PrivateNetwork, Route, + SetAclRequest, + SetAclResponse, SetSubnetsRequest, SetSubnetsResponse, Subnet, @@ -42,15 +47,18 @@ unmarshal_VPC, unmarshal_AddSubnetsResponse, unmarshal_DeleteSubnetsResponse, + unmarshal_GetAclResponse, unmarshal_ListPrivateNetworksResponse, unmarshal_ListSubnetsResponse, unmarshal_ListVPCsResponse, + unmarshal_SetAclResponse, unmarshal_SetSubnetsResponse, marshal_AddSubnetsRequest, marshal_CreatePrivateNetworkRequest, marshal_CreateRouteRequest, marshal_CreateVPCRequest, marshal_DeleteSubnetsRequest, + marshal_SetAclRequest, marshal_SetSubnetsRequest, marshal_UpdatePrivateNetworkRequest, marshal_UpdateRouteRequest, @@ -1112,3 +1120,96 @@ def delete_route( ) self._throw_on_error(res) + + def get_acl( + self, + *, + vpc_id: str, + is_ipv6: bool, + region: Optional[ScwRegion] = None, + ) -> GetAclResponse: + """ + Get Acl Rules for VPC. + Retrieve a list of ACL rules for a VPC, specified by its VPC ID. + :param vpc_id: ID of the Network ACL's VPC. + :param is_ipv6: Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`GetAclResponse ` + + Usage: + :: + + result = api.get_acl( + vpc_id="example", + is_ipv6=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) + + res = self._request( + "GET", + f"/vpc/v2/regions/{param_region}/vpc/{param_vpc_id}/acl-rules", + params={ + "is_ipv6": is_ipv6, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetAclResponse(res.json()) + + def set_acl( + self, + *, + vpc_id: str, + rules: List[AclRule], + is_ipv6: bool, + default_policy: Action, + region: Optional[ScwRegion] = None, + ) -> SetAclResponse: + """ + Set VPC ACL rules. + Set the list of ACL rules and the default routing policy for a VPC. + :param vpc_id: ID of the Network ACL's VPC. + :param rules: List of Network ACL rules. + :param is_ipv6: Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + :param default_policy: Action to take for packets which do not match any rules. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SetAclResponse ` + + Usage: + :: + + result = api.set_acl( + vpc_id="example", + rules=[], + is_ipv6=False, + default_policy=Action.unknown_action, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) + + res = self._request( + "PUT", + f"/vpc/v2/regions/{param_region}/vpc/{param_vpc_id}/acl-rules", + body=marshal_SetAclRequest( + SetAclRequest( + vpc_id=vpc_id, + rules=rules, + is_ipv6=is_ipv6, + default_policy=default_policy, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetAclResponse(res.json()) diff --git a/scaleway/scaleway/vpc/v2/marshalling.py b/scaleway/scaleway/vpc/v2/marshalling.py index 2d8334fa0..ce426cbe4 100644 --- a/scaleway/scaleway/vpc/v2/marshalling.py +++ b/scaleway/scaleway/vpc/v2/marshalling.py @@ -12,15 +12,19 @@ VPC, AddSubnetsResponse, DeleteSubnetsResponse, + AclRule, + GetAclResponse, ListPrivateNetworksResponse, ListSubnetsResponse, ListVPCsResponse, + SetAclResponse, SetSubnetsResponse, AddSubnetsRequest, CreatePrivateNetworkRequest, CreateRouteRequest, CreateVPCRequest, DeleteSubnetsRequest, + SetAclRequest, SetSubnetsRequest, UpdatePrivateNetworkRequest, UpdateRouteRequest, @@ -284,6 +288,76 @@ def unmarshal_DeleteSubnetsResponse(data: Any) -> DeleteSubnetsResponse: return DeleteSubnetsResponse(**args) +def unmarshal_AclRule(data: Any) -> AclRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AclRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("protocol", None) + if field is not None: + args["protocol"] = field + + field = data.get("source", None) + if field is not None: + args["source"] = field + + field = data.get("src_port_low", None) + if field is not None: + args["src_port_low"] = field + + field = data.get("src_port_high", None) + if field is not None: + args["src_port_high"] = field + + field = data.get("destination", None) + if field is not None: + args["destination"] = field + + field = data.get("dst_port_low", None) + if field is not None: + args["dst_port_low"] = field + + field = data.get("dst_port_high", None) + if field is not None: + args["dst_port_high"] = field + + field = data.get("action", None) + if field is not None: + args["action"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + else: + args["description"] = None + + return AclRule(**args) + + +def unmarshal_GetAclResponse(data: Any) -> GetAclResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetAclResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_AclRule(v) for v in field] if field is not None else None + ) + + field = data.get("default_policy", None) + if field is not None: + args["default_policy"] = field + + return GetAclResponse(**args) + + def unmarshal_ListPrivateNetworksResponse(data: Any) -> ListPrivateNetworksResponse: if not isinstance(data, dict): raise TypeError( @@ -345,6 +419,27 @@ def unmarshal_ListVPCsResponse(data: Any) -> ListVPCsResponse: return ListVPCsResponse(**args) +def unmarshal_SetAclResponse(data: Any) -> SetAclResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetAclResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_AclRule(v) for v in field] if field is not None else None + ) + + field = data.get("default_policy", None) + if field is not None: + args["default_policy"] = field + + return SetAclResponse(**args) + + def unmarshal_SetSubnetsResponse(data: Any) -> SetSubnetsResponse: if not isinstance(data, dict): raise TypeError( @@ -456,6 +551,60 @@ def marshal_DeleteSubnetsRequest( return output +def marshal_AclRule( + request: AclRule, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + if request.source is not None: + output["source"] = request.source + + if request.src_port_low is not None: + output["src_port_low"] = request.src_port_low + + if request.src_port_high is not None: + output["src_port_high"] = request.src_port_high + + if request.destination is not None: + output["destination"] = request.destination + + if request.dst_port_low is not None: + output["dst_port_low"] = request.dst_port_low + + if request.dst_port_high is not None: + output["dst_port_high"] = request.dst_port_high + + if request.action is not None: + output["action"] = str(request.action) + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_SetAclRequest( + request: SetAclRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.rules is not None: + output["rules"] = [marshal_AclRule(item, defaults) for item in request.rules] + + if request.is_ipv6 is not None: + output["is_ipv6"] = request.is_ipv6 + + if request.default_policy is not None: + output["default_policy"] = str(request.default_policy) + + return output + + def marshal_SetSubnetsRequest( request: SetSubnetsRequest, defaults: ProfileDefaults, diff --git a/scaleway/scaleway/vpc/v2/types.py b/scaleway/scaleway/vpc/v2/types.py index c74bcc528..3021592d8 100644 --- a/scaleway/scaleway/vpc/v2/types.py +++ b/scaleway/scaleway/vpc/v2/types.py @@ -15,6 +15,25 @@ ) +class AclRuleProtocol(str, Enum, metaclass=StrEnumMeta): + ANY = "any" + TCP = "tcp" + UDP = "udp" + ICMP = "icmp" + + def __str__(self) -> str: + return str(self.value) + + +class Action(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + ACCEPT = "accept" + DROP = "drop" + + def __str__(self) -> str: + return str(self.value) + + class ListPrivateNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -197,6 +216,54 @@ class Route: """ +@dataclass +class AclRule: + protocol: AclRuleProtocol + """ + Protocol to which this rule applies. + """ + + source: str + """ + Source IP range to which this rule applies (CIDR notation with subnet mask). + """ + + src_port_low: int + """ + Starting port of the source port range to which this rule applies (inclusive). + """ + + src_port_high: int + """ + Ending port of the source port range to which this rule applies (inclusive). + """ + + destination: str + """ + Destination IP range to which this rule applies (CIDR notation with subnet mask). + """ + + dst_port_low: int + """ + Starting port of the destination port range to which this rule applies (inclusive). + """ + + dst_port_high: int + """ + Ending port of the destination port range to which this rule applies (inclusive). + """ + + action: Action + """ + Policy to apply to the packet. + """ + + description: Optional[str] + """ + Rule description. + """ + + @dataclass class VPC: id: str @@ -465,6 +532,31 @@ class EnableRoutingRequest: """ +@dataclass +class GetAclRequest: + vpc_id: str + """ + ID of the Network ACL's VPC. + """ + + is_ipv6: bool + """ + Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetAclResponse: + rules: List[AclRule] + + default_policy: Action + + @dataclass class GetPrivateNetworkRequest: private_network_id: str @@ -679,6 +771,41 @@ class ListVPCsResponse: total_count: int +@dataclass +class SetAclRequest: + vpc_id: str + """ + ID of the Network ACL's VPC. + """ + + rules: List[AclRule] + """ + List of Network ACL rules. + """ + + is_ipv6: bool + """ + Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + """ + + default_policy: Action + """ + Action to take for packets which do not match any rules. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SetAclResponse: + rules: List[AclRule] + + default_policy: Action + + @dataclass class SetSubnetsRequest: private_network_id: str From b4832b2f68dab2f1040b3b8a1fcd600edcb522b9 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 18 Mar 2025 16:25:46 +0100 Subject: [PATCH 71/73] docs(lb): update wording for uri param (#915) --- scaleway-async/scaleway_async/lb/v1/types.py | 4 ++-- scaleway/scaleway/lb/v1/types.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scaleway-async/scaleway_async/lb/v1/types.py b/scaleway-async/scaleway_async/lb/v1/types.py index f21a1befc..f15ed37fe 100644 --- a/scaleway-async/scaleway_async/lb/v1/types.py +++ b/scaleway-async/scaleway_async/lb/v1/types.py @@ -297,7 +297,7 @@ class SubscriberWebhookConfig: class HealthCheckHttpConfig: uri: str """ - The HTTP URI to use when performing a health check on backend servers. + The HTTP path to use when performing a health check on backend servers. """ method: str @@ -320,7 +320,7 @@ class HealthCheckHttpConfig: class HealthCheckHttpsConfig: uri: str """ - The HTTP URI to use when performing a health check on backend servers. + The HTTP path to use when performing a health check on backend servers. """ method: str diff --git a/scaleway/scaleway/lb/v1/types.py b/scaleway/scaleway/lb/v1/types.py index f21a1befc..f15ed37fe 100644 --- a/scaleway/scaleway/lb/v1/types.py +++ b/scaleway/scaleway/lb/v1/types.py @@ -297,7 +297,7 @@ class SubscriberWebhookConfig: class HealthCheckHttpConfig: uri: str """ - The HTTP URI to use when performing a health check on backend servers. + The HTTP path to use when performing a health check on backend servers. """ method: str @@ -320,7 +320,7 @@ class HealthCheckHttpConfig: class HealthCheckHttpsConfig: uri: str """ - The HTTP URI to use when performing a health check on backend servers. + The HTTP path to use when performing a health check on backend servers. """ method: str From 4d2974d4dd82a53018f3aa94183574f9dcdcee89 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 18 Mar 2025 16:26:32 +0100 Subject: [PATCH 72/73] fix(instance): remove unset baremetal field (#916) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> --- scaleway-async/scaleway_async/instance/v1/marshalling.py | 8 ++------ scaleway-async/scaleway_async/instance/v1/types.py | 9 ++------- scaleway/scaleway/instance/v1/marshalling.py | 8 ++------ scaleway/scaleway/instance/v1/types.py | 9 ++------- 4 files changed, 8 insertions(+), 26 deletions(-) diff --git a/scaleway-async/scaleway_async/instance/v1/marshalling.py b/scaleway-async/scaleway_async/instance/v1/marshalling.py index 419fa1dda..6a752f91e 100644 --- a/scaleway-async/scaleway_async/instance/v1/marshalling.py +++ b/scaleway-async/scaleway_async/instance/v1/marshalling.py @@ -2172,9 +2172,9 @@ def unmarshal_ServerType(data: Any) -> ServerType: if field is not None: args["arch"] = field - field = data.get("baremetal", None) + field = data.get("end_of_service", None) if field is not None: - args["baremetal"] = field + args["end_of_service"] = field field = data.get("per_volume_constraint", None) if field is not None: @@ -2196,10 +2196,6 @@ def unmarshal_ServerType(data: Any) -> ServerType: else: args["gpu"] = None - field = data.get("end_of_service", None) - if field is not None: - args["end_of_service"] = field - field = data.get("gpu_info", None) if field is not None: args["gpu_info"] = unmarshal_ServerTypeGPUInfo(field) diff --git a/scaleway-async/scaleway_async/instance/v1/types.py b/scaleway-async/scaleway_async/instance/v1/types.py index fef8846e8..160fbef17 100644 --- a/scaleway-async/scaleway_async/instance/v1/types.py +++ b/scaleway-async/scaleway_async/instance/v1/types.py @@ -1355,9 +1355,9 @@ class ServerType: CPU architecture. """ - baremetal: bool + end_of_service: bool """ - True if it is a baremetal Instance. + True if this Instance type has reached end of service. """ per_volume_constraint: Optional[ServerTypeVolumeConstraintsByType] @@ -1375,11 +1375,6 @@ class ServerType: Number of GPU. """ - end_of_service: bool - """ - True if this Instance type has reached end of service. - """ - gpu_info: Optional[ServerTypeGPUInfo] """ GPU information. diff --git a/scaleway/scaleway/instance/v1/marshalling.py b/scaleway/scaleway/instance/v1/marshalling.py index 419fa1dda..6a752f91e 100644 --- a/scaleway/scaleway/instance/v1/marshalling.py +++ b/scaleway/scaleway/instance/v1/marshalling.py @@ -2172,9 +2172,9 @@ def unmarshal_ServerType(data: Any) -> ServerType: if field is not None: args["arch"] = field - field = data.get("baremetal", None) + field = data.get("end_of_service", None) if field is not None: - args["baremetal"] = field + args["end_of_service"] = field field = data.get("per_volume_constraint", None) if field is not None: @@ -2196,10 +2196,6 @@ def unmarshal_ServerType(data: Any) -> ServerType: else: args["gpu"] = None - field = data.get("end_of_service", None) - if field is not None: - args["end_of_service"] = field - field = data.get("gpu_info", None) if field is not None: args["gpu_info"] = unmarshal_ServerTypeGPUInfo(field) diff --git a/scaleway/scaleway/instance/v1/types.py b/scaleway/scaleway/instance/v1/types.py index fef8846e8..160fbef17 100644 --- a/scaleway/scaleway/instance/v1/types.py +++ b/scaleway/scaleway/instance/v1/types.py @@ -1355,9 +1355,9 @@ class ServerType: CPU architecture. """ - baremetal: bool + end_of_service: bool """ - True if it is a baremetal Instance. + True if this Instance type has reached end of service. """ per_volume_constraint: Optional[ServerTypeVolumeConstraintsByType] @@ -1375,11 +1375,6 @@ class ServerType: Number of GPU. """ - end_of_service: bool - """ - True if this Instance type has reached end of service. - """ - gpu_info: Optional[ServerTypeGPUInfo] """ GPU information. From b5082ec333ff4672b6ed4cb8e242a71da2c668b0 Mon Sep 17 00:00:00 2001 From: Scaleway Bot Date: Tue, 18 Mar 2025 16:28:46 +0100 Subject: [PATCH 73/73] feat(k8s): add support iam_nodes_group_id (#917) Co-authored-by: Laure-di <62625835+Laure-di@users.noreply.github.com> --- scaleway-async/scaleway_async/k8s/v1/marshalling.py | 4 ++++ scaleway-async/scaleway_async/k8s/v1/types.py | 5 +++++ scaleway/scaleway/k8s/v1/marshalling.py | 4 ++++ scaleway/scaleway/k8s/v1/types.py | 5 +++++ 4 files changed, 18 insertions(+) diff --git a/scaleway-async/scaleway_async/k8s/v1/marshalling.py b/scaleway-async/scaleway_async/k8s/v1/marshalling.py index da0ede590..558cd4cb8 100644 --- a/scaleway-async/scaleway_async/k8s/v1/marshalling.py +++ b/scaleway-async/scaleway_async/k8s/v1/marshalling.py @@ -468,6 +468,10 @@ def unmarshal_Cluster(data: Any) -> Cluster: if field is not None: args["apiserver_cert_sans"] = field + field = data.get("iam_nodes_group_id", None) + if field is not None: + args["iam_nodes_group_id"] = field + field = data.get("open_id_connect_config", None) if field is not None: args["open_id_connect_config"] = unmarshal_ClusterOpenIDConnectConfig(field) diff --git a/scaleway-async/scaleway_async/k8s/v1/types.py b/scaleway-async/scaleway_async/k8s/v1/types.py index 248f66071..f979885ac 100644 --- a/scaleway-async/scaleway_async/k8s/v1/types.py +++ b/scaleway-async/scaleway_async/k8s/v1/types.py @@ -892,6 +892,11 @@ class Cluster: Additional Subject Alternative Names for the Kubernetes API server certificate. """ + iam_nodes_group_id: str + """ + IAM group that nodes are members of (this field might be empty during early stage of cluster creation). + """ + open_id_connect_config: Optional[ClusterOpenIDConnectConfig] """ This configuration enables to update the OpenID Connect configuration of the Kubernetes API server. diff --git a/scaleway/scaleway/k8s/v1/marshalling.py b/scaleway/scaleway/k8s/v1/marshalling.py index da0ede590..558cd4cb8 100644 --- a/scaleway/scaleway/k8s/v1/marshalling.py +++ b/scaleway/scaleway/k8s/v1/marshalling.py @@ -468,6 +468,10 @@ def unmarshal_Cluster(data: Any) -> Cluster: if field is not None: args["apiserver_cert_sans"] = field + field = data.get("iam_nodes_group_id", None) + if field is not None: + args["iam_nodes_group_id"] = field + field = data.get("open_id_connect_config", None) if field is not None: args["open_id_connect_config"] = unmarshal_ClusterOpenIDConnectConfig(field) diff --git a/scaleway/scaleway/k8s/v1/types.py b/scaleway/scaleway/k8s/v1/types.py index 248f66071..f979885ac 100644 --- a/scaleway/scaleway/k8s/v1/types.py +++ b/scaleway/scaleway/k8s/v1/types.py @@ -892,6 +892,11 @@ class Cluster: Additional Subject Alternative Names for the Kubernetes API server certificate. """ + iam_nodes_group_id: str + """ + IAM group that nodes are members of (this field might be empty during early stage of cluster creation). + """ + open_id_connect_config: Optional[ClusterOpenIDConnectConfig] """ This configuration enables to update the OpenID Connect configuration of the Kubernetes API server.