hcloud: Add Delete Protection to hcloud_volume and hcloud_volume_info (#63665)
This commit is contained in:
parent
e9e4b02b92
commit
8eb46acbb1
3 changed files with 169 additions and 83 deletions
|
@ -18,12 +18,12 @@ DOCUMENTATION = """
|
|||
---
|
||||
module: hcloud_volume
|
||||
|
||||
short_description: Create and manage block volumes on the Hetzner Cloud.
|
||||
short_description: Create and manage block Volume on the Hetzner Cloud.
|
||||
|
||||
version_added: "2.8"
|
||||
|
||||
description:
|
||||
- Create, update and attach/detach block volumes on the Hetzner Cloud.
|
||||
- Create, update and attach/detach block Volume on the Hetzner Cloud.
|
||||
|
||||
author:
|
||||
- Christopher Schmitt (@cschmitt-hcloud)
|
||||
|
@ -64,13 +64,18 @@ options:
|
|||
- Server Name the Volume should be assigned to.
|
||||
- Required if no I(location) is given and Volume does not exists.
|
||||
type: str
|
||||
delete_protection:
|
||||
description:
|
||||
- Protect the Volume for deletion.
|
||||
type: bool
|
||||
version_added: "2.10"
|
||||
labels:
|
||||
description:
|
||||
- User-defined key-value pairs.
|
||||
type: dict
|
||||
state:
|
||||
description:
|
||||
- State of the volume.
|
||||
- State of the Volume.
|
||||
default: present
|
||||
choices: [absent, present]
|
||||
type: str
|
||||
|
@ -78,32 +83,32 @@ extends_documentation_fragment: hcloud
|
|||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Create a volume
|
||||
- name: Create a Volume
|
||||
hcloud_volume:
|
||||
name: my-volume
|
||||
location: fsn1
|
||||
size: 100
|
||||
state: present
|
||||
- name: Create a volume and format it with ext4
|
||||
- name: Create a Volume and format it with ext4
|
||||
hcloud_volume:
|
||||
name: my-volume
|
||||
location: fsn
|
||||
format: ext4
|
||||
size: 100
|
||||
state: present
|
||||
- name: Mount a existing volume and automount
|
||||
- name: Mount a existing Volume and automount
|
||||
hcloud_volume:
|
||||
name: my-volume
|
||||
server: my-server
|
||||
automount: yes
|
||||
state: present
|
||||
- name: Mount a existing volume and automount
|
||||
- name: Mount a existing Volume and automount
|
||||
hcloud_volume:
|
||||
name: my-volume
|
||||
server: my-server
|
||||
automount: yes
|
||||
state: present
|
||||
- name: Ensure the volume is absent (remove if needed)
|
||||
- name: Ensure the Volume is absent (remove if needed)
|
||||
hcloud_volume:
|
||||
name: my-volume
|
||||
state: absent
|
||||
|
@ -111,33 +116,33 @@ EXAMPLES = """
|
|||
|
||||
RETURN = """
|
||||
hcloud_volume:
|
||||
description: The block volume
|
||||
description: The block Volume
|
||||
returned: Always
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: ID of the volume
|
||||
description: ID of the Volume
|
||||
type: int
|
||||
returned: Always
|
||||
sample: 12345
|
||||
name:
|
||||
description: Name of the volume
|
||||
description: Name of the Volume
|
||||
type: str
|
||||
returned: Always
|
||||
sample: my-volume
|
||||
size:
|
||||
description: Size in GB of the volume
|
||||
description: Size in GB of the Volume
|
||||
type: int
|
||||
returned: Always
|
||||
sample: 1337
|
||||
linux_device:
|
||||
description: Path to the device that contains the volume.
|
||||
description: Path to the device that contains the Volume.
|
||||
returned: always
|
||||
type: str
|
||||
sample: /dev/disk/by-id/scsi-0HC_Volume_12345
|
||||
version_added: "2.10"
|
||||
location:
|
||||
description: Location name where the volume is located at
|
||||
description: Location name where the Volume is located at
|
||||
type: str
|
||||
returned: Always
|
||||
sample: "fsn1"
|
||||
|
@ -149,10 +154,16 @@ hcloud_volume:
|
|||
key: value
|
||||
mylabel: 123
|
||||
server:
|
||||
description: Server name where the volume is attached to
|
||||
description: Server name where the Volume is attached to
|
||||
type: str
|
||||
returned: Always
|
||||
sample: "my-server"
|
||||
delete_protection:
|
||||
description: True if Volume is protected for deletion
|
||||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
version_added: "2.10"
|
||||
"""
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
@ -185,6 +196,7 @@ class AnsibleHcloudVolume(Hcloud):
|
|||
"labels": self.hcloud_volume.labels,
|
||||
"server": to_native(server_name),
|
||||
"linux_device": to_native(self.hcloud_volume.linux_device),
|
||||
"delete_protection": self.hcloud_volume.protection["delete"],
|
||||
}
|
||||
|
||||
def _get_volume(self):
|
||||
|
@ -227,36 +239,45 @@ class AnsibleHcloudVolume(Hcloud):
|
|||
self._get_volume()
|
||||
|
||||
def _update_volume(self):
|
||||
size = self.module.params.get("size")
|
||||
if size:
|
||||
if self.hcloud_volume.size < size:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_volume.resize(size).wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
elif self.hcloud_volume.size > size:
|
||||
self.module.warn("Shrinking of volumes is not supported")
|
||||
try:
|
||||
size = self.module.params.get("size")
|
||||
if size:
|
||||
if self.hcloud_volume.size < size:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_volume.resize(size).wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
elif self.hcloud_volume.size > size:
|
||||
self.module.warn("Shrinking of volumes is not supported")
|
||||
|
||||
server_name = self.module.params.get("server")
|
||||
if server_name:
|
||||
server = self.client.servers.get_by_name(server_name)
|
||||
if self.hcloud_volume.server is None or self.hcloud_volume.server.name != server.name:
|
||||
server_name = self.module.params.get("server")
|
||||
if server_name:
|
||||
server = self.client.servers.get_by_name(server_name)
|
||||
if self.hcloud_volume.server is None or self.hcloud_volume.server.name != server.name:
|
||||
if not self.module.check_mode:
|
||||
automount = self.module.params.get("automount", False)
|
||||
self.hcloud_volume.attach(server, automount=automount).wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
else:
|
||||
if self.hcloud_volume.server is not None:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_volume.detach().wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
|
||||
labels = self.module.params.get("labels")
|
||||
if labels is not None and labels != self.hcloud_volume.labels:
|
||||
if not self.module.check_mode:
|
||||
automount = self.module.params.get("automount", False)
|
||||
self.hcloud_volume.attach(server, automount=automount).wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
else:
|
||||
if self.hcloud_volume.server is not None:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_volume.detach().wait_until_finished()
|
||||
self.hcloud_volume.update(labels=labels)
|
||||
self._mark_as_changed()
|
||||
|
||||
labels = self.module.params.get("labels")
|
||||
if labels is not None and labels != self.hcloud_volume.labels:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_volume.update(labels=labels)
|
||||
self._mark_as_changed()
|
||||
delete_protection = self.module.params.get("delete_protection")
|
||||
if delete_protection is not None and delete_protection != self.hcloud_volume.protection["delete"]:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_volume.change_protection(delete=delete_protection).wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
|
||||
self._get_volume()
|
||||
self._get_volume()
|
||||
except hcloud.APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
def present_volume(self):
|
||||
self._get_volume()
|
||||
|
@ -266,12 +287,15 @@ class AnsibleHcloudVolume(Hcloud):
|
|||
self._update_volume()
|
||||
|
||||
def delete_volume(self):
|
||||
self._get_volume()
|
||||
if self.hcloud_volume is not None:
|
||||
if not self.module.check_mode:
|
||||
self.client.volumes.delete(self.hcloud_volume)
|
||||
self._mark_as_changed()
|
||||
self.hcloud_volume = None
|
||||
try:
|
||||
self._get_volume()
|
||||
if self.hcloud_volume is not None:
|
||||
if not self.module.check_mode:
|
||||
self.client.volumes.delete(self.hcloud_volume)
|
||||
self._mark_as_changed()
|
||||
self.hcloud_volume = None
|
||||
except hcloud.APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
@staticmethod
|
||||
def define_module():
|
||||
|
@ -287,6 +311,7 @@ class AnsibleHcloudVolume(Hcloud):
|
|||
format={"type": "str",
|
||||
"choices": ['xfs', 'ext4'],
|
||||
},
|
||||
delete_protection={"type": "bool"},
|
||||
state={
|
||||
"choices": ["absent", "present"],
|
||||
"default": "present",
|
||||
|
|
|
@ -18,11 +18,11 @@ DOCUMENTATION = """
|
|||
---
|
||||
module: hcloud_volume_info
|
||||
|
||||
short_description: Gather infos about your Hetzner Cloud volumes.
|
||||
short_description: Gather infos about your Hetzner Cloud Volumes.
|
||||
|
||||
version_added: "2.8"
|
||||
description:
|
||||
- Gather infos about your Hetzner Cloud volumes.
|
||||
- Gather infos about your Hetzner Cloud Volumes.
|
||||
|
||||
author:
|
||||
- Lukas Kaemmerling (@LKaemmerling)
|
||||
|
@ -30,21 +30,21 @@ author:
|
|||
options:
|
||||
id:
|
||||
description:
|
||||
- The ID of the volume you want to get.
|
||||
- The ID of the Volume you want to get.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- The name of the volume you want to get.
|
||||
- The name of the Volume you want to get.
|
||||
type: str
|
||||
label_selector:
|
||||
description:
|
||||
- The label selector for the volume you want to get.
|
||||
- The label selector for the Volume you want to get.
|
||||
type: str
|
||||
extends_documentation_fragment: hcloud
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Gather hcloud volume infos
|
||||
- name: Gather hcloud Volume infos
|
||||
hcloud_volume_info:
|
||||
register: output
|
||||
- name: Print the gathered infos
|
||||
|
@ -54,41 +54,46 @@ EXAMPLES = """
|
|||
|
||||
RETURN = """
|
||||
hcloud_volume_info:
|
||||
description: The volume infos as list
|
||||
description: The Volume infos as list
|
||||
returned: always
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: Numeric identifier of the volume
|
||||
description: Numeric identifier of the Volume
|
||||
returned: always
|
||||
type: int
|
||||
sample: 1937415
|
||||
name:
|
||||
description: Name of the volume
|
||||
description: Name of the Volume
|
||||
returned: always
|
||||
type: str
|
||||
sample: my-volume
|
||||
size:
|
||||
description: Size of the volume
|
||||
description: Size of the Volume
|
||||
returned: always
|
||||
type: str
|
||||
sample: 10
|
||||
linux_device:
|
||||
description: Path to the device that contains the volume.
|
||||
description: Path to the device that contains the Volume.
|
||||
returned: always
|
||||
type: str
|
||||
sample: /dev/disk/by-id/scsi-0HC_Volume_12345
|
||||
version_added: "2.10"
|
||||
location:
|
||||
description: Name of the location where the volume resides in
|
||||
description: Name of the location where the Volume resides in
|
||||
returned: always
|
||||
type: str
|
||||
sample: fsn1
|
||||
server:
|
||||
description: Name of the server where the volume is attached to
|
||||
description: Name of the server where the Volume is attached to
|
||||
returned: always
|
||||
type: str
|
||||
sample: my-server
|
||||
delete_protection:
|
||||
description: True if the Volume is protected for deletion
|
||||
returned: always
|
||||
type: bool
|
||||
version_added: "2.10"
|
||||
labels:
|
||||
description: User-defined labels (key-value pairs)
|
||||
returned: always
|
||||
|
@ -126,6 +131,7 @@ class AnsibleHcloudVolumeInfo(Hcloud):
|
|||
"labels": volume.labels,
|
||||
"server": to_native(server_name),
|
||||
"linux_device": to_native(volume.linux_device),
|
||||
"delete_protection": volume.protection["delete"],
|
||||
})
|
||||
|
||||
return tmp
|
||||
|
|
|
@ -26,25 +26,25 @@
|
|||
- result is failed
|
||||
- 'result.msg == "missing required arguments: size"'
|
||||
|
||||
- name: test create volume with check mode
|
||||
- name: test create Volume with check mode
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
size: 10
|
||||
location: "fsn1"
|
||||
register: result
|
||||
check_mode: yes
|
||||
- name: verify create volume with check mode result
|
||||
- name: verify create Volume with check mode result
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test create volume
|
||||
- name: test create Volume
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
size: 10
|
||||
location: "fsn1"
|
||||
register: volume
|
||||
- name: verify test create volume
|
||||
- name: verify test create Volume
|
||||
assert:
|
||||
that:
|
||||
- volume is changed
|
||||
|
@ -54,30 +54,30 @@
|
|||
- volume.hcloud_volume.server != "{{hcloud_server_name}}"
|
||||
- volume.hcloud_volume.linux_device is defined
|
||||
|
||||
- name: test create volume idempotence
|
||||
- name: test create Volume idempotence
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
size: 10
|
||||
location: "fsn1"
|
||||
register: volume
|
||||
- name: verify test create volume
|
||||
- name: verify test create Volume
|
||||
assert:
|
||||
that:
|
||||
- volume is not changed
|
||||
|
||||
- name: test attach volume with checkmode
|
||||
- name: test attach Volume with checkmode
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
server: "{{hcloud_server_name}}"
|
||||
check_mode: yes
|
||||
register: volume
|
||||
- name: verify test attach volume with checkmode
|
||||
- name: verify test attach Volume with checkmode
|
||||
assert:
|
||||
that:
|
||||
- volume is changed
|
||||
- volume.hcloud_volume.server != "{{hcloud_server_name}}"
|
||||
|
||||
- name: test attach volume
|
||||
- name: test attach Volume
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
server: "{{hcloud_server_name}}"
|
||||
|
@ -88,29 +88,29 @@
|
|||
- volume is changed
|
||||
- volume.hcloud_volume.server == "{{hcloud_server_name}}"
|
||||
|
||||
- name: test attach volume idempotence
|
||||
- name: test attach Volume idempotence
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
server: "{{hcloud_server_name}}"
|
||||
register: volume
|
||||
- name: verify attach volume idempotence
|
||||
- name: verify attach Volume idempotence
|
||||
assert:
|
||||
that:
|
||||
- volume is not changed
|
||||
- volume.hcloud_volume.server == "{{hcloud_server_name}}"
|
||||
|
||||
- name: test detach volume with checkmode
|
||||
- name: test detach Volume with checkmode
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
check_mode: yes
|
||||
register: volume
|
||||
- name: verify detach volume with checkmode
|
||||
- name: verify detach Volume with checkmode
|
||||
assert:
|
||||
that:
|
||||
- volume is changed
|
||||
- volume.hcloud_volume.server == "{{hcloud_server_name}}"
|
||||
|
||||
- name: test detach volume
|
||||
- name: test detach Volume
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
register: volume
|
||||
|
@ -121,57 +121,112 @@
|
|||
- volume.hcloud_volume.location == "fsn1"
|
||||
- volume.hcloud_volume.server != "{{hcloud_server_name}}"
|
||||
|
||||
- name: test update volume label
|
||||
- name: test update Volume label
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
labels:
|
||||
key: value
|
||||
register: volume
|
||||
- name: verify test update volume lable
|
||||
- name: verify test update Volume label
|
||||
assert:
|
||||
that:
|
||||
- volume is changed
|
||||
- volume.hcloud_volume.labels.key == "value"
|
||||
|
||||
- name: test update volume label with the same label
|
||||
- name: test update Volume label with the same label
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
labels:
|
||||
key: value
|
||||
register: volume
|
||||
- name: verify test update volume lable with the same label
|
||||
- name: verify test update Volume lable with the same label
|
||||
assert:
|
||||
that:
|
||||
- volume is not changed
|
||||
|
||||
- name: test increase volume size
|
||||
- name: test increase Volume size
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
size: 11
|
||||
register: volume
|
||||
- name: verify test increase volume size
|
||||
- name: verify test increase Volume size
|
||||
assert:
|
||||
that:
|
||||
- volume is changed
|
||||
- volume.hcloud_volume.size == 11
|
||||
|
||||
- name: test decreace volume size
|
||||
- name: test decreace Volume size
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
size: 10
|
||||
register: volume
|
||||
- name: verify test decreace volume size
|
||||
- name: verify test decreace Volume size
|
||||
assert:
|
||||
that:
|
||||
- volume is not changed
|
||||
- volume.hcloud_volume.size == 11
|
||||
|
||||
- name: test delete volume
|
||||
- name: test update Volume delete protection
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
delete_protection: true
|
||||
register: volume
|
||||
- name: verify test update Volume delete protection
|
||||
assert:
|
||||
that:
|
||||
- volume is changed
|
||||
- volume.hcloud_volume.delete_protection is sameas true
|
||||
|
||||
- name: test update Volume delete protection idempotency
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
delete_protection: true
|
||||
register: volume
|
||||
- name: verify test update Volume delete protection idempotency
|
||||
assert:
|
||||
that:
|
||||
- volume is not changed
|
||||
- volume.hcloud_volume.delete_protection is sameas true
|
||||
|
||||
- name: test Volume without delete protection set to be idempotent
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
register: volume
|
||||
- name: verify test Volume without delete protection set to be idempotent
|
||||
assert:
|
||||
that:
|
||||
- volume is not changed
|
||||
- volume.hcloud_volume.delete_protection is sameas true
|
||||
|
||||
- name: test delete Volume fails if it is protected
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
register: result
|
||||
- name: verify delete Volume fails if it is protected
|
||||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- 'result.msg == "volume deletion is protected"'
|
||||
|
||||
- name: test update Volume delete protection
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
delete_protection: false
|
||||
register: volume
|
||||
- name: verify test update Volume delete protection
|
||||
assert:
|
||||
that:
|
||||
- volume is changed
|
||||
- volume.hcloud_volume.delete_protection is sameas false
|
||||
|
||||
- name: test delete Volume
|
||||
hcloud_volume:
|
||||
name: "{{hcloud_volume_name}}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify delete volume
|
||||
- name: verify delete Volume
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
||||
|
|
Loading…
Reference in a new issue