From 395682b90b5138fe733c59b644a78ad371e5ffad Mon Sep 17 00:00:00 2001 From: Estelle Soulard Date: Wed, 25 Mar 2026 13:51:40 +0100 Subject: [PATCH 1/2] chore: formatting --- .../applesilicon/v1alpha1/api.py | 5 +- .../container/v1beta1/marshalling.py | 18 +++---- .../scaleway_async/dedibox/v1/api.py | 4 +- .../domain/v2beta1/marshalling.py | 28 +++++------ .../function/v1beta1/marshalling.py | 12 ++--- .../scaleway_async/interlink/v1beta1/api.py | 4 +- .../scaleway_async/lb/v1/marshalling.py | 12 ++--- scaleway-async/scaleway_async/vpcgw/v1/api.py | 4 +- scaleway-async/scaleway_async/vpcgw/v2/api.py | 4 +- .../webhosting/v1/marshalling.py | 12 ++--- .../scaleway/applesilicon/v1alpha1/api.py | 5 +- .../scaleway/container/v1beta1/marshalling.py | 18 +++---- scaleway/scaleway/dedibox/v1/api.py | 4 +- .../scaleway/domain/v2beta1/marshalling.py | 16 +++---- .../scaleway/function/v1beta1/marshalling.py | 18 +++---- scaleway/scaleway/instance/v1/custom_api.py | 4 +- scaleway/scaleway/interlink/v1beta1/api.py | 4 +- scaleway/scaleway/lb/v1/marshalling.py | 48 +++++++++---------- scaleway/scaleway/vpcgw/v1/api.py | 4 +- scaleway/scaleway/vpcgw/v2/api.py | 4 +- .../scaleway/webhosting/v1/marshalling.py | 12 ++--- 21 files changed, 119 insertions(+), 121 deletions(-) diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py index 8e0879e09..8a49e6f15 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py @@ -1106,9 +1106,8 @@ async def wait_for_server_private_network( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status - not in SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES ) return await wait_for_resource_async( diff --git a/scaleway-async/scaleway_async/container/v1beta1/marshalling.py b/scaleway-async/scaleway_async/container/v1beta1/marshalling.py index e444dd2d3..ff8bb1cd5 100644 --- a/scaleway-async/scaleway_async/container/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/container/v1beta1/marshalling.py @@ -610,12 +610,6 @@ def unmarshal_Token(data: Any) -> Token: else: args["token"] = None - field = data.get("public_key", None) - if field is not None: - args["public_key"] = field - else: - args["public_key"] = None - field = data.get("status", None) if field is not None: args["status"] = field @@ -634,6 +628,12 @@ def unmarshal_Token(data: Any) -> Token: else: args["namespace_id"] = None + field = data.get("public_key", None) + if field is not None: + args["public_key"] = field + else: + args["public_key"] = None + field = data.get("description", None) if field is not None: args["description"] = field @@ -1208,9 +1208,6 @@ def marshal_CreateNamespaceRequest( ) -> dict[str, Any]: output: dict[str, Any] = {} - if request.activate_vpc_integration is not None: - output["activate_vpc_integration"] = request.activate_vpc_integration - if request.name is not None: output["name"] = request.name @@ -1234,6 +1231,9 @@ def marshal_CreateNamespaceRequest( if request.tags is not None: output["tags"] = request.tags + if request.activate_vpc_integration is not None: + output["activate_vpc_integration"] = request.activate_vpc_integration + return output diff --git a/scaleway-async/scaleway_async/dedibox/v1/api.py b/scaleway-async/scaleway_async/dedibox/v1/api.py index a6cf8a81a..90f3e71cb 100644 --- a/scaleway-async/scaleway_async/dedibox/v1/api.py +++ b/scaleway-async/scaleway_async/dedibox/v1/api.py @@ -1352,8 +1352,8 @@ async def wait_for_server_install( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status not in SERVER_INSTALL_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in SERVER_INSTALL_TRANSIENT_STATUSES ) return await wait_for_resource_async( diff --git a/scaleway-async/scaleway_async/domain/v2beta1/marshalling.py b/scaleway-async/scaleway_async/domain/v2beta1/marshalling.py index 1d0f4d082..b1df52ff7 100644 --- a/scaleway-async/scaleway_async/domain/v2beta1/marshalling.py +++ b/scaleway-async/scaleway_async/domain/v2beta1/marshalling.py @@ -316,6 +316,12 @@ def unmarshal_ContactExtensionIT(data: Any) -> ContactExtensionIT: args: dict[str, Any] = {} + field = data.get("pin", None) + if field is not None: + args["pin"] = field + else: + args["pin"] = None + field = data.get("european_citizenship", None) if field is not None: args["european_citizenship"] = field @@ -328,12 +334,6 @@ def unmarshal_ContactExtensionIT(data: Any) -> ContactExtensionIT: else: args["tax_code"] = None - field = data.get("pin", None) - if field is not None: - args["pin"] = field - else: - args["pin"] = None - return ContactExtensionIT(**args) @@ -3034,15 +3034,15 @@ def marshal_ContactExtensionIT( ) -> dict[str, Any]: output: dict[str, Any] = {} + if request.pin is not None: + output["pin"] = request.pin + if request.european_citizenship is not None: output["european_citizenship"] = request.european_citizenship if request.tax_code is not None: output["tax_code"] = request.tax_code - if request.pin is not None: - output["pin"] = request.pin - return output @@ -3132,11 +3132,6 @@ def marshal_NewContact( if request.whois_opt_in is not None: output["whois_opt_in"] = request.whois_opt_in - if request.questions is not None: - output["questions"] = [ - marshal_ContactQuestion(item, defaults) for item in request.questions - ] - if request.vat_identification_code is not None: output["vat_identification_code"] = request.vat_identification_code @@ -3166,6 +3161,11 @@ def marshal_NewContact( request.extension_it, defaults ) + if request.questions is not None: + output["questions"] = [ + marshal_ContactQuestion(item, defaults) for item in request.questions + ] + return output diff --git a/scaleway-async/scaleway_async/function/v1beta1/marshalling.py b/scaleway-async/scaleway_async/function/v1beta1/marshalling.py index 9df8e13b0..18f25111e 100644 --- a/scaleway-async/scaleway_async/function/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/function/v1beta1/marshalling.py @@ -484,12 +484,6 @@ def unmarshal_Token(data: Any) -> Token: else: args["token"] = None - field = data.get("public_key", None) - if field is not None: - args["public_key"] = field - else: - args["public_key"] = None - field = data.get("status", None) if field is not None: args["status"] = field @@ -508,6 +502,12 @@ def unmarshal_Token(data: Any) -> Token: else: args["namespace_id"] = None + field = data.get("public_key", None) + if field is not None: + args["public_key"] = field + else: + args["public_key"] = None + field = data.get("description", None) if field is not None: args["description"] = field diff --git a/scaleway-async/scaleway_async/interlink/v1beta1/api.py b/scaleway-async/scaleway_async/interlink/v1beta1/api.py index e0ac46b7e..f2140b4ec 100644 --- a/scaleway-async/scaleway_async/interlink/v1beta1/api.py +++ b/scaleway-async/scaleway_async/interlink/v1beta1/api.py @@ -253,8 +253,8 @@ async def wait_for_dedicated_connection( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status not in DEDICATED_CONNECTION_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in DEDICATED_CONNECTION_TRANSIENT_STATUSES ) return await wait_for_resource_async( diff --git a/scaleway-async/scaleway_async/lb/v1/marshalling.py b/scaleway-async/scaleway_async/lb/v1/marshalling.py index 13215d66e..74c013a69 100644 --- a/scaleway-async/scaleway_async/lb/v1/marshalling.py +++ b/scaleway-async/scaleway_async/lb/v1/marshalling.py @@ -167,12 +167,6 @@ def unmarshal_Ip(data: Any) -> Ip: else: args["tags"] = [] - 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 @@ -185,6 +179,12 @@ def unmarshal_Ip(data: Any) -> Ip: else: args["lb_id"] = None + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + return Ip(**args) diff --git a/scaleway-async/scaleway_async/vpcgw/v1/api.py b/scaleway-async/scaleway_async/vpcgw/v1/api.py index abd53c64f..92d912273 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/api.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/api.py @@ -696,8 +696,8 @@ async def wait_for_gateway_network( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES ) return await wait_for_resource_async( diff --git a/scaleway-async/scaleway_async/vpcgw/v2/api.py b/scaleway-async/scaleway_async/vpcgw/v2/api.py index 7d104ab35..14e427605 100644 --- a/scaleway-async/scaleway_async/vpcgw/v2/api.py +++ b/scaleway-async/scaleway_async/vpcgw/v2/api.py @@ -630,8 +630,8 @@ async def wait_for_gateway_network( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES ) return await wait_for_resource_async( diff --git a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py index f2f8cdb38..44f87579b 100644 --- a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py +++ b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py @@ -1676,18 +1676,18 @@ def unmarshal_ResetHostingPasswordResponse(data: Any) -> ResetHostingPasswordRes args: dict[str, Any] = {} - field = data.get("one_time_password", None) - if field is not None: - args["one_time_password"] = field - else: - args["one_time_password"] = None - field = data.get("one_time_password_b64", None) if field is not None: args["one_time_password_b64"] = field else: args["one_time_password_b64"] = None + field = data.get("one_time_password", None) + if field is not None: + args["one_time_password"] = field + else: + args["one_time_password"] = None + return ResetHostingPasswordResponse(**args) diff --git a/scaleway/scaleway/applesilicon/v1alpha1/api.py b/scaleway/scaleway/applesilicon/v1alpha1/api.py index 00eca7991..1972f3ef8 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/api.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/api.py @@ -1104,9 +1104,8 @@ def wait_for_server_private_network( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status - not in SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES ) return wait_for_resource( diff --git a/scaleway/scaleway/container/v1beta1/marshalling.py b/scaleway/scaleway/container/v1beta1/marshalling.py index e444dd2d3..ff8bb1cd5 100644 --- a/scaleway/scaleway/container/v1beta1/marshalling.py +++ b/scaleway/scaleway/container/v1beta1/marshalling.py @@ -610,12 +610,6 @@ def unmarshal_Token(data: Any) -> Token: else: args["token"] = None - field = data.get("public_key", None) - if field is not None: - args["public_key"] = field - else: - args["public_key"] = None - field = data.get("status", None) if field is not None: args["status"] = field @@ -634,6 +628,12 @@ def unmarshal_Token(data: Any) -> Token: else: args["namespace_id"] = None + field = data.get("public_key", None) + if field is not None: + args["public_key"] = field + else: + args["public_key"] = None + field = data.get("description", None) if field is not None: args["description"] = field @@ -1208,9 +1208,6 @@ def marshal_CreateNamespaceRequest( ) -> dict[str, Any]: output: dict[str, Any] = {} - if request.activate_vpc_integration is not None: - output["activate_vpc_integration"] = request.activate_vpc_integration - if request.name is not None: output["name"] = request.name @@ -1234,6 +1231,9 @@ def marshal_CreateNamespaceRequest( if request.tags is not None: output["tags"] = request.tags + if request.activate_vpc_integration is not None: + output["activate_vpc_integration"] = request.activate_vpc_integration + return output diff --git a/scaleway/scaleway/dedibox/v1/api.py b/scaleway/scaleway/dedibox/v1/api.py index f11df7de9..88be35b11 100644 --- a/scaleway/scaleway/dedibox/v1/api.py +++ b/scaleway/scaleway/dedibox/v1/api.py @@ -1350,8 +1350,8 @@ def wait_for_server_install( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status not in SERVER_INSTALL_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in SERVER_INSTALL_TRANSIENT_STATUSES ) return wait_for_resource( diff --git a/scaleway/scaleway/domain/v2beta1/marshalling.py b/scaleway/scaleway/domain/v2beta1/marshalling.py index 1d0f4d082..c9b811602 100644 --- a/scaleway/scaleway/domain/v2beta1/marshalling.py +++ b/scaleway/scaleway/domain/v2beta1/marshalling.py @@ -3034,15 +3034,15 @@ def marshal_ContactExtensionIT( ) -> dict[str, Any]: output: dict[str, Any] = {} + if request.pin is not None: + output["pin"] = request.pin + if request.european_citizenship is not None: output["european_citizenship"] = request.european_citizenship if request.tax_code is not None: output["tax_code"] = request.tax_code - if request.pin is not None: - output["pin"] = request.pin - return output @@ -3132,11 +3132,6 @@ def marshal_NewContact( if request.whois_opt_in is not None: output["whois_opt_in"] = request.whois_opt_in - if request.questions is not None: - output["questions"] = [ - marshal_ContactQuestion(item, defaults) for item in request.questions - ] - if request.vat_identification_code is not None: output["vat_identification_code"] = request.vat_identification_code @@ -3166,6 +3161,11 @@ def marshal_NewContact( request.extension_it, defaults ) + if request.questions is not None: + output["questions"] = [ + marshal_ContactQuestion(item, defaults) for item in request.questions + ] + return output diff --git a/scaleway/scaleway/function/v1beta1/marshalling.py b/scaleway/scaleway/function/v1beta1/marshalling.py index 9df8e13b0..fac78836f 100644 --- a/scaleway/scaleway/function/v1beta1/marshalling.py +++ b/scaleway/scaleway/function/v1beta1/marshalling.py @@ -484,12 +484,6 @@ def unmarshal_Token(data: Any) -> Token: else: args["token"] = None - field = data.get("public_key", None) - if field is not None: - args["public_key"] = field - else: - args["public_key"] = None - field = data.get("status", None) if field is not None: args["status"] = field @@ -508,6 +502,12 @@ def unmarshal_Token(data: Any) -> Token: else: args["namespace_id"] = None + field = data.get("public_key", None) + if field is not None: + args["public_key"] = field + else: + args["public_key"] = None + field = data.get("description", None) if field is not None: args["description"] = field @@ -1114,9 +1114,6 @@ def marshal_CreateNamespaceRequest( ) -> dict[str, Any]: output: dict[str, Any] = {} - if request.activate_vpc_integration is not None: - output["activate_vpc_integration"] = request.activate_vpc_integration - if request.name is not None: output["name"] = request.name @@ -1140,6 +1137,9 @@ def marshal_CreateNamespaceRequest( if request.tags is not None: output["tags"] = request.tags + if request.activate_vpc_integration is not None: + output["activate_vpc_integration"] = request.activate_vpc_integration + return output diff --git a/scaleway/scaleway/instance/v1/custom_api.py b/scaleway/scaleway/instance/v1/custom_api.py index 853dcc7af..5c85e86f7 100644 --- a/scaleway/scaleway/instance/v1/custom_api.py +++ b/scaleway/scaleway/instance/v1/custom_api.py @@ -111,7 +111,7 @@ def set_all_server_user_data( server_id: str, user_data: Dict[str, bytes], zone: Optional[ScwZone] = None, - ) -> Optional[None]: + ) -> None: param_zone = validate_path_param("zone", zone or self.client.default_zone) param_server_id = validate_path_param("server_id", server_id) @@ -134,7 +134,7 @@ def set_all_server_user_data( content=user_data[key], ) - return None + return def wait_instance_server(self, server_id: str, zone: ScwZone) -> GetServerResponse: wait_interval = interval diff --git a/scaleway/scaleway/interlink/v1beta1/api.py b/scaleway/scaleway/interlink/v1beta1/api.py index cb5ce9d15..225646c9c 100644 --- a/scaleway/scaleway/interlink/v1beta1/api.py +++ b/scaleway/scaleway/interlink/v1beta1/api.py @@ -251,8 +251,8 @@ def wait_for_dedicated_connection( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status not in DEDICATED_CONNECTION_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in DEDICATED_CONNECTION_TRANSIENT_STATUSES ) return wait_for_resource( diff --git a/scaleway/scaleway/lb/v1/marshalling.py b/scaleway/scaleway/lb/v1/marshalling.py index 13215d66e..649132581 100644 --- a/scaleway/scaleway/lb/v1/marshalling.py +++ b/scaleway/scaleway/lb/v1/marshalling.py @@ -167,12 +167,6 @@ def unmarshal_Ip(data: Any) -> Ip: else: args["tags"] = [] - 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 @@ -185,6 +179,12 @@ def unmarshal_Ip(data: Any) -> Ip: else: args["lb_id"] = None + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + return Ip(**args) @@ -515,12 +515,6 @@ def unmarshal_Instance(data: Any) -> Instance: else: args["ip_address"] = 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 @@ -539,6 +533,12 @@ def unmarshal_Instance(data: Any) -> Instance: else: args["updated_at"] = None + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + return Instance(**args) @@ -644,12 +644,6 @@ def unmarshal_Lb(data: Any) -> Lb: else: args["route_count"] = 0 - 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 @@ -674,6 +668,12 @@ def unmarshal_Lb(data: Any) -> Lb: else: args["updated_at"] = None + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + return Lb(**args) @@ -1645,18 +1645,18 @@ def unmarshal_LbType(data: Any) -> LbType: else: args["description"] = 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("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + return LbType(**args) diff --git a/scaleway/scaleway/vpcgw/v1/api.py b/scaleway/scaleway/vpcgw/v1/api.py index b04c7a0c1..7fa509d97 100644 --- a/scaleway/scaleway/vpcgw/v1/api.py +++ b/scaleway/scaleway/vpcgw/v1/api.py @@ -694,8 +694,8 @@ def wait_for_gateway_network( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES ) return wait_for_resource( diff --git a/scaleway/scaleway/vpcgw/v2/api.py b/scaleway/scaleway/vpcgw/v2/api.py index 29ee499ca..102253a73 100644 --- a/scaleway/scaleway/vpcgw/v2/api.py +++ b/scaleway/scaleway/vpcgw/v2/api.py @@ -628,8 +628,8 @@ def wait_for_gateway_network( options = WaitForOptions() if not options.stop: - options.stop = ( - lambda res: res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES + options.stop = lambda res: ( + res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES ) return wait_for_resource( diff --git a/scaleway/scaleway/webhosting/v1/marshalling.py b/scaleway/scaleway/webhosting/v1/marshalling.py index f2f8cdb38..44f87579b 100644 --- a/scaleway/scaleway/webhosting/v1/marshalling.py +++ b/scaleway/scaleway/webhosting/v1/marshalling.py @@ -1676,18 +1676,18 @@ def unmarshal_ResetHostingPasswordResponse(data: Any) -> ResetHostingPasswordRes args: dict[str, Any] = {} - field = data.get("one_time_password", None) - if field is not None: - args["one_time_password"] = field - else: - args["one_time_password"] = None - field = data.get("one_time_password_b64", None) if field is not None: args["one_time_password_b64"] = field else: args["one_time_password_b64"] = None + field = data.get("one_time_password", None) + if field is not None: + args["one_time_password"] = field + else: + args["one_time_password"] = None + return ResetHostingPasswordResponse(**args) From 7c52eacdc3e7a2ad2c3ea28ea102b4bc0b7948ab Mon Sep 17 00:00:00 2001 From: Estelle Soulard Date: Wed, 25 Mar 2026 15:30:35 +0100 Subject: [PATCH 2/2] feat(serverless_jobs): add triggers of type cron --- .../scaleway_async/jobs/v1alpha2/__init__.py | 22 ++ .../scaleway_async/jobs/v1alpha2/api.py | 252 ++++++++++++ .../jobs/v1alpha2/marshalling.py | 205 ++++++++++ .../scaleway_async/jobs/v1alpha2/types.py | 358 ++++++++++++++++++ scaleway/scaleway/jobs/v1alpha2/__init__.py | 22 ++ scaleway/scaleway/jobs/v1alpha2/api.py | 252 ++++++++++++ .../scaleway/jobs/v1alpha2/marshalling.py | 205 ++++++++++ scaleway/scaleway/jobs/v1alpha2/types.py | 358 ++++++++++++++++++ 8 files changed, 1674 insertions(+) diff --git a/scaleway-async/scaleway_async/jobs/v1alpha2/__init__.py b/scaleway-async/scaleway_async/jobs/v1alpha2/__init__.py index 453c9acd3..1e3d1ebdc 100644 --- a/scaleway-async/scaleway_async/jobs/v1alpha2/__init__.py +++ b/scaleway-async/scaleway_async/jobs/v1alpha2/__init__.py @@ -5,26 +5,34 @@ from .content import JOB_RUN_TRANSIENT_STATUSES from .types import ListJobDefinitionsRequestOrderBy from .types import ListJobRunsRequestOrderBy +from .types import ListTriggersRequestOrderBy from .types import SecretEnvVar from .types import SecretFile from .types import CronSchedule from .types import RetryPolicy +from .types import TriggerCronConfig from .types import CreateJobDefinitionRequestCronScheduleConfig from .types import CreateSecretsRequestSecretConfig from .types import Secret +from .types import CreateTriggerRequestCronConfig from .types import JobDefinition from .types import Resource from .types import JobRun +from .types import Trigger from .types import UpdateJobDefinitionRequestCronScheduleConfig +from .types import UpdateTriggerRequestCronConfig from .types import CreateJobDefinitionRequest from .types import CreateSecretsRequest from .types import CreateSecretsResponse +from .types import CreateTriggerRequest from .types import DeleteJobDefinitionRequest from .types import DeleteSecretRequest +from .types import DeleteTriggerRequest from .types import GetJobDefinitionRequest from .types import GetJobLimitsRequest from .types import GetJobRunRequest from .types import GetSecretRequest +from .types import GetTriggerRequest from .types import JobLimits from .types import ListJobDefinitionsRequest from .types import ListJobDefinitionsResponse @@ -34,11 +42,14 @@ from .types import ListJobRunsResponse from .types import ListSecretsRequest from .types import ListSecretsResponse +from .types import ListTriggersRequest +from .types import ListTriggersResponse from .types import StartJobDefinitionRequest from .types import StartJobDefinitionResponse from .types import StopJobRunRequest from .types import UpdateJobDefinitionRequest from .types import UpdateSecretRequest +from .types import UpdateTriggerRequest from .api import JobsV1Alpha2API __all__ = [ @@ -47,26 +58,34 @@ "JOB_RUN_TRANSIENT_STATUSES", "ListJobDefinitionsRequestOrderBy", "ListJobRunsRequestOrderBy", + "ListTriggersRequestOrderBy", "SecretEnvVar", "SecretFile", "CronSchedule", "RetryPolicy", + "TriggerCronConfig", "CreateJobDefinitionRequestCronScheduleConfig", "CreateSecretsRequestSecretConfig", "Secret", + "CreateTriggerRequestCronConfig", "JobDefinition", "Resource", "JobRun", + "Trigger", "UpdateJobDefinitionRequestCronScheduleConfig", + "UpdateTriggerRequestCronConfig", "CreateJobDefinitionRequest", "CreateSecretsRequest", "CreateSecretsResponse", + "CreateTriggerRequest", "DeleteJobDefinitionRequest", "DeleteSecretRequest", + "DeleteTriggerRequest", "GetJobDefinitionRequest", "GetJobLimitsRequest", "GetJobRunRequest", "GetSecretRequest", + "GetTriggerRequest", "JobLimits", "ListJobDefinitionsRequest", "ListJobDefinitionsResponse", @@ -76,10 +95,13 @@ "ListJobRunsResponse", "ListSecretsRequest", "ListSecretsResponse", + "ListTriggersRequest", + "ListTriggersResponse", "StartJobDefinitionRequest", "StartJobDefinitionResponse", "StopJobRunRequest", "UpdateJobDefinitionRequest", "UpdateSecretRequest", + "UpdateTriggerRequest", "JobsV1Alpha2API", ] diff --git a/scaleway-async/scaleway_async/jobs/v1alpha2/api.py b/scaleway-async/scaleway_async/jobs/v1alpha2/api.py index 0057f5cf8..4a7c69ded 100644 --- a/scaleway-async/scaleway_async/jobs/v1alpha2/api.py +++ b/scaleway-async/scaleway_async/jobs/v1alpha2/api.py @@ -17,11 +17,14 @@ JobRunState, ListJobDefinitionsRequestOrderBy, ListJobRunsRequestOrderBy, + ListTriggersRequestOrderBy, CreateJobDefinitionRequest, CreateJobDefinitionRequestCronScheduleConfig, CreateSecretsRequest, CreateSecretsRequestSecretConfig, CreateSecretsResponse, + CreateTriggerRequest, + CreateTriggerRequestCronConfig, JobDefinition, JobLimits, JobRun, @@ -29,30 +32,38 @@ ListJobResourcesResponse, ListJobRunsResponse, ListSecretsResponse, + ListTriggersResponse, RetryPolicy, Secret, StartJobDefinitionRequest, StartJobDefinitionResponse, + Trigger, UpdateJobDefinitionRequest, UpdateJobDefinitionRequestCronScheduleConfig, UpdateSecretRequest, + UpdateTriggerRequest, + UpdateTriggerRequestCronConfig, ) from .marshalling import ( unmarshal_Secret, unmarshal_JobDefinition, unmarshal_JobRun, + unmarshal_Trigger, unmarshal_CreateSecretsResponse, unmarshal_JobLimits, unmarshal_ListJobDefinitionsResponse, unmarshal_ListJobResourcesResponse, unmarshal_ListJobRunsResponse, unmarshal_ListSecretsResponse, + unmarshal_ListTriggersResponse, unmarshal_StartJobDefinitionResponse, marshal_CreateJobDefinitionRequest, marshal_CreateSecretsRequest, + marshal_CreateTriggerRequest, marshal_StartJobDefinitionRequest, marshal_UpdateJobDefinitionRequest, marshal_UpdateSecretRequest, + marshal_UpdateTriggerRequest, ) @@ -814,6 +825,247 @@ async def delete_secret( self._throw_on_error(res) + async def create_trigger( + self, + *, + job_definition_id: str, + name: str, + region: Optional[ScwRegion] = None, + cron_config: Optional[CreateTriggerRequestCronConfig] = None, + ) -> Trigger: + """ + Create a trigger. + :param job_definition_id: UUID of the job definition. + :param name: Name of the trigger. + :param region: Region to target. If none is passed will use default region from the config. + :param cron_config: Configuration of the CRON trigger. + One-Of ('config'): at most one of 'cron_config' could be set. + :return: :class:`Trigger ` + + Usage: + :: + + result = await api.create_trigger( + job_definition_id="example", + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers", + body=marshal_CreateTriggerRequest( + CreateTriggerRequest( + job_definition_id=job_definition_id, + name=name, + region=region, + cron_config=cron_config, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Trigger(res.json()) + + async def get_trigger( + self, + *, + trigger_id: str, + region: Optional[ScwRegion] = None, + ) -> Trigger: + """ + Get a trigger. + :param trigger_id: UUID of the trigger. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Trigger ` + + Usage: + :: + + result = await api.get_trigger( + trigger_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_trigger_id = validate_path_param("trigger_id", trigger_id) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers/{param_trigger_id}", + ) + + self._throw_on_error(res) + return unmarshal_Trigger(res.json()) + + async def list_triggers( + self, + *, + job_definition_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListTriggersRequestOrderBy] = None, + ) -> ListTriggersResponse: + """ + List triggers of a job definition. + :param job_definition_id: UUID of the job definition. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number from paginated list of triggers. + :param page_size: Number of triggers per page. + :param order_by: Sorting order of triggers. + :return: :class:`ListTriggersResponse ` + + Usage: + :: + + result = await api.list_triggers( + job_definition_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers", + params={ + "job_definition_id": job_definition_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTriggersResponse(res.json()) + + async def list_triggers_all( + self, + *, + job_definition_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListTriggersRequestOrderBy] = None, + ) -> list[Trigger]: + """ + List triggers of a job definition. + :param job_definition_id: UUID of the job definition. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number from paginated list of triggers. + :param page_size: Number of triggers per page. + :param order_by: Sorting order of triggers. + :return: :class:`list[Trigger] ` + + Usage: + :: + + result = await api.list_triggers_all( + job_definition_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListTriggersResponse, + key="triggers", + fetcher=self.list_triggers, + args={ + "job_definition_id": job_definition_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + async def update_trigger( + self, + *, + trigger_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + cron_config: Optional[UpdateTriggerRequestCronConfig] = None, + ) -> Trigger: + """ + Update a trigger. + :param trigger_id: UUID of the trigger. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the trigger. + :param cron_config: Configuration of the CRON trigger. + One-Of ('config'): at most one of 'cron_config' could be set. + :return: :class:`Trigger ` + + Usage: + :: + + result = await api.update_trigger( + trigger_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_trigger_id = validate_path_param("trigger_id", trigger_id) + + res = self._request( + "PATCH", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers/{param_trigger_id}", + body=marshal_UpdateTriggerRequest( + UpdateTriggerRequest( + trigger_id=trigger_id, + region=region, + name=name, + cron_config=cron_config, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Trigger(res.json()) + + async def delete_trigger( + self, + *, + trigger_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a trigger. + :param trigger_id: UUID of the trigger. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_trigger( + trigger_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_trigger_id = validate_path_param("trigger_id", trigger_id) + + res = self._request( + "DELETE", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers/{param_trigger_id}", + ) + + self._throw_on_error(res) + async def list_job_resources( self, *, diff --git a/scaleway-async/scaleway_async/jobs/v1alpha2/marshalling.py b/scaleway-async/scaleway_async/jobs/v1alpha2/marshalling.py index 6d4729d1e..aad89ee91 100644 --- a/scaleway-async/scaleway_async/jobs/v1alpha2/marshalling.py +++ b/scaleway-async/scaleway_async/jobs/v1alpha2/marshalling.py @@ -17,6 +17,8 @@ RetryPolicy, JobDefinition, JobRun, + TriggerCronConfig, + Trigger, CreateSecretsResponse, JobLimits, ListJobDefinitionsResponse, @@ -24,15 +26,20 @@ ListJobResourcesResponse, ListJobRunsResponse, ListSecretsResponse, + ListTriggersResponse, StartJobDefinitionResponse, CreateJobDefinitionRequestCronScheduleConfig, CreateJobDefinitionRequest, CreateSecretsRequestSecretConfig, CreateSecretsRequest, + CreateTriggerRequestCronConfig, + CreateTriggerRequest, StartJobDefinitionRequest, UpdateJobDefinitionRequestCronScheduleConfig, UpdateJobDefinitionRequest, UpdateSecretRequest, + UpdateTriggerRequestCronConfig, + UpdateTriggerRequest, ) @@ -409,6 +416,88 @@ def unmarshal_JobRun(data: Any) -> JobRun: return JobRun(**args) +def unmarshal_TriggerCronConfig(data: Any) -> TriggerCronConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TriggerCronConfig' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("schedule", None) + if field is not None: + args["schedule"] = field + else: + args["schedule"] = None + + field = data.get("timezone", None) + if field is not None: + args["timezone"] = field + else: + args["timezone"] = None + + field = data.get("startup_command", None) + if field is not None: + args["startup_command"] = field + else: + args["startup_command"] = [] + + field = data.get("args", None) + if field is not None: + args["args"] = field + else: + args["args"] = [] + + return TriggerCronConfig(**args) + + +def unmarshal_Trigger(data: Any) -> Trigger: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Trigger' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + else: + args["id"] = None + + field = data.get("job_definition_id", None) + if field is not None: + args["job_definition_id"] = field + else: + args["job_definition_id"] = None + + field = data.get("name", None) + if field is not None: + args["name"] = field + else: + args["name"] = 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("cron_config", None) + if field is not None: + args["cron_config"] = unmarshal_TriggerCronConfig(field) + else: + args["cron_config"] = None + + return Trigger(**args) + + def unmarshal_CreateSecretsResponse(data: Any) -> CreateSecretsResponse: if not isinstance(data, dict): raise TypeError( @@ -562,6 +651,31 @@ def unmarshal_ListSecretsResponse(data: Any) -> ListSecretsResponse: return ListSecretsResponse(**args) +def unmarshal_ListTriggersResponse(data: Any) -> ListTriggersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTriggersResponse' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("triggers", None) + if field is not None: + args["triggers"] = ( + [unmarshal_Trigger(v) for v in field] if field is not None else None + ) + else: + args["triggers"] = [] + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + else: + args["total_count"] = 0 + + return ListTriggersResponse(**args) + + def unmarshal_StartJobDefinitionResponse(data: Any) -> StartJobDefinitionResponse: if not isinstance(data, dict): raise TypeError( @@ -708,6 +822,53 @@ def marshal_CreateSecretsRequest( return output +def marshal_CreateTriggerRequestCronConfig( + request: CreateTriggerRequestCronConfig, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.schedule is not None: + output["schedule"] = request.schedule + + if request.timezone is not None: + output["timezone"] = request.timezone + + if request.startup_command is not None: + output["startup_command"] = request.startup_command + + if request.args is not None: + output["args"] = request.args + + return output + + +def marshal_CreateTriggerRequest( + request: CreateTriggerRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility( + param="cron_config", + value=request.cron_config, + marshal_func=marshal_CreateTriggerRequestCronConfig, + ), + ] + ), + ) + + if request.job_definition_id is not None: + output["job_definition_id"] = request.job_definition_id + + if request.name is not None: + output["name"] = request.name + + return output + + def marshal_StartJobDefinitionRequest( request: StartJobDefinitionRequest, defaults: ProfileDefaults, @@ -817,3 +978,47 @@ def marshal_UpdateSecretRequest( output["secret_manager_version"] = request.secret_manager_version return output + + +def marshal_UpdateTriggerRequestCronConfig( + request: UpdateTriggerRequestCronConfig, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.schedule is not None: + output["schedule"] = request.schedule + + if request.timezone is not None: + output["timezone"] = request.timezone + + if request.startup_command is not None: + output["startup_command"] = request.startup_command + + if request.args is not None: + output["args"] = request.args + + return output + + +def marshal_UpdateTriggerRequest( + request: UpdateTriggerRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility( + param="cron_config", + value=request.cron_config, + marshal_func=marshal_UpdateTriggerRequestCronConfig, + ), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + return output diff --git a/scaleway-async/scaleway_async/jobs/v1alpha2/types.py b/scaleway-async/scaleway_async/jobs/v1alpha2/types.py index 1f13dc4f4..9b40596af 100644 --- a/scaleway-async/scaleway_async/jobs/v1alpha2/types.py +++ b/scaleway-async/scaleway_async/jobs/v1alpha2/types.py @@ -66,6 +66,14 @@ def __str__(self) -> str: return str(self.value) +class ListTriggersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + @dataclass class SecretEnvVar: name: str @@ -97,6 +105,29 @@ class RetryPolicy: """ +@dataclass +class TriggerCronConfig: + schedule: str + """ + CRON schedule in UNIX format. + """ + + timezone: str + """ + Time zone for the CRON schedule. + """ + + startup_command: list[str] + """ + Startup command that will be used by the triggered job. + """ + + args: list[str] + """ + Arguments passed to the startup command used by the triggered job. + """ + + @dataclass class CreateJobDefinitionRequestCronScheduleConfig: schedule: str @@ -139,30 +170,120 @@ class Secret: env_var: Optional[SecretEnvVar] = None +@dataclass +class CreateTriggerRequestCronConfig: + schedule: str + """ + CRON schedule in UNIX format. + """ + + timezone: str + """ + Time zone for the CRON schedule. + """ + + startup_command: list[str] + """ + Startup command that will be used by the triggered job. + """ + + args: list[str] + """ + Arguments passed to the startup command used by the triggered job. + """ + + @dataclass class JobDefinition: id: str + """ + UUID of the job definition. + """ + name: str + """ + Name of the job definition. + """ + project_id: str + """ + UUID of the Scaleway Project containing the job. + """ + cpu_limit: int + """ + CPU limit of the job (in mvCPU). + """ + memory_limit: int + """ + Memory limit of the job (in MiB). + """ + local_storage_capacity: int + """ + Local storage capacity of the job (in MiB). + """ + image_uri: str + """ + Image to use for the job. + """ + environment_variables: dict[str, str] + """ + Environment variables of the job. + """ + description: str + """ + Description of the job. + """ + startup_command: list[str] + """ + Job startup command. + """ + args: list[str] + """ + Job arguments passed to the startup command at runtime. + """ + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ created_at: Optional[datetime] = None + """ + Creation date of the job definition. + """ + updated_at: Optional[datetime] = None + """ + Last update date of the job definition. + """ + command: Optional[str] = None + """ + Deprecated, please use startup_command instead. + """ + job_timeout: Optional[str] = None + """ + Timeout of the job in seconds. + """ + cron_schedule: Optional[CronSchedule] = None + """ + Configure a cron for the job. + """ + retry_policy: Optional[RetryPolicy] = None + """ + Retry behaviour in case of job failure. + """ @dataclass @@ -174,29 +295,134 @@ class Resource: @dataclass class JobRun: id: str + """ + UUID of the job run. + """ + job_definition_id: str + """ + UUID of the job definition. + """ + state: JobRunState + """ + State of the job run. + """ + cpu_limit: int + """ + CPU limit of the job (in mvCPU). + """ + memory_limit: int + """ + Memory limit of the job (in MiB). + """ + local_storage_capacity: int + """ + Local storage capacity of the job (in MiB). + """ + environment_variables: dict[str, str] + """ + Environment variables of the job run. + """ + startup_command: list[str] + """ + Job startup command. + """ + args: list[str] + """ + Job arguments passed to the startup command at runtime. + """ + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ created_at: Optional[datetime] = None + """ + Creation date of the job run. + """ + updated_at: Optional[datetime] = None + """ + Last update date of the job run. + """ + started_at: Optional[datetime] = None + """ + Start date of the job run. + """ + terminated_at: Optional[datetime] = None + """ + Termination date of the job run. + """ + run_duration: Optional[str] = None + """ + Duration of the job run. + """ + reason: Optional[JobRunReason] = None + """ + Reason for failure if the job failed. + """ + exit_code: Optional[int] = None + """ + Exit code of the job. + """ + error_message: Optional[str] = None + """ + Error message if the job failed. + """ + command: Optional[str] = None + """ + Deprecated, please use startup_command instead. + """ + attempts: Optional[int] = None + """ + Number of retry attempts. + """ + + +@dataclass +class Trigger: + id: str + """ + UUID of the trigger. + """ + + job_definition_id: str + """ + UUID of the job definition. + """ + + name: str + """ + Human readable name of the trigger. + """ + + created_at: Optional[datetime] = None + """ + Creation time of the trigger. + """ + + updated_at: Optional[datetime] = None + """ + Last update time of the trigger. + """ + + cron_config: Optional[TriggerCronConfig] = None @dataclass @@ -205,6 +431,29 @@ class UpdateJobDefinitionRequestCronScheduleConfig: timezone: Optional[str] = None +@dataclass +class UpdateTriggerRequestCronConfig: + schedule: Optional[str] = None + """ + CRON schedule in UNIX format. + """ + + timezone: Optional[str] = None + """ + Time zone for the CRON schedule. + """ + + startup_command: Optional[list[str]] = field(default_factory=list) + """ + Startup command that will be used by the triggered job. + """ + + args: Optional[list[str]] = field(default_factory=list) + """ + Arguments passed to the startup command used by the triggered job. + """ + + @dataclass class CreateJobDefinitionRequest: cpu_limit: int @@ -311,6 +560,26 @@ class CreateSecretsResponse: """ +@dataclass +class CreateTriggerRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + name: str + """ + Name of the trigger. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + cron_config: Optional[CreateTriggerRequestCronConfig] = None + + @dataclass class DeleteJobDefinitionRequest: job_definition_id: str @@ -337,6 +606,19 @@ class DeleteSecretRequest: """ +@dataclass +class DeleteTriggerRequest: + trigger_id: str + """ + UUID of the trigger. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class GetJobDefinitionRequest: job_definition_id: str @@ -384,6 +666,19 @@ class GetSecretRequest: """ +@dataclass +class GetTriggerRequest: + trigger_id: str + """ + UUID of the trigger. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class JobLimits: secrets_per_job_definition: int @@ -472,6 +767,49 @@ class ListSecretsResponse: """ +@dataclass +class ListTriggersRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] = 0 + """ + Page number from paginated list of triggers. + """ + + page_size: Optional[int] = 0 + """ + Number of triggers per page. + """ + + order_by: Optional[ListTriggersRequestOrderBy] = ( + ListTriggersRequestOrderBy.CREATED_AT_ASC + ) + """ + Sorting order of triggers. + """ + + +@dataclass +class ListTriggersResponse: + triggers: list[Trigger] + """ + List of triggers. + """ + + total_count: int + """ + Total count of triggers. + """ + + @dataclass class StartJobDefinitionRequest: job_definition_id: str @@ -636,3 +974,23 @@ class UpdateSecretRequest: path: Optional[str] = None env_var_name: Optional[str] = None + + +@dataclass +class UpdateTriggerRequest: + trigger_id: str + """ + UUID of the trigger. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] = None + """ + Name of the trigger. + """ + + cron_config: Optional[UpdateTriggerRequestCronConfig] = None diff --git a/scaleway/scaleway/jobs/v1alpha2/__init__.py b/scaleway/scaleway/jobs/v1alpha2/__init__.py index 453c9acd3..1e3d1ebdc 100644 --- a/scaleway/scaleway/jobs/v1alpha2/__init__.py +++ b/scaleway/scaleway/jobs/v1alpha2/__init__.py @@ -5,26 +5,34 @@ from .content import JOB_RUN_TRANSIENT_STATUSES from .types import ListJobDefinitionsRequestOrderBy from .types import ListJobRunsRequestOrderBy +from .types import ListTriggersRequestOrderBy from .types import SecretEnvVar from .types import SecretFile from .types import CronSchedule from .types import RetryPolicy +from .types import TriggerCronConfig from .types import CreateJobDefinitionRequestCronScheduleConfig from .types import CreateSecretsRequestSecretConfig from .types import Secret +from .types import CreateTriggerRequestCronConfig from .types import JobDefinition from .types import Resource from .types import JobRun +from .types import Trigger from .types import UpdateJobDefinitionRequestCronScheduleConfig +from .types import UpdateTriggerRequestCronConfig from .types import CreateJobDefinitionRequest from .types import CreateSecretsRequest from .types import CreateSecretsResponse +from .types import CreateTriggerRequest from .types import DeleteJobDefinitionRequest from .types import DeleteSecretRequest +from .types import DeleteTriggerRequest from .types import GetJobDefinitionRequest from .types import GetJobLimitsRequest from .types import GetJobRunRequest from .types import GetSecretRequest +from .types import GetTriggerRequest from .types import JobLimits from .types import ListJobDefinitionsRequest from .types import ListJobDefinitionsResponse @@ -34,11 +42,14 @@ from .types import ListJobRunsResponse from .types import ListSecretsRequest from .types import ListSecretsResponse +from .types import ListTriggersRequest +from .types import ListTriggersResponse from .types import StartJobDefinitionRequest from .types import StartJobDefinitionResponse from .types import StopJobRunRequest from .types import UpdateJobDefinitionRequest from .types import UpdateSecretRequest +from .types import UpdateTriggerRequest from .api import JobsV1Alpha2API __all__ = [ @@ -47,26 +58,34 @@ "JOB_RUN_TRANSIENT_STATUSES", "ListJobDefinitionsRequestOrderBy", "ListJobRunsRequestOrderBy", + "ListTriggersRequestOrderBy", "SecretEnvVar", "SecretFile", "CronSchedule", "RetryPolicy", + "TriggerCronConfig", "CreateJobDefinitionRequestCronScheduleConfig", "CreateSecretsRequestSecretConfig", "Secret", + "CreateTriggerRequestCronConfig", "JobDefinition", "Resource", "JobRun", + "Trigger", "UpdateJobDefinitionRequestCronScheduleConfig", + "UpdateTriggerRequestCronConfig", "CreateJobDefinitionRequest", "CreateSecretsRequest", "CreateSecretsResponse", + "CreateTriggerRequest", "DeleteJobDefinitionRequest", "DeleteSecretRequest", + "DeleteTriggerRequest", "GetJobDefinitionRequest", "GetJobLimitsRequest", "GetJobRunRequest", "GetSecretRequest", + "GetTriggerRequest", "JobLimits", "ListJobDefinitionsRequest", "ListJobDefinitionsResponse", @@ -76,10 +95,13 @@ "ListJobRunsResponse", "ListSecretsRequest", "ListSecretsResponse", + "ListTriggersRequest", + "ListTriggersResponse", "StartJobDefinitionRequest", "StartJobDefinitionResponse", "StopJobRunRequest", "UpdateJobDefinitionRequest", "UpdateSecretRequest", + "UpdateTriggerRequest", "JobsV1Alpha2API", ] diff --git a/scaleway/scaleway/jobs/v1alpha2/api.py b/scaleway/scaleway/jobs/v1alpha2/api.py index ee6b54cc8..ac07f12ed 100644 --- a/scaleway/scaleway/jobs/v1alpha2/api.py +++ b/scaleway/scaleway/jobs/v1alpha2/api.py @@ -17,11 +17,14 @@ JobRunState, ListJobDefinitionsRequestOrderBy, ListJobRunsRequestOrderBy, + ListTriggersRequestOrderBy, CreateJobDefinitionRequest, CreateJobDefinitionRequestCronScheduleConfig, CreateSecretsRequest, CreateSecretsRequestSecretConfig, CreateSecretsResponse, + CreateTriggerRequest, + CreateTriggerRequestCronConfig, JobDefinition, JobLimits, JobRun, @@ -29,30 +32,38 @@ ListJobResourcesResponse, ListJobRunsResponse, ListSecretsResponse, + ListTriggersResponse, RetryPolicy, Secret, StartJobDefinitionRequest, StartJobDefinitionResponse, + Trigger, UpdateJobDefinitionRequest, UpdateJobDefinitionRequestCronScheduleConfig, UpdateSecretRequest, + UpdateTriggerRequest, + UpdateTriggerRequestCronConfig, ) from .marshalling import ( unmarshal_Secret, unmarshal_JobDefinition, unmarshal_JobRun, + unmarshal_Trigger, unmarshal_CreateSecretsResponse, unmarshal_JobLimits, unmarshal_ListJobDefinitionsResponse, unmarshal_ListJobResourcesResponse, unmarshal_ListJobRunsResponse, unmarshal_ListSecretsResponse, + unmarshal_ListTriggersResponse, unmarshal_StartJobDefinitionResponse, marshal_CreateJobDefinitionRequest, marshal_CreateSecretsRequest, + marshal_CreateTriggerRequest, marshal_StartJobDefinitionRequest, marshal_UpdateJobDefinitionRequest, marshal_UpdateSecretRequest, + marshal_UpdateTriggerRequest, ) @@ -814,6 +825,247 @@ def delete_secret( self._throw_on_error(res) + def create_trigger( + self, + *, + job_definition_id: str, + name: str, + region: Optional[ScwRegion] = None, + cron_config: Optional[CreateTriggerRequestCronConfig] = None, + ) -> Trigger: + """ + Create a trigger. + :param job_definition_id: UUID of the job definition. + :param name: Name of the trigger. + :param region: Region to target. If none is passed will use default region from the config. + :param cron_config: Configuration of the CRON trigger. + One-Of ('config'): at most one of 'cron_config' could be set. + :return: :class:`Trigger ` + + Usage: + :: + + result = api.create_trigger( + job_definition_id="example", + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers", + body=marshal_CreateTriggerRequest( + CreateTriggerRequest( + job_definition_id=job_definition_id, + name=name, + region=region, + cron_config=cron_config, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Trigger(res.json()) + + def get_trigger( + self, + *, + trigger_id: str, + region: Optional[ScwRegion] = None, + ) -> Trigger: + """ + Get a trigger. + :param trigger_id: UUID of the trigger. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Trigger ` + + Usage: + :: + + result = api.get_trigger( + trigger_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_trigger_id = validate_path_param("trigger_id", trigger_id) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers/{param_trigger_id}", + ) + + self._throw_on_error(res) + return unmarshal_Trigger(res.json()) + + def list_triggers( + self, + *, + job_definition_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListTriggersRequestOrderBy] = None, + ) -> ListTriggersResponse: + """ + List triggers of a job definition. + :param job_definition_id: UUID of the job definition. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number from paginated list of triggers. + :param page_size: Number of triggers per page. + :param order_by: Sorting order of triggers. + :return: :class:`ListTriggersResponse ` + + Usage: + :: + + result = api.list_triggers( + job_definition_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers", + params={ + "job_definition_id": job_definition_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTriggersResponse(res.json()) + + def list_triggers_all( + self, + *, + job_definition_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListTriggersRequestOrderBy] = None, + ) -> list[Trigger]: + """ + List triggers of a job definition. + :param job_definition_id: UUID of the job definition. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number from paginated list of triggers. + :param page_size: Number of triggers per page. + :param order_by: Sorting order of triggers. + :return: :class:`list[Trigger] ` + + Usage: + :: + + result = api.list_triggers_all( + job_definition_id="example", + ) + """ + + return fetch_all_pages( + type=ListTriggersResponse, + key="triggers", + fetcher=self.list_triggers, + args={ + "job_definition_id": job_definition_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + def update_trigger( + self, + *, + trigger_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + cron_config: Optional[UpdateTriggerRequestCronConfig] = None, + ) -> Trigger: + """ + Update a trigger. + :param trigger_id: UUID of the trigger. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the trigger. + :param cron_config: Configuration of the CRON trigger. + One-Of ('config'): at most one of 'cron_config' could be set. + :return: :class:`Trigger ` + + Usage: + :: + + result = api.update_trigger( + trigger_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_trigger_id = validate_path_param("trigger_id", trigger_id) + + res = self._request( + "PATCH", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers/{param_trigger_id}", + body=marshal_UpdateTriggerRequest( + UpdateTriggerRequest( + trigger_id=trigger_id, + region=region, + name=name, + cron_config=cron_config, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Trigger(res.json()) + + def delete_trigger( + self, + *, + trigger_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a trigger. + :param trigger_id: UUID of the trigger. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_trigger( + trigger_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_trigger_id = validate_path_param("trigger_id", trigger_id) + + res = self._request( + "DELETE", + f"/serverless-jobs/v1alpha2/regions/{param_region}/triggers/{param_trigger_id}", + ) + + self._throw_on_error(res) + def list_job_resources( self, *, diff --git a/scaleway/scaleway/jobs/v1alpha2/marshalling.py b/scaleway/scaleway/jobs/v1alpha2/marshalling.py index 6d4729d1e..aad89ee91 100644 --- a/scaleway/scaleway/jobs/v1alpha2/marshalling.py +++ b/scaleway/scaleway/jobs/v1alpha2/marshalling.py @@ -17,6 +17,8 @@ RetryPolicy, JobDefinition, JobRun, + TriggerCronConfig, + Trigger, CreateSecretsResponse, JobLimits, ListJobDefinitionsResponse, @@ -24,15 +26,20 @@ ListJobResourcesResponse, ListJobRunsResponse, ListSecretsResponse, + ListTriggersResponse, StartJobDefinitionResponse, CreateJobDefinitionRequestCronScheduleConfig, CreateJobDefinitionRequest, CreateSecretsRequestSecretConfig, CreateSecretsRequest, + CreateTriggerRequestCronConfig, + CreateTriggerRequest, StartJobDefinitionRequest, UpdateJobDefinitionRequestCronScheduleConfig, UpdateJobDefinitionRequest, UpdateSecretRequest, + UpdateTriggerRequestCronConfig, + UpdateTriggerRequest, ) @@ -409,6 +416,88 @@ def unmarshal_JobRun(data: Any) -> JobRun: return JobRun(**args) +def unmarshal_TriggerCronConfig(data: Any) -> TriggerCronConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TriggerCronConfig' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("schedule", None) + if field is not None: + args["schedule"] = field + else: + args["schedule"] = None + + field = data.get("timezone", None) + if field is not None: + args["timezone"] = field + else: + args["timezone"] = None + + field = data.get("startup_command", None) + if field is not None: + args["startup_command"] = field + else: + args["startup_command"] = [] + + field = data.get("args", None) + if field is not None: + args["args"] = field + else: + args["args"] = [] + + return TriggerCronConfig(**args) + + +def unmarshal_Trigger(data: Any) -> Trigger: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Trigger' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + else: + args["id"] = None + + field = data.get("job_definition_id", None) + if field is not None: + args["job_definition_id"] = field + else: + args["job_definition_id"] = None + + field = data.get("name", None) + if field is not None: + args["name"] = field + else: + args["name"] = 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("cron_config", None) + if field is not None: + args["cron_config"] = unmarshal_TriggerCronConfig(field) + else: + args["cron_config"] = None + + return Trigger(**args) + + def unmarshal_CreateSecretsResponse(data: Any) -> CreateSecretsResponse: if not isinstance(data, dict): raise TypeError( @@ -562,6 +651,31 @@ def unmarshal_ListSecretsResponse(data: Any) -> ListSecretsResponse: return ListSecretsResponse(**args) +def unmarshal_ListTriggersResponse(data: Any) -> ListTriggersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTriggersResponse' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("triggers", None) + if field is not None: + args["triggers"] = ( + [unmarshal_Trigger(v) for v in field] if field is not None else None + ) + else: + args["triggers"] = [] + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + else: + args["total_count"] = 0 + + return ListTriggersResponse(**args) + + def unmarshal_StartJobDefinitionResponse(data: Any) -> StartJobDefinitionResponse: if not isinstance(data, dict): raise TypeError( @@ -708,6 +822,53 @@ def marshal_CreateSecretsRequest( return output +def marshal_CreateTriggerRequestCronConfig( + request: CreateTriggerRequestCronConfig, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.schedule is not None: + output["schedule"] = request.schedule + + if request.timezone is not None: + output["timezone"] = request.timezone + + if request.startup_command is not None: + output["startup_command"] = request.startup_command + + if request.args is not None: + output["args"] = request.args + + return output + + +def marshal_CreateTriggerRequest( + request: CreateTriggerRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility( + param="cron_config", + value=request.cron_config, + marshal_func=marshal_CreateTriggerRequestCronConfig, + ), + ] + ), + ) + + if request.job_definition_id is not None: + output["job_definition_id"] = request.job_definition_id + + if request.name is not None: + output["name"] = request.name + + return output + + def marshal_StartJobDefinitionRequest( request: StartJobDefinitionRequest, defaults: ProfileDefaults, @@ -817,3 +978,47 @@ def marshal_UpdateSecretRequest( output["secret_manager_version"] = request.secret_manager_version return output + + +def marshal_UpdateTriggerRequestCronConfig( + request: UpdateTriggerRequestCronConfig, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.schedule is not None: + output["schedule"] = request.schedule + + if request.timezone is not None: + output["timezone"] = request.timezone + + if request.startup_command is not None: + output["startup_command"] = request.startup_command + + if request.args is not None: + output["args"] = request.args + + return output + + +def marshal_UpdateTriggerRequest( + request: UpdateTriggerRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility( + param="cron_config", + value=request.cron_config, + marshal_func=marshal_UpdateTriggerRequestCronConfig, + ), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + return output diff --git a/scaleway/scaleway/jobs/v1alpha2/types.py b/scaleway/scaleway/jobs/v1alpha2/types.py index 1f13dc4f4..9b40596af 100644 --- a/scaleway/scaleway/jobs/v1alpha2/types.py +++ b/scaleway/scaleway/jobs/v1alpha2/types.py @@ -66,6 +66,14 @@ def __str__(self) -> str: return str(self.value) +class ListTriggersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + @dataclass class SecretEnvVar: name: str @@ -97,6 +105,29 @@ class RetryPolicy: """ +@dataclass +class TriggerCronConfig: + schedule: str + """ + CRON schedule in UNIX format. + """ + + timezone: str + """ + Time zone for the CRON schedule. + """ + + startup_command: list[str] + """ + Startup command that will be used by the triggered job. + """ + + args: list[str] + """ + Arguments passed to the startup command used by the triggered job. + """ + + @dataclass class CreateJobDefinitionRequestCronScheduleConfig: schedule: str @@ -139,30 +170,120 @@ class Secret: env_var: Optional[SecretEnvVar] = None +@dataclass +class CreateTriggerRequestCronConfig: + schedule: str + """ + CRON schedule in UNIX format. + """ + + timezone: str + """ + Time zone for the CRON schedule. + """ + + startup_command: list[str] + """ + Startup command that will be used by the triggered job. + """ + + args: list[str] + """ + Arguments passed to the startup command used by the triggered job. + """ + + @dataclass class JobDefinition: id: str + """ + UUID of the job definition. + """ + name: str + """ + Name of the job definition. + """ + project_id: str + """ + UUID of the Scaleway Project containing the job. + """ + cpu_limit: int + """ + CPU limit of the job (in mvCPU). + """ + memory_limit: int + """ + Memory limit of the job (in MiB). + """ + local_storage_capacity: int + """ + Local storage capacity of the job (in MiB). + """ + image_uri: str + """ + Image to use for the job. + """ + environment_variables: dict[str, str] + """ + Environment variables of the job. + """ + description: str + """ + Description of the job. + """ + startup_command: list[str] + """ + Job startup command. + """ + args: list[str] + """ + Job arguments passed to the startup command at runtime. + """ + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ created_at: Optional[datetime] = None + """ + Creation date of the job definition. + """ + updated_at: Optional[datetime] = None + """ + Last update date of the job definition. + """ + command: Optional[str] = None + """ + Deprecated, please use startup_command instead. + """ + job_timeout: Optional[str] = None + """ + Timeout of the job in seconds. + """ + cron_schedule: Optional[CronSchedule] = None + """ + Configure a cron for the job. + """ + retry_policy: Optional[RetryPolicy] = None + """ + Retry behaviour in case of job failure. + """ @dataclass @@ -174,29 +295,134 @@ class Resource: @dataclass class JobRun: id: str + """ + UUID of the job run. + """ + job_definition_id: str + """ + UUID of the job definition. + """ + state: JobRunState + """ + State of the job run. + """ + cpu_limit: int + """ + CPU limit of the job (in mvCPU). + """ + memory_limit: int + """ + Memory limit of the job (in MiB). + """ + local_storage_capacity: int + """ + Local storage capacity of the job (in MiB). + """ + environment_variables: dict[str, str] + """ + Environment variables of the job run. + """ + startup_command: list[str] + """ + Job startup command. + """ + args: list[str] + """ + Job arguments passed to the startup command at runtime. + """ + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ created_at: Optional[datetime] = None + """ + Creation date of the job run. + """ + updated_at: Optional[datetime] = None + """ + Last update date of the job run. + """ + started_at: Optional[datetime] = None + """ + Start date of the job run. + """ + terminated_at: Optional[datetime] = None + """ + Termination date of the job run. + """ + run_duration: Optional[str] = None + """ + Duration of the job run. + """ + reason: Optional[JobRunReason] = None + """ + Reason for failure if the job failed. + """ + exit_code: Optional[int] = None + """ + Exit code of the job. + """ + error_message: Optional[str] = None + """ + Error message if the job failed. + """ + command: Optional[str] = None + """ + Deprecated, please use startup_command instead. + """ + attempts: Optional[int] = None + """ + Number of retry attempts. + """ + + +@dataclass +class Trigger: + id: str + """ + UUID of the trigger. + """ + + job_definition_id: str + """ + UUID of the job definition. + """ + + name: str + """ + Human readable name of the trigger. + """ + + created_at: Optional[datetime] = None + """ + Creation time of the trigger. + """ + + updated_at: Optional[datetime] = None + """ + Last update time of the trigger. + """ + + cron_config: Optional[TriggerCronConfig] = None @dataclass @@ -205,6 +431,29 @@ class UpdateJobDefinitionRequestCronScheduleConfig: timezone: Optional[str] = None +@dataclass +class UpdateTriggerRequestCronConfig: + schedule: Optional[str] = None + """ + CRON schedule in UNIX format. + """ + + timezone: Optional[str] = None + """ + Time zone for the CRON schedule. + """ + + startup_command: Optional[list[str]] = field(default_factory=list) + """ + Startup command that will be used by the triggered job. + """ + + args: Optional[list[str]] = field(default_factory=list) + """ + Arguments passed to the startup command used by the triggered job. + """ + + @dataclass class CreateJobDefinitionRequest: cpu_limit: int @@ -311,6 +560,26 @@ class CreateSecretsResponse: """ +@dataclass +class CreateTriggerRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + name: str + """ + Name of the trigger. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + cron_config: Optional[CreateTriggerRequestCronConfig] = None + + @dataclass class DeleteJobDefinitionRequest: job_definition_id: str @@ -337,6 +606,19 @@ class DeleteSecretRequest: """ +@dataclass +class DeleteTriggerRequest: + trigger_id: str + """ + UUID of the trigger. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class GetJobDefinitionRequest: job_definition_id: str @@ -384,6 +666,19 @@ class GetSecretRequest: """ +@dataclass +class GetTriggerRequest: + trigger_id: str + """ + UUID of the trigger. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class JobLimits: secrets_per_job_definition: int @@ -472,6 +767,49 @@ class ListSecretsResponse: """ +@dataclass +class ListTriggersRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] = 0 + """ + Page number from paginated list of triggers. + """ + + page_size: Optional[int] = 0 + """ + Number of triggers per page. + """ + + order_by: Optional[ListTriggersRequestOrderBy] = ( + ListTriggersRequestOrderBy.CREATED_AT_ASC + ) + """ + Sorting order of triggers. + """ + + +@dataclass +class ListTriggersResponse: + triggers: list[Trigger] + """ + List of triggers. + """ + + total_count: int + """ + Total count of triggers. + """ + + @dataclass class StartJobDefinitionRequest: job_definition_id: str @@ -636,3 +974,23 @@ class UpdateSecretRequest: path: Optional[str] = None env_var_name: Optional[str] = None + + +@dataclass +class UpdateTriggerRequest: + trigger_id: str + """ + UUID of the trigger. + """ + + region: Optional[ScwRegion] = None + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] = None + """ + Name of the trigger. + """ + + cron_config: Optional[UpdateTriggerRequestCronConfig] = None