Add possibility to specify private network when creating or updating servers (#160)

* Add possibility to specify private network when creating or updating a server

This allows creating servers without public internet access

* Add integration tests
This commit is contained in:
Konstantin Köhring 2022-11-09 22:31:03 +01:00 committed by GitHub
parent 6de022e9fb
commit ad8958a2ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 190 additions and 0 deletions

View file

@ -97,6 +97,12 @@ options:
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
private_networks:
description:
- List of private networks the server is attached to (name or ID)
type: list
elements: str
default: []
force_upgrade:
description:
- Deprecated
@ -222,6 +228,16 @@ EXAMPLES = """
name: my-server
placement_group: null
state: present
- name: Add server with private network only
hcloud_server:
name: my-server
enable_ipv4: false
enable_ipv6: false
private_networks:
- my-network
- 4711
state: present
"""
RETURN = """
@ -260,6 +276,12 @@ hcloud_server:
returned: always
type: str
sample: 2a01:4f8:1c1c:c140::/64
private_networks:
description: List of private networks the server is attached to (name or ID)
returned: always
type: list
elements: str
sample: ['my-network', 'another-network', '4711']
location:
description: Name of the location of the server
returned: always
@ -345,6 +367,7 @@ class AnsibleHcloudServer(Hcloud):
"name": to_native(self.hcloud_server.name),
"ipv4_address": ipv4_address,
"ipv6": ipv6,
"private_networks": [to_native(net.network.name) for net in self.hcloud_server.private_net],
"image": image,
"server_type": to_native(self.hcloud_server.server_type.name),
"datacenter": to_native(self.hcloud_server.datacenter.name),
@ -401,6 +424,15 @@ class AnsibleHcloudServer(Hcloud):
p = self.client.primary_ips.get_by_id(self.module.params.get("ipv6"))
params["public_net"].ipv6 = p
if self.module.params.get("private_networks") is not None:
_networks = []
for network_name_or_id in self.module.params.get("private_networks"):
_networks.append(
self.client.networks.get_by_name(network_name_or_id)
or self.client.networks.get_by_id(network_name_or_id)
)
params["networks"] = _networks
if self.module.params.get("ssh_keys") is not None:
params["ssh_keys"] = [
SSHKey(name=ssh_key_name)
@ -665,6 +697,34 @@ class AnsibleHcloudServer(Hcloud):
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()
if "private_networks" in self.module.params:
if not bool(self.module.params["private_networks"]):
# This handles None, "" and []
networks_target = {}
else:
_networks = {}
for network_name_or_id in self.module.params.get("private_networks"):
_found_network = self.client.networks.get_by_name(network_name_or_id) \
or self.client.networks.get_by_id(network_name_or_id)
_networks.update(
{_found_network.id: _found_network}
)
networks_target = _networks
networks_is = dict()
for p_network in self.hcloud_server.private_net:
networks_is.update({p_network.network.id: p_network.network})
for network_id in set(list(networks_is) + list(networks_target)):
if network_id in networks_is and network_id not in networks_target:
self.stop_server_if_forced()
if not self.module.check_mode:
self.hcloud_server.detach_from_network(networks_is[network_id]).wait_until_finished()
self._mark_as_changed()
elif network_id in networks_target and network_id not in networks_is:
self.stop_server_if_forced()
if not self.module.check_mode:
self.hcloud_server.attach_to_network(networks_target[network_id]).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()
@ -811,6 +871,7 @@ class AnsibleHcloudServer(Hcloud):
enable_ipv6={"type": "bool", "default": True},
ipv4={"type": "str"},
ipv6={"type": "str"},
private_networks={"type": "list", "elements": "str", "default": []},
force={"type": "bool", "default": False},
force_upgrade={"type": "bool", "default": False},
allow_deprecated_image={"type": "bool", "default": False},

View file

@ -87,6 +87,12 @@ hcloud_server_info:
returned: always
type: str
sample: 2a01:4f8:1c1c:c140::/64
private_networks:
description: List of private networks the server is attached to (name)
returned: always
type: list
elements: str
sample: ['my-network', 'another-network']
location:
description: Name of the location of the server
returned: always
@ -161,6 +167,7 @@ class AnsibleHcloudServerInfo(Hcloud):
"name": to_native(server.name),
"ipv4_address": ipv4_address,
"ipv6": ipv6,
"private_networks": [to_native(net.network.name) for net in server.private_net],
"image": image,
"server_type": to_native(server.server_type.name),
"datacenter": to_native(server.datacenter.name),

View file

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

View file

@ -5,3 +5,4 @@
#- ansible.builtin.include_tasks: basic.yml
#- ansible.builtin.include_tasks: firewalls.yml
- ansible.builtin.include_tasks: primary_ips.yml
- ansible.builtin.include_tasks: private_network_only.yml

View file

@ -0,0 +1,120 @@
# 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 network
hcloud_network:
name: "{{ hcloud_network_name }}-1"
ip_range: 192.168.0.0/23
register: primaryNetwork
- name: setup create network subnet 1
hcloud_subnetwork:
network: "{{ hcloud_network_name }}-1"
ip_range: 192.168.0.0/24
network_zone: eu-central
type: cloud
state: present
- name: setup create network subnet 2
hcloud_subnetwork:
network: "{{ hcloud_network_name }}-1"
ip_range: 192.168.1.0/24
network_zone: eu-central
type: cloud
state: present
- name: setup create secondary network
hcloud_network:
name: "{{ hcloud_network_name }}-2"
ip_range: 192.168.2.0/23
register: secondaryNetwork
- name: setup create secondary network subnet 1
hcloud_subnetwork:
network: "{{ hcloud_network_name }}-2"
ip_range: 192.168.2.0/24
network_zone: eu-central
type: cloud
state: present
- name: setup create secondary network subnet 2
hcloud_subnetwork:
network: "{{ hcloud_network_name }}-2"
ip_range: 192.168.3.0/24
network_zone: eu-central
type: cloud
state: present
- name: test create server with primary network and no internet
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
image: "ubuntu-20.04"
enable_ipv4: no
enable_ipv6: no
private_networks:
- "{{ primaryNetwork.hcloud_network.name }}"
ssh_keys:
- ci@ansible.hetzner.cloud
state: stopped
register: result
- name: verify test create server with primary network
assert:
that:
- result is changed
- name: test update server by adding secondary network
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
image: "ubuntu-20.04"
enable_ipv4: no
enable_ipv6: no
private_networks:
- "{{ primaryNetwork.hcloud_network.name }}"
- "{{ secondaryNetwork.hcloud_network.id }}"
ssh_keys:
- ci@ansible.hetzner.cloud
state: stopped
register: result
- name: verify test update server by adding secondary network
assert:
that:
- result is changed
- name: test update server idem
hcloud_server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
image: "ubuntu-20.04"
enable_ipv4: no
enable_ipv6: no
private_networks:
- "{{ primaryNetwork.hcloud_network.name }}"
- "{{ secondaryNetwork.hcloud_network.id }}"
ssh_keys:
- ci@ansible.hetzner.cloud
state: stopped
register: result
- name: verify test update server idem
assert:
that:
- result is not changed
- name: cleanup server
hcloud_server:
name: "{{ hcloud_server_name }}"
state: absent
- name: cleanup networks
hcloud_network:
name: "{{ item }}"
state: absent
with_items:
- "{{ primaryNetwork.hcloud_network.name }}"
- "{{ secondaryNetwork.hcloud_network.id }}"
until: result is not failed
retries: 5
delay: 2