1
0
Fork 0
mirror of https://github.com/ansible-collections/hetzner.hcloud.git synced 2026-02-04 16:11:49 +00:00
hetzner.hcloud/plugins/modules/load_balancer_info.py
Jonas L. 579b34e754
fix: ensure returned resource ids are integers (#651)
##### SUMMARY

The documentation states that all our returned resource ids are
integers, this change aligns our modules with the docs.

The impact of this change should be minimal, as ids are used for
identification purposes by directly forwarding the values (no
transformation of the data is done).

##### ISSUE TYPE

- Bugfix Pull Request


##### COMPONENT NAME

All modules
2025-06-11 10:09:12 +02:00

418 lines
16 KiB
Python

#!/usr/bin/python
# 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 annotations
DOCUMENTATION = """
---
module: load_balancer_info
short_description: Gather infos about your Hetzner Cloud Load Balancers.
description:
- Gather infos about your Hetzner Cloud Load Balancers..
author:
- Lukas Kaemmerling (@LKaemmerling)
options:
id:
description:
- The ID of the Load Balancers you want to get.
- The module will fail if the provided ID is invalid.
type: int
name:
description:
- The name of the Load Balancers you want to get.
type: str
label_selector:
description:
- The label selector for the Load Balancers you want to get.
type: str
extends_documentation_fragment:
- hetzner.hcloud.hcloud
"""
EXAMPLES = """
- name: Gather hcloud load_balancer infos
hetzner.hcloud.load_balancer_info:
register: output
- name: Print the gathered infos
debug:
var: output
"""
RETURN = """
hcloud_load_balancer_info:
description: The load_balancer infos as list
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
load_balancer_type:
description: Name of the Load Balancer type of the Load Balancer
returned: always
type: str
sample: cx22
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
targets:
description: The targets of the Load Balancer
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
label_selector:
description: Label Selector
type: str
returned: if I(type) is label_selector
sample: application=backend
ip:
description: IP of the dedicated server
type: str
returned: if I(type) is ip
sample: 127.0.0.1
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.load_balancer_network)
type: bool
sample: true
returned: always
health_status:
description:
- List of health statuses of the services on this target. Only present for target types "server" and "ip".
type: list
returned: if I(type) is server or ip
contains:
listen_port:
description: Load Balancer Target listen port
type: int
returned: always
sample: 80
status:
description: Load Balancer Target status
type: str
choices: [healthy, unhealthy, unknown]
returned: always
sample: healthy
services:
description: all services from this Load Balancer
returned: Always
type: complex
contains:
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 ..module_utils.hcloud import AnsibleHCloud
from ..module_utils.vendor.hcloud import HCloudException
from ..module_utils.vendor.hcloud.load_balancers import (
BoundLoadBalancer,
LoadBalancerService,
LoadBalancerTarget,
)
class AnsibleHCloudLoadBalancerInfo(AnsibleHCloud):
represent = "hcloud_load_balancer_info"
hcloud_load_balancer_info: list[BoundLoadBalancer] | None = None
def _prepare_result(self):
tmp = []
for load_balancer in self.hcloud_load_balancer_info:
if load_balancer is None:
continue
tmp.append(
{
"id": load_balancer.id,
"name": load_balancer.name,
"ipv4_address": load_balancer.public_net.ipv4.ip,
"ipv6_address": load_balancer.public_net.ipv6.ip,
"private_ipv4_address": load_balancer.private_net[0].ip if len(load_balancer.private_net) else None,
"load_balancer_type": load_balancer.load_balancer_type.name,
"location": load_balancer.location.name,
"labels": load_balancer.labels,
"delete_protection": load_balancer.protection["delete"],
"disable_public_interface": False if load_balancer.public_net.enabled else True,
"targets": [self._prepare_target_result(target) for target in load_balancer.targets],
"services": [self._prepare_service_result(service) for service in load_balancer.services],
}
)
return tmp
@staticmethod
def _prepare_service_result(service: LoadBalancerService):
http = None
if service.protocol != "tcp":
http = {
"cookie_name": service.http.cookie_name,
"cookie_lifetime": service.http.cookie_lifetime,
"redirect_http": service.http.redirect_http,
"sticky_sessions": service.http.sticky_sessions,
"certificates": [certificate.name for certificate in service.http.certificates],
}
health_check = {
"protocol": service.health_check.protocol,
"port": service.health_check.port,
"interval": service.health_check.interval,
"timeout": service.health_check.timeout,
"retries": service.health_check.retries,
}
if service.health_check.protocol != "tcp":
health_check["http"] = {
"domain": service.health_check.http.domain,
"path": service.health_check.http.path,
"response": service.health_check.http.response,
"certificates": service.health_check.http.status_codes,
"tls": service.health_check.http.tls,
}
return {
"protocol": service.protocol,
"listen_port": service.listen_port,
"destination_port": service.destination_port,
"proxyprotocol": service.proxyprotocol,
"http": http,
"health_check": health_check,
}
@staticmethod
def _prepare_target_result(target: LoadBalancerTarget):
result = {
"type": target.type,
"use_private_ip": target.use_private_ip,
}
if target.type == "server":
result["server"] = target.server.name
elif target.type == "label_selector":
result["label_selector"] = target.label_selector.selector
elif target.type == "ip":
result["ip"] = target.ip.ip
if target.health_status is not None:
result["health_status"] = [
{
"listen_port": item.listen_port,
"status": item.status,
}
for item in target.health_status
]
return result
def get_load_balancers(self):
try:
if self.module.params.get("id") is not None:
self.hcloud_load_balancer_info = [self.client.load_balancers.get_by_id(self.module.params.get("id"))]
elif self.module.params.get("name") is not None:
self.hcloud_load_balancer_info = [
self.client.load_balancers.get_by_name(self.module.params.get("name"))
]
else:
params = {}
label_selector = self.module.params.get("label_selector")
if label_selector:
params["label_selector"] = label_selector
self.hcloud_load_balancer_info = self.client.load_balancers.get_all(**params)
except HCloudException as exception:
self.fail_json_hcloud(exception)
@classmethod
def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
label_selector={"type": "str"},
**super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
module = AnsibleHCloudLoadBalancerInfo.define_module()
hcloud = AnsibleHCloudLoadBalancerInfo(module)
hcloud.get_load_balancers()
result = hcloud.get_result()
ansible_info = {"hcloud_load_balancer_info": result["hcloud_load_balancer_info"]}
module.exit_json(**ansible_info)
if __name__ == "__main__":
main()