forked from ansible/ansible
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add hcloud_network module (ansible#59366)
* Add hcloud_network module * Apply suggestions from code review Co-Authored-By: Matt Clay <[email protected]> * Add notice about dependency * Adjust tests * Apply suggestions from code review Co-Authored-By: Felix Fontein <[email protected]> * Allow changing of ip range * Add Setup step
- Loading branch information
1 parent
0b27ec3
commit 5bddd2f
Showing
5 changed files
with
343 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright: (c) 2019, Hetzner Cloud GmbH <[email protected]> | ||
# 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 | ||
|
||
ANSIBLE_METADATA = { | ||
"metadata_version": "1.1", | ||
"status": ["preview"], | ||
"supported_by": "community", | ||
} | ||
|
||
DOCUMENTATION = """ | ||
--- | ||
module: hcloud_network | ||
short_description: Create and manage cloud Networks on the Hetzner Cloud. | ||
version_added: "2.9" | ||
description: | ||
- Create, update and manage cloud Networks on the Hetzner Cloud. | ||
- You need at least hcloud-python 1.3.0. | ||
author: | ||
- Lukas Kaemmerling (@lkaemmerling) | ||
options: | ||
id: | ||
description: | ||
- The ID of the Hetzner Cloud Networks to manage. | ||
- Only required if no Network I(name) is given. | ||
type: int | ||
name: | ||
description: | ||
- The Name of the Hetzner Cloud Network to manage. | ||
- Only required if no Network I(id) is given or a Network does not exists. | ||
type: str | ||
ip_range: | ||
description: | ||
- IP range of the Network. | ||
- Required if Network does not exists. | ||
type: str | ||
labels: | ||
description: | ||
- User-defined labels (key-value pairs). | ||
type: dict | ||
state: | ||
description: | ||
- State of the Network. | ||
default: present | ||
choices: [ absent, present ] | ||
type: str | ||
requirements: | ||
- hcloud-python >= 1.3.0 | ||
extends_documentation_fragment: hcloud | ||
""" | ||
|
||
EXAMPLES = """ | ||
- name: Create a basic network | ||
hcloud_network: | ||
name: my-network | ||
ip_range: 10.0.0.0/8 | ||
state: present | ||
- name: Ensure the Network is absent (remove if needed) | ||
hcloud_network: | ||
name: my-network | ||
state: absent | ||
""" | ||
|
||
RETURN = """ | ||
hcloud_network: | ||
description: The Network | ||
returned: always | ||
type: complex | ||
contains: | ||
id: | ||
description: ID of the Network | ||
type: int | ||
returned: always | ||
sample: 12345 | ||
name: | ||
description: Name of the Network | ||
type: string | ||
returned: always | ||
sample: my-volume | ||
ip_range: | ||
description: IP range of the Network | ||
type: str | ||
returned: always | ||
sample: 10.0.0.0/8 | ||
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.module_utils.hcloud import Hcloud | ||
|
||
try: | ||
from hcloud import APIException | ||
except ImportError: | ||
APIException = None | ||
|
||
|
||
class AnsibleHcloudNetwork(Hcloud): | ||
def __init__(self, module): | ||
super(AnsibleHcloudNetwork, self).__init__(module, "hcloud_network") | ||
self.hcloud_network = None | ||
|
||
def _prepare_result(self): | ||
return { | ||
"id": to_native(self.hcloud_network.id), | ||
"name": to_native(self.hcloud_network.name), | ||
"ip_range": to_native(self.hcloud_network.ip_range), | ||
"labels": self.hcloud_network.labels, | ||
} | ||
|
||
def _get_network(self): | ||
try: | ||
if self.module.params.get("id") is not None: | ||
self.hcloud_network = self.client.networks.get_by_id( | ||
self.module.params.get("id") | ||
) | ||
else: | ||
self.hcloud_network = self.client.networks.get_by_name( | ||
self.module.params.get("name") | ||
) | ||
except APIException as e: | ||
self.module.fail_json(msg=e.message) | ||
|
||
def _create_network(self): | ||
|
||
self.module.fail_on_missing_params( | ||
required_params=["name", "ip_range"] | ||
) | ||
params = { | ||
"name": self.module.params.get("name"), | ||
"ip_range": self.module.params.get("ip_range"), | ||
"labels": self.module.params.get("labels"), | ||
} | ||
|
||
if not self.module.check_mode: | ||
self.client.networks.create(**params) | ||
|
||
self._mark_as_changed() | ||
self._get_network() | ||
|
||
def _update_network(self): | ||
|
||
labels = self.module.params.get("labels") | ||
if labels is not None and labels != self.hcloud_network.labels: | ||
if not self.module.check_mode: | ||
self.hcloud_network.update(labels=labels) | ||
self._mark_as_changed() | ||
|
||
ip_range = self.module.params.get("ip_range") | ||
if ip_range is not None and ip_range != self.hcloud_network.ip_range: | ||
if not self.module.check_mode: | ||
self.hcloud_network.change_ip_range(ip_range=ip_range).wait_until_finished() | ||
self._mark_as_changed() | ||
|
||
self._get_network() | ||
|
||
def present_network(self): | ||
self._get_network() | ||
if self.hcloud_network is None: | ||
self._create_network() | ||
else: | ||
self._update_network() | ||
|
||
def delete_network(self): | ||
self._get_network() | ||
if self.hcloud_network is not None: | ||
if not self.module.check_mode: | ||
self.client.networks.delete(self.hcloud_network) | ||
self._mark_as_changed() | ||
self.hcloud_network = None | ||
|
||
@staticmethod | ||
def define_module(): | ||
return AnsibleModule( | ||
argument_spec=dict( | ||
id={"type": "int"}, | ||
name={"type": "str"}, | ||
ip_range={"type": "str"}, | ||
labels={"type": "dict"}, | ||
state={ | ||
"choices": ["absent", "present"], | ||
"default": "present", | ||
}, | ||
**Hcloud.base_module_arguments() | ||
), | ||
required_one_of=[['id', 'name']], | ||
supports_check_mode=True, | ||
) | ||
|
||
|
||
def main(): | ||
module = AnsibleHcloudNetwork.define_module() | ||
|
||
hcloud = AnsibleHcloudNetwork(module) | ||
state = module.params["state"] | ||
if state == "absent": | ||
hcloud.delete_network() | ||
elif state == "present": | ||
hcloud.present_network() | ||
|
||
module.exit_json(**hcloud.get_result()) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
cloud/hcloud | ||
shippable/hcloud/group1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Copyright: (c) 2019, Hetzner Cloud GmbH <[email protected]> | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
--- | ||
hcloud_prefix: "tests" | ||
hcloud_network_name: "{{hcloud_prefix}}-integ" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# Copyright: (c) 2019, Hetzner Cloud GmbH <[email protected]> | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
--- | ||
- name: setup | ||
hcloud_network: | ||
name: "{{ hcloud_network_name }}" | ||
state: absent | ||
register: result | ||
- name: verify setup | ||
assert: | ||
that: | ||
- result is success | ||
|
||
- name: test missing ip_range parameter on create Network | ||
hcloud_network: | ||
name: "{{hcloud_network_name}}" | ||
register: result | ||
ignore_errors: yes | ||
- name: verify fail missing ip_range parameter on create Network result | ||
assert: | ||
that: | ||
- result is failed | ||
- 'result.msg == "missing required arguments: ip_range"' | ||
|
||
- name: test create Network with check mode | ||
hcloud_network: | ||
name: "{{hcloud_network_name}}" | ||
ip_range: "10.0.0.0/16" | ||
register: result | ||
check_mode: yes | ||
- name: verify create Network with check mode result | ||
assert: | ||
that: | ||
- result is changed | ||
|
||
- name: test create Network | ||
hcloud_network: | ||
name: "{{hcloud_network_name}}" | ||
ip_range: "10.0.0.0/16" | ||
register: network | ||
- name: verify test create Network result | ||
assert: | ||
that: | ||
- network is changed | ||
- network.hcloud_network.name == "{{hcloud_network_name}}" | ||
- network.hcloud_network.ip_range == "10.0.0.0/16" | ||
|
||
- name: test create Network idempotence | ||
hcloud_network: | ||
name: "{{hcloud_network_name}}" | ||
ip_range: "10.0.0.0/16" | ||
register: network | ||
- name: verify test create network | ||
assert: | ||
that: | ||
- network is not changed | ||
|
||
- name: test update Network label | ||
hcloud_network: | ||
name: "{{hcloud_network_name}}" | ||
labels: | ||
key: value | ||
register: network | ||
- name: verify test update Network label | ||
assert: | ||
that: | ||
- network is changed | ||
- network.hcloud_network.labels.key == "value" | ||
|
||
- name: test update Network label idempotency | ||
hcloud_network: | ||
name: "{{hcloud_network_name}}" | ||
labels: | ||
key: value | ||
register: network | ||
- name: verify test update Network label idempotency | ||
assert: | ||
that: | ||
- network is not changed | ||
|
||
- name: test update Network ip range | ||
hcloud_network: | ||
name: "{{hcloud_network_name}}" | ||
ip_range: "10.0.0.0/8" | ||
register: network | ||
- name: verify test update Network ip range | ||
assert: | ||
that: | ||
- network is changed | ||
- network.hcloud_network.ip_range == "10.0.0.0/8" | ||
|
||
- name: test update Network ip range idempotency | ||
hcloud_network: | ||
name: "{{hcloud_network_name}}" | ||
ip_range: "10.0.0.0/8" | ||
register: network | ||
- name: verify test update Network ip range idempotency | ||
assert: | ||
that: | ||
- network is not changed | ||
|
||
- name: test delete Network | ||
hcloud_network: | ||
name: "{{hcloud_network_name}}" | ||
state: absent | ||
register: result | ||
- name: verify delete Network | ||
assert: | ||
that: | ||
- result is success |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
hcloud ; python_version >= '2.7' and python_version <= '3.7' # Python 2.6 and 3.8 are not supported | ||
hcloud>=1.3.0 ; python_version >= '2.7' # Python 2.6 is not supported (sanity_ok); Only hcloud >= 1.3.0 supports Networks. |