mirror of
https://github.com/ansible-collections/hetzner.hcloud.git
synced 2026-02-04 08:01:49 +00:00
add snapshot plan
This commit is contained in:
parent
4c75cfc7e5
commit
c5809b6892
4 changed files with 188 additions and 6 deletions
|
|
@ -6,6 +6,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import traceback
|
||||
from copy import deepcopy
|
||||
from typing import Any, NoReturn
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule as AnsibleModuleBase, env_fallback
|
||||
|
|
@ -29,6 +30,23 @@ from .version import version
|
|||
# Provide typing definitions to the AnsibleModule class
|
||||
class AnsibleModule(AnsibleModuleBase):
|
||||
params: dict
|
||||
params_raw: dict
|
||||
|
||||
def _load_params(self):
|
||||
"""
|
||||
Copy the params before validation, to keep track whether a value was defined by the user.
|
||||
|
||||
Validation will modify the params dict by adding missing keys.
|
||||
"""
|
||||
# https://github.com/ansible/ansible/blob/7b4d4ed672415f31689e7f25bc0b40c0697c0c88/lib/ansible/module_utils/basic.py#L1244-L1251
|
||||
super()._load_params()
|
||||
self.params_raw = deepcopy(self.params)
|
||||
|
||||
def param_is_defined(self, key: str):
|
||||
"""
|
||||
Check if a parameter was defined by the user.
|
||||
"""
|
||||
return key in self.params_raw
|
||||
|
||||
|
||||
class AnsibleHCloud:
|
||||
|
|
|
|||
|
|
@ -29,4 +29,15 @@ def prepare_result(o: BoundStorageBox):
|
|||
"size_data": o.stats.size_data,
|
||||
"size_snapshots": o.stats.size_snapshots,
|
||||
},
|
||||
"snapshot_plan": (
|
||||
None
|
||||
if o.snapshot_plan is None
|
||||
else {
|
||||
"max_snapshots": o.snapshot_plan.max_snapshots,
|
||||
"hour": o.snapshot_plan.hour,
|
||||
"minute": o.snapshot_plan.minute,
|
||||
"day_of_week": o.snapshot_plan.day_of_week,
|
||||
"day_of_month": o.snapshot_plan.day_of_month,
|
||||
}
|
||||
),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,36 @@ options:
|
|||
- Whether the ZFS snapshot folder is visible.
|
||||
type: bool
|
||||
default: false
|
||||
snapshot_plan:
|
||||
description:
|
||||
- Snapshot plan of the Storage Box.
|
||||
- Use null to disabled the snapshot plan.
|
||||
type: dict
|
||||
suboptions:
|
||||
max_snapshots:
|
||||
description:
|
||||
- Maximum amount of Snapshots that will be created by this Snapshot Plan.
|
||||
- Older Snapshots will be deleted.
|
||||
type: int
|
||||
hour:
|
||||
description:
|
||||
- Hour when the Snapshot Plan is executed (UTC).
|
||||
type: int
|
||||
minute:
|
||||
description:
|
||||
- Minute when the Snapshot Plan is executed (UTC).
|
||||
type: int
|
||||
day_of_week:
|
||||
description:
|
||||
- Day of the week when the Snapshot Plan is executed.
|
||||
- Starts at 1 for Monday til 7 for Sunday.
|
||||
- Null means every day.
|
||||
type: int
|
||||
day_of_month:
|
||||
description:
|
||||
- Day of the month when the Snapshot Plan is executed.
|
||||
- Null means every day.
|
||||
type: int
|
||||
delete_protection:
|
||||
description:
|
||||
- Protect the Storage Box from deletion.
|
||||
|
|
@ -126,6 +156,24 @@ EXAMPLES = """
|
|||
zfs_enabled: false
|
||||
state: present
|
||||
|
||||
- name: Create a Storage Box with snapshot plan
|
||||
hetzner.hcloud.storage_box:
|
||||
name: my-storage-box
|
||||
storage_box_type: bx11
|
||||
location: fsn1
|
||||
password: my-secret
|
||||
snapshot_plan:
|
||||
max_snapshots: 10
|
||||
hour: 3
|
||||
minute: 30
|
||||
state: present
|
||||
|
||||
- name: Disable a Storage Box snapshot plan
|
||||
hetzner.hcloud.storage_box:
|
||||
name: my-storage-box
|
||||
snapshot_plan: null
|
||||
state: present
|
||||
|
||||
- name: Delete a Storage Box
|
||||
hetzner.hcloud.storage_box:
|
||||
name: my-storage-box
|
||||
|
|
@ -199,6 +247,36 @@ hcloud_storage_box:
|
|||
returned: always
|
||||
type: bool
|
||||
sample: false
|
||||
snapshot_plan:
|
||||
description: Snapshot plan of the Storage Box.
|
||||
returned: when enabled
|
||||
type: dict
|
||||
contains:
|
||||
max_snapshots:
|
||||
description: Maximum amount of Snapshots that will be created by this Snapshot Plan.
|
||||
returned: always
|
||||
type: int
|
||||
sample: 10
|
||||
hour:
|
||||
description: Hour when the Snapshot Plan is executed (UTC).
|
||||
returned: always
|
||||
type: int
|
||||
sample: 3
|
||||
minute:
|
||||
description: Minute when the Snapshot Plan is executed (UTC).
|
||||
returned: always
|
||||
type: int
|
||||
sample: 30
|
||||
day_of_week:
|
||||
description: Day of the week when the Snapshot Plan is executed. Null means every day.
|
||||
returned: always
|
||||
type: int
|
||||
sample: 1
|
||||
day_of_month:
|
||||
description: Day of the month when the Snapshot Plan is executed. Null means every day.
|
||||
returned: always
|
||||
type: int
|
||||
sample: 30
|
||||
username:
|
||||
description: User name of the Storage Box.
|
||||
returned: always
|
||||
|
|
@ -241,16 +319,15 @@ hcloud_storage_box:
|
|||
sample: 10485760
|
||||
"""
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
from ..module_utils import storage_box
|
||||
from ..module_utils.hcloud import AnsibleHCloud
|
||||
from ..module_utils.hcloud import AnsibleHCloud, AnsibleModule
|
||||
from ..module_utils.vendor.hcloud import HCloudException
|
||||
from ..module_utils.vendor.hcloud.locations import Location
|
||||
from ..module_utils.vendor.hcloud.storage_box_types import StorageBoxType
|
||||
from ..module_utils.vendor.hcloud.storage_boxes import (
|
||||
BoundStorageBox,
|
||||
StorageBoxAccessSettings,
|
||||
StorageBoxSnapshotPlan,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -294,9 +371,19 @@ class AnsibleStorageBox(AnsibleHCloud):
|
|||
|
||||
self.storage_box = resp.storage_box
|
||||
|
||||
if not self.module.check_mode:
|
||||
self._wait_actions()
|
||||
|
||||
if (value := self.module.params.get("delete_protection")) is not None:
|
||||
action = self.storage_box.change_protection(delete=value)
|
||||
self.actions.append(action)
|
||||
if not self.module.check_mode:
|
||||
action = self.storage_box.change_protection(delete=value)
|
||||
self.actions.append(action)
|
||||
|
||||
if self.module.param_is_defined("snapshot_plan"):
|
||||
if (value := self.module.params.get("snapshot_plan")) is not None:
|
||||
if not self.module.check_mode:
|
||||
action = self.storage_box.enable_snapshot_plan(StorageBoxSnapshotPlan.from_dict(value))
|
||||
self.actions.append(action)
|
||||
|
||||
if not self.module.check_mode:
|
||||
self._wait_actions()
|
||||
|
|
@ -327,6 +414,24 @@ class AnsibleStorageBox(AnsibleHCloud):
|
|||
self.actions.append(action)
|
||||
self._mark_as_changed()
|
||||
|
||||
if self.module.param_is_defined("snapshot_plan"):
|
||||
if (value := self.module.params.get("snapshot_plan")) is not None:
|
||||
snapshot_plan = StorageBoxSnapshotPlan.from_dict(value)
|
||||
if (
|
||||
self.storage_box.snapshot_plan is None
|
||||
or self.storage_box.snapshot_plan.to_payload() != snapshot_plan.to_payload()
|
||||
):
|
||||
if not self.module.check_mode:
|
||||
action = self.storage_box.enable_snapshot_plan(snapshot_plan)
|
||||
self.actions.append(action)
|
||||
self._mark_as_changed()
|
||||
else:
|
||||
if self.storage_box.snapshot_plan is not None:
|
||||
if not self.module.check_mode:
|
||||
action = self.storage_box.disable_snapshot_plan()
|
||||
self.actions.append(action)
|
||||
self._mark_as_changed()
|
||||
|
||||
# self.storage_box.reset_password
|
||||
|
||||
params = {}
|
||||
|
|
@ -397,6 +502,16 @@ class AnsibleStorageBox(AnsibleHCloud):
|
|||
zfs_enabled={"type": "bool", "default": False},
|
||||
),
|
||||
},
|
||||
snapshot_plan={
|
||||
"type": "dict",
|
||||
"options": dict(
|
||||
max_snapshots={"type": "int", "required": True},
|
||||
hour={"type": "int", "required": True},
|
||||
minute={"type": "int", "required": True},
|
||||
day_of_week={"type": "int"},
|
||||
day_of_month={"type": "int"},
|
||||
),
|
||||
},
|
||||
delete_protection={"type": "bool"},
|
||||
state={
|
||||
"choices": ["absent", "present"],
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@
|
|||
access_settings:
|
||||
ssh_enabled: true
|
||||
zfs_enabled: false
|
||||
snapshot_plan:
|
||||
max_snapshots: 10
|
||||
hour: 3
|
||||
minute: 30
|
||||
labels:
|
||||
key: value
|
||||
register: result
|
||||
|
|
@ -57,6 +61,9 @@
|
|||
- result.hcloud_storage_box.access_settings.ssh_enabled == true
|
||||
- result.hcloud_storage_box.access_settings.webdav_enabled == false
|
||||
- result.hcloud_storage_box.access_settings.zfs_enabled == false
|
||||
- result.hcloud_storage_box.snapshot_plan.max_snapshots == 10
|
||||
- result.hcloud_storage_box.snapshot_plan.hour == 3
|
||||
- result.hcloud_storage_box.snapshot_plan.minute == 30
|
||||
- result.hcloud_storage_box.status == "active"
|
||||
- result.hcloud_storage_box.server is not none
|
||||
- result.hcloud_storage_box.system is not none
|
||||
|
|
@ -76,6 +83,10 @@
|
|||
access_settings:
|
||||
ssh_enabled: true
|
||||
zfs_enabled: false
|
||||
snapshot_plan:
|
||||
max_snapshots: 10
|
||||
hour: 3
|
||||
minute: 30
|
||||
labels:
|
||||
key: value
|
||||
register: result
|
||||
|
|
@ -95,6 +106,11 @@
|
|||
- result is changed
|
||||
- result.hcloud_storage_box.name == hcloud_storage_box_name + "-changed"
|
||||
|
||||
# Ensure snapshot plan was not changed
|
||||
- result.hcloud_storage_box.snapshot_plan.max_snapshots == 10
|
||||
- result.hcloud_storage_box.snapshot_plan.hour == 3
|
||||
- result.hcloud_storage_box.snapshot_plan.minute == 30
|
||||
|
||||
- name: Test update
|
||||
hetzner.hcloud.storage_box:
|
||||
id: "{{ result.hcloud_storage_box.id }}"
|
||||
|
|
@ -106,6 +122,10 @@
|
|||
access_settings: # Update
|
||||
ssh_enabled: false
|
||||
reachable_externally: true
|
||||
snapshot_plan:
|
||||
max_snapshots: 10
|
||||
hour: 4 # Update
|
||||
minute: 30
|
||||
labels:
|
||||
key: changed # Update
|
||||
delete_protection: true # Update
|
||||
|
|
@ -125,6 +145,9 @@
|
|||
- result.hcloud_storage_box.access_settings.ssh_enabled == false
|
||||
- result.hcloud_storage_box.access_settings.webdav_enabled == false
|
||||
- result.hcloud_storage_box.access_settings.zfs_enabled == false
|
||||
- result.hcloud_storage_box.snapshot_plan.max_snapshots == 10
|
||||
- result.hcloud_storage_box.snapshot_plan.hour == 4
|
||||
- result.hcloud_storage_box.snapshot_plan.minute == 30
|
||||
|
||||
- name: Test update idempotency
|
||||
hetzner.hcloud.storage_box:
|
||||
|
|
@ -137,6 +160,10 @@
|
|||
access_settings: # Update
|
||||
ssh_enabled: false
|
||||
reachable_externally: true
|
||||
snapshot_plan:
|
||||
max_snapshots: 10
|
||||
hour: 4 # Update
|
||||
minute: 30
|
||||
labels:
|
||||
key: changed # Update
|
||||
delete_protection: true # Update
|
||||
|
|
@ -163,12 +190,23 @@
|
|||
name: "{{ hcloud_storage_box_name }}"
|
||||
delete_protection: false
|
||||
register: result
|
||||
- name: Verify update primary delete protection
|
||||
- name: Verify update delete protection
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.hcloud_storage_box.delete_protection == false
|
||||
|
||||
- name: Test update snapshot plan
|
||||
hetzner.hcloud.storage_box:
|
||||
name: "{{ hcloud_storage_box_name }}"
|
||||
snapshot_plan: null
|
||||
register: result
|
||||
- name: Verify update snapshot plan
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.hcloud_storage_box.snapshot_plan is none
|
||||
|
||||
- name: Test delete
|
||||
hetzner.hcloud.storage_box:
|
||||
name: "{{ hcloud_storage_box_name }}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue