Add support for Primary IPs (#141)

Signed-off-by: Lukas Kämmerling <lukas.kaemmerling@hetzner-cloud.de>
This commit is contained in:
Lukas Kämmerling 2022-06-29 09:58:01 +02:00 committed by GitHub
parent dd3bc0bf0a
commit 0965f79093
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 1601 additions and 805 deletions

View file

@ -203,9 +203,12 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
self.inventory.set_variable(server.name, "type", to_native(server.server_type.name))
# Network
self.inventory.set_variable(server.name, "ipv4", to_native(server.public_net.ipv4.ip))
self.inventory.set_variable(server.name, "ipv6_network", to_native(server.public_net.ipv6.network))
self.inventory.set_variable(server.name, "ipv6_network_mask", to_native(server.public_net.ipv6.network_mask))
if server.public_net.ipv4:
self.inventory.set_variable(server.name, "ipv4", to_native(server.public_net.ipv4.ip))
if server.public_net.ipv6:
self.inventory.set_variable(server.name, "ipv6_network", to_native(server.public_net.ipv6.network))
self.inventory.set_variable(server.name, "ipv6_network_mask", to_native(server.public_net.ipv6.network_mask))
if self.get_option("network"):
for server_private_network in server.private_net:

View file

@ -0,0 +1,276 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2022, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
---
module: hcloud_primary_ip
short_description: Create and manage cloud Primary IPs on the Hetzner Cloud.
description:
- Create, update and manage cloud Primary IPs on the Hetzner Cloud.
author:
- Lukas Kaemmerling (@lkaemmerling)
version_added: 1.8.0
options:
id:
description:
- The ID of the Hetzner Cloud Primary IPs to manage.
- Only required if no Primary IP I(name) is given.
type: int
name:
description:
- The Name of the Hetzner Cloud Primary IPs to manage.
- Only required if no Primary IP I(id) is given or a Primary IP does not exist.
type: str
datacenter:
description:
- Home Location of the Hetzner Cloud Primary IP.
- Required if no I(server) is given and Primary IP does not exist.
type: str
type:
description:
- Type of the Primary IP.
- Required if Primary IP does not exist
choices: [ ipv4, ipv6 ]
type: str
auto_delete:
description:
- Delete this Primary IP when the resource it is assigned to is deleted
type: bool
default: no
delete_protection:
description:
- Protect the Primary IP for deletion.
type: bool
labels:
description:
- User-defined labels (key-value pairs).
type: dict
state:
description:
- State of the Primary IP.
default: present
choices: [ absent, present ]
type: str
requirements:
- hcloud-python >= 1.9.0
extends_documentation_fragment:
- hetzner.hcloud.hcloud
'''
EXAMPLES = """
- name: Create a basic IPv4 Primary IP
hcloud_primary_ip:
name: my-primary-ip
datacenter: fsn1-dc14
type: ipv4
state: present
- name: Create a basic IPv6 Primary IP
hcloud_primary_ip:
name: my-primary-ip
datacenter: fsn1-dc14
type: ipv6
state: present
- name: Primary IP should be absent
hcloud_primary_ip:
name: my-primary-ip
state: absent
"""
RETURN = """
hcloud_primary_ip:
description: The Primary IP instance
returned: Always
type: complex
contains:
id:
description: ID of the Primary IP
type: int
returned: Always
sample: 12345
name:
description: Name of the Primary IP
type: str
returned: Always
sample: my-primary-ip
ip:
description: IP Address of the Primary IP
type: str
returned: Always
sample: 116.203.104.109
type:
description: Type of the Primary IP
type: str
returned: Always
sample: ipv4
datacenter:
description: Name of the datacenter of the Primary IP
type: str
returned: Always
sample: fsn1-dc14
delete_protection:
description: True if Primary IP is protected for deletion
type: bool
returned: always
sample: false
labels:
description: User-defined labels (key-value pairs)
type: dict
returned: Always
sample:
key: value
mylabel: 123
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud
try:
from hcloud import APIException
except ImportError:
APIException = None
class AnsibleHcloudPrimaryIP(Hcloud):
def __init__(self, module):
Hcloud.__init__(self, module, "hcloud_primary_ip")
self.hcloud_primary_ip = None
def _prepare_result(self):
return {
"id": to_native(self.hcloud_primary_ip.id),
"name": to_native(self.hcloud_primary_ip.name),
"ip": to_native(self.hcloud_primary_ip.ip),
"type": to_native(self.hcloud_primary_ip.type),
"datacenter": to_native(self.hcloud_primary_ip.datacenter.name),
"labels": self.hcloud_primary_ip.labels,
"delete_protection": self.hcloud_primary_ip.protection["delete"],
}
def _get_primary_ip(self):
try:
if self.module.params.get("id") is not None:
self.hcloud_primary_ip = self.client.primary_ips.get_by_id(
self.module.params.get("id")
)
else:
self.hcloud_primary_ip = self.client.primary_ips.get_by_name(
self.module.params.get("name")
)
except Exception as e:
self.module.fail_json(msg=e.message)
def _create_primary_ip(self):
self.module.fail_on_missing_params(
required_params=["type", "datacenter"]
)
try:
params = {
"type": self.module.params.get("type"),
"name": self.module.params.get("name"),
"datacenter": self.client.datacenters.get_by_name(
self.module.params.get("datacenter")
)
}
if self.module.params.get("labels") is not None:
params["labels"] = self.module.params.get("labels")
if not self.module.check_mode:
resp = self.client.primary_ips.create(**params)
self.hcloud_primary_ip = resp.primary_ip
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None:
self.hcloud_primary_ip.change_protection(delete=delete_protection).wait_until_finished()
except Exception as e:
self.module.fail_json(msg=e)
self._mark_as_changed()
self._get_primary_ip()
def _update_primary_ip(self):
try:
labels = self.module.params.get("labels")
if labels is not None and labels != self.hcloud_primary_ip.labels:
if not self.module.check_mode:
self.hcloud_primary_ip.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_primary_ip.protection["delete"]:
if not self.module.check_mode:
self.hcloud_primary_ip.change_protection(delete=delete_protection).wait_until_finished()
self._mark_as_changed()
self._get_primary_ip()
except Exception as e:
self.module.fail_json(msg=e.message)
def present_primary_ip(self):
self._get_primary_ip()
if self.hcloud_primary_ip is None:
self._create_primary_ip()
else:
self._update_primary_ip()
def delete_primary_ip(self):
try:
self._get_primary_ip()
if self.hcloud_primary_ip is not None:
if not self.module.check_mode:
self.client.primary_ips.delete(self.hcloud_primary_ip)
self._mark_as_changed()
self.hcloud_primary_ip = None
except Exception as e:
self.module.fail_json(msg=e.message)
@staticmethod
def define_module():
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
datacenter={"type": "str"},
auto_delete={"type": "bool", "default": False},
type={"choices": ["ipv4", "ipv6"]},
labels={"type": "dict"},
delete_protection={"type": "bool"},
state={
"choices": ["absent", "present"],
"default": "present",
},
**Hcloud.base_module_arguments()
),
required_one_of=[['id', 'name']],
supports_check_mode=True,
)
def main():
module = AnsibleHcloudPrimaryIP.define_module()
hcloud = AnsibleHcloudPrimaryIP(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_primary_ip()
elif state == "present":
hcloud.present_primary_ip()
module.exit_json(**hcloud.get_result())
if __name__ == "__main__":
main()

View file

@ -30,6 +30,10 @@ options:
description:
- The name of the Hetzner Cloud Floating IP you want to add the reverse DNS entry to.
type: str
primary_ip:
description:
- The name of the Hetzner Cloud Primary IP you want to add the reverse DNS entry to.
type: str
load_balancer:
description:
- The name of the Hetzner Cloud Load Balancer you want to add the reverse DNS entry to.
@ -74,6 +78,13 @@ EXAMPLES = """
dns_ptr: example.com
state: present
- name: Create a reverse DNS entry for a Primary IP
hcloud_rdns:
primary_ip: my-primary-ip
ip_address: 123.123.123.123
dns_ptr: example.com
state: present
- name: Create a reverse DNS entry for a Load Balancer
hcloud_rdns:
load_balancer: my-load-balancer
@ -105,6 +116,11 @@ hcloud_rdns:
type: str
returned: always
sample: my-floating-ip
primary_ip:
description: Name of the Primary IP
type: str
returned: always
sample: my-primary-ip
load_balancer:
description: Name of the Load Balancer
type: str
@ -154,6 +170,8 @@ class AnsibleHcloudReverseDNS(Hcloud):
result["floating_ip"] = to_native(self.hcloud_resource.name)
elif self.module.params.get("load_balancer"):
result["load_balancer"] = to_native(self.hcloud_resource.name)
elif self.module.params.get("primary_ip"):
result["primary_ip"] = to_native(self.hcloud_resource.name)
return result
def _get_resource(self):
@ -170,6 +188,12 @@ class AnsibleHcloudReverseDNS(Hcloud):
)
if self.hcloud_resource is None:
self.module.fail_json(msg="The selected Floating IP does not exist")
elif self.module.params.get("primary_ip"):
self.hcloud_resource = self.client.primary_ips.get_by_name(
self.module.params.get("primary_ip")
)
if self.hcloud_resource is None:
self.module.fail_json(msg="The selected Floating IP does not exist")
elif self.module.params.get("load_balancer"):
self.hcloud_resource = self.client.load_balancers.get_by_name(
self.module.params.get("load_balancer")
@ -198,6 +222,14 @@ class AnsibleHcloudReverseDNS(Hcloud):
}
else:
self.module.fail_json(msg="The selected Floating IP does not have this IP address")
elif self.module.params.get("primary_ip"):
if self.hcloud_resource.ip == ip_address:
self.hcloud_rdns = {
"ip_address": self.hcloud_resource.ip,
"dns_ptr": self.hcloud_resource.dns_ptr[0]["dns_ptr"],
}
else:
self.module.fail_json(msg="The selected Primary IP does not have this IP address")
elif self.module.params.get("load_balancer"):
if self.hcloud_resource.public_net.ipv4.ip == ip_address:
self.hcloud_rdns = {
@ -222,6 +254,13 @@ class AnsibleHcloudReverseDNS(Hcloud):
"ip_address": ipv6_address_dns_ptr["ip"],
"dns_ptr": ipv6_address_dns_ptr["dns_ptr"],
}
elif self.module.params.get("primary_ip"):
for ipv6_address_dns_ptr in self.hcloud_resource.dns_ptr:
if ipv6_address_dns_ptr["ip"] == ip_address:
self.hcloud_rdns = {
"ip_address": ipv6_address_dns_ptr["ip"],
"dns_ptr": ipv6_address_dns_ptr["dns_ptr"],
}
elif self.module.params.get("load_balancer"):
for ipv6_address_dns_ptr in self.hcloud_resource.public_net.ipv6.dns_ptr:
if ipv6_address_dns_ptr["ip"] == ip_address:
@ -294,6 +333,7 @@ class AnsibleHcloudReverseDNS(Hcloud):
server={"type": "str"},
floating_ip={"type": "str"},
load_balancer={"type": "str"},
primary_ip={"type": "str"},
ip_address={"type": "str", "required": True},
dns_ptr={"type": "str"},
state={
@ -302,8 +342,8 @@ class AnsibleHcloudReverseDNS(Hcloud):
},
**Hcloud.base_module_arguments()
),
required_one_of=[['server', 'floating_ip', 'load_balancer']],
mutually_exclusive=[["server", "floating_ip", 'load_balancer']],
required_one_of=[['server', 'floating_ip', 'load_balancer', 'primary_ip']],
mutually_exclusive=[["server", "floating_ip", 'load_balancer', 'primary_ip']],
supports_check_mode=True,
)

View file

@ -79,6 +79,24 @@ options:
- If you want to downgrade the server later, this value should be False.
type: bool
default: no
enable_ipv4:
description:
- Enables the public ipv4 address
type: bool
default: yes
enable_ipv6:
description:
- Enables the public ipv6 address
type: bool
default: yes
ipv4:
description:
- ID of the ipv4 Primary IP to use. If omitted and enable_ipv4 is true, a new ipv4 Primary IP will automatically be created
type: str
ipv6:
description:
- ID of the ipv6 Primary IP to use. If omitted and enable_ipv6 is true, a new ipv6 Primary IP will automatically be created.
type: str
force_upgrade:
description:
- Deprecated
@ -294,16 +312,19 @@ from datetime import timedelta
try:
from hcloud.volumes.domain import Volume
from hcloud.ssh_keys.domain import SSHKey
from hcloud.servers.domain import Server
from hcloud.servers.domain import Server, ServerCreatePublicNetwork
from hcloud.firewalls.domain import Firewall, FirewallResource
from hcloud.primary_ips.domain import PrimaryIP
from hcloud import APIException
except ImportError:
APIException = None
Volume = None
SSHKey = None
Server = None
ServerCreatePublicNetwork = None
Firewall = None
FirewallResource = None
PrimaryIP = None
class AnsibleHcloudServer(Hcloud):
@ -313,12 +334,16 @@ class AnsibleHcloudServer(Hcloud):
def _prepare_result(self):
image = None if self.hcloud_server.image is None else to_native(self.hcloud_server.image.name)
placement_group = None if self.hcloud_server.placement_group is None else to_native(self.hcloud_server.placement_group.name)
placement_group = None if self.hcloud_server.placement_group is None else to_native(
self.hcloud_server.placement_group.name)
ipv4_address = None if self.hcloud_server.public_net.ipv4 is None else to_native(
self.hcloud_server.public_net.ipv4.ip)
ipv6 = None if self.hcloud_server.public_net.ipv6 is None else to_native(self.hcloud_server.public_net.ipv6.ip)
return {
"id": to_native(self.hcloud_server.id),
"name": to_native(self.hcloud_server.name),
"ipv4_address": to_native(self.hcloud_server.public_net.ipv4.ip),
"ipv6": to_native(self.hcloud_server.public_net.ipv6.ip),
"ipv4_address": ipv4_address,
"ipv6": ipv6,
"image": image,
"server_type": to_native(self.hcloud_server.server_type.name),
"datacenter": to_native(self.hcloud_server.datacenter.name),
@ -357,8 +382,24 @@ class AnsibleHcloudServer(Hcloud):
"labels": self.module.params.get("labels"),
"image": self._get_image(),
"placement_group": self._get_placement_group(),
"public_net": ServerCreatePublicNetwork(
enable_ipv4=self.module.params.get("enable_ipv4"),
enable_ipv6=self.module.params.get("enable_ipv6")
)
}
if self.module.params.get("ipv4") is not None:
p = self.client.primary_ips.get_by_name(self.module.params.get("ipv4"))
if not p:
p = self.client.primary_ips.get_by_id(self.module.params.get("ipv4"))
params["public_net"].ipv4 = p
if self.module.params.get("ipv6") is not None:
p = self.client.primary_ips.get_by_name(self.module.params.get("ipv6"))
if not p:
p = self.client.primary_ips.get_by_id(self.module.params.get("ipv6"))
params["public_net"].ipv6 = p
if self.module.params.get("ssh_keys") is not None:
params["ssh_keys"] = [
SSHKey(name=ssh_key_name)
@ -436,8 +477,8 @@ class AnsibleHcloudServer(Hcloud):
available_until = image.deprecated + timedelta(days=90)
if self.module.params.get("allow_deprecated_image"):
self.module.warn(
"You try to use a deprecated image. The image %s will continue to be available until %s.") \
% (image.name, available_until.strftime('%Y-%m-%d'))
"You try to use a deprecated image. The image %s will continue to be available until %s.") % (
image.name, available_until.strftime('%Y-%m-%d'))
else:
self.module.fail_json(
msg=("You try to use a deprecated image. The image %s will continue to be available until %s." +
@ -468,12 +509,30 @@ class AnsibleHcloudServer(Hcloud):
try:
placement_group = self.client.placement_groups.get_by_id(self.module.params.get("placement_group"))
except Exception:
self.module.fail_json(msg="placement_group %s was not found" % self.module.params.get("placement_group"))
self.module.fail_json(
msg="placement_group %s was not found" % self.module.params.get("placement_group"))
return placement_group
def _get_primary_ip(self, field):
if self.module.params.get(field) is None:
return None
primary_ip = self.client.primary_ips.get_by_name(
self.module.params.get(field)
)
if primary_ip is None:
try:
primary_ip = self.client.primary_ips.get_by_id(self.module.params.get(field))
except Exception as e:
self.module.fail_json(
msg="primary_ip %s was not found" % self.module.params.get(field))
return primary_ip
def _update_server(self):
self.module.warn("force_upgrade is deprecated, use force instead")
if "force_upgrade" in self.module.params:
self.module.warn("force_upgrade is deprecated, use force instead")
try:
previous_server_status = self.hcloud_server.status
@ -542,14 +601,67 @@ class AnsibleHcloudServer(Hcloud):
else:
placement_group = self._get_placement_group()
if (
placement_group is not None and
(self.hcloud_server.placement_group is None or self.hcloud_server.placement_group.id != placement_group.id)
placement_group is not None and
(
self.hcloud_server.placement_group is None or
self.hcloud_server.placement_group.id != placement_group.id
)
):
self.stop_server_if_forced()
if not self.module.check_mode:
self.hcloud_server.add_to_placement_group(placement_group)
self._mark_as_changed()
if "ipv4" in self.module.params:
if (
self.module.params["ipv4"] is None and
self.hcloud_server.public_net.primary_ipv4 is not None and
not self.module.params.get("enable_ipv4")
):
self.stop_server_if_forced()
if not self.module.check_mode:
self.hcloud_server.public_net.primary_ipv4.unassign().wait_until_finished()
self._mark_as_changed()
else:
primary_ip = self._get_primary_ip("ipv4")
if (
primary_ip is not None and
(
self.hcloud_server.public_net.primary_ipv4 is None or
self.hcloud_server.public_net.primary_ipv4.id != primary_ip.id
)
):
self.stop_server_if_forced()
if not self.module.check_mode:
if self.hcloud_server.public_net.primary_ipv4:
self.hcloud_server.public_net.primary_ipv4.unassign().wait_until_finished()
primary_ip.assign(self.hcloud_server.id, "server").wait_until_finished()
self._mark_as_changed()
if "ipv6" in self.module.params:
if (
(self.module.params["ipv6"] is None or self.module.params["ipv6"] == "") and
self.hcloud_server.public_net.primary_ipv6 is not None and
not self.module.params.get("enable_ipv6")
):
self.stop_server_if_forced()
if not self.module.check_mode:
self.hcloud_server.public_net.primary_ipv6.unassign().wait_until_finished()
self._mark_as_changed()
else:
primary_ip = self._get_primary_ip("ipv6")
if (
primary_ip is not None and
(
self.hcloud_server.public_net.primary_ipv6 is None or
self.hcloud_server.public_net.primary_ipv6.id != primary_ip.id
)
):
self.stop_server_if_forced()
if not self.module.check_mode:
if self.hcloud_server.public_net.primary_ipv6 is not None:
self.hcloud_server.public_net.primary_ipv6.unassign().wait_until_finished()
primary_ip.assign(self.hcloud_server.id, "server").wait_until_finished()
self._mark_as_changed()
server_type = self.module.params.get("server_type")
if server_type is not None and self.hcloud_server.server_type.name != server_type:
self.stop_server_if_forced()
@ -558,7 +670,7 @@ class AnsibleHcloudServer(Hcloud):
if self.module.params.get("upgrade_disk"):
timeout = (
1000
) # When we upgrade the disk too the resize progress takes some more time.
) # When we upgrade the disk to the resize progress takes some more time.
if not self.module.check_mode:
self.hcloud_server.change_type(
server_type=self._get_server_type(),
@ -567,11 +679,14 @@ class AnsibleHcloudServer(Hcloud):
self._mark_as_changed()
if (
not self.module.check_mode and
(
self.module.params.get("state") == "present" and previous_server_status == Server.STATUS_RUNNING or
self.module.params.get("state") == "started"
)
not self.module.check_mode and
(
(
self.module.params.get("state") == "present" and
previous_server_status == Server.STATUS_RUNNING
) or
self.module.params.get("state") == "started"
)
):
self.start_server()
@ -586,7 +701,7 @@ class AnsibleHcloudServer(Hcloud):
self._mark_as_changed()
self._get_server()
except Exception as e:
self.module.fail_json(msg=e.message)
self.module.fail_json(msg=e)
def _set_rescue_mode(self, rescue_mode):
if self.module.params.get("ssh_keys"):
@ -626,9 +741,9 @@ class AnsibleHcloudServer(Hcloud):
previous_server_status = self.hcloud_server.status
if previous_server_status == Server.STATUS_RUNNING and not self.module.check_mode:
if (
self.module.params.get("force_upgrade") or
self.module.params.get("force") or
self.module.params.get("state") == "stopped"
self.module.params.get("force_upgrade") or
self.module.params.get("force") or
self.module.params.get("state") == "stopped"
):
self.stop_server() # Only stopped server can be upgraded
return previous_server_status
@ -689,6 +804,10 @@ class AnsibleHcloudServer(Hcloud):
labels={"type": "dict"},
backups={"type": "bool"},
upgrade_disk={"type": "bool", "default": False},
enable_ipv4={"type": "bool", "default": True},
enable_ipv6={"type": "bool", "default": True},
ipv4={"type": "str"},
ipv6={"type": "str"},
force={"type": "bool", "default": False},
force_upgrade={"type": "bool", "default": False},
allow_deprecated_image={"type": "bool", "default": False},

View file

@ -0,0 +1,2 @@
cloud/hcloud
shippable/hcloud/group2

View file

@ -0,0 +1,6 @@
# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
hcloud_prefix: "tests"
hcloud_primary_ip_name: "{{hcloud_prefix}}-i"
hcloud_server_name: "{{hcloud_prefix}}-fip-t"

View file

@ -0,0 +1,3 @@
collections:
- community.general.ipfilter
- hetzner.cloud

View file

@ -0,0 +1,243 @@
# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: test create Primary IP with check mode
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
register: primaryIP
check_mode: yes
- name: verify test create Primary IP with check mode
assert:
that:
- primaryIP is changed
- name: test create Primary IP
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
register: primaryIP
- name: verify test create Primary IP
assert:
that:
- primaryIP is changed
- primaryIP.hcloud_primary_ip.name ==hcloud_primary_ip_name
- primaryIP.hcloud_primary_ip.datacenter == "fsn1-dc14"
- name: test create Primary IP idempotency
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
register: primaryIP
- name: verify test create Primary IP idempotency
assert:
that:
- primaryIP is not changed
- name: test update Primary IP
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
labels:
key: value
register: primaryIP
- name: verify test update Primary IP
assert:
that:
- primaryIP is changed
- name: test update Primary IP idempotency
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
labels:
key: value
register: primaryIP
- name: verify test update Primary IP idempotency
assert:
that:
- primaryIP is not changed
- name: test update Primary IP with same labels
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
labels:
key: value
register: primaryIP
- name: verify test update Primary IP with same labels
assert:
that:
- primaryIP is not changed
- name: test update Primary IP with other labels
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
labels:
key: value
other: label
register: primaryIP
- name: verify test update Primary IP with other labels
assert:
that:
- primaryIP is changed
- name: test update Primary IP with other labels in different order
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
labels:
other: label
key: value
register: primaryIP
- name: verify test update Primary IP with other labels in different order
assert:
that:
- primaryIP is not changed
- name: test update Primary IP delete protection
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
delete_protection: true
register: primaryIP
- name: verify update Primary IP delete protection
assert:
that:
- primaryIP is changed
- primaryIP.hcloud_primary_ip.delete_protection is sameas true
- name: test update Primary IP delete protection idempotency
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
delete_protection: true
register: primaryIP
- name: verify update Primary IP delete protection idempotency
assert:
that:
- primaryIP is not changed
- primaryIP.hcloud_primary_ip.delete_protection is sameas true
- name: test Primary IP without delete protection set to be idempotent
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
register: primaryIP
- name: verify Primary IP without delete protection set to be idempotent
assert:
that:
- primaryIP is not changed
- primaryIP.hcloud_primary_ip.delete_protection is sameas true
- name: test delete Primary IP fails if it is protected
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
ignore_errors: yes
- name: verify test delete primary ip
assert:
that:
- result is failed
- 'result.msg == "Primary IP deletion is protected"'
- name: test update Primary IP delete protection
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
delete_protection: false
register: primaryIP
- name: verify update Primary IP delete protection
assert:
that:
- primaryIP is changed
- primaryIP.hcloud_primary_ip.delete_protection is sameas false
- name: test delete primary ip
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
- name: verify test delete primary ip
assert:
that:
- result is changed
- name: test create ipv6 primary ip
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv6
datacenter: "fsn1-dc14"
state: "present"
register: result
- name: verify test create ipv6 primary ip
assert:
that:
- result is changed
- name: test delete ipv6 primary ip
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
- name: verify test delete ipv6 primary ip
assert:
that:
- result is changed
- name: test create Primary IP with delete protection
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: fsn1-dc14
delete_protection: true
register: primaryIP
- name: verify create Primary IP with delete protection
assert:
that:
- primaryIP is changed
- primaryIP.hcloud_primary_ip.delete_protection is sameas true
- name: test delete Primary IP fails if it is protected
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
ignore_errors: yes
- name: verify test delete primary ip
assert:
that:
- result is failed
- 'result.msg == "Primary IP deletion is protected"'
- name: test update Primary IP delete protection
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
delete_protection: false
register: primaryIP
- name: verify update Primary IP delete protection
assert:
that:
- primaryIP is changed
- primaryIP.hcloud_primary_ip.delete_protection is sameas false
- name: test delete primary ip
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
- name: verify test delete primary ip
assert:
that:
- result is changed

View file

@ -4,4 +4,5 @@
hcloud_prefix: "tests"
hcloud_server_name: "{{hcloud_prefix}}"
hcloud_floating_ip_name: "{{hcloud_prefix}}"
hcloud_primary_ip_name: "{{hcloud_prefix}}"
hcloud_load_balancer_name: "{{hcloud_prefix}}"

View file

@ -5,7 +5,7 @@
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cx11
image: "ubuntu-18.04"
image: "ubuntu-22.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
@ -15,13 +15,13 @@
that:
- setup is success
- name: test create Floating IP
- name: setup Floating IP
hcloud_floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
home_location: "fsn1"
register: floatingIP
- name: verify test create Floating IP
- name: verify setup Floating IP
assert:
that:
- floatingIP is success
@ -38,6 +38,17 @@
that:
- load_balancer is success
- name: setup Primary IP
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
register: primaryIP
- name: verify setup Primary IP
assert:
that:
- primaryIP is success
- name: test missing required parameter
hcloud_rdns:
state: present
@ -142,6 +153,21 @@
- rdns.hcloud_rdns.ip_address == "{{ floatingIP.hcloud_floating_ip.ip}}"
- rdns.hcloud_rdns.dns_ptr == "example.com"
- name: test create rdns with primary IP
hcloud_rdns:
primary_ip: "{{ hcloud_primary_ip_name }}"
ip_address: "{{ primaryIP.hcloud_primary_ip.ip}}"
dns_ptr: "example.com"
state: present
register: rdns
- name: verify create rdns
assert:
that:
- rdns is changed
- rdns.hcloud_rdns.primary_ip == "{{ hcloud_primary_ip_name }}"
- rdns.hcloud_rdns.ip_address == "{{ primaryIP.hcloud_primary_ip.ip}}"
- rdns.hcloud_rdns.dns_ptr == "example.com"
- name: test create rdns with load balancer
hcloud_rdns:
load_balancer: "{{ hcloud_load_balancer_name }}"
@ -177,6 +203,16 @@
that:
- result is success
- name: cleanup
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- result is success
- name: cleanup
hcloud_load_balancer:
name: "{{ hcloud_load_balancer_name }}"

View file

@ -4,3 +4,4 @@
hcloud_prefix: "tests"
hcloud_server_name: "{{hcloud_prefix}}-i"
hcloud_firewall_name: "{{hcloud_prefix}}-i"
hcloud_primary_ip_name: "{{hcloud_prefix}}-i"

View file

@ -0,0 +1,600 @@
- name: test create server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cx11
image: ubuntu-20.04
state: present
register: result
check_mode: yes
- name: test create server server
assert:
that:
- result is changed
- name: test create server
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: ubuntu-20.04
enable_ipv6: False
state: started
register: main_server
- name: verify create server
assert:
that:
- main_server is changed
- main_server.hcloud_server.name == "{{ hcloud_server_name }}"
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
- name: test create server idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
state: started
register: result
- name: verify create server idempotence
assert:
that:
- result is not changed
- name: test stop server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
state: stopped
register: result
check_mode: yes
- name: verify stop server with check mode
assert:
that:
- result is changed
- result.hcloud_server.status == "running"
- name: test stop server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: stopped
register: result
- name: verify stop server
assert:
that:
- result is changed
- result.hcloud_server.status == "off"
- name: test start server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
state: started
register: result
check_mode: true
- name: verify start server with check mode
assert:
that:
- result is changed
- name: test start server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: started
register: result
- name: verify start server
assert:
that:
- result is changed
- result.hcloud_server.status == "running"
- name: test start server idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
state: started
register: result
- name: verify start server idempotence
assert:
that:
- result is not changed
- result.hcloud_server.status == "running"
- name: test stop server by its id
hcloud_server:
id: "{{ main_server.hcloud_server.id }}"
state: stopped
register: result
- name: verify stop server by its id
assert:
that:
- result is changed
- result.hcloud_server.status == "off"
- name: test resize server running without force
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: present
register: result
check_mode: true
- name: verify test resize server running without force
assert:
that:
- result is changed
- result.hcloud_server.server_type == "cx11"
- name: test resize server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: stopped
register: result
check_mode: true
- name: verify resize server with check mode
assert:
that:
- result is changed
- name: test resize server without disk
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: stopped
register: result
- name: verify resize server without disk
assert:
that:
- result is changed
- result.hcloud_server.server_type == "cx21"
- name: test resize server idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: stopped
register: result
- name: verify resize server idempotence
assert:
that:
- result is not changed
- name: test resize server to smaller plan
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx11"
state: stopped
register: result
- name: verify resize server to smaller plan
assert:
that:
- result is changed
- result.hcloud_server.server_type == "cx11"
- name: test resize server with disk
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
upgrade_disk: true
state: stopped
register: result
- name: verify resize server with disk
assert:
that:
- result is changed
- result.hcloud_server.server_type == "cx21"
- name: test enable backups with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
backups: true
state: stopped
register: result
check_mode: true
- name: verify enable backups with check mode
assert:
that:
- result is changed
- name: test enable backups
hcloud_server:
name: "{{ hcloud_server_name }}"
backups: true
state: stopped
register: result
- name: verify enable backups
assert:
that:
- result is changed
- result.hcloud_server.backup_window != ""
- name: test enable backups idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
backups: true
state: stopped
register: result
- name: verify enable backups idempotence
assert:
that:
- result is not changed
- result.hcloud_server.backup_window != ""
- name: test rebuild server
hcloud_server:
name: "{{ hcloud_server_name }}"
image: ubuntu-20.04
state: rebuild
register: result_after_test
- name: verify rebuild server
assert:
that:
- result_after_test is changed
- result.hcloud_server.id == result_after_test.hcloud_server.id
- name: test rebuild server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
image: ubuntu-20.04
state: rebuild
register: result_after_test
check_mode: true
- name: verify rebuild server with check mode
assert:
that:
- result_after_test is changed
- name: test update server protection booth protection arguments are required
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: true
state: present
register: result_after_test
ignore_errors: true
- name: verify update server protection booth protection arguments are required
assert:
that:
- result_after_test is failed
- 'result_after_test.msg == "parameters are required together: delete_protection, rebuild_protection"'
- name: test update server protection fails if they are not the same
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: true
rebuild_protection: false
state: present
register: result_after_test
ignore_errors: true
- name: verify update server protection fails if they are not the same
assert:
that:
- result_after_test is failed
- name: test update server protection
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: true
rebuild_protection: true
state: present
register: result_after_test
ignore_errors: true
- name: verify update server protection
assert:
that:
- result_after_test is changed
- result_after_test.hcloud_server.delete_protection is sameas true
- result_after_test.hcloud_server.rebuild_protection is sameas true
- name: test server without protection set to be idempotent
hcloud_server:
name: "{{hcloud_server_name}}"
register: result_after_test
- name: verify test server without protection set to be idempotent
assert:
that:
- result_after_test is not changed
- result_after_test.hcloud_server.delete_protection is sameas true
- result_after_test.hcloud_server.rebuild_protection is sameas true
- name: test delete server fails if it is protected
hcloud_server:
name: "{{hcloud_server_name}}"
state: absent
ignore_errors: yes
register: result
- name: verify delete server fails if it is protected
assert:
that:
- result is failed
- 'result.msg == "server deletion is protected"'
- name: test rebuild server fails if it is protected
hcloud_server:
name: "{{hcloud_server_name}}"
image: ubuntu-20.04
state: rebuild
ignore_errors: yes
register: result
- name: verify rebuild server fails if it is protected
assert:
that:
- result is failed
- 'result.msg == "server rebuild is protected"'
- name: test remove server protection
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: false
rebuild_protection: false
state: present
register: result_after_test
ignore_errors: true
- name: verify remove server protection
assert:
that:
- result_after_test is changed
- result_after_test.hcloud_server.delete_protection is sameas false
- result_after_test.hcloud_server.rebuild_protection is sameas false
- name: absent server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify absent server
assert:
that:
- result is success
- name: test create server with ssh key
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: started
register: main_server
- name: verify create server with ssh key
assert:
that:
- main_server is changed
- main_server.hcloud_server.name == "{{ hcloud_server_name }}"
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
- name: test activate rescue mode with check_mode
hcloud_server:
name: "{{ hcloud_server_name }}"
rescue_mode: "linux64"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: main_server
check_mode: true
- name: verify activate rescue mode
assert:
that:
- main_server is changed
- name: test activate rescue mode
hcloud_server:
name: "{{ hcloud_server_name }}"
rescue_mode: "linux64"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: main_server
- name: verify activate rescue mode
assert:
that:
- main_server is changed
- main_server.hcloud_server.rescue_enabled is sameas true
- name: test disable rescue mode
hcloud_server:
name: "{{ hcloud_server_name }}"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: main_server
- name: verify activate rescue mode
assert:
that:
- main_server is changed
- main_server.hcloud_server.rescue_enabled is sameas false
- name: test activate rescue mode without ssh keys
hcloud_server:
name: "{{ hcloud_server_name }}"
rescue_mode: "linux64"
state: present
register: main_server
- name: verify activate rescue mode without ssh keys
assert:
that:
- main_server is changed
- main_server.hcloud_server.rescue_enabled is sameas true
- name: absent server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify absent server
assert:
that:
- result is success
- name: test create server with rescue_mode
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
rescue_mode: "linux64"
state: started
register: main_server
- name: verify create server with rescue_mode
assert:
that:
- main_server is changed
- main_server.hcloud_server.name == "{{ hcloud_server_name }}"
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
- main_server.hcloud_server.rescue_enabled is sameas true
- name: absent server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify absent server
assert:
that:
- result is success
- name: test create server with labels
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
labels:
key: value
mylabel: "val123"
state: started
register: main_server
- name: verify create server with labels
assert:
that:
- main_server is changed
- main_server.hcloud_server.labels.key == "value"
- main_server.hcloud_server.labels.mylabel == "val123"
- name: test update server with labels
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
labels:
key: other
mylabel: "val123"
state: started
register: main_server
- name: verify update server with labels
assert:
that:
- main_server is changed
- main_server.hcloud_server.labels.key == "other"
- main_server.hcloud_server.labels.mylabel == "val123"
- name: test update server with labels in other order
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
labels:
mylabel: "val123"
key: other
state: started
register: main_server
- name: verify update server with labels in other order
assert:
that:
- main_server is not changed
- name: cleanup with labels
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- result is success
- name: test create server with enabled backups
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
backups: true
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify enable backups
assert:
that:
- result is changed
- result.hcloud_server.backup_window != ""
- name: cleanup test create server with enabled backups
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- result is success
- name: test create server with protection
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: true
rebuild_protection: true
server_type: cpx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result_after_test
ignore_errors: true
- name: verify create server with protection
assert:
that:
- result_after_test is changed
- result_after_test.hcloud_server.delete_protection is sameas true
- result_after_test.hcloud_server.rebuild_protection is sameas true
- name: test delete server fails if it is protected
hcloud_server:
name: "{{hcloud_server_name}}"
state: absent
ignore_errors: yes
register: result
- name: verify delete server fails if it is protected
assert:
that:
- result is failed
- 'result.msg == "server deletion is protected"'
- name: remove protection from server
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: false
rebuild_protection: false
state: present
register: result_after_test
ignore_errors: true
- name: verify update server protection
assert:
that:
- result_after_test is changed
- result_after_test.hcloud_server.delete_protection is sameas false
- result_after_test.hcloud_server.rebuild_protection is sameas false
- name: cleanup
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- result is success

View file

@ -0,0 +1,105 @@
# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: test add not existing firewall should fail
hcloud_server:
name: "{{ hcloud_server_name }}"
firewalls:
- not-existing
state: present
ignore_errors: yes
register: result
- name: verify add not existing firewall should fail
assert:
that:
- result is failed
- 'result.msg == "firewall not-existing was not found"'
- name: setup create firewalls
hcloud_firewall:
name: "{{ item }}"
rules:
- direction: in
protocol: icmp
source_ips:
- 0.0.0.0/0
- ::/0
with_items:
- "{{ hcloud_firewall_name }}"
- "{{ hcloud_firewall_name }}2"
- name: test create server with firewalls
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}"
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify test create server with firewalls
assert:
that:
- result is changed
- name: test create server with firewalls idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}"
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify test create server with firewalls idempotence
assert:
that:
- result is not changed
- name: test update server with firewalls
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}2"
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify test update server with firewalls
assert:
that:
- result is changed
- name: test update server with firewalls idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}2"
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify test update server with firewalls idempotence
assert:
that:
- result is not changed
- name: cleanup server with firewalls
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
- name: cleanup test create firewall
hcloud_firewall:
name: "{{ item }}"
state: absent
with_items:
- "{{ hcloud_firewall_name }}"
- "{{ hcloud_firewall_name }}2"

View file

@ -1,779 +1,7 @@
# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# Copyright: (c) 2022, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify setup
assert:
that:
- result is success
- name: test missing required parameters on create server
hcloud_server:
name: "{{ hcloud_server_name }}"
register: result
ignore_errors: yes
- name: verify fail test missing required parameters on create server
assert:
that:
- result is failed
- 'result.msg == "missing required arguments: server_type, image"'
- name: test create server with not existing server type
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: not-existing-server-type
image: ubuntu-20.04
state: present
register: result
ignore_errors: yes
- name: verify fail test create server with not existing server type
assert:
that:
- result is failed
- 'result.msg == "server_type not-existing-server-type was not found"'
- name: test create server with not existing image
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cx11
image: my-not-existing-image-20.04
state: present
register: result
ignore_errors: yes
- name: verify fail test create server with not existing image
assert:
that:
- result is failed
- 'result.msg == "Image my-not-existing-image-20.04 was not found"'
- name: test create server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cx11
image: ubuntu-20.04
state: present
register: result
check_mode: yes
- name: test create server server
assert:
that:
- result is changed
- name: test create server
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: ubuntu-20.04
state: started
register: main_server
- name: verify create server
assert:
that:
- main_server is changed
- main_server.hcloud_server.name == "{{ hcloud_server_name }}"
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
- name: test create server idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
state: started
register: result
- name: verify create server idempotence
assert:
that:
- result is not changed
- name: test stop server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
state: stopped
register: result
check_mode: yes
- name: verify stop server with check mode
assert:
that:
- result is changed
- result.hcloud_server.status == "running"
- name: test stop server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: stopped
register: result
- name: verify stop server
assert:
that:
- result is changed
- result.hcloud_server.status == "off"
- name: test start server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
state: started
register: result
check_mode: true
- name: verify start server with check mode
assert:
that:
- result is changed
- name: test start server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: started
register: result
- name: verify start server
assert:
that:
- result is changed
- result.hcloud_server.status == "running"
- name: test start server idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
state: started
register: result
- name: verify start server idempotence
assert:
that:
- result is not changed
- result.hcloud_server.status == "running"
- name: test stop server by its id
hcloud_server:
id: "{{ main_server.hcloud_server.id }}"
state: stopped
register: result
- name: verify stop server by its id
assert:
that:
- result is changed
- result.hcloud_server.status == "off"
- name: test resize server running without force
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: present
register: result
check_mode: true
- name: verify test resize server running without force
assert:
that:
- result is changed
- result.hcloud_server.server_type == "cx11"
- name: test resize server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: stopped
register: result
check_mode: true
- name: verify resize server with check mode
assert:
that:
- result is changed
- name: test resize server without disk
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: stopped
register: result
- name: verify resize server without disk
assert:
that:
- result is changed
- result.hcloud_server.server_type == "cx21"
- name: test resize server idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: stopped
register: result
- name: verify resize server idempotence
assert:
that:
- result is not changed
- name: test resize server to smaller plan
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx11"
state: stopped
register: result
- name: verify resize server to smaller plan
assert:
that:
- result is changed
- result.hcloud_server.server_type == "cx11"
- name: test resize server with disk
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
upgrade_disk: true
state: stopped
register: result
- name: verify resize server with disk
assert:
that:
- result is changed
- result.hcloud_server.server_type == "cx21"
- name: test enable backups with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
backups: true
state: stopped
register: result
check_mode: true
- name: verify enable backups with check mode
assert:
that:
- result is changed
- name: test enable backups
hcloud_server:
name: "{{ hcloud_server_name }}"
backups: true
state: stopped
register: result
- name: verify enable backups
assert:
that:
- result is changed
- result.hcloud_server.backup_window != ""
- name: test enable backups idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
backups: true
state: stopped
register: result
- name: verify enable backups idempotence
assert:
that:
- result is not changed
- result.hcloud_server.backup_window != ""
- name: test rebuild server
hcloud_server:
name: "{{ hcloud_server_name }}"
image: ubuntu-20.04
state: rebuild
register: result_after_test
- name: verify rebuild server
assert:
that:
- result_after_test is changed
- result.hcloud_server.id == result_after_test.hcloud_server.id
- name: test rebuild server with check mode
hcloud_server:
name: "{{ hcloud_server_name }}"
image: ubuntu-20.04
state: rebuild
register: result_after_test
check_mode: true
- name: verify rebuild server with check mode
assert:
that:
- result_after_test is changed
- name: test update server protection booth protection arguments are required
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: true
state: present
register: result_after_test
ignore_errors: true
- name: verify update server protection booth protection arguments are required
assert:
that:
- result_after_test is failed
- 'result_after_test.msg == "parameters are required together: delete_protection, rebuild_protection"'
- name: test update server protection fails if they are not the same
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: true
rebuild_protection: false
state: present
register: result_after_test
ignore_errors: true
- name: verify update server protection fails if they are not the same
assert:
that:
- result_after_test is failed
- name: test update server protection
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: true
rebuild_protection: true
state: present
register: result_after_test
ignore_errors: true
- name: verify update server protection
assert:
that:
- result_after_test is changed
- result_after_test.hcloud_server.delete_protection is sameas true
- result_after_test.hcloud_server.rebuild_protection is sameas true
- name: test server without protection set to be idempotent
hcloud_server:
name: "{{hcloud_server_name}}"
register: result_after_test
- name: verify test server without protection set to be idempotent
assert:
that:
- result_after_test is not changed
- result_after_test.hcloud_server.delete_protection is sameas true
- result_after_test.hcloud_server.rebuild_protection is sameas true
- name: test delete server fails if it is protected
hcloud_server:
name: "{{hcloud_server_name}}"
state: absent
ignore_errors: yes
register: result
- name: verify delete server fails if it is protected
assert:
that:
- result is failed
- 'result.msg == "server deletion is protected"'
- name: test rebuild server fails if it is protected
hcloud_server:
name: "{{hcloud_server_name}}"
image: ubuntu-20.04
state: rebuild
ignore_errors: yes
register: result
- name: verify rebuild server fails if it is protected
assert:
that:
- result is failed
- 'result.msg == "server rebuild is protected"'
- name: test remove server protection
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: false
rebuild_protection: false
state: present
register: result_after_test
ignore_errors: true
- name: verify remove server protection
assert:
that:
- result_after_test is changed
- result_after_test.hcloud_server.delete_protection is sameas false
- result_after_test.hcloud_server.rebuild_protection is sameas false
- name: absent server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify absent server
assert:
that:
- result is success
- name: test create server with ssh key
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: started
register: main_server
- name: verify create server with ssh key
assert:
that:
- main_server is changed
- main_server.hcloud_server.name == "{{ hcloud_server_name }}"
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
- name: absent server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify absent server
assert:
that:
- result is success
- name: test create server with rescue_mode
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
rescue_mode: "linux64"
state: started
register: main_server
- name: verify create server with rescue_mode
assert:
that:
- main_server is changed
- main_server.hcloud_server.name == "{{ hcloud_server_name }}"
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
- main_server.hcloud_server.rescue_enabled is sameas true
- name: absent server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify absent server
assert:
that:
- result is success
- name: setup server
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: ubuntu-20.04
state: started
register: main_server
- name: verify setup server
assert:
that:
- main_server is changed
- main_server.hcloud_server.name == "{{ hcloud_server_name }}"
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
- name: test add not existing firewall should fail
hcloud_server:
name: "{{ hcloud_server_name }}"
firewalls:
- not-existing
state: present
ignore_errors: yes
register: result
- name: verifyt add not existing firewall should fail
assert:
that:
- result is failed
- 'result.msg == "firewall not-existing was not found"'
- name: test activate rescue mode with check_mode
hcloud_server:
name: "{{ hcloud_server_name }}"
rescue_mode: "linux64"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: main_server
check_mode: true
- name: verify activate rescue mode
assert:
that:
- main_server is changed
- name: test activate rescue mode
hcloud_server:
name: "{{ hcloud_server_name }}"
rescue_mode: "linux64"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: main_server
- name: verify activate rescue mode
assert:
that:
- main_server is changed
- main_server.hcloud_server.rescue_enabled is sameas true
- name: test disable rescue mode
hcloud_server:
name: "{{ hcloud_server_name }}"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: main_server
- name: verify activate rescue mode
assert:
that:
- main_server is changed
- main_server.hcloud_server.rescue_enabled is sameas false
- name: test activate rescue mode without ssh keys
hcloud_server:
name: "{{ hcloud_server_name }}"
rescue_mode: "linux64"
state: present
register: main_server
- name: verify activate rescue mode without ssh keys
assert:
that:
- main_server is changed
- main_server.hcloud_server.rescue_enabled is sameas true
- name: cleanup
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- result is success
- name: test create server with labels
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
labels:
key: value
mylabel: "val123"
state: started
register: main_server
- name: verify create server with labels
assert:
that:
- main_server is changed
- main_server.hcloud_server.labels.key == "value"
- main_server.hcloud_server.labels.mylabel == "val123"
- name: test update server with labels
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
labels:
key: other
mylabel: "val123"
state: started
register: main_server
- name: verify update server with labels
assert:
that:
- main_server is changed
- main_server.hcloud_server.labels.key == "other"
- main_server.hcloud_server.labels.mylabel == "val123"
- name: test update server with labels in other order
hcloud_server:
name: "{{ hcloud_server_name}}"
server_type: cx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
labels:
mylabel: "val123"
key: other
state: started
register: main_server
- name: verify update server with labels in other order
assert:
that:
- main_server is not changed
- name: cleanup with labels
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- result is success
- name: test create server with enabled backups
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
backups: true
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify enable backups
assert:
that:
- result is changed
- result.hcloud_server.backup_window != ""
- name: cleanup test create server with enabled backups
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- result is success
- name: test create server with protection
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: true
rebuild_protection: true
server_type: cpx11
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result_after_test
ignore_errors: true
- name: verify create server with protection
assert:
that:
- result_after_test is changed
- result_after_test.hcloud_server.delete_protection is sameas true
- result_after_test.hcloud_server.rebuild_protection is sameas true
- name: test delete server fails if it is protected
hcloud_server:
name: "{{hcloud_server_name}}"
state: absent
ignore_errors: yes
register: result
- name: verify delete server fails if it is protected
assert:
that:
- result is failed
- 'result.msg == "server deletion is protected"'
- name: remove protection from server
hcloud_server:
name: "{{ hcloud_server_name }}"
delete_protection: false
rebuild_protection: false
state: present
register: result_after_test
ignore_errors: true
- name: verify update server protection
assert:
that:
- result_after_test is changed
- result_after_test.hcloud_server.delete_protection is sameas false
- result_after_test.hcloud_server.rebuild_protection is sameas false
- name: cleanup
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- result is success
- name: setup create firewalls
hcloud_firewall:
name: "{{ item }}"
rules:
- direction: in
protocol: icmp
source_ips:
- 0.0.0.0/0
- ::/0
with_items:
- "{{ hcloud_firewall_name }}"
- "{{ hcloud_firewall_name }}2"
- name: test create server with firewalls
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}"
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify test create server with firewalls
assert:
that:
- result is changed
- name: test create server with firewalls idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}"
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify test create server with firewalls idempotence
assert:
that:
- result is not changed
- name: test update server with firewalls
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}2"
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify test update server with firewalls
assert:
that:
- result is changed
- name: test update server with firewalls idempotence
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}2"
image: "ubuntu-20.04"
ssh_keys:
- ci@ansible.hetzner.cloud
state: present
register: result
- name: verify test update server with firewalls idempotence
assert:
that:
- result is not changed
- name: cleanup server with firewalls
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
- name: cleanup test create firewall
hcloud_firewall:
name: "{{ item }}"
state: absent
with_items:
- "{{ hcloud_firewall_name }}"
- "{{ hcloud_firewall_name }}2"
#- ansible.builtin.include_tasks: validation.yml
#- ansible.builtin.include_tasks: basic.yml
#- ansible.builtin.include_tasks: firewalls.yml
- ansible.builtin.include_tasks: primary_ips.yml

View file

@ -0,0 +1,82 @@
# Copyright: (c) 2022, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup create primary ipv4
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}v4"
type: ipv4
datacenter: "fsn1-dc14"
register: primaryIPv4
- name: setup create second primary ipv4
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}v42"
type: ipv4
datacenter: "fsn1-dc14"
register: secondPrimaryIPv4
- name: setup create primary ipv6
hcloud_primary_ip:
name: "{{ hcloud_primary_ip_name }}v6"
type: ipv6
datacenter: "fsn1-dc14"
register: primaryIPv6
- name: test create server with primary ips
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
image: "ubuntu-20.04"
ipv4: "{{primaryIPv4.hcloud_primary_ip.id}}"
ipv6: "{{primaryIPv6.hcloud_primary_ip.id}}"
ssh_keys:
- ci@ansible.hetzner.cloud
state: stopped
register: result
- name: verify test create server with primary ips
assert:
that:
- result is changed
- name: test update server with primary ips
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
image: "ubuntu-20.04"
ipv4: "{{secondPrimaryIPv4.hcloud_primary_ip.id}}"
ipv6: ""
enable_ipv6: no
ssh_keys:
- ci@ansible.hetzner.cloud
state: stopped
register: result
- name: verify test create server with primary ips
assert:
that:
- result is changed
- name: cleanup server with primary ips
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
- name: cleanup test create primary ips
hcloud_primary_ip:
name: "{{ hcloud_server_name }}v4"
state: absent
- name: cleanup test create primary ips
hcloud_primary_ip:
name: "{{ hcloud_server_name }}v42"
state: absent
until: result is not failed
retries: 5
delay: 2
- name: cleanup test create primary ips
hcloud_primary_ip:
name: "{{ hcloud_server_name }}v6"
state: absent
until: result is not failed
retries: 5
delay: 2

View file

@ -0,0 +1,51 @@
# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify setup
assert:
that:
- result is success
- name: test missing required parameters on create server
hcloud_server:
name: "{{ hcloud_server_name }}"
register: result
ignore_errors: yes
- name: verify fail test missing required parameters on create server
assert:
that:
- result is failed
- 'result.msg == "missing required arguments: server_type, image"'
- name: test create server with not existing server type
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: not-existing-server-type
image: ubuntu-20.04
state: present
register: result
ignore_errors: yes
- name: verify fail test create server with not existing server type
assert:
that:
- result is failed
- 'result.msg == "server_type not-existing-server-type was not found"'
- name: test create server with not existing image
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cx11
image: my-not-existing-image-20.04
state: present
register: result
ignore_errors: yes
- name: verify fail test create server with not existing image
assert:
that:
- result is failed
- 'result.msg == "Image my-not-existing-image-20.04 was not found"'