From 36b4a96a10d1526d1c1f5fc7daac92bf4ed32fbc Mon Sep 17 00:00:00 2001 From: jo Date: Fri, 19 Dec 2025 17:54:06 +0100 Subject: [PATCH] chore: update vendored files --- .../module_utils/vendor/hcloud/__init__.py | 24 ++- plugins/module_utils/vendor/hcloud/_client.py | 12 +- .../module_utils/vendor/hcloud/_version.py | 2 +- .../vendor/hcloud/actions/__init__.py | 16 +- .../vendor/hcloud/actions/client.py | 164 ++++++++++++------ .../vendor/hcloud/actions/domain.py | 47 +++-- .../vendor/hcloud/certificates/client.py | 127 +++++++------- .../vendor/hcloud/certificates/domain.py | 19 +- .../module_utils/vendor/hcloud/core/client.py | 42 +++-- .../module_utils/vendor/hcloud/core/domain.py | 33 +++- .../vendor/hcloud/datacenters/client.py | 10 +- .../vendor/hcloud/datacenters/domain.py | 5 + .../vendor/hcloud/deprecation/__init__.py | 4 +- .../vendor/hcloud/deprecation/domain.py | 15 +- .../module_utils/vendor/hcloud/exp/zone.py | 5 + .../vendor/hcloud/firewalls/client.py | 130 +++++++------- .../vendor/hcloud/firewalls/domain.py | 17 +- .../vendor/hcloud/floating_ips/__init__.py | 3 +- .../vendor/hcloud/floating_ips/client.py | 128 +++++++------- .../vendor/hcloud/floating_ips/domain.py | 25 ++- .../vendor/hcloud/helpers/__init__.py | 4 +- .../vendor/hcloud/helpers/labels.py | 4 + .../vendor/hcloud/images/__init__.py | 3 +- .../vendor/hcloud/images/client.py | 129 +++++++------- .../vendor/hcloud/images/domain.py | 24 ++- .../module_utils/vendor/hcloud/isos/client.py | 8 +- .../module_utils/vendor/hcloud/isos/domain.py | 9 +- .../hcloud/load_balancer_types/client.py | 8 +- .../hcloud/load_balancer_types/domain.py | 8 +- .../vendor/hcloud/load_balancers/__init__.py | 4 + .../vendor/hcloud/load_balancers/client.py | 127 +++++++------- .../vendor/hcloud/load_balancers/domain.py | 42 +++-- .../vendor/hcloud/locations/client.py | 8 +- .../vendor/hcloud/locations/domain.py | 4 + .../vendor/hcloud/metrics/domain.py | 15 +- .../vendor/hcloud/networks/__init__.py | 2 + .../vendor/hcloud/networks/client.py | 127 +++++++------- .../vendor/hcloud/networks/domain.py | 25 ++- .../vendor/hcloud/placement_groups/client.py | 8 +- .../vendor/hcloud/placement_groups/domain.py | 12 +- .../vendor/hcloud/primary_ips/__init__.py | 3 +- .../vendor/hcloud/primary_ips/client.py | 141 ++++++++++++++- .../vendor/hcloud/primary_ips/domain.py | 71 ++++++-- .../vendor/hcloud/rdns/__init__.py | 7 + .../module_utils/vendor/hcloud/rdns/domain.py | 12 ++ .../vendor/hcloud/server_types/client.py | 10 +- .../vendor/hcloud/server_types/domain.py | 12 +- .../vendor/hcloud/servers/__init__.py | 6 + .../vendor/hcloud/servers/client.py | 147 ++++++++-------- .../vendor/hcloud/servers/domain.py | 79 +++++++-- .../vendor/hcloud/ssh_keys/client.py | 8 +- .../vendor/hcloud/ssh_keys/domain.py | 11 +- .../vendor/hcloud/storage_box_types/client.py | 8 +- .../vendor/hcloud/storage_box_types/domain.py | 10 +- .../vendor/hcloud/storage_boxes/client.py | 108 +++++++----- .../vendor/hcloud/storage_boxes/domain.py | 31 +++- .../vendor/hcloud/volumes/__init__.py | 3 +- .../vendor/hcloud/volumes/client.py | 127 +++++++------- .../vendor/hcloud/volumes/domain.py | 21 ++- .../vendor/hcloud/zones/__init__.py | 20 +++ .../vendor/hcloud/zones/client.py | 115 ++++++------ .../vendor/hcloud/zones/domain.py | 31 ++-- 62 files changed, 1486 insertions(+), 894 deletions(-) create mode 100644 plugins/module_utils/vendor/hcloud/rdns/__init__.py create mode 100644 plugins/module_utils/vendor/hcloud/rdns/domain.py diff --git a/plugins/module_utils/vendor/hcloud/__init__.py b/plugins/module_utils/vendor/hcloud/__init__.py index 95709bb..8a9fa14 100644 --- a/plugins/module_utils/vendor/hcloud/__init__.py +++ b/plugins/module_utils/vendor/hcloud/__init__.py @@ -1,12 +1,18 @@ from __future__ import annotations -from ._client import ( # noqa pylint: disable=C0414 - Client as Client, - constant_backoff_function as constant_backoff_function, - exponential_backoff_function as exponential_backoff_function, +from ._client import ( + Client, + constant_backoff_function, + exponential_backoff_function, ) -from ._exceptions import ( # noqa pylint: disable=C0414 - APIException as APIException, - HCloudException as HCloudException, -) -from ._version import __version__ # noqa +from ._exceptions import APIException, HCloudException +from ._version import __version__ + +__all__ = [ + "__version__", + "Client", + "constant_backoff_function", + "exponential_backoff_function", + "APIException", + "HCloudException", +] diff --git a/plugins/module_utils/vendor/hcloud/_client.py b/plugins/module_utils/vendor/hcloud/_client.py index e552433..b6b570a 100644 --- a/plugins/module_utils/vendor/hcloud/_client.py +++ b/plugins/module_utils/vendor/hcloud/_client.py @@ -3,7 +3,7 @@ from __future__ import annotations import time from http import HTTPStatus from random import uniform -from typing import Protocol +from typing import Any, Protocol try: import requests @@ -75,7 +75,7 @@ def exponential_backoff_function( """ def func(retries: int) -> float: - interval = base * multiplier**retries # Exponential backoff + interval: float = base * multiplier**retries # Exponential backoff interval = min(cap, interval) # Cap backoff if jitter: interval = uniform(base, interval) # Add jitter @@ -295,7 +295,7 @@ class Client: method: str, url: str, **kwargs, - ) -> dict: + ) -> dict[str, Any]: """Perform a request to the Hetzner Cloud API. :param method: Method to perform the request. @@ -348,7 +348,7 @@ class ClientBase: method: str, url: str, **kwargs, - ) -> dict: + ) -> dict[str, Any]: """Perform a request to the provided URL. :param method: Method to perform the request. @@ -384,7 +384,7 @@ class ClientBase: continue raise - def _read_response(self, response) -> dict: + def _read_response(self, response) -> dict[str, Any]: correlation_id = response.headers.get("X-Correlation-Id") payload = {} try: @@ -407,7 +407,7 @@ class ClientBase: correlation_id=correlation_id, ) - error: dict = payload["error"] + error: dict[str, Any] = payload["error"] raise APIException( code=error["code"], message=error["message"], diff --git a/plugins/module_utils/vendor/hcloud/_version.py b/plugins/module_utils/vendor/hcloud/_version.py index 77282e5..4e8b02a 100644 --- a/plugins/module_utils/vendor/hcloud/_version.py +++ b/plugins/module_utils/vendor/hcloud/_version.py @@ -1,3 +1,3 @@ from __future__ import annotations -__version__ = "2.12.0" # x-releaser-pleaser-version +__version__ = "2.13.0" # x-releaser-pleaser-version diff --git a/plugins/module_utils/vendor/hcloud/actions/__init__.py b/plugins/module_utils/vendor/hcloud/actions/__init__.py index 8a96e5d..ac67793 100644 --- a/plugins/module_utils/vendor/hcloud/actions/__init__.py +++ b/plugins/module_utils/vendor/hcloud/actions/__init__.py @@ -2,24 +2,32 @@ from __future__ import annotations from .client import ( ActionsClient, + ActionSort, ActionsPageResult, BoundAction, ResourceActionsClient, ) from .domain import ( Action, + ActionError, ActionException, ActionFailedException, + ActionResource, + ActionStatus, ActionTimeoutException, ) __all__ = [ - "Action", - "ActionException", - "ActionFailedException", - "ActionTimeoutException", "ActionsClient", "ActionsPageResult", "BoundAction", "ResourceActionsClient", + "ActionSort", + "ActionStatus", + "Action", + "ActionResource", + "ActionError", + "ActionException", + "ActionFailedException", + "ActionTimeoutException", ] diff --git a/plugins/module_utils/vendor/hcloud/actions/client.py b/plugins/module_utils/vendor/hcloud/actions/client.py index a0c0cc4..176a6b1 100644 --- a/plugins/module_utils/vendor/hcloud/actions/client.py +++ b/plugins/module_utils/vendor/hcloud/actions/client.py @@ -2,16 +2,25 @@ from __future__ import annotations import time import warnings -from typing import TYPE_CHECKING, Any, NamedTuple +from typing import TYPE_CHECKING, Any, Literal, NamedTuple from ..core import BoundModelBase, Meta, ResourceClientBase -from .domain import Action, ActionFailedException, ActionTimeoutException +from .domain import Action, ActionFailedException, ActionStatus, ActionTimeoutException if TYPE_CHECKING: from .._client import Client -class BoundAction(BoundModelBase, Action): +__all__ = [ + "ActionsClient", + "ActionsPageResult", + "BoundAction", + "ResourceActionsClient", + "ActionSort", +] + + +class BoundAction(BoundModelBase[Action], Action): _client: ActionsClient model = Action @@ -45,12 +54,78 @@ class BoundAction(BoundModelBase, Action): raise ActionFailedException(action=self) +ActionSort = Literal[ + "id", + "id:asc", + "id:desc", + "command", + "command:asc", + "command:desc", + "status", + "status:asc", + "status:desc", + "started", + "started:asc", + "started:desc", + "finished", + "finished:asc", + "finished:desc", +] + + class ActionsPageResult(NamedTuple): actions: list[BoundAction] meta: Meta -class ResourceActionsClient(ResourceClientBase): +class ResourceClientBaseActionsMixin(ResourceClientBase): + def _get_action_by_id( + self, + base_url: str, + id: int, + ) -> BoundAction: + response = self._client.request( + method="GET", + url=f"{base_url}/actions/{id}", + ) + return BoundAction( + client=self._parent.actions, + data=response["action"], + ) + + def _get_actions_list( + self, + base_url: str, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, + page: int | None = None, + per_page: int | None = None, + ) -> ActionsPageResult: + params: dict[str, Any] = {} + if status is not None: + params["status"] = status + if sort is not None: + params["sort"] = sort + if page is not None: + params["page"] = page + if per_page is not None: + params["per_page"] = per_page + + response = self._client.request( + method="GET", + url=f"{base_url}/actions", + params=params, + ) + return ActionsPageResult( + actions=[BoundAction(self._parent.actions, o) for o in response["actions"]], + meta=Meta.parse_meta(response), + ) + + +class ResourceActionsClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _resource: str def __init__(self, client: ResourceClientBase | Client, resource: str | None): @@ -66,69 +141,46 @@ class ResourceActionsClient(ResourceClientBase): self._resource = resource or "" def get_by_id(self, id: int) -> BoundAction: - """Get a specific action by its ID. - - :param id: int - :return: :class:`BoundAction ` """ - response = self._client.request( - url=f"{self._resource}/actions/{id}", - method="GET", - ) - return BoundAction(self._parent.actions, response["action"]) + Returns a specific Action by its ID. + + :param id: ID of the Action. + """ + return self._get_action_by_id(self._resource, id) def get_list( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Get a list of actions. - - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `command` `status` `progress` `started` `finished` . You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default) - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page + Returns a paginated list of Actions. - response = self._client.request( - url=f"{self._resource}/actions", - method="GET", - params=params, + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + self._resource, + status=status, + sort=sort, + page=page, + per_page=per_page, ) - actions = [ - BoundAction(self._parent.actions, action_data) - for action_data in response["actions"] - ] - return ActionsPageResult(actions, Meta.parse_meta(response)) def get_all( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Get all actions. + """ + Returns all Actions. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `command` `status` `progress` `started` `finished` . You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default) - :return: List[:class:`BoundAction `] + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages(self.get_list, status=status, sort=sort) @@ -139,8 +191,8 @@ class ActionsClient(ResourceActionsClient): def get_list( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: @@ -162,8 +214,8 @@ class ActionsClient(ResourceActionsClient): def get_all( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: """ .. deprecated:: 1.28 diff --git a/plugins/module_utils/vendor/hcloud/actions/domain.py b/plugins/module_utils/vendor/hcloud/actions/domain.py index 92b40a8..59b7f44 100644 --- a/plugins/module_utils/vendor/hcloud/actions/domain.py +++ b/plugins/module_utils/vendor/hcloud/actions/domain.py @@ -1,11 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING - -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None +from typing import TYPE_CHECKING, Any, Literal, TypedDict from .._exceptions import HCloudException from ..core import BaseDomain @@ -13,6 +8,22 @@ from ..core import BaseDomain if TYPE_CHECKING: from .client import BoundAction +__all__ = [ + "ActionStatus", + "Action", + "ActionResource", + "ActionError", + "ActionException", + "ActionFailedException", + "ActionTimeoutException", +] + +ActionStatus = Literal[ + "running", + "success", + "error", +] + class Action(BaseDomain): """Action Domain @@ -50,24 +61,35 @@ class Action(BaseDomain): self, id: int, command: str | None = None, - status: str | None = None, + status: ActionStatus | None = None, progress: int | None = None, started: str | None = None, finished: str | None = None, - resources: list[dict] | None = None, - error: dict | None = None, + resources: list[ActionResource] | None = None, + error: ActionError | None = None, ): self.id = id self.command = command self.status = status self.progress = progress - self.started = isoparse(started) if started else None - self.finished = isoparse(finished) if finished else None + self.started = self._parse_datetime(started) + self.finished = self._parse_datetime(finished) self.resources = resources self.error = error +class ActionResource(TypedDict): + id: int + type: str + + +class ActionError(TypedDict): + code: str + message: str + details: dict[str, Any] + + class ActionException(HCloudException): """A generic action exception""" @@ -85,7 +107,8 @@ class ActionException(HCloudException): extras.append(action.error["code"]) else: - extras.append(action.command) + if action.command is not None: + extras.append(action.command) extras.append(str(action.id)) message += f" ({', '.join(extras)})" diff --git a/plugins/module_utils/vendor/hcloud/certificates/client.py b/plugins/module_utils/vendor/hcloud/certificates/client.py index 8b2a7ef..46a6a53 100644 --- a/plugins/module_utils/vendor/hcloud/certificates/client.py +++ b/plugins/module_utils/vendor/hcloud/certificates/client.py @@ -2,7 +2,14 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, NamedTuple -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import ( Certificate, @@ -15,12 +22,24 @@ if TYPE_CHECKING: from .._client import Client -class BoundCertificate(BoundModelBase, Certificate): +__all__ = [ + "BoundCertificate", + "CertificatesPageResult", + "CertificatesClient", +] + + +class BoundCertificate(BoundModelBase[Certificate], Certificate): _client: CertificatesClient model = Certificate - def __init__(self, client: CertificatesClient, data: dict, complete: bool = True): + def __init__( + self, + client: CertificatesClient, + data: dict[str, Any], + complete: bool = True, + ): status = data.get("status") if status is not None: error_data = status.get("error") @@ -36,22 +55,18 @@ class BoundCertificate(BoundModelBase, Certificate): def get_actions_list( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a Certificate. + """ + Returns a paginated list of Actions for a Certificate. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ return self._client.get_actions_list( self, @@ -63,16 +78,14 @@ class BoundCertificate(BoundModelBase, Certificate): def get_actions( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a Certificate. + """ + Returns all Actions for a Certificate. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._client.get_actions( self, @@ -117,7 +130,10 @@ class CertificatesPageResult(NamedTuple): meta: Meta -class CertificatesClient(ResourceClientBase): +class CertificatesClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _base_url = "/certificates" actions: ResourceActionsClient @@ -306,59 +322,40 @@ class CertificatesClient(ResourceClientBase): def get_actions_list( self, certificate: Certificate | BoundCertificate, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a Certificate. - - :param certificate: :class:`BoundCertificate ` or :class:`Certificate ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page + Returns a paginated list of Actions for a Certificate. - response = self._client.request( - url=f"{self._base_url}/{certificate.id}/actions", - method="GET", - params=params, + :param certificate: Certificate to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + f"{self._base_url}/{certificate.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) - actions = [ - BoundAction(self._parent.actions, action_data) - for action_data in response["actions"] - ] - return ActionsPageResult(actions, Meta.parse_meta(response)) def get_actions( self, certificate: Certificate | BoundCertificate, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a Certificate. + """ + Returns all Actions for a Certificate. - :param certificate: :class:`BoundCertificate ` or :class:`Certificate ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param certificate: Certificate to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages( self.get_actions_list, diff --git a/plugins/module_utils/vendor/hcloud/certificates/domain.py b/plugins/module_utils/vendor/hcloud/certificates/domain.py index 67daa8e..677ab8f 100644 --- a/plugins/module_utils/vendor/hcloud/certificates/domain.py +++ b/plugins/module_utils/vendor/hcloud/certificates/domain.py @@ -2,11 +2,6 @@ from __future__ import annotations from typing import TYPE_CHECKING -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None - from ..core import BaseDomain, DomainIdentityMixin if TYPE_CHECKING: @@ -14,6 +9,14 @@ if TYPE_CHECKING: from .client import BoundCertificate +__all__ = [ + "Certificate", + "ManagedCertificateStatus", + "ManagedCertificateError", + "CreateManagedCertificateResponse", +] + + class Certificate(BaseDomain, DomainIdentityMixin): """Certificate Domain @@ -72,9 +75,9 @@ class Certificate(BaseDomain, DomainIdentityMixin): self.certificate = certificate self.domain_names = domain_names self.fingerprint = fingerprint - self.not_valid_before = isoparse(not_valid_before) if not_valid_before else None - self.not_valid_after = isoparse(not_valid_after) if not_valid_after else None - self.created = isoparse(created) if created else None + self.not_valid_before = self._parse_datetime(not_valid_before) + self.not_valid_after = self._parse_datetime(not_valid_after) + self.created = self._parse_datetime(created) self.labels = labels self.status = status diff --git a/plugins/module_utils/vendor/hcloud/core/client.py b/plugins/module_utils/vendor/hcloud/core/client.py index f0e67a7..4ff7f24 100644 --- a/plugins/module_utils/vendor/hcloud/core/client.py +++ b/plugins/module_utils/vendor/hcloud/core/client.py @@ -2,11 +2,22 @@ from __future__ import annotations import warnings from collections.abc import Callable -from typing import TYPE_CHECKING, Any, ClassVar +from typing import TYPE_CHECKING, Any, ClassVar, Generic, TypeVar + +from .domain import BaseDomain if TYPE_CHECKING: from .._client import Client, ClientBase - from .domain import BaseDomain + from .domain import Meta + +__all__ = [ + "ResourceClientBase", + "ClientEntityBase", + "BoundModelBase", +] + + +T = TypeVar("T") class ResourceClientBase: @@ -23,10 +34,10 @@ class ResourceClientBase: def _iter_pages( # type: ignore[no-untyped-def] self, - list_function: Callable, + list_function: Callable[..., tuple[list[T], Meta]], *args, **kwargs, - ) -> list: + ) -> list[T]: results = [] page = 1 @@ -46,7 +57,12 @@ class ResourceClientBase: return results - def _get_first_by(self, list_function: Callable, *args, **kwargs): # type: ignore[no-untyped-def] + def _get_first_by( # type: ignore[no-untyped-def] + self, + list_function: Callable[..., tuple[list[T], Meta]], + *args, + **kwargs, + ) -> T | None: entities, _ = list_function(*args, **kwargs) return entities[0] if entities else None @@ -69,15 +85,18 @@ class ClientEntityBase(ResourceClientBase): super().__init__(client) -class BoundModelBase: +Domain = TypeVar("Domain", bound=BaseDomain) + + +class BoundModelBase(Generic[Domain]): """Bound Model Base""" - model: type[BaseDomain] + model: type[Domain] def __init__( self, client: ResourceClientBase, - data: dict, + data: dict[str, Any], complete: bool = True, ): """ @@ -90,7 +109,7 @@ class BoundModelBase: """ self._client = client self.complete = complete - self.data_model = self.model.from_dict(data) + self.data_model: Domain = self.model.from_dict(data) def __getattr__(self, name: str): # type: ignore[no-untyped-def] """Allow magical access to the properties of the model @@ -103,9 +122,10 @@ class BoundModelBase: value = getattr(self.data_model, name) return value - def _get_self(self) -> BoundModelBase: + def _get_self(self) -> BoundModelBase[Domain]: assert hasattr(self._client, "get_by_id") - return self._client.get_by_id(self.data_model.id) + assert hasattr(self.data_model, "id") + return self._client.get_by_id(self.data_model.id) # type: ignore def reload(self) -> None: """Reloads the model and tries to get all data from the API""" diff --git a/plugins/module_utils/vendor/hcloud/core/domain.py b/plugins/module_utils/vendor/hcloud/core/domain.py index b2ac197..a68079b 100644 --- a/plugins/module_utils/vendor/hcloud/core/domain.py +++ b/plugins/module_utils/vendor/hcloud/core/domain.py @@ -1,13 +1,26 @@ from __future__ import annotations -from typing import Any +from datetime import datetime +from typing import Any, overload + +try: + from dateutil.parser import isoparse +except ImportError: + isoparse = None + +__all__ = [ + "BaseDomain", + "DomainIdentityMixin", + "Pagination", + "Meta", +] class BaseDomain: - __api_properties__: tuple + __api_properties__: tuple[str, ...] @classmethod - def from_dict(cls, data: dict): # type: ignore[no-untyped-def] + def from_dict(cls, data: dict[str, Any]): # type: ignore[no-untyped-def] """ Build the domain object from the data dict. """ @@ -15,7 +28,7 @@ class BaseDomain: return cls(**supported_data) def __repr__(self) -> str: - kwargs = [f"{key}={getattr(self, key)!r}" for key in self.__api_properties__] # type: ignore[var-annotated] + kwargs = [f"{key}={getattr(self, key)!r}" for key in self.__api_properties__] return f"{self.__class__.__qualname__}({', '.join(kwargs)})" def __eq__(self, other: Any) -> bool: @@ -27,6 +40,16 @@ class BaseDomain: return False return True + @overload + def _parse_datetime(self, value: str) -> datetime: ... + @overload + def _parse_datetime(self, value: None) -> None: ... + + def _parse_datetime(self, value: str | None) -> datetime | None: + if value is None: + return None + return isoparse(value) + class DomainIdentityMixin: @@ -106,7 +129,7 @@ class Meta(BaseDomain): self.pagination = pagination @classmethod - def parse_meta(cls, response: dict) -> Meta: + def parse_meta(cls, response: dict[str, Any]) -> Meta: """ If present, extract the meta details from the response and return a meta object. """ diff --git a/plugins/module_utils/vendor/hcloud/datacenters/client.py b/plugins/module_utils/vendor/hcloud/datacenters/client.py index ae338a5..5d7fe96 100644 --- a/plugins/module_utils/vendor/hcloud/datacenters/client.py +++ b/plugins/module_utils/vendor/hcloud/datacenters/client.py @@ -7,13 +7,19 @@ from ..locations import BoundLocation from ..server_types import BoundServerType from .domain import Datacenter, DatacenterServerTypes +__all__ = [ + "BoundDatacenter", + "DatacentersPageResult", + "DatacentersClient", +] -class BoundDatacenter(BoundModelBase, Datacenter): + +class BoundDatacenter(BoundModelBase[Datacenter], Datacenter): _client: DatacentersClient model = Datacenter - def __init__(self, client: DatacentersClient, data: dict): + def __init__(self, client: DatacentersClient, data: dict[str, Any]): location = data.get("location") if location is not None: data["location"] = BoundLocation(client._parent.locations, location) diff --git a/plugins/module_utils/vendor/hcloud/datacenters/domain.py b/plugins/module_utils/vendor/hcloud/datacenters/domain.py index badd335..4867915 100644 --- a/plugins/module_utils/vendor/hcloud/datacenters/domain.py +++ b/plugins/module_utils/vendor/hcloud/datacenters/domain.py @@ -8,6 +8,11 @@ if TYPE_CHECKING: from ..locations import Location from ..server_types import BoundServerType +__all__ = [ + "Datacenter", + "DatacenterServerTypes", +] + class Datacenter(BaseDomain, DomainIdentityMixin): """Datacenter Domain diff --git a/plugins/module_utils/vendor/hcloud/deprecation/__init__.py b/plugins/module_utils/vendor/hcloud/deprecation/__init__.py index db30b0f..4dd0e91 100644 --- a/plugins/module_utils/vendor/hcloud/deprecation/__init__.py +++ b/plugins/module_utils/vendor/hcloud/deprecation/__init__.py @@ -2,4 +2,6 @@ from __future__ import annotations from .domain import DeprecationInfo -__all__ = ["DeprecationInfo"] +__all__ = [ + "DeprecationInfo", +] diff --git a/plugins/module_utils/vendor/hcloud/deprecation/domain.py b/plugins/module_utils/vendor/hcloud/deprecation/domain.py index 3eb7d50..c78c43e 100644 --- a/plugins/module_utils/vendor/hcloud/deprecation/domain.py +++ b/plugins/module_utils/vendor/hcloud/deprecation/domain.py @@ -1,12 +1,11 @@ from __future__ import annotations -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None - from ..core import BaseDomain +__all__ = [ + "DeprecationInfo", +] + class DeprecationInfo(BaseDomain): """Describes if, when & how the resources was deprecated. If this field is set to ``None`` the resource is not @@ -31,7 +30,5 @@ class DeprecationInfo(BaseDomain): announced: str | None = None, unavailable_after: str | None = None, ): - self.announced = isoparse(announced) if announced else None - self.unavailable_after = ( - isoparse(unavailable_after) if unavailable_after else None - ) + self.announced = self._parse_datetime(announced) + self.unavailable_after = self._parse_datetime(unavailable_after) diff --git a/plugins/module_utils/vendor/hcloud/exp/zone.py b/plugins/module_utils/vendor/hcloud/exp/zone.py index 0860128..c8dd3d0 100644 --- a/plugins/module_utils/vendor/hcloud/exp/zone.py +++ b/plugins/module_utils/vendor/hcloud/exp/zone.py @@ -5,6 +5,11 @@ library, breaking changes may occur within minor releases. from __future__ import annotations +__all__ = [ + "is_txt_record_quoted", + "format_txt_record", +] + def is_txt_record_quoted(value: str) -> bool: """ diff --git a/plugins/module_utils/vendor/hcloud/firewalls/client.py b/plugins/module_utils/vendor/hcloud/firewalls/client.py index a088947..f314b68 100644 --- a/plugins/module_utils/vendor/hcloud/firewalls/client.py +++ b/plugins/module_utils/vendor/hcloud/firewalls/client.py @@ -2,7 +2,14 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, NamedTuple -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import ( CreateFirewallResponse, @@ -17,12 +24,24 @@ if TYPE_CHECKING: from .._client import Client -class BoundFirewall(BoundModelBase, Firewall): +__all__ = [ + "BoundFirewall", + "FirewallsPageResult", + "FirewallsClient", +] + + +class BoundFirewall(BoundModelBase[Firewall], Firewall): _client: FirewallsClient model = Firewall - def __init__(self, client: FirewallsClient, data: dict, complete: bool = True): + def __init__( + self, + client: FirewallsClient, + data: dict[str, Any], + complete: bool = True, + ): rules = data.get("rules", []) if rules: rules = [ @@ -92,22 +111,18 @@ class BoundFirewall(BoundModelBase, Firewall): def get_actions_list( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a Firewall. + """ + Returns a paginated list of Actions for a Firewall. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ return self._client.get_actions_list( self, @@ -119,17 +134,14 @@ class BoundFirewall(BoundModelBase, Firewall): def get_actions( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a Firewall. + """ + Returns all Actions for a Firewall. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - - :return: List[:class:`BoundAction `] + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._client.get_actions( self, @@ -193,7 +205,10 @@ class FirewallsPageResult(NamedTuple): meta: Meta -class FirewallsClient(ResourceClientBase): +class FirewallsClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _base_url = "/firewalls" actions: ResourceActionsClient @@ -209,59 +224,40 @@ class FirewallsClient(ResourceClientBase): def get_actions_list( self, firewall: Firewall | BoundFirewall, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a Firewall. - - :param firewall: :class:`BoundFirewall ` or :class:`Firewall ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page - response = self._client.request( - url=f"{self._base_url}/{firewall.id}/actions", - method="GET", - params=params, + Returns a paginated list of Actions for a Firewall. + + :param firewall: Firewall to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + f"{self._base_url}/{firewall.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) - actions = [ - BoundAction(self._parent.actions, action_data) - for action_data in response["actions"] - ] - return ActionsPageResult(actions, Meta.parse_meta(response)) def get_actions( self, firewall: Firewall | BoundFirewall, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a Firewall. + """ + Returns all Actions for a Firewall. - :param firewall: :class:`BoundFirewall ` or :class:`Firewall ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - - :return: List[:class:`BoundAction `] + :param firewall: Firewall to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages( self.get_actions_list, diff --git a/plugins/module_utils/vendor/hcloud/firewalls/domain.py b/plugins/module_utils/vendor/hcloud/firewalls/domain.py index a38fb48..76a9b59 100644 --- a/plugins/module_utils/vendor/hcloud/firewalls/domain.py +++ b/plugins/module_utils/vendor/hcloud/firewalls/domain.py @@ -2,11 +2,6 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None - from ..core import BaseDomain, DomainIdentityMixin if TYPE_CHECKING: @@ -15,6 +10,16 @@ if TYPE_CHECKING: from .client import BoundFirewall +__all__ = [ + "Firewall", + "FirewallRule", + "FirewallResource", + "FirewallResourceAppliedToResources", + "FirewallResourceLabelSelector", + "CreateFirewallResponse", +] + + class Firewall(BaseDomain, DomainIdentityMixin): """Firewall Domain @@ -49,7 +54,7 @@ class Firewall(BaseDomain, DomainIdentityMixin): self.rules = rules self.applied_to = applied_to self.labels = labels - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) class FirewallRule(BaseDomain): diff --git a/plugins/module_utils/vendor/hcloud/floating_ips/__init__.py b/plugins/module_utils/vendor/hcloud/floating_ips/__init__.py index 8c45c77..5ae08fc 100644 --- a/plugins/module_utils/vendor/hcloud/floating_ips/__init__.py +++ b/plugins/module_utils/vendor/hcloud/floating_ips/__init__.py @@ -5,12 +5,13 @@ from .client import ( FloatingIPsClient, FloatingIPsPageResult, ) -from .domain import CreateFloatingIPResponse, FloatingIP +from .domain import CreateFloatingIPResponse, FloatingIP, FloatingIPProtection __all__ = [ "BoundFloatingIP", "CreateFloatingIPResponse", "FloatingIP", + "FloatingIPProtection", "FloatingIPsClient", "FloatingIPsPageResult", ] diff --git a/plugins/module_utils/vendor/hcloud/floating_ips/client.py b/plugins/module_utils/vendor/hcloud/floating_ips/client.py index ce28be3..88e7ea4 100644 --- a/plugins/module_utils/vendor/hcloud/floating_ips/client.py +++ b/plugins/module_utils/vendor/hcloud/floating_ips/client.py @@ -2,7 +2,14 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, NamedTuple -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from ..locations import BoundLocation from .domain import CreateFloatingIPResponse, FloatingIP @@ -12,13 +19,24 @@ if TYPE_CHECKING: from ..locations import Location from ..servers import BoundServer, Server +__all__ = [ + "BoundFloatingIP", + "FloatingIPsPageResult", + "FloatingIPsClient", +] -class BoundFloatingIP(BoundModelBase, FloatingIP): + +class BoundFloatingIP(BoundModelBase[FloatingIP], FloatingIP): _client: FloatingIPsClient model = FloatingIP - def __init__(self, client: FloatingIPsClient, data: dict, complete: bool = True): + def __init__( + self, + client: FloatingIPsClient, + data: dict[str, Any], + complete: bool = True, + ): # pylint: disable=import-outside-toplevel from ..servers import BoundServer @@ -38,22 +56,18 @@ class BoundFloatingIP(BoundModelBase, FloatingIP): def get_actions_list( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a Floating IP. + """ + Returns a paginated list of Actions for a Floating IP. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ return self._client.get_actions_list( self, @@ -65,16 +79,14 @@ class BoundFloatingIP(BoundModelBase, FloatingIP): def get_actions( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a Floating IP. + """ + Returns all Actions for a Floating IP. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._client.get_actions(self, status=status, sort=sort) @@ -147,7 +159,10 @@ class FloatingIPsPageResult(NamedTuple): meta: Meta -class FloatingIPsClient(ResourceClientBase): +class FloatingIPsClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _base_url = "/floating_ips" actions: ResourceActionsClient @@ -163,59 +178,40 @@ class FloatingIPsClient(ResourceClientBase): def get_actions_list( self, floating_ip: FloatingIP | BoundFloatingIP, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a Floating IP. - - :param floating_ip: :class:`BoundFloatingIP ` or :class:`FloatingIP ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page - response = self._client.request( - url=f"{self._base_url}/{floating_ip.id}/actions", - method="GET", - params=params, + Returns a paginated list of Actions for a Floating IP. + + :param floating_ip: Floating IP to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + f"{self._base_url}/{floating_ip.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) - actions = [ - BoundAction(self._parent.actions, action_data) - for action_data in response["actions"] - ] - return ActionsPageResult(actions, Meta.parse_meta(response)) def get_actions( self, floating_ip: FloatingIP | BoundFloatingIP, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a Floating IP. + """ + Returns all Actions for a Floating IP. - :param floating_ip: :class:`BoundFloatingIP ` or :class:`FloatingIP ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - - :return: List[:class:`BoundAction `] + :param floating_ip: Floating IP to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages( self.get_actions_list, diff --git a/plugins/module_utils/vendor/hcloud/floating_ips/domain.py b/plugins/module_utils/vendor/hcloud/floating_ips/domain.py index e2ef74a..3946da7 100644 --- a/plugins/module_utils/vendor/hcloud/floating_ips/domain.py +++ b/plugins/module_utils/vendor/hcloud/floating_ips/domain.py @@ -1,21 +1,24 @@ from __future__ import annotations -from typing import TYPE_CHECKING - -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None +from typing import TYPE_CHECKING, TypedDict from ..core import BaseDomain, DomainIdentityMixin if TYPE_CHECKING: from ..actions import BoundAction from ..locations import BoundLocation + from ..rdns import DNSPtr from ..servers import BoundServer from .client import BoundFloatingIP +__all__ = [ + "FloatingIP", + "FloatingIPProtection", + "CreateFloatingIPResponse", +] + + class FloatingIP(BaseDomain, DomainIdentityMixin): """Floating IP Domain @@ -68,10 +71,10 @@ class FloatingIP(BaseDomain, DomainIdentityMixin): description: str | None = None, ip: str | None = None, server: BoundServer | None = None, - dns_ptr: list[dict] | None = None, + dns_ptr: list[DNSPtr] | None = None, home_location: BoundLocation | None = None, blocked: bool | None = None, - protection: dict | None = None, + protection: FloatingIPProtection | None = None, labels: dict[str, str] | None = None, created: str | None = None, name: str | None = None, @@ -86,10 +89,14 @@ class FloatingIP(BaseDomain, DomainIdentityMixin): self.blocked = blocked self.protection = protection self.labels = labels - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) self.name = name +class FloatingIPProtection(TypedDict): + delete: bool + + class CreateFloatingIPResponse(BaseDomain): """Create Floating IP Response Domain diff --git a/plugins/module_utils/vendor/hcloud/helpers/__init__.py b/plugins/module_utils/vendor/hcloud/helpers/__init__.py index 044703b..e8ec1dc 100644 --- a/plugins/module_utils/vendor/hcloud/helpers/__init__.py +++ b/plugins/module_utils/vendor/hcloud/helpers/__init__.py @@ -2,4 +2,6 @@ from __future__ import annotations from .labels import LabelValidator -__all__ = ["LabelValidator"] +__all__ = [ + "LabelValidator", +] diff --git a/plugins/module_utils/vendor/hcloud/helpers/labels.py b/plugins/module_utils/vendor/hcloud/helpers/labels.py index 3604157..78f4314 100644 --- a/plugins/module_utils/vendor/hcloud/helpers/labels.py +++ b/plugins/module_utils/vendor/hcloud/helpers/labels.py @@ -2,6 +2,10 @@ from __future__ import annotations import re +__all__ = [ + "LabelValidator", +] + class LabelValidator: KEY_REGEX = re.compile( diff --git a/plugins/module_utils/vendor/hcloud/images/__init__.py b/plugins/module_utils/vendor/hcloud/images/__init__.py index 071a92b..c299722 100644 --- a/plugins/module_utils/vendor/hcloud/images/__init__.py +++ b/plugins/module_utils/vendor/hcloud/images/__init__.py @@ -1,12 +1,13 @@ from __future__ import annotations from .client import BoundImage, ImagesClient, ImagesPageResult -from .domain import CreateImageResponse, Image +from .domain import CreateImageResponse, Image, ImageProtection __all__ = [ "BoundImage", "CreateImageResponse", "Image", + "ImageProtection", "ImagesClient", "ImagesPageResult", ] diff --git a/plugins/module_utils/vendor/hcloud/images/client.py b/plugins/module_utils/vendor/hcloud/images/client.py index b9425b7..2566a96 100644 --- a/plugins/module_utils/vendor/hcloud/images/client.py +++ b/plugins/module_utils/vendor/hcloud/images/client.py @@ -3,7 +3,14 @@ from __future__ import annotations import warnings from typing import TYPE_CHECKING, Any, NamedTuple -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import Image @@ -11,12 +18,23 @@ if TYPE_CHECKING: from .._client import Client -class BoundImage(BoundModelBase, Image): +__all__ = [ + "BoundImage", + "ImagesPageResult", + "ImagesClient", +] + + +class BoundImage(BoundModelBase[Image], Image): _client: ImagesClient model = Image - def __init__(self, client: ImagesClient, data: dict): + def __init__( + self, + client: ImagesClient, + data: dict[str, Any], + ): # pylint: disable=import-outside-toplevel from ..servers import BoundServer @@ -35,22 +53,18 @@ class BoundImage(BoundModelBase, Image): def get_actions_list( self, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, - status: list[str] | None = None, ) -> ActionsPageResult: - """Returns a list of action objects for the image. + """ + Returns a paginated list of Actions for a Image. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ return self._client.get_actions_list( self, @@ -62,16 +76,14 @@ class BoundImage(BoundModelBase, Image): def get_actions( self, - sort: list[str] | None = None, - status: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for the image. + """ + Returns all Actions for a Image. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._client.get_actions( self, @@ -122,7 +134,10 @@ class ImagesPageResult(NamedTuple): meta: Meta -class ImagesClient(ResourceClientBase): +class ImagesClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _base_url = "/images" actions: ResourceActionsClient @@ -138,64 +153,46 @@ class ImagesClient(ResourceClientBase): def get_actions_list( self, image: Image | BoundImage, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, - status: list[str] | None = None, ) -> ActionsPageResult: - """Returns a list of action objects for an image. - - :param image: :class:`BoundImage ` or :class:`Image ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) """ - params: dict[str, Any] = {} - if sort is not None: - params["sort"] = sort - if status is not None: - params["status"] = status - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page - response = self._client.request( - url=f"{self._base_url}/{image.id}/actions", - method="GET", - params=params, + Returns a paginated list of Actions for a Image. + + :param image: Image to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + f"{self._base_url}/{image.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) - actions = [ - BoundAction(self._parent.actions, action_data) - for action_data in response["actions"] - ] - return ActionsPageResult(actions, Meta.parse_meta(response)) def get_actions( self, image: Image | BoundImage, - sort: list[str] | None = None, - status: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for an image. + """ + Returns all Actions for a Image. - :param image: :class:`BoundImage ` or :class:`Image ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `command` `status` `progress` `started` `finished` . You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default) - :return: List[:class:`BoundAction `] + :param image: Image to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages( self.get_actions_list, image, - sort=sort, status=status, + sort=sort, ) def get_by_id(self, id: int) -> BoundImage: diff --git a/plugins/module_utils/vendor/hcloud/images/domain.py b/plugins/module_utils/vendor/hcloud/images/domain.py index 907fa7b..915ace6 100644 --- a/plugins/module_utils/vendor/hcloud/images/domain.py +++ b/plugins/module_utils/vendor/hcloud/images/domain.py @@ -1,11 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING - -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None +from typing import TYPE_CHECKING, TypedDict from ..core import BaseDomain, DomainIdentityMixin @@ -15,6 +10,13 @@ if TYPE_CHECKING: from .client import BoundImage +__all__ = [ + "Image", + "ImageProtection", + "CreateImageResponse", +] + + class Image(BaseDomain, DomainIdentityMixin): """Image Domain @@ -92,18 +94,18 @@ class Image(BaseDomain, DomainIdentityMixin): architecture: str | None = None, rapid_deploy: bool | None = None, created_from: Server | BoundServer | None = None, - protection: dict | None = None, + protection: ImageProtection | None = None, labels: dict[str, str] | None = None, status: str | None = None, ): self.id = id self.name = name self.type = type - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) self.description = description self.image_size = image_size self.disk_size = disk_size - self.deprecated = isoparse(deprecated) if deprecated else None + self.deprecated = self._parse_datetime(deprecated) self.bound_to = bound_to self.os_flavor = os_flavor self.os_version = os_version @@ -115,6 +117,10 @@ class Image(BaseDomain, DomainIdentityMixin): self.status = status +class ImageProtection(TypedDict): + delete: bool + + class CreateImageResponse(BaseDomain): """Create Image Response Domain diff --git a/plugins/module_utils/vendor/hcloud/isos/client.py b/plugins/module_utils/vendor/hcloud/isos/client.py index d5e4496..b9c3a5a 100644 --- a/plugins/module_utils/vendor/hcloud/isos/client.py +++ b/plugins/module_utils/vendor/hcloud/isos/client.py @@ -5,8 +5,14 @@ from typing import Any, NamedTuple from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import Iso +__all__ = [ + "BoundIso", + "IsosPageResult", + "IsosClient", +] -class BoundIso(BoundModelBase, Iso): + +class BoundIso(BoundModelBase[Iso], Iso): _client: IsosClient model = Iso diff --git a/plugins/module_utils/vendor/hcloud/isos/domain.py b/plugins/module_utils/vendor/hcloud/isos/domain.py index 2a5667e..5fd50c6 100644 --- a/plugins/module_utils/vendor/hcloud/isos/domain.py +++ b/plugins/module_utils/vendor/hcloud/isos/domain.py @@ -1,11 +1,16 @@ from __future__ import annotations from datetime import datetime +from typing import Any from warnings import warn from ..core import BaseDomain, DomainIdentityMixin from ..deprecation import DeprecationInfo +__all__ = [ + "Iso", +] + class Iso(BaseDomain, DomainIdentityMixin): """Iso Domain @@ -45,7 +50,7 @@ class Iso(BaseDomain, DomainIdentityMixin): architecture: str | None = None, description: str | None = None, deprecated: str | None = None, # pylint: disable=unused-argument - deprecation: dict | None = None, + deprecation: dict[str, Any] | None = None, ): self.id = id self.name = name @@ -67,4 +72,4 @@ class Iso(BaseDomain, DomainIdentityMixin): ) if self.deprecation is None: return None - return self.deprecation.unavailable_after + return self.deprecation.unavailable_after # type: ignore[no-any-return] diff --git a/plugins/module_utils/vendor/hcloud/load_balancer_types/client.py b/plugins/module_utils/vendor/hcloud/load_balancer_types/client.py index fbfb08d..87d44e2 100644 --- a/plugins/module_utils/vendor/hcloud/load_balancer_types/client.py +++ b/plugins/module_utils/vendor/hcloud/load_balancer_types/client.py @@ -5,8 +5,14 @@ from typing import Any, NamedTuple from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import LoadBalancerType +__all__ = [ + "BoundLoadBalancerType", + "LoadBalancerTypesPageResult", + "LoadBalancerTypesClient", +] -class BoundLoadBalancerType(BoundModelBase, LoadBalancerType): + +class BoundLoadBalancerType(BoundModelBase[LoadBalancerType], LoadBalancerType): _client: LoadBalancerTypesClient model = LoadBalancerType diff --git a/plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py b/plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py index 9142cb5..1e594e9 100644 --- a/plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py +++ b/plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py @@ -1,7 +1,13 @@ from __future__ import annotations +from typing import Any + from ..core import BaseDomain, DomainIdentityMixin +__all__ = [ + "LoadBalancerType", +] + class LoadBalancerType(BaseDomain, DomainIdentityMixin): """LoadBalancerType Domain @@ -46,7 +52,7 @@ class LoadBalancerType(BaseDomain, DomainIdentityMixin): max_services: int | None = None, max_targets: int | None = None, max_assigned_certificates: int | None = None, - prices: list[dict] | None = None, + prices: list[dict[str, Any]] | None = None, ): self.id = id self.name = name diff --git a/plugins/module_utils/vendor/hcloud/load_balancers/__init__.py b/plugins/module_utils/vendor/hcloud/load_balancers/__init__.py index f84c7e2..9b07d02 100644 --- a/plugins/module_utils/vendor/hcloud/load_balancers/__init__.py +++ b/plugins/module_utils/vendor/hcloud/load_balancers/__init__.py @@ -15,12 +15,14 @@ from .domain import ( LoadBalancerHealtCheckHttp, LoadBalancerHealthCheck, LoadBalancerHealthCheckHttp, + LoadBalancerProtection, LoadBalancerService, LoadBalancerServiceHttp, LoadBalancerTarget, LoadBalancerTargetHealthStatus, LoadBalancerTargetIP, LoadBalancerTargetLabelSelector, + MetricsType, PrivateNet, PublicNetwork, ) @@ -32,6 +34,7 @@ __all__ = [ "IPv4Address", "IPv6Network", "LoadBalancer", + "LoadBalancerProtection", "LoadBalancerAlgorithm", "LoadBalancerHealtCheckHttp", "LoadBalancerHealthCheckHttp", @@ -46,4 +49,5 @@ __all__ = [ "LoadBalancersPageResult", "PrivateNet", "PublicNetwork", + "MetricsType", ] diff --git a/plugins/module_utils/vendor/hcloud/load_balancers/client.py b/plugins/module_utils/vendor/hcloud/load_balancers/client.py index 45c7464..c711fc2 100644 --- a/plugins/module_utils/vendor/hcloud/load_balancers/client.py +++ b/plugins/module_utils/vendor/hcloud/load_balancers/client.py @@ -8,7 +8,14 @@ try: except ImportError: isoparse = None -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..certificates import BoundCertificate from ..core import BoundModelBase, Meta, ResourceClientBase from ..load_balancer_types import BoundLoadBalancerType @@ -43,13 +50,25 @@ if TYPE_CHECKING: from ..networks import Network -class BoundLoadBalancer(BoundModelBase, LoadBalancer): +__all__ = [ + "BoundLoadBalancer", + "LoadBalancersPageResult", + "LoadBalancersClient", +] + + +class BoundLoadBalancer(BoundModelBase[LoadBalancer], LoadBalancer): _client: LoadBalancersClient model = LoadBalancer # pylint: disable=too-many-branches,too-many-locals - def __init__(self, client: LoadBalancersClient, data: dict, complete: bool = True): + def __init__( + self, + client: LoadBalancersClient, + data: dict[str, Any], + complete: bool = True, + ): algorithm = data.get("algorithm") if algorithm: data["algorithm"] = LoadBalancerAlgorithm(type=algorithm["type"]) @@ -210,22 +229,18 @@ class BoundLoadBalancer(BoundModelBase, LoadBalancer): def get_actions_list( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a Load Balancer. + """ + Returns a paginated list of Actions for a Load Balancer. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ return self._client.get_actions_list( self, @@ -237,16 +252,14 @@ class BoundLoadBalancer(BoundModelBase, LoadBalancer): def get_actions( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a Load Balancer. + """ + Returns all Actions for a Load Balancer. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._client.get_actions(self, status=status, sort=sort) @@ -386,7 +399,10 @@ class LoadBalancersPageResult(NamedTuple): meta: Meta -class LoadBalancersClient(ResourceClientBase): +class LoadBalancersClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _base_url = "/load_balancers" actions: ResourceActionsClient @@ -619,59 +635,40 @@ class LoadBalancersClient(ResourceClientBase): def get_actions_list( self, load_balancer: LoadBalancer | BoundLoadBalancer, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a Load Balancer. - - :param load_balancer: :class:`BoundLoadBalancer ` or :class:`LoadBalancer ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page + Returns a paginated list of Actions for a Load Balancer. - response = self._client.request( - url=f"{self._base_url}/{load_balancer.id}/actions", - method="GET", - params=params, + :param load_balancer: Load Balancer to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + f"{self._base_url}/{load_balancer.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) - actions = [ - BoundAction(self._parent.actions, action_data) - for action_data in response["actions"] - ] - return ActionsPageResult(actions, Meta.parse_meta(response)) def get_actions( self, load_balancer: LoadBalancer | BoundLoadBalancer, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a Load Balancer. + """ + Returns all Actions for a Load Balancer. - :param load_balancer: :class:`BoundLoadBalancer ` or :class:`LoadBalancer ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param load_balancer: Load Balancer to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages( self.get_actions_list, diff --git a/plugins/module_utils/vendor/hcloud/load_balancers/domain.py b/plugins/module_utils/vendor/hcloud/load_balancers/domain.py index d2a9adc..c02e110 100644 --- a/plugins/module_utils/vendor/hcloud/load_balancers/domain.py +++ b/plugins/module_utils/vendor/hcloud/load_balancers/domain.py @@ -1,12 +1,7 @@ from __future__ import annotations import warnings -from typing import TYPE_CHECKING, Any, Literal - -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None +from typing import TYPE_CHECKING, Any, Literal, TypedDict from ..core import BaseDomain, DomainIdentityMixin @@ -21,6 +16,29 @@ if TYPE_CHECKING: from .client import BoundLoadBalancer +__all__ = [ + "LoadBalancer", + "LoadBalancerProtection", + "LoadBalancerService", + "LoadBalancerServiceHttp", + "LoadBalancerHealthCheck", + "LoadBalancerHealthCheckHttp", + "LoadBalancerHealtCheckHttp", + "LoadBalancerTarget", + "LoadBalancerTargetHealthStatus", + "LoadBalancerTargetLabelSelector", + "LoadBalancerTargetIP", + "LoadBalancerAlgorithm", + "PublicNetwork", + "IPv4Address", + "IPv6Network", + "PrivateNet", + "CreateLoadBalancerResponse", + "GetMetricsResponse", + "MetricsType", +] + + class LoadBalancer(BaseDomain, DomainIdentityMixin): """LoadBalancer Domain @@ -86,7 +104,7 @@ class LoadBalancer(BaseDomain, DomainIdentityMixin): algorithm: LoadBalancerAlgorithm | None = None, services: list[LoadBalancerService] | None = None, load_balancer_type: BoundLoadBalancerType | None = None, - protection: dict | None = None, + protection: LoadBalancerProtection | None = None, labels: dict[str, str] | None = None, targets: list[LoadBalancerTarget] | None = None, created: str | None = None, @@ -96,7 +114,7 @@ class LoadBalancer(BaseDomain, DomainIdentityMixin): ): self.id = id self.name = name - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) self.public_net = public_net self.private_net = private_net self.location = location @@ -121,6 +139,10 @@ class LoadBalancer(BaseDomain, DomainIdentityMixin): return None +class LoadBalancerProtection(TypedDict): + delete: bool + + class LoadBalancerService(BaseDomain): """LoadBalancerService Domain @@ -339,7 +361,7 @@ class LoadBalancerHealthCheckHttp(BaseDomain): domain: str | None = None, path: str | None = None, response: str | None = None, - status_codes: list | None = None, + status_codes: list[str] | None = None, tls: bool | None = None, ): self.domain = domain @@ -362,7 +384,7 @@ class LoadBalancerHealtCheckHttp(LoadBalancerHealthCheckHttp): domain: str | None = None, path: str | None = None, response: str | None = None, - status_codes: list | None = None, + status_codes: list[str] | None = None, tls: bool | None = None, ): warnings.warn( diff --git a/plugins/module_utils/vendor/hcloud/locations/client.py b/plugins/module_utils/vendor/hcloud/locations/client.py index e6f685d..5a71c0f 100644 --- a/plugins/module_utils/vendor/hcloud/locations/client.py +++ b/plugins/module_utils/vendor/hcloud/locations/client.py @@ -5,8 +5,14 @@ from typing import Any, NamedTuple from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import Location +__all__ = [ + "BoundLocation", + "LocationsPageResult", + "LocationsClient", +] -class BoundLocation(BoundModelBase, Location): + +class BoundLocation(BoundModelBase[Location], Location): _client: LocationsClient model = Location diff --git a/plugins/module_utils/vendor/hcloud/locations/domain.py b/plugins/module_utils/vendor/hcloud/locations/domain.py index dcdf7a9..b33b157 100644 --- a/plugins/module_utils/vendor/hcloud/locations/domain.py +++ b/plugins/module_utils/vendor/hcloud/locations/domain.py @@ -2,6 +2,10 @@ from __future__ import annotations from ..core import BaseDomain, DomainIdentityMixin +__all__ = [ + "Location", +] + class Location(BaseDomain, DomainIdentityMixin): """Location Domain diff --git a/plugins/module_utils/vendor/hcloud/metrics/domain.py b/plugins/module_utils/vendor/hcloud/metrics/domain.py index 7f29128..3213e27 100644 --- a/plugins/module_utils/vendor/hcloud/metrics/domain.py +++ b/plugins/module_utils/vendor/hcloud/metrics/domain.py @@ -3,13 +3,14 @@ from __future__ import annotations from datetime import datetime from typing import Literal -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None - from ..core import BaseDomain +__all__ = [ + "TimeSeries", + "Metrics", +] + + TimeSeries = dict[str, dict[Literal["values"], list[tuple[float, str]]]] @@ -44,7 +45,7 @@ class Metrics(BaseDomain): step: float, time_series: TimeSeries, ): - self.start = isoparse(start) - self.end = isoparse(end) + self.start = self._parse_datetime(start) + self.end = self._parse_datetime(end) self.step = step self.time_series = time_series diff --git a/plugins/module_utils/vendor/hcloud/networks/__init__.py b/plugins/module_utils/vendor/hcloud/networks/__init__.py index fc86564..f49b993 100644 --- a/plugins/module_utils/vendor/hcloud/networks/__init__.py +++ b/plugins/module_utils/vendor/hcloud/networks/__init__.py @@ -4,6 +4,7 @@ from .client import BoundNetwork, NetworksClient, NetworksPageResult from .domain import ( CreateNetworkResponse, Network, + NetworkProtection, NetworkRoute, NetworkSubnet, ) @@ -12,6 +13,7 @@ __all__ = [ "BoundNetwork", "CreateNetworkResponse", "Network", + "NetworkProtection", "NetworkRoute", "NetworkSubnet", "NetworksClient", diff --git a/plugins/module_utils/vendor/hcloud/networks/client.py b/plugins/module_utils/vendor/hcloud/networks/client.py index abef2b6..73b33e5 100644 --- a/plugins/module_utils/vendor/hcloud/networks/client.py +++ b/plugins/module_utils/vendor/hcloud/networks/client.py @@ -2,7 +2,14 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, NamedTuple -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import Network, NetworkRoute, NetworkSubnet @@ -10,12 +17,24 @@ if TYPE_CHECKING: from .._client import Client -class BoundNetwork(BoundModelBase, Network): +__all__ = [ + "BoundNetwork", + "NetworksPageResult", + "NetworksClient", +] + + +class BoundNetwork(BoundModelBase[Network], Network): _client: NetworksClient model = Network - def __init__(self, client: NetworksClient, data: dict, complete: bool = True): + def __init__( + self, + client: NetworksClient, + data: dict[str, Any], + complete: bool = True, + ): subnets = data.get("subnets", []) if subnets is not None: subnets = [NetworkSubnet.from_dict(subnet) for subnet in subnets] @@ -72,22 +91,18 @@ class BoundNetwork(BoundModelBase, Network): def get_actions_list( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a network. + """ + Returns a paginated list of Actions for a Network. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ return self._client.get_actions_list( self, @@ -99,16 +114,14 @@ class BoundNetwork(BoundModelBase, Network): def get_actions( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a network. + """ + Returns all Actions for a Network. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._client.get_actions(self, status=status, sort=sort) @@ -172,7 +185,10 @@ class NetworksPageResult(NamedTuple): meta: Meta -class NetworksClient(ResourceClientBase): +class NetworksClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _base_url = "/networks" actions: ResourceActionsClient @@ -359,59 +375,40 @@ class NetworksClient(ResourceClientBase): def get_actions_list( self, network: Network | BoundNetwork, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a network. - - :param network: :class:`BoundNetwork ` or :class:`Network ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page + Returns a paginated list of Actions for a Network. - response = self._client.request( - url=f"{self._base_url}/{network.id}/actions", - method="GET", - params=params, + :param network: Network to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + f"{self._base_url}/{network.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) - actions = [ - BoundAction(self._parent.actions, action_data) - for action_data in response["actions"] - ] - return ActionsPageResult(actions, Meta.parse_meta(response)) def get_actions( self, network: Network | BoundNetwork, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a network. + """ + Returns all Actions for a Network. - :param network: :class:`BoundNetwork ` or :class:`Network ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param network: Network to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages( self.get_actions_list, diff --git a/plugins/module_utils/vendor/hcloud/networks/domain.py b/plugins/module_utils/vendor/hcloud/networks/domain.py index 3c5f02d..80c3bad 100644 --- a/plugins/module_utils/vendor/hcloud/networks/domain.py +++ b/plugins/module_utils/vendor/hcloud/networks/domain.py @@ -1,12 +1,7 @@ from __future__ import annotations import warnings -from typing import TYPE_CHECKING - -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None +from typing import TYPE_CHECKING, TypedDict from ..core import BaseDomain, DomainIdentityMixin @@ -15,6 +10,14 @@ if TYPE_CHECKING: from ..servers import BoundServer from .client import BoundNetwork +__all__ = [ + "Network", + "NetworkProtection", + "NetworkSubnet", + "NetworkRoute", + "CreateNetworkResponse", +] + class Network(BaseDomain, DomainIdentityMixin): """Network Domain @@ -63,12 +66,12 @@ class Network(BaseDomain, DomainIdentityMixin): routes: list[NetworkRoute] | None = None, expose_routes_to_vswitch: bool | None = None, servers: list[BoundServer] | None = None, - protection: dict | None = None, + protection: NetworkProtection | None = None, labels: dict[str, str] | None = None, ): self.id = id self.name = name - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) self.ip_range = ip_range self.subnets = subnets self.routes = routes @@ -78,6 +81,10 @@ class Network(BaseDomain, DomainIdentityMixin): self.labels = labels +class NetworkProtection(TypedDict): + delete: bool + + class NetworkSubnet(BaseDomain): """Network Subnet Domain @@ -116,7 +123,7 @@ class NetworkSubnet(BaseDomain): """ Used to connect cloud servers and load balancers with dedicated servers. - See https://docs.hetzner.com/cloud/networks/connect-dedi-vswitch/ + See https://docs.hetzner.com/networking/networks/connect-dedi-vswitch/ """ __api_properties__ = ("type", "ip_range", "network_zone", "gateway", "vswitch_id") diff --git a/plugins/module_utils/vendor/hcloud/placement_groups/client.py b/plugins/module_utils/vendor/hcloud/placement_groups/client.py index 9493934..041118d 100644 --- a/plugins/module_utils/vendor/hcloud/placement_groups/client.py +++ b/plugins/module_utils/vendor/hcloud/placement_groups/client.py @@ -6,8 +6,14 @@ from ..actions import BoundAction from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import CreatePlacementGroupResponse, PlacementGroup +__all__ = [ + "BoundPlacementGroup", + "PlacementGroupsPageResult", + "PlacementGroupsClient", +] -class BoundPlacementGroup(BoundModelBase, PlacementGroup): + +class BoundPlacementGroup(BoundModelBase[PlacementGroup], PlacementGroup): _client: PlacementGroupsClient model = PlacementGroup diff --git a/plugins/module_utils/vendor/hcloud/placement_groups/domain.py b/plugins/module_utils/vendor/hcloud/placement_groups/domain.py index 950eeba..1dc9b9d 100644 --- a/plugins/module_utils/vendor/hcloud/placement_groups/domain.py +++ b/plugins/module_utils/vendor/hcloud/placement_groups/domain.py @@ -2,17 +2,17 @@ from __future__ import annotations from typing import TYPE_CHECKING -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None - from ..core import BaseDomain, DomainIdentityMixin if TYPE_CHECKING: from ..actions import BoundAction from .client import BoundPlacementGroup +__all__ = [ + "PlacementGroup", + "CreatePlacementGroupResponse", +] + class PlacementGroup(BaseDomain, DomainIdentityMixin): """Placement Group Domain @@ -53,7 +53,7 @@ class PlacementGroup(BaseDomain, DomainIdentityMixin): self.labels = labels self.servers = servers self.type = type - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) class CreatePlacementGroupResponse(BaseDomain): diff --git a/plugins/module_utils/vendor/hcloud/primary_ips/__init__.py b/plugins/module_utils/vendor/hcloud/primary_ips/__init__.py index 3dc5ed0..9997404 100644 --- a/plugins/module_utils/vendor/hcloud/primary_ips/__init__.py +++ b/plugins/module_utils/vendor/hcloud/primary_ips/__init__.py @@ -1,12 +1,13 @@ from __future__ import annotations from .client import BoundPrimaryIP, PrimaryIPsClient, PrimaryIPsPageResult -from .domain import CreatePrimaryIPResponse, PrimaryIP +from .domain import CreatePrimaryIPResponse, PrimaryIP, PrimaryIPProtection __all__ = [ "BoundPrimaryIP", "CreatePrimaryIPResponse", "PrimaryIP", + "PrimaryIPProtection", "PrimaryIPsClient", "PrimaryIPsPageResult", ] diff --git a/plugins/module_utils/vendor/hcloud/primary_ips/client.py b/plugins/module_utils/vendor/hcloud/primary_ips/client.py index eb5d30d..6d6693d 100644 --- a/plugins/module_utils/vendor/hcloud/primary_ips/client.py +++ b/plugins/module_utils/vendor/hcloud/primary_ips/client.py @@ -1,31 +1,97 @@ from __future__ import annotations +import warnings from typing import TYPE_CHECKING, Any, NamedTuple -from ..actions import BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import CreatePrimaryIPResponse, PrimaryIP if TYPE_CHECKING: from .._client import Client from ..datacenters import BoundDatacenter, Datacenter + from ..locations import BoundLocation, Location -class BoundPrimaryIP(BoundModelBase, PrimaryIP): +__all__ = [ + "BoundPrimaryIP", + "PrimaryIPsPageResult", + "PrimaryIPsClient", +] + + +class BoundPrimaryIP(BoundModelBase[PrimaryIP], PrimaryIP): _client: PrimaryIPsClient model = PrimaryIP - def __init__(self, client: PrimaryIPsClient, data: dict, complete: bool = True): + def __init__( + self, + client: PrimaryIPsClient, + data: dict[str, Any], + complete: bool = True, + ): # pylint: disable=import-outside-toplevel from ..datacenters import BoundDatacenter + from ..locations import BoundLocation - datacenter = data.get("datacenter", {}) - if datacenter: - data["datacenter"] = BoundDatacenter(client._parent.datacenters, datacenter) + raw = data.get("datacenter", {}) + if raw: + data["datacenter"] = BoundDatacenter(client._parent.datacenters, raw) + + raw = data.get("location", {}) + if raw: + data["location"] = BoundLocation(client._parent.locations, raw) super().__init__(client, data, complete) + def get_actions_list( + self, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, + page: int | None = None, + per_page: int | None = None, + ) -> ActionsPageResult: + """ + Returns a paginated list of Actions for a Primary IP. + + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._client.get_actions_list( + self, + status=status, + sort=sort, + page=page, + per_page=per_page, + ) + + def get_actions( + self, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, + ) -> list[BoundAction]: + """ + Returns all Actions for a Primary IP. + + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + """ + return self._client.get_actions( + self, + status=status, + sort=sort, + ) + def update( self, auto_delete: bool | None = None, @@ -102,7 +168,10 @@ class PrimaryIPsPageResult(NamedTuple): meta: Meta -class PrimaryIPsClient(ResourceClientBase): +class PrimaryIPsClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _base_url = "/primary_ips" actions: ResourceActionsClient @@ -115,6 +184,51 @@ class PrimaryIPsClient(ResourceClientBase): super().__init__(client) self.actions = ResourceActionsClient(client, self._base_url) + def get_actions_list( + self, + primary_ip: PrimaryIP | BoundPrimaryIP, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, + page: int | None = None, + per_page: int | None = None, + ) -> ActionsPageResult: + """ + Returns a paginated list of Actions for a Primary IP. + + :param primary_ip: Primary IP to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + f"{self._base_url}/{primary_ip.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, + ) + + def get_actions( + self, + primary_ip: PrimaryIP | BoundPrimaryIP, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, + ) -> list[BoundAction]: + """ + Returns all Actions for a Primary IP. + + :param primary_ip: Primary IP to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + """ + return self._iter_pages( + self.get_actions_list, + primary_ip, + status=status, + sort=sort, + ) + def get_by_id(self, id: int) -> BoundPrimaryIP: """Returns a specific Primary IP object. @@ -196,16 +310,18 @@ class PrimaryIPsClient(ResourceClientBase): type: str, name: str, datacenter: Datacenter | BoundDatacenter | None = None, + location: Location | BoundLocation | None = None, assignee_type: str | None = "server", assignee_id: int | None = None, auto_delete: bool | None = False, - labels: dict | None = None, + labels: dict[str, str] | None = None, ) -> CreatePrimaryIPResponse: """Creates a new Primary IP assigned to a server. :param type: str Primary IP type Choices: ipv4, ipv6 :param name: str :param datacenter: Datacenter (optional) + :param location: Location (optional) :param assignee_type: str (optional) :param assignee_id: int (optional) :param auto_delete: bool (optional) @@ -220,7 +336,16 @@ class PrimaryIPsClient(ResourceClientBase): "auto_delete": auto_delete, } if datacenter is not None: + warnings.warn( + "The 'datacenter' argument is deprecated and will be removed after 1 July 2026. " + "Please use the 'location' argument instead. " + "See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters", + DeprecationWarning, + stacklevel=2, + ) data["datacenter"] = datacenter.id_or_name + if location is not None: + data["location"] = location.id_or_name if assignee_id is not None: data["assignee_id"] = assignee_id if labels is not None: diff --git a/plugins/module_utils/vendor/hcloud/primary_ips/domain.py b/plugins/module_utils/vendor/hcloud/primary_ips/domain.py index 83e5d7b..96749be 100644 --- a/plugins/module_utils/vendor/hcloud/primary_ips/domain.py +++ b/plugins/module_utils/vendor/hcloud/primary_ips/domain.py @@ -1,19 +1,23 @@ from __future__ import annotations -from typing import TYPE_CHECKING - -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None +import warnings +from typing import TYPE_CHECKING, TypedDict from ..core import BaseDomain, DomainIdentityMixin if TYPE_CHECKING: from ..actions import BoundAction from ..datacenters import BoundDatacenter + from ..locations import BoundLocation + from ..rdns import DNSPtr from .client import BoundPrimaryIP +__all__ = [ + "PrimaryIP", + "PrimaryIPProtection", + "CreatePrimaryIPResponse", +] + class PrimaryIP(BaseDomain, DomainIdentityMixin): """Primary IP Domain @@ -27,7 +31,15 @@ class PrimaryIP(BaseDomain, DomainIdentityMixin): :param dns_ptr: List[Dict] Array of reverse DNS entries :param datacenter: :class:`Datacenter ` - Datacenter the Primary IP was created in. + Datacenter the Primary IP was created in. + + This property is deprecated and will be removed after 1 July 2026. + Please use the ``location`` property instead. + + See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters. + + :param location: :class:`Location ` + Location the Primary IP was created in. :param blocked: boolean Whether the IP is blocked :param protection: dict @@ -46,12 +58,12 @@ class PrimaryIP(BaseDomain, DomainIdentityMixin): Delete the Primary IP when the Assignee it is assigned to is deleted. """ - __api_properties__ = ( + __properties__ = ( "id", "ip", "type", "dns_ptr", - "datacenter", + "location", "blocked", "protection", "labels", @@ -61,18 +73,26 @@ class PrimaryIP(BaseDomain, DomainIdentityMixin): "assignee_type", "auto_delete", ) - __slots__ = __api_properties__ + __api_properties__ = ( + *__properties__, + "datacenter", + ) + __slots__ = ( + *__properties__, + "_datacenter", + ) def __init__( self, id: int | None = None, type: str | None = None, ip: str | None = None, - dns_ptr: list[dict] | None = None, + dns_ptr: list[DNSPtr] | None = None, datacenter: BoundDatacenter | None = None, + location: BoundLocation | None = None, blocked: bool | None = None, - protection: dict | None = None, - labels: dict[str, dict] | None = None, + protection: PrimaryIPProtection | None = None, + labels: dict[str, str] | None = None, created: str | None = None, name: str | None = None, assignee_id: int | None = None, @@ -84,15 +104,38 @@ class PrimaryIP(BaseDomain, DomainIdentityMixin): self.ip = ip self.dns_ptr = dns_ptr self.datacenter = datacenter + self.location = location self.blocked = blocked self.protection = protection self.labels = labels - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) self.name = name self.assignee_id = assignee_id self.assignee_type = assignee_type self.auto_delete = auto_delete + @property + def datacenter(self) -> BoundDatacenter | None: + """ + :meta private: + """ + warnings.warn( + "The 'datacenter' property is deprecated and will be removed after 1 July 2026. " + "Please use the 'location' property instead. " + "See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters.", + DeprecationWarning, + stacklevel=2, + ) + return self._datacenter + + @datacenter.setter + def datacenter(self, value: BoundDatacenter | None) -> None: + self._datacenter = value + + +class PrimaryIPProtection(TypedDict): + delete: bool + class CreatePrimaryIPResponse(BaseDomain): """Create Primary IP Response Domain diff --git a/plugins/module_utils/vendor/hcloud/rdns/__init__.py b/plugins/module_utils/vendor/hcloud/rdns/__init__.py new file mode 100644 index 0000000..116a632 --- /dev/null +++ b/plugins/module_utils/vendor/hcloud/rdns/__init__.py @@ -0,0 +1,7 @@ +from __future__ import annotations + +from .domain import DNSPtr + +__all__ = [ + "DNSPtr", +] diff --git a/plugins/module_utils/vendor/hcloud/rdns/domain.py b/plugins/module_utils/vendor/hcloud/rdns/domain.py new file mode 100644 index 0000000..e0e5ac6 --- /dev/null +++ b/plugins/module_utils/vendor/hcloud/rdns/domain.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +from typing import TypedDict + +__all__ = [ + "DNSPtr", +] + + +class DNSPtr(TypedDict): + ip: str + dns_ptr: str diff --git a/plugins/module_utils/vendor/hcloud/server_types/client.py b/plugins/module_utils/vendor/hcloud/server_types/client.py index db0ef54..98da70a 100644 --- a/plugins/module_utils/vendor/hcloud/server_types/client.py +++ b/plugins/module_utils/vendor/hcloud/server_types/client.py @@ -6,8 +6,14 @@ from ..core import BoundModelBase, Meta, ResourceClientBase from ..locations import BoundLocation from .domain import ServerType, ServerTypeLocation +__all__ = [ + "BoundServerType", + "ServerTypesPageResult", + "ServerTypesClient", +] -class BoundServerType(BoundModelBase, ServerType): + +class BoundServerType(BoundModelBase[ServerType], ServerType): _client: ServerTypesClient model = ServerType @@ -15,7 +21,7 @@ class BoundServerType(BoundModelBase, ServerType): def __init__( self, client: ServerTypesClient, - data: dict, + data: dict[str, Any], complete: bool = True, ): raw = data.get("locations") diff --git a/plugins/module_utils/vendor/hcloud/server_types/domain.py b/plugins/module_utils/vendor/hcloud/server_types/domain.py index ff9e3fd..279d928 100644 --- a/plugins/module_utils/vendor/hcloud/server_types/domain.py +++ b/plugins/module_utils/vendor/hcloud/server_types/domain.py @@ -1,11 +1,17 @@ from __future__ import annotations import warnings +from typing import Any from ..core import BaseDomain, DomainIdentityMixin from ..deprecation import DeprecationInfo from ..locations import BoundLocation +__all__ = [ + "ServerType", + "ServerTypeLocation", +] + class ServerType(BaseDomain, DomainIdentityMixin): """ServerType Domain @@ -79,12 +85,12 @@ class ServerType(BaseDomain, DomainIdentityMixin): cores: int | None = None, memory: int | None = None, disk: int | None = None, - prices: list[dict] | None = None, + prices: list[dict[str, Any]] | None = None, storage_type: str | None = None, cpu_type: str | None = None, architecture: str | None = None, deprecated: bool | None = None, - deprecation: dict | None = None, + deprecation: dict[str, Any] | None = None, included_traffic: int | None = None, locations: list[ServerTypeLocation] | None = None, ): @@ -191,7 +197,7 @@ class ServerTypeLocation(BaseDomain): self, *, location: BoundLocation, - deprecation: dict | None, + deprecation: dict[str, Any] | None, ): self.location = location self.deprecation = ( diff --git a/plugins/module_utils/vendor/hcloud/servers/__init__.py b/plugins/module_utils/vendor/hcloud/servers/__init__.py index 0b02a11..c71c63e 100644 --- a/plugins/module_utils/vendor/hcloud/servers/__init__.py +++ b/plugins/module_utils/vendor/hcloud/servers/__init__.py @@ -7,13 +7,16 @@ from .domain import ( GetMetricsResponse, IPv4Address, IPv6Network, + MetricsType, PrivateNet, PublicNetwork, PublicNetworkFirewall, + RebuildResponse, RequestConsoleResponse, ResetPasswordResponse, Server, ServerCreatePublicNetwork, + ServerProtection, ) __all__ = [ @@ -29,7 +32,10 @@ __all__ = [ "RequestConsoleResponse", "ResetPasswordResponse", "Server", + "ServerProtection", "ServerCreatePublicNetwork", "ServersClient", "ServersPageResult", + "RebuildResponse", + "MetricsType", ] diff --git a/plugins/module_utils/vendor/hcloud/servers/client.py b/plugins/module_utils/vendor/hcloud/servers/client.py index 6aefab0..49cc794 100644 --- a/plugins/module_utils/vendor/hcloud/servers/client.py +++ b/plugins/module_utils/vendor/hcloud/servers/client.py @@ -1,5 +1,6 @@ from __future__ import annotations +import warnings from datetime import datetime from typing import TYPE_CHECKING, Any, NamedTuple @@ -8,13 +9,21 @@ try: except ImportError: isoparse = None -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from ..datacenters import BoundDatacenter from ..firewalls import BoundFirewall from ..floating_ips import BoundFloatingIP from ..images import BoundImage, CreateImageResponse from ..isos import BoundIso +from ..locations import BoundLocation, Location from ..metrics import Metrics from ..placement_groups import BoundPlacementGroup from ..primary_ips import BoundPrimaryIP @@ -42,7 +51,6 @@ if TYPE_CHECKING: from ..firewalls import Firewall from ..images import Image from ..isos import Iso - from ..locations import BoundLocation, Location from ..networks import BoundNetwork, Network from ..placement_groups import PlacementGroup from ..server_types import ServerType @@ -51,16 +59,32 @@ if TYPE_CHECKING: from .domain import ServerCreatePublicNetwork -class BoundServer(BoundModelBase, Server): +__all__ = [ + "BoundServer", + "ServersPageResult", + "ServersClient", +] + + +class BoundServer(BoundModelBase[Server], Server): _client: ServersClient model = Server # pylint: disable=too-many-locals - def __init__(self, client: ServersClient, data: dict, complete: bool = True): - datacenter = data.get("datacenter") - if datacenter is not None: - data["datacenter"] = BoundDatacenter(client._parent.datacenters, datacenter) + def __init__( + self, + client: ServersClient, + data: dict[str, Any], + complete: bool = True, + ): + raw = data.get("datacenter") + if raw: + data["datacenter"] = BoundDatacenter(client._parent.datacenters, raw) + + raw = data.get("location") + if raw: + data["location"] = BoundLocation(client._parent.locations, raw) volumes = data.get("volumes", []) if volumes: @@ -169,22 +193,18 @@ class BoundServer(BoundModelBase, Server): def get_actions_list( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a server. + """ + Returns a paginated list of Actions for a Server. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ return self._client.get_actions_list( self, @@ -196,16 +216,14 @@ class BoundServer(BoundModelBase, Server): def get_actions( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a server. + """ + Returns all Actions for a Server. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._client.get_actions(self, status=status, sort=sort) @@ -506,7 +524,10 @@ class ServersPageResult(NamedTuple): meta: Meta -class ServersClient(ResourceClientBase): +class ServersClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _base_url = "/servers" actions: ResourceActionsClient @@ -660,6 +681,13 @@ class ServersClient(ResourceClientBase): if location is not None: data["location"] = location.id_or_name if datacenter is not None: + warnings.warn( + "The 'datacenter' argument is deprecated and will be removed after 1 July 2026. " + "Please use the 'location' argument instead. " + "See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters", + DeprecationWarning, + stacklevel=2, + ) data["datacenter"] = datacenter.id_or_name if ssh_keys is not None: data["ssh_keys"] = [ssh_key.id_or_name for ssh_key in ssh_keys] @@ -705,59 +733,40 @@ class ServersClient(ResourceClientBase): def get_actions_list( self, server: Server | BoundServer, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a server. - - :param server: :class:`BoundServer ` or :class:`Server ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page + Returns a paginated list of Actions for a Server. - response = self._client.request( - url=f"{self._base_url}/{server.id}/actions", - method="GET", - params=params, + :param server: Server to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + f"{self._base_url}/{server.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) - actions = [ - BoundAction(self._parent.actions, action_data) - for action_data in response["actions"] - ] - return ActionsPageResult(actions, Meta.parse_meta(response)) def get_actions( self, server: Server | BoundServer, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a server. + """ + Returns all Actions for a Server. - :param server: :class:`BoundServer ` or :class:`Server ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param server: Server to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages( self.get_actions_list, diff --git a/plugins/module_utils/vendor/hcloud/servers/domain.py b/plugins/module_utils/vendor/hcloud/servers/domain.py index bc8b79a..ec019e4 100644 --- a/plugins/module_utils/vendor/hcloud/servers/domain.py +++ b/plugins/module_utils/vendor/hcloud/servers/domain.py @@ -1,11 +1,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Literal - -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None +import warnings +from typing import TYPE_CHECKING, Literal, TypedDict from ..core import BaseDomain, DomainIdentityMixin @@ -16,15 +12,36 @@ if TYPE_CHECKING: from ..floating_ips import BoundFloatingIP from ..images import BoundImage from ..isos import BoundIso + from ..locations import BoundLocation from ..metrics import Metrics from ..networks import BoundNetwork, Network from ..placement_groups import BoundPlacementGroup from ..primary_ips import BoundPrimaryIP, PrimaryIP + from ..rdns import DNSPtr from ..server_types import BoundServerType from ..volumes import BoundVolume from .client import BoundServer +__all__ = [ + "Server", + "ServerProtection", + "CreateServerResponse", + "ResetPasswordResponse", + "EnableRescueResponse", + "RequestConsoleResponse", + "RebuildResponse", + "PublicNetwork", + "PublicNetworkFirewall", + "IPv4Address", + "IPv6Network", + "PrivateNet", + "ServerCreatePublicNetwork", + "GetMetricsResponse", + "MetricsType", +] + + class Server(BaseDomain, DomainIdentityMixin): """Server Domain @@ -40,6 +57,12 @@ class Server(BaseDomain, DomainIdentityMixin): Public network information. :param server_type: :class:`BoundServerType ` :param datacenter: :class:`BoundDatacenter ` + + This property is deprecated and will be removed after 1 July 2026. + Please use the ``location`` property instead. + + See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters. + :param location: :class:`BoundLocation ` :param image: :class:`BoundImage `, None :param iso: :class:`BoundIso `, None :param rescue_enabled: bool @@ -85,13 +108,13 @@ class Server(BaseDomain, DomainIdentityMixin): STATUS_UNKNOWN = "unknown" """Server Status unknown""" - __api_properties__ = ( + __properties__ = ( "id", "name", "status", "public_net", "server_type", - "datacenter", + "location", "image", "iso", "rescue_enabled", @@ -108,7 +131,14 @@ class Server(BaseDomain, DomainIdentityMixin): "primary_disk_size", "placement_group", ) - __slots__ = __api_properties__ + __api_properties__ = ( + *__properties__, + "datacenter", + ) + __slots__ = ( + *__properties__, + "_datacenter", + ) # pylint: disable=too-many-locals def __init__( @@ -120,6 +150,7 @@ class Server(BaseDomain, DomainIdentityMixin): public_net: PublicNetwork | None = None, server_type: BoundServerType | None = None, datacenter: BoundDatacenter | None = None, + location: BoundLocation | None = None, image: BoundImage | None = None, iso: BoundIso | None = None, rescue_enabled: bool | None = None, @@ -128,7 +159,7 @@ class Server(BaseDomain, DomainIdentityMixin): outgoing_traffic: int | None = None, ingoing_traffic: int | None = None, included_traffic: int | None = None, - protection: dict | None = None, + protection: ServerProtection | None = None, labels: dict[str, str] | None = None, volumes: list[BoundVolume] | None = None, private_net: list[PrivateNet] | None = None, @@ -138,10 +169,11 @@ class Server(BaseDomain, DomainIdentityMixin): self.id = id self.name = name self.status = status - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) self.public_net = public_net self.server_type = server_type self.datacenter = datacenter + self.location = location self.image = image self.iso = iso self.rescue_enabled = rescue_enabled @@ -167,6 +199,29 @@ class Server(BaseDomain, DomainIdentityMixin): return o return None + @property + def datacenter(self) -> BoundDatacenter | None: + """ + :meta private: + """ + warnings.warn( + "The 'datacenter' property is deprecated and will be removed after 1 July 2026. " + "Please use the 'location' property instead. " + "See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters.", + DeprecationWarning, + stacklevel=2, + ) + return self._datacenter + + @datacenter.setter + def datacenter(self, value: BoundDatacenter | None) -> None: + self._datacenter = value + + +class ServerProtection(TypedDict): + rebuild: bool + delete: bool + class CreateServerResponse(BaseDomain): """Create Server Response Domain @@ -392,7 +447,7 @@ class IPv6Network(BaseDomain): self, ip: str, blocked: bool, - dns_ptr: list, + dns_ptr: list[DNSPtr], ): self.ip = ip self.blocked = blocked diff --git a/plugins/module_utils/vendor/hcloud/ssh_keys/client.py b/plugins/module_utils/vendor/hcloud/ssh_keys/client.py index a565469..d88800a 100644 --- a/plugins/module_utils/vendor/hcloud/ssh_keys/client.py +++ b/plugins/module_utils/vendor/hcloud/ssh_keys/client.py @@ -5,8 +5,14 @@ from typing import Any, NamedTuple from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import SSHKey +__all__ = [ + "BoundSSHKey", + "SSHKeysPageResult", + "SSHKeysClient", +] -class BoundSSHKey(BoundModelBase, SSHKey): + +class BoundSSHKey(BoundModelBase[SSHKey], SSHKey): _client: SSHKeysClient model = SSHKey diff --git a/plugins/module_utils/vendor/hcloud/ssh_keys/domain.py b/plugins/module_utils/vendor/hcloud/ssh_keys/domain.py index 2297b6b..c3fc7c6 100644 --- a/plugins/module_utils/vendor/hcloud/ssh_keys/domain.py +++ b/plugins/module_utils/vendor/hcloud/ssh_keys/domain.py @@ -1,12 +1,11 @@ from __future__ import annotations -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None - from ..core import BaseDomain, DomainIdentityMixin +__all__ = [ + "SSHKey", +] + class SSHKey(BaseDomain, DomainIdentityMixin): """SSHKey Domain @@ -49,4 +48,4 @@ class SSHKey(BaseDomain, DomainIdentityMixin): self.fingerprint = fingerprint self.public_key = public_key self.labels = labels - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) diff --git a/plugins/module_utils/vendor/hcloud/storage_box_types/client.py b/plugins/module_utils/vendor/hcloud/storage_box_types/client.py index 05cb03e..25c1e89 100644 --- a/plugins/module_utils/vendor/hcloud/storage_box_types/client.py +++ b/plugins/module_utils/vendor/hcloud/storage_box_types/client.py @@ -8,8 +8,14 @@ from .domain import StorageBoxType if TYPE_CHECKING: from .._client import Client +__all__ = [ + "BoundStorageBoxType", + "StorageBoxTypesPageResult", + "StorageBoxTypesClient", +] -class BoundStorageBoxType(BoundModelBase, StorageBoxType): + +class BoundStorageBoxType(BoundModelBase[StorageBoxType], StorageBoxType): _client: StorageBoxTypesClient model = StorageBoxType diff --git a/plugins/module_utils/vendor/hcloud/storage_box_types/domain.py b/plugins/module_utils/vendor/hcloud/storage_box_types/domain.py index b807ce2..b393b15 100644 --- a/plugins/module_utils/vendor/hcloud/storage_box_types/domain.py +++ b/plugins/module_utils/vendor/hcloud/storage_box_types/domain.py @@ -1,8 +1,14 @@ from __future__ import annotations +from typing import Any + from ..core import BaseDomain, DomainIdentityMixin from ..deprecation import DeprecationInfo +__all__ = [ + "StorageBoxType", +] + class StorageBoxType(BaseDomain, DomainIdentityMixin): """ @@ -33,8 +39,8 @@ class StorageBoxType(BaseDomain, DomainIdentityMixin): automatic_snapshot_limit: int | None = None, subaccounts_limit: int | None = None, size: int | None = None, - prices: list[dict] | None = None, - deprecation: dict | None = None, + prices: list[dict[str, Any]] | None = None, + deprecation: dict[str, Any] | None = None, ): self.id = id self.name = name diff --git a/plugins/module_utils/vendor/hcloud/storage_boxes/client.py b/plugins/module_utils/vendor/hcloud/storage_boxes/client.py index 0cb3c2d..4d258b9 100644 --- a/plugins/module_utils/vendor/hcloud/storage_boxes/client.py +++ b/plugins/module_utils/vendor/hcloud/storage_boxes/client.py @@ -2,7 +2,14 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, NamedTuple -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from ..locations import BoundLocation, Location from ..ssh_keys import BoundSSHKey, SSHKey @@ -28,8 +35,18 @@ from .domain import ( if TYPE_CHECKING: from .._client import Client +__all__ = [ + "BoundStorageBox", + "BoundStorageBoxSnapshot", + "BoundStorageBoxSubaccount", + "StorageBoxesPageResult", + "StorageBoxSnapshotsPageResult", + "StorageBoxSubaccountsPageResult", + "StorageBoxesClient", +] -class BoundStorageBox(BoundModelBase, StorageBox): + +class BoundStorageBox(BoundModelBase[StorageBox], StorageBox): _client: StorageBoxesClient model = StorageBox @@ -67,20 +84,20 @@ class BoundStorageBox(BoundModelBase, StorageBox): def get_actions_list( self, *, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: """ - Returns a paginated list of Actions for a Storage Box for a specific page. + Returns a paginated list of Actions for a Storage Box. See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-list-actions-for-a-storage-box - :param status: Filter the actions by status. The response will only contain actions matching the specified statuses. - :param sort: Sort resources by field and direction. - :param page: Page number to return. - :param per_page: Maximum number of entries returned per page. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. Experimental: Storage Box support is experimental, breaking changes may occur within minor releases. @@ -96,8 +113,8 @@ class BoundStorageBox(BoundModelBase, StorageBox): def get_actions( self, *, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: """ Returns all Actions for a Storage Box. @@ -322,7 +339,7 @@ class BoundStorageBox(BoundModelBase, StorageBox): def get_snapshot_by_name( self, name: str, - ) -> BoundStorageBoxSnapshot: + ) -> BoundStorageBoxSnapshot | None: """ Returns a single Snapshot from a Storage Box. @@ -438,7 +455,7 @@ class BoundStorageBox(BoundModelBase, StorageBox): def get_subaccount_by_username( self, username: str, - ) -> BoundStorageBoxSubaccount: + ) -> BoundStorageBoxSubaccount | None: """ Returns a single Subaccount from a Storage Box. @@ -537,7 +554,7 @@ class BoundStorageBox(BoundModelBase, StorageBox): ) -class BoundStorageBoxSnapshot(BoundModelBase, StorageBoxSnapshot): +class BoundStorageBoxSnapshot(BoundModelBase[StorageBoxSnapshot], StorageBoxSnapshot): _client: StorageBoxesClient model = StorageBoxSnapshot @@ -561,6 +578,8 @@ class BoundStorageBoxSnapshot(BoundModelBase, StorageBoxSnapshot): super().__init__(client, data, complete) def _get_self(self) -> BoundStorageBoxSnapshot: + assert self.data_model.storage_box is not None + assert self.data_model.id is not None return self._client.get_snapshot_by_id( self.data_model.storage_box, self.data_model.id, @@ -603,7 +622,9 @@ class BoundStorageBoxSnapshot(BoundModelBase, StorageBoxSnapshot): return self._client.delete_snapshot(self) -class BoundStorageBoxSubaccount(BoundModelBase, StorageBoxSubaccount): +class BoundStorageBoxSubaccount( + BoundModelBase[StorageBoxSubaccount], StorageBoxSubaccount +): _client: StorageBoxesClient model = StorageBoxSubaccount @@ -627,6 +648,8 @@ class BoundStorageBoxSubaccount(BoundModelBase, StorageBoxSubaccount): super().__init__(client, data, complete) def _get_self(self) -> BoundStorageBoxSubaccount: + assert self.data_model.storage_box is not None + assert self.data_model.id is not None return self._client.get_subaccount_by_id( self.data_model.storage_box, self.data_model.id, @@ -737,7 +760,10 @@ class StorageBoxSubaccountsPageResult(NamedTuple): meta: Meta -class StorageBoxesClient(ResourceClientBase): +class StorageBoxesClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): """ A client for the Storage Boxes API. @@ -1006,58 +1032,46 @@ class StorageBoxesClient(ResourceClientBase): self, storage_box: StorageBox | BoundStorageBox, *, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: """ - Returns a paginated list of Actions for a Storage Box for a specific page. + Returns a paginated list of Actions for a Storage Box. See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-list-actions-for-a-storage-box - :param storage_box: Storage Box to fetch the Actions from. - :param status: Filter the actions by status. The response will only contain actions matching the specified statuses. - :param sort: Sort resources by field and direction. - :param page: Page number to return. - :param per_page: Maximum number of entries returned per page. + :param storage_box: Storage Box to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. Experimental: Storage Box support is experimental, breaking changes may occur within minor releases. """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page - - response = self._client.request( - method="GET", - url=f"/storage_boxes/{storage_box.id}/actions", - params=params, - ) - return ActionsPageResult( - actions=[BoundAction(self._parent.actions, o) for o in response["actions"]], - meta=Meta.parse_meta(response), + return self._get_actions_list( + f"{self._base_url}/{storage_box.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) def get_actions( self, storage_box: StorageBox | BoundStorageBox, *, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: """ Returns all Actions for a Storage Box. See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-list-actions-for-a-storage-box - :param storage_box: Storage Box to fetch the Actions from. + :param storage_box: Storage Box to get the Actions for. :param status: Filter the actions by status. The response will only contain actions matching the specified statuses. :param sort: Sort resources by field and direction. @@ -1279,7 +1293,7 @@ class StorageBoxesClient(ResourceClientBase): self, storage_box: StorageBox | BoundStorageBox, name: str, - ) -> BoundStorageBoxSnapshot: + ) -> BoundStorageBoxSnapshot | None: """ Returns a single Snapshot from a Storage Box. @@ -1500,7 +1514,7 @@ class StorageBoxesClient(ResourceClientBase): self, storage_box: StorageBox | BoundStorageBox, username: str, - ) -> BoundStorageBoxSubaccount: + ) -> BoundStorageBoxSubaccount | None: """ Returns a single Subaccount from a Storage Box. diff --git a/plugins/module_utils/vendor/hcloud/storage_boxes/domain.py b/plugins/module_utils/vendor/hcloud/storage_boxes/domain.py index 040f6e8..03eaab1 100644 --- a/plugins/module_utils/vendor/hcloud/storage_boxes/domain.py +++ b/plugins/module_utils/vendor/hcloud/storage_boxes/domain.py @@ -2,11 +2,6 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, Literal -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None - from ..actions import BoundAction from ..core import BaseDomain, DomainIdentityMixin from ..locations import BoundLocation, Location @@ -19,6 +14,26 @@ if TYPE_CHECKING: BoundStorageBoxSubaccount, ) +__all__ = [ + "StorageBox", + "StorageBoxAccessSettings", + "StorageBoxStats", + "StorageBoxSnapshotPlan", + "CreateStorageBoxResponse", + "DeleteStorageBoxResponse", + "StorageBoxFoldersResponse", + "StorageBoxSnapshot", + "StorageBoxSnapshotStats", + "CreateStorageBoxSnapshotResponse", + "DeleteStorageBoxSnapshotResponse", + "StorageBoxSubaccount", + "StorageBoxSubaccountAccessSettings", + "CreateStorageBoxSubaccountResponse", + "DeleteStorageBoxSubaccountResponse", + "StorageBoxStatus", +] + + StorageBoxStatus = Literal[ "active", "initializing", @@ -85,7 +100,7 @@ class StorageBox(BaseDomain, DomainIdentityMixin): self.access_settings = access_settings self.stats = stats self.status = status - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) class StorageBoxAccessSettings(BaseDomain): @@ -288,7 +303,7 @@ class StorageBoxSnapshot(BaseDomain, DomainIdentityMixin): self.is_automatic = is_automatic self.labels = labels self.storage_box = storage_box - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) self.stats = stats @@ -389,7 +404,7 @@ class StorageBoxSubaccount(BaseDomain, DomainIdentityMixin): self.access_settings = access_settings self.labels = labels self.storage_box = storage_box - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) class StorageBoxSubaccountAccessSettings(BaseDomain): diff --git a/plugins/module_utils/vendor/hcloud/volumes/__init__.py b/plugins/module_utils/vendor/hcloud/volumes/__init__.py index 046df10..1722623 100644 --- a/plugins/module_utils/vendor/hcloud/volumes/__init__.py +++ b/plugins/module_utils/vendor/hcloud/volumes/__init__.py @@ -1,12 +1,13 @@ from __future__ import annotations from .client import BoundVolume, VolumesClient, VolumesPageResult -from .domain import CreateVolumeResponse, Volume +from .domain import CreateVolumeResponse, Volume, VolumeProtection __all__ = [ "BoundVolume", "CreateVolumeResponse", "Volume", + "VolumeProtection", "VolumesClient", "VolumesPageResult", ] diff --git a/plugins/module_utils/vendor/hcloud/volumes/client.py b/plugins/module_utils/vendor/hcloud/volumes/client.py index 9d1cded..a4155cf 100644 --- a/plugins/module_utils/vendor/hcloud/volumes/client.py +++ b/plugins/module_utils/vendor/hcloud/volumes/client.py @@ -2,7 +2,14 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, NamedTuple -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from ..locations import BoundLocation from .domain import CreateVolumeResponse, Volume @@ -13,12 +20,24 @@ if TYPE_CHECKING: from ..servers import BoundServer, Server -class BoundVolume(BoundModelBase, Volume): +__all__ = [ + "BoundVolume", + "VolumesPageResult", + "VolumesClient", +] + + +class BoundVolume(BoundModelBase[Volume], Volume): _client: VolumesClient model = Volume - def __init__(self, client: VolumesClient, data: dict, complete: bool = True): + def __init__( + self, + client: VolumesClient, + data: dict[str, Any], + complete: bool = True, + ): location = data.get("location") if location is not None: data["location"] = BoundLocation(client._parent.locations, location) @@ -35,22 +54,18 @@ class BoundVolume(BoundModelBase, Volume): def get_actions_list( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a volume. + """ + Returns a paginated list of Actions for a Volume. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ return self._client.get_actions_list( self, status=status, sort=sort, page=page, per_page=per_page @@ -58,16 +73,14 @@ class BoundVolume(BoundModelBase, Volume): def get_actions( self, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a volume. + """ + Returns all Actions for a Volume. - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._client.get_actions(self, status=status, sort=sort) @@ -137,7 +150,10 @@ class VolumesPageResult(NamedTuple): meta: Meta -class VolumesClient(ResourceClientBase): +class VolumesClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): _base_url = "/volumes" actions: ResourceActionsClient @@ -288,59 +304,40 @@ class VolumesClient(ResourceClientBase): def get_actions_list( self, volume: Volume | BoundVolume, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: - """Returns all action objects for a volume. - - :param volume: :class:`BoundVolume ` or :class:`Volume ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :param page: int (optional) - Specifies the page to fetch - :param per_page: int (optional) - Specifies how many results are returned by page - :return: (List[:class:`BoundAction `], :class:`Meta `) """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page + Returns a paginated list of Actions for a Volume. - response = self._client.request( - url=f"{self._base_url}/{volume.id}/actions", - method="GET", - params=params, + :param volume: Volume to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. + """ + return self._get_actions_list( + f"{self._base_url}/{volume.id}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) - actions = [ - BoundAction(self._parent.actions, action_data) - for action_data in response["actions"] - ] - return ActionsPageResult(actions, Meta.parse_meta(response)) def get_actions( self, volume: Volume | BoundVolume, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: - """Returns all action objects for a volume. + """ + Returns all Actions for a Volume. - :param volume: :class:`BoundVolume ` or :class:`Volume ` - :param status: List[str] (optional) - Response will have only actions with specified statuses. Choices: `running` `success` `error` - :param sort: List[str] (optional) - Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc` - :return: List[:class:`BoundAction `] + :param volume: Volume to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages( self.get_actions_list, diff --git a/plugins/module_utils/vendor/hcloud/volumes/domain.py b/plugins/module_utils/vendor/hcloud/volumes/domain.py index adfd661..2ed3333 100644 --- a/plugins/module_utils/vendor/hcloud/volumes/domain.py +++ b/plugins/module_utils/vendor/hcloud/volumes/domain.py @@ -1,11 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING - -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None +from typing import TYPE_CHECKING, TypedDict from ..core import BaseDomain, DomainIdentityMixin @@ -15,6 +10,12 @@ if TYPE_CHECKING: from ..servers import BoundServer, Server from .client import BoundVolume +__all__ = [ + "Volume", + "VolumeProtection", + "CreateVolumeResponse", +] + class Volume(BaseDomain, DomainIdentityMixin): """Volume Domain @@ -73,14 +74,14 @@ class Volume(BaseDomain, DomainIdentityMixin): size: int | None = None, linux_device: str | None = None, format: str | None = None, - protection: dict | None = None, + protection: VolumeProtection | None = None, labels: dict[str, str] | None = None, status: str | None = None, ): self.id = id self.name = name self.server = server - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) self.location = location self.size = size self.linux_device = linux_device @@ -90,6 +91,10 @@ class Volume(BaseDomain, DomainIdentityMixin): self.status = status +class VolumeProtection(TypedDict): + delete: bool + + class CreateVolumeResponse(BaseDomain): """Create Volume Response Domain diff --git a/plugins/module_utils/vendor/hcloud/zones/__init__.py b/plugins/module_utils/vendor/hcloud/zones/__init__.py index 7871e10..4cbee7f 100644 --- a/plugins/module_utils/vendor/hcloud/zones/__init__.py +++ b/plugins/module_utils/vendor/hcloud/zones/__init__.py @@ -3,16 +3,26 @@ from __future__ import annotations from .client import ( BoundZone, BoundZoneRRSet, + ZoneRRSetsPageResult, ZonesClient, ZonesPageResult, ) from .domain import ( CreateZoneResponse, + CreateZoneRRSetResponse, + DeleteZoneResponse, + DeleteZoneRRSetResponse, + ExportZonefileResponse, Zone, ZoneAuthoritativeNameservers, + ZoneMode, ZonePrimaryNameserver, + ZoneProtection, ZoneRecord, + ZoneRegistrar, ZoneRRSet, + ZoneRRSetProtection, + ZoneStatus, ) __all__ = [ @@ -26,4 +36,14 @@ __all__ = [ "ZoneRRSet", "ZonesClient", "ZonesPageResult", + "DeleteZoneRRSetResponse", + "ZoneRRSetProtection", + "DeleteZoneResponse", + "ZoneRegistrar", + "ZoneMode", + "ZoneRRSetsPageResult", + "ZoneProtection", + "ExportZonefileResponse", + "CreateZoneRRSetResponse", + "ZoneStatus", ] diff --git a/plugins/module_utils/vendor/hcloud/zones/client.py b/plugins/module_utils/vendor/hcloud/zones/client.py index b334604..2f68028 100644 --- a/plugins/module_utils/vendor/hcloud/zones/client.py +++ b/plugins/module_utils/vendor/hcloud/zones/client.py @@ -2,7 +2,14 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, NamedTuple -from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient +from ..actions import ( + ActionSort, + ActionsPageResult, + ActionStatus, + BoundAction, + ResourceActionsClient, +) +from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase from .domain import ( CreateZoneResponse, @@ -22,8 +29,16 @@ from .domain import ( if TYPE_CHECKING: from .._client import Client +__all__ = [ + "BoundZone", + "BoundZoneRRSet", + "ZonesPageResult", + "ZoneRRSetsPageResult", + "ZonesClient", +] -class BoundZone(BoundModelBase, Zone): + +class BoundZone(BoundModelBase[Zone], Zone): _client: ZonesClient model = Zone @@ -81,20 +96,20 @@ class BoundZone(BoundModelBase, Zone): def get_actions_list( self, *, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: """ - Returns all Actions for the Zone for a specific page. + Returns a paginated list of Actions for a Zone. See https://docs.hetzner.cloud/reference/cloud#zones-list-zones - :param status: Filter the actions by status. The response will only contain actions matching the specified statuses. - :param sort: Sort resources by field and direction. - :param page: Page number to return. - :param per_page: Maximum number of entries returned per page. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ return self._client.get_actions_list( self, @@ -107,16 +122,16 @@ class BoundZone(BoundModelBase, Zone): def get_actions( self, *, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: """ - Returns all Actions for the Zone. + Returns all Actions for a Zone. See https://docs.hetzner.cloud/reference/cloud#zones-list-zones - :param status: Filter the actions by status. The response will only contain actions matching the specified statuses. - :param sort: Sort resources by field and direction. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._client.get_actions( self, @@ -367,7 +382,7 @@ class BoundZone(BoundModelBase, Zone): """ Updates records in a ZoneRRSet. - See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-update-records-to-an-rrset + See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-update-records-of-an-rrset :param rrset: RRSet to update. :param records: Records to update in the RRSet. @@ -405,12 +420,17 @@ class BoundZone(BoundModelBase, Zone): return self._client.set_rrset_records(rrset=rrset, records=records) -class BoundZoneRRSet(BoundModelBase, ZoneRRSet): +class BoundZoneRRSet(BoundModelBase[ZoneRRSet], ZoneRRSet): _client: ZonesClient model = ZoneRRSet - def __init__(self, client: ZonesClient, data: dict, complete: bool = True): + def __init__( + self, + client: ZonesClient, + data: dict[str, Any], + complete: bool = True, + ): raw = data.get("zone") if raw is not None: data["zone"] = BoundZone(client, data={"id": raw}, complete=False) @@ -422,6 +442,8 @@ class BoundZoneRRSet(BoundModelBase, ZoneRRSet): super().__init__(client, data, complete) def _get_self(self) -> BoundZoneRRSet: + assert self.data_model.zone is not None + assert self.data_model.type is not None return self._client.get_rrset( self.data_model.zone, self.data_model.name, @@ -501,7 +523,7 @@ class BoundZoneRRSet(BoundModelBase, ZoneRRSet): """ Updates records in a ZoneRRSet. - See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-update-records-to-an-rrset + See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-update-records-of-an-rrset :param records: Records to update in the RRSet. """ @@ -544,7 +566,10 @@ class ZoneRRSetsPageResult(NamedTuple): meta: Meta -class ZonesClient(ResourceClientBase): +class ZonesClient( + ResourceClientBaseActionsMixin, + ResourceClientBase, +): """ ZoneClient is a client for the Zone (DNS) API. @@ -767,57 +792,45 @@ class ZonesClient(ResourceClientBase): self, zone: Zone | BoundZone, *, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, page: int | None = None, per_page: int | None = None, ) -> ActionsPageResult: """ - Returns all Actions for a Zone for a specific page. + Returns a paginated list of Actions for a Zone. See https://docs.hetzner.cloud/reference/cloud#zones-list-zones - :param zone: Zone to fetch the Actions from. - :param status: Filter the actions by status. The response will only contain actions matching the specified statuses. - :param sort: Sort resources by field and direction. - :param page: Page number to return. - :param per_page: Maximum number of entries returned per page. + :param zone: Zone to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. + :param page: Page number to get. + :param per_page: Maximum number of Actions returned per page. """ - params: dict[str, Any] = {} - if status is not None: - params["status"] = status - if sort is not None: - params["sort"] = sort - if page is not None: - params["page"] = page - if per_page is not None: - params["per_page"] = per_page - - response = self._client.request( - method="GET", - url=f"{self._base_url}/{zone.id_or_name}/actions", - params=params, - ) - return ActionsPageResult( - actions=[BoundAction(self._parent.actions, o) for o in response["actions"]], - meta=Meta.parse_meta(response), + return self._get_actions_list( + f"{self._base_url}/{zone.id_or_name}", + status=status, + sort=sort, + page=page, + per_page=per_page, ) def get_actions( self, zone: Zone | BoundZone, *, - status: list[str] | None = None, - sort: list[str] | None = None, + status: list[ActionStatus] | None = None, + sort: list[ActionSort] | None = None, ) -> list[BoundAction]: """ Returns all Actions for a Zone. See https://docs.hetzner.cloud/reference/cloud#zones-list-zones - :param zone: Zone to fetch the Actions from. - :param status: Filter the actions by status. The response will only contain actions matching the specified statuses. - :param sort: Sort resources by field and direction. + :param zone: Zone to get the Actions for. + :param status: Filter the Actions by status. + :param sort: Sort Actions by field and direction. """ return self._iter_pages( self.get_actions_list, @@ -1208,7 +1221,7 @@ class ZonesClient(ResourceClientBase): """ Updates records in a ZoneRRSet. - See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-update-records-to-an-rrset + See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-update-records-of-an-rrset :param rrset: RRSet to update. :param records: Records to update in the RRSet. diff --git a/plugins/module_utils/vendor/hcloud/zones/domain.py b/plugins/module_utils/vendor/hcloud/zones/domain.py index 726641e..77aee48 100644 --- a/plugins/module_utils/vendor/hcloud/zones/domain.py +++ b/plugins/module_utils/vendor/hcloud/zones/domain.py @@ -2,11 +2,6 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, Literal, TypedDict -try: - from dateutil.parser import isoparse -except ImportError: - isoparse = None - from ..core import BaseDomain, DomainIdentityMixin if TYPE_CHECKING: @@ -14,6 +9,24 @@ if TYPE_CHECKING: from .client import BoundZone, BoundZoneRRSet +__all__ = [ + "ZoneMode", + "ZoneStatus", + "ZoneRegistrar", + "Zone", + "ZonePrimaryNameserver", + "ZoneAuthoritativeNameservers", + "ZoneProtection", + "CreateZoneResponse", + "DeleteZoneResponse", + "ExportZonefileResponse", + "ZoneRRSet", + "ZoneRRSetProtection", + "ZoneRecord", + "CreateZoneRRSetResponse", + "DeleteZoneRRSetResponse", +] + ZoneMode = Literal["primary", "secondary"] ZoneStatus = Literal["ok", "updating", "error"] ZoneRegistrar = Literal["hetzner", "other", "unknown"] @@ -81,7 +94,7 @@ class Zone(BaseDomain, DomainIdentityMixin): ): self.id = id self.name = name - self.created = isoparse(created) if created else None + self.created = self._parse_datetime(created) self.mode = mode self.ttl = ttl self.labels = labels @@ -188,11 +201,7 @@ class ZoneAuthoritativeNameservers(BaseDomain): ): self.assigned = assigned self.delegated = delegated - self.delegation_last_check = ( - isoparse(delegation_last_check) - if delegation_last_check is not None - else None - ) + self.delegation_last_check = self._parse_datetime(delegation_last_check) self.delegation_status = delegation_status