|
8 | 8 | from ..storage_box_types import BoundStorageBoxType, StorageBoxType |
9 | 9 | from .domain import ( |
10 | 10 | CreateStorageBoxResponse, |
| 11 | + CreateStorageBoxSnapshotResponse, |
11 | 12 | DeleteStorageBoxResponse, |
| 13 | + DeleteStorageBoxSnapshotResponse, |
12 | 14 | StorageBox, |
13 | 15 | StorageBoxAccessSettings, |
14 | 16 | StorageBoxFoldersResponse, |
15 | 17 | StorageBoxSnapshot, |
16 | 18 | StorageBoxSnapshotPlan, |
| 19 | + StorageBoxSnapshotStats, |
17 | 20 | StorageBoxStats, |
18 | 21 | ) |
19 | 22 |
|
@@ -105,11 +108,41 @@ def get_actions( |
105 | 108 | # TODO: implement bound methods |
106 | 109 |
|
107 | 110 |
|
| 111 | +class BoundStorageBoxSnapshot(BoundModelBase, StorageBoxSnapshot): |
| 112 | + _client: StorageBoxesClient |
| 113 | + |
| 114 | + model = StorageBoxSnapshot |
| 115 | + |
| 116 | + def __init__( |
| 117 | + self, |
| 118 | + client: StorageBoxesClient, |
| 119 | + data: dict[str, Any], |
| 120 | + complete: bool = True, |
| 121 | + ): |
| 122 | + |
| 123 | + raw = data.get("storage_box") |
| 124 | + if raw is not None: |
| 125 | + data["zone"] = BoundStorageBox(client, data={"id": raw}, complete=False) |
| 126 | + |
| 127 | + raw = data.get("stats") |
| 128 | + if raw is not None: |
| 129 | + data["stats"] = StorageBoxSnapshotStats.from_dict(raw) |
| 130 | + |
| 131 | + super().__init__(client, data, complete) |
| 132 | + |
| 133 | + # TODO: implement bound methods |
| 134 | + |
| 135 | + |
108 | 136 | class StorageBoxesPageResult(NamedTuple): |
109 | 137 | storage_boxes: list[BoundStorageBox] |
110 | 138 | meta: Meta |
111 | 139 |
|
112 | 140 |
|
| 141 | +class StorageBoxSnapshotsPageResult(NamedTuple): |
| 142 | + snapshots: list[BoundStorageBoxSnapshot] |
| 143 | + meta: Meta |
| 144 | + |
| 145 | + |
113 | 146 | class StorageBoxesClient(ResourceClientBase): |
114 | 147 | """ |
115 | 148 | A client for the Storage Boxes API. |
@@ -556,3 +589,192 @@ def enable_snapshot_plan( |
556 | 589 | json=data, |
557 | 590 | ) |
558 | 591 | return BoundAction(self._parent.actions, response["action"]) |
| 592 | + |
| 593 | + # Snapshots |
| 594 | + ########################################################################### |
| 595 | + |
| 596 | + def get_snapshot( |
| 597 | + self, |
| 598 | + storage_box: StorageBox | BoundStorageBox, |
| 599 | + id: int, |
| 600 | + ) -> BoundStorageBoxSnapshot: |
| 601 | + """ |
| 602 | + Returns a single Snapshot from a Storage Box. |
| 603 | +
|
| 604 | + See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-get-a-snapshot |
| 605 | +
|
| 606 | + :param storage_box: Storage Box to get the Snapshot from. |
| 607 | + :param id: ID of the Snapshot. |
| 608 | + """ |
| 609 | + response = self._client.request( |
| 610 | + method="GET", |
| 611 | + url=f"{self._base_url}/{storage_box.id}/snapshots/{id}", |
| 612 | + ) |
| 613 | + return BoundStorageBoxSnapshot(self, response["snapshot"]) |
| 614 | + |
| 615 | + def get_snapshot_list( |
| 616 | + self, |
| 617 | + storage_box: StorageBox | BoundStorageBox, |
| 618 | + *, |
| 619 | + name: str | None = None, |
| 620 | + is_automatic: bool | None = None, |
| 621 | + label_selector: str | None = None, |
| 622 | + sort: list[str] | None = None, |
| 623 | + page: int | None = None, |
| 624 | + per_page: int | None = None, |
| 625 | + ) -> StorageBoxSnapshotsPageResult: |
| 626 | + """ |
| 627 | + Returns a paginated list of Snapshots for a Storage Box. |
| 628 | +
|
| 629 | + See https://docs.hetzner.cloud/reference/cloud#zone-snapshots-list-snapshots |
| 630 | +
|
| 631 | + :param zone: Zone to fetch the RRSets from. |
| 632 | + :param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name. |
| 633 | + :param type: Filter resources by their type. The response will only contain the resources matching exactly the specified type. |
| 634 | + :param label_selector: Filter resources by labels. The response will only contain resources matching the label selector. |
| 635 | + :param sort: Sort resources by field and direction. |
| 636 | + :param page: Page number to return. |
| 637 | + :param per_page: Maximum number of entries returned per page. |
| 638 | + """ |
| 639 | + params: dict[str, Any] = {} |
| 640 | + if name is not None: |
| 641 | + params["name"] = name |
| 642 | + if is_automatic is not None: |
| 643 | + params["is_automatic"] = is_automatic |
| 644 | + if label_selector is not None: |
| 645 | + params["label_selector"] = label_selector |
| 646 | + if sort is not None: |
| 647 | + params["sort"] = sort |
| 648 | + if page is not None: |
| 649 | + params["page"] = page |
| 650 | + if per_page is not None: |
| 651 | + params["per_page"] = per_page |
| 652 | + |
| 653 | + response = self._client.request( |
| 654 | + method="GET", |
| 655 | + url=f"{self._base_url}/{storage_box.id}/snapshots", |
| 656 | + params=params, |
| 657 | + ) |
| 658 | + return StorageBoxSnapshotsPageResult( |
| 659 | + snapshots=[ |
| 660 | + BoundStorageBoxSnapshot(self, item) for item in response["snapshots"] |
| 661 | + ], |
| 662 | + meta=Meta.parse_meta(response), |
| 663 | + ) |
| 664 | + |
| 665 | + def get_snapshot_all( |
| 666 | + self, |
| 667 | + storage_box: StorageBox | BoundStorageBox, |
| 668 | + *, |
| 669 | + name: str | None = None, |
| 670 | + is_automatic: bool | None = None, |
| 671 | + label_selector: str | None = None, |
| 672 | + sort: list[str] | None = None, |
| 673 | + ) -> list[BoundStorageBoxSnapshot]: |
| 674 | + """ |
| 675 | + Returns all Snapshots for a Storage Box. |
| 676 | +
|
| 677 | + See https://docs.hetzner.cloud/reference/cloud#zone-snapshots-list-snapshots |
| 678 | +
|
| 679 | + :param zone: Zone to fetch the RRSets from. |
| 680 | + :param name: Filter resources by their name. The response will only contain the resources matching exactly the specified name. |
| 681 | + :param type: Filter resources by their type. The response will only contain the resources matching exactly the specified type. |
| 682 | + :param label_selector: Filter resources by labels. The response will only contain resources matching the label selector. |
| 683 | + :param sort: Sort resources by field and direction. |
| 684 | + """ |
| 685 | + return self._iter_pages( |
| 686 | + self.get_snapshot_list, |
| 687 | + storage_box, |
| 688 | + name=name, |
| 689 | + is_automatic=is_automatic, |
| 690 | + label_selector=label_selector, |
| 691 | + sort=sort, |
| 692 | + ) |
| 693 | + |
| 694 | + def create_snapshot( |
| 695 | + self, |
| 696 | + storage_box: StorageBox | BoundStorageBox, |
| 697 | + *, |
| 698 | + description: str | None = None, |
| 699 | + labels: dict[str, str] | None = None, |
| 700 | + ) -> CreateStorageBoxSnapshotResponse: |
| 701 | + """ |
| 702 | + Creates a Snapshot of the Storage Box. |
| 703 | +
|
| 704 | + See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-create-a-snapshot |
| 705 | +
|
| 706 | + :param zone: Zone to create the RRSets in. |
| 707 | + :param name: Name of the RRSet. |
| 708 | + :param type: Type of the RRSet. |
| 709 | + :param ttl: Time To Live (TTL) of the RRSet. |
| 710 | + :param labels: User-defined labels (key/value pairs) for the Resource. |
| 711 | + :param records: Records of the RRSet. |
| 712 | + """ |
| 713 | + data: dict[str, Any] = {} |
| 714 | + if description is not None: |
| 715 | + data["description"] = description |
| 716 | + if labels is not None: |
| 717 | + data["labels"] = labels |
| 718 | + |
| 719 | + response = self._client.request( |
| 720 | + method="POST", |
| 721 | + url=f"{self._base_url}/{storage_box.id}/snapshots", |
| 722 | + json=data, |
| 723 | + ) |
| 724 | + return CreateStorageBoxSnapshotResponse( |
| 725 | + snapshot=BoundStorageBoxSnapshot(self, response["snapshot"]), |
| 726 | + action=BoundAction(self._parent.actions, response["action"]), |
| 727 | + ) |
| 728 | + |
| 729 | + def update_snapshot( |
| 730 | + self, |
| 731 | + snapshot: StorageBoxSnapshot | BoundStorageBoxSnapshot, |
| 732 | + *, |
| 733 | + description: str | None = None, |
| 734 | + labels: dict[str, str] | None = None, |
| 735 | + ) -> BoundStorageBoxSnapshot: |
| 736 | + """ |
| 737 | + Updates a Storage Box Snapshot. |
| 738 | +
|
| 739 | + See https://docs.hetzner.cloud/reference/hetzner#storage-box-snapshots-update-a-snapshot |
| 740 | +
|
| 741 | + :param snapshot: RRSet to update. |
| 742 | + :param labels: User-defined labels (key/value pairs) for the Resource. |
| 743 | + """ |
| 744 | + if snapshot.storage_box is None: |
| 745 | + raise ValueError("snapshot storage_box property is none") |
| 746 | + |
| 747 | + data: dict[str, Any] = {} |
| 748 | + if description is not None: |
| 749 | + data["description"] = description |
| 750 | + if labels is not None: |
| 751 | + data["labels"] = labels |
| 752 | + |
| 753 | + response = self._client.request( |
| 754 | + method="PUT", |
| 755 | + url=f"{self._base_url}/{snapshot.storage_box.id}/snapshots/{snapshot.id}", |
| 756 | + json=data, |
| 757 | + ) |
| 758 | + return BoundStorageBoxSnapshot(self, response["snapshot"]) |
| 759 | + |
| 760 | + def delete_snapshot( |
| 761 | + self, |
| 762 | + snapshot: StorageBoxSnapshot | BoundStorageBoxSnapshot, |
| 763 | + ) -> DeleteStorageBoxSnapshotResponse: |
| 764 | + """ |
| 765 | + Deletes a ZoneRRSet. |
| 766 | +
|
| 767 | + See https://docs.hetzner.cloud/reference/cloud#zone-snapshots-delete-an-snapshot |
| 768 | +
|
| 769 | + :param snapshot: RRSet to delete. |
| 770 | + """ |
| 771 | + if snapshot.storage_box is None: |
| 772 | + raise ValueError("snapshot storage_box property is none") |
| 773 | + |
| 774 | + response = self._client.request( |
| 775 | + method="DELETE", |
| 776 | + url=f"{self._base_url}/{snapshot.storage_box.id}/snapshots/{snapshot.id}", |
| 777 | + ) |
| 778 | + return DeleteStorageBoxSnapshotResponse( |
| 779 | + action=BoundAction(self._parent.actions, response["action"]), |
| 780 | + ) |
0 commit comments