mirror of
https://github.com/ansible-collections/hetzner.hcloud.git
synced 2026-02-04 08:01:49 +00:00
This PR contains the following updates: | Package | Change | Age | Confidence | |---|---|---|---| | [hcloud](https://redirect.github.com/hetznercloud/hcloud-python) ([changelog](https://redirect.github.com/hetznercloud/hcloud-python/blob/main/CHANGELOG.md)) | `2.10.0` -> `2.11.0` | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>hetznercloud/hcloud-python (hcloud)</summary> ### [`v2.11.0`](https://redirect.github.com/hetznercloud/hcloud-python/blob/HEAD/CHANGELOG.md#v2110) [Compare Source](https://redirect.github.com/hetznercloud/hcloud-python/compare/v2.10.0...v2.11.0) ##### DNS API is now generally available The DNS API is now generally available, as well as support for features in this project that are related to the DNS API. To migrate existing zones to the new DNS API, see the [DNS migration guide](https://docs.hetzner.com/networking/dns/migration-to-hetzner-console/process). See the [changelog](https://docs.hetzner.cloud/changelog#2025-11-10-dns-ga) for more details. ##### Features - DNS support is now generally available ([#​581](https://redirect.github.com/hetznercloud/hcloud-python/issues/581)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/ansible-collections/hetzner.hcloud). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNTkuNCIsInVwZGF0ZWRJblZlciI6IjQxLjE1OS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: jo <ljonas@riseup.net>
1220 lines
38 KiB
Python
1220 lines
38 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, Any, NamedTuple
|
|
|
|
from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
|
|
from ..core import BoundModelBase, Meta, ResourceClientBase
|
|
from .domain import (
|
|
CreateZoneResponse,
|
|
CreateZoneRRSetResponse,
|
|
DeleteZoneResponse,
|
|
DeleteZoneRRSetResponse,
|
|
ExportZonefileResponse,
|
|
Zone,
|
|
ZoneAuthoritativeNameservers,
|
|
ZoneMode,
|
|
ZonePrimaryNameserver,
|
|
ZoneRecord,
|
|
ZoneRRSet,
|
|
ZoneRRSetType,
|
|
)
|
|
|
|
if TYPE_CHECKING:
|
|
from .._client import Client
|
|
|
|
|
|
class BoundZone(BoundModelBase, Zone):
|
|
_client: ZonesClient
|
|
|
|
model = Zone
|
|
|
|
def __init__(
|
|
self,
|
|
client: ZonesClient,
|
|
data: dict[str, Any],
|
|
complete: bool = True,
|
|
):
|
|
raw = data.get("primary_nameservers")
|
|
if raw is not None:
|
|
data["primary_nameservers"] = [
|
|
ZonePrimaryNameserver.from_dict(o) for o in raw
|
|
]
|
|
|
|
raw = data.get("authoritative_nameservers")
|
|
if raw:
|
|
data["authoritative_nameservers"] = ZoneAuthoritativeNameservers.from_dict(
|
|
raw
|
|
)
|
|
|
|
super().__init__(client, data, complete)
|
|
|
|
def update(
|
|
self,
|
|
*,
|
|
labels: dict[str, str] | None = None,
|
|
) -> BoundZone:
|
|
"""
|
|
Updates the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-update-a-zone
|
|
|
|
:param labels: User-defined labels (key/value pairs) for the Resource.
|
|
"""
|
|
return self._client.update(self, labels=labels)
|
|
|
|
def delete(self) -> DeleteZoneResponse:
|
|
"""
|
|
Deletes the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-delete-a-zone
|
|
"""
|
|
return self._client.delete(self)
|
|
|
|
def export_zonefile(self) -> ExportZonefileResponse:
|
|
"""
|
|
Returns a generated Zone file in BIND (RFC 1034/1035) format.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-export-a-zone-file
|
|
"""
|
|
return self._client.export_zonefile(self)
|
|
|
|
def get_actions_list(
|
|
self,
|
|
*,
|
|
status: list[str] | None = None,
|
|
sort: list[str] | None = None,
|
|
page: int | None = None,
|
|
per_page: int | None = None,
|
|
) -> ActionsPageResult:
|
|
"""
|
|
Returns all Actions for the Zone for a specific page.
|
|
|
|
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.
|
|
"""
|
|
return self._client.get_actions_list(
|
|
self,
|
|
status=status,
|
|
sort=sort,
|
|
page=page,
|
|
per_page=per_page,
|
|
)
|
|
|
|
def get_actions(
|
|
self,
|
|
*,
|
|
status: list[str] | None = None,
|
|
sort: list[str] | None = None,
|
|
) -> list[BoundAction]:
|
|
"""
|
|
Returns all Actions for the 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.
|
|
"""
|
|
return self._client.get_actions(
|
|
self,
|
|
status=status,
|
|
sort=sort,
|
|
)
|
|
|
|
def import_zonefile(
|
|
self,
|
|
zonefile: str,
|
|
) -> BoundAction:
|
|
"""
|
|
Imports a zone file, replacing all resource record sets (ZoneRRSet).
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-actions-import-a-zone-file
|
|
|
|
:param zonefile: Zone file to import.
|
|
"""
|
|
return self._client.import_zonefile(self, zonefile=zonefile)
|
|
|
|
def change_protection(
|
|
self,
|
|
*,
|
|
delete: bool | None = None,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the protection of the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-actions-change-a-zones-protection
|
|
|
|
:param delete: Prevents the Zone from being deleted.
|
|
"""
|
|
return self._client.change_protection(self, delete=delete)
|
|
|
|
def change_ttl(
|
|
self,
|
|
ttl: int,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the TTL of the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-actions-change-a-zones-default-ttl
|
|
|
|
:param ttl: Default Time To Live (TTL) of the Zone.
|
|
"""
|
|
return self._client.change_ttl(self, ttl=ttl)
|
|
|
|
def change_primary_nameservers(
|
|
self,
|
|
primary_nameservers: list[ZonePrimaryNameserver],
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the primary nameservers of the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-actions-change-a-zones-primary-nameservers
|
|
|
|
:param primary_nameservers: Primary nameservers of the Zone.
|
|
"""
|
|
return self._client.change_primary_nameservers(
|
|
self,
|
|
primary_nameservers=primary_nameservers,
|
|
)
|
|
|
|
def get_rrset(
|
|
self,
|
|
name: str,
|
|
type: ZoneRRSetType,
|
|
) -> BoundZoneRRSet:
|
|
"""
|
|
Returns a single ZoneRRSet from the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-get-an-rrset
|
|
|
|
:param name: Name of the RRSet.
|
|
:param type: Type of the RRSet.
|
|
"""
|
|
return self._client.get_rrset(self, name=name, type=type)
|
|
|
|
def get_rrset_list(
|
|
self,
|
|
*,
|
|
name: str | None = None,
|
|
type: list[ZoneRRSetType] | None = None,
|
|
label_selector: str | None = None,
|
|
sort: list[str] | None = None,
|
|
page: int | None = None,
|
|
per_page: int | None = None,
|
|
) -> ZoneRRSetsPageResult:
|
|
"""
|
|
Returns all ZoneRRSet in the Zone for a specific page.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-list-rrsets
|
|
|
|
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
|
|
:param type: Filter resources by their type. The response will only contain the resources matching exactly the specified type.
|
|
:param label_selector: Filter resources by labels. The response will only contain resources matching the label selector.
|
|
:param sort: Sort resources by field and direction.
|
|
:param page: Page number to return.
|
|
:param per_page: Maximum number of entries returned per page.
|
|
"""
|
|
return self._client.get_rrset_list(
|
|
self,
|
|
name=name,
|
|
type=type,
|
|
label_selector=label_selector,
|
|
sort=sort,
|
|
page=page,
|
|
per_page=per_page,
|
|
)
|
|
|
|
def get_rrset_all(
|
|
self,
|
|
*,
|
|
name: str | None = None,
|
|
type: list[ZoneRRSetType] | None = None,
|
|
label_selector: str | None = None,
|
|
sort: list[str] | None = None,
|
|
) -> list[BoundZoneRRSet]:
|
|
"""
|
|
Returns all ZoneRRSet in the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-list-rrsets
|
|
|
|
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
|
|
:param type: Filter resources by their type. The response will only contain the resources matching exactly the specified type.
|
|
:param label_selector: Filter resources by labels. The response will only contain resources matching the label selector.
|
|
:param sort: Sort resources by field and direction.
|
|
"""
|
|
return self._client.get_rrset_all(
|
|
self,
|
|
name=name,
|
|
type=type,
|
|
label_selector=label_selector,
|
|
sort=sort,
|
|
)
|
|
|
|
def create_rrset(
|
|
self,
|
|
*,
|
|
name: str,
|
|
type: ZoneRRSetType,
|
|
ttl: int | None = None,
|
|
labels: dict[str, str] | None = None,
|
|
records: list[ZoneRecord] | None = None,
|
|
) -> CreateZoneRRSetResponse:
|
|
"""
|
|
Creates a ZoneRRSet in the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-create-an-rrset
|
|
|
|
:param name: Name of the RRSet.
|
|
:param type: Type of the RRSet.
|
|
:param ttl: Time To Live (TTL) of the RRSet.
|
|
:param labels: User-defined labels (key/value pairs) for the Resource.
|
|
:param records: Records of the RRSet.
|
|
"""
|
|
return self._client.create_rrset(
|
|
self,
|
|
name=name,
|
|
type=type,
|
|
ttl=ttl,
|
|
labels=labels,
|
|
records=records,
|
|
)
|
|
|
|
def update_rrset(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
*,
|
|
labels: dict[str, str] | None = None,
|
|
) -> BoundZoneRRSet:
|
|
"""
|
|
Updates a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-update-an-rrset
|
|
|
|
:param rrset: RRSet to update.
|
|
:param labels: User-defined labels (key/value pairs) for the Resource.
|
|
"""
|
|
return self._client.update_rrset(rrset=rrset, labels=labels)
|
|
|
|
def delete_rrset(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
) -> DeleteZoneRRSetResponse:
|
|
"""
|
|
Deletes a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-delete-an-rrset
|
|
|
|
:param rrset: RRSet to delete.
|
|
"""
|
|
return self._client.delete_rrset(rrset=rrset)
|
|
|
|
def change_rrset_protection(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
*,
|
|
change: bool | None = None,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the protection of a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-change-an-rrsets-protection
|
|
|
|
:param rrset: RRSet to update.
|
|
:param change: Prevent the Zone from being changed (deletion and updates).
|
|
"""
|
|
return self._client.change_rrset_protection(rrset=rrset, change=change)
|
|
|
|
def change_rrset_ttl(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
ttl: int | None,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the TTL of a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-change-an-rrsets-ttl
|
|
|
|
:param rrset: RRSet to update.
|
|
:param change: Time To Live (TTL) of the RRSet.
|
|
"""
|
|
return self._client.change_rrset_ttl(rrset=rrset, ttl=ttl)
|
|
|
|
def add_rrset_records(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
records: list[ZoneRecord],
|
|
ttl: int | None = None,
|
|
) -> BoundAction:
|
|
"""
|
|
Adds records to a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-add-records-to-an-rrset
|
|
|
|
:param rrset: RRSet to update.
|
|
:param records: Records to add to the RRSet.
|
|
:param ttl: Time To Live (TTL) of the RRSet.
|
|
"""
|
|
return self._client.add_rrset_records(rrset=rrset, records=records, ttl=ttl)
|
|
|
|
def remove_rrset_records(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
records: list[ZoneRecord],
|
|
) -> BoundAction:
|
|
"""
|
|
Removes records from a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-remove-records-from-an-rrset
|
|
|
|
:param rrset: RRSet to update.
|
|
:param records: Records to remove from the RRSet.
|
|
"""
|
|
return self._client.remove_rrset_records(rrset=rrset, records=records)
|
|
|
|
def set_rrset_records(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
records: list[ZoneRecord],
|
|
) -> BoundAction:
|
|
"""
|
|
Sets the records of a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-set-records-of-an-rrset
|
|
|
|
:param rrset: RRSet to update.
|
|
:param records: Records to set in the RRSet.
|
|
"""
|
|
return self._client.set_rrset_records(rrset=rrset, records=records)
|
|
|
|
|
|
class BoundZoneRRSet(BoundModelBase, ZoneRRSet):
|
|
_client: ZonesClient
|
|
|
|
model = ZoneRRSet
|
|
|
|
def __init__(self, client: ZonesClient, data: dict, complete: bool = True):
|
|
raw = data.get("zone")
|
|
if raw is not None:
|
|
data["zone"] = BoundZone(client, data={"id": raw}, complete=False)
|
|
|
|
raw = data.get("records")
|
|
if raw is not None:
|
|
data["records"] = [ZoneRecord.from_dict(o) for o in raw]
|
|
|
|
super().__init__(client, data, complete)
|
|
|
|
def update_rrset(
|
|
self,
|
|
*,
|
|
labels: dict[str, str] | None = None,
|
|
) -> BoundZoneRRSet:
|
|
"""
|
|
Updates the ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-update-an-rrset
|
|
|
|
:param labels: User-defined labels (key/value pairs) for the Resource.
|
|
"""
|
|
return self._client.update_rrset(self, labels=labels)
|
|
|
|
def delete_rrset(
|
|
self,
|
|
) -> DeleteZoneRRSetResponse:
|
|
"""
|
|
Deletes the ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-delete-an-rrset
|
|
"""
|
|
return self._client.delete_rrset(self)
|
|
|
|
def change_rrset_protection(
|
|
self,
|
|
*,
|
|
change: bool | None = None,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the protection of the ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-change-an-rrsets-protection
|
|
|
|
:param change: Prevent the Zone from being changed (deletion and updates).
|
|
"""
|
|
return self._client.change_rrset_protection(self, change=change)
|
|
|
|
def change_rrset_ttl(
|
|
self,
|
|
ttl: int | None,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the TTL of the ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-change-an-rrsets-ttl
|
|
|
|
:param change: Time To Live (TTL) of the RRSet.
|
|
"""
|
|
return self._client.change_rrset_ttl(self, ttl=ttl)
|
|
|
|
def add_rrset_records(
|
|
self,
|
|
records: list[ZoneRecord],
|
|
ttl: int | None = None,
|
|
) -> BoundAction:
|
|
"""
|
|
Adds records to the ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-add-records-to-an-rrset
|
|
|
|
:param records: Records to add to the RRSet.
|
|
:param ttl: Time To Live (TTL) of the RRSet.
|
|
"""
|
|
return self._client.add_rrset_records(self, records=records, ttl=ttl)
|
|
|
|
def remove_rrset_records(
|
|
self,
|
|
records: list[ZoneRecord],
|
|
) -> BoundAction:
|
|
"""
|
|
Removes records from the ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-remove-records-from-an-rrset
|
|
|
|
:param records: Records to remove from the RRSet.
|
|
"""
|
|
return self._client.remove_rrset_records(self, records=records)
|
|
|
|
def set_rrset_records(
|
|
self,
|
|
records: list[ZoneRecord],
|
|
) -> BoundAction:
|
|
"""
|
|
Sets the records of the ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-set-records-of-an-rrset
|
|
|
|
:param records: Records to set in the RRSet.
|
|
"""
|
|
return self._client.set_rrset_records(self, records=records)
|
|
|
|
|
|
class ZonesPageResult(NamedTuple):
|
|
zones: list[BoundZone]
|
|
meta: Meta
|
|
|
|
|
|
class ZoneRRSetsPageResult(NamedTuple):
|
|
rrsets: list[BoundZoneRRSet]
|
|
meta: Meta
|
|
|
|
|
|
class ZonesClient(ResourceClientBase):
|
|
"""
|
|
ZoneClient is a client for the Zone (DNS) API.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones and https://docs.hetzner.cloud/reference/cloud#zone-rrsets.
|
|
"""
|
|
|
|
_base_url = "/zones"
|
|
|
|
actions: ResourceActionsClient
|
|
"""Zones scoped actions client
|
|
|
|
:type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
|
|
"""
|
|
|
|
def __init__(self, client: Client):
|
|
super().__init__(client)
|
|
self.actions = ResourceActionsClient(client, self._base_url)
|
|
|
|
def get(self, id_or_name: int | str) -> BoundZone:
|
|
"""
|
|
Returns a single Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-get-a-zone
|
|
|
|
:param id_or_name: ID or Name of the Zone.
|
|
"""
|
|
response = self._client.request(
|
|
method="GET",
|
|
url=f"{self._base_url}/{id_or_name}",
|
|
)
|
|
return BoundZone(self, response["zone"])
|
|
|
|
def get_list(
|
|
self,
|
|
*,
|
|
name: str | None = None,
|
|
mode: ZoneMode | None = None,
|
|
label_selector: str | None = None,
|
|
sort: list[str] | None = None,
|
|
page: int | None = None,
|
|
per_page: int | None = None,
|
|
) -> ZonesPageResult:
|
|
"""
|
|
Returns a list of Zone for a specific page.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-list-zones
|
|
|
|
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
|
|
:param mode: Filter resources by their mode. The response will only contain the resources matching exactly the specified mode.
|
|
:param label_selector: Filter resources by labels. The response will only contain resources matching the label selector.
|
|
:param sort: Sort resources by field and direction.
|
|
:param page: Page number to return.
|
|
:param per_page: Maximum number of entries returned per page.
|
|
"""
|
|
params: dict[str, Any] = {}
|
|
if name is not None:
|
|
params["name"] = name
|
|
if mode is not None:
|
|
params["mode"] = mode
|
|
if label_selector is not None:
|
|
params["label_selector"] = label_selector
|
|
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}",
|
|
params=params,
|
|
)
|
|
return ZonesPageResult(
|
|
zones=[BoundZone(self, item) for item in response["zones"]],
|
|
meta=Meta.parse_meta(response),
|
|
)
|
|
|
|
def get_all(
|
|
self,
|
|
*,
|
|
name: str | None = None,
|
|
mode: ZoneMode | None = None,
|
|
label_selector: str | None = None,
|
|
sort: list[str] | None = None,
|
|
) -> list[BoundZone]:
|
|
"""
|
|
Returns a list of all Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-list-zones
|
|
|
|
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
|
|
:param mode: Filter resources by their mode. The response will only contain the resources matching exactly the specified mode.
|
|
:param label_selector: Filter resources by labels. The response will only contain resources matching the label selector.
|
|
:param sort: Sort resources by field and direction.
|
|
"""
|
|
return self._iter_pages(
|
|
self.get_list,
|
|
name=name,
|
|
mode=mode,
|
|
label_selector=label_selector,
|
|
sort=sort,
|
|
)
|
|
|
|
def create(
|
|
self,
|
|
*,
|
|
name: str,
|
|
mode: ZoneMode,
|
|
ttl: int | None = None,
|
|
labels: dict[str, str] | None = None,
|
|
primary_nameservers: list[ZonePrimaryNameserver] | None = None,
|
|
rrsets: list[ZoneRRSet] | None = None,
|
|
zonefile: str | None = None,
|
|
) -> CreateZoneResponse:
|
|
"""
|
|
Creates a Zone.
|
|
|
|
A default SOA and three NS resource records with the assigned Hetzner nameservers are created automatically.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-create-a-zone
|
|
|
|
:param name: Name of the Zone.
|
|
:param mode: Mode of the Zone.
|
|
:param ttl: Default Time To Live (TTL) of the Zone.
|
|
:param labels: User-defined labels (key/value pairs) for the Resource.
|
|
:param primary_nameservers: Primary nameservers of the Zone.
|
|
:param rrsets: RRSets to be added to the Zone.
|
|
:param zonefile: Zone file to import.
|
|
"""
|
|
data: dict[str, Any] = {
|
|
"name": name,
|
|
"mode": mode,
|
|
}
|
|
if ttl is not None:
|
|
data["ttl"] = ttl
|
|
if labels is not None:
|
|
data["labels"] = labels
|
|
if primary_nameservers is not None:
|
|
data["primary_nameservers"] = [o.to_payload() for o in primary_nameservers]
|
|
if rrsets is not None:
|
|
data["rrsets"] = [o.to_payload() for o in rrsets]
|
|
if zonefile is not None:
|
|
data["zonefile"] = zonefile
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}",
|
|
json=data,
|
|
)
|
|
|
|
return CreateZoneResponse(
|
|
zone=BoundZone(self, response["zone"]),
|
|
action=BoundAction(self._parent.actions, response["action"]),
|
|
)
|
|
|
|
def update(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
*,
|
|
labels: dict[str, str] | None = None,
|
|
) -> BoundZone:
|
|
"""
|
|
Updates a Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-update-a-zone
|
|
|
|
:param zone: Zone to update.
|
|
:param labels: User-defined labels (key/value pairs) for the Resource.
|
|
"""
|
|
data: dict[str, Any] = {}
|
|
if labels is not None:
|
|
data["labels"] = labels
|
|
|
|
response = self._client.request(
|
|
method="PUT",
|
|
url=f"{self._base_url}/{zone.id_or_name}",
|
|
json=data,
|
|
)
|
|
return BoundZone(self, response["zone"])
|
|
|
|
def delete(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
) -> DeleteZoneResponse:
|
|
"""
|
|
Deletes a Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-delete-a-zone
|
|
|
|
:param zone: Zone to delete.
|
|
"""
|
|
response = self._client.request(
|
|
method="DELETE",
|
|
url=f"{self._base_url}/{zone.id_or_name}",
|
|
)
|
|
|
|
return DeleteZoneResponse(
|
|
action=BoundAction(self._parent.actions, response["action"]),
|
|
)
|
|
|
|
def export_zonefile(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
) -> ExportZonefileResponse:
|
|
"""
|
|
Returns a generated Zone file in BIND (RFC 1034/1035) format.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zones-export-a-zone-file
|
|
|
|
:param zone: Zone to export the zone file from.
|
|
"""
|
|
response = self._client.request(
|
|
method="GET",
|
|
url=f"{self._base_url}/{zone.id_or_name}/zonefile",
|
|
)
|
|
return ExportZonefileResponse(response["zonefile"])
|
|
|
|
def get_actions_list(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
*,
|
|
status: list[str] | None = None,
|
|
sort: list[str] | None = None,
|
|
page: int | None = None,
|
|
per_page: int | None = None,
|
|
) -> ActionsPageResult:
|
|
"""
|
|
Returns all Actions for a Zone for a specific page.
|
|
|
|
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.
|
|
"""
|
|
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),
|
|
)
|
|
|
|
def get_actions(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
*,
|
|
status: list[str] | None = None,
|
|
sort: list[str] | 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.
|
|
"""
|
|
return self._iter_pages(
|
|
self.get_actions_list,
|
|
zone,
|
|
status=status,
|
|
sort=sort,
|
|
)
|
|
|
|
def import_zonefile(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
zonefile: str,
|
|
) -> BoundAction:
|
|
"""
|
|
Imports a zone file, replacing all resource record sets (ZoneRRSet).
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-actions-import-a-zone-file
|
|
|
|
:param zone: Zone to import the zone file into.
|
|
:param zonefile: Zone file to import.
|
|
"""
|
|
data: dict[str, Any] = {
|
|
"zonefile": zonefile,
|
|
}
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{zone.id_or_name}/actions/import_zonefile",
|
|
json=data,
|
|
)
|
|
return BoundAction(self._parent.actions, response["action"])
|
|
|
|
def change_protection(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
*,
|
|
delete: bool | None = None,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the protection of a Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-actions-change-a-zones-protection
|
|
|
|
:param zone: Zone to update.
|
|
:param delete: Prevents the Zone from being deleted.
|
|
"""
|
|
data: dict[str, Any] = {}
|
|
if delete is not None:
|
|
data["delete"] = delete
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{zone.id_or_name}/actions/change_protection",
|
|
json=data,
|
|
)
|
|
return BoundAction(self._parent.actions, response["action"])
|
|
|
|
def change_ttl(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
ttl: int,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the TTL of a Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-actions-change-a-zones-default-ttl
|
|
|
|
:param zone: Zone to update.
|
|
:param ttl: Default Time To Live (TTL) of the Zone.
|
|
"""
|
|
data: dict[str, Any] = {
|
|
"ttl": ttl,
|
|
}
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{zone.id_or_name}/actions/change_ttl",
|
|
json=data,
|
|
)
|
|
return BoundAction(self._parent.actions, response["action"])
|
|
|
|
def change_primary_nameservers(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
primary_nameservers: list[ZonePrimaryNameserver],
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the primary nameservers of a Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-actions-change-a-zones-primary-nameservers
|
|
|
|
:param zone: Zone to update.
|
|
:param primary_nameservers: Primary nameservers of the Zone.
|
|
"""
|
|
data: dict[str, Any] = {
|
|
"primary_nameservers": [o.to_payload() for o in primary_nameservers],
|
|
}
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{zone.id_or_name}/actions/change_primary_nameservers",
|
|
json=data,
|
|
)
|
|
return BoundAction(self._parent.actions, response["action"])
|
|
|
|
def get_rrset(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
name: str,
|
|
type: ZoneRRSetType,
|
|
) -> BoundZoneRRSet:
|
|
"""
|
|
Returns a single ZoneRRSet from the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-get-an-rrset
|
|
|
|
:param zone: Zone to fetch the RRSet from.
|
|
:param name: Name of the RRSet.
|
|
:param type: Type of the RRSet.
|
|
"""
|
|
response = self._client.request(
|
|
method="GET",
|
|
url=f"{self._base_url}/{zone.id_or_name}/rrsets/{name}/{type}",
|
|
)
|
|
return BoundZoneRRSet(self, response["rrset"])
|
|
|
|
def get_rrset_list(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
*,
|
|
name: str | None = None,
|
|
type: list[ZoneRRSetType] | None = None,
|
|
label_selector: str | None = None,
|
|
sort: list[str] | None = None,
|
|
page: int | None = None,
|
|
per_page: int | None = None,
|
|
) -> ZoneRRSetsPageResult:
|
|
"""
|
|
Returns all ZoneRRSet in the Zone for a specific page.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-list-rrsets
|
|
|
|
:param zone: Zone to fetch the RRSets from.
|
|
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
|
|
:param type: Filter resources by their type. The response will only contain the resources matching exactly the specified type.
|
|
:param label_selector: Filter resources by labels. The response will only contain resources matching the label selector.
|
|
:param sort: Sort resources by field and direction.
|
|
:param page: Page number to return.
|
|
:param per_page: Maximum number of entries returned per page.
|
|
"""
|
|
params: dict[str, Any] = {}
|
|
if name is not None:
|
|
params["name"] = name
|
|
if type is not None:
|
|
params["type"] = type
|
|
if label_selector is not None:
|
|
params["label_selector"] = label_selector
|
|
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}/rrsets",
|
|
params=params,
|
|
)
|
|
return ZoneRRSetsPageResult(
|
|
rrsets=[BoundZoneRRSet(self, item) for item in response["rrsets"]],
|
|
meta=Meta.parse_meta(response),
|
|
)
|
|
|
|
def get_rrset_all(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
*,
|
|
name: str | None = None,
|
|
type: list[ZoneRRSetType] | None = None,
|
|
label_selector: str | None = None,
|
|
sort: list[str] | None = None,
|
|
) -> list[BoundZoneRRSet]:
|
|
"""
|
|
Returns all ZoneRRSet in the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-list-rrsets
|
|
|
|
:param zone: Zone to fetch the RRSets from.
|
|
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
|
|
:param type: Filter resources by their type. The response will only contain the resources matching exactly the specified type.
|
|
:param label_selector: Filter resources by labels. The response will only contain resources matching the label selector.
|
|
:param sort: Sort resources by field and direction.
|
|
"""
|
|
return self._iter_pages(
|
|
self.get_rrset_list,
|
|
zone,
|
|
name=name,
|
|
type=type,
|
|
label_selector=label_selector,
|
|
sort=sort,
|
|
)
|
|
|
|
def create_rrset(
|
|
self,
|
|
zone: Zone | BoundZone,
|
|
*,
|
|
name: str,
|
|
type: ZoneRRSetType,
|
|
ttl: int | None = None,
|
|
labels: dict[str, str] | None = None,
|
|
records: list[ZoneRecord] | None = None,
|
|
) -> CreateZoneRRSetResponse:
|
|
"""
|
|
Creates a ZoneRRSet in the Zone.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-create-an-rrset
|
|
|
|
:param zone: Zone to create the RRSets in.
|
|
:param name: Name of the RRSet.
|
|
:param type: Type of the RRSet.
|
|
:param ttl: Time To Live (TTL) of the RRSet.
|
|
:param labels: User-defined labels (key/value pairs) for the Resource.
|
|
:param records: Records of the RRSet.
|
|
"""
|
|
data: dict[str, Any] = {
|
|
"name": name,
|
|
"type": type,
|
|
}
|
|
if ttl is not None:
|
|
data["ttl"] = ttl
|
|
if labels is not None:
|
|
data["labels"] = labels
|
|
if records is not None:
|
|
data["records"] = [o.to_payload() for o in records]
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{zone.id_or_name}/rrsets",
|
|
json=data,
|
|
)
|
|
return CreateZoneRRSetResponse(
|
|
rrset=BoundZoneRRSet(self, response["rrset"]),
|
|
action=BoundAction(self._parent.actions, response["action"]),
|
|
)
|
|
|
|
def update_rrset(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
*,
|
|
labels: dict[str, str] | None = None,
|
|
) -> BoundZoneRRSet:
|
|
"""
|
|
Updates a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-update-an-rrset
|
|
|
|
:param rrset: RRSet to update.
|
|
:param labels: User-defined labels (key/value pairs) for the Resource.
|
|
"""
|
|
if rrset.zone is None:
|
|
raise ValueError("rrset zone property is none")
|
|
|
|
data: dict[str, Any] = {}
|
|
if labels is not None:
|
|
data["labels"] = labels
|
|
|
|
response = self._client.request(
|
|
method="PUT",
|
|
url=f"{self._base_url}/{rrset.zone.id_or_name}/rrsets/{rrset.name}/{rrset.type}",
|
|
json=data,
|
|
)
|
|
return BoundZoneRRSet(self, response["rrset"])
|
|
|
|
def delete_rrset(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
) -> DeleteZoneRRSetResponse:
|
|
"""
|
|
Deletes a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrsets-delete-an-rrset
|
|
|
|
:param rrset: RRSet to delete.
|
|
"""
|
|
if rrset.zone is None:
|
|
raise ValueError("rrset zone property is none")
|
|
|
|
response = self._client.request(
|
|
method="DELETE",
|
|
url=f"{self._base_url}/{rrset.zone.id_or_name}/rrsets/{rrset.name}/{rrset.type}",
|
|
)
|
|
return DeleteZoneRRSetResponse(
|
|
action=BoundAction(self._parent.actions, response["action"]),
|
|
)
|
|
|
|
def change_rrset_protection(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
*,
|
|
change: bool | None = None,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the protection of a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-change-an-rrsets-protection
|
|
|
|
:param rrset: RRSet to update.
|
|
:param change: Prevent the Zone from being changed (deletion and updates).
|
|
"""
|
|
if rrset.zone is None:
|
|
raise ValueError("rrset zone property is none")
|
|
|
|
data: dict[str, Any] = {}
|
|
if change is not None:
|
|
data["change"] = change
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{rrset.zone.id_or_name}/rrsets/{rrset.name}/{rrset.type}/actions/change_protection",
|
|
json=data,
|
|
)
|
|
return BoundAction(self._parent.actions, response["action"])
|
|
|
|
def change_rrset_ttl(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
ttl: int | None,
|
|
) -> BoundAction:
|
|
"""
|
|
Changes the TTL of a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-change-an-rrsets-ttl
|
|
|
|
:param rrset: RRSet to update.
|
|
:param change: Time To Live (TTL) of the RRSet.
|
|
"""
|
|
if rrset.zone is None:
|
|
raise ValueError("rrset zone property is none")
|
|
|
|
data: dict[str, Any] = {
|
|
"ttl": ttl,
|
|
}
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{rrset.zone.id_or_name}/rrsets/{rrset.name}/{rrset.type}/actions/change_ttl",
|
|
json=data,
|
|
)
|
|
return BoundAction(self._parent.actions, response["action"])
|
|
|
|
def add_rrset_records(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
records: list[ZoneRecord],
|
|
ttl: int | None = None,
|
|
) -> BoundAction:
|
|
"""
|
|
Adds records to a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-add-records-to-an-rrset
|
|
|
|
:param rrset: RRSet to update.
|
|
:param records: Records to add to the RRSet.
|
|
:param ttl: Time To Live (TTL) of the RRSet.
|
|
"""
|
|
if rrset.zone is None:
|
|
raise ValueError("rrset zone property is none")
|
|
|
|
data: dict[str, Any] = {
|
|
"records": [o.to_payload() for o in records],
|
|
}
|
|
if ttl is not None:
|
|
data["ttl"] = ttl
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{rrset.zone.id_or_name}/rrsets/{rrset.name}/{rrset.type}/actions/add_records",
|
|
json=data,
|
|
)
|
|
return BoundAction(self._parent.actions, response["action"])
|
|
|
|
def remove_rrset_records(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
records: list[ZoneRecord],
|
|
) -> BoundAction:
|
|
"""
|
|
Removes records from a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-remove-records-from-an-rrset
|
|
|
|
:param rrset: RRSet to update.
|
|
:param records: Records to remove from the RRSet.
|
|
"""
|
|
if rrset.zone is None:
|
|
raise ValueError("rrset zone property is none")
|
|
|
|
data: dict[str, Any] = {
|
|
"records": [o.to_payload() for o in records],
|
|
}
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{rrset.zone.id_or_name}/rrsets/{rrset.name}/{rrset.type}/actions/remove_records",
|
|
json=data,
|
|
)
|
|
return BoundAction(self._parent.actions, response["action"])
|
|
|
|
def set_rrset_records(
|
|
self,
|
|
rrset: ZoneRRSet | BoundZoneRRSet,
|
|
records: list[ZoneRecord],
|
|
) -> BoundAction:
|
|
"""
|
|
Sets the records of a ZoneRRSet.
|
|
|
|
See https://docs.hetzner.cloud/reference/cloud#zone-rrset-actions-set-records-of-an-rrset
|
|
|
|
:param rrset: RRSet to update.
|
|
:param records: Records to set in the RRSet.
|
|
"""
|
|
if rrset.zone is None:
|
|
raise ValueError("rrset zone property is none")
|
|
|
|
data: dict[str, Any] = {
|
|
"records": [o.to_payload() for o in records],
|
|
}
|
|
|
|
response = self._client.request(
|
|
method="POST",
|
|
url=f"{self._base_url}/{rrset.zone.id_or_name}/rrsets/{rrset.name}/{rrset.type}/actions/set_records",
|
|
json=data,
|
|
)
|
|
return BoundAction(self._parent.actions, response["action"])
|