from __future__ import annotations
from typing import TYPE_CHECKING, Any, NamedTuple
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
from ..storage_box_types import BoundStorageBoxType, StorageBoxType
from .domain import (
CreateStorageBoxResponse,
CreateStorageBoxSnapshotResponse,
CreateStorageBoxSubaccountResponse,
DeleteStorageBoxResponse,
DeleteStorageBoxSnapshotResponse,
DeleteStorageBoxSubaccountResponse,
StorageBox,
StorageBoxAccessSettings,
StorageBoxFoldersResponse,
StorageBoxSnapshot,
StorageBoxSnapshotPlan,
StorageBoxSnapshotStats,
StorageBoxStats,
StorageBoxSubaccount,
StorageBoxSubaccountAccessSettings,
)
if TYPE_CHECKING:
from .._client import Client
__all__ = [
"BoundStorageBox",
"BoundStorageBoxSnapshot",
"BoundStorageBoxSubaccount",
"StorageBoxesPageResult",
"StorageBoxSnapshotsPageResult",
"StorageBoxSubaccountsPageResult",
"StorageBoxesClient",
]
[docs]
class BoundStorageBox(BoundModelBase[StorageBox], StorageBox):
_client: StorageBoxesClient
model = StorageBox
def __init__(
self,
client: StorageBoxesClient,
data: dict[str, Any],
complete: bool = True,
):
raw = data.get("storage_box_type")
if raw is not None:
data["storage_box_type"] = BoundStorageBoxType(
client._parent.storage_box_types, raw
)
raw = data.get("location")
if raw is not None:
data["location"] = BoundLocation(client._parent.locations, raw)
raw = data.get("snapshot_plan")
if raw is not None:
data["snapshot_plan"] = StorageBoxSnapshotPlan.from_dict(raw)
raw = data.get("access_settings")
if raw is not None:
data["access_settings"] = StorageBoxAccessSettings.from_dict(raw)
raw = data.get("stats")
if raw is not None:
data["stats"] = StorageBoxStats.from_dict(raw)
super().__init__(client, data, complete)
[docs]
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 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.
: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,
)
[docs]
def get_actions(
self,
*,
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 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,
)
[docs]
def update(
self,
*,
name: str | None = None,
labels: dict[str, str] | None = None,
) -> BoundStorageBox:
"""
Updates a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-update-a-storage-box
:param name: Name of the Storage Box.
:param labels: User-defined labels (key/value pairs) for the Storage Box.
"""
return self._client.update(
self,
name=name,
labels=labels,
)
[docs]
def delete(self) -> DeleteStorageBoxResponse:
"""
Deletes a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-delete-a-storage-box
"""
return self._client.delete(self)
[docs]
def get_folders(
self,
*,
path: str | None = None,
) -> StorageBoxFoldersResponse:
"""
Lists the (sub)folders contained in a Storage Box.
Files are not part of the response.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-list-folders-of-a-storage-box
:param path: Relative path to list the folders from.
"""
return self._client.get_folders(
self,
path=path,
)
[docs]
def change_protection(
self,
*,
delete: bool | None = None,
) -> BoundAction:
"""
Changes the protection of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-change-protection
:param delete: Prevents the Storage Box from being deleted.
"""
return self._client.change_protection(
self,
delete=delete,
)
[docs]
def change_type(
self,
storage_box_type: StorageBoxType | BoundStorageBoxType,
) -> BoundAction:
"""
Changes the type of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-change-type
:param storage_box_type: Storage Box Type to change to.
"""
return self._client.change_type(
self,
storage_box_type=storage_box_type,
)
[docs]
def reset_password(
self,
password: str,
) -> BoundAction:
"""
Reset the password of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-reset-password
:param password: New password.
"""
return self._client.reset_password(
self,
password=password,
)
[docs]
def update_access_settings(
self,
access_settings: StorageBoxAccessSettings,
) -> BoundAction:
"""
Update the access settings of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-update-access-settings
:param access_settings: New access settings for the Storage Box.
"""
return self._client.update_access_settings(
self,
access_settings=access_settings,
)
[docs]
def rollback_snapshot(
self,
snapshot: StorageBoxSnapshot | BoundStorageBoxSnapshot,
) -> BoundAction:
"""
Rollback the Storage Box to the given snapshot.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-rollback-snapshot
:param snapshot: Snapshot to rollback to.
"""
return self._client.rollback_snapshot(
self,
snapshot=snapshot,
)
[docs]
def disable_snapshot_plan(
self,
) -> BoundAction:
"""
Disable the snapshot plan of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-disable-snapshot-plan
"""
return self._client.disable_snapshot_plan(self)
[docs]
def enable_snapshot_plan(
self,
snapshot_plan: StorageBoxSnapshotPlan,
) -> BoundAction:
"""
Enable the snapshot plan of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-enable-snapshot-plan
:param snapshot_plan: Snapshot Plan to enable.
"""
return self._client.enable_snapshot_plan(
self,
snapshot_plan=snapshot_plan,
)
# Snapshots
###########################################################################
[docs]
def get_snapshot_by_id(
self,
id: int,
) -> BoundStorageBoxSnapshot:
"""
Returns a single Snapshot from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-get-a-snapshot
:param id: ID of the Snapshot.
"""
return self._client.get_snapshot_by_id(self, id=id)
[docs]
def get_snapshot_by_name(
self,
name: str,
) -> BoundStorageBoxSnapshot | None:
"""
Returns a single Snapshot from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-list-snapshots
:param name: Name of the Snapshot.
"""
return self._client.get_snapshot_by_name(self, name=name)
[docs]
def get_snapshot_list(
self,
*,
name: str | None = None,
is_automatic: bool | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
) -> StorageBoxSnapshotsPageResult:
"""
Returns all Snapshots for a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-list-snapshots
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
:param is_automatic: Filter wether the snapshot was made by a Snapshot Plan.
: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_snapshot_list(
self,
name=name,
is_automatic=is_automatic,
label_selector=label_selector,
sort=sort,
)
[docs]
def get_snapshot_all(
self,
*,
name: str | None = None,
is_automatic: bool | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
) -> list[BoundStorageBoxSnapshot]:
"""
Returns all Snapshots for a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-list-snapshots
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
:param is_automatic: Filter whether the snapshot was made by a Snapshot Plan.
: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_snapshot_all(
self,
name=name,
is_automatic=is_automatic,
label_selector=label_selector,
sort=sort,
)
[docs]
def create_snapshot(
self,
*,
description: str | None = None,
labels: dict[str, str] | None = None,
) -> CreateStorageBoxSnapshotResponse:
"""
Creates a Snapshot of the Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-create-a-snapshot
:param description: Description of the Snapshot.
:param labels: User-defined labels (key/value pairs) for the Snapshot.
"""
return self._client.create_snapshot(
self,
description=description,
labels=labels,
)
# Subaccounts
###########################################################################
[docs]
def get_subaccount_by_id(
self,
id: int,
) -> BoundStorageBoxSubaccount:
"""
Returns a single Subaccount from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-get-a-subaccount
:param id: ID of the Subaccount.
"""
return self._client.get_subaccount_by_id(self, id=id)
[docs]
def get_subaccount_by_name(
self,
name: str,
) -> BoundStorageBoxSubaccount | None:
"""
Returns a single Subaccount from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts
:param name: Name of the Subaccount.
"""
return self._client.get_subaccount_by_name(self, name=name)
[docs]
def get_subaccount_by_username(
self,
username: str,
) -> BoundStorageBoxSubaccount | None:
"""
Returns a single Subaccount from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts
:param username: User name of the Subaccount.
"""
return self._client.get_subaccount_by_username(self, username=username)
[docs]
def get_subaccount_list(
self,
*,
name: str | None = None,
username: str | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
) -> StorageBoxSubaccountsPageResult:
"""
Returns all Subaccounts for a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
:param username: Filter resources by their username. The response will only contain the resources matching exactly the specified username.
: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_subaccount_list(
self,
name=name,
username=username,
label_selector=label_selector,
sort=sort,
)
[docs]
def get_subaccount_all(
self,
*,
name: str | None = None,
username: str | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
) -> list[BoundStorageBoxSubaccount]:
"""
Returns all Subaccounts for a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
:param username: Filter resources by their username. The response will only contain the resources matching exactly the specified username.
: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_subaccount_all(
self,
name=name,
username=username,
label_selector=label_selector,
sort=sort,
)
[docs]
def create_subaccount(
self,
*,
name: str | None = None,
home_directory: str,
password: str,
access_settings: StorageBoxSubaccountAccessSettings | None = None,
description: str | None = None,
labels: dict[str, str] | None = None,
) -> CreateStorageBoxSubaccountResponse:
"""
Creates a Subaccount for the Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-create-a-subaccount
:param storage_box: Storage Box to create a Subaccount for.
:param name: Name of the Subaccount.
:param home_directory: Home directory of the Subaccount.
:param password: Password of the Subaccount.
:param access_settings: Access settings of the Subaccount.
:param description: Description of the Subaccount.
:param labels: User-defined labels (key/value pairs) for the Subaccount.
"""
return self._client.create_subaccount(
self,
name=name,
home_directory=home_directory,
password=password,
access_settings=access_settings,
description=description,
labels=labels,
)
[docs]
class BoundStorageBoxSnapshot(BoundModelBase[StorageBoxSnapshot], StorageBoxSnapshot):
_client: StorageBoxesClient
model = StorageBoxSnapshot
def __init__(
self,
client: StorageBoxesClient,
data: dict[str, Any],
complete: bool = True,
):
raw = data.get("storage_box")
if raw is not None:
data["storage_box"] = BoundStorageBox(
client, data={"id": raw}, complete=False
)
raw = data.get("stats")
if raw is not None:
data["stats"] = StorageBoxSnapshotStats.from_dict(raw)
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,
)
[docs]
def update(
self,
*,
description: str | None = None,
labels: dict[str, str] | None = None,
) -> BoundStorageBoxSnapshot:
"""
Updates a Storage Box Snapshot.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-update-a-snapshot
:param description: Description of the Snapshot.
:param labels: User-defined labels (key/value pairs) for the Snapshot.
"""
return self._client.update_snapshot(
self,
description=description,
labels=labels,
)
[docs]
def delete(
self,
) -> DeleteStorageBoxSnapshotResponse:
"""
Deletes a Storage Box Snapshot.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-delete-a-snapshot
"""
return self._client.delete_snapshot(self)
[docs]
class BoundStorageBoxSubaccount(
BoundModelBase[StorageBoxSubaccount], StorageBoxSubaccount
):
_client: StorageBoxesClient
model = StorageBoxSubaccount
def __init__(
self,
client: StorageBoxesClient,
data: dict[str, Any],
complete: bool = True,
):
raw = data.get("storage_box")
if raw is not None:
data["storage_box"] = BoundStorageBox(
client, data={"id": raw}, complete=False
)
raw = data.get("access_settings")
if raw is not None:
data["access_settings"] = StorageBoxSubaccountAccessSettings.from_dict(raw)
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,
)
[docs]
def update(
self,
*,
name: str | None = None,
description: str | None = None,
labels: dict[str, str] | None = None,
) -> BoundStorageBoxSubaccount:
"""
Updates a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-update-a-subaccount
:param name: Name of the Subaccount.
:param description: Description of the Subaccount.
:param labels: User-defined labels (key/value pairs) for the Subaccount.
"""
return self._client.update_subaccount(
self,
name=name,
description=description,
labels=labels,
)
[docs]
def delete(
self,
) -> DeleteStorageBoxSubaccountResponse:
"""
Deletes a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-delete-a-subaccount
"""
return self._client.delete_subaccount(self)
[docs]
def change_home_directory(
self,
home_directory: str,
) -> BoundAction:
"""
Change the home directory of a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccount-actions-change-home-directory
:param home_directory: Home directory for the Subaccount.
"""
return self._client.change_subaccount_home_directory(
self, home_directory=home_directory
)
[docs]
def reset_password(
self,
password: str,
) -> BoundAction:
"""
Reset the password of a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccount-actions-reset-password
:param password: Password for the Subaccount.
"""
return self._client.reset_subaccount_password(self, password=password)
[docs]
def update_access_settings(
self,
access_settings: StorageBoxSubaccountAccessSettings,
) -> BoundAction:
"""
Update the access settings of a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccount-actions-update-access-settings
:param access_settings: Access settings for the Subaccount.
"""
return self._client.update_subaccount_access_settings(
self,
access_settings=access_settings,
)
[docs]
class StorageBoxesClient(
ResourceClientBaseActionsMixin,
ResourceClientBase,
):
"""
A client for the Storage Boxes API.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes.
"""
_base_url = "/storage_boxes"
actions: ResourceActionsClient
"""Storage Boxes scoped actions client
:type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
"""
def __init__(self, client: Client):
super().__init__(client)
self._client = client._client_hetzner
self.actions = ResourceActionsClient(self, self._base_url)
[docs]
def get_by_id(self, id: int) -> BoundStorageBox:
"""
Returns a specific Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-get-a-storage-box
:param id: ID of the Storage Box.
"""
response = self._client.request(
method="GET",
url=f"{self._base_url}/{id}",
)
return BoundStorageBox(self, response["storage_box"])
[docs]
def get_by_name(self, name: str) -> BoundStorageBox | None:
"""
Returns a specific Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-list-storage-boxes
:param name: Name of the Storage Box.
"""
return self._get_first_by(self.get_list, name=name)
[docs]
def get_list(
self,
*,
name: str | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
page: int | None = None,
per_page: int | None = None,
) -> StorageBoxesPageResult:
"""
Returns a paginated list of Storage Boxes for a specific page.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-list-storage-boxes
:param name: Name of the Storage Box.
: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 label_selector is not None:
params["label_selector"] = label_selector
if page is not None:
params["page"] = page
if per_page is not None:
params["per_page"] = per_page
if sort is not None:
params["sort"] = sort
response = self._client.request(
method="GET",
url=f"{self._base_url}",
params=params,
)
return StorageBoxesPageResult(
storage_boxes=[BoundStorageBox(self, o) for o in response["storage_boxes"]],
meta=Meta.parse_meta(response),
)
[docs]
def get_all(
self,
*,
name: str | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
) -> list[BoundStorageBox]:
"""
Returns all Storage Boxes.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-list-storage-boxes
:param name: Name of the Storage Box.
: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,
label_selector=label_selector,
sort=sort,
)
[docs]
def create(
self,
*,
name: str,
password: str,
location: BoundLocation | Location,
storage_box_type: BoundStorageBoxType | StorageBoxType,
ssh_keys: list[str | SSHKey | BoundSSHKey] | None = None,
access_settings: StorageBoxAccessSettings | None = None,
labels: dict[str, str] | None = None,
) -> CreateStorageBoxResponse:
"""
Creates a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-create-a-storage-box
:param name: Name of the Storage Box.
:param password: Password of the Storage Box.
:param location: Location of the Storage Box.
:param storage_box_type: Type of the Storage Box.
:param ssh_keys: SSH public keys of the Storage Box.
:param access_settings: Access settings of the Storage Box.
:param labels: User-defined labels (key/value pairs) for the Storage Box.
"""
data: dict[str, Any] = {
"name": name,
"password": password,
"location": location.id_or_name,
"storage_box_type": storage_box_type.id_or_name,
}
if ssh_keys is not None:
data["ssh_keys"] = [
o.public_key if isinstance(o, (SSHKey, BoundSSHKey)) else o
for o in ssh_keys
]
if access_settings is not None:
data["access_settings"] = access_settings.to_payload()
if labels is not None:
data["labels"] = labels
response = self._client.request(
method="POST",
url=f"{self._base_url}",
json=data,
)
return CreateStorageBoxResponse(
storage_box=BoundStorageBox(self, response["storage_box"]),
action=BoundAction(self._parent.actions, response["action"]),
)
[docs]
def update(
self,
storage_box: BoundStorageBox | StorageBox,
*,
name: str | None = None,
labels: dict[str, str] | None = None,
) -> BoundStorageBox:
"""
Updates a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-update-a-storage-box
:param storage_box: Storage Box to update.
:param name: Name of the Storage Box.
:param labels: User-defined labels (key/value pairs) for the Storage Box.
"""
data: dict[str, Any] = {}
if name is not None:
data["name"] = name
if labels is not None:
data["labels"] = labels
response = self._client.request(
method="PUT",
url=f"{self._base_url}/{storage_box.id}",
json=data,
)
return BoundStorageBox(self, response["storage_box"])
[docs]
def delete(
self,
storage_box: BoundStorageBox | StorageBox,
) -> DeleteStorageBoxResponse:
"""
Deletes a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-delete-a-storage-box
:param storage_box: Storage Box to delete.
"""
response = self._client.request(
method="DELETE",
url=f"{self._base_url}/{storage_box.id}",
)
return DeleteStorageBoxResponse(
action=BoundAction(self._parent.actions, response["action"])
)
[docs]
def get_folders(
self,
storage_box: BoundStorageBox | StorageBox,
*,
path: str | None = None,
) -> StorageBoxFoldersResponse:
"""
Lists the (sub)folders contained in a Storage Box.
Files are not part of the response.
See https://docs.hetzner.cloud/reference/hetzner#storage-boxes-list-folders-of-a-storage-box
:param storage_box: Storage Box to list the folders from.
:param path: Relative path to list the folders from.
"""
params: dict[str, Any] = {}
if path is not None:
params["path"] = path
response = self._client.request(
method="GET",
url=f"{self._base_url}/{storage_box.id}/folders",
params=params,
)
return StorageBoxFoldersResponse(folders=response["folders"])
[docs]
def get_actions_list(
self,
storage_box: StorageBox | BoundStorageBox,
*,
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.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-list-actions-for-a-storage-box
: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.
"""
return self._get_actions_list(
f"{self._base_url}/{storage_box.id}",
status=status,
sort=sort,
page=page,
per_page=per_page,
)
[docs]
def get_actions(
self,
storage_box: StorageBox | BoundStorageBox,
*,
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 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.
"""
return self._iter_pages(
self.get_actions_list,
storage_box,
status=status,
sort=sort,
)
[docs]
def change_protection(
self,
storage_box: StorageBox | BoundStorageBox,
*,
delete: bool | None = None,
) -> BoundAction:
"""
Changes the protection of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-change-protection
:param storage_box: Storage Box to update.
:param delete: Prevents the Storage Box 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}/{storage_box.id}/actions/change_protection",
json=data,
)
return BoundAction(self._parent.actions, response["action"])
[docs]
def change_type(
self,
storage_box: StorageBox | BoundStorageBox,
storage_box_type: StorageBoxType | BoundStorageBoxType,
) -> BoundAction:
"""
Changes the type of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-change-type
:param storage_box: Storage Box to update.
:param storage_box_type: Storage Box Type to change to.
"""
data: dict[str, Any] = {
"storage_box_type": storage_box_type.id_or_name,
}
response = self._client.request(
method="POST",
url=f"{self._base_url}/{storage_box.id}/actions/change_type",
json=data,
)
return BoundAction(self._parent.actions, response["action"])
[docs]
def reset_password(
self,
storage_box: StorageBox | BoundStorageBox,
password: str,
) -> BoundAction:
"""
Reset the password of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-reset-password
:param storage_box: Storage Box to update.
:param password: New password.
"""
data: dict[str, Any] = {
"password": password,
}
response = self._client.request(
method="POST",
url=f"{self._base_url}/{storage_box.id}/actions/reset_password",
json=data,
)
return BoundAction(self._parent.actions, response["action"])
[docs]
def update_access_settings(
self,
storage_box: StorageBox | BoundStorageBox,
access_settings: StorageBoxAccessSettings,
) -> BoundAction:
"""
Update the access settings of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-update-access-settings
:param storage_box: Storage Box to update.
:param access_settings: New access settings for the Storage Box.
"""
data: dict[str, Any] = access_settings.to_payload()
response = self._client.request(
method="POST",
url=f"{self._base_url}/{storage_box.id}/actions/update_access_settings",
json=data,
)
return BoundAction(self._parent.actions, response["action"])
[docs]
def rollback_snapshot(
self,
storage_box: StorageBox | BoundStorageBox,
snapshot: StorageBoxSnapshot | BoundStorageBoxSnapshot,
) -> BoundAction:
"""
Rollback the Storage Box to the given snapshot.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-rollback-snapshot
:param storage_box: Storage Box to update.
:param snapshot: Snapshot to rollback to.
"""
data: dict[str, Any] = {
"snapshot": snapshot.id_or_name,
}
response = self._client.request(
method="POST",
url=f"{self._base_url}/{storage_box.id}/actions/rollback_snapshot",
json=data,
)
return BoundAction(self._parent.actions, response["action"])
[docs]
def disable_snapshot_plan(
self,
storage_box: StorageBox | BoundStorageBox,
) -> BoundAction:
"""
Disable the snapshot plan of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-disable-snapshot-plan
:param storage_box: Storage Box to update.
"""
response = self._client.request(
method="POST",
url=f"{self._base_url}/{storage_box.id}/actions/disable_snapshot_plan",
)
return BoundAction(self._parent.actions, response["action"])
[docs]
def enable_snapshot_plan(
self,
storage_box: StorageBox | BoundStorageBox,
snapshot_plan: StorageBoxSnapshotPlan,
) -> BoundAction:
"""
Enable the snapshot plan of a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-actions-enable-snapshot-plan
:param storage_box: Storage Box to update.
:param snapshot_plan: Snapshot Plan to enable.
"""
data: dict[str, Any] = snapshot_plan.to_payload()
response = self._client.request(
method="POST",
url=f"{self._base_url}/{storage_box.id}/actions/enable_snapshot_plan",
json=data,
)
return BoundAction(self._parent.actions, response["action"])
# Snapshots
###########################################################################
[docs]
def get_snapshot_by_id(
self,
storage_box: StorageBox | BoundStorageBox,
id: int,
) -> BoundStorageBoxSnapshot:
"""
Returns a single Snapshot from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-get-a-snapshot
:param storage_box: Storage Box to get the Snapshot from.
:param id: ID of the Snapshot.
"""
response = self._client.request(
method="GET",
url=f"{self._base_url}/{storage_box.id}/snapshots/{id}",
)
return BoundStorageBoxSnapshot(self, response["snapshot"])
[docs]
def get_snapshot_by_name(
self,
storage_box: StorageBox | BoundStorageBox,
name: str,
) -> BoundStorageBoxSnapshot | None:
"""
Returns a single Snapshot from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-list-snapshots
:param storage_box: Storage Box to get the Snapshot from.
:param name: Name of the Snapshot.
"""
return self._get_first_by(self.get_snapshot_list, storage_box, name=name)
[docs]
def get_snapshot_list(
self,
storage_box: StorageBox | BoundStorageBox,
*,
name: str | None = None,
is_automatic: bool | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
) -> StorageBoxSnapshotsPageResult:
"""
Returns all Snapshots for a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-list-snapshots
:param storage_box: Storage Box to get the Snapshots from.
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
:param is_automatic: Filter whether the snapshot was made by a Snapshot Plan.
: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.
"""
params: dict[str, Any] = {}
if name is not None:
params["name"] = name
if is_automatic is not None:
params["is_automatic"] = is_automatic
if label_selector is not None:
params["label_selector"] = label_selector
if sort is not None:
params["sort"] = sort
response = self._client.request(
method="GET",
url=f"{self._base_url}/{storage_box.id}/snapshots",
params=params,
)
return StorageBoxSnapshotsPageResult(
snapshots=[
BoundStorageBoxSnapshot(self, item) for item in response["snapshots"]
],
meta=Meta.parse_meta(response),
)
[docs]
def get_snapshot_all(
self,
storage_box: StorageBox | BoundStorageBox,
*,
name: str | None = None,
is_automatic: bool | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
) -> list[BoundStorageBoxSnapshot]:
"""
Returns all Snapshots for a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-list-snapshots
:param storage_box: Storage Box to get the Snapshots from.
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
:param is_automatic: Filter whether the snapshot was made by a Snapshot Plan.
: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.
"""
# The endpoint does not have pagination, forward to the list method.
result, _ = self.get_snapshot_list(
storage_box,
name=name,
is_automatic=is_automatic,
label_selector=label_selector,
sort=sort,
)
return result
[docs]
def create_snapshot(
self,
storage_box: StorageBox | BoundStorageBox,
*,
description: str | None = None,
labels: dict[str, str] | None = None,
) -> CreateStorageBoxSnapshotResponse:
"""
Creates a Snapshot of the Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-create-a-snapshot
:param storage_box: Storage Box to create a Snapshot from.
:param description: Description of the Snapshot.
:param labels: User-defined labels (key/value pairs) for the Snapshot.
"""
data: dict[str, Any] = {}
if description is not None:
data["description"] = description
if labels is not None:
data["labels"] = labels
response = self._client.request(
method="POST",
url=f"{self._base_url}/{storage_box.id}/snapshots",
json=data,
)
return CreateStorageBoxSnapshotResponse(
snapshot=BoundStorageBoxSnapshot(
self,
response["snapshot"],
# API only returns a partial object.
complete=False,
),
action=BoundAction(self._parent.actions, response["action"]),
)
[docs]
def update_snapshot(
self,
snapshot: StorageBoxSnapshot | BoundStorageBoxSnapshot,
*,
description: str | None = None,
labels: dict[str, str] | None = None,
) -> BoundStorageBoxSnapshot:
"""
Updates a Storage Box Snapshot.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-update-a-snapshot
:param snapshot: Storage Box Snapshot to update.
:param description: Description of the Snapshot.
:param labels: User-defined labels (key/value pairs) for the Snapshot.
"""
if snapshot.storage_box is None:
raise ValueError("snapshot storage_box property is none")
data: dict[str, Any] = {}
if description is not None:
data["description"] = description
if labels is not None:
data["labels"] = labels
response = self._client.request(
method="PUT",
url=f"{self._base_url}/{snapshot.storage_box.id}/snapshots/{snapshot.id}",
json=data,
)
return BoundStorageBoxSnapshot(self, response["snapshot"])
[docs]
def delete_snapshot(
self,
snapshot: StorageBoxSnapshot | BoundStorageBoxSnapshot,
) -> DeleteStorageBoxSnapshotResponse:
"""
Deletes a Storage Box Snapshot.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-delete-a-snapshot
:param snapshot: Storage Box Snapshot to delete.
"""
if snapshot.storage_box is None:
raise ValueError("snapshot storage_box property is none")
response = self._client.request(
method="DELETE",
url=f"{self._base_url}/{snapshot.storage_box.id}/snapshots/{snapshot.id}",
)
return DeleteStorageBoxSnapshotResponse(
action=BoundAction(self._parent.actions, response["action"]),
)
# Subaccounts
###########################################################################
[docs]
def get_subaccount_by_id(
self,
storage_box: StorageBox | BoundStorageBox,
id: int,
) -> BoundStorageBoxSubaccount:
"""
Returns a single Subaccount from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-get-a-subaccount
:param storage_box: Storage Box to get the Subaccount from.
:param id: ID of the Subaccount.
"""
response = self._client.request(
method="GET",
url=f"{self._base_url}/{storage_box.id}/subaccounts/{id}",
)
return BoundStorageBoxSubaccount(self, response["subaccount"])
[docs]
def get_subaccount_by_name(
self,
storage_box: StorageBox | BoundStorageBox,
name: str,
) -> BoundStorageBoxSubaccount | None:
"""
Returns a single Subaccount from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts
:param storage_box: Storage Box to get the Subaccount from.
:param name: Name of the Subaccount.
"""
return self._get_first_by(
self.get_subaccount_list,
storage_box,
name=name,
)
[docs]
def get_subaccount_by_username(
self,
storage_box: StorageBox | BoundStorageBox,
username: str,
) -> BoundStorageBoxSubaccount | None:
"""
Returns a single Subaccount from a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts
:param storage_box: Storage Box to get the Subaccount from.
:param username: User name of the Subaccount.
"""
return self._get_first_by(
self.get_subaccount_list,
storage_box,
username=username,
)
[docs]
def get_subaccount_list(
self,
storage_box: StorageBox | BoundStorageBox,
*,
name: str | None = None,
username: str | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
) -> StorageBoxSubaccountsPageResult:
"""
Returns all Subaccounts for a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts
:param storage_box: Storage Box to get the Subaccount from.
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
:param username: Filter resources by their username. The response will only contain the resources matching exactly the specified username.
: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.
"""
params: dict[str, Any] = {}
if name is not None:
params["name"] = name
if username is not None:
params["username"] = username
if label_selector is not None:
params["label_selector"] = label_selector
if sort is not None:
params["sort"] = sort
response = self._client.request(
method="GET",
url=f"{self._base_url}/{storage_box.id}/subaccounts",
params=params,
)
return StorageBoxSubaccountsPageResult(
subaccounts=[
BoundStorageBoxSubaccount(self, item)
for item in response["subaccounts"]
],
meta=Meta.parse_meta(response),
)
[docs]
def get_subaccount_all(
self,
storage_box: StorageBox | BoundStorageBox,
*,
name: str | None = None,
username: str | None = None,
label_selector: str | None = None,
sort: list[str] | None = None,
) -> list[BoundStorageBoxSubaccount]:
"""
Returns all Subaccounts for a Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts
:param storage_box: Storage Box to get the Subaccount from.
:param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name.
:param username: Filter resources by their username. The response will only contain the resources matching exactly the specified username.
: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.
"""
# The endpoint does not have pagination, forward to the list method.
result, _ = self.get_subaccount_list(
storage_box,
name=name,
username=username,
label_selector=label_selector,
sort=sort,
)
return result
[docs]
def create_subaccount(
self,
storage_box: StorageBox | BoundStorageBox,
*,
name: str | None = None,
home_directory: str,
password: str,
access_settings: StorageBoxSubaccountAccessSettings | None = None,
description: str | None = None,
labels: dict[str, str] | None = None,
) -> CreateStorageBoxSubaccountResponse:
"""
Creates a Subaccount for the Storage Box.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-create-a-subaccount
:param storage_box: Storage Box to create a Subaccount for.
:param name: Name of the Subaccount.
:param home_directory: Home directory of the Subaccount.
:param password: Password of the Subaccount.
:param access_settings: Access settings of the Subaccount.
:param description: Description of the Subaccount.
:param labels: User-defined labels (key/value pairs) for the Subaccount.
"""
data: dict[str, Any] = {
"home_directory": home_directory,
"password": password,
}
if name is not None:
data["name"] = name
if access_settings is not None:
data["access_settings"] = access_settings.to_payload()
if description is not None:
data["description"] = description
if labels is not None:
data["labels"] = labels
response = self._client.request(
method="POST",
url=f"{self._base_url}/{storage_box.id}/subaccounts",
json=data,
)
return CreateStorageBoxSubaccountResponse(
subaccount=BoundStorageBoxSubaccount(
self,
response["subaccount"],
# API only returns a partial object.
complete=False,
),
action=BoundAction(self._parent.actions, response["action"]),
)
[docs]
def update_subaccount(
self,
subaccount: StorageBoxSubaccount | BoundStorageBoxSubaccount,
*,
name: str | None = None,
description: str | None = None,
labels: dict[str, str] | None = None,
) -> BoundStorageBoxSubaccount:
"""
Updates a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-update-a-subaccount
:param subaccount: Storage Box Subaccount to update.
:param name: Name of the Subaccount.
:param description: Description of the Subaccount.
:param labels: User-defined labels (key/value pairs) for the Subaccount.
"""
if subaccount.storage_box is None:
raise ValueError("subaccount storage_box property is none")
data: dict[str, Any] = {}
if name is not None:
data["name"] = name
if description is not None:
data["description"] = description
if labels is not None:
data["labels"] = labels
response = self._client.request(
method="PUT",
url=f"{self._base_url}/{subaccount.storage_box.id}/subaccounts/{subaccount.id}",
json=data,
)
return BoundStorageBoxSubaccount(self, response["subaccount"])
[docs]
def delete_subaccount(
self,
subaccount: StorageBoxSubaccount | BoundStorageBoxSubaccount,
) -> DeleteStorageBoxSubaccountResponse:
"""
Deletes a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-delete-a-subaccount
:param subaccount: Storage Box Subaccount to delete.
"""
if subaccount.storage_box is None:
raise ValueError("subaccount storage_box property is none")
response = self._client.request(
method="DELETE",
url=f"{self._base_url}/{subaccount.storage_box.id}/subaccounts/{subaccount.id}",
)
return DeleteStorageBoxSubaccountResponse(
action=BoundAction(self._parent.actions, response["action"]),
)
[docs]
def change_subaccount_home_directory(
self,
subaccount: StorageBoxSubaccount | BoundStorageBoxSubaccount,
home_directory: str,
) -> BoundAction:
"""
Change the home directory of a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccount-actions-change-home-directory
:param subaccount: Storage Box Subaccount to update.
:param home_directory: Home directory for the Subaccount.
"""
if subaccount.storage_box is None:
raise ValueError("subaccount storage_box property is none")
data: dict[str, Any] = {
"home_directory": home_directory,
}
response = self._client.request(
method="POST",
url=f"{self._base_url}/{subaccount.storage_box.id}/subaccounts/{subaccount.id}/actions/change_home_directory",
json=data,
)
return BoundAction(self._parent.actions, response["action"])
[docs]
def reset_subaccount_password(
self,
subaccount: StorageBoxSubaccount | BoundStorageBoxSubaccount,
password: str,
) -> BoundAction:
"""
Reset the password of a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccount-actions-reset-password
:param subaccount: Storage Box Subaccount to update.
:param password: Password for the Subaccount.
"""
if subaccount.storage_box is None:
raise ValueError("subaccount storage_box property is none")
data: dict[str, Any] = {
"password": password,
}
response = self._client.request(
method="POST",
url=f"{self._base_url}/{subaccount.storage_box.id}/subaccounts/{subaccount.id}/actions/reset_subaccount_password",
json=data,
)
return BoundAction(self._parent.actions, response["action"])
[docs]
def update_subaccount_access_settings(
self,
subaccount: StorageBoxSubaccount | BoundStorageBoxSubaccount,
access_settings: StorageBoxSubaccountAccessSettings,
) -> BoundAction:
"""
Update the access settings of a Storage Box Subaccount.
See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccount-actions-update-access-settings
:param subaccount: Storage Box Subaccount to update.
:param access_settings: Access settings for the Subaccount.
"""
if subaccount.storage_box is None:
raise ValueError("subaccount storage_box property is none")
data: dict[str, Any] = access_settings.to_payload()
response = self._client.request(
method="POST",
url=f"{self._base_url}/{subaccount.storage_box.id}/subaccounts/{subaccount.id}/actions/update_access_settings",
json=data,
)
return BoundAction(self._parent.actions, response["action"])