mirror of
https://github.com/ansible-collections/hetzner.hcloud
synced 2024-11-10 06:34:13 +00:00
Implement Load Balancers and Certificates and prepare release (#13)
This commit is contained in:
parent
6d83275ffa
commit
769a63ff22
50 changed files with 2817 additions and 18 deletions
|
@ -5,6 +5,7 @@ stages:
|
|||
ansible-devel-1/4:
|
||||
stage: sanity
|
||||
image: python:3.8-buster
|
||||
allow_failure: true
|
||||
except:
|
||||
- tags
|
||||
script:
|
||||
|
@ -15,6 +16,7 @@ ansible-devel-1/4:
|
|||
ansible-devel-2/4:
|
||||
stage: sanity
|
||||
image: python:3.8-buster
|
||||
allow_failure: true
|
||||
except:
|
||||
- tags
|
||||
script:
|
||||
|
@ -25,6 +27,7 @@ ansible-devel-2/4:
|
|||
ansible-devel-3/4:
|
||||
stage: sanity
|
||||
image: python:3.8-buster
|
||||
allow_failure: true
|
||||
except:
|
||||
- tags
|
||||
script:
|
||||
|
@ -35,6 +38,7 @@ ansible-devel-3/4:
|
|||
ansible-devel-4/4:
|
||||
stage: sanity
|
||||
image: python:3.8-buster
|
||||
allow_failure: true
|
||||
except:
|
||||
- tags
|
||||
script:
|
||||
|
|
25
changelogs/changelog.yaml
Normal file
25
changelogs/changelog.yaml
Normal file
|
@ -0,0 +1,25 @@
|
|||
ancestor: null
|
||||
releases:
|
||||
0.1.0:
|
||||
modules:
|
||||
- description: Create and manage cloud Floating IPs on the Hetzner Cloud.
|
||||
name: hcloud_floating_ip
|
||||
namespace: ''
|
||||
- description: Create and manage cloud Load Balancers on the Hetzner Cloud.
|
||||
name: hcloud_load_balancer
|
||||
namespace: ''
|
||||
- description: Manage the relationship between Hetzner Cloud Networks and Load
|
||||
Balancers
|
||||
name: hcloud_load_balancer_network
|
||||
namespace: ''
|
||||
- description: Create and manage the services of cloud Load Balancers on the Hetzner
|
||||
Cloud.
|
||||
name: hcloud_load_balancer_service
|
||||
namespace: ''
|
||||
- description: Manage Hetzner Cloud Load Balancer targets
|
||||
name: hcloud_load_balancer_target
|
||||
namespace: ''
|
||||
- description: Gather infos about the Hetzner Cloud Load Balancer types.
|
||||
name: hcloud_load_balancer_type_info
|
||||
namespace: ''
|
||||
release_date: '2020-06-29'
|
264
plugins/modules/hcloud_certificate.py
Normal file
264
plugins/modules/hcloud_certificate.py
Normal file
|
@ -0,0 +1,264 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2020, 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
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
"metadata_version": "1.1",
|
||||
"status": ["preview"],
|
||||
"supported_by": "community",
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: hcloud_certificate
|
||||
|
||||
short_description: Create and manage certificates on the Hetzner Cloud.
|
||||
|
||||
|
||||
description:
|
||||
- Create, update and manage certificates on the Hetzner Cloud.
|
||||
|
||||
author:
|
||||
- Lukas Kaemmerling (@lkaemmerling)
|
||||
|
||||
options:
|
||||
id:
|
||||
description:
|
||||
- The ID of the Hetzner Cloud certificate to manage.
|
||||
- Only required if no certificate I(name) is given
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- The Name of the Hetzner Cloud certificate to manage.
|
||||
- Only required if no certificate I(id) is given or a certificate does not exists.
|
||||
type: str
|
||||
labels:
|
||||
description:
|
||||
- User-defined labels (key-value pairs)
|
||||
type: dict
|
||||
certificate:
|
||||
description:
|
||||
- Certificate and chain in PEM format, in order so that each record directly certifies the one preceding.
|
||||
- Required if certificate does not exists.
|
||||
type: str
|
||||
private_key:
|
||||
description:
|
||||
- Certificate key in PEM format.
|
||||
- Required if certificate does not exists.
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- State of the certificate.
|
||||
default: present
|
||||
choices: [ absent, present ]
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- hetzner.hcloud.hcloud
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Create a basic certificate
|
||||
hcloud_certificate:
|
||||
name: my-certificate
|
||||
certificate: "ssh-rsa AAAjjk76kgf...Xt"
|
||||
private_key: "ssh-rsa AAAjjk76kgf...Xt"
|
||||
state: present
|
||||
|
||||
- name: Create a certificate with labels
|
||||
hcloud_certificate:
|
||||
name: my-certificate
|
||||
certificate: "ssh-rsa AAAjjk76kgf...Xt"
|
||||
private_key: "ssh-rsa AAAjjk76kgf...Xt"
|
||||
labels:
|
||||
key: value
|
||||
mylabel: 123
|
||||
state: present
|
||||
|
||||
- name: Ensure the certificate is absent (remove if needed)
|
||||
hcloud_certificate:
|
||||
name: my-certificate
|
||||
state: absent
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
hcloud_certificate:
|
||||
description: The certificate instance
|
||||
returned: Always
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: Numeric identifier of the certificate
|
||||
returned: always
|
||||
type: int
|
||||
sample: 1937415
|
||||
name:
|
||||
description: Name of the certificate
|
||||
returned: always
|
||||
type: str
|
||||
sample: my website cert
|
||||
fingerprint:
|
||||
description: Fingerprint of the certificate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "03:c7:55:9b:2a:d1:04:17:09:f6:d0:7f:18:34:63:d4:3e:5f"
|
||||
certificate:
|
||||
description: Certificate and chain in PEM format
|
||||
returned: always
|
||||
type: str
|
||||
sample: "-----BEGIN CERTIFICATE-----..."
|
||||
domain_names:
|
||||
description: List of Domains and Subdomains covered by the Certificate
|
||||
returned: always
|
||||
type: dict
|
||||
not_valid_before:
|
||||
description: Point in time when the Certificate becomes valid (in ISO-8601 format)
|
||||
returned: always
|
||||
type: str
|
||||
not_valid_after:
|
||||
description: Point in time when the Certificate stops being valid (in ISO-8601 format)
|
||||
returned: always
|
||||
type: str
|
||||
labels:
|
||||
description: User-defined labels (key-value pairs)
|
||||
returned: always
|
||||
type: dict
|
||||
"""
|
||||
|
||||
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.certificates.domain import Certificate
|
||||
from hcloud.certificates.domain import Server
|
||||
from hcloud import APIException
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class AnsibleHcloudCertificate(Hcloud):
|
||||
def __init__(self, module):
|
||||
Hcloud.__init__(self, module, "hcloud_certificate")
|
||||
self.hcloud_certificate = None
|
||||
|
||||
def _prepare_result(self):
|
||||
return {
|
||||
"id": to_native(self.hcloud_certificate.id),
|
||||
"name": to_native(self.hcloud_certificate.name),
|
||||
"fingerprint": to_native(self.hcloud_certificate.fingerprint),
|
||||
"certificate": to_native(self.hcloud_certificate.certificate),
|
||||
"not_valid_before": to_native(self.hcloud_certificate.not_valid_before),
|
||||
"not_valid_after": to_native(self.hcloud_certificate.not_valid_after),
|
||||
"domain_names": [to_native(domain) for domain in self.hcloud_certificate.domain_names],
|
||||
"labels": self.hcloud_certificate.labels
|
||||
}
|
||||
|
||||
def _get_certificate(self):
|
||||
try:
|
||||
if self.module.params.get("id") is not None:
|
||||
self.hcloud_certificate = self.client.certificates.get_by_id(
|
||||
self.module.params.get("id")
|
||||
)
|
||||
elif self.module.params.get("name") is not None:
|
||||
self.hcloud_certificate = self.client.certificates.get_by_name(
|
||||
self.module.params.get("name")
|
||||
)
|
||||
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
def _create_certificate(self):
|
||||
self.module.fail_on_missing_params(
|
||||
required_params=["name", "certificate", "private_key"]
|
||||
)
|
||||
params = {
|
||||
"name": self.module.params.get("name"),
|
||||
"certificate": self.module.params.get("certificate"),
|
||||
"private_key": self.module.params.get("private_key"),
|
||||
"labels": self.module.params.get("labels")
|
||||
}
|
||||
|
||||
if not self.module.check_mode:
|
||||
try:
|
||||
self.client.certificates.create(**params)
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
self._mark_as_changed()
|
||||
self._get_certificate()
|
||||
|
||||
def _update_certificate(self):
|
||||
name = self.module.params.get("name")
|
||||
if name is not None and self.hcloud_certificate.name != name:
|
||||
self.module.fail_on_missing_params(
|
||||
required_params=["id"]
|
||||
)
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_certificate.update(name=name)
|
||||
self._mark_as_changed()
|
||||
|
||||
labels = self.module.params.get("labels")
|
||||
if labels is not None and self.hcloud_certificate.labels != labels:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_certificate.update(labels=labels)
|
||||
self._mark_as_changed()
|
||||
|
||||
self._get_certificate()
|
||||
|
||||
def present_certificate(self):
|
||||
self._get_certificate()
|
||||
if self.hcloud_certificate is None:
|
||||
self._create_certificate()
|
||||
else:
|
||||
self._update_certificate()
|
||||
|
||||
def delete_certificate(self):
|
||||
self._get_certificate()
|
||||
if self.hcloud_certificate is not None:
|
||||
if not self.module.check_mode:
|
||||
self.client.certificates.delete(self.hcloud_certificate)
|
||||
self._mark_as_changed()
|
||||
self.hcloud_certificate = None
|
||||
|
||||
@staticmethod
|
||||
def define_module():
|
||||
return AnsibleModule(
|
||||
argument_spec=dict(
|
||||
id={"type": "int"},
|
||||
name={"type": "str"},
|
||||
certificate={"type": "str"},
|
||||
private_key={"type": "str"},
|
||||
labels={"type": "dict"},
|
||||
state={
|
||||
"choices": ["absent", "present"],
|
||||
"default": "present",
|
||||
},
|
||||
**Hcloud.base_module_arguments()
|
||||
),
|
||||
required_one_of=[['id', 'name']],
|
||||
required_if=[['state', 'present', ['name']]],
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleHcloudCertificate.define_module()
|
||||
|
||||
hcloud = AnsibleHcloudCertificate(module)
|
||||
state = module.params.get("state")
|
||||
if state == "absent":
|
||||
hcloud.delete_certificate()
|
||||
elif state == "present":
|
||||
hcloud.present_certificate()
|
||||
|
||||
module.exit_json(**hcloud.get_result())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
173
plugins/modules/hcloud_certificate_info.py
Normal file
173
plugins/modules/hcloud_certificate_info.py
Normal file
|
@ -0,0 +1,173 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2020, 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
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
"metadata_version": "1.1",
|
||||
"status": ["preview"],
|
||||
"supported_by": "community",
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: hcloud_certificate_info
|
||||
short_description: Gather infos about your Hetzner Cloud certificates.
|
||||
description:
|
||||
- Gather facts about your Hetzner Cloud certificates.
|
||||
author:
|
||||
- Lukas Kaemmerling (@LKaemmerling)
|
||||
options:
|
||||
id:
|
||||
description:
|
||||
- The ID of the certificate you want to get.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- The name of the certificate you want to get.
|
||||
type: str
|
||||
label_selector:
|
||||
description:
|
||||
- The label selector for the certificate you want to get.
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- hetzner.hcloud.hcloud
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Gather hcloud certificate infos
|
||||
hcloud_certificate_info:
|
||||
register: output
|
||||
- name: Print the gathered infos
|
||||
debug:
|
||||
var: output.hcloud_certificate_info
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
hcloud_certificate_info:
|
||||
description: The certificate instances
|
||||
returned: Always
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: Numeric identifier of the certificate
|
||||
returned: always
|
||||
type: int
|
||||
sample: 1937415
|
||||
name:
|
||||
description: Name of the certificate
|
||||
returned: always
|
||||
type: str
|
||||
sample: my website cert
|
||||
fingerprint:
|
||||
description: Fingerprint of the certificate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "03:c7:55:9b:2a:d1:04:17:09:f6:d0:7f:18:34:63:d4:3e:5f"
|
||||
certificate:
|
||||
description: Certificate and chain in PEM format
|
||||
returned: always
|
||||
type: str
|
||||
sample: "-----BEGIN CERTIFICATE-----..."
|
||||
domain_names:
|
||||
description: List of Domains and Subdomains covered by the Certificate
|
||||
returned: always
|
||||
type: dict
|
||||
not_valid_before:
|
||||
description: Point in time when the Certificate becomes valid (in ISO-8601 format)
|
||||
returned: always
|
||||
type: str
|
||||
not_valid_after:
|
||||
description: Point in time when the Certificate stops being valid (in ISO-8601 format)
|
||||
returned: always
|
||||
type: str
|
||||
labels:
|
||||
description: User-defined labels (key-value pairs)
|
||||
returned: always
|
||||
type: dict
|
||||
"""
|
||||
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:
|
||||
pass
|
||||
|
||||
|
||||
class AnsibleHcloudCertificateInfo(Hcloud):
|
||||
def __init__(self, module):
|
||||
Hcloud.__init__(self, module, "hcloud_certificate_info")
|
||||
self.hcloud_certificate_info = None
|
||||
|
||||
def _prepare_result(self):
|
||||
certificates = []
|
||||
|
||||
for certificate in self.hcloud_certificate_info:
|
||||
if certificate:
|
||||
certificates.append({
|
||||
"id": to_native(certificate.id),
|
||||
"name": to_native(certificate.name),
|
||||
"fingerprint": to_native(certificate.fingerprint),
|
||||
"certificate": to_native(certificate.certificate),
|
||||
"not_valid_before": to_native(certificate.not_valid_before),
|
||||
"not_valid_after": to_native(certificate.not_valid_after),
|
||||
"domain_names": [to_native(domain) for domain in certificate.domain_names],
|
||||
"labels": certificate.labels
|
||||
})
|
||||
return certificates
|
||||
|
||||
def get_certificates(self):
|
||||
try:
|
||||
if self.module.params.get("id") is not None:
|
||||
self.hcloud_certificate_info = [self.client.certificates.get_by_id(
|
||||
self.module.params.get("id")
|
||||
)]
|
||||
elif self.module.params.get("name") is not None:
|
||||
self.hcloud_certificate_info = [self.client.certificates.get_by_name(
|
||||
self.module.params.get("name")
|
||||
)]
|
||||
elif self.module.params.get("label_selector") is not None:
|
||||
self.hcloud_certificate_info = self.client.certificates.get_all(
|
||||
label_selector=self.module.params.get("label_selector"))
|
||||
else:
|
||||
self.hcloud_certificate_info = self.client.certificates.get_all()
|
||||
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
@staticmethod
|
||||
def define_module():
|
||||
return AnsibleModule(
|
||||
argument_spec=dict(
|
||||
id={"type": "int"},
|
||||
name={"type": "str"},
|
||||
label_selector={"type": "str"},
|
||||
**Hcloud.base_module_arguments()
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleHcloudCertificateInfo.define_module()
|
||||
|
||||
hcloud = AnsibleHcloudCertificateInfo(module)
|
||||
hcloud.get_certificates()
|
||||
result = hcloud.get_result()
|
||||
|
||||
ansible_info = {
|
||||
'hcloud_certificate_info': result['hcloud_certificate_info']
|
||||
}
|
||||
module.exit_json(**ansible_info)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -20,7 +20,7 @@ description:
|
|||
|
||||
author:
|
||||
- Lukas Kaemmerling (@lkaemmerling)
|
||||
|
||||
version_added: 0.1.0
|
||||
options:
|
||||
id:
|
||||
description:
|
||||
|
@ -155,7 +155,7 @@ hcloud_floating_ip:
|
|||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
labels:
|
||||
description: User-defined labels (key-value pairs)
|
||||
type: dict
|
||||
|
|
|
@ -61,7 +61,7 @@ hcloud_floating_ip_info:
|
|||
returned: Always
|
||||
type: str
|
||||
sample: my-floating-ip
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
description:
|
||||
description: Description of the Floating IP
|
||||
returned: always
|
||||
|
@ -91,7 +91,7 @@ hcloud_floating_ip_info:
|
|||
description: True if the Floating IP is protected for deletion
|
||||
returned: always
|
||||
type: bool
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
labels:
|
||||
description: User-defined labels (key-value pairs)
|
||||
returned: always
|
||||
|
|
307
plugins/modules/hcloud_load_balancer.py
Normal file
307
plugins/modules/hcloud_load_balancer.py
Normal file
|
@ -0,0 +1,307 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2020, 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_load_balancer
|
||||
|
||||
short_description: Create and manage cloud Load Balancers on the Hetzner Cloud.
|
||||
|
||||
|
||||
description:
|
||||
- Create, update and manage cloud Load Balancers on the Hetzner Cloud.
|
||||
|
||||
author:
|
||||
- Lukas Kaemmerling (@LKaemmerling)
|
||||
version_added: 0.1.0
|
||||
options:
|
||||
id:
|
||||
description:
|
||||
- The ID of the Hetzner Cloud Load Balancer to manage.
|
||||
- Only required if no Load Balancer I(name) is given
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- The Name of the Hetzner Cloud Load Balancer to manage.
|
||||
- Only required if no Load Balancer I(id) is given or a Load Balancer does not exists.
|
||||
type: str
|
||||
load_balancer_type:
|
||||
description:
|
||||
- The Load Balancer Type of the Hetzner Cloud Load Balancer to manage.
|
||||
- Required if Load Balancer does not exists.
|
||||
type: str
|
||||
location:
|
||||
description:
|
||||
- Location of Load Balancer.
|
||||
- Required if no I(network_zone) is given and Load Balancer does not exists.
|
||||
type: str
|
||||
network_zone:
|
||||
description:
|
||||
- Network Zone of Load Balancer.
|
||||
- Required of no I(location) is given and Load Balancer does not exists.
|
||||
type: str
|
||||
labels:
|
||||
description:
|
||||
- User-defined labels (key-value pairs).
|
||||
type: dict
|
||||
disable_public_interface:
|
||||
description:
|
||||
- Disables the public interface.
|
||||
type: bool
|
||||
default: False
|
||||
delete_protection:
|
||||
description:
|
||||
- Protect the Load Balancer for deletion.
|
||||
type: bool
|
||||
state:
|
||||
description:
|
||||
- State of the Load Balancer.
|
||||
default: present
|
||||
choices: [ absent, present ]
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- hetzner.hcloud.hcloud
|
||||
|
||||
requirements:
|
||||
- hcloud-python >= 1.8.0
|
||||
'''
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Create a basic Load Balancer
|
||||
hcloud_load_balancer:
|
||||
name: my-Load Balancer
|
||||
load_balancer_type: lb11
|
||||
location: fsn1
|
||||
state: present
|
||||
|
||||
- name: Ensure the Load Balancer is absent (remove if needed)
|
||||
hcloud_load_balancer:
|
||||
name: my-Load Balancer
|
||||
state: absent
|
||||
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
hcloud_load_balancer:
|
||||
description: The Load Balancer instance
|
||||
returned: Always
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: Numeric identifier of the Load Balancer
|
||||
returned: always
|
||||
type: int
|
||||
sample: 1937415
|
||||
name:
|
||||
description: Name of the Load Balancer
|
||||
returned: always
|
||||
type: str
|
||||
sample: my-Load-Balancer
|
||||
status:
|
||||
description: Status of the Load Balancer
|
||||
returned: always
|
||||
type: str
|
||||
sample: running
|
||||
load_balancer_type:
|
||||
description: Name of the Load Balancer type of the Load Balancer
|
||||
returned: always
|
||||
type: str
|
||||
sample: cx11
|
||||
ipv4_address:
|
||||
description: Public IPv4 address of the Load Balancer
|
||||
returned: always
|
||||
type: str
|
||||
sample: 116.203.104.109
|
||||
ipv6_address:
|
||||
description: Public IPv6 address of the Load Balancer
|
||||
returned: always
|
||||
type: str
|
||||
sample: 2a01:4f8:1c1c:c140::1
|
||||
location:
|
||||
description: Name of the location of the Load Balancer
|
||||
returned: always
|
||||
type: str
|
||||
sample: fsn1
|
||||
labels:
|
||||
description: User-defined labels (key-value pairs)
|
||||
returned: always
|
||||
type: dict
|
||||
delete_protection:
|
||||
description: True if Load Balancer is protected for deletion
|
||||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
disable_public_interface:
|
||||
description: True if Load Balancer public interface is disabled
|
||||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
"""
|
||||
|
||||
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.load_balancers.domain import LoadBalancer
|
||||
from hcloud import APIException
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class AnsibleHcloudLoadBalancer(Hcloud):
|
||||
def __init__(self, module):
|
||||
Hcloud.__init__(self, module, "hcloud_load_balancer")
|
||||
self.hcloud_load_balancer = None
|
||||
|
||||
def _prepare_result(self):
|
||||
private_ipv4_address = None if len(self.hcloud_load_balancer.private_net) == 0 else to_native(
|
||||
self.hcloud_load_balancer.private_net[0].ip)
|
||||
return {
|
||||
"id": to_native(self.hcloud_load_balancer.id),
|
||||
"name": to_native(self.hcloud_load_balancer.name),
|
||||
"ipv4_address": to_native(self.hcloud_load_balancer.public_net.ipv4.ip),
|
||||
"ipv6_address": to_native(self.hcloud_load_balancer.public_net.ipv6.ip),
|
||||
"private_ipv4_address": private_ipv4_address,
|
||||
"load_balancer_type": to_native(self.hcloud_load_balancer.load_balancer_type.name),
|
||||
"location": to_native(self.hcloud_load_balancer.location.name),
|
||||
"labels": self.hcloud_load_balancer.labels,
|
||||
"delete_protection": self.hcloud_load_balancer.protection["delete"],
|
||||
"disable_public_interface": self.hcloud_load_balancer.public_net.enabled
|
||||
}
|
||||
|
||||
def _get_load_balancer(self):
|
||||
try:
|
||||
if self.module.params.get("id") is not None:
|
||||
self.hcloud_load_balancer = self.client.load_balancers.get_by_id(
|
||||
self.module.params.get("id")
|
||||
)
|
||||
else:
|
||||
self.hcloud_load_balancer = self.client.load_balancers.get_by_name(
|
||||
self.module.params.get("name")
|
||||
)
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
def _create_load_balancer(self):
|
||||
|
||||
self.module.fail_on_missing_params(
|
||||
required_params=["name", "load_balancer_type"]
|
||||
)
|
||||
|
||||
params = {
|
||||
"name": self.module.params.get("name"),
|
||||
"load_balancer_type": self.client.load_balancer_types.get_by_name(
|
||||
self.module.params.get("load_balancer_type")
|
||||
),
|
||||
"labels": self.module.params.get("labels"),
|
||||
}
|
||||
|
||||
if self.module.params.get("location") is None and self.module.params.get("network_zone") is None:
|
||||
self.module.fail_json(msg="one of the following is required: location, network_zone")
|
||||
elif self.module.params.get("location") is not None and self.module.params.get("network_zone") is None:
|
||||
params["location"] = self.client.locations.get_by_name(
|
||||
self.module.params.get("location")
|
||||
)
|
||||
elif self.module.params.get("location") is None and self.module.params.get("network_zone") is not None:
|
||||
params["network_zone"] = self.module.params.get("network_zone")
|
||||
|
||||
if not self.module.check_mode:
|
||||
resp = self.client.load_balancers.create(**params)
|
||||
resp.action.wait_until_finished(max_retries=1000)
|
||||
|
||||
self._mark_as_changed()
|
||||
self._get_load_balancer()
|
||||
self._update_load_balancer()
|
||||
|
||||
def _update_load_balancer(self):
|
||||
try:
|
||||
labels = self.module.params.get("labels")
|
||||
if labels is not None and labels != self.hcloud_load_balancer.labels:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_load_balancer.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_load_balancer.protection["delete"]:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_load_balancer.change_protection(delete=delete_protection).wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
self._get_load_balancer()
|
||||
|
||||
disable_public_interface = self.module.params.get("disable_public_interface")
|
||||
if disable_public_interface is not None and disable_public_interface != self.hcloud_load_balancer.public_net.enabled:
|
||||
if not self.module.check_mode:
|
||||
if disable_public_interface is True:
|
||||
self.hcloud_load_balancer.disable_public_interface().wait_until_finished()
|
||||
else:
|
||||
self.hcloud_load_balancer.enable_public_interface().wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
self._get_load_balancer()
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
def present_load_balancer(self):
|
||||
self._get_load_balancer()
|
||||
if self.hcloud_load_balancer is None:
|
||||
self._create_load_balancer()
|
||||
else:
|
||||
self._update_load_balancer()
|
||||
|
||||
def delete_load_balancer(self):
|
||||
try:
|
||||
self._get_load_balancer()
|
||||
if self.hcloud_load_balancer is not None:
|
||||
if not self.module.check_mode:
|
||||
self.client.load_balancers.delete(self.hcloud_load_balancer)
|
||||
self._mark_as_changed()
|
||||
self.hcloud_load_balancer = None
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
@staticmethod
|
||||
def define_module():
|
||||
return AnsibleModule(
|
||||
argument_spec=dict(
|
||||
id={"type": "int"},
|
||||
name={"type": "str"},
|
||||
load_balancer_type={"type": "str"},
|
||||
location={"type": "str"},
|
||||
network_zone={"type": "str"},
|
||||
labels={"type": "dict"},
|
||||
delete_protection={"type": "bool"},
|
||||
disable_public_interface={"type": "bool", "default": False},
|
||||
state={
|
||||
"choices": ["absent", "present"],
|
||||
"default": "present",
|
||||
},
|
||||
**Hcloud.base_module_arguments()
|
||||
),
|
||||
required_one_of=[['id', 'name']],
|
||||
mutually_exclusive=[["location", "network_zone"]],
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleHcloudLoadBalancer.define_module()
|
||||
|
||||
hcloud = AnsibleHcloudLoadBalancer(module)
|
||||
state = module.params.get("state")
|
||||
if state == "absent":
|
||||
hcloud.delete_load_balancer()
|
||||
elif state == "present":
|
||||
hcloud.present_load_balancer()
|
||||
|
||||
module.exit_json(**hcloud.get_result())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
201
plugins/modules/hcloud_load_balancer_network.py
Normal file
201
plugins/modules/hcloud_load_balancer_network.py
Normal file
|
@ -0,0 +1,201 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2020, 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_load_balancer_network
|
||||
|
||||
short_description: Manage the relationship between Hetzner Cloud Networks and Load Balancers
|
||||
|
||||
|
||||
description:
|
||||
- Create and delete the relationship Hetzner Cloud Networks and Load Balancers
|
||||
|
||||
author:
|
||||
- Lukas Kaemmerling (@lkaemmerling)
|
||||
version_added: 0.1.0
|
||||
options:
|
||||
network:
|
||||
description:
|
||||
- The name of the Hetzner Cloud Networks.
|
||||
type: str
|
||||
required: true
|
||||
load_balancer:
|
||||
description:
|
||||
- The name of the Hetzner Cloud Load Balancer.
|
||||
type: str
|
||||
required: true
|
||||
ip:
|
||||
description:
|
||||
- The IP the Load Balancer should have.
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- State of the load_balancer_network.
|
||||
default: present
|
||||
choices: [ absent, present ]
|
||||
type: str
|
||||
|
||||
requirements:
|
||||
- hcloud-python >= 1.8.1
|
||||
|
||||
extends_documentation_fragment:
|
||||
- hetzner.hcloud.hcloud
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Create a basic Load Balancer network
|
||||
hcloud_load_balancer_network:
|
||||
network: my-network
|
||||
load_balancer: my-LoadBalancer
|
||||
state: present
|
||||
|
||||
- name: Create a Load Balancer network and specify the ip address
|
||||
hcloud_load_balancer_network:
|
||||
network: my-network
|
||||
load_balancer: my-LoadBalancer
|
||||
ip: 10.0.0.1
|
||||
state: present
|
||||
|
||||
- name: Ensure the Load Balancer network is absent (remove if needed)
|
||||
hcloud_load_balancer_network:
|
||||
network: my-network
|
||||
load_balancer: my-LoadBalancer
|
||||
state: absent
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
hcloud_load_balancer_network:
|
||||
description: The relationship between a Load Balancer and a network
|
||||
returned: always
|
||||
type: complex
|
||||
contains:
|
||||
network:
|
||||
description: Name of the Network
|
||||
type: str
|
||||
returned: always
|
||||
sample: my-network
|
||||
load_balancer:
|
||||
description: Name of the Load Balancer
|
||||
type: str
|
||||
returned: always
|
||||
sample: my-LoadBalancer
|
||||
ip:
|
||||
description: IP of the Load Balancer within the Network ip range
|
||||
type: str
|
||||
returned: always
|
||||
sample: 10.0.0.8
|
||||
"""
|
||||
|
||||
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
|
||||
NetworkSubnet = None
|
||||
|
||||
|
||||
class AnsibleHcloudLoadBalancerNetwork(Hcloud):
|
||||
def __init__(self, module):
|
||||
super(AnsibleHcloudLoadBalancerNetwork, self).__init__(module, "hcloud_load_balancer_network")
|
||||
self.hcloud_network = None
|
||||
self.hcloud_load_balancer = None
|
||||
self.hcloud_load_balancer_network = None
|
||||
|
||||
def _prepare_result(self):
|
||||
return {
|
||||
"network": to_native(self.hcloud_network.name),
|
||||
"load_balancer": to_native(self.hcloud_load_balancer.name),
|
||||
"ip": to_native(self.hcloud_load_balancer_network.ip),
|
||||
}
|
||||
|
||||
def _get_load_balancer_and_network(self):
|
||||
try:
|
||||
self.hcloud_network = self.client.networks.get_by_name(self.module.params.get("network"))
|
||||
self.hcloud_load_balancer = self.client.load_balancers.get_by_name(self.module.params.get("load_balancer"))
|
||||
self.hcloud_load_balancer_network = None
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
def _get_load_balancer_network(self):
|
||||
for privateNet in self.hcloud_load_balancer.private_net:
|
||||
if privateNet.network.id == self.hcloud_network.id:
|
||||
self.hcloud_load_balancer_network = privateNet
|
||||
|
||||
def _create_load_balancer_network(self):
|
||||
params = {
|
||||
"network": self.hcloud_network
|
||||
}
|
||||
|
||||
if self.module.params.get("ip") is not None:
|
||||
params["ip"] = self.module.params.get("ip")
|
||||
|
||||
if not self.module.check_mode:
|
||||
try:
|
||||
self.hcloud_load_balancer.attach_to_network(**params).wait_until_finished()
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
self._mark_as_changed()
|
||||
self._get_load_balancer_and_network()
|
||||
self._get_load_balancer_network()
|
||||
|
||||
def present_load_balancer_network(self):
|
||||
self._get_load_balancer_and_network()
|
||||
self._get_load_balancer_network()
|
||||
if self.hcloud_load_balancer_network is None:
|
||||
self._create_load_balancer_network()
|
||||
|
||||
def delete_load_balancer_network(self):
|
||||
self._get_load_balancer_and_network()
|
||||
self._get_load_balancer_network()
|
||||
if self.hcloud_load_balancer_network is not None and self.hcloud_load_balancer is not None:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_load_balancer.detach_from_network(
|
||||
self.hcloud_load_balancer_network.network).wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
self.hcloud_load_balancer_network = None
|
||||
|
||||
@staticmethod
|
||||
def define_module():
|
||||
return AnsibleModule(
|
||||
argument_spec=dict(
|
||||
network={"type": "str", "required": True},
|
||||
load_balancer={"type": "str", "required": True},
|
||||
ip={"type": "str"},
|
||||
state={
|
||||
"choices": ["absent", "present"],
|
||||
"default": "present",
|
||||
},
|
||||
**Hcloud.base_module_arguments()
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleHcloudLoadBalancerNetwork.define_module()
|
||||
|
||||
hcloud = AnsibleHcloudLoadBalancerNetwork(module)
|
||||
state = module.params["state"]
|
||||
if state == "absent":
|
||||
hcloud.delete_load_balancer_network()
|
||||
elif state == "present":
|
||||
hcloud.present_load_balancer_network()
|
||||
|
||||
module.exit_json(**hcloud.get_result())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
609
plugins/modules/hcloud_load_balancer_service.py
Normal file
609
plugins/modules/hcloud_load_balancer_service.py
Normal file
|
@ -0,0 +1,609 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2020, 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_load_balancer_service
|
||||
|
||||
short_description: Create and manage the services of cloud Load Balancers on the Hetzner Cloud.
|
||||
|
||||
|
||||
description:
|
||||
- Create, update and manage the services of cloud Load Balancers on the Hetzner Cloud.
|
||||
|
||||
author:
|
||||
- Lukas Kaemmerling (@LKaemmerling)
|
||||
version_added: 0.1.0
|
||||
options:
|
||||
load_balancer:
|
||||
description:
|
||||
- The Name of the Hetzner Cloud Load Balancer the service belongs to
|
||||
type: str
|
||||
required: true
|
||||
listen_port:
|
||||
description:
|
||||
- The port the service listens on, i.e. the port users can connect to.
|
||||
type: int
|
||||
required: true
|
||||
destination_port:
|
||||
description:
|
||||
- The port traffic is forwarded to, i.e. the port the targets are listening and accepting connections on.
|
||||
- Required if services does not exists and protocol is tcp.
|
||||
type: int
|
||||
protocol:
|
||||
description:
|
||||
- Protocol of the service.
|
||||
- Required if Load Balancer does not exists.
|
||||
type: str
|
||||
choices: [ http, https, tcp ]
|
||||
proxyprotocol:
|
||||
description:
|
||||
- Enable the PROXY protocol.
|
||||
type: bool
|
||||
http:
|
||||
description:
|
||||
- Configuration for HTTP and HTTPS services
|
||||
type: dict
|
||||
suboptions:
|
||||
cookie_name:
|
||||
description:
|
||||
- Name of the cookie which will be set when you enable sticky sessions
|
||||
type: str
|
||||
cookie_lifetime:
|
||||
description:
|
||||
- Lifetime of the cookie which will be set when you enable sticky sessions, in seconds
|
||||
type: int
|
||||
certificates:
|
||||
description:
|
||||
- List of Names or IDs of certificates
|
||||
type: list
|
||||
elements: str
|
||||
sticky_sessions:
|
||||
description:
|
||||
- Enable or disable sticky_sessions
|
||||
type: bool
|
||||
redirect_http:
|
||||
description:
|
||||
- Redirect Traffic from Port 80 to Port 443, only available if protocol is https
|
||||
type: bool
|
||||
health_check:
|
||||
description:
|
||||
- Configuration for health checks
|
||||
type: dict
|
||||
suboptions:
|
||||
protocol:
|
||||
description:
|
||||
- Protocol the health checks will be performed over
|
||||
type: str
|
||||
choices: [ http, https, tcp ]
|
||||
port:
|
||||
description:
|
||||
- Port the health check will be performed on
|
||||
type: int
|
||||
interval:
|
||||
description:
|
||||
- Interval of health checks, in seconds
|
||||
type: int
|
||||
timeout:
|
||||
description:
|
||||
- Timeout of health checks, in seconds
|
||||
type: int
|
||||
retries:
|
||||
description:
|
||||
- Number of retries until a target is marked as unhealthy
|
||||
type: int
|
||||
http:
|
||||
description:
|
||||
- Additional Configuration of health checks with protocol http/https
|
||||
type: dict
|
||||
suboptions:
|
||||
domain:
|
||||
description:
|
||||
- Domain we will set within the HTTP HOST header
|
||||
type: str
|
||||
path:
|
||||
description:
|
||||
- Path we will try to access
|
||||
type: str
|
||||
response:
|
||||
description:
|
||||
- Response we expect, if response is not within the health check response the target is unhealthy
|
||||
type: str
|
||||
status_codes:
|
||||
description:
|
||||
- List of HTTP status codes we expect to get when we perform the health check.
|
||||
type: list
|
||||
elements: str
|
||||
tls:
|
||||
description:
|
||||
- Verify the TLS certificate, only available if health check protocol is https
|
||||
type: bool
|
||||
state:
|
||||
description:
|
||||
- State of the Load Balancer.
|
||||
default: present
|
||||
choices: [ absent, present ]
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- hetzner.hcloud.hcloud
|
||||
|
||||
requirements:
|
||||
- hcloud-python >= 1.8.1
|
||||
'''
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Create a basic Load Balancer service with Port 80
|
||||
hcloud_load_balancer_service:
|
||||
load_balancer: my-load-balancer
|
||||
protocol: http
|
||||
listen_port: 80
|
||||
state: present
|
||||
|
||||
- name: Ensure the Load Balancer is absent (remove if needed)
|
||||
hcloud_load_balancer_service:
|
||||
load_balancer: my-Load Balancer
|
||||
protocol: http
|
||||
listen_port: 80
|
||||
state: absent
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
hcloud_load_balancer_service:
|
||||
description: The Load Balancer service instance
|
||||
returned: Always
|
||||
type: complex
|
||||
contains:
|
||||
load_balancer:
|
||||
description: The name of the Load Balancer where the service belongs to
|
||||
returned: always
|
||||
type: str
|
||||
sample: my-load-balancer
|
||||
listen_port:
|
||||
description: The port the service listens on, i.e. the port users can connect to.
|
||||
returned: always
|
||||
type: int
|
||||
sample: 443
|
||||
protocol:
|
||||
description: Protocol of the service
|
||||
returned: always
|
||||
type: str
|
||||
sample: http
|
||||
destination_port:
|
||||
description:
|
||||
- The port traffic is forwarded to, i.e. the port the targets are listening and accepting connections on.
|
||||
returned: always
|
||||
type: int
|
||||
sample: 80
|
||||
proxyprotocol:
|
||||
description:
|
||||
- Enable the PROXY protocol.
|
||||
returned: always
|
||||
type: bool
|
||||
sample: false
|
||||
http:
|
||||
description: Configuration for HTTP and HTTPS services
|
||||
returned: always
|
||||
type: complex
|
||||
contains:
|
||||
cookie_name:
|
||||
description: Name of the cookie which will be set when you enable sticky sessions
|
||||
returned: always
|
||||
type: str
|
||||
sample: HCLBSTICKY
|
||||
cookie_lifetime:
|
||||
description: Lifetime of the cookie which will be set when you enable sticky sessions, in seconds
|
||||
returned: always
|
||||
type: int
|
||||
sample: 3600
|
||||
certificates:
|
||||
description: List of Names or IDs of certificates
|
||||
returned: always
|
||||
type: list
|
||||
elements: str
|
||||
sticky_sessions:
|
||||
description: Enable or disable sticky_sessions
|
||||
returned: always
|
||||
type: bool
|
||||
sample: true
|
||||
redirect_http:
|
||||
description: Redirect Traffic from Port 80 to Port 443, only available if protocol is https
|
||||
returned: always
|
||||
type: bool
|
||||
sample: false
|
||||
health_check:
|
||||
description: Configuration for health checks
|
||||
returned: always
|
||||
type: complex
|
||||
contains:
|
||||
protocol:
|
||||
description: Protocol the health checks will be performed over
|
||||
returned: always
|
||||
type: str
|
||||
sample: http
|
||||
port:
|
||||
description: Port the health check will be performed on
|
||||
returned: always
|
||||
type: int
|
||||
sample: 80
|
||||
interval:
|
||||
description: Interval of health checks, in seconds
|
||||
returned: always
|
||||
type: int
|
||||
sample: 15
|
||||
timeout:
|
||||
description: Timeout of health checks, in seconds
|
||||
returned: always
|
||||
type: int
|
||||
sample: 10
|
||||
retries:
|
||||
description: Number of retries until a target is marked as unhealthy
|
||||
returned: always
|
||||
type: int
|
||||
sample: 3
|
||||
http:
|
||||
description: Additional Configuration of health checks with protocol http/https
|
||||
returned: always
|
||||
type: complex
|
||||
contains:
|
||||
domain:
|
||||
description: Domain we will set within the HTTP HOST header
|
||||
returned: always
|
||||
type: str
|
||||
sample: example.com
|
||||
path:
|
||||
description: Path we will try to access
|
||||
returned: always
|
||||
type: str
|
||||
sample: /
|
||||
response:
|
||||
description: Response we expect, if response is not within the health check response the target is unhealthy
|
||||
returned: always
|
||||
type: str
|
||||
status_codes:
|
||||
description: List of HTTP status codes we expect to get when we perform the health check.
|
||||
returned: always
|
||||
type: list
|
||||
elements: str
|
||||
sample: ["2??","3??"]
|
||||
tls:
|
||||
description: Verify the TLS certificate, only available if health check protocol is https
|
||||
returned: always
|
||||
type: bool
|
||||
sample: false
|
||||
"""
|
||||
|
||||
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.load_balancers.domain import LoadBalancer, LoadBalancerService, LoadBalancerServiceHttp, \
|
||||
LoadBalancerServiceHealthCheck, LoadBalancerServiceHealthCheckHttp
|
||||
from hcloud import APIException
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class AnsibleHcloudLoadBalancerService(Hcloud):
|
||||
def __init__(self, module):
|
||||
Hcloud.__init__(self, module, "hcloud_load_balancer_service")
|
||||
self.hcloud_load_balancer = None
|
||||
self.hcloud_load_balancer_service = None
|
||||
|
||||
def _prepare_result(self):
|
||||
http = None
|
||||
if self.hcloud_load_balancer_service.protocol != "tcp":
|
||||
http = {
|
||||
"cookie_name": to_native(self.hcloud_load_balancer_service.http.cookie_name),
|
||||
"cookie_lifetime": self.hcloud_load_balancer_service.http.cookie_name,
|
||||
"redirect_http": self.hcloud_load_balancer_service.http.redirect_http,
|
||||
"sticky_sessions": self.hcloud_load_balancer_service.http.sticky_sessions,
|
||||
"certificates": [to_native(certificate.name) for certificate in
|
||||
self.hcloud_load_balancer_service.http.certificates],
|
||||
}
|
||||
health_check = {
|
||||
"protocol": to_native(self.hcloud_load_balancer_service.health_check.protocol),
|
||||
"port": self.hcloud_load_balancer_service.health_check.port,
|
||||
"interval": self.hcloud_load_balancer_service.health_check.interval,
|
||||
"timeout": self.hcloud_load_balancer_service.health_check.timeout,
|
||||
"retries": self.hcloud_load_balancer_service.health_check.retries,
|
||||
}
|
||||
if self.hcloud_load_balancer_service.health_check.protocol != "tcp":
|
||||
health_check["http"] = {
|
||||
"domain": to_native(self.hcloud_load_balancer_service.health_check.http.domain),
|
||||
"path": to_native(self.hcloud_load_balancer_service.health_check.http.path),
|
||||
"response": to_native(self.hcloud_load_balancer_service.health_check.http.response),
|
||||
"certificates": [to_native(status_code) for status_code in
|
||||
self.hcloud_load_balancer_service.health_check.http.status_codes],
|
||||
"tls": self.hcloud_load_balancer_service.health_check.tls,
|
||||
}
|
||||
return {
|
||||
"load_balancer": to_native(self.hcloud_load_balancer.name),
|
||||
"protocol": to_native(self.hcloud_load_balancer_service.protocol),
|
||||
"listen_port": self.hcloud_load_balancer_service.listen_port,
|
||||
"destination_port": self.hcloud_load_balancer_service.destination_port,
|
||||
"proxyprotocol": self.hcloud_load_balancer_service.proxyprotocol,
|
||||
"http": http,
|
||||
"health_check": health_check,
|
||||
}
|
||||
|
||||
def _get_load_balancer(self):
|
||||
try:
|
||||
self.hcloud_load_balancer = self.client.load_balancers.get_by_name(
|
||||
self.module.params.get("load_balancer")
|
||||
)
|
||||
self._get_load_balancer_service()
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
def _create_load_balancer_service(self):
|
||||
|
||||
self.module.fail_on_missing_params(
|
||||
required_params=["protocol"]
|
||||
)
|
||||
if self.module.params.get("protocol") == "tcp":
|
||||
self.module.fail_on_missing_params(
|
||||
required_params=["destination_port"]
|
||||
)
|
||||
|
||||
params = {
|
||||
"protocol": self.module.params.get("protocol"),
|
||||
"listen_port": self.module.params.get("listen_port"),
|
||||
"proxyprotocol": self.module.params.get("proxyprotocol")
|
||||
}
|
||||
|
||||
if self.module.params.get("destination_port"):
|
||||
params["destination_port"] = self.module.params.get("destination_port")
|
||||
|
||||
if self.module.params.get("http"):
|
||||
params["http"] = self.__get_service_http(http_arg=self.module.params.get("http"))
|
||||
|
||||
if self.module.params.get("health_check"):
|
||||
params["health_check"] = self.__get_service_health_checks(
|
||||
health_check=self.module.params.get("health_check"))
|
||||
|
||||
if not self.module.check_mode:
|
||||
try:
|
||||
self.hcloud_load_balancer.add_service(LoadBalancerService(**params)).wait_until_finished(
|
||||
max_retries=1000)
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
self._mark_as_changed()
|
||||
self._get_load_balancer()
|
||||
self._get_load_balancer_service()
|
||||
|
||||
def __get_service_http(self, http_arg):
|
||||
service_http = LoadBalancerServiceHttp(certificates=[])
|
||||
if http_arg.get("cookie_name") is not None:
|
||||
service_http.cookie_name = http_arg.get("cookie_name")
|
||||
if http_arg.get("cookie_lifetime") is not None:
|
||||
service_http.cookie_lifetime = http_arg.get("cookie_lifetime")
|
||||
if http_arg.get("sticky_sessions") is not None:
|
||||
service_http.sticky_sessions = http_arg.get("sticky_sessions")
|
||||
if http_arg.get("redirect_http") is not None:
|
||||
service_http.redirect_http = http_arg.get("redirect_http")
|
||||
if http_arg.get("certificates") is not None:
|
||||
certificates = http_arg.get("certificates")
|
||||
if certificates is not None:
|
||||
for certificate in certificates:
|
||||
hcloud_cert = None
|
||||
try:
|
||||
try:
|
||||
hcloud_cert = self.client.certificates.get_by_name(
|
||||
certificate
|
||||
)
|
||||
except APIException:
|
||||
hcloud_cert = self.client.certificates.get_by_id(
|
||||
certificate
|
||||
)
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
service_http.certificates.append(hcloud_cert)
|
||||
|
||||
return service_http
|
||||
|
||||
def __get_service_health_checks(self, health_check):
|
||||
service_health_check = LoadBalancerServiceHealthCheck()
|
||||
if health_check.get("protocol") is not None:
|
||||
service_health_check.protocol = health_check.get("protocol")
|
||||
if health_check.get("port") is not None:
|
||||
service_health_check.port = health_check.get("port")
|
||||
if health_check.get("interval") is not None:
|
||||
service_health_check.interval = health_check.get("interval")
|
||||
if health_check.get("timeout") is not None:
|
||||
service_health_check.timeout = health_check.get("timeout")
|
||||
if health_check.get("retries") is not None:
|
||||
service_health_check.retries = health_check.get("retries")
|
||||
if health_check.get("http") is not None:
|
||||
health_check_http = health_check.get("http")
|
||||
service_health_check.http = LoadBalancerServiceHealthCheckHttp()
|
||||
if health_check_http.get("domain") is not None:
|
||||
service_health_check.http.domain = health_check_http.get("domain")
|
||||
if health_check_http.get("path") is not None:
|
||||
service_health_check.http.path = health_check_http.get("path")
|
||||
if health_check_http.get("response") is not None:
|
||||
service_health_check.http.response = health_check_http.get("response")
|
||||
if health_check_http.get("status_codes") is not None:
|
||||
service_health_check.http.status_codes = health_check_http.get("status_codes")
|
||||
if health_check_http.get("tls") is not None:
|
||||
service_health_check.http.tls = health_check_http.get("tls")
|
||||
|
||||
return service_health_check
|
||||
|
||||
def _update_load_balancer_service(self):
|
||||
changed = False
|
||||
try:
|
||||
params = {
|
||||
"listen_port": self.module.params.get("listen_port"),
|
||||
}
|
||||
|
||||
if self.module.params.get("destination_port") is not None:
|
||||
if self.hcloud_load_balancer_service.destination_port != self.module.params.get("destination_port"):
|
||||
params["destination_port"] = self.module.params.get("destination_port")
|
||||
changed = True
|
||||
|
||||
if self.module.params.get("protocol") is not None:
|
||||
if self.hcloud_load_balancer_service.protocol != self.module.params.get("protocol"):
|
||||
params["protocol"] = self.module.params.get("protocol")
|
||||
changed = True
|
||||
|
||||
if self.module.params.get("proxyprotocol") is not None:
|
||||
if self.hcloud_load_balancer_service.proxyprotocol != self.module.params.get("proxyprotocol"):
|
||||
params["proxyprotocol"] = self.module.params.get("proxyprotocol")
|
||||
changed = True
|
||||
|
||||
if self.module.params.get("http") is not None:
|
||||
params["http"] = self.__get_service_http(http_arg=self.module.params.get("http"))
|
||||
changed = True
|
||||
|
||||
if self.module.params.get("health_check") is not None:
|
||||
params["health_check"] = self.__get_service_health_checks(
|
||||
health_check=self.module.params.get("health_check"))
|
||||
changed = True
|
||||
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_load_balancer.update_service(LoadBalancerService(**params)).wait_until_finished(
|
||||
max_retries=1000)
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
self._get_load_balancer()
|
||||
|
||||
if changed:
|
||||
self._mark_as_changed()
|
||||
|
||||
def _get_load_balancer_service(self):
|
||||
for service in self.hcloud_load_balancer.services:
|
||||
if self.module.params.get("listen_port") == service.listen_port:
|
||||
self.hcloud_load_balancer_service = service
|
||||
|
||||
def present_load_balancer_service(self):
|
||||
self._get_load_balancer()
|
||||
if self.hcloud_load_balancer_service is None:
|
||||
self._create_load_balancer_service()
|
||||
else:
|
||||
self._update_load_balancer_service()
|
||||
|
||||
def delete_load_balancer_service(self):
|
||||
try:
|
||||
self._get_load_balancer()
|
||||
if self.hcloud_load_balancer_service is not None:
|
||||
if not self.module.check_mode:
|
||||
self.hcloud_load_balancer.delete_service(self.hcloud_load_balancer_service).wait_until_finished(
|
||||
max_retries=1000)
|
||||
self._mark_as_changed()
|
||||
self.hcloud_load_balancer_service = None
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
@staticmethod
|
||||
def define_module():
|
||||
return AnsibleModule(
|
||||
argument_spec=dict(
|
||||
load_balancer={"type": "str", "required": True},
|
||||
listen_port={"type": "int", "required": True},
|
||||
destination_port={"type": "int"},
|
||||
protocol={
|
||||
"type": "str",
|
||||
"choices": ["http", "https", "tcp"],
|
||||
},
|
||||
proxyprotocol={"type": "bool", "default": False},
|
||||
http={
|
||||
"type": "dict",
|
||||
"options": dict(
|
||||
cookie_name={
|
||||
"type": "str"
|
||||
},
|
||||
cookie_lifetime={
|
||||
"type": "int"
|
||||
},
|
||||
sticky_sessions={
|
||||
"type": "bool",
|
||||
"default": False
|
||||
},
|
||||
redirect_http={
|
||||
"type": "bool",
|
||||
"default": False
|
||||
},
|
||||
certificates={
|
||||
"type": "list",
|
||||
"elements": "str"
|
||||
},
|
||||
|
||||
)
|
||||
},
|
||||
health_check={
|
||||
"type": "dict",
|
||||
"options": dict(
|
||||
protocol={
|
||||
"type": "str",
|
||||
"choices": ["http", "https", "tcp"],
|
||||
},
|
||||
port={
|
||||
"type": "int"
|
||||
},
|
||||
interval={
|
||||
"type": "int"
|
||||
},
|
||||
timeout={
|
||||
"type": "int"
|
||||
},
|
||||
retries={
|
||||
"type": "int"
|
||||
},
|
||||
http={
|
||||
"type": "dict",
|
||||
"options": dict(
|
||||
domain={
|
||||
"type": "str"
|
||||
},
|
||||
path={
|
||||
"type": "str"
|
||||
},
|
||||
response={
|
||||
"type": "str"
|
||||
},
|
||||
status_codes={
|
||||
"type": "list",
|
||||
"elements": "str"
|
||||
},
|
||||
tls={
|
||||
"type": "bool",
|
||||
"default": False
|
||||
},
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
},
|
||||
state={
|
||||
"choices": ["absent", "present"],
|
||||
"default": "present",
|
||||
},
|
||||
**Hcloud.base_module_arguments()
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleHcloudLoadBalancerService.define_module()
|
||||
|
||||
hcloud = AnsibleHcloudLoadBalancerService(module)
|
||||
state = module.params.get("state")
|
||||
if state == "absent":
|
||||
hcloud.delete_load_balancer_service()
|
||||
elif state == "present":
|
||||
hcloud.present_load_balancer_service()
|
||||
|
||||
module.exit_json(**hcloud.get_result())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
213
plugins/modules/hcloud_load_balancer_target.py
Normal file
213
plugins/modules/hcloud_load_balancer_target.py
Normal file
|
@ -0,0 +1,213 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: hcloud_load_balancer_target
|
||||
|
||||
short_description: Manage Hetzner Cloud Load Balancer targets
|
||||
|
||||
|
||||
description:
|
||||
- Create and delete Hetzner Cloud Load Balancer targets
|
||||
|
||||
author:
|
||||
- Lukas Kaemmerling (@lkaemmerling)
|
||||
version_added: 0.1.0
|
||||
options:
|
||||
type:
|
||||
description:
|
||||
- The type of the target.
|
||||
type: str
|
||||
choices: [ server ]
|
||||
required: true
|
||||
load_balancer:
|
||||
description:
|
||||
- The name of the Hetzner Cloud Load Balancer.
|
||||
type: str
|
||||
required: true
|
||||
server:
|
||||
description:
|
||||
- The name of the Hetzner Cloud Server.
|
||||
- Required if I(type) is server
|
||||
type: str
|
||||
use_private_ip:
|
||||
description:
|
||||
- Route the traffic over the private IP of the Load Balancer through a Hetzner Cloud Network.
|
||||
- Load Balancer needs to be attached to a network. See M(hetzner.hcloud.hcloud.hcloud_load_balancer_network)
|
||||
type: bool
|
||||
state:
|
||||
description:
|
||||
- State of the load_balancer_network.
|
||||
default: present
|
||||
choices: [ absent, present ]
|
||||
type: str
|
||||
|
||||
requirements:
|
||||
- hcloud-python >= 1.8.1
|
||||
|
||||
extends_documentation_fragment:
|
||||
- hetzner.hcloud.hcloud
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Create a server Load Balancer target
|
||||
hcloud_load_balancer_target:
|
||||
type: server
|
||||
load_balancer: my-LoadBalancer
|
||||
server: my-server
|
||||
state: present
|
||||
|
||||
- name: Ensure the Load Balancer target is absent (remove if needed)
|
||||
hcloud_load_balancer_target:
|
||||
type: server
|
||||
load_balancer: my-LoadBalancer
|
||||
server: my-server
|
||||
state: absent
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
hcloud_load_balancer_target:
|
||||
description: The relationship between a Load Balancer and a network
|
||||
returned: always
|
||||
type: complex
|
||||
contains:
|
||||
type:
|
||||
description: Type of the Load Balancer Target
|
||||
type: str
|
||||
returned: always
|
||||
sample: server
|
||||
load_balancer:
|
||||
description: Name of the Load Balancer
|
||||
type: str
|
||||
returned: always
|
||||
sample: my-LoadBalancer
|
||||
server:
|
||||
description: Name of the Server
|
||||
type: str
|
||||
returned: if I(type) is server
|
||||
sample: my-server
|
||||
"""
|
||||
|
||||
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
|
||||
from hcloud.load_balancers.domain import LoadBalancerTarget
|
||||
except ImportError:
|
||||
APIException = None
|
||||
|
||||
|
||||
class AnsibleHcloudLoadBalancerTarget(Hcloud):
|
||||
def __init__(self, module):
|
||||
super(AnsibleHcloudLoadBalancerTarget, self).__init__(module, "hcloud_load_balancer_target")
|
||||
self.hcloud_load_balancer = None
|
||||
self.hcloud_load_balancer_target = None
|
||||
self.hcloud_server = None
|
||||
|
||||
def _prepare_result(self):
|
||||
return {
|
||||
"type": to_native(self.hcloud_load_balancer_target.type),
|
||||
"load_balancer": to_native(self.hcloud_load_balancer.name),
|
||||
"server": to_native(self.hcloud_server.name) if self.hcloud_server else None,
|
||||
}
|
||||
|
||||
def _get_load_balancer_and_target(self):
|
||||
try:
|
||||
self.hcloud_load_balancer = self.client.load_balancers.get_by_name(self.module.params.get("load_balancer"))
|
||||
if self.module.params.get("type") == "server":
|
||||
self.hcloud_server = self.client.servers.get_by_name(self.module.params.get("server"))
|
||||
self.hcloud_load_balancer_target = None
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
def _get_load_balancer_target(self):
|
||||
for target in self.hcloud_load_balancer.targets:
|
||||
if self.module.params.get("type") == "server":
|
||||
if target.server.id == self.hcloud_server.id:
|
||||
self.hcloud_load_balancer_target = target
|
||||
|
||||
def _create_load_balancer_target(self):
|
||||
params = {
|
||||
"target": None
|
||||
}
|
||||
|
||||
if self.module.params.get("type") == "server":
|
||||
self.module.fail_on_missing_params(
|
||||
required_params=["server"]
|
||||
)
|
||||
params["target"] = LoadBalancerTarget(type=self.module.params.get("type"), server=self.hcloud_server,
|
||||
use_private_ip=self.module.params.get("use_private_ip"))
|
||||
if not self.module.check_mode:
|
||||
try:
|
||||
self.hcloud_load_balancer.add_target(**params).wait_until_finished()
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
self._mark_as_changed()
|
||||
self._get_load_balancer_and_target()
|
||||
self._get_load_balancer_target()
|
||||
|
||||
def present_load_balancer_target(self):
|
||||
self._get_load_balancer_and_target()
|
||||
self._get_load_balancer_target()
|
||||
if self.hcloud_load_balancer_target is None:
|
||||
self._create_load_balancer_target()
|
||||
|
||||
def delete_load_balancer_target(self):
|
||||
self._get_load_balancer_and_target()
|
||||
self._get_load_balancer_target()
|
||||
if self.hcloud_load_balancer_target is not None and self.hcloud_load_balancer is not None:
|
||||
if not self.module.check_mode:
|
||||
target = None
|
||||
if self.module.params.get("type") == "server":
|
||||
target = LoadBalancerTarget(type=self.module.params.get("type"),
|
||||
server=self.hcloud_server,
|
||||
use_private_ip=self.module.params.get("use_private_ip"))
|
||||
self.hcloud_load_balancer.remove_target(target).wait_until_finished()
|
||||
self._mark_as_changed()
|
||||
self.hcloud_load_balancer_target = None
|
||||
|
||||
@staticmethod
|
||||
def define_module():
|
||||
return AnsibleModule(
|
||||
argument_spec=dict(
|
||||
type={"type": "str", "required": True, "choices": ["server"]},
|
||||
load_balancer={"type": "str", "required": True},
|
||||
server={"type": "str"},
|
||||
use_private_ip={"type": "bool", "default": False},
|
||||
state={
|
||||
"choices": ["absent", "present"],
|
||||
"default": "present",
|
||||
},
|
||||
**Hcloud.base_module_arguments()
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleHcloudLoadBalancerTarget.define_module()
|
||||
|
||||
hcloud = AnsibleHcloudLoadBalancerTarget(module)
|
||||
state = module.params["state"]
|
||||
if state == "absent":
|
||||
hcloud.delete_load_balancer_target()
|
||||
elif state == "present":
|
||||
hcloud.present_load_balancer_target()
|
||||
|
||||
module.exit_json(**hcloud.get_result())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
163
plugins/modules/hcloud_load_balancer_type_info.py
Normal file
163
plugins/modules/hcloud_load_balancer_type_info.py
Normal file
|
@ -0,0 +1,163 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: hcloud_load_balancer_type_info
|
||||
|
||||
short_description: Gather infos about the Hetzner Cloud Load Balancer types.
|
||||
|
||||
|
||||
description:
|
||||
- Gather infos about your Hetzner Cloud Load Balancer types.
|
||||
|
||||
author:
|
||||
- Lukas Kaemmerling (@LKaemmerling)
|
||||
version_added: 0.1.0
|
||||
options:
|
||||
id:
|
||||
description:
|
||||
- The ID of the Load Balancer type you want to get.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- The name of the Load Balancer type you want to get.
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- hetzner.hcloud.hcloud
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Gather hcloud Load Balancer type infos
|
||||
hcloud_load_balancer_type_info:
|
||||
register: output
|
||||
|
||||
- name: Print the gathered infos
|
||||
debug:
|
||||
var: output.hcloud_load_balancer_type_info
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
hcloud_load_balancer_type_info:
|
||||
description: The Load Balancer type infos as list
|
||||
returned: always
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: Numeric identifier of the Load Balancer type
|
||||
returned: always
|
||||
type: int
|
||||
sample: 1937415
|
||||
name:
|
||||
description: Name of the Load Balancer type
|
||||
returned: always
|
||||
type: str
|
||||
sample: lb11
|
||||
description:
|
||||
description: Description of the Load Balancer type
|
||||
returned: always
|
||||
type: str
|
||||
sample: LB11
|
||||
max_connections:
|
||||
description: Number of maximum simultaneous open connections
|
||||
returned: always
|
||||
type: int
|
||||
sample: 1
|
||||
max_services:
|
||||
description: Number of services a Load Balancer of this type can have
|
||||
returned: always
|
||||
type: int
|
||||
sample: 1
|
||||
max_targets:
|
||||
description: Number of targets a single Load Balancer can have
|
||||
returned: always
|
||||
type: int
|
||||
sample: 25
|
||||
max_assigned_certificates:
|
||||
description: Number of SSL Certificates that can be assigned to a single Load Balancer
|
||||
returned: always
|
||||
type: int
|
||||
sample: 5
|
||||
"""
|
||||
|
||||
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:
|
||||
pass
|
||||
|
||||
|
||||
class AnsibleHcloudLoadBalancerTypeInfo(Hcloud):
|
||||
def __init__(self, module):
|
||||
Hcloud.__init__(self, module, "hcloud_load_balancer_type_info")
|
||||
self.hcloud_load_balancer_type_info = None
|
||||
|
||||
def _prepare_result(self):
|
||||
tmp = []
|
||||
|
||||
for load_balancer_type in self.hcloud_load_balancer_type_info:
|
||||
if load_balancer_type is not None:
|
||||
tmp.append({
|
||||
"id": to_native(load_balancer_type.id),
|
||||
"name": to_native(load_balancer_type.name),
|
||||
"description": to_native(load_balancer_type.description),
|
||||
"max_connections": load_balancer_type.max_connections,
|
||||
"max_services": load_balancer_type.max_services,
|
||||
"max_targets": load_balancer_type.max_targets,
|
||||
"max_assigned_certificates": load_balancer_type.max_assigned_certificates
|
||||
})
|
||||
return tmp
|
||||
|
||||
def get_load_balancer_types(self):
|
||||
try:
|
||||
if self.module.params.get("id") is not None:
|
||||
self.hcloud_load_balancer_type_info = [self.client.load_balancer_types.get_by_id(
|
||||
self.module.params.get("id")
|
||||
)]
|
||||
elif self.module.params.get("name") is not None:
|
||||
self.hcloud_load_balancer_type_info = [self.client.load_balancer_types.get_by_name(
|
||||
self.module.params.get("name")
|
||||
)]
|
||||
else:
|
||||
self.hcloud_load_balancer_type_info = self.client.load_balancer_types.get_all()
|
||||
|
||||
except APIException as e:
|
||||
self.module.fail_json(msg=e.message)
|
||||
|
||||
@staticmethod
|
||||
def define_module():
|
||||
return AnsibleModule(
|
||||
argument_spec=dict(
|
||||
id={"type": "int"},
|
||||
name={"type": "str"},
|
||||
**Hcloud.base_module_arguments()
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleHcloudLoadBalancerTypeInfo.define_module()
|
||||
|
||||
hcloud = AnsibleHcloudLoadBalancerTypeInfo(module)
|
||||
hcloud.get_load_balancer_types()
|
||||
result = hcloud.get_result()
|
||||
ansible_info = {
|
||||
'hcloud_load_balancer_type_info': result['hcloud_load_balancer_type_info']
|
||||
}
|
||||
module.exit_json(**ansible_info)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -100,7 +100,7 @@ hcloud_network:
|
|||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
labels:
|
||||
description: User-defined labels (key-value pairs)
|
||||
type: dict
|
||||
|
|
|
@ -173,7 +173,7 @@ hcloud_network_info:
|
|||
description: True if the network is protected for deletion
|
||||
returned: always
|
||||
type: bool
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
labels:
|
||||
description: Labels of the network
|
||||
returned: always
|
||||
|
|
|
@ -238,13 +238,13 @@ hcloud_server:
|
|||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
rebuild_protection:
|
||||
description: True if server is protected for rebuild
|
||||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
"""
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
|
|
@ -116,13 +116,13 @@ hcloud_server_info:
|
|||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
rebuild_protection:
|
||||
description: True if server is protected for rebuild
|
||||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
"""
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
|
|
@ -25,7 +25,6 @@ options:
|
|||
network:
|
||||
description:
|
||||
- The name of the Hetzner Cloud Networks.
|
||||
|
||||
type: str
|
||||
required: true
|
||||
server:
|
||||
|
|
|
@ -25,7 +25,6 @@ options:
|
|||
network:
|
||||
description:
|
||||
- The ID or Name of the Hetzner Cloud Networks.
|
||||
|
||||
type: str
|
||||
required: true
|
||||
ip_range:
|
||||
|
|
|
@ -134,7 +134,7 @@ hcloud_volume:
|
|||
returned: always
|
||||
type: str
|
||||
sample: /dev/disk/by-id/scsi-0HC_Volume_12345
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
location:
|
||||
description: Location name where the Volume is located at
|
||||
type: str
|
||||
|
@ -157,7 +157,7 @@ hcloud_volume:
|
|||
type: bool
|
||||
returned: always
|
||||
sample: false
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
"""
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
|
|
@ -73,7 +73,7 @@ hcloud_volume_info:
|
|||
returned: always
|
||||
type: str
|
||||
sample: /dev/disk/by-id/scsi-0HC_Volume_12345
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
location:
|
||||
description: Name of the location where the Volume resides in
|
||||
returned: always
|
||||
|
@ -88,7 +88,7 @@ hcloud_volume_info:
|
|||
description: True if the Volume is protected for deletion
|
||||
returned: always
|
||||
type: bool
|
||||
version_added: "1.0.0"
|
||||
version_added: "0.1.0"
|
||||
labels:
|
||||
description: User-defined labels (key-value pairs)
|
||||
returned: always
|
||||
|
|
2
tests/integration/targets/hcloud_certificate/aliases
Normal file
2
tests/integration/targets/hcloud_certificate/aliases
Normal file
|
@ -0,0 +1,2 @@
|
|||
cloud/hcloud
|
||||
shippable/hcloud/group2
|
|
@ -0,0 +1,5 @@
|
|||
# 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_certificate_name: "{{hcloud_prefix}}-integration"
|
|
@ -0,0 +1,5 @@
|
|||
dependencies:
|
||||
- setup_selfsigned_certificate
|
||||
collections:
|
||||
- community.general.ipfilter
|
||||
- hetzner.cloud
|
123
tests/integration/targets/hcloud_certificate/tasks/main.yml
Normal file
123
tests/integration/targets/hcloud_certificate/tasks/main.yml
Normal file
|
@ -0,0 +1,123 @@
|
|||
# Copyright: (c) 2020, 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 missing required parameters on create certificate
|
||||
hcloud_certificate:
|
||||
name: "{{ hcloud_certificate_name }}"
|
||||
register: result
|
||||
ignore_errors: yes
|
||||
- name: verify fail test missing required parameters on create certificate
|
||||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- 'result.msg == "missing required arguments: certificate, private_key"'
|
||||
|
||||
- name: test create certificate with check mode
|
||||
hcloud_certificate:
|
||||
name: "{{ hcloud_certificate_name }}"
|
||||
certificate: "{{ certificate_example_com }}"
|
||||
private_key: "{{ certificate_example_com_key }}"
|
||||
register: result
|
||||
check_mode: yes
|
||||
- name: test create certificate with check mode
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test create certificate
|
||||
hcloud_certificate:
|
||||
name: "{{ hcloud_certificate_name }}"
|
||||
certificate: "{{ certificate_example_com }}"
|
||||
private_key: "{{ certificate_example_com_key }}"
|
||||
labels:
|
||||
key: value
|
||||
my-label: label
|
||||
register: certificate
|
||||
- name: verify create certificate
|
||||
assert:
|
||||
that:
|
||||
- certificate is changed
|
||||
- certificate.hcloud_certificate.name == "{{ hcloud_certificate_name }}"
|
||||
- certificate.hcloud_certificate.domain_names[0] == "www.example.com"
|
||||
- certificate.hcloud_certificate.labels.key == "value"
|
||||
|
||||
- name: test create certificate idempotence
|
||||
hcloud_certificate:
|
||||
name: "{{ hcloud_certificate_name }}"
|
||||
certificate: "{{ certificate_example_com }}"
|
||||
private_key: "{{ certificate_example_com_key }}"
|
||||
register: result
|
||||
- name: verify create certificate idempotence
|
||||
assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- name: test update certificate with check mode
|
||||
hcloud_certificate:
|
||||
id: "{{ certificate.hcloud_certificate.id }}"
|
||||
name: "changed-{{ hcloud_certificate_name }}"
|
||||
register: result
|
||||
check_mode: yes
|
||||
- name: test create certificate with check mode
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test update certificate
|
||||
hcloud_certificate:
|
||||
id: "{{ certificate.hcloud_certificate.id }}"
|
||||
name: "changed-{{ hcloud_certificate_name }}"
|
||||
labels:
|
||||
key: value
|
||||
register: result
|
||||
- name: test update certificate
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.hcloud_certificate.name == "changed-{{ hcloud_certificate_name }}"
|
||||
|
||||
- name: test update certificate with same labels
|
||||
hcloud_certificate:
|
||||
id: "{{ certificate.hcloud_certificate.id }}"
|
||||
name: "changed-{{ hcloud_certificate_name }}"
|
||||
labels:
|
||||
key: value
|
||||
register: result
|
||||
- name: test update certificate with same labels
|
||||
assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- name: test update certificate with other labels
|
||||
hcloud_certificate:
|
||||
id: "{{ certificate.hcloud_certificate.id }}"
|
||||
name: "changed-{{ hcloud_certificate_name }}"
|
||||
labels:
|
||||
key: value
|
||||
test: "val123"
|
||||
register: result
|
||||
- name: test update certificate with other labels
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test rename certificate
|
||||
hcloud_certificate:
|
||||
id: "{{ certificate.hcloud_certificate.id }}"
|
||||
name: "{{ hcloud_certificate_name }}"
|
||||
register: result
|
||||
- name: test rename certificate
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.hcloud_certificate.name == "{{ hcloud_certificate_name }}"
|
||||
|
||||
- name: absent certificate
|
||||
hcloud_certificate:
|
||||
id: "{{ certificate.hcloud_certificate.id }}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify absent server
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
|
@ -0,0 +1,2 @@
|
|||
cloud/hcloud
|
||||
shippable/hcloud/group2
|
|
@ -0,0 +1,5 @@
|
|||
# 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_certificate_name: "always-there-cert"
|
|
@ -0,0 +1,2 @@
|
|||
collections:
|
||||
- hetzner.cloud
|
|
@ -0,0 +1,39 @@
|
|||
# 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 gather hcloud certificate infos in check mode
|
||||
hcloud_certificate_info:
|
||||
register: hcloud_certificate
|
||||
check_mode: yes
|
||||
- name: verify test gather hcloud certificate infos in check mode
|
||||
assert:
|
||||
that:
|
||||
- hcloud_certificate.hcloud_certificate_info| list | count >= 1
|
||||
|
||||
- name: test gather hcloud certificate infos
|
||||
hcloud_certificate_info:
|
||||
register: hcloud_certificate
|
||||
check_mode: yes
|
||||
- name: verify test gather hcloud certificate infos
|
||||
assert:
|
||||
that:
|
||||
- hcloud_certificate.hcloud_certificate_info| list | count >= 1
|
||||
|
||||
- name: test gather hcloud certificate infos with correct label selector
|
||||
hcloud_certificate_info:
|
||||
label_selector: "key=value"
|
||||
register: hcloud_certificate
|
||||
- name: verify test gather hcloud certificate infos with correct label selector
|
||||
assert:
|
||||
that:
|
||||
- hcloud_certificate.hcloud_certificate_info|selectattr('name','equalto','{{ hcloud_certificate_name }}') | list | count == 1
|
||||
|
||||
- name: test gather hcloud certificate infos with wrong label selector
|
||||
hcloud_certificate_info:
|
||||
label_selector: "key!=value"
|
||||
register: hcloud_certificate
|
||||
- name: verify test gather hcloud certificate infos with wrong label selector
|
||||
assert:
|
||||
that:
|
||||
- hcloud_certificate.hcloud_certificate_info | list | count == 0
|
2
tests/integration/targets/hcloud_load_balancer/aliases
Normal file
2
tests/integration/targets/hcloud_load_balancer/aliases
Normal file
|
@ -0,0 +1,2 @@
|
|||
cloud/hcloud
|
||||
shippable/hcloud/group1
|
|
@ -0,0 +1,5 @@
|
|||
# Copyright: (c) 2020, 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_load_balancer_name: "{{hcloud_prefix}}-integration"
|
|
@ -0,0 +1,3 @@
|
|||
collections:
|
||||
- community.general.ipfilter
|
||||
- hetzner.cloud
|
176
tests/integration/targets/hcloud_load_balancer/tasks/main.yml
Normal file
176
tests/integration/targets/hcloud_load_balancer/tasks/main.yml
Normal file
|
@ -0,0 +1,176 @@
|
|||
# Copyright: (c) 2020, 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_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify setup
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
||||
- name: test missing required parameters on create Load Balancer
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
register: result
|
||||
ignore_errors: yes
|
||||
- name: verify fail test missing required parameters on create Load Balancer
|
||||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- 'result.msg == "missing required arguments: load_balancer_type"'
|
||||
|
||||
- name: test create Load Balancer with check mode
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
load_balancer_type: lb11
|
||||
network_zone: eu-central
|
||||
state: present
|
||||
register: result
|
||||
check_mode: yes
|
||||
- name: test create Load Balancer Load Balancer
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test create Load Balancer
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name}}"
|
||||
load_balancer_type: lb11
|
||||
network_zone: eu-central
|
||||
state: present
|
||||
register: main_load_balancer
|
||||
- name: verify create Load Balancer
|
||||
assert:
|
||||
that:
|
||||
- main_load_balancer is changed
|
||||
- main_load_balancer.hcloud_load_balancer.name == "{{ hcloud_load_balancer_name }}"
|
||||
- main_load_balancer.hcloud_load_balancer.load_balancer_type == "lb11"
|
||||
|
||||
- name: test create Load Balancer idempotence
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
state: present
|
||||
register: result
|
||||
- name: verify create Load Balancer idempotence
|
||||
assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- name: test update Load Balancer protection
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
delete_protection: true
|
||||
state: present
|
||||
register: result_after_test
|
||||
ignore_errors: true
|
||||
- name: verify update Load Balancer protection
|
||||
assert:
|
||||
that:
|
||||
- result_after_test is changed
|
||||
- result_after_test.hcloud_load_balancer.delete_protection is sameas true
|
||||
|
||||
- name: test Load Balancer without protection set to be idempotent
|
||||
hcloud_load_balancer:
|
||||
name: "{{hcloud_load_balancer_name}}"
|
||||
register: result_after_test
|
||||
- name: verify test Load Balancer without protection set to be idempotent
|
||||
assert:
|
||||
that:
|
||||
- result_after_test is not changed
|
||||
- result_after_test.hcloud_load_balancer.delete_protection is sameas true
|
||||
|
||||
- name: test delete Load Balancer fails if it is protected
|
||||
hcloud_load_balancer:
|
||||
name: "{{hcloud_load_balancer_name}}"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
register: result
|
||||
- name: verify delete Load Balancer fails if it is protected
|
||||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- 'result.msg == "load balancer deletion is protected"'
|
||||
|
||||
- name: test remove Load Balancer protection
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
delete_protection: false
|
||||
state: present
|
||||
register: result_after_test
|
||||
ignore_errors: true
|
||||
- name: verify remove Load Balancer protection
|
||||
assert:
|
||||
that:
|
||||
- result_after_test is changed
|
||||
- result_after_test.hcloud_load_balancer.delete_protection is sameas false
|
||||
|
||||
- name: absent Load Balancer
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify absent Load Balancer
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
||||
|
||||
- name: test create Load Balancer with labels
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name}}"
|
||||
load_balancer_type: lb11
|
||||
network_zone: eu-central
|
||||
labels:
|
||||
key: value
|
||||
mylabel: "val123"
|
||||
state: present
|
||||
register: main_load_balancer
|
||||
- name: verify create Load Balancer with labels
|
||||
assert:
|
||||
that:
|
||||
- main_load_balancer is changed
|
||||
- main_load_balancer.hcloud_load_balancer.labels.key == "value"
|
||||
- main_load_balancer.hcloud_load_balancer.labels.mylabel == "val123"
|
||||
|
||||
- name: test update Load Balancer with labels
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name}}"
|
||||
load_balancer_type: lb11
|
||||
network_zone: eu-central
|
||||
labels:
|
||||
key: other
|
||||
mylabel: "val123"
|
||||
state: present
|
||||
register: main_load_balancer
|
||||
- name: verify update Load Balancer with labels
|
||||
assert:
|
||||
that:
|
||||
- main_load_balancer is changed
|
||||
- main_load_balancer.hcloud_load_balancer.labels.key == "other"
|
||||
- main_load_balancer.hcloud_load_balancer.labels.mylabel == "val123"
|
||||
|
||||
- name: test update Load Balancer with labels in other order
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name}}"
|
||||
load_balancer_type: lb11
|
||||
network_zone: eu-central
|
||||
labels:
|
||||
mylabel: "val123"
|
||||
key: other
|
||||
state: present
|
||||
register: main_load_balancer
|
||||
- name: verify update Load Balancer with labels in other order
|
||||
assert:
|
||||
that:
|
||||
- main_load_balancer is not changed
|
||||
|
||||
- name: cleanup with labels
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify cleanup
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
|
@ -0,0 +1,2 @@
|
|||
cloud/hcloud
|
||||
shippable/hcloud/group1
|
|
@ -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_network_name: "{{hcloud_prefix}}-load_balancer-network"
|
||||
hcloud_load_balancer_name: "{{hcloud_prefix}}-load_balancer-network"
|
|
@ -0,0 +1,3 @@
|
|||
collections:
|
||||
- community.general.ipfilter
|
||||
- hetzner.cloud
|
|
@ -0,0 +1,155 @@
|
|||
# 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 network
|
||||
hcloud_network:
|
||||
name: "{{ hcloud_network_name }}"
|
||||
ip_range: "10.0.0.0/8"
|
||||
state: present
|
||||
register: network
|
||||
- name: verify setup network
|
||||
assert:
|
||||
that:
|
||||
- network is success
|
||||
|
||||
- name: setup subnetwork
|
||||
hcloud_subnetwork:
|
||||
network: "{{ hcloud_network_name }}"
|
||||
ip_range: "10.0.0.0/16"
|
||||
type: "cloud"
|
||||
network_zone: "eu-central"
|
||||
state: present
|
||||
register: subnetwork
|
||||
- name: verify subnetwork
|
||||
assert:
|
||||
that:
|
||||
- subnetwork is success
|
||||
|
||||
- name: setup load_balancer
|
||||
hcloud_load_balancer:
|
||||
name: "{{hcloud_load_balancer_name}}"
|
||||
load_balancer_type: lb11
|
||||
state: present
|
||||
location: "fsn1"
|
||||
register: load_balancer
|
||||
- name: verify setup load_balancer
|
||||
assert:
|
||||
that:
|
||||
- load_balancer is success
|
||||
|
||||
- name: test missing required parameters on create load_balancer network
|
||||
hcloud_load_balancer_network:
|
||||
state: present
|
||||
register: result
|
||||
ignore_errors: yes
|
||||
- name: verify fail test missing required parameters on create load_balancer network
|
||||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- 'result.msg == "missing required arguments: load_balancer, network"'
|
||||
|
||||
- name: test create load_balancer network with checkmode
|
||||
hcloud_load_balancer_network:
|
||||
network: "{{ hcloud_network_name }}"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
state: present
|
||||
register: result
|
||||
check_mode: yes
|
||||
- name: verify test create load_balancer network with checkmode
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test create load_balancer network
|
||||
hcloud_load_balancer_network:
|
||||
network: "{{ hcloud_network_name }}"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
state: present
|
||||
register: load_balancerNetwork
|
||||
- name: verify create load_balancer network
|
||||
assert:
|
||||
that:
|
||||
- load_balancerNetwork is changed
|
||||
- load_balancerNetwork.hcloud_load_balancer_network.network == hcloud_network_name
|
||||
- load_balancerNetwork.hcloud_load_balancer_network.load_balancer == hcloud_load_balancer_name
|
||||
|
||||
- name: test create load_balancer network idempotency
|
||||
hcloud_load_balancer_network:
|
||||
network: "{{ hcloud_network_name }}"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
state: present
|
||||
register: load_balancerNetwork
|
||||
- name: verify create load_balancer network idempotency
|
||||
assert:
|
||||
that:
|
||||
- load_balancerNetwork is not changed
|
||||
|
||||
- name: test absent load_balancer network
|
||||
hcloud_load_balancer_network:
|
||||
network: "{{ hcloud_network_name }}"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify test absent load_balancer network
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test create load_balancer network with specified ip
|
||||
hcloud_load_balancer_network:
|
||||
network: "{{ hcloud_network_name }}"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
ip: "10.0.0.2"
|
||||
state: present
|
||||
register: load_balancerNetwork
|
||||
- name: verify create load_balancer network with specified ip
|
||||
assert:
|
||||
that:
|
||||
- load_balancerNetwork is changed
|
||||
- load_balancerNetwork.hcloud_load_balancer_network.network == hcloud_network_name
|
||||
- load_balancerNetwork.hcloud_load_balancer_network.load_balancer == hcloud_load_balancer_name
|
||||
- load_balancerNetwork.hcloud_load_balancer_network.ip == "10.0.0.2"
|
||||
|
||||
- name: cleanup create load_balancer network with specified ip
|
||||
hcloud_load_balancer_network:
|
||||
network: "{{ hcloud_network_name }}"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify cleanup create load_balancer network with specified ip
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: cleanup load_balancer
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify cleanup load_balancer
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
||||
|
||||
- name: cleanup subnetwork
|
||||
hcloud_subnetwork:
|
||||
network: "{{ hcloud_network_name }}"
|
||||
ip_range: "10.0.0.0/16"
|
||||
type: "load_balancer"
|
||||
network_zone: "eu-central"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify cleanup subnetwork
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: cleanup
|
||||
hcloud_network:
|
||||
name: "{{hcloud_network_name}}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify cleanup
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
|
@ -0,0 +1,2 @@
|
|||
cloud/hcloud
|
||||
shippable/hcloud/group1
|
|
@ -0,0 +1,5 @@
|
|||
# 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_load_balancer_name: "{{hcloud_prefix}}-load_balancer-target"
|
|
@ -0,0 +1,3 @@
|
|||
collections:
|
||||
- community.general.ipfilter
|
||||
- hetzner.cloud
|
|
@ -0,0 +1,112 @@
|
|||
# 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 load_balancer
|
||||
hcloud_load_balancer:
|
||||
name: "{{hcloud_load_balancer_name}}"
|
||||
load_balancer_type: lb11
|
||||
state: present
|
||||
location: "fsn1"
|
||||
register: load_balancer
|
||||
- name: verify setup load_balancer
|
||||
assert:
|
||||
that:
|
||||
- load_balancer is success
|
||||
|
||||
- name: test create load_balancer service with checkmode
|
||||
hcloud_load_balancer_service:
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
protocol: "http"
|
||||
listen_port: 80
|
||||
state: present
|
||||
register: result
|
||||
check_mode: yes
|
||||
- name: verify test create load_balancer service with checkmode
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test create load_balancer service
|
||||
hcloud_load_balancer_service:
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
protocol: "http"
|
||||
listen_port: 80
|
||||
state: present
|
||||
register: load_balancer_service
|
||||
- name: verify create load_balancer service
|
||||
assert:
|
||||
that:
|
||||
- load_balancer_service is changed
|
||||
- load_balancer_service.hcloud_load_balancer_service.protocol == "http"
|
||||
- load_balancer_service.hcloud_load_balancer_service.listen_port == 80
|
||||
- load_balancer_service.hcloud_load_balancer_service.destination_port == 80
|
||||
- load_balancer_service.hcloud_load_balancer_service.proxyprotocol is sameas false
|
||||
|
||||
- name: test create load_balancer service idempotency
|
||||
hcloud_load_balancer_service:
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
protocol: "http"
|
||||
listen_port: 80
|
||||
state: present
|
||||
register: load_balancer_service
|
||||
- name: verify create load_balancer service idempotency
|
||||
assert:
|
||||
that:
|
||||
- load_balancer_service is not changed
|
||||
|
||||
- name: test update load_balancer service
|
||||
hcloud_load_balancer_service:
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
protocol: "tcp"
|
||||
listen_port: 80
|
||||
state: present
|
||||
register: load_balancer_service
|
||||
- name: verify create load_balancer service
|
||||
assert:
|
||||
that:
|
||||
- load_balancer_service is changed
|
||||
- load_balancer_service.hcloud_load_balancer_service.protocol == "tcp"
|
||||
- load_balancer_service.hcloud_load_balancer_service.listen_port == 80
|
||||
- load_balancer_service.hcloud_load_balancer_service.destination_port == 80
|
||||
- load_balancer_service.hcloud_load_balancer_service.proxyprotocol is sameas false
|
||||
|
||||
- name: test absent load_balancer service
|
||||
hcloud_load_balancer_service:
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
protocol: "http"
|
||||
listen_port: 80
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify test absent load_balancer service
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test create load_balancer service with http
|
||||
hcloud_load_balancer_service:
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
protocol: "http"
|
||||
listen_port: 80
|
||||
http:
|
||||
cookie_name: "Test"
|
||||
sticky_sessions: yes
|
||||
state: present
|
||||
register: load_balancer_service
|
||||
- name: verify create load_balancer service
|
||||
assert:
|
||||
that:
|
||||
- load_balancer_service is changed
|
||||
- load_balancer_service.hcloud_load_balancer_service.protocol == "http"
|
||||
- load_balancer_service.hcloud_load_balancer_service.listen_port == 80
|
||||
- load_balancer_service.hcloud_load_balancer_service.destination_port == 80
|
||||
- load_balancer_service.hcloud_load_balancer_service.proxyprotocol is sameas false
|
||||
|
||||
- name: cleanup load_balancer
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify cleanup load_balancer
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
|
@ -0,0 +1,2 @@
|
|||
cloud/hcloud
|
||||
shippable/hcloud/group1
|
|
@ -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_server_name: "{{hcloud_prefix}}-lb-target"
|
||||
hcloud_load_balancer_name: "{{hcloud_prefix}}-load_balancer-target"
|
|
@ -0,0 +1,3 @@
|
|||
collections:
|
||||
- community.general.ipfilter
|
||||
- hetzner.cloud
|
|
@ -0,0 +1,99 @@
|
|||
# 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 server
|
||||
hcloud_server:
|
||||
name: "{{hcloud_server_name}}"
|
||||
server_type: cx11
|
||||
image: ubuntu-20.04
|
||||
state: started
|
||||
location: "fsn1"
|
||||
register: server
|
||||
- name: verify setup server
|
||||
assert:
|
||||
that:
|
||||
- server is success
|
||||
|
||||
- name: setup load_balancer
|
||||
hcloud_load_balancer:
|
||||
name: "{{hcloud_load_balancer_name}}"
|
||||
load_balancer_type: lb11
|
||||
state: present
|
||||
location: "fsn1"
|
||||
register: load_balancer
|
||||
- name: verify setup load_balancer
|
||||
assert:
|
||||
that:
|
||||
- load_balancer is success
|
||||
|
||||
- name: test create load_balancer target with checkmode
|
||||
hcloud_load_balancer_target:
|
||||
type: "server"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
server: "{{hcloud_server_name}}"
|
||||
state: present
|
||||
register: result
|
||||
check_mode: yes
|
||||
- name: verify test create load_balancer target with checkmode
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: test create load_balancer target
|
||||
hcloud_load_balancer_target:
|
||||
type: "server"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
server: "{{hcloud_server_name}}"
|
||||
state: present
|
||||
register: load_balancer_target
|
||||
- name: verify create load_balancer target
|
||||
assert:
|
||||
that:
|
||||
- load_balancer_target is changed
|
||||
- load_balancer_target.hcloud_load_balancer_target.type == "server"
|
||||
- load_balancer_target.hcloud_load_balancer_target.server == hcloud_server_name
|
||||
- load_balancer_target.hcloud_load_balancer_target.load_balancer == hcloud_load_balancer_name
|
||||
|
||||
- name: test create load_balancer target idempotency
|
||||
hcloud_load_balancer_target:
|
||||
type: "server"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
server: "{{hcloud_server_name}}"
|
||||
state: present
|
||||
register: load_balancer_target
|
||||
- name: verify create load_balancer target idempotency
|
||||
assert:
|
||||
that:
|
||||
- load_balancer_target is not changed
|
||||
|
||||
- name: test absent load_balancer target
|
||||
hcloud_load_balancer_target:
|
||||
type: "server"
|
||||
load_balancer: "{{hcloud_load_balancer_name}}"
|
||||
server: "{{hcloud_server_name}}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify test absent load_balancer target
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: cleanup load_balancer
|
||||
hcloud_load_balancer:
|
||||
name: "{{ hcloud_load_balancer_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify cleanup load_balancer
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
||||
|
||||
- name: cleanup
|
||||
hcloud_server:
|
||||
name: "{{hcloud_server_name}}"
|
||||
state: absent
|
||||
register: result
|
||||
- name: verify cleanup
|
||||
assert:
|
||||
that:
|
||||
- result is success
|
|
@ -0,0 +1,2 @@
|
|||
cloud/hcloud
|
||||
shippable/hcloud/group2
|
|
@ -0,0 +1,5 @@
|
|||
# Copyright: (c) 2020, 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_load_balancer_type_name: "lb11"
|
||||
hcloud_load_balancer_type_id: 1
|
|
@ -0,0 +1,3 @@
|
|||
collections:
|
||||
- community.general.ipfilter
|
||||
- hetzner.cloud
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright: (c) 2020, 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 gather hcloud Load Balancer type infos
|
||||
hcloud_load_balancer_type_info:
|
||||
register: hcloud_load_balancer_types
|
||||
- name: verify test gather hcloud Load Balancer type infos
|
||||
assert:
|
||||
that:
|
||||
- hcloud_load_balancer_types.hcloud_load_balancer_type_info| list | count >= 1
|
||||
|
||||
- name: test gather hcloud Load Balancer type infos in check mode
|
||||
hcloud_load_balancer_type_info:
|
||||
check_mode: yes
|
||||
register: hcloud_load_balancer_types
|
||||
|
||||
- name: verify test gather hcloud Load Balancer type infos in check mode
|
||||
assert:
|
||||
that:
|
||||
- hcloud_load_balancer_types.hcloud_load_balancer_type_info| list | count >= 1
|
||||
|
||||
- name: test gather hcloud Load Balancer type infos with name
|
||||
hcloud_load_balancer_type_info:
|
||||
name: "{{hcloud_load_balancer_type_name}}"
|
||||
register: hcloud_load_balancer_types
|
||||
- name: verify test gather hcloud Load Balancer type with name
|
||||
assert:
|
||||
that:
|
||||
- hcloud_load_balancer_types.hcloud_load_balancer_type_info|selectattr('name','equalto','{{ hcloud_load_balancer_type_name }}') | list | count == 1
|
||||
|
||||
- name: test gather hcloud Load Balancer type infos with correct id
|
||||
hcloud_load_balancer_type_info:
|
||||
id: "{{hcloud_load_balancer_type_id}}"
|
||||
register: hcloud_load_balancer_types
|
||||
- name: verify test gather hcloud Load Balancer type with correct id
|
||||
assert:
|
||||
that:
|
||||
- hcloud_load_balancer_types.hcloud_load_balancer_type_info|selectattr('name','equalto','{{ hcloud_load_balancer_type_name }}') | list | count == 1
|
|
@ -0,0 +1,27 @@
|
|||
# Copyright: (c) 2020, 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: create a cert temp file
|
||||
tempfile:
|
||||
state: file
|
||||
register: certificate_example_com
|
||||
tags:
|
||||
- prepare
|
||||
- name: create a key temp file
|
||||
tempfile:
|
||||
state: file
|
||||
register: certificate_example_com_key
|
||||
tags:
|
||||
- prepare
|
||||
-
|
||||
- name: generate certificate
|
||||
shell: openssl req -nodes -new -x509 -keyout {{ certificate_example_com_key.path }} -out {{ certificate_example_com.path }} -subj "/C=DE/ST=Munich/L=Bavaria/O=Dis/CN=www.example.com"
|
||||
tags:
|
||||
- prepare
|
||||
|
||||
- name: set facts for future roles
|
||||
set_fact:
|
||||
certificate_example_com: "{{ lookup('file',certificate_example_com.path) }}"
|
||||
certificate_example_com_key: "{{ lookup('file',certificate_example_com_key.path) }}"
|
||||
tags:
|
||||
- prepare
|
|
@ -55,7 +55,7 @@ retry ansible-galaxy -vvv collection install community.general
|
|||
retry ansible-galaxy -vvv collection install ansible.netcommon
|
||||
retry ansible-galaxy -vvv collection install community.internal_test_tools
|
||||
retry pip install netaddr --disable-pip-version-check
|
||||
retry pip install hcloud
|
||||
retry python -m pip install hcloud
|
||||
# END: HACK
|
||||
|
||||
export PYTHONIOENCODING='utf-8'
|
||||
|
|
|
@ -12,4 +12,4 @@ hcloud_api_token=${HCLOUD_TOKEN}
|
|||
export SHIPPABLE="true"
|
||||
export SHIPPABLE_BUILD_NUMBER="gl-$(cat prefix.txt)"
|
||||
export SHIPPABLE_JOB_NUMBER="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 2 | head -n 1)"
|
||||
ansible-test integration --color --local -v "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"}
|
||||
ansible-test integration --color --local -vvvvv "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"}
|
||||
|
|
Loading…
Reference in a new issue