summaryrefslogtreecommitdiffstats
path: root/ansible_collections/hetzner
diff options
context:
space:
mode:
Diffstat (limited to 'ansible_collections/hetzner')
-rw-r--r--ansible_collections/hetzner/hcloud/.ansible-lint27
-rw-r--r--ansible_collections/hetzner/hcloud/.azure-pipelines/azure-pipelines.yml184
-rwxr-xr-xansible_collections/hetzner/hcloud/.azure-pipelines/scripts/aggregate-coverage.sh8
-rwxr-xr-xansible_collections/hetzner/hcloud/.azure-pipelines/scripts/combine-coverage.py27
-rwxr-xr-xansible_collections/hetzner/hcloud/.azure-pipelines/scripts/publish-codecov.sh26
-rwxr-xr-xansible_collections/hetzner/hcloud/.azure-pipelines/scripts/report-coverage.sh10
-rwxr-xr-xansible_collections/hetzner/hcloud/.azure-pipelines/scripts/run-tests.sh24
-rwxr-xr-xansible_collections/hetzner/hcloud/.azure-pipelines/scripts/time-command.py11
-rw-r--r--ansible_collections/hetzner/hcloud/.azure-pipelines/templates/matrix.yml14
-rw-r--r--ansible_collections/hetzner/hcloud/.azure-pipelines/templates/test.yml68
-rw-r--r--ansible_collections/hetzner/hcloud/.flake83
-rw-r--r--ansible_collections/hetzner/hcloud/.github/release-please-config.json15
-rw-r--r--ansible_collections/hetzner/hcloud/.github/release-please-manifest.json1
-rw-r--r--ansible_collections/hetzner/hcloud/.github/workflows/check-changelog-fragments.yml20
-rw-r--r--ansible_collections/hetzner/hcloud/.github/workflows/lint.yml25
-rw-r--r--ansible_collections/hetzner/hcloud/.github/workflows/release-please.yml74
-rw-r--r--ansible_collections/hetzner/hcloud/.github/workflows/stale.yml13
-rw-r--r--ansible_collections/hetzner/hcloud/.github/workflows/vendor.yml26
-rw-r--r--ansible_collections/hetzner/hcloud/.gitignore4
-rw-r--r--ansible_collections/hetzner/hcloud/.gitlab-ci.yml14
-rw-r--r--ansible_collections/hetzner/hcloud/.pre-commit-config.yaml85
-rw-r--r--ansible_collections/hetzner/hcloud/CHANGELOG.rst202
-rw-r--r--ansible_collections/hetzner/hcloud/COPYING1
-rw-r--r--ansible_collections/hetzner/hcloud/FILES.json2802
-rw-r--r--ansible_collections/hetzner/hcloud/MANIFEST.json8
-rw-r--r--ansible_collections/hetzner/hcloud/Makefile42
-rw-r--r--ansible_collections/hetzner/hcloud/README.md28
-rw-r--r--ansible_collections/hetzner/hcloud/changelogs/changelog.yaml215
-rw-r--r--ansible_collections/hetzner/hcloud/changelogs/config.yaml32
-rw-r--r--ansible_collections/hetzner/hcloud/changelogs/dev-changelog.md64
-rw-r--r--ansible_collections/hetzner/hcloud/docs/docsite/extra-docs.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/docs/docsite/links.yml10
-rw-r--r--ansible_collections/hetzner/hcloud/docs/docsite/rst/guides.rst50
-rw-r--r--ansible_collections/hetzner/hcloud/examples/inventory.hcloud.yml7
-rw-r--r--ansible_collections/hetzner/hcloud/examples/server-with-firewall.yml62
-rw-r--r--ansible_collections/hetzner/hcloud/examples/server-with-private-ip-only.yml50
-rw-r--r--ansible_collections/hetzner/hcloud/examples/use-module-defaults-group.yml27
-rw-r--r--ansible_collections/hetzner/hcloud/examples/use-refresh-inventory.yml35
-rw-r--r--ansible_collections/hetzner/hcloud/meta/runtime.yml137
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/__init__.py0
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/doc_fragments/hcloud.py46
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/inventory/hcloud.py659
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/client.py108
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/hcloud.py116
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/__init__.py0
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/__init__.py7
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_client.py236
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_exceptions.py17
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_version.py3
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/__init__.py14
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/client.py166
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/domain.py89
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/__init__.py13
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/client.py371
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/domain.py133
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/__init__.py4
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/client.py98
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/domain.py84
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/__init__.py8
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/client.py121
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/domain.py60
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/deprecation/__init__.py3
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/deprecation/domain.py36
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/__init__.py11
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/client.py501
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/domain.py221
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/__init__.py8
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/client.py459
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/domain.py109
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/hcloud.py12
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/helpers/__init__.py3
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/helpers/labels.py46
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/__init__.py4
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/client.py393
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/domain.py134
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/__init__.py4
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/client.py128
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/domain.py69
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/__init__.py8
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/client.py89
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py57
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/__init__.py25
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/client.py939
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/domain.py537
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/__init__.py4
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/client.py82
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/domain.py56
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/metrics/__init__.py3
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/metrics/domain.py49
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/__init__.py9
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/client.py556
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/domain.py150
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/__init__.py8
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/client.py214
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/domain.py75
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/__init__.py4
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/client.py361
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/domain.py113
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/py.typed1
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/__init__.py8
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/client.py84
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/domain.py85
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/__init__.py17
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/client.py1265
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/domain.py455
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/__init__.py4
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/client.py194
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/domain.py44
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/__init__.py4
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/client.py458
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/domain.py113
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/module_utils/version.py3
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/certificate.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate.py)124
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/certificate_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate_info.py)80
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/datacenter_info.py192
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/firewall.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_firewall.py)311
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/firewall_info.py246
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/firewall_resource.py243
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/floating_ip.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip.py)109
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/floating_ip_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_info.py)101
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_facts.py160
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_info.py160
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_facts.py185
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_facts.py219
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_facts.py159
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_facts.py244
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_facts.py183
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_info.py183
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_info.py169
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_facts.py186
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/image_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_info.py)108
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/iso_info.py206
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/load_balancer.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer.py)122
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_info.py)128
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_network.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_network.py)96
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_service.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_service.py)206
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_target.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_target.py)168
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_type_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_type_info.py)79
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/location_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_info.py)86
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/network.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network.py)100
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/network_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network_info.py)89
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/placement_group.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_placement_group.py)72
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/primary_ip.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_primary_ip.py)79
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/primary_ip_info.py203
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/rdns.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_rdns.py)132
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/route.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_route.py)70
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/server.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server.py)484
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/server_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_info.py)120
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/server_network.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_network.py)102
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/server_type_info.py204
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/ssh_key.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key.py)87
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/ssh_key_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_facts.py)95
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/subnetwork.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_subnetwork.py)87
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/volume.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume.py)93
-rw-r--r--ansible_collections/hetzner/hcloud/plugins/modules/volume_info.py (renamed from ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_info.py)94
-rw-r--r--ansible_collections/hetzner/hcloud/pyproject.toml28
-rw-r--r--ansible_collections/hetzner/hcloud/renovate.json12
-rw-r--r--ansible_collections/hetzner/hcloud/requirements.txt12
-rwxr-xr-xansible_collections/hetzner/hcloud/scripts/integration-test-files.sh28
-rwxr-xr-xansible_collections/hetzner/hcloud/scripts/vendor.py114
-rw-r--r--ansible_collections/hetzner/hcloud/tests/config.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/constraints.txt2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/README.md27
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/common/defaults/main/common.yml9
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/common/tasks/main.yml28
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/constraints.txt1
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/requirements.txt5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/defaults/main/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/meta/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/meta/main.yml)3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/tasks/main.yml)54
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/defaults/main.yml)3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/prepare.yml10
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/test.yml77
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/defaults/main.yml)4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/tasks/test.yml58
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/defaults/main/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/cleanup.yml10
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/prepare.yml8
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/test.yml197
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/aliases (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/aliases)0
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/defaults/main/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/cleanup.yml10
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/prepare.yml35
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/test.yml93
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/defaults/main/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/cleanup.yml10
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/prepare.yml25
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/test.yml95
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/defaults/main/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/tasks/main.yml)130
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/defaults/main.yml)3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/prepare.yml9
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/test.yml77
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/defaults/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/meta/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/tasks/main.yml66
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/tasks/main.yml39
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/tasks/main.yml210
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/defaults/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/tasks/main.yml87
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/defaults/main.yml7
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/tasks/main.yml93
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/tasks/main.yml247
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/defaults/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/tasks/main.yml128
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/defaults/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/defaults/main.yml7
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/tasks/main.yml38
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/tasks/main.yml57
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/aliases3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/defaults/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/tasks/main.yml117
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/defaults/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/defaults/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/defaults/main.yml8
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/tasks/main.yml224
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/defaults/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/defaults/main.yml8
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/main.yml8
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/defaults/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/tasks/main.yml128
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/aliases3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/defaults/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/tasks/main.yml38
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/defaults/main.yml11
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/meta/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/meta/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/tasks/main.yml68
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/defaults/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/tasks/main.yml125
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/defaults/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/defaults/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/tasks/main.yml101
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/defaults/main/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/prepare.yml23
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/test.yml104
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/defaults/main/main.yml7
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/tasks/test.yml73
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/defaults/main.yml)3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/test.yml145
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/defaults/main/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/meta/main.yml0
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/cleanup.yml10
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/prepare.yml33
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/test.yml86
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/defaults/main/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/tasks/main.yml)68
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/defaults/main.yml)3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/tasks/main.yml)62
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/defaults/main/main.yml7
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/tasks/main.yml)66
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/defaults/main.yml)2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/tasks/test.yml56
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/defaults/main.yml)2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/tasks/test.yml56
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network/aliases3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network/defaults/main/main.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/tasks/main.yml)117
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/defaults/main/main.yml4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/prepare.yml23
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/test.yml79
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/defaults/main/main.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/prepare.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/tasks/main.yml)48
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/defaults/main.yml)4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/tasks/main.yml)51
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/defaults/main/main.yml4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/prepare.yml9
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/test.yml77
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/defaults/main/main.yml8
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/cleanup.yml20
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/prepare.yml32
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/test.yml148
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/route/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/route/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/route/defaults/main/main.yml4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/route/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/route/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/tasks/main.yml)40
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/defaults/main/main.yml8
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/prepare.yml6
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test.yml8
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_basic.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/basic.yml)168
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_firewalls.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/firewalls.yml)34
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_primary_ips.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/primary_ips.yml)28
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_private_network_only.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/private_network_only.yml)52
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_validation.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/validation.yml)18
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/defaults/main/main.yml4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/cleanup.yml10
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/prepare.yml22
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/test.yml89
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/aliases3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/defaults/main.yml)4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/tasks/main.yml)98
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/defaults/main/main.yml7
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/tasks/test.yml69
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/setup_hcloud_cli/tasks/main.yml16
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml58
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/setup_ssh_keypair/tasks/main.yml19
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/setup_sshkey/tasks/main.yml55
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/defaults/main.yml)4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/cleanup.yml10
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/tasks/main.yml)82
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/defaults/main/main.yml4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/meta/main.yml3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/prepare.yml8
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/test.yml77
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/defaults/main/main.yml23
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/prepare.yml11
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/test.yml103
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume/defaults/main/main.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/defaults/main.yml)4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume/tasks/test.yml (renamed from ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/tasks/main.yml)81
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/aliases2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/defaults/main/common.yml12
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/defaults/main/main.yml4
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/cleanup.yml5
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/main.yml31
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/prepare.yml9
-rw-r--r--ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/test.yml81
-rw-r--r--ansible_collections/hetzner/hcloud/tests/requirements.yml8
-rw-r--r--ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.12.txt2
-rw-r--r--ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.13.txt71
-rw-r--r--ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.14.txt70
-rw-r--r--ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.15.txt3
-rw-r--r--ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.16.txt1
-rw-r--r--ansible_collections/hetzner/hcloud/tests/unit/module_utils/test_hcloud.py125
-rw-r--r--ansible_collections/hetzner/hcloud/tests/unit/requirements.txt2
-rwxr-xr-xansible_collections/hetzner/hcloud/tests/utils/ci.sh141
-rwxr-xr-xansible_collections/hetzner/hcloud/tests/utils/gitlab/gitlab.sh68
-rwxr-xr-xansible_collections/hetzner/hcloud/tests/utils/gitlab/sanity.sh34
-rwxr-xr-xansible_collections/hetzner/hcloud/tests/utils/shippable/check_matrix.py120
-rwxr-xr-xansible_collections/hetzner/hcloud/tests/utils/shippable/hcloud.sh34
-rwxr-xr-xansible_collections/hetzner/hcloud/tests/utils/shippable/sanity.sh27
-rwxr-xr-xansible_collections/hetzner/hcloud/tests/utils/shippable/shippable.sh213
-rwxr-xr-xansible_collections/hetzner/hcloud/tests/utils/shippable/timing.py16
-rwxr-xr-xansible_collections/hetzner/hcloud/tests/utils/shippable/timing.sh5
492 files changed, 22262 insertions, 7852 deletions
diff --git a/ansible_collections/hetzner/hcloud/.ansible-lint b/ansible_collections/hetzner/hcloud/.ansible-lint
new file mode 100644
index 000000000..b8282450d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/.ansible-lint
@@ -0,0 +1,27 @@
+---
+exclude_paths:
+ - .azure-pipelines
+ - .cache/
+ - .git/
+ - .github/
+ - changelogs/
+ - examples/
+ - tests/integration/targets/certificate
+ - tests/integration/targets/floating_ip
+ - tests/integration/targets/load_balancer_network
+ - tests/integration/targets/load_balancer_service
+ - tests/integration/targets/load_balancer_target
+ - tests/integration/targets/network
+ - tests/integration/targets/placement_group
+ - tests/integration/targets/primary_ip
+ - tests/integration/targets/route
+ - tests/integration/targets/server
+ - tests/integration/targets/server_network
+ - tests/integration/targets/ssh_key
+ - tests/integration/targets/volume
+
+warn_list:
+ - internal-error
+ - sanity[cannot-ignore]
+ # TODO: remove once unsupported ansible-core version are dropped
+ - meta-runtime[unsupported-version]
diff --git a/ansible_collections/hetzner/hcloud/.azure-pipelines/azure-pipelines.yml b/ansible_collections/hetzner/hcloud/.azure-pipelines/azure-pipelines.yml
index d55524f27..8300381b4 100644
--- a/ansible_collections/hetzner/hcloud/.azure-pipelines/azure-pipelines.yml
+++ b/ansible_collections/hetzner/hcloud/.azure-pipelines/azure-pipelines.yml
@@ -1,22 +1,20 @@
trigger:
batch: true
branches:
- include:
- - main
+ include: [main, stable-1]
pr:
autoCancel: true
+ drafts: false
branches:
- include:
- - main
+ include: [main, stable-1]
schedules:
- cron: 0 9 * * *
displayName: Nightly
always: true
branches:
- include:
- - main
+ include: [main, stable-1]
variables:
- name: checkoutPath
@@ -26,20 +24,20 @@ variables:
- name: pipelinesCoverage
value: coverage
- name: entryPoint
- value: tests/utils/shippable/shippable.sh
+ value: tests/utils/ci.sh
- name: fetchDepth
value: 0
resources:
containers:
- container: default
- image: quay.io/ansible/azure-pipelines-test-container:3.0.0
+ image: quay.io/ansible/azure-pipelines-test-container:4.0.1
pool: Standard
stages:
-### Sanity
- - stage: Ansible_devel
+ ### Sanity
+ - stage: Sanity_devel
displayName: Sanity devel
dependsOn: []
jobs:
@@ -47,9 +45,29 @@ stages:
parameters:
targets:
- name: Sanity
- test: 'devel/sanity/1'
+ test: devel/sanity
- - stage: Ansible_2_14
+ - stage: Sanity_2_16
+ displayName: Sanity 2.16
+ dependsOn: []
+ jobs:
+ - template: templates/matrix.yml
+ parameters:
+ targets:
+ - name: Sanity
+ test: 2.16/sanity
+
+ - stage: Sanity_2_15
+ displayName: Sanity 2.15
+ dependsOn: []
+ jobs:
+ - template: templates/matrix.yml
+ parameters:
+ targets:
+ - name: Sanity
+ test: 2.15/sanity
+
+ - stage: Sanity_2_14
displayName: Sanity 2.14
dependsOn: []
jobs:
@@ -57,8 +75,9 @@ stages:
parameters:
targets:
- name: Sanity
- test: '2.14/sanity/1'
- - stage: Ansible_2_13
+ test: 2.14/sanity
+
+ - stage: Sanity_2_13
displayName: Sanity 2.13
dependsOn: []
jobs:
@@ -66,82 +85,133 @@ stages:
parameters:
targets:
- name: Sanity
- test: '2.13/sanity/1'
- - stage: Ansible_2_12
- displayName: Sanity 2.12
+ test: 2.13/sanity
+
+ ### Units
+ - stage: Units_devel
+ displayName: Units devel
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
targets:
- - name: Sanity
- test: '2.12/sanity/1'
+ - name: (py3.12)
+ test: devel/units/3.12
+
+ - stage: Units_2_16
+ displayName: Units 2.16
+ dependsOn: []
+ jobs:
+ - template: templates/matrix.yml
+ parameters:
+ targets:
+ - name: (py3.10)
+ test: 2.16/units/3.10
+ - stage: Units_2_15
+ displayName: Units 2.15
+ dependsOn: []
+ jobs:
+ - template: templates/matrix.yml
+ parameters:
+ targets:
+ - name: (py3.9)
+ test: 2.15/units/3.9
+
+ - stage: Units_2_14
+ displayName: Units 2.14
+ dependsOn: []
+ jobs:
+ - template: templates/matrix.yml
+ parameters:
+ targets:
+ - name: (py3.9)
+ test: 2.14/units/3.9
+
+ - stage: Units_2_13
+ displayName: Units 2.13
+ dependsOn: []
+ jobs:
+ - template: templates/matrix.yml
+ parameters:
+ targets:
+ - name: (py3.8)
+ test: 2.13/units/3.8
+
+ ## Integration
+ - stage: Integration_devel
+ displayName: Integration devel
+ dependsOn: []
+ jobs:
+ - template: templates/matrix.yml
+ parameters:
+ groups: [1, 2, 3]
+ targets:
+ - name: (py3.12)
+ test: devel/integration/3.12
-## Integration tests (remote)
- - stage: Hetzner_devel
- displayName: Hetzner devel
+ - stage: Integration_2_16
+ displayName: Integration 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
- groups:
- - 1
- - 2
+ groups: [1, 2, 3]
targets:
- - name: hcloud
- test: 'devel/hcloud/3.9'
+ - name: (py3.10)
+ test: 2.16/integration/3.10
- - stage: Hetzner_2_14
- displayName: Hetzner 2.14
+ - stage: Integration_2_15
+ displayName: Integration 2.15
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
- groups:
- - 1
- - 2
+ groups: [1, 2, 3]
targets:
- - name: hcloud
- test: '2.14/hcloud/3.9'
+ - name: (py3.9)
+ test: 2.15/integration/3.9
- - stage: Hetzner_2_13
- displayName: Hetzner 2.13
+ - stage: Integration_2_14
+ displayName: Integration 2.14
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
- groups:
- - 1
- - 2
+ groups: [1, 2, 3]
targets:
- - name: hcloud
- test: '2.13/hcloud/3.9'
+ - name: (py3.9)
+ test: 2.14/integration/3.9
- - stage: Hetzner_2_12
- displayName: Hetzner 2.12
+ - stage: Integration_2_13
+ displayName: Integration 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
- groups:
- - 1
- - 2
+ groups: [1, 2, 3]
targets:
- - name: hcloud
- test: '2.12/hcloud/3.9'
+ - name: (py3.8)
+ test: 2.13/integration/3.8
-### Finally
+ ### Finally
- stage: Summary
condition: succeededOrFailed()
dependsOn:
- - Ansible_devel
- - Ansible_2_14
- - Ansible_2_13
- - Ansible_2_12
- - Hetzner_devel
- - Hetzner_2_14
- - Hetzner_2_13
- - Hetzner_2_12
+ - Sanity_devel
+ - Sanity_2_16
+ - Sanity_2_15
+ - Sanity_2_14
+ - Sanity_2_13
+ - Units_devel
+ - Units_2_16
+ - Units_2_15
+ - Units_2_14
+ - Units_2_13
+ - Integration_devel
+ - Integration_2_16
+ - Integration_2_15
+ - Integration_2_14
+ - Integration_2_13
jobs:
- template: templates/coverage.yml
diff --git a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/aggregate-coverage.sh b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/aggregate-coverage.sh
index f3113dd0a..c196ab014 100755
--- a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/aggregate-coverage.sh
+++ b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/aggregate-coverage.sh
@@ -13,8 +13,8 @@ options=(--venv --venv-system-site-packages --color -v)
ansible-test coverage combine --export "${agent_temp_directory}/coverage/" "${options[@]}"
-if ansible-test coverage analyze targets generate --help >/dev/null 2>&1; then
- # Only analyze coverage if the installed version of ansible-test supports it.
- # Doing so allows this script to work unmodified for multiple Ansible versions.
- ansible-test coverage analyze targets generate "${agent_temp_directory}/coverage/coverage-analyze-targets.json" "${options[@]}"
+if ansible-test coverage analyze targets generate --help > /dev/null 2>&1; then
+ # Only analyze coverage if the installed version of ansible-test supports it.
+ # Doing so allows this script to work unmodified for multiple Ansible versions.
+ ansible-test coverage analyze targets generate "${agent_temp_directory}/coverage/coverage-analyze-targets.json" "${options[@]}"
fi
diff --git a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/combine-coverage.py b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/combine-coverage.py
index 506ade646..bab3c4226 100755
--- a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/combine-coverage.py
+++ b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/combine-coverage.py
@@ -7,8 +7,7 @@ Keep in mind that Azure Pipelines does not enforce unique job display names (onl
It is up to pipeline authors to avoid name collisions when deviating from the recommended format.
"""
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
+from __future__ import annotations
import os
import re
@@ -20,12 +19,12 @@ def main():
"""Main program entry point."""
source_directory = sys.argv[1]
- if '/ansible_collections/' in os.getcwd():
+ if "/ansible_collections/" in os.getcwd():
output_path = "tests/output"
else:
output_path = "test/results"
- destination_directory = os.path.join(output_path, 'coverage')
+ destination_directory = os.path.join(output_path, "coverage")
if not os.path.exists(destination_directory):
os.makedirs(destination_directory)
@@ -34,27 +33,27 @@ def main():
count = 0
for name in os.listdir(source_directory):
- match = re.search('^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$', name)
- label = match.group('label')
- attempt = int(match.group('attempt'))
+ match = re.search("^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$", name)
+ label = match.group("label")
+ attempt = int(match.group("attempt"))
jobs[label] = max(attempt, jobs.get(label, 0))
for label, attempt in jobs.items():
- name = 'Coverage {attempt} {label}'.format(label=label, attempt=attempt)
+ name = f"Coverage {attempt} {label}"
source = os.path.join(source_directory, name)
source_files = os.listdir(source)
for source_file in source_files:
source_path = os.path.join(source, source_file)
- destination_path = os.path.join(destination_directory, source_file + '.' + label)
- print('"%s" -> "%s"' % (source_path, destination_path))
+ destination_path = os.path.join(destination_directory, source_file + "." + label)
+ print(f'"{source_path}" -> "{destination_path}"')
shutil.copyfile(source_path, destination_path)
count += 1
- print('Coverage file count: %d' % count)
- print('##vso[task.setVariable variable=coverageFileCount]%d' % count)
- print('##vso[task.setVariable variable=outputPath]%s' % output_path)
+ print("Coverage file count: %d" % count)
+ print("##vso[task.setVariable variable=coverageFileCount]%d" % count)
+ print("##vso[task.setVariable variable=outputPath]%s" % output_path)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/publish-codecov.sh b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/publish-codecov.sh
index 6d184f0b8..5dd7cfde7 100755
--- a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/publish-codecov.sh
+++ b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/publish-codecov.sh
@@ -10,18 +10,18 @@ output_path="$1"
curl --silent --show-error https://ansible-ci-files.s3.us-east-1.amazonaws.com/codecov/codecov.sh > codecov.sh
for file in "${output_path}"/reports/coverage*.xml; do
- name="${file}"
- name="${name##*/}" # remove path
- name="${name##coverage=}" # remove 'coverage=' prefix if present
- name="${name%.xml}" # remove '.xml' suffix
+ name="${file}"
+ name="${name##*/}" # remove path
+ name="${name##coverage=}" # remove 'coverage=' prefix if present
+ name="${name%.xml}" # remove '.xml' suffix
- bash codecov.sh \
- -f "${file}" \
- -n "${name}" \
- -X coveragepy \
- -X gcov \
- -X fix \
- -X search \
- -X xcode \
- || echo "Failed to upload code coverage report to codecov.io: ${file}"
+ bash codecov.sh \
+ -f "${file}" \
+ -n "${name}" \
+ -X coveragepy \
+ -X gcov \
+ -X fix \
+ -X search \
+ -X xcode ||
+ echo "Failed to upload code coverage report to codecov.io: ${file}"
done
diff --git a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/report-coverage.sh b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/report-coverage.sh
index 1bd91bdc9..a397f63e7 100755
--- a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/report-coverage.sh
+++ b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/report-coverage.sh
@@ -5,11 +5,11 @@ set -o pipefail -eu
PATH="${PWD}/bin:${PATH}"
-if ! ansible-test --help >/dev/null 2>&1; then
- # Install the devel version of ansible-test for generating code coverage reports.
- # This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs).
- # Since a version of ansible-test is required that can work the output from multiple older releases, the devel version is used.
- pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
+if ! ansible-test --help > /dev/null 2>&1; then
+ # Install the devel version of ansible-test for generating code coverage reports.
+ # This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs).
+ # Since a version of ansible-test is required that can work the output from multiple older releases, the devel version is used.
+ pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
fi
ansible-test coverage xml --stub --venv --venv-system-site-packages --color -v
diff --git a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/run-tests.sh b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/run-tests.sh
index a947fdf01..25a576cba 100755
--- a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/run-tests.sh
+++ b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/run-tests.sh
@@ -4,7 +4,7 @@
set -o pipefail -eu
entry_point="$1"
-test="$2"
+entry_point_args="$2"
read -r -a coverage_branches <<< "$3" # space separated list of branches to run code coverage on for scheduled builds
export COMMIT_MESSAGE
@@ -13,22 +13,22 @@ export COVERAGE
export IS_PULL_REQUEST
if [ "${SYSTEM_PULLREQUEST_TARGETBRANCH:-}" ]; then
- IS_PULL_REQUEST=true
- COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD^2)
+ IS_PULL_REQUEST=true
+ COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD^2)
else
- IS_PULL_REQUEST=
- COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD)
+ IS_PULL_REQUEST=false
+ COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD)
fi
-COMPLETE=
-COVERAGE=
+COMPLETE=false
+COVERAGE=false
if [ "${BUILD_REASON}" = "Schedule" ]; then
- COMPLETE=yes
+ COMPLETE=true
- if printf '%s\n' "${coverage_branches[@]}" | grep -q "^${BUILD_SOURCEBRANCHNAME}$"; then
- COVERAGE=yes
- fi
+ if printf '%s\n' "${coverage_branches[@]}" | grep -q "^${BUILD_SOURCEBRANCHNAME}$"; then
+ COVERAGE=true
+ fi
fi
-"${entry_point}" "${test}" 2>&1 | "$(dirname "$0")/time-command.py"
+"${entry_point}" "${entry_point_args}" 2>&1 | "$(dirname "$0")/time-command.py"
diff --git a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/time-command.py b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/time-command.py
index 5e8eb8d4c..783e745d8 100755
--- a/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/time-command.py
+++ b/ansible_collections/hetzner/hcloud/.azure-pipelines/scripts/time-command.py
@@ -1,8 +1,7 @@
#!/usr/bin/env python
"""Prepends a relative timestamp to each input line from stdin and writes it to stdout."""
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
+from __future__ import annotations
import sys
import time
@@ -12,14 +11,14 @@ def main():
"""Main program entry point."""
start = time.time()
- sys.stdin.reconfigure(errors='surrogateescape')
- sys.stdout.reconfigure(errors='surrogateescape')
+ sys.stdin.reconfigure(errors="surrogateescape")
+ sys.stdout.reconfigure(errors="surrogateescape")
for line in sys.stdin:
seconds = time.time() - start
- sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line))
+ sys.stdout.write("%02d:%02d %s" % (seconds // 60, seconds % 60, line))
sys.stdout.flush()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/ansible_collections/hetzner/hcloud/.azure-pipelines/templates/matrix.yml b/ansible_collections/hetzner/hcloud/.azure-pipelines/templates/matrix.yml
index 4e9555dd3..d0a659f71 100644
--- a/ansible_collections/hetzner/hcloud/.azure-pipelines/templates/matrix.yml
+++ b/ansible_collections/hetzner/hcloud/.azure-pipelines/templates/matrix.yml
@@ -45,11 +45,11 @@ jobs:
parameters:
jobs:
- ${{ if eq(length(parameters.groups), 0) }}:
- - ${{ each target in parameters.targets }}:
- - name: ${{ format(parameters.nameFormat, coalesce(target.name, target.test)) }}
- test: ${{ format(parameters.testFormat, coalesce(target.test, target.name)) }}
- - ${{ if not(eq(length(parameters.groups), 0)) }}:
- - ${{ each group in parameters.groups }}:
- ${{ each target in parameters.targets }}:
- - name: ${{ format(format(parameters.nameGroupFormat, parameters.nameFormat), coalesce(target.name, target.test), group) }}
- test: ${{ format(format(parameters.testGroupFormat, parameters.testFormat), coalesce(target.test, target.name), group) }}
+ - name: ${{ format(parameters.nameFormat, coalesce(target.name, target.test)) }}
+ test: ${{ format(parameters.testFormat, coalesce(target.test, target.name)) }}
+ - ${{ if not(eq(length(parameters.groups), 0)) }}:
+ - ${{ each group in parameters.groups }}:
+ - ${{ each target in parameters.targets }}:
+ - name: ${{ format(format(parameters.nameGroupFormat, parameters.nameFormat), coalesce(target.name, target.test), group) }}
+ test: ${{ format(format(parameters.testGroupFormat, parameters.testFormat), coalesce(target.test, target.name), group) }}
diff --git a/ansible_collections/hetzner/hcloud/.azure-pipelines/templates/test.yml b/ansible_collections/hetzner/hcloud/.azure-pipelines/templates/test.yml
index 5250ed802..a4ea5a78d 100644
--- a/ansible_collections/hetzner/hcloud/.azure-pipelines/templates/test.yml
+++ b/ansible_collections/hetzner/hcloud/.azure-pipelines/templates/test.yml
@@ -9,37 +9,37 @@ parameters:
jobs:
- ${{ each job in parameters.jobs }}:
- - job: test_${{ replace(replace(replace(job.test, '/', '_'), '.', '_'), '-', '_') }}
- displayName: ${{ job.name }}
- container: default
- workspace:
- clean: all
- steps:
- - checkout: self
- fetchDepth: $(fetchDepth)
- path: $(checkoutPath)
- - bash: .azure-pipelines/scripts/run-tests.sh "$(entryPoint)" "${{ job.test }}" "$(coverageBranches)"
- displayName: Run Tests
- - bash: .azure-pipelines/scripts/process-results.sh
- condition: succeededOrFailed()
- displayName: Process Results
- - bash: .azure-pipelines/scripts/aggregate-coverage.sh "$(Agent.TempDirectory)"
- condition: eq(variables.haveCoverageData, 'true')
- displayName: Aggregate Coverage Data
- - task: PublishTestResults@2
- condition: eq(variables.haveTestResults, 'true')
- inputs:
- testResultsFiles: "$(outputPath)/junit/*.xml"
- displayName: Publish Test Results
- - task: PublishPipelineArtifact@1
- condition: eq(variables.haveBotResults, 'true')
- displayName: Publish Bot Results
- inputs:
- targetPath: "$(outputPath)/bot/"
- artifactName: "Bot $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
- - task: PublishPipelineArtifact@1
- condition: eq(variables.haveCoverageData, 'true')
- displayName: Publish Coverage Data
- inputs:
- targetPath: "$(Agent.TempDirectory)/coverage/"
- artifactName: "Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
+ - job: test_${{ replace(replace(replace(job.test, '/', '_'), '.', '_'), '-', '_') }}
+ displayName: ${{ job.name }}
+ container: default
+ workspace:
+ clean: all
+ steps:
+ - checkout: self
+ fetchDepth: $(fetchDepth)
+ path: $(checkoutPath)
+ - bash: .azure-pipelines/scripts/run-tests.sh "$(entryPoint)" "${{ job.test }}" "$(coverageBranches)"
+ displayName: Run Tests
+ - bash: .azure-pipelines/scripts/process-results.sh
+ condition: succeededOrFailed()
+ displayName: Process Results
+ - bash: .azure-pipelines/scripts/aggregate-coverage.sh "$(Agent.TempDirectory)"
+ condition: eq(variables.haveCoverageData, 'true')
+ displayName: Aggregate Coverage Data
+ - task: PublishTestResults@2
+ condition: eq(variables.haveTestResults, 'true')
+ inputs:
+ testResultsFiles: "$(outputPath)/junit/*.xml"
+ displayName: Publish Test Results
+ - task: PublishPipelineArtifact@1
+ condition: eq(variables.haveBotResults, 'true')
+ displayName: Publish Bot Results
+ inputs:
+ targetPath: "$(outputPath)/bot/"
+ artifactName: "Bot $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
+ - task: PublishPipelineArtifact@1
+ condition: eq(variables.haveCoverageData, 'true')
+ displayName: Publish Coverage Data
+ inputs:
+ targetPath: "$(Agent.TempDirectory)/coverage/"
+ artifactName: "Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
diff --git a/ansible_collections/hetzner/hcloud/.flake8 b/ansible_collections/hetzner/hcloud/.flake8
new file mode 100644
index 000000000..9e9cd9200
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/.flake8
@@ -0,0 +1,3 @@
+[flake8]
+extend-ignore =
+ E501
diff --git a/ansible_collections/hetzner/hcloud/.github/release-please-config.json b/ansible_collections/hetzner/hcloud/.github/release-please-config.json
new file mode 100644
index 000000000..dc066f009
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/.github/release-please-config.json
@@ -0,0 +1,15 @@
+{
+ "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
+ "bootstrap-sha": "359539fdd65b3a8849f7ea783cddc700c399c78c",
+ "include-component-in-tag": false,
+ "include-v-in-tag": false,
+ "draft-pull-request": true,
+ "packages": {
+ ".": {
+ "release-type": "simple",
+ "package-name": "hetzner.hcloud",
+ "changelog-path": "changelogs/dev-changelog.md",
+ "extra-files": ["galaxy.yml", "plugins/module_utils/version.py"]
+ }
+ }
+}
diff --git a/ansible_collections/hetzner/hcloud/.github/release-please-manifest.json b/ansible_collections/hetzner/hcloud/.github/release-please-manifest.json
new file mode 100644
index 000000000..b2b35cf9b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/.github/release-please-manifest.json
@@ -0,0 +1 @@
+{".":"2.5.0"}
diff --git a/ansible_collections/hetzner/hcloud/.github/workflows/check-changelog-fragments.yml b/ansible_collections/hetzner/hcloud/.github/workflows/check-changelog-fragments.yml
deleted file mode 100644
index 037ff7ec0..000000000
--- a/ansible_collections/hetzner/hcloud/.github/workflows/check-changelog-fragments.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: antsibull-changelog tests
-
-on: [push, pull_request]
-
-jobs:
- build:
- runs-on: ubuntu-latest
- name: antsibull-changelog-lint
- steps:
- - uses: actions/checkout@v2
- - name: Setup python
- uses: actions/setup-python@v3
- with:
- python-version: "3.10"
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install antsibull-changelog
- - name: test with lint
- run: antsibull-changelog lint
diff --git a/ansible_collections/hetzner/hcloud/.github/workflows/lint.yml b/ansible_collections/hetzner/hcloud/.github/workflows/lint.yml
new file mode 100644
index 000000000..2205c461e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/.github/workflows/lint.yml
@@ -0,0 +1,25 @@
+name: Lint
+
+on:
+ push:
+ branches: [main, stable-1]
+ pull_request:
+
+jobs:
+ docs:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.11"
+ cache: pip
+ cache-dependency-path: requirements.txt
+
+ - name: Install dependencies
+ run: make venv
+
+ - name: Lint docs
+ run: make lint-docs
diff --git a/ansible_collections/hetzner/hcloud/.github/workflows/release-please.yml b/ansible_collections/hetzner/hcloud/.github/workflows/release-please.yml
new file mode 100644
index 000000000..a5b035c14
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/.github/workflows/release-please.yml
@@ -0,0 +1,74 @@
+name: Release-please
+
+on:
+ push:
+ branches: [main]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ release-please:
+ # Do not run on forks.
+ if: github.repository == 'ansible-collections/hetzner.hcloud'
+
+ runs-on: ubuntu-latest
+ steps:
+ - id: release
+ uses: google-github-actions/release-please-action@v4
+ with:
+ token: ${{ secrets.HCLOUD_BOT_TOKEN }}
+ config-file: .github/release-please-config.json
+ manifest-file: .github/release-please-manifest.json
+
+ - name: Prepare outputs
+ id: outputs
+ if: steps.release.outputs.pr != ''
+ run: |
+ echo "pr-updated=true" >> "$GITHUB_OUTPUT"
+ echo "branch=${{ fromJSON(steps.release.outputs.pr).headBranchName }}" >> "$GITHUB_OUTPUT"
+ echo "version=$(echo "${{ fromJSON(steps.release.outputs.pr).title }}" | awk '{print $3}')" >> "$GITHUB_OUTPUT"
+
+ outputs:
+ pr-updated: ${{ steps.outputs.outputs.pr-updated }}
+ branch: ${{ steps.outputs.outputs.branch }}
+ version: ${{ steps.outputs.outputs.version }}
+
+ antsibull-changelog:
+ needs: [release-please]
+ if: needs.release-please.outputs.pr-updated
+
+ runs-on: ubuntu-latest
+ steps:
+ - name: Setup python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.11"
+ - name: Install dependencies
+ run: pip install antsibull-changelog
+
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ needs.release-please.outputs.branch }}
+
+ - name: antsibull-changelog
+ run: antsibull-changelog release --version "${{ needs.release-please.outputs.version }}"
+
+ - name: Check for diff
+ id: antsibull-diff
+ run: |
+ if [[ $(git status --porcelain) ]]; then
+ echo "changed=true" >> "$GITHUB_OUTPUT"
+ fi
+
+ - name: Commit & Push
+ if: ${{ steps.antsibull-diff.outputs.changed }}
+ run: |
+ git config user.name "Hetzner Cloud Bot"
+ git config user.email "45457231+hcloud-bot@users.noreply.github.com"
+
+ git add changelogs/ CHANGELOG.rst
+ git commit -m "chore(main): changelog for version ${{ needs.release-please.outputs.version }}"
+
+ git push --force origin ${{ needs.release-please.outputs.branch }}
diff --git a/ansible_collections/hetzner/hcloud/.github/workflows/stale.yml b/ansible_collections/hetzner/hcloud/.github/workflows/stale.yml
new file mode 100644
index 000000000..d9410ae91
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/.github/workflows/stale.yml
@@ -0,0 +1,13 @@
+name: Close stale issues
+
+on:
+ schedule:
+ - cron: "30 12 * * *"
+
+jobs:
+ stale:
+ permissions:
+ issues: write
+ pull-requests: write
+
+ uses: hetznercloud/.github/.github/workflows/stale.yml@main
diff --git a/ansible_collections/hetzner/hcloud/.github/workflows/vendor.yml b/ansible_collections/hetzner/hcloud/.github/workflows/vendor.yml
new file mode 100644
index 000000000..7fa92f4ef
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/.github/workflows/vendor.yml
@@ -0,0 +1,26 @@
+name: Vendor
+
+on:
+ push:
+ branches: [main, stable-1]
+ paths:
+ - plugins/module_utils/vendor/**
+ - scripts/vendor.py
+ pull_request:
+ paths:
+ - plugins/module_utils/vendor/**
+ - scripts/vendor.py
+
+jobs:
+ check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.11"
+
+ - name: Ensure vendors are not diverging
+ run: make vendor-check
diff --git a/ansible_collections/hetzner/hcloud/.gitignore b/ansible_collections/hetzner/hcloud/.gitignore
index d6a37e5c5..cdfb360ad 100644
--- a/ansible_collections/hetzner/hcloud/.gitignore
+++ b/ansible_collections/hetzner/hcloud/.gitignore
@@ -1,3 +1,5 @@
+.venv
+venv
# Created by https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
# Edit at https://www.gitignore.io/?templates=git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
@@ -55,7 +57,6 @@ flycheck_*.el
# network security
/network-security.data
-
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
@@ -387,3 +388,4 @@ $RECYCLE.BIN/
# End of https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
cloud-config-hcloud.ini
+tests/integration/inventory
diff --git a/ansible_collections/hetzner/hcloud/.gitlab-ci.yml b/ansible_collections/hetzner/hcloud/.gitlab-ci.yml
index 7748f7237..3387f825b 100644
--- a/ansible_collections/hetzner/hcloud/.gitlab-ci.yml
+++ b/ansible_collections/hetzner/hcloud/.gitlab-ci.yml
@@ -1,13 +1,23 @@
+include:
+ - project: cloud/integrations/ci
+ file:
+ - default.yml
+ - pre-commit.yml
+
stages:
+ - test
- sanity
- integration
variables:
- PYTHON_VERSION: "3.9"
+ PYTHON_VERSION: "3.10"
default:
image: python:$PYTHON_VERSION
+pre-commit:
+ extends: [.pre-commit]
+
sanity:
stage: sanity
allow_failure: true
@@ -15,7 +25,7 @@ sanity:
- tags
parallel:
matrix:
- - ANSIBLE_VERSION: ["devel", "2.12", "2.13", "2.14"]
+ - ANSIBLE_VERSION: ["devel", "2.13", "2.14", "2.15"]
GROUP: [1]
script:
- bash tests/utils/gitlab/gitlab.sh ${ANSIBLE_VERSION}/sanity/${GROUP}
diff --git a/ansible_collections/hetzner/hcloud/.pre-commit-config.yaml b/ansible_collections/hetzner/hcloud/.pre-commit-config.yaml
new file mode 100644
index 000000000..d1d1c6a4d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/.pre-commit-config.yaml
@@ -0,0 +1,85 @@
+---
+# See https://pre-commit.com for more information
+# See https://pre-commit.com/hooks.html for more hooks
+exclude: ^plugins/module_utils/vendor/hcloud/.*$
+repos:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.5.0
+ hooks:
+ - id: check-added-large-files
+ - id: check-case-conflict
+ - id: check-symlinks
+ - id: destroyed-symlinks
+
+ - id: check-json
+ - id: check-yaml
+ - id: check-toml
+
+ - id: check-merge-conflict
+ - id: end-of-file-fixer
+ - id: mixed-line-ending
+ - id: trailing-whitespace
+
+ - repo: https://github.com/pre-commit/mirrors-prettier
+ rev: v3.1.0
+ hooks:
+ - id: prettier
+ files: \.(md|ya?ml)$
+ exclude: ^changelogs/(dev-changelog\.md|changelog\.yaml)$
+
+ - repo: https://github.com/asottile/pyupgrade
+ rev: v3.15.0
+ hooks:
+ - id: pyupgrade
+ args: [--py38-plus]
+
+ - repo: https://github.com/pycqa/isort
+ rev: 5.13.2
+ hooks:
+ - id: isort
+
+ - repo: https://github.com/psf/black-pre-commit-mirror
+ rev: 24.1.1
+ hooks:
+ - id: black
+
+ - repo: https://github.com/ansible-community/antsibull-changelog
+ rev: 0.23.0
+ hooks:
+ - id: antsibull-changelog-lint
+ - id: antsibull-changelog-lint-changelog-yaml
+
+ - repo: https://github.com/ansible/ansible-lint
+ rev: v6.22.2
+ hooks:
+ - id: ansible-lint
+ name: ansible-lint
+ args: [--offline]
+ additional_dependencies:
+ - ansible-core>=2.13.3
+ - netaddr
+
+ - repo: local
+ hooks:
+ - id: shfmt
+ name: shfmt
+ description: Format shell scripts with shfmt
+ language: golang
+ additional_dependencies: [mvdan.cc/sh/v3/cmd/shfmt@v3.7.0]
+ entry: shfmt -i 2 -ci -sr -kp -w
+ types: [shell]
+
+ - repo: https://github.com/shellcheck-py/shellcheck-py
+ rev: v0.9.0.6
+ hooks:
+ - id: shellcheck
+
+ - repo: local
+ hooks:
+ - id: check-integration-test-files
+ name: check integration test files
+ description: Ensure the integration test files are in sync
+ language: system
+ entry: scripts/integration-test-files.sh
+ pass_filenames: false
+ files: ^(scripts/integration-test-files.sh$|tests/integration)
diff --git a/ansible_collections/hetzner/hcloud/CHANGELOG.rst b/ansible_collections/hetzner/hcloud/CHANGELOG.rst
index e9eff3cad..2a40778f4 100644
--- a/ansible_collections/hetzner/hcloud/CHANGELOG.rst
+++ b/ansible_collections/hetzner/hcloud/CHANGELOG.rst
@@ -5,6 +5,208 @@ Hetzner Cloud Ansible Collection Release Notes
.. contents:: Topics
+v2.5.0
+======
+
+Minor Changes
+-------------
+
+- Replace deprecated `ansible.netcommon` ip utils with python `ipaddress` module. The `ansible.netcommon` collection is no longer required by the collections.
+- firewall - Allow forcing the deletion of firewalls that are still in use.
+- firewall - Do not silence 'firewall still in use' delete failures.
+- firewall - Return resources the firewall is `applied_to`.
+- firewall_info - Add new `firewall_info` module to gather firewalls info.
+- firewall_resource - Add new `firewall_resource` module to manage firewalls resources.
+- inventory - Add `hostvars_prefix` and hostvars_suffix` options to customize the inventory host variables keys.
+
+New Modules
+-----------
+
+- firewall_resource - Manage Resources a Hetzner Cloud Firewall is applied to.
+
+v2.4.1
+======
+
+Bugfixes
+--------
+
+- hcloud inventory - Ensure the API client use a new cache for every *cached session*.
+
+v2.4.0
+======
+
+Minor Changes
+-------------
+
+- Add the `hetzner.hcloud.all` group to configure all the modules using `module_defaults`.
+- Allow to set the `api_endpoint` module argument using the `HCLOUD_ENDPOINT` environment variable.
+- Removed the `hcloud_` prefix from all modules names, e.g. `hetzner.hcloud.hcloud_firewall` was renamed to `hetzner.hcloud.firewall`. Old module names will continue working.
+- Renamed the `endpoint` module argument to `api_endpoint`, backward compatibility is maintained using an alias.
+- hcloud inventory - Add the `api_endpoint` option.
+- hcloud inventory - Deprecate the `api_token_env` option, suggest using a lookup plugin (`{{ lookup('ansible.builtin.env', 'YOUR_ENV_VAR') }}`) or use the well-known `HCLOUD_TOKEN` environment variable name.
+- hcloud inventory - Rename the `token_env` option to `api_token_env`, use aliases for backward compatibility.
+- hcloud inventory - Rename the `token` option to `api_token`, use aliases for backward compatibility.
+
+v2.3.0
+======
+
+Minor Changes
+-------------
+
+- hcloud_datacenter_info - Add `server_types` field
+- hcloud_server - Add `created` field
+- hcloud_server_info - Add `created` field
+
+v2.2.0
+======
+
+Minor Changes
+-------------
+
+- hcloud_iso_info - Add deprecation field
+- hcloud_load_balancer_network - Allow selecting a `load_balancer` or `network` using its ID.
+- hcloud_load_balancer_service - Allow selecting a `load_balancer` using its ID.
+- hcloud_load_balancer_target - Allow selecting a `load_balancer` or `server` using its ID.
+- hcloud_rdns - Allow selecting a `server`, `floating_ip`, `primary_ip` or `load_balancer` using its ID.
+- hcloud_route - Allow selecting a `network` using its ID.
+- hcloud_server_network - Allow selecting a `network` or `server` using its ID.
+- hcloud_subnetwork - Allow selecting to a `network` using its ID.
+
+v2.1.2
+======
+
+Bugfixes
+--------
+
+- hcloud_firewall - The port argument is required when the firewall rule protocol is `udp` or `tcp`.
+- hcloud_load_balancer_service - In the returned data, the invalid `health_check.http.certificates` field was renamed to `health_check.http.status_codes`.
+
+v2.1.1
+======
+
+Bugfixes
+--------
+
+- hcloud_server - Fix string formatting error on deprecated server type warning
+
+v2.1.0
+======
+
+Minor Changes
+-------------
+
+- Use the collection version in the hcloud user-agent instead of the ansible-core version.
+- hcloud_floating_ip_info - Allow querying floating ip by name.
+- hcloud_load_balancer_info - Add targets health status field.
+- inventory - Allow caching the hcloud inventory.
+
+Bugfixes
+--------
+
+- `*_info` - Consistently fail on invalid ID in `*_info` modules.
+
+v2.0.0
+======
+
+Release Summary
+---------------
+
+This release bundles the hcloud dependency in the collection, this allows us to ship new features or bug fixes without having to release new major versions and require the users to upgrade their version of the hcloud dependency.
+
+Minor Changes
+-------------
+
+- Bundle hcloud python dependency inside the collection.
+- python-dateutil >= 2.7.5 is now required by the collection. If you already have the hcloud package installed, this dependency should also be installed.
+- requests >= 2.20 is now required by the collection. If you already have the hcloud package installed, this dependency should also be installed.
+
+Breaking Changes / Porting Guide
+--------------------------------
+
+- Drop support for ansible-core 2.12
+- Drop support for python 3.7
+- inventory plugin - Don't set the server image variables (`image_id`, `image_os_flavor` and `image_name`) when the server image is not defined.
+
+Removed Features (previously deprecated)
+----------------------------------------
+
+- hcloud_datacenter_facts Removed deprecated facts module
+- hcloud_floating_ip_facts Removed deprecated facts module
+- hcloud_image_facts Removed deprecated facts module
+- hcloud_location_facts Removed deprecated facts module
+- hcloud_server_facts Removed deprecated facts module
+- hcloud_server_type_facts Removed deprecated facts module
+- hcloud_ssh_key_facts Removed deprecated facts module
+- hcloud_volume_facts Removed deprecated facts module
+
+v1.16.0
+=======
+
+Release Summary
+---------------
+
+This release bundles the hcloud dependency in the collection, this allows us to ship new features or bug fixes without having to release new major versions and require the users to upgrade their version of the hcloud dependency.
+
+Minor Changes
+-------------
+
+- Bundle hcloud python dependency inside the collection.
+- python-dateutil >= 2.7.5 is now required by the collection. If you already have the hcloud package installed, this dependency should also be installed.
+- requests >= 2.20 is now required by the collection. If you already have the hcloud package installed, this dependency should also be installed.
+
+v1.15.0
+=======
+
+Minor Changes
+-------------
+
+- hcloud_iso_info Create hcloud_iso_info module
+
+Bugfixes
+--------
+
+- hcloud_image_info Fix facts modules deprecated result key
+- hcloud_location_info Fix facts modules deprecation warnings
+- hcloud_server_type_info Fix facts modules deprecated result dict
+- hcloud_server_type_info Fix facts modules deprecation warnings
+
+v1.14.0
+=======
+
+Minor Changes
+-------------
+
+- hcloud_network Add expose_routes_to_vswitch field.
+- hcloud_network_info Return expose_routes_to_vswitch for network.
+
+v1.13.0
+=======
+
+Minor Changes
+-------------
+
+- hcloud_primary_ip_info Create hcloud_primary_ip_info module
+- hcloud_server Show warning if used server_type is deprecated.
+- hcloud_server_type_info Return deprecation info for server types.
+
+Bugfixes
+--------
+
+- hcloud_server - TypeError when trying to use deprecated image with allow_deprecated_image
+
+v1.12.0
+=======
+
+Minor Changes
+-------------
+
+- hcloud_server_type_info - Add field included_traffic to returned server types
+
+Breaking Changes / Porting Guide
+--------------------------------
+
+- hcloud-python 1.20.0 is now required for full compatibility
+
v1.11.0
=======
diff --git a/ansible_collections/hetzner/hcloud/COPYING b/ansible_collections/hetzner/hcloud/COPYING
index 10926e87f..94a9ed024 100644
--- a/ansible_collections/hetzner/hcloud/COPYING
+++ b/ansible_collections/hetzner/hcloud/COPYING
@@ -672,4 +672,3 @@ may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
-
diff --git a/ansible_collections/hetzner/hcloud/FILES.json b/ansible_collections/hetzner/hcloud/FILES.json
index 5d393e7b2..7fc09f2f0 100644
--- a/ansible_collections/hetzner/hcloud/FILES.json
+++ b/ansible_collections/hetzner/hcloud/FILES.json
@@ -25,14 +25,14 @@
"name": ".azure-pipelines/scripts/aggregate-coverage.sh",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "820353ffde6fd3ad655118772547549d84ccf0a7ba951e8fb1325f912ef640a0",
+ "chksum_sha256": "531abea7db6392f1de84b0809f72737b8505f7e64b11207b17a2e7e6e3bf5cf4",
"format": 1
},
{
"name": ".azure-pipelines/scripts/combine-coverage.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "e34d4e863a65b9f53c4ca8ae37655858969898a949e050e9cb3cb0d5f02342d0",
+ "chksum_sha256": "decbefc6322e3d08d54fb229920166bad6fb36f59dc165d51f7cb98c32dbf0c6",
"format": 1
},
{
@@ -46,28 +46,28 @@
"name": ".azure-pipelines/scripts/publish-codecov.sh",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "70c795c8dbca2534b7909b17911630b7afaa693bbd7154e63a51340bc8b28dad",
+ "chksum_sha256": "e991f98ae3b734710a8c853e5ea3684c0b3333056f2c8d3be143e35efbe0943d",
"format": 1
},
{
"name": ".azure-pipelines/scripts/report-coverage.sh",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "f6a373322759ccc2736fb25d25d8c402dfe16b5d9a57cfccb1ca8cb136e09663",
+ "chksum_sha256": "c9720aee235dfe28ab0c161797cf077c30b56feef7452feb84416b12b6165e6a",
"format": 1
},
{
"name": ".azure-pipelines/scripts/run-tests.sh",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "cb08a3ec5715b00d476ae6d63ca22e11a9ad8887239439937d2a7ea342e5a623",
+ "chksum_sha256": "3134e5893e361cb651eddad6b860f7f2675404a8f29b27a4469bd8e4cf5cfd95",
"format": 1
},
{
"name": ".azure-pipelines/scripts/time-command.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "0232f415efeb583ddff907c058986963b775441eaf129d7162aee0acb0d36834",
+ "chksum_sha256": "ee82a161d94a52873583501cae6c66f17cce0b8d2dd5c72b6bf470351c7ed3ac",
"format": 1
},
{
@@ -88,14 +88,14 @@
"name": ".azure-pipelines/templates/matrix.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "4fb0d3ffb2125d5806c7597e4f9d4b2af69cf8c337e9d57803081eddd4a6b081",
+ "chksum_sha256": "b77f92bac77a91e2c4a4ead402920e338ec0e5813f0a75021d688e9c98f4575d",
"format": 1
},
{
"name": ".azure-pipelines/templates/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "2cfa1271f94c71f05ffa0b1f763d8946394b5636e14579cda8ee14bb38bbcf1c",
+ "chksum_sha256": "e9e72d5efa3e0f5a568ea833bb5f5dc3441c31fb83c215e512ec4b6f18fceb20",
"format": 1
},
{
@@ -109,7 +109,7 @@
"name": ".azure-pipelines/azure-pipelines.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "3c838b484ce8f956163c6fd6ae930f4b792075d5c1b6ddd1130196a48b9333d6",
+ "chksum_sha256": "2caa1318c14d2aa8d9ea75178d1fd142762b00712708d0dced4482bb254db4da",
"format": 1
},
{
@@ -127,10 +127,45 @@
"format": 1
},
{
- "name": ".github/workflows/check-changelog-fragments.yml",
+ "name": ".github/workflows/lint.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c0c78648b73d122ec9cbc96b6b1640ef97fbf31cc8cbb847667ed4b68637f26d",
+ "chksum_sha256": "82e14b10a9c352180c4fa468a84ac330fcb07d3c1e15691b1857f26bfed1dcde",
+ "format": 1
+ },
+ {
+ "name": ".github/workflows/release-please.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5d798fc37f93510a52569257b31062faa3d076cf292ccb4956ee803c851e3061",
+ "format": 1
+ },
+ {
+ "name": ".github/workflows/stale.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "70c41e3f458fe3dd7a748d94e2f577baa52a65ac01300dc72b1a45e2f14bd826",
+ "format": 1
+ },
+ {
+ "name": ".github/workflows/vendor.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "055198ee5dd3ff87c482baa0178158674e50f8674f1b4ebc4238dae383462700",
+ "format": 1
+ },
+ {
+ "name": ".github/release-please-config.json",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "72c031fde659e0ba12c71a2d9a54f3cfbf68f4f76909882a8b9a79b582bffcd5",
+ "format": 1
+ },
+ {
+ "name": ".github/release-please-manifest.json",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "042044c5e6e65c58917f2ca482ea5c6ba22d79d9cd6cd42f422ac9e041573955",
"format": 1
},
{
@@ -165,14 +200,105 @@
"name": "changelogs/changelog.yaml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "3310467c01307e817d9efba1a431034cd39df741f4c758842fce4dd899822d6b",
+ "chksum_sha256": "be4d9f48a034d816590f2e2d5d3f3fe866273f355963f9ad4ab67460b0e72b76",
"format": 1
},
{
"name": "changelogs/config.yaml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "cfa06a718f8b3c226c944d5f33fd3ba5a07415293b07146631503539bea5d1ea",
+ "chksum_sha256": "c75f2c36674d58bbb6ce5936e60183e221367b24949bf8e11530a4b0ff64ee0e",
+ "format": 1
+ },
+ {
+ "name": "changelogs/dev-changelog.md",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ac62c11d1513004587ad3042473970d71d5f767e468f0e42905556df0456bc6c",
+ "format": 1
+ },
+ {
+ "name": "docs",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "docs/docsite",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "docs/docsite/rst",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "docs/docsite/rst/guides.rst",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "73c3bbbf92bbdd10cd528a667fa6772fb6720180421721e244bbf0bc266e55f2",
+ "format": 1
+ },
+ {
+ "name": "docs/docsite/extra-docs.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "75be447658e708b1dd0f959ccdf7f9dbf3aeddfce9bb1fc90cf453449e6e29b2",
+ "format": 1
+ },
+ {
+ "name": "docs/docsite/links.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "104f6ea9937b7c9fd67cbc4a4bb2d14dacfb214565f970713912866d72eb8b9e",
+ "format": 1
+ },
+ {
+ "name": "examples",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "examples/inventory.hcloud.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1be881272139cafcb2a9fe4d9bcce8da1b409925176b5dfa90a75daa85a2b4ab",
+ "format": 1
+ },
+ {
+ "name": "examples/server-with-firewall.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "329fb1fe6e1619827414bd5f51676a7100c032892e264cc8a04c3bfc67f26b27",
+ "format": 1
+ },
+ {
+ "name": "examples/server-with-private-ip-only.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ff8f0e5640dd9c91aa6ebab10a6938124426b7ae5f00e0b6f1895cfb25a3d1f8",
+ "format": 1
+ },
+ {
+ "name": "examples/use-module-defaults-group.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5fca0a688f2a345ab924bb3d2c5922141e43f7c41cdbb890b88e45042f4efcda",
+ "format": 1
+ },
+ {
+ "name": "examples/use-refresh-inventory.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1f92f7fd225c70ab8b80a396006c494cd51daeb35108132f852edad3dac7a612",
"format": 1
},
{
@@ -186,7 +312,7 @@
"name": "meta/runtime.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "3758e45dc3de5da271325c52c3f1a95a8bb518de67721dc634a85e67e93ecc69",
+ "chksum_sha256": "d5bd163e45ad774369d04d500f630d969dd3305dfe292cd49406c5d3912c3bb1",
"format": 1
},
{
@@ -214,7 +340,7 @@
"name": "plugins/doc_fragments/hcloud.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "40624302c695078a48d9883e47133f0b29809c188584af3a314005eb6c495c2d",
+ "chksum_sha256": "36dc9a087d06d4eea1f4c953f765d7573390e923f23761fc6877d97e03c93fa3",
"format": 1
},
{
@@ -235,7 +361,7 @@
"name": "plugins/inventory/hcloud.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "2a457686e85db10e3bde0e48a603988fbb64a121ba11372a869f66c988ea5338",
+ "chksum_sha256": "ab8a8501df0fca5d3947fbebb82a979ec23e3ff03752fedcf8a1a94b427ff76f",
"format": 1
},
{
@@ -246,2026 +372,3545 @@
"format": 1
},
{
- "name": "plugins/module_utils/__init__.py",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "name": "plugins/module_utils/vendor",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "plugins/module_utils/hcloud.py",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "8246c7b016b767dbf0d5bffe0e27d5f2992b83cce4393255f664e41663e2e7dd",
+ "name": "plugins/module_utils/vendor/hcloud",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "plugins/modules",
+ "name": "plugins/module_utils/vendor/hcloud/actions",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "plugins/modules/hcloud_datacenter_facts.py",
+ "name": "plugins/module_utils/vendor/hcloud/actions/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "e35fd6cad5a6e867260be027a13e985623e1e147ec6b25bce848b2cf1d0d1e5f",
+ "chksum_sha256": "35998e4cf41531ce81aff4bd67b78b05f336f27762a66a600a5fd6e10965939e",
"format": 1
},
{
- "name": "plugins/modules/hcloud_floating_ip_facts.py",
+ "name": "plugins/module_utils/vendor/hcloud/actions/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "6f6b9bd26b6f508d71824832ece8b1463e7ff8bc2e9225d1f8694006793b7c16",
+ "chksum_sha256": "93b11a12849e3b2141933ed1763abcc3b3409e7222f68701581794d50ed9c707",
"format": 1
},
{
- "name": "plugins/modules/hcloud_image_facts.py",
+ "name": "plugins/module_utils/vendor/hcloud/actions/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "2383873b050200488ca7c90e6506a7c11539bbc60948fe914eafe1c606047c48",
+ "chksum_sha256": "c560adb2ee230b7f1319ef4fbe41817154ed01273c6a848f052eab3f808b3b32",
"format": 1
},
{
- "name": "plugins/modules/hcloud_location_facts.py",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "7e4c87b1fac74d9b15dd76c462aab1cdb219ddd14009c392162e0e7ce18aecca",
+ "name": "plugins/module_utils/vendor/hcloud/certificates",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "plugins/modules/hcloud_server_facts.py",
+ "name": "plugins/module_utils/vendor/hcloud/certificates/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "69f52a3daa13373f32f14074dc1ef14d586fb5d87d653438dae06d78ef12975f",
+ "chksum_sha256": "fd65d4d36c2c7c0ce095ec376c18fd992488ba6b60f39e56856e4ebc66bdc9b8",
"format": 1
},
{
- "name": "plugins/modules/hcloud_server_type_facts.py",
+ "name": "plugins/module_utils/vendor/hcloud/certificates/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8716f5f31f6fc0c868ea9526812b99b0d67e6645f6e993983967a2a04544e5b6",
+ "chksum_sha256": "4cc351febb45ade25dba56062cdb61968389da7e6c69378229b97c5fcd1f81b9",
"format": 1
},
{
- "name": "plugins/modules/hcloud_ssh_key_facts.py",
+ "name": "plugins/module_utils/vendor/hcloud/certificates/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "6b33f5766ad194010c3bf1b872d27ae6e8bf2fdb5ed7f00fcd998451b7b86528",
+ "chksum_sha256": "88420631111bd32e92d231140c9f6ac07818ede0d06552d60776e0c5f5d9a0bd",
"format": 1
},
{
- "name": "plugins/modules/hcloud_volume_facts.py",
+ "name": "plugins/module_utils/vendor/hcloud/core",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/core/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c2e4545af69cd1ef6dc10ffbf5901b4ba1cae2cb693f5ab4bbde6603e25e6aec",
+ "chksum_sha256": "63b51b70b61e142c7878feb354fcbef40bdc985b1d5c32c49cb5cd04d0ca7ed6",
"format": 1
},
{
- "name": "plugins/modules/__init__.py",
+ "name": "plugins/module_utils/vendor/hcloud/core/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "chksum_sha256": "5c3f76aa70378bd9523ee5198bcbfb58d281d197d5141ef46de3af6e7b37fe55",
"format": 1
},
{
- "name": "plugins/modules/hcloud_certificate.py",
+ "name": "plugins/module_utils/vendor/hcloud/core/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "73e1556df459f2da780aa9aacfd95884cec28e1e14e688aee12df4d521b04825",
+ "chksum_sha256": "6ccbb73a325759635e5259657164db8f29de49c6b45d7ae1bca3abed12198c0d",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/datacenters",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "plugins/modules/hcloud_certificate_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/datacenters/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "181d2abb4c961c065a4661173835d48795e04ed569b2ac91788c5db2b0e9faeb",
+ "chksum_sha256": "bfdba3d6f5da4307851aa5d9ce2d8f6d87a61c39ccfbd9f5248d03658b56b18a",
"format": 1
},
{
- "name": "plugins/modules/hcloud_datacenter_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/datacenters/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "e35fd6cad5a6e867260be027a13e985623e1e147ec6b25bce848b2cf1d0d1e5f",
+ "chksum_sha256": "8032ebdd92944ee7cbb1f8a1a954f1fa6599918d30f554d03e82848ec06dd770",
"format": 1
},
{
- "name": "plugins/modules/hcloud_firewall.py",
+ "name": "plugins/module_utils/vendor/hcloud/datacenters/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "a2541dd2758819ab99904da21c29dcb7f973069d9d228ae16f77ea4bb312b4b7",
+ "chksum_sha256": "27273dc6c5038695d488a075814362e5f72b15e3bf0f86a50738b7b4eedaad39",
"format": 1
},
{
- "name": "plugins/modules/hcloud_floating_ip.py",
+ "name": "plugins/module_utils/vendor/hcloud/deprecation",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/deprecation/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "6668354c432db61272b71c8424a9a2ad38fc9179bb7e5b9c88d049012cf79259",
+ "chksum_sha256": "f8981f1aff8cc4218ee6e9cc95d20e61d75cf27b990c8d56f21b9f498be299f8",
"format": 1
},
{
- "name": "plugins/modules/hcloud_floating_ip_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/deprecation/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "6f6b9bd26b6f508d71824832ece8b1463e7ff8bc2e9225d1f8694006793b7c16",
+ "chksum_sha256": "68c2eb0e3cf46b140835d1773d9bbe047626f523103174a797021283f91e19b1",
"format": 1
},
{
- "name": "plugins/modules/hcloud_image_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/firewalls",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/firewalls/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "2383873b050200488ca7c90e6506a7c11539bbc60948fe914eafe1c606047c48",
+ "chksum_sha256": "e15a656061d0732a0be2963e4a67cd47661246a9472336a7a353631cc38f61cf",
"format": 1
},
{
- "name": "plugins/modules/hcloud_load_balancer.py",
+ "name": "plugins/module_utils/vendor/hcloud/firewalls/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "9040e4d20e62211a45f5e87886d0d4274be88fa5642f7ca838bad6e9e4da85a9",
+ "chksum_sha256": "c32c3715d2ff80af0e03571969428ece0e74ea7141fa0a1f50ec924d2385c14c",
"format": 1
},
{
- "name": "plugins/modules/hcloud_load_balancer_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/firewalls/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "19c0f2673a29c02a85280f75f3cad34ac070ee611eb87f6b12a6ec5d15066349",
+ "chksum_sha256": "5dae67805c04fc8edf2d7d80501fdb52f03e6d2225bc4d196c9fa16893322a21",
"format": 1
},
{
- "name": "plugins/modules/hcloud_load_balancer_network.py",
+ "name": "plugins/module_utils/vendor/hcloud/floating_ips",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/floating_ips/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "1add8639020a29332c474f5d590b523b16c214cfc312aeb9c2fb476e6d6043ba",
+ "chksum_sha256": "aff70816a40dc8d1bfcab950c6ee46a6f35361ac841e0ba8040a03831f5325cf",
"format": 1
},
{
- "name": "plugins/modules/hcloud_load_balancer_service.py",
+ "name": "plugins/module_utils/vendor/hcloud/floating_ips/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c36342c4f33995aed50a5c31de45a14c6636d4c3188edee4fd85ae1d0a4041b1",
+ "chksum_sha256": "a474eb1108064ac1a2cdee352ffc4129e6fda656cc270fbf4d8cc3dcfbee4db9",
"format": 1
},
{
- "name": "plugins/modules/hcloud_load_balancer_target.py",
+ "name": "plugins/module_utils/vendor/hcloud/floating_ips/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "f228d4c8c9e3cbabb11c003db01ba4399195d5881a9e001b24c2e83cec4aed2f",
+ "chksum_sha256": "5f08d0091db38b48e8984c2cc7d56150dd9fe4cd8f0b606b81f699dc816ff194",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/helpers",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "plugins/modules/hcloud_load_balancer_type_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/helpers/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "44b9672195eb0ba06bacd81c871595ca31455ca343887b964d3d6e473509c41a",
+ "chksum_sha256": "821b1278b1c33ce89a4fa7264a245a1c41c5d207aa367f145e01cedd97112471",
"format": 1
},
{
- "name": "plugins/modules/hcloud_location_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/helpers/labels.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "7e4c87b1fac74d9b15dd76c462aab1cdb219ddd14009c392162e0e7ce18aecca",
+ "chksum_sha256": "f24902eb5eeb94db2a649611ed579c165b75a0d649f4fc7eb648e54d9c79f8cd",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/images",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "plugins/modules/hcloud_network.py",
+ "name": "plugins/module_utils/vendor/hcloud/images/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "9e18800b2b9d77a3e14d02460263809ca5859288f4a5db9ac3f5487d590edab2",
+ "chksum_sha256": "1560e51ec1f075fc5e231d7f223530bd8b1230f5996cf8b1d28cc7c81eee7558",
"format": 1
},
{
- "name": "plugins/modules/hcloud_network_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/images/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c672dbebee7fce20c3ace097e427e52e1aa240c3ac32b256a79edee38c7d89c2",
+ "chksum_sha256": "1c2ac5b28d51381625fb7f667173ff0f66ab45f78ced21dbcd1feb26662b2c62",
"format": 1
},
{
- "name": "plugins/modules/hcloud_placement_group.py",
+ "name": "plugins/module_utils/vendor/hcloud/images/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "ac5dcbe68d6775b17a3731be4eae060ab191d649dc4d93ef5bd608d1795c3855",
+ "chksum_sha256": "fb80abb568da31a61478f0ac5b545788b5897f8c60aa5b1b26be4d88bf57ec09",
"format": 1
},
{
- "name": "plugins/modules/hcloud_primary_ip.py",
+ "name": "plugins/module_utils/vendor/hcloud/isos",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/isos/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b9c4bb5f7c6cb8daae694c649910d2191aeb5577b04e5032e9fd4e1cb54acfde",
+ "chksum_sha256": "c9ed2c450144903b843adc29195b069dd58b0adc7dc53f75c43a51766fb48167",
"format": 1
},
{
- "name": "plugins/modules/hcloud_rdns.py",
+ "name": "plugins/module_utils/vendor/hcloud/isos/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "f1ff9bb22dd97a9188cfdfda654bedefb0f261b7ec6b469642e93b0c7ac588db",
+ "chksum_sha256": "438951acaf9becd34968dbfcd0a652f048980237360a2fe9b78a33b381dee443",
"format": 1
},
{
- "name": "plugins/modules/hcloud_route.py",
+ "name": "plugins/module_utils/vendor/hcloud/isos/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "d3b94be64a305628502f5798b6125f6f8f6ae7ab2f249d30c3773c03bf4cab2a",
+ "chksum_sha256": "f43cfe53862e45b9676efa0a0e15b434cac1755d136dccb71a9323525fafe7e6",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/load_balancer_types",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "plugins/modules/hcloud_server.py",
+ "name": "plugins/module_utils/vendor/hcloud/load_balancer_types/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "60ce8badfaa9266dded57290497619e234904a555b6f61d18cfac7f0d581a780",
+ "chksum_sha256": "71caf061c4d466851a43798a1f17bdc19eccb090bd67a1c2a129bd788328899d",
"format": 1
},
{
- "name": "plugins/modules/hcloud_server_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/load_balancer_types/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "69f52a3daa13373f32f14074dc1ef14d586fb5d87d653438dae06d78ef12975f",
+ "chksum_sha256": "1a05bb879c0a8f2f1925b1505a99cb02d163e9998285638e2f1e3430ea835f0c",
"format": 1
},
{
- "name": "plugins/modules/hcloud_server_network.py",
+ "name": "plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8e6d0b574c0c7704b61d89e06b7ea7cae10d3f61f71807e4694f6cfdcf8abb7c",
+ "chksum_sha256": "ded063b76c63624614391fb69f2be72bcfe70ae286c749d2b7c4ea9353567502",
"format": 1
},
{
- "name": "plugins/modules/hcloud_server_type_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/load_balancers",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/load_balancers/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8716f5f31f6fc0c868ea9526812b99b0d67e6645f6e993983967a2a04544e5b6",
+ "chksum_sha256": "161c9000b9234efa249acaadec4ccd9ead7cecee84140f44c4ebd5666c50801d",
"format": 1
},
{
- "name": "plugins/modules/hcloud_ssh_key.py",
+ "name": "plugins/module_utils/vendor/hcloud/load_balancers/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "753f50cadb0aff1240c92302ba83bfe36601d80c08b131f2b975781bf2e0f2f6",
+ "chksum_sha256": "2c06ec62a41f5151fb948f4273e0f9b69cfbd65643583e7743e4a0d5db1215c7",
"format": 1
},
{
- "name": "plugins/modules/hcloud_ssh_key_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/load_balancers/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "6b33f5766ad194010c3bf1b872d27ae6e8bf2fdb5ed7f00fcd998451b7b86528",
+ "chksum_sha256": "040f6ed68c8a9a3c17e3844a84cee66e8c8aa65d9d198008b2a159dbf2c248c2",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/locations",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "plugins/modules/hcloud_subnetwork.py",
+ "name": "plugins/module_utils/vendor/hcloud/locations/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "3100c0f9fe4f184386b57ff90462437649eaab8513631e7ed26db3f4c9514220",
+ "chksum_sha256": "d006c2bebf911826db83f28ea30364c0b1ae5548fb29bf9fcf339f09c69790c8",
"format": 1
},
{
- "name": "plugins/modules/hcloud_volume.py",
+ "name": "plugins/module_utils/vendor/hcloud/locations/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "7b80037e2b1ab8e38dfeb86dcaef129711436ae8314e82288cec7c3be358a94c",
+ "chksum_sha256": "e444638821213c7efbe99e1fb0274c49f5f891e3f54bbde57db3a4bd6517cf89",
"format": 1
},
{
- "name": "plugins/modules/hcloud_volume_info.py",
+ "name": "plugins/module_utils/vendor/hcloud/locations/domain.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c2e4545af69cd1ef6dc10ffbf5901b4ba1cae2cb693f5ab4bbde6603e25e6aec",
+ "chksum_sha256": "b8a294758b7833502cacabaf29cb24d49409aabb581653b8ec8666707ff12208",
"format": 1
},
{
- "name": "tests",
+ "name": "plugins/module_utils/vendor/hcloud/metrics",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration",
- "ftype": "dir",
- "chksum_type": null,
- "chksum_sha256": null,
+ "name": "plugins/module_utils/vendor/hcloud/metrics/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b1ffba070e027a488dad69d9f2c1a1e03773866221659fca418b846368c0ec3a",
"format": 1
},
{
- "name": "tests/integration/targets",
+ "name": "plugins/module_utils/vendor/hcloud/metrics/domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "79e3e2dc74284723c515f1b44f78531cf92e0349dd3ae25dfba93236b7dd9d4e",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/networks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate",
+ "name": "plugins/module_utils/vendor/hcloud/networks/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7b71fdc2ed7722bf7979c1b8b2aab782a8d579aeef322cd4f14c53003e6b1513",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/networks/client.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b5c0ed6f78872df7d0179e8b46b9c6120c27e907db70d98f786edaee11381a0d",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/networks/domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "966de8dfbde97299aa023f3782aed0d0125c6cca3381a793908721fb0581e29e",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/placement_groups",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate/defaults",
+ "name": "plugins/module_utils/vendor/hcloud/placement_groups/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "79f1e97604e25b3b475677ca3a226392e5be0f7563c604a7735838b5c05635a1",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/placement_groups/client.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f0f51f75f0ad37b31a78febf60c1e6b1d8f221de4c616ff8959b9fae77718e92",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/placement_groups/domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c45a8e918b2ad87c7393180da6a1798a1d31ab69099cef858feff9e05caf28db",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/primary_ips",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate/defaults/main.yml",
+ "name": "plugins/module_utils/vendor/hcloud/primary_ips/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8c7f6588b06981201aaac29d9812da66019603bb613dd38f415355e6ea3f2f17",
+ "chksum_sha256": "5e874e0100ae8904b20ae2f6e0c69548cc6c23e9aed3fd0ea1c87d936f6a511e",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate/meta",
+ "name": "plugins/module_utils/vendor/hcloud/primary_ips/client.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "39af4f01f5d85a02db97759e4c6d003ab74fd40952ace0e45e1d20e95a830229",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/primary_ips/domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5e19cd121863e11beab0981443834f28f4a75094a0c7e0a5a061401f2e4f63c2",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/server_types",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate/meta/main.yml",
+ "name": "plugins/module_utils/vendor/hcloud/server_types/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "a613e3027e9e2dd78cda228949082fa43284dae03c297b946e974ee3c0e76129",
+ "chksum_sha256": "e6da3fc784f3da36c212b42215b9e2912328fcd59bb831d3fea471b58acd58a2",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate/tasks",
+ "name": "plugins/module_utils/vendor/hcloud/server_types/client.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "90a3f293748bbb55ee730dd030e58dac40e62dd93e1fa25bcc9db0bc10ae21bc",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/server_types/domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4a54d898753315f1a791d41027c5f5f2ce8e520d83f77eb2e822e8077abba7df",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/servers",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate/tasks/main.yml",
+ "name": "plugins/module_utils/vendor/hcloud/servers/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8fb8130a3dfba9804a0d0cdb26aea93c41ae4fc555c6e0cd1cef303a6556150e",
+ "chksum_sha256": "ad284d5c360237cc9b1ae6915ea70ba7a2cac155e0a0ab4f99248ba941ef2314",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate/aliases",
+ "name": "plugins/module_utils/vendor/hcloud/servers/client.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "0eacb79a9bb8696718a4b8a099c061809ef409bc10418bbeb187f00ca098d4f5",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate_info",
+ "name": "plugins/module_utils/vendor/hcloud/servers/domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1d3f2802d9bcfe35a430f1f52986c353da6601deb864d496f2ec9d5a2d0cc4aa",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/ssh_keys",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate_info/defaults",
+ "name": "plugins/module_utils/vendor/hcloud/ssh_keys/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "aff19b5d16f971f0e48b0c5ef0a33dea3b6d6ecec321c5847111ef51dbe805c2",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/ssh_keys/client.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f9c89c0366b722835fdc6536f9e3af62e1e2209503737eb3c1735049100551a5",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/ssh_keys/domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "76806268d6bf2d7a3a8ffac8a89f5807cd87702370a4ff4c270ed8834bbd1a9d",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/volumes",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate_info/defaults/main.yml",
+ "name": "plugins/module_utils/vendor/hcloud/volumes/__init__.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "54abe03862bd73dde2caed2d60073ae9a9f43aa16642f877891afde936dbadd1",
+ "chksum_sha256": "8a5821b3704a961aca3ae5d3eb702879fe10a515dc54d7a8aa8956b858ea1272",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate_info/meta",
+ "name": "plugins/module_utils/vendor/hcloud/volumes/client.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "81e3bf0dcf125db04983da876f4632706ec52dc2778e7e712653769b13f921cd",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/volumes/domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "651109345eb28455a181de68154a7791f260b68441111c4d2b0df476a2452c59",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ba0400e50866b1dc00567cc8920ca0cf2631465c46030e47535b685273cce6a0",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/_client.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "62318ee61219fc5563fbca19da815d47c2abafb6520606a867c9ce834f9ab7f0",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/_exceptions.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b8207b9aebc834910427cf808480c0bea7c803147eb31cc61d4970c5aa5336d5",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/_version.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3480ae676e9f8016a95ede33f2afba76e90a15747c9a568ea19164c4a4819289",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/hcloud.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2bb04844604c6c109a763d1a0e7eca632219e189fb72bff9ef8d8cbc553eb076",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/hcloud/py.typed",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6d67b0f661e0332f0ba8cbbb46ea905c55cb071876091c747546d2c7edf0138f",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/vendor/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/client.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c0b846cf790f98291097a5d2ebe05235a8e9a65082467e54c76b0e04d97261be",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/hcloud.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "757b549f7087e0a78b69143c190177f46344d1ba510d3b17d34e73534c129b4f",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/version.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ba0c1aca62f6adfabff56202492b5d4941e5ff0a5ef3686821cc046e882baca3",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate_info/meta/main.yml",
+ "name": "plugins/modules/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/certificate.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "09c842e0a9d0933c9abd6d5fae99e861e3a85dcbbcdd21d3ac91287e3ac8b086",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/certificate_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8f161a4e958682a52dbfec80232469482a7017d5eb9fc33c62fac1a8a25e06c",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/datacenter_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "72c739e5039fa088da5705985099c2a089546971d2e312ba836f8e9338d10c58",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/firewall.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "376cdd1493b06f30375afa678898262f1f60061ddff3c8b9269681cc190d3353",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/firewall_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "981f7f9230b0046aebd6b1dee180e52c81b88f79e560d38f7398e49cc20210ba",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/firewall_resource.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "04a07b4ecaa1549c3fa8e6d79e11c98d360a8602bcb36faf1c3c8bf3166f2b2f",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/floating_ip.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3d716b8875aad3a6aa7ac4dab5070c1959e4829fc283a606dafbaa4ced11ccbb",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/floating_ip_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "907a9c87aaaabf470f08a49d1407b8f6e2991988f5d9ee5f53562f3d9ffff3b4",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/image_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e66fedae39facbc1d89b4cd7be1813b980f294990cf3799dc4554833cb43bb81",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/iso_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9366ae2eb9d6fb18d02bd82c776eb6c92ef0e47087aae86dd3b7c2be87f0ae8c",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/load_balancer.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b4f3515b0a9f2eff4907025f7a852d017084e2ab4fc60512a5d97b8f32b9f106",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/load_balancer_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "707101d55ed354171668ec60f1c0769de8976d5fad9c9001a90199e075ed2280",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/load_balancer_network.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "29bc3cc6725abc235f597ce9ebb074613cd74788c135bf6b896ba5e42a9b056d",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/load_balancer_service.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c40d3e075bc53481bce19d3e50a0f216075c1da864e00bc0b4c1bea2b347f4f5",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/load_balancer_target.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "55efb3bbb7018cf5810a5c93d39d3647f245e2e46db1fda2a4a45332e951767b",
+ "chksum_sha256": "ee8c10b5a44fd09723854cb3dd814d1e4f1dea0a5f62107a75ef81bd2e4f2ca3",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate_info/tasks",
+ "name": "plugins/modules/load_balancer_type_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "302a5953254603e46ecac5fb04021228f13ca2e66b67a4dfd57fdbaef4fc3153",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/location_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "15571d3c16960ff15fad111d9602d688acbdd49febc5314a9fc0d57841b07c40",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/network.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7a1eb9cfafb175e0ca130179a0f692263b98823897bc036565d2a48ed723c4ff",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/network_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d89fee964c48a06d0255049ad9981fb4184af29d94a6d4290defb0d54529253f",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/placement_group.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8a77ff1cefd870cce48b03d1a344eca233ed7de3a469977c8b9d35bfb4f18ac0",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/primary_ip.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8642642c6e944824959d671dd536c45f0fcf4c02515515749c56ee0e7778a548",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/primary_ip_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a5957f795d0abb11f0389d6d9bc6f1aafb4ff09ed52b0baf48cf593dd3a8507f",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/rdns.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9734b7c3f08137511a5f6c122e95c3ea003e5f9dc69e12076f5bf5c6614a0d8a",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/route.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1b7f689e4ff302ef28daf7a80b07835b6b6da96f545ec1abdd5213d089a8a4e7",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/server.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a451eac9d2620aba7956e52729842ab4f3297954c0dfcb074d7d2b71a4bed90d",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/server_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "cb88b4ff41204761144380ed9854388f53df45e1bd6da6e8da9446ba128ce9e3",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/server_network.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "376f6464ab45438fa5e5f04168c8d666aaab3ee3916daf6bad6bd64c5349cc5f",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/server_type_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b0f5c0186d54da14115c2a65867e80b7fae4a60e49a7e385faad192ac572d87a",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/ssh_key.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9560f0f9d6ac83fa89acaa7986308cd04d0e4e7464f5fe115c567173fbcdb9f8",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/ssh_key_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ab0a6ea5ffdb1f98525be155ff1e999abdf7d10056c45ef5b2a203803b455606",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/subnetwork.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "908458ed99857ebd8dd05ef3eaf18786beaa8877657bf464ae8481082c9f3699",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/volume.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0b9363ac9df20b307046c6f8ec1f05c93660e020ff831117a1e74144820aa47f",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/volume_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5cb42a56726cab37af48ce4f6742efbadcb413ecdfac82bfbf1852f46cfa9a5e",
+ "format": 1
+ },
+ {
+ "name": "plugins/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "scripts",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate_info/tasks/main.yml",
+ "name": "scripts/integration-test-files.sh",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "a63d83d5da4d2fbea8fd4849cadab7dadb4ade729f6b9fcc6fe5c789e766d725",
+ "chksum_sha256": "d835890c4d8350de8bb621221ce1268cd38f6f3addc58adb86b107ff63306ada",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_certificate_info/aliases",
+ "name": "scripts/vendor.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "d750276690c449d94acffc1c4a65b3d53279f09297a6c296ba99a5b4bc2ed6b9",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_datacenter_info",
+ "name": "tests",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_datacenter_info/defaults",
+ "name": "tests/integration",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_datacenter_info/defaults/main.yml",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "40e03f6534c2f7203b2b3f2aaa720b36d1ef10bfb6e6ab7f46e34bed8c976ec0",
+ "name": "tests/integration/common",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_datacenter_info/meta",
+ "name": "tests/integration/common/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_datacenter_info/meta/main.yml",
+ "name": "tests/integration/common/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/common/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "d8c30f5355ba8e803396d6ea50c3544369aaff6e21a01bfd8aa580c411a8cfe3",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_datacenter_info/tasks",
+ "name": "tests/integration/common/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_datacenter_info/tasks/main.yml",
+ "name": "tests/integration/common/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "d340f77bcf4217306d8913fed14a3fbfcc1c07960e79c9967e194386778bb2c1",
+ "chksum_sha256": "e9f6c6e47087728c97db611995d108175c380225331d1147fe2fc1b85161e03e",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_datacenter_info/aliases",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "name": "tests/integration/targets",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_firewall",
+ "name": "tests/integration/targets/certificate",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_firewall/defaults",
+ "name": "tests/integration/targets/certificate/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_firewall/defaults/main.yml",
+ "name": "tests/integration/targets/certificate/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/certificate/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/certificate/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "61d34ce86e49d5276fafb8777f7bae73bbfa4a19634bd3b20acb7a0478518c62",
+ "chksum_sha256": "d4fad8529286707ffa108e1ef456d63196e37ce0275a793b7acf7e95bba436b8",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_firewall/meta",
+ "name": "tests/integration/targets/certificate/meta",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_firewall/meta/main.yml",
+ "name": "tests/integration/targets/certificate/meta/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "5ca0ad9b9be4ca3dedf78d98ebe3a3c83e0ea1ad47953dc626956fd2fddb6ba8",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_firewall/tasks",
+ "name": "tests/integration/targets/certificate/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_firewall/tasks/main.yml",
+ "name": "tests/integration/targets/certificate/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "123c9c4f92f86644b19fcb25c3be36c460b4c70354f0fbfef84de7ad580954ce",
+ "chksum_sha256": "aafe97e26c1fbaa05d9a65cbcf3dedd5341e5105f0f0fa898e1141c8b17b9514",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_firewall/aliases",
+ "name": "tests/integration/targets/certificate/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/certificate/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ea99c83481a65032bdfa140e98a9c264b168923d717702d64028d6b903608ad9",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip",
+ "name": "tests/integration/targets/certificate/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/certificate_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip/defaults",
+ "name": "tests/integration/targets/certificate_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip/defaults/main.yml",
+ "name": "tests/integration/targets/certificate_info/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/certificate_info/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "fbd1af75fee59098d3aad4eb8d3c33da014855310457f3b28309ea0f6d601782",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip/meta",
+ "name": "tests/integration/targets/certificate_info/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ea2da52d6fb3f83fdb8fb09895aa7bebdbcd3daddf29056bc6f29332438b2b29",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/certificate_info/meta",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip/meta/main.yml",
+ "name": "tests/integration/targets/certificate_info/meta/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "5ca0ad9b9be4ca3dedf78d98ebe3a3c83e0ea1ad47953dc626956fd2fddb6ba8",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip/tasks",
+ "name": "tests/integration/targets/certificate_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip/tasks/main.yml",
+ "name": "tests/integration/targets/certificate_info/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "0276c136a340f6ab58b9d3b70f4c977a65fb71c097afda3085bddfcb388de6b9",
+ "chksum_sha256": "b3dbc0de71d0b7cfa1748b522d515c688af588e852ce8bbe598d382eed0d688c",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip/aliases",
+ "name": "tests/integration/targets/certificate_info/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/certificate_info/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "68d3ec6c207868c15a09077e16e7ae59b3e1f5b36afefd72cdeb4aa8103e2385",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/certificate_info/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8f72dd1ffbf49a8ef7bbafc7b0b109eeee08c55e1d48c5ad85ebae063e0b832e",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/certificate_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/datacenter_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip_info",
+ "name": "tests/integration/targets/datacenter_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip_info/defaults",
+ "name": "tests/integration/targets/datacenter_info/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip_info/defaults/main.yml",
+ "name": "tests/integration/targets/datacenter_info/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/datacenter_info/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8da453a6164fb45ef21bc3c098f838b2fc8d12d218b9a5181033f9d9fe1f10bc",
+ "chksum_sha256": "d03aee3bf07ce52c4114da7533d37eeafbac75d94bfbf2452d072153f6779e82",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip_info/meta",
+ "name": "tests/integration/targets/datacenter_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip_info/meta/main.yml",
+ "name": "tests/integration/targets/datacenter_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/datacenter_info/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "c8fd4d89bc9a54425fbaf95852e31ce7261452b10f58ceb3610d664e8604d3b3",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/datacenter_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip_info/tasks",
+ "name": "tests/integration/targets/firewall/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip_info/tasks/main.yml",
+ "name": "tests/integration/targets/firewall/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "6046d0d6217a122060d5475f76a7cf78577850caca478faa95e8483cbb53d753",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_floating_ip_info/aliases",
+ "name": "tests/integration/targets/firewall/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "f8705fc2213ee576bf8ee5d04a481345dfe2510c79ffde92b6aa175c1125ce8d",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_image_info",
+ "name": "tests/integration/targets/firewall/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_image_info/defaults",
+ "name": "tests/integration/targets/firewall/tasks/cleanup.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8dd870926bba2e051a95750ce3b4eecef5a3833377e161e6bef078928274ad92",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "173da05c6cc7b889b350035f9652014c6c8bd831ab310a8a1b789c1b293dcc07",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ba26d33321fa93dca7304bfb232a2ee64886eb4262db53f561fd3f35eb3905d0",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_image_info/defaults/main.yml",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "8c980497c38e44bc1a09ec895a592835525728c6b43efd9e5ae77242fd0e17d3",
+ "name": "tests/integration/targets/firewall_info/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_image_info/meta",
+ "name": "tests/integration/targets/firewall_info/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_image_info/meta/main.yml",
+ "name": "tests/integration/targets/firewall_info/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_image_info/tasks",
+ "name": "tests/integration/targets/firewall_info/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1693ac14fe568edec1ab921b3e8e531a4224efd18e8661016d8d2c3fe8a4b02c",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_image_info/tasks/main.yml",
+ "name": "tests/integration/targets/firewall_info/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "54275a2526a90d1dd179f685f0a80970f34a6b714bd3ff988a6faa0613ff639d",
+ "chksum_sha256": "8dd870926bba2e051a95750ce3b4eecef5a3833377e161e6bef078928274ad92",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_image_info/aliases",
+ "name": "tests/integration/targets/firewall_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall_info/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "05dfe524b49de9946d238d1a70fa56c406d05d0a88bb0befac879d4e236d35fa",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall_info/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "69d25a91d098086e1e51b175236bc2e407c366b055dde4368e046d81b230ef72",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall_info/aliases",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer",
+ "name": "tests/integration/targets/firewall_resource",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer/defaults",
+ "name": "tests/integration/targets/firewall_resource/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer/defaults/main.yml",
+ "name": "tests/integration/targets/firewall_resource/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall_resource/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "ffd88985ada5f3e746640b7767ad9fd1b2de04da44dad808cb4c44005be83136",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer/meta",
+ "name": "tests/integration/targets/firewall_resource/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1693ac14fe568edec1ab921b3e8e531a4224efd18e8661016d8d2c3fe8a4b02c",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/firewall_resource/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer/meta/main.yml",
+ "name": "tests/integration/targets/firewall_resource/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "8dd870926bba2e051a95750ce3b4eecef5a3833377e161e6bef078928274ad92",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer/tasks",
- "ftype": "dir",
- "chksum_type": null,
- "chksum_sha256": null,
+ "name": "tests/integration/targets/firewall_resource/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer/tasks/main.yml",
+ "name": "tests/integration/targets/firewall_resource/tasks/prepare.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "37823961c8a8ad27ade27df4d929423373e9ad5d8037240f6f137747e39f3c72",
+ "chksum_sha256": "ec7d8cfba75d93fe977b25f3bb61bde4088eab4391f506cf12c3299ee8dd3533",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer/aliases",
+ "name": "tests/integration/targets/firewall_resource/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4",
+ "chksum_sha256": "579d339b4b48dafbe2593389a0c93a623fc12b3b8e574dcb0227ea995f314b3f",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_info",
- "ftype": "dir",
- "chksum_type": null,
- "chksum_sha256": null,
+ "name": "tests/integration/targets/firewall_resource/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_info/defaults",
+ "name": "tests/integration/targets/floating_ip",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_info/defaults/main.yml",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "b8e931c775c02f0df653a7f9b077d0baa6ff8cba2651e7e7e37b2770259b1590",
+ "name": "tests/integration/targets/floating_ip/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_info/meta",
+ "name": "tests/integration/targets/floating_ip/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_info/meta/main.yml",
+ "name": "tests/integration/targets/floating_ip/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_info/tasks",
+ "name": "tests/integration/targets/floating_ip/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ee8ff95cdae5d642d0e2f3e9deec28939b952a333577a0c769d0571c086b0322",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/floating_ip/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_info/tasks/main.yml",
+ "name": "tests/integration/targets/floating_ip/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/floating_ip/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c595101d0d1838a92198660b95c472514fc903757989378c3905cb1d644e5fcd",
+ "chksum_sha256": "16ab089febd775cfa9f5a8a3056011c532a93b1d1f950651a915d62e24d7f19a",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_info/aliases",
+ "name": "tests/integration/targets/floating_ip/aliases",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4",
+ "chksum_sha256": "8f69b796700c4a65ac5e4f99e98e9ed67c924a70ac01a47dc24e97e95ba74cd6",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_network",
+ "name": "tests/integration/targets/floating_ip_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_network/defaults",
+ "name": "tests/integration/targets/floating_ip_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_network/defaults/main.yml",
+ "name": "tests/integration/targets/floating_ip_info/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/floating_ip_info/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/floating_ip_info/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "5f84c924f92341fe78976aac4e941b2b12b351b19db1e2a1ad111d7c75143844",
+ "chksum_sha256": "f47b074a854695595e870da5d5691e5ece467efd750956ffbbcd9d9020efc0e4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_network/meta",
+ "name": "tests/integration/targets/floating_ip_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_network/meta/main.yml",
+ "name": "tests/integration/targets/floating_ip_info/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "99bbb1c9e8aa96c95043637aa790b282d3322c2f8d229576f8f56c5d7dd25f24",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_network/tasks",
- "ftype": "dir",
- "chksum_type": null,
- "chksum_sha256": null,
+ "name": "tests/integration/targets/floating_ip_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/floating_ip_info/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5ee8b6ba8ba3fc445ced424d49d396dbdbe6ee7514fd1ef592d1e9c5b3dab975",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_network/tasks/main.yml",
+ "name": "tests/integration/targets/floating_ip_info/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "5969da2934af118e3359860f30d323073a266f82adc0c1cf85335fc1c387d306",
+ "chksum_sha256": "aca3d846992ca256bfaa2c0d768a9001eb8bfe3ccdf2562badf720a0b872bf96",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_network/aliases",
+ "name": "tests/integration/targets/floating_ip_info/aliases",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4",
+ "chksum_sha256": "8f69b796700c4a65ac5e4f99e98e9ed67c924a70ac01a47dc24e97e95ba74cd6",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/image_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_service",
+ "name": "tests/integration/targets/image_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_service/defaults",
+ "name": "tests/integration/targets/image_info/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_service/defaults/main.yml",
+ "name": "tests/integration/targets/image_info/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "04105693afa5180466c36776a37b716b03bf6a359f433d9a52f4e91845f8ba8a",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_service/meta",
+ "name": "tests/integration/targets/image_info/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f26b39d72138efec41c82970a699845ba8386a646351d5601aa688c60b7eff53",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/image_info/meta",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_service/meta/main.yml",
+ "name": "tests/integration/targets/image_info/meta/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "ad47b88e83ca21b36960d3ae0c769bdd9e675fbb710acd12e359fed6f35f0512",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_service/tasks",
+ "name": "tests/integration/targets/image_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_service/tasks/main.yml",
+ "name": "tests/integration/targets/image_info/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "3107b8864c2eaeaa97d3568f7a52122b64bea694f9903151e073924b1b45574e",
+ "chksum_sha256": "7e951d86914dc01657a37661b746259f9e40dcdcb813126b324692f95412b2f0",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_service/aliases",
+ "name": "tests/integration/targets/image_info/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_target",
- "ftype": "dir",
- "chksum_type": null,
- "chksum_sha256": null,
+ "name": "tests/integration/targets/image_info/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7ea853326f39729110be0b037326a29ec310331efce5034372ccc03203a4e8d7",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_target/defaults",
+ "name": "tests/integration/targets/image_info/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ffe84d68a629b68e7134c3532fb9d37662be13377d7e0bc56287e24d150cacfa",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/image_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/iso_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_target/defaults/main.yml",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "ecbfca90616286afa88ca58f5bd84522a9adb959fb673893e6e4298c6e07ab37",
+ "name": "tests/integration/targets/iso_info/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_target/meta",
+ "name": "tests/integration/targets/iso_info/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_target/meta/main.yml",
+ "name": "tests/integration/targets/iso_info/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_target/tasks",
+ "name": "tests/integration/targets/iso_info/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f5cb61f65fecc3450541bd4b4688c084dc2d11816d139c5bfd1acbb8669081ae",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/iso_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_target/tasks/main.yml",
+ "name": "tests/integration/targets/iso_info/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "3338b80159baa36a184a00750e6943d5cf7770febdc2db91d047f803c9410f6c",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_target/aliases",
+ "name": "tests/integration/targets/iso_info/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4",
+ "chksum_sha256": "6cb6af8c77bcb39364e5ad398cc1e42481e7cb27c78c9234940545b6af75bb97",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/iso_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8f69b796700c4a65ac5e4f99e98e9ed67c924a70ac01a47dc24e97e95ba74cd6",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_type_info",
+ "name": "tests/integration/targets/load_balancer/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_type_info/defaults",
+ "name": "tests/integration/targets/load_balancer/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_type_info/defaults/main.yml",
+ "name": "tests/integration/targets/load_balancer/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "e5641db8ac5de1ea6954d78949fbf6ac9829f86f9135ae9361859aa8220d1892",
+ "chksum_sha256": "f6de5f5e4c25e8c96aae26bd8562abc8e1c96943c8e6c79671a4440aab0742db",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_type_info/meta",
+ "name": "tests/integration/targets/load_balancer/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_type_info/meta/main.yml",
+ "name": "tests/integration/targets/load_balancer/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "5a99ac3c61265385f9385ea4ec0a418e2dffe34761d314f0e62859519229926a",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_type_info/tasks",
- "ftype": "dir",
- "chksum_type": null,
- "chksum_sha256": null,
+ "name": "tests/integration/targets/load_balancer/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_type_info/tasks/main.yml",
+ "name": "tests/integration/targets/load_balancer/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "56fc91b4ed15be279423b2859d700b70589bb1e10bee32a829fa263253917fa2",
+ "chksum_sha256": "fce600c1ef1affccfe85e9dcff37aec4b0871d71d56f2c11120dd3a702a0092a",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_load_balancer_type_info/aliases",
+ "name": "tests/integration/targets/load_balancer/aliases",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "7487e3a1fe3da170468c7132137f40e49195c30d9a6657f44b055c9c641e3953",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_location_info",
+ "name": "tests/integration/targets/load_balancer_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_location_info/defaults",
+ "name": "tests/integration/targets/load_balancer_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_location_info/defaults/main.yml",
+ "name": "tests/integration/targets/load_balancer_info/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_info/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "49468959c5285a8c2c8bccefa9c1d9dca5f0239158eb292bb8f4b768af0fc387",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_location_info/meta",
+ "name": "tests/integration/targets/load_balancer_info/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "bd45a114383aa5d59c5778ca8c73704099082ecf1bc15570c6d176b727964b5c",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_info/meta",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_location_info/meta/main.yml",
+ "name": "tests/integration/targets/load_balancer_info/meta/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_location_info/tasks",
+ "name": "tests/integration/targets/load_balancer_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_location_info/tasks/main.yml",
+ "name": "tests/integration/targets/load_balancer_info/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c56ca0af25e0ff72b7f1eb84a71924b3ba7b65a659f47e2c2ee75e797dfd3ad7",
+ "chksum_sha256": "c225009b2c8cd3de8b711c3fe8d0e1e141d6d183977edb95c91866d0d92738d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_location_info/aliases",
+ "name": "tests/integration/targets/load_balancer_info/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_info/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b24030c8971a1d5cf054c44707ad97ed13c74083e2662a156f99f1f67bd27809",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network",
+ "name": "tests/integration/targets/load_balancer_info/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "983f436cf1f93d8eb8bb3422a29d9880e396a4975c80f8f89ae9ca15516a0502",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7487e3a1fe3da170468c7132137f40e49195c30d9a6657f44b055c9c641e3953",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_network",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network/defaults",
+ "name": "tests/integration/targets/load_balancer_network/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network/defaults/main.yml",
+ "name": "tests/integration/targets/load_balancer_network/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_network/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_network/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c7c1cb312be5bbd4d22ec450029303bd989ec1701b9776f03787f96539fcdd1c",
+ "chksum_sha256": "f1dc2f50249a137e482d1ca622a8e9f50d4e9d52c9e5955c4b0c6d7e305dcacb",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network/meta",
+ "name": "tests/integration/targets/load_balancer_network/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network/meta/main.yml",
+ "name": "tests/integration/targets/load_balancer_network/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network/tasks",
+ "name": "tests/integration/targets/load_balancer_network/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e2b1d11efadf81e27292730061f34398782cbc83a8a2dd3531b3aca5ca1bde1b",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_network/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7487e3a1fe3da170468c7132137f40e49195c30d9a6657f44b055c9c641e3953",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_service",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network/tasks/main.yml",
+ "name": "tests/integration/targets/load_balancer_service/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_service/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_service/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "93baf9ebc898fb93f961dad90033a1a50e0aa9aa4c9cc197aa78587738e42616",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network/aliases",
+ "name": "tests/integration/targets/load_balancer_service/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "67633416742aa9e9480b796190982c057f5a9b7cff7c57625029c3958b07bfb4",
+ "chksum_sha256": "02300d4510db4a06cb1547d249a5162bcc5a0d08d0cb0103f9e70597fbf0e6b1",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network_info",
+ "name": "tests/integration/targets/load_balancer_service/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network_info/defaults",
+ "name": "tests/integration/targets/load_balancer_service/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_service/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "32be6d9a04b2a48cdbd01cf0f8af04eb3bf53f82146103978cb974d746091e19",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_service/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7487e3a1fe3da170468c7132137f40e49195c30d9a6657f44b055c9c641e3953",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_target",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network_info/defaults/main.yml",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "c35ec449e5b6556c7c7205e598fdc98b7dff12a9b4a6be290b3fffd936422dc4",
+ "name": "tests/integration/targets/load_balancer_target/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network_info/meta",
+ "name": "tests/integration/targets/load_balancer_target/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network_info/meta/main.yml",
+ "name": "tests/integration/targets/load_balancer_target/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_target/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "177697b0f735081cbd3ab5edece930f4648659671cc4de4679528b5bee37a749",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network_info/tasks",
+ "name": "tests/integration/targets/load_balancer_target/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network_info/tasks/main.yml",
+ "name": "tests/integration/targets/load_balancer_target/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_target/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "cd53b64efc25ba17d0b8dd5db034e63ddd2bc30bd912766fd8e6f4bed585510a",
+ "chksum_sha256": "ba13cee3ba0ed0d0ba97e4b518f78db4a4c452006aac77b79328da174dc13bd2",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_network_info/aliases",
+ "name": "tests/integration/targets/load_balancer_target/aliases",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4",
+ "chksum_sha256": "7487e3a1fe3da170468c7132137f40e49195c30d9a6657f44b055c9c641e3953",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_type_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_placement_group",
+ "name": "tests/integration/targets/load_balancer_type_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_placement_group/defaults",
+ "name": "tests/integration/targets/load_balancer_type_info/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_placement_group/defaults/main.yml",
+ "name": "tests/integration/targets/load_balancer_type_info/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_type_info/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "17ff18cf59a1d19ba682a9ec20ea00af243721108fb8ae635d26a4f7c8159bdb",
+ "chksum_sha256": "859cd8bca45204be87a549a1029cd610673872a207aeee448d2a7b8c16791fef",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_placement_group/meta",
+ "name": "tests/integration/targets/load_balancer_type_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_placement_group/meta/main.yml",
+ "name": "tests/integration/targets/load_balancer_type_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_type_info/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "91f416ba4aeca7549f77cd552073305770d13e2e612129f8d507164946a8107c",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/load_balancer_type_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/location_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_placement_group/tasks",
+ "name": "tests/integration/targets/location_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_placement_group/tasks/main.yml",
+ "name": "tests/integration/targets/location_info/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/location_info/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "aeb396dd105fc91adda4785d275eef4a421b2a4d8512ae0ad74532452253162f",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_placement_group/aliases",
+ "name": "tests/integration/targets/location_info/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "cec2c8560ce24757623da13bf8b4b96e00d10dc6b27219343de84c302b8a23c7",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_primary_ip",
+ "name": "tests/integration/targets/location_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_primary_ip/defaults",
+ "name": "tests/integration/targets/location_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/location_info/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5820b7ee81974045b5946bbe66668b4f4e9069a47873ef413f5990a0f6704117",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/location_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8f69b796700c4a65ac5e4f99e98e9ed67c924a70ac01a47dc24e97e95ba74cd6",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/network",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_primary_ip/defaults/main.yml",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "e6bd2109171a870ae7429ace6bf18a6c0280f188c0030623a1eb7ec5b8c2f72e",
+ "name": "tests/integration/targets/network/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_primary_ip/meta",
+ "name": "tests/integration/targets/network/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_primary_ip/meta/main.yml",
+ "name": "tests/integration/targets/network/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_primary_ip/tasks",
+ "name": "tests/integration/targets/network/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6ebb966b0125a1f2d47085ec0ec1b7bf5fe77546b0c20e7aa611e5030d6d9858",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/network/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_primary_ip/tasks/main.yml",
+ "name": "tests/integration/targets/network/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "f757913b19fad8b1256fc52046dc8f7bc286e135832837452d54e1744bf6236b",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_primary_ip/aliases",
+ "name": "tests/integration/targets/network/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "0431a784bc8a2466094fd6c62232127726e53f8edaec2a49427005ecd2dcba89",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/network/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9581657d21f8bc0c17584836cc436825d28f40fb04208162424c3e8f5cbd1d17",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_rdns",
+ "name": "tests/integration/targets/network_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_rdns/defaults",
+ "name": "tests/integration/targets/network_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_rdns/defaults/main.yml",
+ "name": "tests/integration/targets/network_info/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/network_info/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/network_info/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8eb41c71669a809fdc595161f96c374cd0514a0fe232db2af105c5b97c86f7d3",
+ "chksum_sha256": "198cc6e4f9cfdacce2d589208c673f7f14bf8275c47b8bced31a3bbd6f773576",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_rdns/meta",
+ "name": "tests/integration/targets/network_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_rdns/meta/main.yml",
+ "name": "tests/integration/targets/network_info/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "cf9085335e8c310c57255c35c9a7f9ed61437277b0eb23af810565ed3a1b63d9",
+ "chksum_sha256": "a5269525807e9843a939b1e5953ee9ce827f6be8afa561e38281487e8e7ef4b5",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_rdns/tasks",
- "ftype": "dir",
- "chksum_type": null,
- "chksum_sha256": null,
+ "name": "tests/integration/targets/network_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_rdns/tasks/main.yml",
+ "name": "tests/integration/targets/network_info/tasks/prepare.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "90b0be18a534d3700c7fefb669b463786e8c3321377b14b909135ba59629f46a",
+ "chksum_sha256": "45693cf1a774261838acc82fc21f2577598271ef46c1e7fb32a292670c1747ca",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_rdns/aliases",
+ "name": "tests/integration/targets/network_info/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4",
+ "chksum_sha256": "eab97cc6891bb3b071b69d017b703629339189b2d0716bbbd7990bfbc6556e66",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_route",
+ "name": "tests/integration/targets/network_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7487e3a1fe3da170468c7132137f40e49195c30d9a6657f44b055c9c641e3953",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/placement_group",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_route/defaults",
+ "name": "tests/integration/targets/placement_group/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_route/defaults/main.yml",
+ "name": "tests/integration/targets/placement_group/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/placement_group/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "73f973bef8b6a33b117aaac954c339df4a6f8c5d482db92f4cc1e95e30153001",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_route/meta",
+ "name": "tests/integration/targets/placement_group/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0f0ae84d1e77da69c3c1301cb427ab012cbca399c2b2eac4e271ecd525fefd06",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/placement_group/meta",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_route/meta/main.yml",
+ "name": "tests/integration/targets/placement_group/meta/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "cf9085335e8c310c57255c35c9a7f9ed61437277b0eb23af810565ed3a1b63d9",
+ "chksum_sha256": "f073c7028f9bc45238179f3d0d3bab0daaa1869b0b99a51689b7cfd848079e9e",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_route/tasks",
+ "name": "tests/integration/targets/placement_group/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_route/tasks/main.yml",
+ "name": "tests/integration/targets/placement_group/tasks/cleanup.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b26e28bc9c79f4ba4df5aaba914a41937602230829a42d5d1deed53a33f93dec",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/placement_group/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/placement_group/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "255e31ee3625bd4d451ac04b084f973ac34913a7e16d019b6c81b36a558bef59",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/placement_group/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "754a7fee0573b3a5c27cba4c53e7f66bb36ca485e153305efbd3b332d52c36d7",
+ "chksum_sha256": "912665632b18f00f5a4e9d5f1d38d6c5ae1500682bd43486cf84e3e2f1fb68d9",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_route/aliases",
+ "name": "tests/integration/targets/placement_group/aliases",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server",
+ "name": "tests/integration/targets/primary_ip",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/defaults",
+ "name": "tests/integration/targets/primary_ip/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/defaults/main.yml",
+ "name": "tests/integration/targets/primary_ip/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/primary_ip/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/primary_ip/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "96ffda2413e62b64c60f03e5861ebeb6bf0f2837775a412cd2f6c166329ce40b",
+ "chksum_sha256": "1a08b93d149ae35d7b4971c436478a6c07d214aa85aa415b163344edd24679ae",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/meta",
+ "name": "tests/integration/targets/primary_ip/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/meta/main.yml",
+ "name": "tests/integration/targets/primary_ip/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/tasks",
+ "name": "tests/integration/targets/primary_ip/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "41dad71607635d485207ada2c6b36b2241bbe8dc625ece233666fa6663dbdced",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/primary_ip/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8f69b796700c4a65ac5e4f99e98e9ed67c924a70ac01a47dc24e97e95ba74cd6",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/primary_ip_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/tasks/basic.yml",
+ "name": "tests/integration/targets/primary_ip_info/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/primary_ip_info/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/primary_ip_info/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "19feb42f8f21128cb8cf3fc0efe562d4d8b2a5d0126bde222ff1fa674204be67",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/tasks/firewalls.yml",
+ "name": "tests/integration/targets/primary_ip_info/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b43203d049ab787df703e53808f6bcaed4917283ee0a6c5108fab3bc7a0533e9",
+ "chksum_sha256": "b08efb022cd220cb621bd279a957fe5077a6f969c39fb0aad6332d5d4e4540e3",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/primary_ip_info/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/tasks/main.yml",
+ "name": "tests/integration/targets/primary_ip_info/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "6be3a83aea87ad5a7d89ebf84718d1881d9106e95b55d0895fc58e8aaad4bb6e",
+ "chksum_sha256": "f485ed9ac7ed72c2e682fcb57a8ea304b1e238b02ed9d4dcbb5340d7af39c7ee",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/tasks/primary_ips.yml",
+ "name": "tests/integration/targets/primary_ip_info/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "67a5ed8f27f4c55daa46c128212ccffda58b15dd9e1adea5fd75d027820d45ee",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/tasks/private_network_only.yml",
+ "name": "tests/integration/targets/primary_ip_info/tasks/prepare.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "6fe7897ff35cd82e4bef8d5a1fa44a6901a16e75b84f605984cd8881120e41fc",
+ "chksum_sha256": "e04ceb120ba9d72ac80a937aa669708e4982d0b7cc15d608a8d94f0325ed4643",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/tasks/validation.yml",
+ "name": "tests/integration/targets/primary_ip_info/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "4ca7c4b3b4460686b05dc9878c6365c99dd2f0e290f6b79563312ac9e48a45d7",
+ "chksum_sha256": "c1a39778efc4b23857542de2a4ac78c34b4e308567b1b20105542cf8d7b5ccc6",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server/aliases",
+ "name": "tests/integration/targets/primary_ip_info/aliases",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4",
+ "chksum_sha256": "8f69b796700c4a65ac5e4f99e98e9ed67c924a70ac01a47dc24e97e95ba74cd6",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_info",
+ "name": "tests/integration/targets/rdns",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_info/defaults",
+ "name": "tests/integration/targets/rdns/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_info/defaults/main.yml",
+ "name": "tests/integration/targets/rdns/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/rdns/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/rdns/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "86d40e0b83f231ac4c5d3d94657d4fb529311261efbba7c0db0093959d82e3a8",
+ "chksum_sha256": "d5c8e1c0a3056d89a3f6faaef42a1d8eb4527c6bc7a4602e39d59ce9ca1e593f",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_info/meta",
+ "name": "tests/integration/targets/rdns/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_info/meta/main.yml",
+ "name": "tests/integration/targets/rdns/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "9b84e2434430aabf5824220a30514d47022f22642441714f3d57f1dd593e2962",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_info/tasks",
+ "name": "tests/integration/targets/rdns/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/rdns/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "954557c50987b4e0c2623decc35154dfb44dfab4bba1712a5a75d174e2152141",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/rdns/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a6339b5c76d064603cf1d80cd67f67e624bcb8fd90a56c8e5965381cc3336bb3",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/rdns/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7487e3a1fe3da170468c7132137f40e49195c30d9a6657f44b055c9c641e3953",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/route",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/route/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_info/tasks/main.yml",
+ "name": "tests/integration/targets/route/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/route/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "9b22f51084b84013a65066696e8e389643dc7bbf35a64545072bf5c6767b71c1",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_info/aliases",
+ "name": "tests/integration/targets/route/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "198cc6e4f9cfdacce2d589208c673f7f14bf8275c47b8bced31a3bbd6f773576",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/route/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/route/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_network",
+ "name": "tests/integration/targets/route/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0031b5a7b0fe8f5d354360f3c0527445614539487ed6d5e99939100daed4fa67",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/route/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7487e3a1fe3da170468c7132137f40e49195c30d9a6657f44b055c9c641e3953",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_network/defaults",
+ "name": "tests/integration/targets/server/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_network/defaults/main.yml",
+ "name": "tests/integration/targets/server/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "0d2464557ed4ade951ffc241834816068b4869198c79cb12d58c3d297f3f9d62",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_network/meta",
+ "name": "tests/integration/targets/server/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f4d3d7d8b59263668e9c41f19f78e5041686be54e72080e3ac7b4660791b66cb",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server/meta",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_network/meta/main.yml",
+ "name": "tests/integration/targets/server/meta/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "f073c7028f9bc45238179f3d0d3bab0daaa1869b0b99a51689b7cfd848079e9e",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_network/tasks",
+ "name": "tests/integration/targets/server/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_network/tasks/main.yml",
+ "name": "tests/integration/targets/server/tasks/cleanup.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b26e28bc9c79f4ba4df5aaba914a41937602230829a42d5d1deed53a33f93dec",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "255e31ee3625bd4d451ac04b084f973ac34913a7e16d019b6c81b36a558bef59",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d86fb4be961c47637ce1aac842c3841a820d4cc71499f60aaf398ebda962ba70",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server/tasks/test_basic.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "bbaa1a6325538510af5f484a375db05fa78e0c01d5eba621c47bb4d1334c6165",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server/tasks/test_firewalls.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1ddcad3dccc8d45a0a35579b57ffad87a4837a296e3503dbb98e18af06c8b618",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server/tasks/test_primary_ips.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "4aaf9b7f5c70031287488817d492fb19e9b23cb8e2f886bcf9c7f2b6bb647bf0",
+ "chksum_sha256": "8caa0b1b0773ce3eaad2afb17670351cf63e477b3c9f49aee4308eb43f22bf20",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_network/aliases",
+ "name": "tests/integration/targets/server/tasks/test_private_network_only.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "864269fd363e663625df637c1cca2ad3a47ca364bbbad59da58cb75c6002a827",
+ "chksum_sha256": "83b5f595d0e1184e26087029a3790b52b4a9382879afc4b74919ba85de3e2fcf",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_type_info",
+ "name": "tests/integration/targets/server/tasks/test_validation.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "36a7a338d06d69fa47aac6fcbf3ff5204d59836548d41c255cfd38726aad6fa5",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8f69b796700c4a65ac5e4f99e98e9ed67c924a70ac01a47dc24e97e95ba74cd6",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_type_info/defaults",
+ "name": "tests/integration/targets/server_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_type_info/defaults/main.yml",
+ "name": "tests/integration/targets/server_info/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_info/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "1be0206ddc23c1059392c89a7d0e321ceccf2f3f04a0a33f2d72ff209fb51b62",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_type_info/meta",
+ "name": "tests/integration/targets/server_info/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "92668ff038a7b9962185484ba6656786f259ef4c9bf03bbc93af8e1da63c8966",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_type_info/meta/main.yml",
+ "name": "tests/integration/targets/server_info/tasks/cleanup.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "565e1f3618e5dbd550c64cf235b172b8e0b00e89ac20c6b26fc50bfeeb16b312",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_info/tasks/prepare.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "09186e955def1c3db23eeeef46aa27cdc43a43c12b5242bf886fbd78504f76a1",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_type_info/tasks",
+ "name": "tests/integration/targets/server_info/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "80d5f9bace3abe6b098985a10f256cfafe206c286c796e4510e02dae92d9be61",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_network",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_network/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_type_info/tasks/main.yml",
+ "name": "tests/integration/targets/server_network/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_network/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "cbc4ccf4a22f6d7cf98a9c1c5710a93611f4992817dd6ffd8260e7c503274852",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_server_type_info/aliases",
+ "name": "tests/integration/targets/server_network/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "237c63c224a0b4cf03d2ed9695571cb3415373629d6db9a15b4d1f7bfbf9cd50",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key",
+ "name": "tests/integration/targets/server_network/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key/defaults",
+ "name": "tests/integration/targets/server_network/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_network/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c8720a7da054c73c059f61d0ed72ddaa434e2cc77bb9593d5bf931c5dccdb7f6",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_network/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0258aae2182ba7af39814062303251139ba3f539c4bd6abcc33c735021c1936f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_type_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key/defaults/main.yml",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "e9edea10b3c410594ee50a56d4ee65e460170c493ac0af8b0cd64e515af2bcde",
+ "name": "tests/integration/targets/server_type_info/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key/meta",
+ "name": "tests/integration/targets/server_type_info/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key/meta/main.yml",
+ "name": "tests/integration/targets/server_type_info/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/server_type_info/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "2267e95d9e1412bfa94ca2ecb76ecf5ea027753e4b50f87cf59c9450f9090b00",
+ "chksum_sha256": "1627b4770407ecf6d1817b248762a9c95ad73946cd567bd3d201d5d8feb9f039",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key/tasks",
+ "name": "tests/integration/targets/server_type_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key/tasks/main.yml",
+ "name": "tests/integration/targets/server_type_info/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "f70d83fc7b47354a328da3c929ef9c7c0eda4d9b98707e5c591399963c15c262",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key/aliases",
+ "name": "tests/integration/targets/server_type_info/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "69cb31ea4e2610e364b7c1e1808771b2d7083ecd000477114601eb1f6554903f",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key_info",
+ "name": "tests/integration/targets/server_type_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/setup_hcloud_cli",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key_info/defaults",
+ "name": "tests/integration/targets/setup_hcloud_cli/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key_info/defaults/main.yml",
+ "name": "tests/integration/targets/setup_hcloud_cli/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "622b6f801a80c1b2c9e0f1743cee078a93689245b8b05744a6797e52cd152272",
+ "chksum_sha256": "ea9ffb6e72f13dfcd04c82c2c97d5fe0f781d8ffcc7ce6644fd102f22ade9c8a",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key_info/meta",
+ "name": "tests/integration/targets/setup_selfsigned_certificate",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key_info/meta/main.yml",
+ "name": "tests/integration/targets/setup_selfsigned_certificate/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "2267e95d9e1412bfa94ca2ecb76ecf5ea027753e4b50f87cf59c9450f9090b00",
+ "chksum_sha256": "a82e09972ee6f55c8ab1f1223693658d2ae6484cf079ee1b7c1df86e434db22b",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key_info/tasks",
+ "name": "tests/integration/targets/setup_ssh_keypair",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key_info/tasks/main.yml",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "f2ac15fb16f8e251a10741c938b839bbe4786accfa7ac34a52624f1b03c4d1a9",
+ "name": "tests/integration/targets/setup_ssh_keypair/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_ssh_key_info/aliases",
+ "name": "tests/integration/targets/setup_ssh_keypair/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "bcf41c2ee52b037558de2be251057f281ba5a179953577a427ff1692820623f8",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/ssh_key",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_subnetwork",
+ "name": "tests/integration/targets/ssh_key/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_subnetwork/defaults",
+ "name": "tests/integration/targets/ssh_key/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_subnetwork/defaults/main.yml",
+ "name": "tests/integration/targets/ssh_key/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "48ec8ba489041f8a7f69a1bdca4f5e2a4fea038317fb8cafd870b9b2dc2aaea9",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_subnetwork/meta",
+ "name": "tests/integration/targets/ssh_key/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "aef3bffd48aac9423474a2460c6dd72ff7ebe21c416fe5511754255af7c0e986",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/ssh_key/meta",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_subnetwork/meta/main.yml",
+ "name": "tests/integration/targets/ssh_key/meta/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "f073c7028f9bc45238179f3d0d3bab0daaa1869b0b99a51689b7cfd848079e9e",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_subnetwork/tasks",
+ "name": "tests/integration/targets/ssh_key/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_subnetwork/tasks/main.yml",
+ "name": "tests/integration/targets/ssh_key/tasks/cleanup.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f4711831c1afed00bb7a91743cd73c0dd48219a7481d46203652614d6196bddf",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/ssh_key/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/ssh_key/tasks/test.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "a1b71650fde2c710274a8e017cca68e43832ed6360f5aa83eb5909f8f8dc00fd",
+ "chksum_sha256": "a989382c4723e0cc5fa7132c0bcbdf1ed98c20f714a70ff1f70b99c3927d3c24",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_subnetwork/aliases",
+ "name": "tests/integration/targets/ssh_key/aliases",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "a48fdbe183742154c38aa6c1658c907b2fac5a90170aca3f813c65234a33845e",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume",
+ "name": "tests/integration/targets/ssh_key_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume/defaults",
+ "name": "tests/integration/targets/ssh_key_info/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume/defaults/main.yml",
+ "name": "tests/integration/targets/ssh_key_info/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/ssh_key_info/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/ssh_key_info/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "4be0ed3631b304c66f46a7443dcc0f05b5d7eb99c8d55dc98cf3a4ec7a513a44",
+ "chksum_sha256": "f2f46edfa24807685a0d8fc8b61c55edcbb8be13b9b0fb8ac94b04778f90e122",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume/meta",
+ "name": "tests/integration/targets/ssh_key_info/meta",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume/meta/main.yml",
+ "name": "tests/integration/targets/ssh_key_info/meta/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "f073c7028f9bc45238179f3d0d3bab0daaa1869b0b99a51689b7cfd848079e9e",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume/tasks",
+ "name": "tests/integration/targets/ssh_key_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume/tasks/main.yml",
+ "name": "tests/integration/targets/ssh_key_info/tasks/cleanup.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b41df455c2d9c29dad9308de40a386808471e6c386ca104bb9f3fcd0f7b86555",
+ "chksum_sha256": "b26e28bc9c79f4ba4df5aaba914a41937602230829a42d5d1deed53a33f93dec",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume/aliases",
+ "name": "tests/integration/targets/ssh_key_info/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/ssh_key_info/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d178f1df74e003613f8994ed427fd67d2f8882f9d745f13dd9c6d62c77ca2b9e",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume_info",
+ "name": "tests/integration/targets/ssh_key_info/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "371a6ad6db6b445c6a0a5b8ab7001eb22fe10bbef016faaa93b48ce7f1b6027a",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/ssh_key_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/subnetwork",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume_info/defaults",
+ "name": "tests/integration/targets/subnetwork/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume_info/defaults/main.yml",
+ "name": "tests/integration/targets/subnetwork/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/subnetwork/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "59d614a7e95cd4313b26fb93a5bc68fc1fd8591c08a103af883e885858232d0f",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume_info/meta",
+ "name": "tests/integration/targets/subnetwork/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "32f6a598c604eec6f0099b84f097aa20a6196d59640c83df05294cf895e02a95",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/subnetwork/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume_info/meta/main.yml",
+ "name": "tests/integration/targets/subnetwork/tasks/cleanup.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a5269525807e9843a939b1e5953ee9ce827f6be8afa561e38281487e8e7ef4b5",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/subnetwork/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/subnetwork/tasks/prepare.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "56045f6ec8ff13b5d0aff5bbc475800a6419ab316cbbed8e8bda4b2613a2549f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/subnetwork/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ce4392dd35f0c625c3882ae3ead18bf959fd0bffae7250f3105d71853110a6fc",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/subnetwork/aliases",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986",
+ "chksum_sha256": "8f69b796700c4a65ac5e4f99e98e9ed67c924a70ac01a47dc24e97e95ba74cd6",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume_info/tasks",
+ "name": "tests/integration/targets/volume/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume_info/tasks/main.yml",
+ "name": "tests/integration/targets/volume/defaults/main",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume/defaults/main/common.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "85ad9de1a55e08bfa43a2fc065a515eda84b9c4cc411fee92084c7f47ad7485b",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
"format": 1
},
{
- "name": "tests/integration/targets/hcloud_volume_info/aliases",
+ "name": "tests/integration/targets/volume/defaults/main/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5",
+ "chksum_sha256": "ddb11611392004f5c051344d1796fe0c612d6a6871e4d7a7f5cf08cfadd01dd9",
"format": 1
},
{
- "name": "tests/integration/targets/setup_selfsigned_certificate",
+ "name": "tests/integration/targets/volume/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/setup_selfsigned_certificate/tasks",
+ "name": "tests/integration/targets/volume/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d647af7b292a38d1c68d348b99fbaea7e40244a3588cb63f6658e44f1dd806c2",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume_info",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "e4d4d2cd1069f55d65c9e6c8017b934023575ecb0540445ac65714d85d422323",
+ "name": "tests/integration/targets/volume_info/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/setup_sshkey",
+ "name": "tests/integration/targets/volume_info/defaults/main",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/setup_sshkey/tasks",
+ "name": "tests/integration/targets/volume_info/defaults/main/common.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be14638f15126802a9e86e2cf7080d6fa592a357eb6bc7330d243a8546ea6218",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume_info/defaults/main/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7d6f2491e4f90d881e3523fdc14381b1afc8a96a4bc201165df04ea92ad1faac",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume_info/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/integration/targets/setup_sshkey/tasks/main.yml",
+ "name": "tests/integration/targets/volume_info/tasks/cleanup.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "23cc28c94d303945afa4d902e2ebff652f7e55260dcc38344f187e25f13fc11c",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume_info/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "016d4c789eb18f7d6cd03c5cd32300a5e1ccec5bb6695aa35b60105c0a5d5d2d",
+ "chksum_sha256": "f8fa7936e810d502f5960448c95b70be0219cb6de06034f8c84aefede2b661d4",
"format": 1
},
{
- "name": "tests/integration/constraints.txt",
+ "name": "tests/integration/targets/volume_info/tasks/prepare.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "67495540cfc7f8c60daeb40ff4607f95f44163cd1ee5d29726042ae7e6c7f45b",
+ "chksum_sha256": "b995c3cda7ee53f795d5f46a823be7c63f3773f8e5844de4463b8430393f6a35",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume_info/tasks/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3f63786237de282418be7b5f82f1c9c2fdaa979f7c66b2dd064074de36ec3b62",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/volume_info/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d924d2bc6bd615c6717c4d8b837fb0c9f5e4bd8df1c4ae94e3f649265d9ed19f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/README.md",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "cd09c93479d97689a033c01fb5ea3644b37fa9821739f770f75ca196858edff1",
"format": 1
},
{
"name": "tests/integration/requirements.txt",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "f8c3336e9a6315d376c59719374e5aced8a1be5d81934e0b39bc9483fdb49dc6",
+ "chksum_sha256": "ecdcaa388cde1f4c3487a06fb5b09ada6870c193a3b0d948132fd96d51bc11f8",
"format": 1
},
{
@@ -2276,164 +3921,213 @@
"format": 1
},
{
- "name": "tests/sanity/ignore-2.12.txt",
+ "name": "tests/sanity/ignore-2.13.txt",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8b8815dcc93330716312b23095ad47d984bd7a039d20a5baa1127ce6d73ca6e8",
+ "chksum_sha256": "6cd38282c4ae22a82047d6491cf2c203b54a59dad3f30b73f760404aaab212b6",
"format": 1
},
{
- "name": "tests/sanity/ignore-2.13.txt",
+ "name": "tests/sanity/ignore-2.14.txt",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8b8815dcc93330716312b23095ad47d984bd7a039d20a5baa1127ce6d73ca6e8",
+ "chksum_sha256": "a81ea2400b9a7784f1ddd256bce51cae5a74dd3e06695e5a452e2754ae0407fc",
"format": 1
},
{
- "name": "tests/sanity/ignore-2.14.txt",
+ "name": "tests/sanity/ignore-2.15.txt",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8b8815dcc93330716312b23095ad47d984bd7a039d20a5baa1127ce6d73ca6e8",
+ "chksum_sha256": "c895e7338fb3f7aa695054166a509d750c337963f7cdd8fbca0e3d458c8eeb6a",
"format": 1
},
{
- "name": "tests/sanity/ignore-2.15.txt",
+ "name": "tests/sanity/ignore-2.16.txt",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "8b8815dcc93330716312b23095ad47d984bd7a039d20a5baa1127ce6d73ca6e8",
+ "chksum_sha256": "c895e7338fb3f7aa695054166a509d750c337963f7cdd8fbca0e3d458c8eeb6a",
"format": 1
},
{
- "name": "tests/utils",
+ "name": "tests/unit",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/utils/gitlab",
+ "name": "tests/unit/module_utils",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/utils/gitlab/gitlab.sh",
+ "name": "tests/unit/module_utils/test_hcloud.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "4649d4c2fc11e85bf786a6a5894aebdb114f32866006f18d3878058b04318501",
+ "chksum_sha256": "548d821beaa35a1804b6f3dc2b3dbd08a1a678ec0ba93a4f6a474d68fc3ed90f",
"format": 1
},
{
- "name": "tests/utils/gitlab/integration.sh",
+ "name": "tests/unit/requirements.txt",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "944d27147a31dfcee01b9a94003b06d1f0ba0c7a396b8fe53f606045ad80d186",
+ "chksum_sha256": "5ccac8097140973987120cb958c4aaf19a44c6026c678b11cb2be4c784ad133a",
"format": 1
},
{
- "name": "tests/utils/gitlab/sanity.sh",
- "ftype": "file",
- "chksum_type": "sha256",
- "chksum_sha256": "d3de6463986d6023f096a2cd43900cecbe697e7b46b4014a6d1c22a7403a7017",
+ "name": "tests/utils",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
"format": 1
},
{
- "name": "tests/utils/shippable",
+ "name": "tests/utils/gitlab",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
- "name": "tests/utils/shippable/check_matrix.py",
+ "name": "tests/utils/gitlab/gitlab.sh",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "eca2864515b1854d55dd78b481962969ac030fa8d10a4fd4edb9833797ee85fb",
+ "chksum_sha256": "9251f81ffb8ee5d83b22743c52a1bc4da60ba0b487c06847be39a9887664a280",
"format": 1
},
{
- "name": "tests/utils/shippable/hcloud.sh",
+ "name": "tests/utils/gitlab/integration.sh",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "99db6946e47cf9e49ab2fccbe0aca8ffc9aaa0918fdc9e3ef543601c55a98713",
+ "chksum_sha256": "944d27147a31dfcee01b9a94003b06d1f0ba0c7a396b8fe53f606045ad80d186",
"format": 1
},
{
- "name": "tests/utils/shippable/sanity.sh",
+ "name": "tests/utils/gitlab/sanity.sh",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "5815f3e7f2275a6a218e94c6529b0bff8dd6c162b2fece0dacca65cf734c0b22",
+ "chksum_sha256": "9b2d61be8801d4975930f40eff00561beccfd9b7a1444ec4fe0b500085f8bab5",
"format": 1
},
{
- "name": "tests/utils/shippable/shippable.sh",
+ "name": "tests/utils/ci.sh",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "76af8f1e1f106ddd5128405aed79a4cfc15f26ee090b1f20c0b82281efecaf51",
+ "chksum_sha256": "37eb9786585891fd9c37037770b91c7bb5551c5def84c877e6420e247d59de6e",
"format": 1
},
{
- "name": "tests/utils/shippable/timing.py",
+ "name": "tests/.gitignore",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "ebb7d3553349747ad41d80899ed353e13cf32fcbecbb6566cf36e9d2bc33703e",
+ "chksum_sha256": "b5726d3ec9335a09c124469eca039523847a6b0f08a083efaefd002b83326600",
"format": 1
},
{
- "name": "tests/utils/shippable/timing.sh",
+ "name": "tests/config.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "f3f3cc03a997cdba719b0542fe668fc612451841cbe840ab36865f30aa54a1bd",
+ "chksum_sha256": "673096e872f1747b59841ac7bc000c35bc81af7581de76f7e8137a4608c9b909",
"format": 1
},
{
- "name": "tests/.gitignore",
+ "name": "tests/constraints.txt",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "b5726d3ec9335a09c124469eca039523847a6b0f08a083efaefd002b83326600",
+ "chksum_sha256": "478864a698082b5ccea9854ad41052b6be43e5417503e31f280fdb4f014b936a",
"format": 1
},
{
"name": "tests/requirements.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "bdf5cf6c8dad0da0a4e726e341c0ba44124759ce387da8c1ab158a6662cb2bb6",
+ "chksum_sha256": "ebad45710389fc9c2f5cc910cab9014355faf15995ea9eb5f620c7de39874777",
+ "format": 1
+ },
+ {
+ "name": ".ansible-lint",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "cf689ed57f2490cabb563d4e59b6abc0fd8d236bf635cf3da4c434cf55f892a7",
+ "format": 1
+ },
+ {
+ "name": ".flake8",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "28c9956d5f02f520015d5b67be3a7c18efc83b97ea9ef54c50e792ed88776ee9",
"format": 1
},
{
"name": ".gitignore",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c30262d952e58b561e2f59039f3dee6b5b16ff266c5e948fa7ea36049a19acfb",
+ "chksum_sha256": "d2486cacee7a77366eb4c121fb5aca1112383898975408da427ea7f2c3ee0f8a",
"format": 1
},
{
"name": ".gitlab-ci.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "1fcd5b6555665ac7b3c1a8ec7c0183fc3c9e35f40d8e549faf02a86b948338bc",
+ "chksum_sha256": "eb567b2e12c80f6541f0afa43e50e8c8b5345ac802ccf7c6b37459ad7b240769",
+ "format": 1
+ },
+ {
+ "name": ".pre-commit-config.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "da31f2118bc2255609a17b9d3cc0e1890355b0b5fbc3d03918afaba12913a1cb",
"format": 1
},
{
"name": "CHANGELOG.rst",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "5c0249d66834ac8b3f72c326bf8666fc3c46ca8d8f023b9363745a0b7c51e358",
+ "chksum_sha256": "367305440cc3eb10145002d97843578480820303a33ba94efad87790c113090c",
"format": 1
},
{
"name": "COPYING",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "0ae0485a5bd37a63e63603596417e4eb0e653334fa6c7f932ca3a0e85d4af227",
+ "chksum_sha256": "8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b165a1dcd80c7c545eb65b903",
+ "format": 1
+ },
+ {
+ "name": "Makefile",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "aafc23f45f3a932b4cb743f04ba476e20334967e6f694b1c60e8e45e95ea7b67",
"format": 1
},
{
"name": "README.md",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "036ac8c2ec4dcbbdea4b3b5e8bb5ad1e0576ffa4795ad7dc6245da27f8f7998e",
+ "chksum_sha256": "60ad30b06e6a30077c22cc3c6993a0f254b5003d1965a8654ecf24a12b5e5ea2",
+ "format": 1
+ },
+ {
+ "name": "pyproject.toml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b3d7daeee52b89e89e6d9ae221c798c93e534aab36d40ce2a5779fc407ee4a2b",
+ "format": 1
+ },
+ {
+ "name": "renovate.json",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e661c54a7b50c698a98791849805cc4e8f80df0814fdc935c5cf2b87bcb6bdec",
+ "format": 1
+ },
+ {
+ "name": "requirements.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5bd140232f60ddf13de976b1fb62d039e9e095c3d3e61ea0a2f85b2e2ff56f19",
"format": 1
}
],
diff --git a/ansible_collections/hetzner/hcloud/MANIFEST.json b/ansible_collections/hetzner/hcloud/MANIFEST.json
index 3a02e99d8..9a5a2871e 100644
--- a/ansible_collections/hetzner/hcloud/MANIFEST.json
+++ b/ansible_collections/hetzner/hcloud/MANIFEST.json
@@ -2,7 +2,7 @@
"collection_info": {
"namespace": "hetzner",
"name": "hcloud",
- "version": "1.11.0",
+ "version": "2.5.0",
"authors": [
"Hetzner Cloud (github.com/hetznercloud)"
],
@@ -17,9 +17,7 @@
"GPL-3.0-or-later"
],
"license_file": null,
- "dependencies": {
- "ansible.netcommon": ">=0.0.1"
- },
+ "dependencies": {},
"repository": "https://github.com/ansible-collections/hetzner.hcloud",
"documentation": "https://docs.ansible.com/ansible/latest/collections/hetzner/hcloud",
"homepage": "https://github.com/ansible-collections/hetzner.hcloud",
@@ -29,7 +27,7 @@
"name": "FILES.json",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "c08aa88abd3883a1ce05b7b35a56516e099b1d2b8acbc37dc495d39e2874c31a",
+ "chksum_sha256": "afff741537d1ee1b0ef966debfc999feb8bcab30ee5b5780613c7de284cfbb58",
"format": 1
},
"format": 1
diff --git a/ansible_collections/hetzner/hcloud/Makefile b/ansible_collections/hetzner/hcloud/Makefile
new file mode 100644
index 000000000..48c411d64
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/Makefile
@@ -0,0 +1,42 @@
+SHELL := bash
+.PHONY: vendor clean
+
+vendor:
+ python3 scripts/vendor.py
+
+vendor-check:
+ python3 scripts/vendor.py --check
+
+venv:
+ python3 -m venv venv
+ venv/bin/pip install -r requirements.txt
+
+lint: venv
+ venv/bin/pylint plugins
+
+lint-docs: venv
+ venv/bin/antsibull-docs lint-collection-docs \
+ --plugin-docs \
+ --validate-collection-refs self \
+ .
+
+clean:
+ git clean -xdf \
+ -e tests/integration/cloud-config-hcloud.ini
+
+sanity:
+ ansible-test sanity --color --truncate 0 -v \
+ --exclude plugins/module_utils/vendor/ \
+ --exclude scripts/ \
+ --exclude tests/utils/ \
+ --docker default \
+ --allow-disabled
+
+units:
+ ansible-test units --color --truncate 0 -v \
+ --docker default
+
+integration:
+ ansible-test integration --color --truncate 0 -v \
+ --docker default \
+ --allow-disabled
diff --git a/ansible_collections/hetzner/hcloud/README.md b/ansible_collections/hetzner/hcloud/README.md
index f57ae7be3..274c90884 100644
--- a/ansible_collections/hetzner/hcloud/README.md
+++ b/ansible_collections/hetzner/hcloud/README.md
@@ -1,20 +1,29 @@
-[![Build Status](https://dev.azure.com/ansible/hetzner.hcloud/_apis/build/status/CI?branchName=master)](https://dev.azure.com/ansible/hetzner.hcloud/_build?definitionId=35)
+[![Galaxy version](https://img.shields.io/badge/dynamic/json?label=galaxy&prefix=v&url=https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/index/hetzner/hcloud/&query=highest_version.version)](https://galaxy.ansible.com/ui/repo/published/hetzner/hcloud)
+[![GitHub version](https://img.shields.io/github/v/release/ansible-collections/hetzner.hcloud)](https://github.com/ansible-collections/hetzner.hcloud/releases)
+[![Build Status](https://dev.azure.com/ansible/hetzner.hcloud/_apis/build/status/ci?branchName=main)](https://dev.azure.com/ansible/hetzner.hcloud/_build?definitionId=35)
[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/hetzner.hcloud)](https://codecov.io/gh/ansible-collections/hetzner.hcloud)
-Ansible Collection: hetzner.hcloud
-=================================================
+# Ansible Collection: hetzner.hcloud
Ansible Hetzner Cloud Collection for controlling your Hetzner Cloud Resources.
+### Python version compatibility
+
+This collection depends on the [hcloud](https://github.com/hetznercloud/hcloud-python) library. Due to the [hcloud](https://github.com/hetznercloud/hcloud-python) Python Support Policy this collection requires Python 3.8 or greater.
+
## Release notes
See [here](https://github.com/ansible-collections/hetzner.hcloud/tree/master/CHANGELOG.rst).
+### Release policy
+
+The `main` branch is used for the development of the latest versions of the collections, and may contain breaking changes. The `stable-*` branches (e.g. `stable-1` for the `1.x.y` releases) are used to cut additional minor or patch releases if needed, but we do not provide official support for multiple versions of the collection.
+
## Documentation
The documentation for all modules are available through `ansible-doc`.
-Sample: `ansible-doc hetzner.hcloud.hcloud_server` shows the documentation for the `hcloud_server` module.
+Sample: `ansible-doc hetzner.hcloud.server` shows the documentation for the `server` module.
For all modules that were part of Ansible directly (before Ansible 2.11) we also have the documentation published in the
Ansible documentation: https://docs.ansible.com/ansible/latest/collections/hetzner/hcloud/
@@ -47,16 +56,9 @@ After this you should be able to use `ansible-test integration` to perform the i
Sample:
```
-ansible-test integration --color --local -vvv hcloud_server // Executed all integration tests for hcloud_server module
+ansible-test integration --color --local -vvv hetzner.hcloud.server // Executed all integration tests for server module
```
## Releasing a new version
-### Generating changelog from fragments
-
-1. Check if the changelog fragments are available (there should be files in `changelogs/fragments`)
-2. Run `antsibull-changelog release --version <version>`, it should remove all fragments and change
- the `changelogs/changlog.yaml` and `CHANGELOG.rst`
-3. Push the changes to the main branch
-4. Tag the release through the Github UI, after this the Github Actions will run and publish the collection to Ansible
- Galaxy
+If there are releasable changes, `release-please` will open a PR on GitHub with the proposed version. When this PR is merged, `release-please` will tag the release.
diff --git a/ansible_collections/hetzner/hcloud/changelogs/changelog.yaml b/ansible_collections/hetzner/hcloud/changelogs/changelog.yaml
index 0a4f123d0..cba509728 100644
--- a/ansible_collections/hetzner/hcloud/changelogs/changelog.yaml
+++ b/ansible_collections/hetzner/hcloud/changelogs/changelog.yaml
@@ -97,6 +97,64 @@ releases:
fragments:
- arm-features.yaml
release_date: '2023-04-11'
+ 1.12.0:
+ changes:
+ breaking_changes:
+ - hcloud-python 1.20.0 is now required for full compatibility
+ minor_changes:
+ - hcloud_server_type_info - Add field included_traffic to returned server types
+ fragments:
+ - server-type-included-traffic.yml
+ release_date: '2023-05-16'
+ 1.13.0:
+ changes:
+ bugfixes:
+ - hcloud_server - TypeError when trying to use deprecated image with allow_deprecated_image
+ minor_changes:
+ - hcloud_primary_ip_info Create hcloud_primary_ip_info module
+ - hcloud_server Show warning if used server_type is deprecated.
+ - hcloud_server_type_info Return deprecation info for server types.
+ fragments:
+ - create_primary_ip_info.yml
+ - server-type-deprecation.yml
+ - server_error_deprecated_image.yml
+ release_date: '2023-06-20'
+ 1.14.0:
+ changes:
+ minor_changes:
+ - hcloud_network Add expose_routes_to_vswitch field.
+ - hcloud_network_info Return expose_routes_to_vswitch for network.
+ fragments:
+ - add-field-expose_routes_to_vswitch.yml
+ release_date: '2023-06-22'
+ 1.15.0:
+ changes:
+ bugfixes:
+ - hcloud_image_info Fix facts modules deprecated result key
+ - hcloud_location_info Fix facts modules deprecation warnings
+ - hcloud_server_type_info Fix facts modules deprecated result dict
+ - hcloud_server_type_info Fix facts modules deprecation warnings
+ minor_changes:
+ - hcloud_iso_info Create hcloud_iso_info module
+ fragments:
+ - add-hcloud_iso_info-module.yml
+ - fix-facts-modules-deprecation.yml
+ release_date: '2023-07-04'
+ 1.16.0:
+ changes:
+ minor_changes:
+ - Bundle hcloud python dependency inside the collection.
+ - python-dateutil >= 2.7.5 is now required by the collection. If you already
+ have the hcloud package installed, this dependency should also be installed.
+ - requests >= 2.20 is now required by the collection. If you already have the
+ hcloud package installed, this dependency should also be installed.
+ release_summary: This release bundles the hcloud dependency in the collection,
+ this allows us to ship new features or bug fixes without having to release
+ new major versions and require the users to upgrade their version of the hcloud
+ dependency.
+ fragments:
+ - vendor-hcloud-python-dependency.yml
+ release_date: '2023-07-13'
1.2.0:
changes:
minor_changes:
@@ -273,3 +331,160 @@ releases:
fragments:
- hcloud_server-removed-networks.yml
release_date: '2022-12-20'
+ 2.0.0:
+ changes:
+ breaking_changes:
+ - Drop support for ansible-core 2.12
+ - Drop support for python 3.7
+ - inventory plugin - Don't set the server image variables (`image_id`, `image_os_flavor`
+ and `image_name`) when the server image is not defined.
+ minor_changes:
+ - Bundle hcloud python dependency inside the collection.
+ - python-dateutil >= 2.7.5 is now required by the collection. If you already
+ have the hcloud package installed, this dependency should also be installed.
+ - requests >= 2.20 is now required by the collection. If you already have the
+ hcloud package installed, this dependency should also be installed.
+ release_summary: This release bundles the hcloud dependency in the collection,
+ this allows us to ship new features or bug fixes without having to release
+ new major versions and require the users to upgrade their version of the hcloud
+ dependency.
+ removed_features:
+ - hcloud_datacenter_facts Removed deprecated facts module
+ - hcloud_floating_ip_facts Removed deprecated facts module
+ - hcloud_image_facts Removed deprecated facts module
+ - hcloud_location_facts Removed deprecated facts module
+ - hcloud_server_facts Removed deprecated facts module
+ - hcloud_server_type_facts Removed deprecated facts module
+ - hcloud_ssh_key_facts Removed deprecated facts module
+ - hcloud_volume_facts Removed deprecated facts module
+ fragments:
+ - do-not-set-inventory-server-image-variables-when-undefined.yml
+ - drop-support-for-ansible-core-2.12.yml
+ - drop-support-for-python-3.7.yml
+ - remove-deprecated-facts-modules.yml
+ - vendor-hcloud-python-dependency.yml
+ release_date: '2023-07-24'
+ 2.1.0:
+ changes:
+ bugfixes:
+ - '`*_info` - Consistently fail on invalid ID in `*_info` modules.'
+ minor_changes:
+ - Use the collection version in the hcloud user-agent instead of the ansible-core
+ version.
+ - hcloud_floating_ip_info - Allow querying floating ip by name.
+ - hcloud_load_balancer_info - Add targets health status field.
+ - inventory - Allow caching the hcloud inventory.
+ fragments:
+ - add-target-health-status-in-hcloud_load_balancer_info.yml
+ - allow-caching-hcloud-inventory.yml
+ - consistently-fail-on-invalid-id.yml
+ - query-hcloud_floating_ip_info-by-name.yml
+ - use-collection-version-in-user-agent.yml
+ release_date: '2023-08-17'
+ 2.1.1:
+ changes:
+ bugfixes:
+ - hcloud_server - Fix string formatting error on deprecated server type warning
+ fragments:
+ - fix-string-formatting-error-on-deprecated-server-type-warning.yml
+ release_date: '2023-08-23'
+ 2.1.2:
+ changes:
+ bugfixes:
+ - hcloud_firewall - The port argument is required when the firewall rule protocol
+ is `udp` or `tcp`.
+ - hcloud_load_balancer_service - In the returned data, the invalid `health_check.http.certificates`
+ field was renamed to `health_check.http.status_codes`.
+ fragments:
+ - rename-load-balancer-service-http-health-check-dict.yaml
+ - require-firewall-port-argument-on-tcp-or-udp-protocol.yaml
+ release_date: '2023-10-05'
+ 2.2.0:
+ changes:
+ minor_changes:
+ - hcloud_iso_info - Add deprecation field
+ - hcloud_load_balancer_network - Allow selecting a `load_balancer` or `network`
+ using its ID.
+ - hcloud_load_balancer_service - Allow selecting a `load_balancer` using its
+ ID.
+ - hcloud_load_balancer_target - Allow selecting a `load_balancer` or `server`
+ using its ID.
+ - hcloud_rdns - Allow selecting a `server`, `floating_ip`, `primary_ip` or `load_balancer`
+ using its ID.
+ - hcloud_route - Allow selecting a `network` using its ID.
+ - hcloud_server_network - Allow selecting a `network` or `server` using its
+ ID.
+ - hcloud_subnetwork - Allow selecting to a `network` using its ID.
+ fragments:
+ - add-deprecation-field-to-iso-info.yaml
+ - allow-selecting-a-resource-using-its-id.yaml
+ release_date: '2023-10-23'
+ 2.3.0:
+ changes:
+ minor_changes:
+ - hcloud_datacenter_info - Add `server_types` field
+ - hcloud_server - Add `created` field
+ - hcloud_server_info - Add `created` field
+ fragments:
+ - add-server_types-to-datacenter-info.yaml
+ - add_created_to_server_info.yaml
+ release_date: '2023-11-07'
+ 2.4.0:
+ changes:
+ minor_changes:
+ - Add the `hetzner.hcloud.all` group to configure all the modules using `module_defaults`.
+ - Allow to set the `api_endpoint` module argument using the `HCLOUD_ENDPOINT`
+ environment variable.
+ - Removed the `hcloud_` prefix from all modules names, e.g. `hetzner.hcloud.hcloud_firewall`
+ was renamed to `hetzner.hcloud.firewall`. Old module names will continue working.
+ - Renamed the `endpoint` module argument to `api_endpoint`, backward compatibility
+ is maintained using an alias.
+ - hcloud inventory - Add the `api_endpoint` option.
+ - hcloud inventory - Deprecate the `api_token_env` option, suggest using a lookup
+ plugin (`{{ lookup('ansible.builtin.env', 'YOUR_ENV_VAR') }}`) or use the
+ well-known `HCLOUD_TOKEN` environment variable name.
+ - hcloud inventory - Rename the `token_env` option to `api_token_env`, use aliases
+ for backward compatibility.
+ - hcloud inventory - Rename the `token` option to `api_token`, use aliases for
+ backward compatibility.
+ fragments:
+ - add-module-defaults-group-for-all-modules.yml
+ - improve-inventory-api-options.yml
+ - improve-modules-api-arguments.yml
+ - remove-hcloud-prefix-from-modules-names.yml
+ release_date: '2023-11-24'
+ 2.4.1:
+ changes:
+ bugfixes:
+ - hcloud inventory - Ensure the API client use a new cache for every *cached
+ session*.
+ fragments:
+ - fix-inventory-fresh-cache.yaml
+ release_date: '2023-11-27'
+ 2.5.0:
+ changes:
+ minor_changes:
+ - 'Replace deprecated `ansible.netcommon` ip utils with python `ipaddress` module.
+ The `ansible.netcommon` collection is no longer required by the collections.
+
+ '
+ - firewall - Allow forcing the deletion of firewalls that are still in use.
+ - firewall - Do not silence 'firewall still in use' delete failures.
+ - firewall - Return resources the firewall is `applied_to`.
+ - firewall_info - Add new `firewall_info` module to gather firewalls info.
+ - firewall_resource - Add new `firewall_resource` module to manage firewalls
+ resources.
+ - 'inventory - Add `hostvars_prefix` and hostvars_suffix` options to customize
+ the inventory host variables keys.
+
+ '
+ fragments:
+ - add-inventory-hostvars-prefix-and-suffix-option.yml
+ - fix-firewall-deletion.yml
+ - improve-firewall-resources-management.yml
+ - replace-deprecated-ansible.netcommon-with-python-ipaddress.yml
+ modules:
+ - description: Manage Resources a Hetzner Cloud Firewall is applied to.
+ name: firewall_resource
+ namespace: ''
+ release_date: '2024-02-02'
diff --git a/ansible_collections/hetzner/hcloud/changelogs/config.yaml b/ansible_collections/hetzner/hcloud/changelogs/config.yaml
index 739603a44..688ddbb0b 100644
--- a/ansible_collections/hetzner/hcloud/changelogs/config.yaml
+++ b/ansible_collections/hetzner/hcloud/changelogs/config.yaml
@@ -10,19 +10,19 @@ notesdir: fragments
prelude_section_name: release_summary
prelude_section_title: Release Summary
sections:
-- - major_changes
- - Major Changes
-- - minor_changes
- - Minor Changes
-- - breaking_changes
- - Breaking Changes / Porting Guide
-- - deprecated_features
- - Deprecated Features
-- - removed_features
- - Removed Features (previously deprecated)
-- - security_fixes
- - Security Fixes
-- - bugfixes
- - Bugfixes
-- - known_issues
- - Known Issues
+ - - major_changes
+ - Major Changes
+ - - minor_changes
+ - Minor Changes
+ - - breaking_changes
+ - Breaking Changes / Porting Guide
+ - - deprecated_features
+ - Deprecated Features
+ - - removed_features
+ - Removed Features (previously deprecated)
+ - - security_fixes
+ - Security Fixes
+ - - bugfixes
+ - Bugfixes
+ - - known_issues
+ - Known Issues
diff --git a/ansible_collections/hetzner/hcloud/changelogs/dev-changelog.md b/ansible_collections/hetzner/hcloud/changelogs/dev-changelog.md
new file mode 100644
index 000000000..9fbbf81a3
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/changelogs/dev-changelog.md
@@ -0,0 +1,64 @@
+# Changelog
+
+## [2.5.0](https://github.com/ansible-collections/hetzner.hcloud/compare/2.4.1...2.5.0) (2024-02-02)
+
+
+### Features
+
+* add `hostvars_prefix` and `hostvars_suffix` options to inventory hostvars ([#423](https://github.com/ansible-collections/hetzner.hcloud/issues/423)) ([4e3f89a](https://github.com/ansible-collections/hetzner.hcloud/commit/4e3f89aed3be6f040e304521d69329c313616df5))
+* allow forcing the deletion of firewalls that are still in use ([#447](https://github.com/ansible-collections/hetzner.hcloud/issues/447)) ([559d315](https://github.com/ansible-collections/hetzner.hcloud/commit/559d31561ad1e0fcf8dd14523bd3eb4262a8a3c1))
+* improve firewall resources management ([#324](https://github.com/ansible-collections/hetzner.hcloud/issues/324)) ([2757fe7](https://github.com/ansible-collections/hetzner.hcloud/commit/2757fe745fcd80409290a453db72e9e6e4016f8f))
+* replace `ansible.netcommon` utils with python3 `ipaddress` module ([#416](https://github.com/ansible-collections/hetzner.hcloud/issues/416)) ([4cfdf50](https://github.com/ansible-collections/hetzner.hcloud/commit/4cfdf50b26536c468705c729cdb48d4b2d421571))
+
+## [2.4.1](https://github.com/ansible-collections/hetzner.hcloud/compare/2.4.0...2.4.1) (2023-11-27)
+
+
+### Bug Fixes
+
+* **inventory:** always use fresh cache on new cached session ([#404](https://github.com/ansible-collections/hetzner.hcloud/issues/404)) ([df7fa04](https://github.com/ansible-collections/hetzner.hcloud/commit/df7fa041494eb3609fcdbe65517a58a6396e0a84))
+
+## [2.4.0](https://github.com/ansible-collections/hetzner.hcloud/compare/2.3.0...2.4.0) (2023-11-24)
+
+
+### Features
+
+* add `hetzner.hcloud.all` action group ([#396](https://github.com/ansible-collections/hetzner.hcloud/issues/396)) ([6581ed5](https://github.com/ansible-collections/hetzner.hcloud/commit/6581ed50db8fd7a3e7525cb364acd63fec256c3a))
+* **inventory:** improve api options ([#397](https://github.com/ansible-collections/hetzner.hcloud/issues/397)) ([9905bd0](https://github.com/ansible-collections/hetzner.hcloud/commit/9905bd0e01ca5a21bb2db94f29a4c5276ffc638b))
+* remove `hcloud_` prefix from all modules names ([#390](https://github.com/ansible-collections/hetzner.hcloud/issues/390)) ([933a162](https://github.com/ansible-collections/hetzner.hcloud/commit/933a16249bc224ee135fcf28a2ebb9ad34978d85))
+* rename api_endpoint module argument ([#395](https://github.com/ansible-collections/hetzner.hcloud/issues/395)) ([7c9fbf8](https://github.com/ansible-collections/hetzner.hcloud/commit/7c9fbf85a734bc7884ff967680beb1fe422dc0ff))
+
+
+### Bug Fixes
+
+* **inventory:** improve performance ([#402](https://github.com/ansible-collections/hetzner.hcloud/issues/402)) ([f85d8f4](https://github.com/ansible-collections/hetzner.hcloud/commit/f85d8f4492f5c400dfcc4601f8212b6310f5c691))
+
+## [2.3.0](https://github.com/ansible-collections/hetzner.hcloud/compare/2.2.0...2.3.0) (2023-11-07)
+
+### Features
+
+- add `created` field to server and server_info modules ([#381](https://github.com/ansible-collections/hetzner.hcloud/issues/381)) ([c3e4c0e](https://github.com/ansible-collections/hetzner.hcloud/commit/c3e4c0ea0a77bec26b83476af99d35078ed9cf6d))
+- add server_types to datacenter info module ([#379](https://github.com/ansible-collections/hetzner.hcloud/issues/379)) ([084e04d](https://github.com/ansible-collections/hetzner.hcloud/commit/084e04d576798e7b49c5c3101803e7b8d2e80181))
+
+## [2.2.0](https://github.com/ansible-collections/hetzner.hcloud/compare/2.1.2...2.2.0) (2023-10-23)
+
+### Features
+
+- add deprecation field to hcloud_iso_info ([#357](https://github.com/ansible-collections/hetzner.hcloud/issues/357)) ([76ef636](https://github.com/ansible-collections/hetzner.hcloud/commit/76ef636f07feb91daa91ecaa17619d10fea7d6e4))
+- add load_balancer algorithm option ([#368](https://github.com/ansible-collections/hetzner.hcloud/issues/368)) ([a93dbaa](https://github.com/ansible-collections/hetzner.hcloud/commit/a93dbaa428a128555d71a9ef36a1a6c211e09952))
+- allow selecting a resource using its ID ([#361](https://github.com/ansible-collections/hetzner.hcloud/issues/361)) ([5e425c5](https://github.com/ansible-collections/hetzner.hcloud/commit/5e425c56c2643f7c0c68b7c6feb8d3e098d4bcdb))
+
+## [2.1.2](https://github.com/ansible-collections/hetzner.hcloud/compare/2.1.1...v2.1.2) (2023-10-05)
+
+### Bug Fixes
+
+- firewall port argument is required with udp or tcp ([#345](https://github.com/ansible-collections/hetzner.hcloud/issues/345)) ([76c1abf](https://github.com/ansible-collections/hetzner.hcloud/commit/76c1abf44764778aa6e11bae57df5ee5f69a947b))
+- invalid field in load_balancer_service health_check.http return data ([#333](https://github.com/ansible-collections/hetzner.hcloud/issues/333)) ([fb35516](https://github.com/ansible-collections/hetzner.hcloud/commit/fb35516e7609fad4dd3fa75138dbc603f83d9aa0))
+
+## Dev Changelog
+
+> [!WARNING]
+> For the user changelog, please check out [CHANGELOG.rst](../CHANGELOG.rst) instead.
+
+This file contains a list of changes intended towards developers. It is auto-generated by release-please.
+
+We would prefer to not generate this file, but disabling this is not supported currently: https://github.com/googleapis/release-please/issues/2007
diff --git a/ansible_collections/hetzner/hcloud/docs/docsite/extra-docs.yml b/ansible_collections/hetzner/hcloud/docs/docsite/extra-docs.yml
new file mode 100644
index 000000000..fa9b5bd68
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/docs/docsite/extra-docs.yml
@@ -0,0 +1,5 @@
+---
+sections:
+ - title: Guides
+ toctree:
+ - guides
diff --git a/ansible_collections/hetzner/hcloud/docs/docsite/links.yml b/ansible_collections/hetzner/hcloud/docs/docsite/links.yml
new file mode 100644
index 000000000..c7ae323c2
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/docs/docsite/links.yml
@@ -0,0 +1,10 @@
+---
+edit_on_github:
+ repository: ansible-collections/hetzner.hcloud
+ branch: main
+
+extra_links:
+ - description: Hetzner Cloud API Reference
+ url: https://docs.hetzner.cloud
+ - description: Hetzner Cloud API Changelog
+ url: https://docs.hetzner.cloud/changelog
diff --git a/ansible_collections/hetzner/hcloud/docs/docsite/rst/guides.rst b/ansible_collections/hetzner/hcloud/docs/docsite/rst/guides.rst
new file mode 100644
index 000000000..14e6b2f05
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/docs/docsite/rst/guides.rst
@@ -0,0 +1,50 @@
+.. _ansible_collections.hetzner.hcloud.docsite.authentication:
+
+Authentication
+==============
+
+To `authenticate the API call against the Hetzner Cloud API <https://docs.hetzner.cloud/#authentication>`_ when
+using the ``hetzner.hcloud`` collection, you can provide the API token by different means:
+
+You can pass the API token using an environment variable (recommended):
+
+.. code-block:: bash
+
+ export HCLOUD_TOKEN='LRK9DAWQ1ZAEFSrCNEEzLCUwhYX1U3g7wMg4dTlkkDC96fyDuyJ39nVbVjCKSDfj'
+
+ # Verify that your token is working
+ ansible -m hetzner.hcloud.location_info localhost
+
+Alternatively, you may provide the API token directly as module argument:
+
+.. code-block:: yaml
+
+ - name: Create server
+ hetzner.hcloud.server:
+ api_token: LRK9DAWQ1ZAEFSrCNEEzLCUwhYX1U3g7wMg4dTlkkDC96fyDuyJ39nVbVjCKSDfj
+ name: my-server
+ server_type: cx11
+ image: debian-12
+ state: present
+
+To reduce the duplication of the above solution, you may configure the
+``hetzner.hcloud.*`` modules using the ``hetzner.hcloud.all`` action group, for
+example if you want to store your API token in a vault:
+
+.. code-block:: yaml
+
+ - name: Demonstrate the usage of the 'hetzner.hcloud.all' module_defaults group
+ hosts: localhost
+ connection: local
+
+ module_defaults:
+ group/hetzner.hcloud.all:
+ api_token: "{{ _vault_hcloud_api_token }}"
+
+ tasks:
+ - name: Create server
+ hetzner.hcloud.server:
+ name: my-server
+ server_type: cx11
+ image: debian-12
+ state: present
diff --git a/ansible_collections/hetzner/hcloud/examples/inventory.hcloud.yml b/ansible_collections/hetzner/hcloud/examples/inventory.hcloud.yml
new file mode 100644
index 000000000..6a67e2836
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/examples/inventory.hcloud.yml
@@ -0,0 +1,7 @@
+# You can list the hosts using:
+# ansible-inventory --list -i examples/inventory.hcloud.yml --extra-vars=network_name=my-network
+
+plugin: hetzner.hcloud.hcloud
+
+network: "{{ network_name }}"
+status: [running]
diff --git a/ansible_collections/hetzner/hcloud/examples/server-with-firewall.yml b/ansible_collections/hetzner/hcloud/examples/server-with-firewall.yml
new file mode 100644
index 000000000..0e5709676
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/examples/server-with-firewall.yml
@@ -0,0 +1,62 @@
+---
+- name: Demonstrate creating servers with a firewall
+ hosts: localhost
+ connection: local
+
+ vars:
+ servers:
+ - name: my-server1
+ - name: my-server2
+
+ tasks:
+ - name: Create firewall
+ hetzner.hcloud.firewall:
+ name: my-firewall
+ rules:
+ - description: allow icmp from everywhere
+ direction: in
+ protocol: icmp
+ source_ips:
+ - 0.0.0.0/0
+ - ::/0
+ - description: allow ssh from everywhere
+ direction: in
+ protocol: tcp
+ port: 22
+ source_ips:
+ - 0.0.0.0/0
+ - ::/0
+ state: present
+
+ - name: Create servers
+ hetzner.hcloud.server:
+ name: "{{ item.name }}"
+ server_type: cx11
+ image: debian-12
+ labels:
+ kind: runners
+ state: started
+ loop: "{{ servers }}"
+
+ - name: Apply firewall to resources using label selectors
+ hetzner.hcloud.firewall_resource:
+ firewall: my-firewall
+ label_selectors: [kind=runners]
+ state: present
+
+ - name: Apply firewall to individual servers
+ hetzner.hcloud.firewall_resource:
+ firewall: my-firewall
+ servers: "{{ servers | map(attribute='name') }}"
+ state: present
+
+ - name: Delete firewall
+ hetzner.hcloud.firewall:
+ name: my-firewall
+ state: absent
+
+ - name: Delete servers
+ hetzner.hcloud.server:
+ name: "{{ item.name }}"
+ state: absent
+ loop: "{{ servers }}"
diff --git a/ansible_collections/hetzner/hcloud/examples/server-with-private-ip-only.yml b/ansible_collections/hetzner/hcloud/examples/server-with-private-ip-only.yml
new file mode 100644
index 000000000..67cf47e51
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/examples/server-with-private-ip-only.yml
@@ -0,0 +1,50 @@
+---
+- name: Demonstrate creating a server that only has a private ip
+ hosts: localhost
+ connection: local
+
+ vars:
+ servers:
+ - name: my-server1
+ private_ip: 10.0.0.2
+ - name: my-server2
+ private_ip: 10.0.0.3
+
+ tasks:
+ - name: Create a network
+ hetzner.hcloud.network:
+ name: my-network
+ ip_range: 10.0.0.0/8
+ state: present
+
+ - name: Create a subnetwork
+ hetzner.hcloud.subnetwork:
+ network: my-network
+ ip_range: 10.0.0.0/16
+ network_zone: eu-central
+ type: cloud
+ state: present
+
+ - name: Create servers without public IPs
+ hetzner.hcloud.server:
+ name: "{{ item.name }}"
+ server_type: cx11
+ image: debian-12
+ enable_ipv4: false
+ enable_ipv6: false
+ state: stopped # A server without networking cannot be started!
+ loop: "{{ servers }}"
+
+ - name: Attach private IP to servers
+ hetzner.hcloud.server_network:
+ network: my-network
+ server: "{{ item.name }}"
+ ip: "{{ item.private_ip }}"
+ state: present
+ loop: "{{ servers }}"
+
+ - name: Start servers
+ hetzner.hcloud.server:
+ name: "{{ item.name }}"
+ state: started
+ loop: "{{ servers }}"
diff --git a/ansible_collections/hetzner/hcloud/examples/use-module-defaults-group.yml b/ansible_collections/hetzner/hcloud/examples/use-module-defaults-group.yml
new file mode 100644
index 000000000..f3de9adac
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/examples/use-module-defaults-group.yml
@@ -0,0 +1,27 @@
+---
+- name: Demonstrate the usage of the 'hetzner.hcloud.all' module_defaults group
+ hosts: localhost
+ connection: local
+
+ module_defaults:
+ group/hetzner.hcloud.all:
+ api_token: LRK9DAWQ1ZAEFSrCNEEzLCUwhYX1U3g7wMg4dTlkkDC96fyDuyJ39nVbVjCKSDfj
+
+ tasks:
+ - name: Create a volume
+ hetzner.hcloud.volume:
+ name: my-volume
+ location: fsn1
+ size: 100
+ state: present
+ register: volume
+
+ - name: Create a server
+ hetzner.hcloud.server:
+ name: my-server
+ server_type: cx11
+ image: debian-12
+ location: fsn1
+ volumes:
+ - "{{ volume.hcloud_volume.id }}"
+ state: present
diff --git a/ansible_collections/hetzner/hcloud/examples/use-refresh-inventory.yml b/ansible_collections/hetzner/hcloud/examples/use-refresh-inventory.yml
new file mode 100644
index 000000000..fd4c351b6
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/examples/use-refresh-inventory.yml
@@ -0,0 +1,35 @@
+---
+- name: Demonstrate the usage of 'refresh_inventory'
+ hosts: localhost
+ connection: local
+
+ tasks:
+ - name: Print hostvars
+ ansible.builtin.debug:
+ var: hostvars
+
+ - name: Create new server
+ hetzner.hcloud.server:
+ name: my-server
+ server_type: cx11
+ image: debian-12
+
+ - name: Refresh inventory
+ ansible.builtin.meta: refresh_inventory
+
+ - name: Run tests
+ block:
+ - name: Print updated inventory
+ ansible.builtin.debug:
+ var: hostvars
+
+ - name: Verify hostvars is not empty
+ ansible.builtin.assert:
+ that:
+ - hostvars != {}
+
+ always:
+ - name: Cleanup server
+ hetzner.hcloud.server:
+ name: my-server
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/meta/runtime.yml b/ansible_collections/hetzner/hcloud/meta/runtime.yml
index d37a1864a..9891ce73a 100644
--- a/ansible_collections/hetzner/hcloud/meta/runtime.yml
+++ b/ansible_collections/hetzner/hcloud/meta/runtime.yml
@@ -1,35 +1,106 @@
-requires_ansible: '>=2.12.0'
+requires_ansible: ">=2.13.0"
+
+action_groups:
+ all:
+ - certificate
+ - certificate_info
+ - datacenter_info
+ - firewall
+ - firewall_info
+ - firewall_resource
+ - floating_ip
+ - floating_ip_info
+ - image_info
+ - iso_info
+ - load_balancer
+ - load_balancer_info
+ - load_balancer_network
+ - load_balancer_service
+ - load_balancer_target
+ - load_balancer_type_info
+ - location_info
+ - network
+ - network_info
+ - placement_group
+ - primary_ip
+ - primary_ip_info
+ - rdns
+ - route
+ - server
+ - server_info
+ - server_network
+ - server_type_info
+ - ssh_key
+ - ssh_key_info
+ - subnetwork
+ - volume
+ - volume_info
+
plugin_routing:
modules:
- hcloud_location_facts:
- deprecation:
- removal_version: 2.0.0
- warning_text: see plugin documentation for details
- hcloud_server_type_facts:
- deprecation:
- removal_version: 2.0.0
- warning_text: see plugin documentation for details
- hcloud_image_facts:
- deprecation:
- removal_version: 2.0.0
- warning_text: see plugin documentation for details
- hcloud_volume_facts:
- deprecation:
- removal_version: 2.0.0
- warning_text: see plugin documentation for details
- hcloud_floating_ip_facts:
- deprecation:
- removal_version: 2.0.0
- warning_text: see plugin documentation for details
- hcloud_ssh_key_facts:
- deprecation:
- removal_version: 2.0.0
- warning_text: see plugin documentation for details
- hcloud_datacenter_facts:
- deprecation:
- removal_version: 2.0.0
- warning_text: see plugin documentation for details
- hcloud_server_facts:
- deprecation:
- removal_version: 2.0.0
- warning_text: see plugin documentation for details
+ hcloud_certificate_info:
+ redirect: hetzner.hcloud.certificate_info
+ hcloud_certificate:
+ redirect: hetzner.hcloud.certificate
+ hcloud_datacenter_info:
+ redirect: hetzner.hcloud.datacenter_info
+ hcloud_firewall:
+ redirect: hetzner.hcloud.firewall
+ hcloud_firewall_info:
+ redirect: hetzner.hcloud.firewall_info
+ hcloud_firewall_resource:
+ redirect: hetzner.hcloud.firewall_resource
+ hcloud_floating_ip_info:
+ redirect: hetzner.hcloud.floating_ip_info
+ hcloud_floating_ip:
+ redirect: hetzner.hcloud.floating_ip
+ hcloud_image_info:
+ redirect: hetzner.hcloud.image_info
+ hcloud_iso_info:
+ redirect: hetzner.hcloud.iso_info
+ hcloud_load_balancer_info:
+ redirect: hetzner.hcloud.load_balancer_info
+ hcloud_load_balancer_network:
+ redirect: hetzner.hcloud.load_balancer_network
+ hcloud_load_balancer_service:
+ redirect: hetzner.hcloud.load_balancer_service
+ hcloud_load_balancer_target:
+ redirect: hetzner.hcloud.load_balancer_target
+ hcloud_load_balancer_type_info:
+ redirect: hetzner.hcloud.load_balancer_type_info
+ hcloud_load_balancer:
+ redirect: hetzner.hcloud.load_balancer
+ hcloud_location_info:
+ redirect: hetzner.hcloud.location_info
+ hcloud_network_info:
+ redirect: hetzner.hcloud.network_info
+ hcloud_network:
+ redirect: hetzner.hcloud.network
+ hcloud_placement_group:
+ redirect: hetzner.hcloud.placement_group
+ hcloud_primary_ip_info:
+ redirect: hetzner.hcloud.primary_ip_info
+ hcloud_primary_ip:
+ redirect: hetzner.hcloud.primary_ip
+ hcloud_rdns:
+ redirect: hetzner.hcloud.rdns
+ hcloud_route:
+ redirect: hetzner.hcloud.route
+ hcloud_server_info:
+ redirect: hetzner.hcloud.server_info
+ hcloud_server_network:
+ redirect: hetzner.hcloud.server_network
+ hcloud_server_type_info:
+ redirect: hetzner.hcloud.server_type_info
+ hcloud_server:
+ redirect: hetzner.hcloud.server
+ hcloud_ssh_key_info:
+ redirect: hetzner.hcloud.ssh_key_info
+ hcloud_ssh_key:
+ redirect: hetzner.hcloud.ssh_key
+ hcloud_subnetwork:
+ redirect: hetzner.hcloud.subnetwork
+ hcloud_volume_info:
+ redirect: hetzner.hcloud.volume_info
+ hcloud_volume:
+ redirect: hetzner.hcloud.volume
diff --git a/ansible_collections/hetzner/hcloud/plugins/__init__.py b/ansible_collections/hetzner/hcloud/plugins/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/__init__.py
diff --git a/ansible_collections/hetzner/hcloud/plugins/doc_fragments/hcloud.py b/ansible_collections/hetzner/hcloud/plugins/doc_fragments/hcloud.py
index d19e64616..eee4a9c83 100644
--- a/ansible_collections/hetzner/hcloud/plugins/doc_fragments/hcloud.py
+++ b/ansible_collections/hetzner/hcloud/plugins/doc_fragments/hcloud.py
@@ -1,29 +1,33 @@
-# -*- 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
+from __future__ import annotations
-class ModuleDocFragment(object):
- DOCUMENTATION = '''
+
+class ModuleDocFragment:
+ DOCUMENTATION = """
options:
- api_token:
- description:
- - This is the API Token for the Hetzner Cloud.
- - You can also set this option by using the environment variable HCLOUD_TOKEN
- required: True
- type: str
- endpoint:
- description:
- - This is the API Endpoint for the Hetzner Cloud.
- default: https://api.hetzner.cloud/v1
- type: str
+ api_token:
+ description:
+ - The API Token for the Hetzner Cloud.
+ - You can also set this option by using the C(HCLOUD_TOKEN) environment variable.
+ required: True
+ type: str
+ api_endpoint:
+ description:
+ - The API Endpoint for the Hetzner Cloud.
+ - You can also set this option by using the C(HCLOUD_ENDPOINT) environment variable.
+ default: https://api.hetzner.cloud/v1
+ type: str
+ aliases: [endpoint]
+
requirements:
- - hcloud-python >= 1.0.0
+ - python-dateutil >= 2.7.5
+ - requests >=2.20
+
seealso:
-- name: Documentation for Hetzner Cloud API
- description: Complete reference for the Hetzner Cloud API.
- link: https://docs.hetzner.cloud/
-'''
+ - name: Documentation for Hetzner Cloud API
+ description: Complete reference for the Hetzner Cloud API.
+ link: https://docs.hetzner.cloud
+"""
diff --git a/ansible_collections/hetzner/hcloud/plugins/inventory/hcloud.py b/ansible_collections/hetzner/hcloud/plugins/inventory/hcloud.py
index 390dedc4c..449342271 100644
--- a/ansible_collections/hetzner/hcloud/plugins/inventory/hcloud.py
+++ b/ansible_collections/hetzner/hcloud/plugins/inventory/hcloud.py
@@ -1,102 +1,139 @@
# 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 = r'''
- name: hcloud
- author:
- - Lukas Kaemmerling (@lkaemmerling)
- short_description: Ansible dynamic inventory plugin for the Hetzner Cloud.
- requirements:
- - python >= 3.5
- - hcloud-python >= 1.0.0
+from __future__ import annotations
+
+DOCUMENTATION = """
+name: hcloud
+short_description: Ansible dynamic inventory plugin for the Hetzner Cloud.
+
+description:
+ - Reads inventories from the Hetzner Cloud API.
+ - Uses a YAML configuration file that ends with C(hcloud.yml) or C(hcloud.yaml).
+
+author:
+ - Lukas Kaemmerling (@lkaemmerling)
+
+requirements:
+ - python-dateutil >= 2.7.5
+ - requests >=2.20
+
+extends_documentation_fragment:
+ - constructed
+ - inventory_cache
+
+options:
+ plugin:
+ description: Mark this as an P(hetzner.hcloud.hcloud#inventory) inventory instance.
+ required: true
+ choices: [hcloud, hetzner.hcloud.hcloud]
+
+ api_token:
+ description:
+ - The API Token for the Hetzner Cloud.
+ type: str
+ required: false # TODO: Mark as required once 'api_token_env' is removed.
+ aliases: [token]
+ env:
+ - name: HCLOUD_TOKEN
+ api_token_env:
+ description:
+ - Environment variable name to load the Hetzner Cloud API Token from.
+ type: str
+ default: HCLOUD_TOKEN
+ aliases: [token_env]
+ deprecated:
+ why: The option is adding too much complexity, while the alternatives are preferred.
+ collection_name: hetzner.hcloud
+ version: 3.0.0
+ alternatives: Use the P(ansible.builtin.env#lookup) lookup plugin instead.
+ api_endpoint:
description:
- - Reads inventories from the Hetzner Cloud API.
- - Uses a YAML configuration file that ends with hcloud.(yml|yaml).
- extends_documentation_fragment:
- - constructed
- options:
- plugin:
- description: marks this as an instance of the "hcloud" plugin
- required: true
- choices: ["hcloud", "hetzner.hcloud.hcloud"]
- token:
- description: The Hetzner Cloud API Token.
- required: false
- group:
- description: The group all servers are automatically added to.
- default: hcloud
- type: str
- required: false
- token_env:
- description: Environment variable to load the Hetzner Cloud API Token from.
- default: HCLOUD_TOKEN
- type: str
- required: false
- connect_with:
- description: |
- Connect to the server using the value from this field. This sets the `ansible_host`
- variable to the value indicated, if that value is available. If you need further
- customization, like falling back to private ipv4 if the server has no public ipv4,
- you can use `compose` top-level key.
- default: public_ipv4
- type: str
- choices:
- - public_ipv4
- - public_ipv6
- - hostname
- - ipv4_dns_ptr
- - private_ipv4
- locations:
- description: Populate inventory with instances in this location.
- default: []
- type: list
- elements: str
- required: false
- types:
- description: Populate inventory with instances with this type.
- default: []
- type: list
- elements: str
- required: false
- images:
- description: Populate inventory with instances with this image name, only available for system images.
- default: []
- type: list
- elements: str
- required: false
- label_selector:
- description: Populate inventory with instances with this label.
- default: ""
- type: str
- required: false
- network:
- description: Populate inventory with instances which are attached to this network name or ID.
- default: ""
- type: str
- required: false
- status:
- description: Populate inventory with instances with this status.
- default: []
- type: list
- elements: str
- required: false
-'''
-
-EXAMPLES = r"""
-# Minimal example. `HCLOUD_TOKEN` is exposed in environment.
-plugin: hcloud
+ - The API Endpoint for the Hetzner Cloud.
+ type: str
+ default: https://api.hetzner.cloud/v1
+ env:
+ - name: HCLOUD_ENDPOINT
+
+ group:
+ description: The group all servers are automatically added to.
+ default: hcloud
+ type: str
+ required: false
+ connect_with:
+ description: |
+ Connect to the server using the value from this field. This sets the C(ansible_host)
+ variable to the value indicated, if that value is available. If you need further
+ customization, like falling back to private ipv4 if the server has no public ipv4,
+ you can use O(compose) top-level key.
+ default: public_ipv4
+ type: str
+ choices:
+ - public_ipv4
+ - public_ipv6
+ - hostname
+ - ipv4_dns_ptr
+ - private_ipv4
+
+ locations:
+ description: Populate inventory with instances in this location.
+ default: []
+ type: list
+ elements: str
+ required: false
+ types:
+ description: Populate inventory with instances with this type.
+ default: []
+ type: list
+ elements: str
+ required: false
+ images:
+ description: Populate inventory with instances with this image name, only available for system images.
+ default: []
+ type: list
+ elements: str
+ required: false
+ label_selector:
+ description: Populate inventory with instances with this label.
+ default: ""
+ type: str
+ required: false
+ network:
+ description: Populate inventory with instances which are attached to this network name or ID.
+ default: ""
+ type: str
+ required: false
+ status:
+ description: Populate inventory with instances with this status.
+ default: []
+ type: list
+ elements: str
+ required: false
+
+ hostvars_prefix:
+ description:
+ - The prefix for host variables names coming from Hetzner Cloud.
+ type: str
+ version_added: 2.5.0
+ hostvars_suffix:
+ description:
+ - The suffix for host variables names coming from Hetzner Cloud.
+ type: str
+ version_added: 2.5.0
+"""
+EXAMPLES = """
+# Minimal example. 'HCLOUD_TOKEN' is exposed in environment.
+plugin: hetzner.hcloud.hcloud
+
+---
# Example with templated token, e.g. provided through extra vars.
-plugin: hcloud
-token: "{{ hetzner_apitoken }}"
+plugin: hetzner.hcloud.hcloud
+api_token: "{{ _vault_hetzner_cloud_token }}"
-# Example with locations, types, status and token
-plugin: hcloud
-token: foobar
+---
+# Example with locations, types, status
+plugin: hetzner.hcloud.hcloud
locations:
- nbg1
types:
@@ -104,10 +141,11 @@ types:
status:
- running
+---
# Group by a location with prefix e.g. "hcloud_location_nbg1"
# and image_os_flavor without prefix and separator e.g. "ubuntu"
# and status with prefix e.g. "server_status_running"
-plugin: hcloud
+plugin: hetzner.hcloud.hcloud
keyed_groups:
- key: location
prefix: hcloud_location
@@ -118,234 +156,355 @@ keyed_groups:
"""
import os
-from ansible.errors import AnsibleError
-from ansible.module_utils._text import to_native
-from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
-from ansible.release import __version__
+import sys
from ipaddress import IPv6Network
-try:
- from hcloud import hcloud
- from hcloud import APIException
- HAS_HCLOUD = True
-except ImportError:
- HAS_HCLOUD = False
+from ansible.errors import AnsibleError
+from ansible.inventory.manager import InventoryData
+from ansible.module_utils.common.text.converters import to_native
+from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, Constructable
+from ansible.utils.display import Display
+
+from ..module_utils.client import (
+ Client,
+ ClientException,
+ client_check_required_lib,
+ client_get_by_name_or_id,
+)
+from ..module_utils.vendor.hcloud import APIException
+from ..module_utils.vendor.hcloud.networks import Network
+from ..module_utils.vendor.hcloud.servers import Server
+from ..module_utils.version import version
+
+if sys.version_info >= (3, 11):
+ # The typed dicts are only used to help development and we prefer not requiring
+ # the additional typing-extensions dependency
+ from typing import NotRequired, TypedDict
+
+ class InventoryPrivateNetwork(TypedDict):
+ id: int
+ name: str
+ ip: str
+
+ class InventoryServer(TypedDict):
+ id: int
+ name: str
+ status: str
+
+ # Server Type
+ type: str
+ server_type: str
+ architecture: str
+ # Datacenter
+ datacenter: str
+ location: str
-class InventoryModule(BaseInventoryPlugin, Constructable):
- NAME = 'hetzner.hcloud.hcloud'
+ # Labels
+ labels: dict[str, str]
+
+ # Network
+ ipv4: NotRequired[str]
+ ipv6: NotRequired[str]
+ ipv6_network: NotRequired[str]
+ ipv6_network_mask: NotRequired[str]
+ private_ipv4: NotRequired[str]
+ private_networks: list[InventoryPrivateNetwork]
+
+ # Image
+ image_id: int
+ image_name: str
+ image_os_flavor: str
+
+ # Ansible
+ ansible_host: str
+
+else:
+ InventoryServer = dict
+
+
+def first_ipv6_address(network: str) -> str:
+ """
+ Return the first address for a ipv6 network.
+
+ :param network: IPv6 Network.
+ """
+ return next(IPv6Network(network).hosts())
+
+
+class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
+ NAME = "hetzner.hcloud.hcloud"
+
+ inventory: InventoryData
+ display: Display
+
+ client: Client
+
+ network: Network | None
def _configure_hcloud_client(self):
- self.token_env = self.get_option("token_env")
- self.templar.available_variables = self._vars
- self.api_token = self.templar.template(self.get_option("token"), fail_on_undefined=False) or os.getenv(self.token_env)
- if self.api_token is None:
+ # If api_token_env is not the default, print a deprecation warning and load the
+ # environment variable.
+ api_token_env = self.get_option("api_token_env")
+ if api_token_env != "HCLOUD_TOKEN":
+ self.display.deprecated(
+ "The 'api_token_env' option is deprecated, please use the 'HCLOUD_TOKEN' "
+ "environment variable or use the 'ansible.builtin.env' lookup instead.",
+ version="3.0.0",
+ collection_name="hetzner.hcloud",
+ )
+ if api_token_env in os.environ:
+ self.set_option("api_token", os.environ.get(api_token_env))
+
+ api_token = self.get_option("api_token")
+ api_endpoint = self.get_option("api_endpoint")
+
+ if api_token is None: # TODO: Remove once I(api_token_env) is removed.
raise AnsibleError(
- "Please specify a token, via the option token, via environment variable HCLOUD_TOKEN "
- "or via custom environment variable set by token_env option."
+ "No setting was provided for required configuration setting: "
+ "plugin_type: inventory "
+ "plugin: hetzner.hcloud.hcloud "
+ "setting: api_token"
)
- self.endpoint = os.getenv("HCLOUD_ENDPOINT") or "https://api.hetzner.cloud/v1"
+ # Resolve template string
+ api_token = self.templar.template(api_token)
- self.client = hcloud.Client(token=self.api_token,
- api_endpoint=self.endpoint,
- application_name="ansible-inventory",
- application_version=__version__)
+ self.client = Client(
+ token=api_token,
+ api_endpoint=api_endpoint,
+ application_name="ansible-inventory",
+ application_version=version,
+ )
- def _test_hcloud_token(self):
try:
- # We test the API Token against the location API, because this is the API with the smallest result
- # and not controllable from the customer.
- self.client.locations.get_all()
- except APIException:
- raise AnsibleError("Invalid Hetzner Cloud API Token.")
-
- def _get_servers(self):
- if len(self.get_option("label_selector")) > 0:
- self.servers = self.client.servers.get_all(label_selector=self.get_option("label_selector"))
- else:
- self.servers = self.client.servers.get_all()
-
- def _filter_servers(self):
+ # Ensure the api token is valid
+ self.client.locations.get_list()
+ except APIException as exception:
+ raise AnsibleError("Invalid Hetzner Cloud API Token.") from exception
+
+ def _validate_options(self) -> None:
if self.get_option("network"):
- network = self.templar.template(self.get_option("network"), fail_on_undefined=False) or self.get_option("network")
+ network_param: str = self.get_option("network")
+ network_param = self.templar.template(network_param)
+
try:
- self.network = self.client.networks.get_by_name(network)
- if self.network is None:
- self.network = self.client.networks.get_by_id(network)
- except APIException:
- raise AnsibleError(
- "The given network is not found.")
-
- tmp = []
- for server in self.servers:
- for server_private_network in server.private_net:
- if server_private_network.network.id == self.network.id:
- tmp.append(server)
- self.servers = tmp
+ self.network = client_get_by_name_or_id(self.client, "networks", network_param)
+ except (ClientException, APIException) as exception:
+ raise AnsibleError(to_native(exception)) from exception
+
+ def _fetch_servers(self) -> list[Server]:
+ self._validate_options()
+
+ get_servers_params = {}
+ if self.get_option("label_selector"):
+ get_servers_params["label_selector"] = self.get_option("label_selector")
+
+ if self.get_option("status"):
+ get_servers_params["status"] = self.get_option("status")
+
+ servers = self.client.servers.get_all(**get_servers_params)
+
+ if self.get_option("network"):
+ servers = [s for s in servers if self.network.id in [p.network.id for p in s.private_net]]
if self.get_option("locations"):
- tmp = []
- for server in self.servers:
- if server.datacenter.location.name in self.get_option("locations"):
- tmp.append(server)
- self.servers = tmp
+ locations: list[str] = self.get_option("locations")
+ servers = [s for s in servers if s.datacenter.location.name in locations]
if self.get_option("types"):
- tmp = []
- for server in self.servers:
- if server.server_type.name in self.get_option("types"):
- tmp.append(server)
- self.servers = tmp
+ server_types: list[str] = self.get_option("types")
+ servers = [s for s in servers if s.server_type.name in server_types]
if self.get_option("images"):
- tmp = []
- for server in self.servers:
- if server.image is not None and server.image.os_flavor in self.get_option("images"):
- tmp.append(server)
- self.servers = tmp
+ images: list[str] = self.get_option("images")
+ servers = [s for s in servers if s.image is not None and s.image.os_flavor in images]
- if self.get_option("status"):
- tmp = []
- for server in self.servers:
- if server.status in self.get_option("status"):
- tmp.append(server)
- self.servers = tmp
-
- def _set_server_attributes(self, server):
- self.inventory.set_variable(server.name, "id", to_native(server.id))
- self.inventory.set_variable(server.name, "name", to_native(server.name))
- self.inventory.set_variable(server.name, "status", to_native(server.status))
- self.inventory.set_variable(server.name, "type", to_native(server.server_type.name))
- self.inventory.set_variable(server.name, "architecture", to_native(server.server_type.architecture))
+ return servers
+
+ def _build_inventory_server(self, server: Server) -> InventoryServer:
+ server_dict: InventoryServer = {}
+ server_dict["id"] = server.id
+ server_dict["name"] = to_native(server.name)
+ server_dict["status"] = to_native(server.status)
+
+ # Server Type
+ server_dict["type"] = to_native(server.server_type.name)
+ server_dict["server_type"] = to_native(server.server_type.name)
+ server_dict["architecture"] = to_native(server.server_type.architecture)
# Network
if server.public_net.ipv4:
- self.inventory.set_variable(server.name, "ipv4", to_native(server.public_net.ipv4.ip))
+ server_dict["ipv4"] = to_native(server.public_net.ipv4.ip)
if server.public_net.ipv6:
- self.inventory.set_variable(server.name, "ipv6_network", to_native(server.public_net.ipv6.network))
- self.inventory.set_variable(server.name, "ipv6_network_mask", to_native(server.public_net.ipv6.network_mask))
- self.inventory.set_variable(server.name, "ipv6", to_native(self._first_ipv6_address(server.public_net.ipv6.ip)))
-
- self.inventory.set_variable(
- server.name,
- "private_networks",
- [
- {"name": n.network.name, "id": n.network.id, "ip": n.ip}
- for n in server.private_net
- ],
- )
+ server_dict["ipv6"] = to_native(first_ipv6_address(server.public_net.ipv6.ip))
+ server_dict["ipv6_network"] = to_native(server.public_net.ipv6.network)
+ server_dict["ipv6_network_mask"] = to_native(server.public_net.ipv6.network_mask)
+
+ server_dict["private_networks"] = [
+ {"id": v.network.id, "name": to_native(v.network.name), "ip": to_native(v.ip)} for v in server.private_net
+ ]
if self.get_option("network"):
- for server_private_network in server.private_net:
+ for private_net in server.private_net:
# Set private_ipv4 if user filtered for one network
- if server_private_network.network.id == self.network.id:
- self.inventory.set_variable(server.name, "private_ipv4", to_native(server_private_network.ip))
-
- try:
- self.inventory.set_variable(server.name, "ansible_host", self._get_server_ansible_host(server))
- except AnsibleError as e:
- # Log warning that for this host can not be connected to, using the
- # method specified in `connect_with`. Users might use `compose` to
- # override the connection method, or implement custom logic, so we
- # do not need to abort if nothing matched.
- self.display.v("[hcloud] %s" % e, server.name)
-
- # Server Type
- if server.server_type is not None:
- self.inventory.set_variable(server.name, "server_type", to_native(server.server_type.name))
+ if private_net.network.id == self.network.id:
+ server_dict["private_ipv4"] = to_native(private_net.ip)
+ break
# Datacenter
- self.inventory.set_variable(server.name, "datacenter", to_native(server.datacenter.name))
- self.inventory.set_variable(server.name, "location", to_native(server.datacenter.location.name))
+ server_dict["datacenter"] = to_native(server.datacenter.name)
+ server_dict["location"] = to_native(server.datacenter.location.name)
# Image
if server.image is not None:
- self.inventory.set_variable(server.name, "image_id", to_native(server.image.id))
- self.inventory.set_variable(server.name, "image_os_flavor", to_native(server.image.os_flavor))
- if server.image.name is not None:
- self.inventory.set_variable(server.name, "image_name", to_native(server.image.name))
- else:
- self.inventory.set_variable(server.name, "image_name", to_native(server.image.description))
- else:
- self.inventory.set_variable(server.name, "image_id", to_native("No Image ID found"))
- self.inventory.set_variable(server.name, "image_name", to_native("No Image Name found"))
- self.inventory.set_variable(server.name, "image_os_flavor", to_native("No Image OS Flavor found"))
+ server_dict["image_id"] = server.image.id
+ server_dict["image_os_flavor"] = to_native(server.image.os_flavor)
+ server_dict["image_name"] = to_native(server.image.name or server.image.description)
# Labels
- self.inventory.set_variable(server.name, "labels", dict(server.labels))
+ server_dict["labels"] = dict(server.labels)
- def _get_server_ansible_host(self, server):
+ try:
+ server_dict["ansible_host"] = self._get_server_ansible_host(server)
+ except AnsibleError as exception:
+ # Log warning that for this host can not be connected to, using the
+ # method specified in 'connect_with'. Users might use 'compose' to
+ # override the connection method, or implement custom logic, so we
+ # do not need to abort if nothing matched.
+ self.display.v(f"[hcloud] {exception}", server.name)
+
+ return server_dict
+
+ def _get_server_ansible_host(self, server: Server):
if self.get_option("connect_with") == "public_ipv4":
if server.public_net.ipv4:
return to_native(server.public_net.ipv4.ip)
- else:
- raise AnsibleError("Server has no public ipv4, but connect_with=public_ipv4 was specified")
+ raise AnsibleError("Server has no public ipv4, but connect_with=public_ipv4 was specified")
if self.get_option("connect_with") == "public_ipv6":
if server.public_net.ipv6:
- return to_native(self._first_ipv6_address(server.public_net.ipv6.ip))
- else:
- raise AnsibleError("Server has no public ipv6, but connect_with=public_ipv6 was specified")
+ return to_native(first_ipv6_address(server.public_net.ipv6.ip))
+ raise AnsibleError("Server has no public ipv6, but connect_with=public_ipv6 was specified")
- elif self.get_option("connect_with") == "hostname":
+ if self.get_option("connect_with") == "hostname":
# every server has a name, no need to guard this
return to_native(server.name)
- elif self.get_option("connect_with") == "ipv4_dns_ptr":
+ if self.get_option("connect_with") == "ipv4_dns_ptr":
if server.public_net.ipv4:
return to_native(server.public_net.ipv4.dns_ptr)
- else:
- raise AnsibleError("Server has no public ipv4, but connect_with=ipv4_dns_ptr was specified")
+ raise AnsibleError("Server has no public ipv4, but connect_with=ipv4_dns_ptr was specified")
- elif self.get_option("connect_with") == "private_ipv4":
+ if self.get_option("connect_with") == "private_ipv4":
if self.get_option("network"):
- for server_private_network in server.private_net:
- if server_private_network.network.id == self.network.id:
- return to_native(server_private_network.ip)
+ for private_net in server.private_net:
+ if private_net.network.id == self.network.id:
+ return to_native(private_net.ip)
else:
- raise AnsibleError(
- "You can only connect via private IPv4 if you specify a network")
-
- def _first_ipv6_address(self, network):
- return next(IPv6Network(network).hosts())
+ raise AnsibleError("You can only connect via private IPv4 if you specify a network")
def verify_file(self, path):
"""Return the possibly of a file being consumable by this plugin."""
- return (
- super(InventoryModule, self).verify_file(path) and
- path.endswith(("hcloud.yaml", "hcloud.yml"))
- )
+ return super().verify_file(path) and path.endswith(("hcloud.yaml", "hcloud.yml"))
+
+ def _get_cached_result(self, path, cache) -> tuple[list[InventoryServer], bool]:
+ # false when refresh_cache or --flush-cache is used
+ if not cache:
+ return [], False
+
+ # get the user-specified directive
+ if not self.get_option("cache"):
+ return [], False
+
+ cache_key = self.get_cache_key(path)
+ try:
+ cached_result = self._cache[cache_key]
+ except KeyError:
+ # if cache expires or cache file doesn"t exist
+ return [], False
+
+ return cached_result, True
+
+ def _update_cached_result(self, path, cache, result: list[InventoryServer]):
+ if not self.get_option("cache"):
+ return
+
+ cache_key = self.get_cache_key(path)
+ # We weren't explicitly told to flush the cache, and there's already a cache entry,
+ # this means that the result we're being passed came from the cache. As such we don't
+ # want to "update" the cache as that could reset a TTL on the cache entry.
+ if cache and cache_key in self._cache:
+ return
+
+ self._cache[cache_key] = result
def parse(self, inventory, loader, path, cache=True):
- super(InventoryModule, self).parse(inventory, loader, path, cache)
+ super().parse(inventory, loader, path, cache)
+
+ try:
+ client_check_required_lib()
+ except ClientException as exception:
+ raise AnsibleError(to_native(exception)) from exception
- if not HAS_HCLOUD:
- raise AnsibleError("The Hetzner Cloud dynamic inventory plugin requires hcloud-python.")
+ # Allow using extra variables arguments as template variables (e.g.
+ # '--extra-vars my_var=my_value')
+ self.templar.available_variables = self._vars
self._read_config_data(path)
self._configure_hcloud_client()
- self._test_hcloud_token()
- self._get_servers()
- self._filter_servers()
+
+ servers, cached = self._get_cached_result(path, cache)
+ if not cached:
+ with self.client.cached_session():
+ servers = [self._build_inventory_server(s) for s in self._fetch_servers()]
# Add a top group
self.inventory.add_group(group=self.get_option("group"))
- for server in self.servers:
- self.inventory.add_host(server.name, group=self.get_option("group"))
- self._set_server_attributes(server)
+ hostvars_prefix = self.get_option("hostvars_prefix")
+ hostvars_suffix = self.get_option("hostvars_suffix")
+
+ for server in servers:
+ self.inventory.add_host(server["name"], group=self.get_option("group"))
+ for key, value in server.items():
+ # Add hostvars prefix and suffix for variables coming from the Hetzner Cloud.
+ if hostvars_prefix or hostvars_suffix:
+ if key not in ("ansible_host",):
+ if hostvars_prefix:
+ key = hostvars_prefix + key
+ if hostvars_suffix:
+ key = key + hostvars_suffix
+
+ self.inventory.set_variable(server["name"], key, value)
# Use constructed if applicable
- strict = self.get_option('strict')
+ strict = self.get_option("strict")
# Composed variables
- self._set_composite_vars(self.get_option('compose'), self.inventory.get_host(server.name).get_vars(), server.name, strict=strict)
+ self._set_composite_vars(
+ self.get_option("compose"),
+ self.inventory.get_host(server["name"]).get_vars(),
+ server["name"],
+ strict=strict,
+ )
# Complex groups based on jinja2 conditionals, hosts that meet the conditional are added to group
- self._add_host_to_composed_groups(self.get_option('groups'), {}, server.name, strict=strict)
+ self._add_host_to_composed_groups(
+ self.get_option("groups"),
+ {},
+ server["name"],
+ strict=strict,
+ )
# Create groups based on variable values and add the corresponding hosts to it
- self._add_host_to_keyed_groups(self.get_option('keyed_groups'), {}, server.name, strict=strict)
+ self._add_host_to_keyed_groups(
+ self.get_option("keyed_groups"),
+ {},
+ server["name"],
+ strict=strict,
+ )
+
+ self._update_cached_result(path, cache, servers)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/client.py
new file mode 100644
index 000000000..d82a63007
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/client.py
@@ -0,0 +1,108 @@
+# Copyright: (c) 2023, Hetzner Cloud GmbH <info@hetzner-cloud.de>
+
+from __future__ import annotations
+
+from contextlib import contextmanager
+
+from ansible.module_utils.basic import missing_required_lib
+
+from .vendor.hcloud import APIException, Client as ClientBase
+
+HAS_REQUESTS = True
+HAS_DATEUTIL = True
+
+try:
+ import requests # pylint: disable=unused-import
+except ImportError:
+ HAS_REQUESTS = False
+
+try:
+ import dateutil # pylint: disable=unused-import
+except ImportError:
+ HAS_DATEUTIL = False
+
+
+class ClientException(Exception):
+ """An error related to the client occurred."""
+
+
+def client_check_required_lib():
+ if not HAS_REQUESTS:
+ raise ClientException(missing_required_lib("requests"))
+ if not HAS_DATEUTIL:
+ raise ClientException(missing_required_lib("python-dateutil"))
+
+
+def _client_resource_not_found(resource: str, param: str | int):
+ return ClientException(f"resource ({resource.rstrip('s')}) does not exist: {param}")
+
+
+def client_get_by_name_or_id(client: Client, resource: str, param: str | int):
+ """
+ Get a resource by name, and if not found by its ID.
+
+ :param client: Client to use to make the call
+ :param resource: Name of the resource client that implements both `get_by_name` and `get_by_id` methods
+ :param param: Name or ID of the resource to query
+ """
+ resource_client = getattr(client, resource)
+
+ result = resource_client.get_by_name(param)
+ if result is not None:
+ return result
+
+ # If the param is not a valid ID, prevent an unnecessary call to the API.
+ try:
+ int(param)
+ except ValueError as exception:
+ raise _client_resource_not_found(resource, param) from exception
+
+ try:
+ return resource_client.get_by_id(param)
+ except APIException as exception:
+ if exception.code == "not_found":
+ raise _client_resource_not_found(resource, param) from exception
+ raise exception
+
+
+if HAS_REQUESTS:
+
+ class CachedSession(requests.Session):
+ cache: dict[str, requests.Response]
+
+ def __init__(self) -> None:
+ super().__init__()
+ self.cache = {}
+
+ def send(self, request: requests.PreparedRequest, **kwargs) -> requests.Response: # type: ignore[no-untyped-def]
+ """
+ Send a given PreparedRequest.
+ """
+ if request.method != "GET" or request.url is None:
+ return super().send(request, **kwargs)
+
+ if request.url in self.cache:
+ return self.cache[request.url]
+
+ response = super().send(request, **kwargs)
+ if response.ok:
+ self.cache[request.url] = response
+
+ return response
+
+
+class Client(ClientBase):
+ @contextmanager
+ def cached_session(self):
+ """
+ Swap the client session during the scope of the context. The session will cache
+ all GET requests.
+
+ Cached response will not expire, therefore the cached client must not be used
+ for long living scopes.
+ """
+ self._requests_session = CachedSession()
+ try:
+ yield
+ finally:
+ self._requests_session = requests.Session()
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/hcloud.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/hcloud.py
index 932b0c529..eab0aef59 100644
--- a/ansible_collections/hetzner/hcloud/plugins/module_utils/hcloud.py
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/hcloud.py
@@ -1,45 +1,101 @@
-# -*- coding: utf-8 -*-
# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
+from __future__ import annotations
-from ansible.module_utils.ansible_release import __version__
-from ansible.module_utils.basic import env_fallback, missing_required_lib
+import traceback
+from typing import Any, NoReturn
-try:
- import hcloud
+from ansible.module_utils.basic import AnsibleModule as AnsibleModuleBase, env_fallback
+from ansible.module_utils.common.text.converters import to_native
- HAS_HCLOUD = True
-except ImportError:
- HAS_HCLOUD = False
+from .client import ClientException, client_check_required_lib, client_get_by_name_or_id
+from .vendor.hcloud import APIException, Client, HCloudException
+from .vendor.hcloud.actions import ActionException
+from .version import version
-class Hcloud(object):
- def __init__(self, module, represent):
+# Provide typing definitions to the AnsibleModule class
+class AnsibleModule(AnsibleModuleBase):
+ params: dict
+
+
+class AnsibleHCloud:
+ represent: str
+
+ module: AnsibleModule
+
+ def __init__(self, module: AnsibleModule):
+ if not self.represent:
+ raise NotImplementedError(f"represent property is not defined for {self.__class__.__name__}")
+
self.module = module
- self.represent = represent
self.result = {"changed": False, self.represent: None}
- if not HAS_HCLOUD:
- module.fail_json(msg=missing_required_lib("hcloud-python"))
+
+ try:
+ client_check_required_lib()
+ except ClientException as exception:
+ module.fail_json(msg=to_native(exception))
+
self._build_client()
- def _build_client(self):
- self.client = hcloud.Client(
+ def fail_json_hcloud(
+ self,
+ exception: HCloudException,
+ msg: str | None = None,
+ params: Any = None,
+ **kwargs,
+ ) -> NoReturn:
+ last_traceback = traceback.format_exc()
+
+ failure = {}
+
+ if params is not None:
+ failure["params"] = params
+
+ if isinstance(exception, APIException):
+ failure["message"] = exception.message
+ failure["code"] = exception.code
+ failure["details"] = exception.details
+
+ elif isinstance(exception, ActionException):
+ failure["action"] = {k: getattr(exception.action, k) for k in exception.action.__slots__}
+
+ exception_message = to_native(exception)
+ if msg is not None:
+ msg = f"{exception_message}: {msg}"
+ else:
+ msg = exception_message
+
+ self.module.fail_json(msg=msg, exception=last_traceback, failure=failure, **kwargs)
+
+ def _build_client(self) -> None:
+ self.client = Client(
token=self.module.params["api_token"],
- api_endpoint=self.module.params["endpoint"],
+ api_endpoint=self.module.params["api_endpoint"],
application_name="ansible-module",
- application_version=__version__,
+ application_version=version,
)
- def _mark_as_changed(self):
+ def _client_get_by_name_or_id(self, resource: str, param: str | int):
+ """
+ Get a resource by name, and if not found by its ID.
+
+ :param resource: Name of the resource client that implements both `get_by_name` and `get_by_id` methods
+ :param param: Name or ID of the resource to query
+ """
+ try:
+ return client_get_by_name_or_id(self.client, resource, param)
+ except ClientException as exception:
+ self.module.fail_json(msg=to_native(exception))
+
+ def _mark_as_changed(self) -> None:
self.result["changed"] = True
- @staticmethod
- def base_module_arguments():
+ @classmethod
+ def base_module_arguments(cls):
return {
"api_token": {
"type": "str",
@@ -47,17 +103,19 @@ class Hcloud(object):
"fallback": (env_fallback, ["HCLOUD_TOKEN"]),
"no_log": True,
},
- "endpoint": {"type": "str", "default": "https://api.hetzner.cloud/v1"},
+ "api_endpoint": {
+ "type": "str",
+ "fallback": (env_fallback, ["HCLOUD_ENDPOINT"]),
+ "default": "https://api.hetzner.cloud/v1",
+ "aliases": ["endpoint"],
+ },
}
- def _prepare_result(self):
- """Prepare the result for every module
-
- :return: dict
- """
+ def _prepare_result(self) -> dict[str, Any]:
+ """Prepare the result for every module"""
return {}
- def get_result(self):
+ def get_result(self) -> dict[str, Any]:
if getattr(self, self.represent) is not None:
self.result[self.represent] = self._prepare_result()
return self.result
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/__init__.py
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/__init__.py
new file mode 100644
index 000000000..6b69b1699
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/__init__.py
@@ -0,0 +1,7 @@
+from __future__ import annotations
+
+from ._client import Client as Client # noqa pylint: disable=C0414
+from ._exceptions import ( # noqa pylint: disable=C0414
+ APIException as APIException,
+ HCloudException as HCloudException,
+)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_client.py
new file mode 100644
index 000000000..257d361c7
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_client.py
@@ -0,0 +1,236 @@
+from __future__ import annotations
+
+import time
+from typing import NoReturn
+
+try:
+ import requests
+except ImportError:
+ requests = None
+
+from ._version import VERSION
+from ._exceptions import APIException
+from .actions import ActionsClient
+from .certificates import CertificatesClient
+from .datacenters import DatacentersClient
+from .firewalls import FirewallsClient
+from .floating_ips import FloatingIPsClient
+from .images import ImagesClient
+from .isos import IsosClient
+from .load_balancer_types import LoadBalancerTypesClient
+from .load_balancers import LoadBalancersClient
+from .locations import LocationsClient
+from .networks import NetworksClient
+from .placement_groups import PlacementGroupsClient
+from .primary_ips import PrimaryIPsClient
+from .server_types import ServerTypesClient
+from .servers import ServersClient
+from .ssh_keys import SSHKeysClient
+from .volumes import VolumesClient
+
+
+class Client:
+ """Base Client for accessing the Hetzner Cloud API"""
+
+ _version = VERSION
+ _retry_wait_time = 0.5
+ __user_agent_prefix = "hcloud-python"
+
+ def __init__(
+ self,
+ token: str,
+ api_endpoint: str = "https://api.hetzner.cloud/v1",
+ application_name: str | None = None,
+ application_version: str | None = None,
+ poll_interval: int = 1,
+ timeout: float | tuple[float, float] | None = None,
+ ):
+ """Create a new Client instance
+
+ :param token: Hetzner Cloud API token
+ :param api_endpoint: Hetzner Cloud API endpoint
+ :param application_name: Your application name
+ :param application_version: Your application _version
+ :param poll_interval: Interval for polling information from Hetzner Cloud API in seconds
+ :param timeout: Requests timeout in seconds
+ """
+ self.token = token
+ self._api_endpoint = api_endpoint
+ self._application_name = application_name
+ self._application_version = application_version
+ self._requests_session = requests.Session()
+ self._requests_timeout = timeout
+ self.poll_interval = poll_interval
+
+ self.datacenters = DatacentersClient(self)
+ """DatacentersClient Instance
+
+ :type: :class:`DatacentersClient <hcloud.datacenters.client.DatacentersClient>`
+ """
+ self.locations = LocationsClient(self)
+ """LocationsClient Instance
+
+ :type: :class:`LocationsClient <hcloud.locations.client.LocationsClient>`
+ """
+ self.servers = ServersClient(self)
+ """ServersClient Instance
+
+ :type: :class:`ServersClient <hcloud.servers.client.ServersClient>`
+ """
+ self.server_types = ServerTypesClient(self)
+ """ServerTypesClient Instance
+
+ :type: :class:`ServerTypesClient <hcloud.server_types.client.ServerTypesClient>`
+ """
+ self.volumes = VolumesClient(self)
+ """VolumesClient Instance
+
+ :type: :class:`VolumesClient <hcloud.volumes.client.VolumesClient>`
+ """
+ self.actions = ActionsClient(self)
+ """ActionsClient Instance
+
+ :type: :class:`ActionsClient <hcloud.actions.client.ActionsClient>`
+ """
+ self.images = ImagesClient(self)
+ """ImagesClient Instance
+
+ :type: :class:`ImagesClient <hcloud.images.client.ImagesClient>`
+ """
+ self.isos = IsosClient(self)
+ """ImagesClient Instance
+
+ :type: :class:`IsosClient <hcloud.isos.client.IsosClient>`
+ """
+ self.ssh_keys = SSHKeysClient(self)
+ """SSHKeysClient Instance
+
+ :type: :class:`SSHKeysClient <hcloud.ssh_keys.client.SSHKeysClient>`
+ """
+ self.floating_ips = FloatingIPsClient(self)
+ """FloatingIPsClient Instance
+
+ :type: :class:`FloatingIPsClient <hcloud.floating_ips.client.FloatingIPsClient>`
+ """
+ self.primary_ips = PrimaryIPsClient(self)
+ """PrimaryIPsClient Instance
+
+ :type: :class:`PrimaryIPsClient <hcloud.primary_ips.client.PrimaryIPsClient>`
+ """
+ self.networks = NetworksClient(self)
+ """NetworksClient Instance
+
+ :type: :class:`NetworksClient <hcloud.networks.client.NetworksClient>`
+ """
+ self.certificates = CertificatesClient(self)
+ """CertificatesClient Instance
+
+ :type: :class:`CertificatesClient <hcloud.certificates.client.CertificatesClient>`
+ """
+
+ self.load_balancers = LoadBalancersClient(self)
+ """LoadBalancersClient Instance
+
+ :type: :class:`LoadBalancersClient <hcloud.load_balancers.client.LoadBalancersClient>`
+ """
+
+ self.load_balancer_types = LoadBalancerTypesClient(self)
+ """LoadBalancerTypesClient Instance
+
+ :type: :class:`LoadBalancerTypesClient <hcloud.load_balancer_types.client.LoadBalancerTypesClient>`
+ """
+
+ self.firewalls = FirewallsClient(self)
+ """FirewallsClient Instance
+
+ :type: :class:`FirewallsClient <hcloud.firewalls.client.FirewallsClient>`
+ """
+
+ self.placement_groups = PlacementGroupsClient(self)
+ """PlacementGroupsClient Instance
+
+ :type: :class:`PlacementGroupsClient <hcloud.placement_groups.client.PlacementGroupsClient>`
+ """
+
+ def _get_user_agent(self) -> str:
+ """Get the user agent of the hcloud-python instance with the user application name (if specified)
+
+ :return: The user agent of this hcloud-python instance
+ """
+ user_agents = []
+ for name, version in [
+ (self._application_name, self._application_version),
+ (self.__user_agent_prefix, self._version),
+ ]:
+ if name is not None:
+ user_agents.append(name if version is None else f"{name}/{version}")
+
+ return " ".join(user_agents)
+
+ def _get_headers(self) -> dict:
+ headers = {
+ "User-Agent": self._get_user_agent(),
+ "Authorization": f"Bearer {self.token}",
+ }
+ return headers
+
+ def _raise_exception_from_response(self, response) -> NoReturn:
+ raise APIException(
+ code=response.status_code,
+ message=response.reason,
+ details={"content": response.content},
+ )
+
+ def _raise_exception_from_content(self, content: dict) -> NoReturn:
+ raise APIException(
+ code=content["error"]["code"],
+ message=content["error"]["message"],
+ details=content["error"]["details"],
+ )
+
+ def request( # type: ignore[no-untyped-def]
+ self,
+ method: str,
+ url: str,
+ tries: int = 1,
+ **kwargs,
+ ) -> dict:
+ """Perform a request to the Hetzner Cloud API, wrapper around requests.request
+
+ :param method: HTTP Method to perform the Request
+ :param url: URL of the Endpoint
+ :param tries: Tries of the request (used internally, should not be set by the user)
+ :param timeout: Requests timeout in seconds
+ :return: Response
+ """
+ timeout = kwargs.pop("timeout", self._requests_timeout)
+
+ response = self._requests_session.request(
+ method=method,
+ url=self._api_endpoint + url,
+ headers=self._get_headers(),
+ timeout=timeout,
+ **kwargs,
+ )
+
+ content = response.content
+ try:
+ if len(content) > 0:
+ content = response.json()
+ except (TypeError, ValueError):
+ self._raise_exception_from_response(response)
+
+ if not response.ok:
+ if content:
+ assert isinstance(content, dict)
+ if content["error"]["code"] == "rate_limit_exceeded" and tries < 5:
+ time.sleep(tries * self._retry_wait_time)
+ tries = tries + 1
+ return self.request(method, url, tries, **kwargs)
+
+ self._raise_exception_from_content(content)
+ else:
+ self._raise_exception_from_response(response)
+
+ # TODO: return an empty dict instead of an empty string when content == "".
+ return content # type: ignore[return-value]
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_exceptions.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_exceptions.py
new file mode 100644
index 000000000..877083f87
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_exceptions.py
@@ -0,0 +1,17 @@
+from __future__ import annotations
+
+from typing import Any
+
+
+class HCloudException(Exception):
+ """There was an error while using the hcloud library"""
+
+
+class APIException(HCloudException):
+ """There was an error while performing an API Request"""
+
+ def __init__(self, code: int | str, message: str | None, details: Any):
+ super().__init__(code if message is None and isinstance(code, str) else message)
+ self.code = code
+ self.message = message
+ self.details = details
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_version.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_version.py
new file mode 100644
index 000000000..e03c1b434
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/_version.py
@@ -0,0 +1,3 @@
+from __future__ import annotations
+
+VERSION = "1.33.2" # x-release-please-version
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/__init__.py
new file mode 100644
index 000000000..ca93c89f5
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/__init__.py
@@ -0,0 +1,14 @@
+from __future__ import annotations
+
+from .client import ( # noqa: F401
+ ActionsClient,
+ ActionsPageResult,
+ BoundAction,
+ ResourceActionsClient,
+)
+from .domain import ( # noqa: F401
+ Action,
+ ActionException,
+ ActionFailedException,
+ ActionTimeoutException,
+)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/client.py
new file mode 100644
index 000000000..a188f6247
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/client.py
@@ -0,0 +1,166 @@
+from __future__ import annotations
+
+import time
+import warnings
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import Action, ActionFailedException, ActionTimeoutException
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundAction(BoundModelBase, Action):
+ _client: ActionsClient
+
+ model = Action
+
+ def wait_until_finished(self, max_retries: int = 100) -> None:
+ """Wait until the specific action has status="finished" (set Client.poll_interval to specify a delay between checks)
+
+ :param max_retries: int
+ Specify how many retries will be performed before an ActionTimeoutException will be raised
+ :raises: ActionFailedException when action is finished with status=="error"
+ :raises: ActionTimeoutException when Action is still in "running" state after max_retries reloads.
+ """
+ while self.status == Action.STATUS_RUNNING:
+ if max_retries > 0:
+ self.reload()
+ # pylint: disable=protected-access
+ time.sleep(self._client._client.poll_interval)
+ max_retries = max_retries - 1
+ else:
+ raise ActionTimeoutException(action=self)
+
+ if self.status == Action.STATUS_ERROR:
+ raise ActionFailedException(action=self)
+
+
+class ActionsPageResult(NamedTuple):
+ actions: list[BoundAction]
+ meta: Meta | None
+
+
+class ResourceActionsClient(ClientEntityBase):
+ _resource: str
+
+ def __init__(self, client: Client, resource: str | None):
+ super().__init__(client)
+ self._resource = resource or ""
+
+ def get_by_id(self, id: int) -> BoundAction:
+ """Get a specific action by its ID.
+
+ :param id: int
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"{self._resource}/actions/{id}",
+ method="GET",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def get_list(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Get a list of actions.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `command` `status` `progress` `started` `finished` . You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default)
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if status is not None:
+ params["status"] = status
+ if sort is not None:
+ params["sort"] = sort
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url=f"{self._resource}/actions",
+ method="GET",
+ params=params,
+ )
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+ return ActionsPageResult(actions, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Get all actions.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `command` `status` `progress` `started` `finished` . You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default)
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._iter_pages(self.get_list, status=status, sort=sort)
+
+
+class ActionsClient(ResourceActionsClient):
+ def __init__(self, client: Client):
+ super().__init__(client, None)
+
+ def get_list(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """
+ .. deprecated:: 1.28
+ Use :func:`client.<resource>.actions.get_list` instead,
+ e.g. using :attr:`hcloud.certificates.client.CertificatesClient.actions`.
+
+ `Starting 1 October 2023, it will no longer be available. <https://docs.hetzner.cloud/changelog#2023-07-20-actions-list-endpoint-is-deprecated>`_
+ """
+ warnings.warn(
+ "The 'client.actions.get_list' method is deprecated, please use the "
+ "'client.<resource>.actions.get_list' method instead (e.g. "
+ "'client.certificates.actions.get_list').",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return super().get_list(status=status, sort=sort, page=page, per_page=per_page)
+
+ def get_all(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """
+ .. deprecated:: 1.28
+ Use :func:`client.<resource>.actions.get_all` instead,
+ e.g. using :attr:`hcloud.certificates.client.CertificatesClient.actions`.
+
+ `Starting 1 October 2023, it will no longer be available. <https://docs.hetzner.cloud/changelog#2023-07-20-actions-list-endpoint-is-deprecated>`_
+ """
+ warnings.warn(
+ "The 'client.actions.get_all' method is deprecated, please use the "
+ "'client.<resource>.actions.get_all' method instead (e.g. "
+ "'client.certificates.actions.get_all').",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return super().get_all(status=status, sort=sort)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/domain.py
new file mode 100644
index 000000000..16b74ac68
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/actions/domain.py
@@ -0,0 +1,89 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from .._exceptions import HCloudException
+from ..core import BaseDomain
+
+if TYPE_CHECKING:
+ from .client import BoundAction
+
+
+class Action(BaseDomain):
+ """Action Domain
+
+ :param id: int ID of an action
+ :param command: Command executed in the action
+ :param status: Status of the action
+ :param progress: Progress of action in percent
+ :param started: Point in time when the action was started
+ :param datetime,None finished: Point in time when the action was finished. Only set if the action is finished otherwise None
+ :param resources: Resources the action relates to
+ :param error: Error message for the action if error occurred, otherwise None.
+ """
+
+ STATUS_RUNNING = "running"
+ """Action Status running"""
+ STATUS_SUCCESS = "success"
+ """Action Status success"""
+ STATUS_ERROR = "error"
+ """Action Status error"""
+
+ __slots__ = (
+ "id",
+ "command",
+ "status",
+ "progress",
+ "resources",
+ "error",
+ "started",
+ "finished",
+ )
+
+ def __init__(
+ self,
+ id: int,
+ command: str | None = None,
+ status: str | None = None,
+ progress: int | None = None,
+ started: str | None = None,
+ finished: str | None = None,
+ resources: list[dict] | None = None,
+ error: dict | None = None,
+ ):
+ self.id = id
+ self.command = command
+
+ self.status = status
+ self.progress = progress
+ self.started = isoparse(started) if started else None
+ self.finished = isoparse(finished) if finished else None
+ self.resources = resources
+ self.error = error
+
+
+class ActionException(HCloudException):
+ """A generic action exception"""
+
+ def __init__(self, action: Action | BoundAction):
+ assert self.__doc__ is not None
+ message = self.__doc__
+ if action.error is not None and "message" in action.error:
+ message += f": {action.error['message']}"
+
+ super().__init__(message)
+ self.message = message
+ self.action = action
+
+
+class ActionFailedException(ActionException):
+ """The pending action failed"""
+
+
+class ActionTimeoutException(ActionException):
+ """The pending action timed out"""
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/__init__.py
new file mode 100644
index 000000000..4e63df576
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/__init__.py
@@ -0,0 +1,13 @@
+from __future__ import annotations
+
+from .client import ( # noqa: F401
+ BoundCertificate,
+ CertificatesClient,
+ CertificatesPageResult,
+)
+from .domain import ( # noqa: F401
+ Certificate,
+ CreateManagedCertificateResponse,
+ ManagedCertificateError,
+ ManagedCertificateStatus,
+)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/client.py
new file mode 100644
index 000000000..a5fe1d77f
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/client.py
@@ -0,0 +1,371 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import (
+ Certificate,
+ CreateManagedCertificateResponse,
+ ManagedCertificateError,
+ ManagedCertificateStatus,
+)
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundCertificate(BoundModelBase, Certificate):
+ _client: CertificatesClient
+
+ model = Certificate
+
+ def __init__(self, client: CertificatesClient, data: dict, complete: bool = True):
+ status = data.get("status")
+ if status is not None:
+ error_data = status.get("error")
+ error = None
+ if error_data:
+ error = ManagedCertificateError(
+ code=error_data["code"], message=error_data["message"]
+ )
+ data["status"] = ManagedCertificateStatus(
+ issuance=status["issuance"], renewal=status["renewal"], error=error
+ )
+ super().__init__(client, data, complete)
+
+ def get_actions_list(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a Certificate.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ return self._client.get_actions_list(self, status, sort, page, per_page)
+
+ def get_actions(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a Certificate.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.get_actions(self, status, sort)
+
+ def update(
+ self,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundCertificate:
+ """Updates an certificate. You can update an certificate name and the certificate labels.
+
+ :param name: str (optional)
+ New name to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
+ """
+ return self._client.update(self, name, labels)
+
+ def delete(self) -> bool:
+ """Deletes a certificate.
+ :return: boolean
+ """
+ return self._client.delete(self)
+
+ def retry_issuance(self) -> BoundAction:
+ """Retry a failed Certificate issuance or renewal.
+ :return: BoundAction
+ """
+ return self._client.retry_issuance(self)
+
+
+class CertificatesPageResult(NamedTuple):
+ certificates: list[BoundCertificate]
+ meta: Meta | None
+
+
+class CertificatesClient(ClientEntityBase):
+ _client: Client
+
+ actions: ResourceActionsClient
+ """Certificates scoped actions client
+
+ :type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
+ """
+
+ def __init__(self, client: Client):
+ super().__init__(client)
+ self.actions = ResourceActionsClient(client, "/certificates")
+
+ def get_by_id(self, id: int) -> BoundCertificate:
+ """Get a specific certificate by its ID.
+
+ :param id: int
+ :return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
+ """
+ response = self._client.request(url=f"/certificates/{id}", method="GET")
+ return BoundCertificate(self, response["certificate"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> CertificatesPageResult:
+ """Get a list of certificates
+
+ :param name: str (optional)
+ Can be used to filter certificates by their name.
+ :param label_selector: str (optional)
+ Can be used to filter certificates by labels. The response will only contain certificates matching the label selector.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+
+ if page is not None:
+ params["page"] = page
+
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url="/certificates", method="GET", params=params
+ )
+
+ certificates = [
+ BoundCertificate(self, certificate_data)
+ for certificate_data in response["certificates"]
+ ]
+
+ return CertificatesPageResult(certificates, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ ) -> list[BoundCertificate]:
+ """Get all certificates
+
+ :param name: str (optional)
+ Can be used to filter certificates by their name.
+ :param label_selector: str (optional)
+ Can be used to filter certificates by labels. The response will only contain certificates matching the label selector.
+ :return: List[:class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`]
+ """
+ return self._iter_pages(self.get_list, name=name, label_selector=label_selector)
+
+ def get_by_name(self, name: str) -> BoundCertificate | None:
+ """Get certificate by name
+
+ :param name: str
+ Used to get certificate by name.
+ :return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
+ """
+ return self._get_first_by(name=name)
+
+ def create(
+ self,
+ name: str,
+ certificate: str,
+ private_key: str,
+ labels: dict[str, str] | None = None,
+ ) -> BoundCertificate:
+ """Creates a new Certificate with the given name, certificate and private_key. This methods allows only creating
+ custom uploaded certificates. If you want to create a managed certificate use :func:`~hcloud.certificates.client.CertificatesClient.create_managed`
+
+ :param name: str
+ :param certificate: str
+ Certificate and chain in PEM format, in order so that each record directly certifies the one preceding
+ :param private_key: str
+ Certificate key in PEM format
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
+ """
+ data: dict[str, Any] = {
+ "name": name,
+ "certificate": certificate,
+ "private_key": private_key,
+ "type": Certificate.TYPE_UPLOADED,
+ }
+ if labels is not None:
+ data["labels"] = labels
+ response = self._client.request(url="/certificates", method="POST", json=data)
+ return BoundCertificate(self, response["certificate"])
+
+ def create_managed(
+ self,
+ name: str,
+ domain_names: list[str],
+ labels: dict[str, str] | None = None,
+ ) -> CreateManagedCertificateResponse:
+ """Creates a new managed Certificate with the given name and domain names. This methods allows only creating
+ managed certificates for domains that are using the Hetzner DNS service. If you want to create a custom uploaded certificate use :func:`~hcloud.certificates.client.CertificatesClient.create`
+
+ :param name: str
+ :param domain_names: List[str]
+ Domains and subdomains that should be contained in the Certificate
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
+ """
+ data: dict[str, Any] = {
+ "name": name,
+ "type": Certificate.TYPE_MANAGED,
+ "domain_names": domain_names,
+ }
+ if labels is not None:
+ data["labels"] = labels
+ response = self._client.request(url="/certificates", method="POST", json=data)
+ return CreateManagedCertificateResponse(
+ certificate=BoundCertificate(self, response["certificate"]),
+ action=BoundAction(self._client.actions, response["action"]),
+ )
+
+ def update(
+ self,
+ certificate: Certificate | BoundCertificate,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundCertificate:
+ """Updates a Certificate. You can update a certificate name and labels.
+
+ :param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
+ :param name: str (optional)
+ New name to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
+ """
+ data: dict[str, Any] = {}
+ if name is not None:
+ data["name"] = name
+ if labels is not None:
+ data["labels"] = labels
+ response = self._client.request(
+ url=f"/certificates/{certificate.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundCertificate(self, response["certificate"])
+
+ def delete(self, certificate: Certificate | BoundCertificate) -> bool:
+ """Deletes a certificate.
+
+ :param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
+ :return: True
+ """
+ self._client.request(
+ url=f"/certificates/{certificate.id}",
+ method="DELETE",
+ )
+ # Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
+ return True
+
+ def get_actions_list(
+ self,
+ certificate: Certificate | BoundCertificate,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a Certificate.
+
+ :param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if status is not None:
+ params["status"] = status
+ if sort is not None:
+ params["sort"] = sort
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url=f"/certificates/{certificate.id}/actions",
+ method="GET",
+ params=params,
+ )
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+ return ActionsPageResult(actions, Meta.parse_meta(response))
+
+ def get_actions(
+ self,
+ certificate: Certificate | BoundCertificate,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a Certificate.
+
+ :param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._iter_pages(
+ self.get_actions_list,
+ certificate,
+ status=status,
+ sort=sort,
+ )
+
+ def retry_issuance(
+ self,
+ certificate: Certificate | BoundCertificate,
+ ) -> BoundAction:
+ """Returns all action objects for a Certificate.
+
+ :param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/certificates/{certificate.id}/actions/retry",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/domain.py
new file mode 100644
index 000000000..c09c288d3
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/certificates/domain.py
@@ -0,0 +1,133 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain, DomainIdentityMixin
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from .client import BoundCertificate
+
+
+class Certificate(BaseDomain, DomainIdentityMixin):
+ """Certificate Domain
+
+ :param id: int ID of Certificate
+ :param name: str Name of Certificate
+ :param certificate: str Certificate and chain in PEM format, in order so that each record directly certifies the one preceding
+ :param not_valid_before: datetime
+ Point in time when the Certificate becomes valid
+ :param not_valid_after: datetime
+ Point in time when the Certificate becomes invalid
+ :param domain_names: List[str] List of domains and subdomains covered by this certificate
+ :param fingerprint: str Fingerprint of the Certificate
+ :param labels: dict
+ User-defined labels (key-value pairs)
+ :param created: datetime
+ Point in time when the certificate was created
+ :param type: str Type of Certificate
+ :param status: ManagedCertificateStatus Current status of a type managed Certificate, always none for type uploaded Certificates
+ """
+
+ __slots__ = (
+ "id",
+ "name",
+ "certificate",
+ "not_valid_before",
+ "not_valid_after",
+ "domain_names",
+ "fingerprint",
+ "created",
+ "labels",
+ "type",
+ "status",
+ )
+ TYPE_UPLOADED = "uploaded"
+ TYPE_MANAGED = "managed"
+
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ certificate: str | None = None,
+ not_valid_before: str | None = None,
+ not_valid_after: str | None = None,
+ domain_names: list[str] | None = None,
+ fingerprint: str | None = None,
+ created: str | None = None,
+ labels: dict[str, str] | None = None,
+ type: str | None = None,
+ status: ManagedCertificateStatus | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.type = type
+ self.certificate = certificate
+ self.domain_names = domain_names
+ self.fingerprint = fingerprint
+ self.not_valid_before = isoparse(not_valid_before) if not_valid_before else None
+ self.not_valid_after = isoparse(not_valid_after) if not_valid_after else None
+ self.created = isoparse(created) if created else None
+ self.labels = labels
+ self.status = status
+
+
+class ManagedCertificateStatus(BaseDomain):
+ """ManagedCertificateStatus Domain
+
+ :param issuance: str
+ Status of the issuance process of the Certificate
+ :param renewal: str
+ Status of the renewal process of the Certificate
+ :param error: ManagedCertificateError
+ If issuance or renewal reports failure, this property contains information about what happened
+ """
+
+ def __init__(
+ self,
+ issuance: str | None = None,
+ renewal: str | None = None,
+ error: ManagedCertificateError | None = None,
+ ):
+ self.issuance = issuance
+ self.renewal = renewal
+ self.error = error
+
+
+class ManagedCertificateError(BaseDomain):
+ """ManagedCertificateError Domain
+
+ :param code: str
+ Error code identifying the error
+ :param message:
+ Message detailing the error
+ """
+
+ def __init__(self, code: str | None = None, message: str | None = None):
+ self.code = code
+ self.message = message
+
+
+class CreateManagedCertificateResponse(BaseDomain):
+ """Create Managed Certificate Response Domain
+
+ :param certificate: :class:`BoundCertificate <hcloud.certificate.client.BoundCertificate>`
+ The created server
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ Shows the progress of the certificate creation
+ """
+
+ __slots__ = ("certificate", "action")
+
+ def __init__(
+ self,
+ certificate: BoundCertificate,
+ action: BoundAction,
+ ):
+ self.certificate = certificate
+ self.action = action
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/__init__.py
new file mode 100644
index 000000000..4e17dac97
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/__init__.py
@@ -0,0 +1,4 @@
+from __future__ import annotations
+
+from .client import BoundModelBase, ClientEntityBase # noqa: F401
+from .domain import BaseDomain, DomainIdentityMixin, Meta, Pagination # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/client.py
new file mode 100644
index 000000000..d213daf00
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/client.py
@@ -0,0 +1,98 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, Callable
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class ClientEntityBase:
+ _client: Client
+
+ max_per_page: int = 50
+
+ def __init__(self, client: Client):
+ """
+ :param client: Client
+ :return self
+ """
+ self._client = client
+
+ def _iter_pages( # type: ignore[no-untyped-def]
+ self,
+ list_function: Callable,
+ *args,
+ **kwargs,
+ ) -> list:
+ results = []
+
+ page = 1
+ while page:
+ # The *PageResult tuples MUST have the following structure
+ # `(result: List[Bound*], meta: Meta)`
+ result, meta = list_function(
+ *args, page=page, per_page=self.max_per_page, **kwargs
+ )
+ if result:
+ results.extend(result)
+
+ if meta and meta.pagination and meta.pagination.next_page:
+ page = meta.pagination.next_page
+ else:
+ page = 0
+
+ return results
+
+ def _get_first_by(self, **kwargs): # type: ignore[no-untyped-def]
+ assert hasattr(self, "get_list")
+ # pylint: disable=no-member
+ entities, _ = self.get_list(**kwargs)
+ return entities[0] if entities else None
+
+
+class BoundModelBase:
+ """Bound Model Base"""
+
+ model: Any
+
+ def __init__(
+ self,
+ client: ClientEntityBase,
+ data: dict,
+ complete: bool = True,
+ ):
+ """
+ :param client:
+ The client for the specific model to use
+ :param data:
+ The data of the model
+ :param complete: bool
+ False if not all attributes of the model fetched
+ """
+ self._client = client
+ self.complete = complete
+ self.data_model = self.model.from_dict(data)
+
+ def __getattr__(self, name: str): # type: ignore[no-untyped-def]
+ """Allow magical access to the properties of the model
+ :param name: str
+ :return:
+ """
+ value = getattr(self.data_model, name)
+ if not value and not self.complete:
+ self.reload()
+ value = getattr(self.data_model, name)
+ return value
+
+ def reload(self) -> None:
+ """Reloads the model and tries to get all data from the APIx"""
+ assert hasattr(self._client, "get_by_id")
+ bound_model = self._client.get_by_id(self.data_model.id)
+ self.data_model = bound_model.data_model
+ self.complete = True
+
+ def __repr__(self) -> str:
+ # Override and reset hcloud.core.domain.BaseDomain.__repr__ method for bound
+ # models, as they will generate a lot of API call trying to print all the fields
+ # of the model.
+ return object.__repr__(self)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/domain.py
new file mode 100644
index 000000000..692f7488b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/core/domain.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+
+class BaseDomain:
+ __slots__ = ()
+
+ @classmethod
+ def from_dict(cls, data: dict): # type: ignore[no-untyped-def]
+ """
+ Build the domain object from the data dict.
+ """
+ supported_data = {k: v for k, v in data.items() if k in cls.__slots__}
+ return cls(**supported_data)
+
+ def __repr__(self) -> str:
+ kwargs = [f"{key}={getattr(self, key)!r}" for key in self.__slots__] # type: ignore[var-annotated]
+ return f"{self.__class__.__qualname__}({', '.join(kwargs)})"
+
+
+class DomainIdentityMixin:
+ __slots__ = ()
+
+ id: int | None
+ name: str | None
+
+ @property
+ def id_or_name(self) -> int | str:
+ """
+ Return the first defined value, and fails if none is defined.
+ """
+ if self.id is not None:
+ return self.id
+ if self.name is not None:
+ return self.name
+ raise ValueError("id or name must be set")
+
+
+class Pagination(BaseDomain):
+ __slots__ = (
+ "page",
+ "per_page",
+ "previous_page",
+ "next_page",
+ "last_page",
+ "total_entries",
+ )
+
+ def __init__(
+ self,
+ page: int,
+ per_page: int,
+ previous_page: int | None = None,
+ next_page: int | None = None,
+ last_page: int | None = None,
+ total_entries: int | None = None,
+ ):
+ self.page = page
+ self.per_page = per_page
+ self.previous_page = previous_page
+ self.next_page = next_page
+ self.last_page = last_page
+ self.total_entries = total_entries
+
+
+class Meta(BaseDomain):
+ __slots__ = ("pagination",)
+
+ def __init__(self, pagination: Pagination | None = None):
+ self.pagination = pagination
+
+ @classmethod
+ def parse_meta(cls, response: dict) -> Meta | None:
+ """
+ If present, extract the meta details from the response and return a meta object.
+ """
+ meta = None
+ if response and "meta" in response:
+ meta = cls()
+ try:
+ meta.pagination = Pagination(**response["meta"]["pagination"])
+ except KeyError:
+ pass
+
+ return meta
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/__init__.py
new file mode 100644
index 000000000..559694c06
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/__init__.py
@@ -0,0 +1,8 @@
+from __future__ import annotations
+
+from .client import ( # noqa: F401
+ BoundDatacenter,
+ DatacentersClient,
+ DatacentersPageResult,
+)
+from .domain import Datacenter, DatacenterServerTypes # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/client.py
new file mode 100644
index 000000000..1be1e126e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/client.py
@@ -0,0 +1,121 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from ..locations import BoundLocation
+from ..server_types import BoundServerType
+from .domain import Datacenter, DatacenterServerTypes
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundDatacenter(BoundModelBase, Datacenter):
+ _client: DatacentersClient
+
+ model = Datacenter
+
+ def __init__(self, client: DatacentersClient, data: dict):
+ location = data.get("location")
+ if location is not None:
+ data["location"] = BoundLocation(client._client.locations, location)
+
+ server_types = data.get("server_types")
+ if server_types is not None:
+ available = [
+ BoundServerType(
+ client._client.server_types, {"id": server_type}, complete=False
+ )
+ for server_type in server_types["available"]
+ ]
+ supported = [
+ BoundServerType(
+ client._client.server_types, {"id": server_type}, complete=False
+ )
+ for server_type in server_types["supported"]
+ ]
+ available_for_migration = [
+ BoundServerType(
+ client._client.server_types, {"id": server_type}, complete=False
+ )
+ for server_type in server_types["available_for_migration"]
+ ]
+ data["server_types"] = DatacenterServerTypes(
+ available=available,
+ supported=supported,
+ available_for_migration=available_for_migration,
+ )
+
+ super().__init__(client, data)
+
+
+class DatacentersPageResult(NamedTuple):
+ datacenters: list[BoundDatacenter]
+ meta: Meta | None
+
+
+class DatacentersClient(ClientEntityBase):
+ _client: Client
+
+ def get_by_id(self, id: int) -> BoundDatacenter:
+ """Get a specific datacenter by its ID.
+
+ :param id: int
+ :return: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`
+ """
+ response = self._client.request(url=f"/datacenters/{id}", method="GET")
+ return BoundDatacenter(self, response["datacenter"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> DatacentersPageResult:
+ """Get a list of datacenters
+
+ :param name: str (optional)
+ Can be used to filter datacenters by their name.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+
+ if page is not None:
+ params["page"] = page
+
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(url="/datacenters", method="GET", params=params)
+
+ datacenters = [
+ BoundDatacenter(self, datacenter_data)
+ for datacenter_data in response["datacenters"]
+ ]
+
+ return DatacentersPageResult(datacenters, Meta.parse_meta(response))
+
+ def get_all(self, name: str | None = None) -> list[BoundDatacenter]:
+ """Get all datacenters
+
+ :param name: str (optional)
+ Can be used to filter datacenters by their name.
+ :return: List[:class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`]
+ """
+ return self._iter_pages(self.get_list, name=name)
+
+ def get_by_name(self, name: str) -> BoundDatacenter | None:
+ """Get datacenter by name
+
+ :param name: str
+ Used to get datacenter by name.
+ :return: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`
+ """
+ return self._get_first_by(name=name)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/domain.py
new file mode 100644
index 000000000..05d5f793f
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/datacenters/domain.py
@@ -0,0 +1,60 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from ..core import BaseDomain, DomainIdentityMixin
+
+if TYPE_CHECKING:
+ from ..locations import Location
+ from ..server_types import BoundServerType
+
+
+class Datacenter(BaseDomain, DomainIdentityMixin):
+ """Datacenter Domain
+
+ :param id: int ID of Datacenter
+ :param name: str Name of Datacenter
+ :param description: str Description of Datacenter
+ :param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
+ :param server_types: :class:`DatacenterServerTypes <hcloud.datacenters.domain.DatacenterServerTypes>`
+ """
+
+ __slots__ = ("id", "name", "description", "location", "server_types")
+
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ description: str | None = None,
+ location: Location | None = None,
+ server_types: DatacenterServerTypes | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.description = description
+ self.location = location
+ self.server_types = server_types
+
+
+class DatacenterServerTypes(BaseDomain):
+ """DatacenterServerTypes Domain
+
+ :param available: List[:class:`BoundServerTypes <hcloud.server_types.client.BoundServerTypes>`]
+ All available server types for this datacenter
+ :param supported: List[:class:`BoundServerTypes <hcloud.server_types.client.BoundServerTypes>`]
+ All supported server types for this datacenter
+ :param available_for_migration: List[:class:`BoundServerTypes <hcloud.server_types.client.BoundServerTypes>`]
+ All available for migration (change type) server types for this datacenter
+ """
+
+ __slots__ = ("available", "supported", "available_for_migration")
+
+ def __init__(
+ self,
+ available: list[BoundServerType],
+ supported: list[BoundServerType],
+ available_for_migration: list[BoundServerType],
+ ):
+ self.available = available
+ self.supported = supported
+ self.available_for_migration = available_for_migration
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/deprecation/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/deprecation/__init__.py
new file mode 100644
index 000000000..315576b11
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/deprecation/__init__.py
@@ -0,0 +1,3 @@
+from __future__ import annotations
+
+from .domain import DeprecationInfo # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/deprecation/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/deprecation/domain.py
new file mode 100644
index 000000000..b79e70943
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/deprecation/domain.py
@@ -0,0 +1,36 @@
+from __future__ import annotations
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain
+
+
+class DeprecationInfo(BaseDomain):
+ """Describes if, when & how the resources was deprecated. If this field is set to ``None`` the resource is not
+ deprecated. If it has a value, it is considered deprecated.
+
+ :param announced: datetime
+ Date of when the deprecation was announced.
+ :param unavailable_after: datetime
+ After the time in this field, the resource will not be available from the general listing endpoint of the
+ resource type, and it can not be used in new resources. For example, if this is an image, you can not create
+ new servers with this image after the mentioned date.
+ """
+
+ __slots__ = (
+ "announced",
+ "unavailable_after",
+ )
+
+ def __init__(
+ self,
+ announced: str | None = None,
+ unavailable_after: str | None = None,
+ ):
+ self.announced = isoparse(announced) if announced else None
+ self.unavailable_after = (
+ isoparse(unavailable_after) if unavailable_after else None
+ )
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/__init__.py
new file mode 100644
index 000000000..5205d7664
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/__init__.py
@@ -0,0 +1,11 @@
+from __future__ import annotations
+
+from .client import BoundFirewall, FirewallsClient, FirewallsPageResult # noqa: F401
+from .domain import ( # noqa: F401
+ CreateFirewallResponse,
+ Firewall,
+ FirewallResource,
+ FirewallResourceAppliedToResources,
+ FirewallResourceLabelSelector,
+ FirewallRule,
+)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/client.py
new file mode 100644
index 000000000..fbcd10080
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/client.py
@@ -0,0 +1,501 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import (
+ CreateFirewallResponse,
+ Firewall,
+ FirewallResource,
+ FirewallResourceAppliedToResources,
+ FirewallResourceLabelSelector,
+ FirewallRule,
+)
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundFirewall(BoundModelBase, Firewall):
+ _client: FirewallsClient
+
+ model = Firewall
+
+ def __init__(self, client: FirewallsClient, data: dict, complete: bool = True):
+ rules = data.get("rules", [])
+ if rules:
+ rules = [
+ FirewallRule(
+ direction=rule["direction"],
+ source_ips=rule["source_ips"],
+ destination_ips=rule["destination_ips"],
+ protocol=rule["protocol"],
+ port=rule["port"],
+ description=rule["description"],
+ )
+ for rule in rules
+ ]
+ data["rules"] = rules
+
+ applied_to = data.get("applied_to", [])
+ if applied_to:
+ # pylint: disable=import-outside-toplevel
+ from ..servers import BoundServer
+
+ data_applied_to = []
+ for firewall_resource in applied_to:
+ applied_to_resources = None
+ if firewall_resource.get("applied_to_resources"):
+ applied_to_resources = [
+ FirewallResourceAppliedToResources(
+ type=resource["type"],
+ server=(
+ BoundServer(
+ client._client.servers,
+ resource.get("server"),
+ complete=False,
+ )
+ if resource.get("server") is not None
+ else None
+ ),
+ )
+ for resource in firewall_resource.get("applied_to_resources")
+ ]
+
+ if firewall_resource["type"] == FirewallResource.TYPE_SERVER:
+ data_applied_to.append(
+ FirewallResource(
+ type=firewall_resource["type"],
+ server=BoundServer(
+ client._client.servers,
+ firewall_resource["server"],
+ complete=False,
+ ),
+ applied_to_resources=applied_to_resources,
+ )
+ )
+ elif firewall_resource["type"] == FirewallResource.TYPE_LABEL_SELECTOR:
+ data_applied_to.append(
+ FirewallResource(
+ type=firewall_resource["type"],
+ label_selector=FirewallResourceLabelSelector(
+ selector=firewall_resource["label_selector"]["selector"]
+ ),
+ applied_to_resources=applied_to_resources,
+ )
+ )
+
+ data["applied_to"] = data_applied_to
+
+ super().__init__(client, data, complete)
+
+ def get_actions_list(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a Firewall.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ return self._client.get_actions_list(self, status, sort, page, per_page)
+
+ def get_actions(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a Firewall.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.get_actions(self, status, sort)
+
+ def update(
+ self,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundFirewall:
+ """Updates the name or labels of a Firewall.
+
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param name: str (optional)
+ New Name to set
+ :return: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
+ """
+ return self._client.update(self, labels, name)
+
+ def delete(self) -> bool:
+ """Deletes a Firewall.
+
+ :return: boolean
+ """
+ return self._client.delete(self)
+
+ def set_rules(self, rules: list[FirewallRule]) -> list[BoundAction]:
+ """Sets the rules of a Firewall. All existing rules will be overwritten. Pass an empty rules array to remove all rules.
+ :param rules: List[:class:`FirewallRule <hcloud.firewalls.domain.FirewallRule>`]
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+
+ return self._client.set_rules(self, rules)
+
+ def apply_to_resources(
+ self,
+ resources: list[FirewallResource],
+ ) -> list[BoundAction]:
+ """Applies one Firewall to multiple resources.
+ :param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.apply_to_resources(self, resources)
+
+ def remove_from_resources(
+ self,
+ resources: list[FirewallResource],
+ ) -> list[BoundAction]:
+ """Removes one Firewall from multiple resources.
+ :param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.remove_from_resources(self, resources)
+
+
+class FirewallsPageResult(NamedTuple):
+ firewalls: list[BoundFirewall]
+ meta: Meta | None
+
+
+class FirewallsClient(ClientEntityBase):
+ _client: Client
+
+ actions: ResourceActionsClient
+ """Firewalls scoped actions client
+
+ :type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
+ """
+
+ def __init__(self, client: Client):
+ super().__init__(client)
+ self.actions = ResourceActionsClient(client, "/firewalls")
+
+ def get_actions_list(
+ self,
+ firewall: Firewall | BoundFirewall,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a Firewall.
+
+ :param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if status is not None:
+ params["status"] = status
+ if sort is not None:
+ params["sort"] = sort
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+ response = self._client.request(
+ url=f"/firewalls/{firewall.id}/actions",
+ method="GET",
+ params=params,
+ )
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+ return ActionsPageResult(actions, Meta.parse_meta(response))
+
+ def get_actions(
+ self,
+ firewall: Firewall | BoundFirewall,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a Firewall.
+
+ :param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._iter_pages(
+ self.get_actions_list,
+ firewall,
+ status=status,
+ sort=sort,
+ )
+
+ def get_by_id(self, id: int) -> BoundFirewall:
+ """Returns a specific Firewall object.
+
+ :param id: int
+ :return: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
+ """
+ response = self._client.request(url=f"/firewalls/{id}", method="GET")
+ return BoundFirewall(self, response["firewall"])
+
+ def get_list(
+ self,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ name: str | None = None,
+ sort: list[str] | None = None,
+ ) -> FirewallsPageResult:
+ """Get a list of floating ips from this account
+
+ :param label_selector: str (optional)
+ Can be used to filter Firewalls by labels. The response will only contain Firewalls matching the label selector values.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :param name: str (optional)
+ Can be used to filter networks by their name.
+ :param sort: List[str] (optional)
+ Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
+ :return: (List[:class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+ if name is not None:
+ params["name"] = name
+ if sort is not None:
+ params["sort"] = sort
+ response = self._client.request(url="/firewalls", method="GET", params=params)
+ firewalls = [
+ BoundFirewall(self, firewall_data)
+ for firewall_data in response["firewalls"]
+ ]
+
+ return FirewallsPageResult(firewalls, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ label_selector: str | None = None,
+ name: str | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundFirewall]:
+ """Get all floating ips from this account
+
+ :param label_selector: str (optional)
+ Can be used to filter Firewalls by labels. The response will only contain Firewalls matching the label selector values.
+ :param name: str (optional)
+ Can be used to filter networks by their name.
+ :param sort: List[str] (optional)
+ Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
+ :return: List[:class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`]
+ """
+ return self._iter_pages(
+ self.get_list,
+ label_selector=label_selector,
+ name=name,
+ sort=sort,
+ )
+
+ def get_by_name(self, name: str) -> BoundFirewall | None:
+ """Get Firewall by name
+
+ :param name: str
+ Used to get Firewall by name.
+ :return: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
+ """
+ return self._get_first_by(name=name)
+
+ def create(
+ self,
+ name: str,
+ rules: list[FirewallRule] | None = None,
+ labels: str | None = None,
+ resources: list[FirewallResource] | None = None,
+ ) -> CreateFirewallResponse:
+ """Creates a new Firewall.
+
+ :param name: str
+ Firewall Name
+ :param rules: List[:class:`FirewallRule <hcloud.firewalls.domain.FirewallRule>`] (optional)
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`] (optional)
+ :return: :class:`CreateFirewallResponse <hcloud.firewalls.domain.CreateFirewallResponse>`
+ """
+
+ data: dict[str, Any] = {"name": name}
+ if labels is not None:
+ data["labels"] = labels
+
+ if rules is not None:
+ data.update({"rules": []})
+ for rule in rules:
+ data["rules"].append(rule.to_payload())
+ if resources is not None:
+ data.update({"apply_to": []})
+ for resource in resources:
+ data["apply_to"].append(resource.to_payload())
+ response = self._client.request(url="/firewalls", json=data, method="POST")
+
+ actions = []
+ if response.get("actions") is not None:
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+
+ result = CreateFirewallResponse(
+ firewall=BoundFirewall(self, response["firewall"]), actions=actions
+ )
+ return result
+
+ def update(
+ self,
+ firewall: Firewall | BoundFirewall,
+ labels: dict[str, str] | None = None,
+ name: str | None = None,
+ ) -> BoundFirewall:
+ """Updates the description or labels of a Firewall.
+
+ :param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param name: str (optional)
+ New name to set
+ :return: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
+ """
+ data: dict[str, Any] = {}
+ if labels is not None:
+ data["labels"] = labels
+ if name is not None:
+ data["name"] = name
+
+ response = self._client.request(
+ url=f"/firewalls/{firewall.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundFirewall(self, response["firewall"])
+
+ def delete(self, firewall: Firewall | BoundFirewall) -> bool:
+ """Deletes a Firewall.
+
+ :param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
+ :return: boolean
+ """
+ self._client.request(
+ url=f"/firewalls/{firewall.id}",
+ method="DELETE",
+ )
+ # Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
+ return True
+
+ def set_rules(
+ self,
+ firewall: Firewall | BoundFirewall,
+ rules: list[FirewallRule],
+ ) -> list[BoundAction]:
+ """Sets the rules of a Firewall. All existing rules will be overwritten. Pass an empty rules array to remove all rules.
+
+ :param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
+ :param rules: List[:class:`FirewallRule <hcloud.firewalls.domain.FirewallRule>`]
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ data: dict[str, Any] = {"rules": []}
+ for rule in rules:
+ data["rules"].append(rule.to_payload())
+ response = self._client.request(
+ url=f"/firewalls/{firewall.id}/actions/set_rules",
+ method="POST",
+ json=data,
+ )
+ return [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+
+ def apply_to_resources(
+ self,
+ firewall: Firewall | BoundFirewall,
+ resources: list[FirewallResource],
+ ) -> list[BoundAction]:
+ """Applies one Firewall to multiple resources.
+
+ :param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
+ :param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ data: dict[str, Any] = {"apply_to": []}
+ for resource in resources:
+ data["apply_to"].append(resource.to_payload())
+ response = self._client.request(
+ url=f"/firewalls/{firewall.id}/actions/apply_to_resources",
+ method="POST",
+ json=data,
+ )
+ return [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+
+ def remove_from_resources(
+ self,
+ firewall: Firewall | BoundFirewall,
+ resources: list[FirewallResource],
+ ) -> list[BoundAction]:
+ """Removes one Firewall from multiple resources.
+
+ :param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
+ :param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ data: dict[str, Any] = {"remove_from": []}
+ for resource in resources:
+ data["remove_from"].append(resource.to_payload())
+ response = self._client.request(
+ url=f"/firewalls/{firewall.id}/actions/remove_from_resources",
+ method="POST",
+ json=data,
+ )
+ return [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/domain.py
new file mode 100644
index 000000000..5ce9281d9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/firewalls/domain.py
@@ -0,0 +1,221 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from ..servers import BoundServer, Server
+ from .client import BoundFirewall
+
+
+class Firewall(BaseDomain):
+ """Firewall Domain
+
+ :param id: int
+ ID of the Firewall
+ :param name: str
+ Name of the Firewall
+ :param labels: dict
+ User-defined labels (key-value pairs)
+ :param rules: List[:class:`FirewallRule <hcloud.firewalls.domain.FirewallRule>`]
+ Rules of the Firewall
+ :param applied_to: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
+ Resources currently using the Firewall
+ :param created: datetime
+ Point in time when the image was created
+ """
+
+ __slots__ = ("id", "name", "labels", "rules", "applied_to", "created")
+
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ rules: list[FirewallRule] | None = None,
+ applied_to: list[FirewallResource] | None = None,
+ created: str | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.rules = rules
+ self.applied_to = applied_to
+ self.labels = labels
+ self.created = isoparse(created) if created else None
+
+
+class FirewallRule(BaseDomain):
+ """Firewall Rule Domain
+
+ :param direction: str
+ The Firewall which was created
+ :param port: str
+ Port to which traffic will be allowed, only applicable for protocols TCP and UDP, specify port ranges by using
+ - as a indicator, Sample: 80-85 means all ports between 80 & 85 (80, 82, 83, 84, 85)
+ :param protocol: str
+ Select traffic direction on which rule should be applied. Use source_ips for direction in and destination_ips for direction out.
+ :param source_ips: List[str]
+ List of permitted IPv4/IPv6 addresses in CIDR notation. Use 0.0.0.0/0 to allow all IPv4 addresses and ::/0 to allow all IPv6 addresses. You can specify 100 CIDRs at most.
+ :param destination_ips: List[str]
+ List of permitted IPv4/IPv6 addresses in CIDR notation. Use 0.0.0.0/0 to allow all IPv4 addresses and ::/0 to allow all IPv6 addresses. You can specify 100 CIDRs at most.
+ :param description: str
+ Short description of the firewall rule
+ """
+
+ __slots__ = (
+ "direction",
+ "port",
+ "protocol",
+ "source_ips",
+ "destination_ips",
+ "description",
+ )
+
+ DIRECTION_IN = "in"
+ """Firewall Rule Direction In"""
+ DIRECTION_OUT = "out"
+ """Firewall Rule Direction Out"""
+
+ PROTOCOL_UDP = "udp"
+ """Firewall Rule Protocol UDP"""
+ PROTOCOL_ICMP = "icmp"
+ """Firewall Rule Protocol ICMP"""
+ PROTOCOL_TCP = "tcp"
+ """Firewall Rule Protocol TCP"""
+ PROTOCOL_ESP = "esp"
+ """Firewall Rule Protocol ESP"""
+ PROTOCOL_GRE = "gre"
+ """Firewall Rule Protocol GRE"""
+
+ def __init__(
+ self,
+ direction: str,
+ protocol: str,
+ source_ips: list[str],
+ port: str | None = None,
+ destination_ips: list[str] | None = None,
+ description: str | None = None,
+ ):
+ self.direction = direction
+ self.port = port
+ self.protocol = protocol
+ self.source_ips = source_ips
+ self.destination_ips = destination_ips or []
+ self.description = description
+
+ def to_payload(self) -> dict[str, Any]:
+ """
+ Generates the request payload from this domain object.
+ """
+ payload: dict[str, Any] = {
+ "direction": self.direction,
+ "protocol": self.protocol,
+ "source_ips": self.source_ips,
+ }
+ if len(self.destination_ips) > 0:
+ payload["destination_ips"] = self.destination_ips
+ if self.port is not None:
+ payload["port"] = self.port
+ if self.description is not None:
+ payload["description"] = self.description
+ return payload
+
+
+class FirewallResource(BaseDomain):
+ """Firewall Used By Domain
+
+ :param type: str
+ Type of resource referenced
+ :param server: Optional[Server]
+ Server the Firewall is applied to
+ :param label_selector: Optional[FirewallResourceLabelSelector]
+ Label Selector for Servers the Firewall should be applied to
+ :param applied_to_resources: (read-only) List of effective resources the firewall is
+ applied to.
+ """
+
+ __slots__ = ("type", "server", "label_selector", "applied_to_resources")
+
+ TYPE_SERVER = "server"
+ """Firewall Used By Type Server"""
+ TYPE_LABEL_SELECTOR = "label_selector"
+ """Firewall Used By Type label_selector"""
+
+ def __init__(
+ self,
+ type: str,
+ server: Server | BoundServer | None = None,
+ label_selector: FirewallResourceLabelSelector | None = None,
+ applied_to_resources: list[FirewallResourceAppliedToResources] | None = None,
+ ):
+ self.type = type
+ self.server = server
+ self.label_selector = label_selector
+ self.applied_to_resources = applied_to_resources
+
+ def to_payload(self) -> dict[str, Any]:
+ """
+ Generates the request payload from this domain object.
+ """
+ payload: dict[str, Any] = {"type": self.type}
+ if self.server is not None:
+ payload["server"] = {"id": self.server.id}
+
+ if self.label_selector is not None:
+ payload["label_selector"] = {"selector": self.label_selector.selector}
+ return payload
+
+
+class FirewallResourceAppliedToResources(BaseDomain):
+ """Firewall Resource applied to Domain
+
+ :param type: Type of resource referenced
+ :param server: Server the Firewall is applied to
+ """
+
+ __slots__ = ("type", "server")
+
+ def __init__(
+ self,
+ type: str,
+ server: BoundServer | None = None,
+ ):
+ self.type = type
+ self.server = server
+
+
+class FirewallResourceLabelSelector(BaseDomain):
+ """FirewallResourceLabelSelector Domain
+
+ :param selector: str Target label selector
+ """
+
+ def __init__(self, selector: str | None = None):
+ self.selector = selector
+
+
+class CreateFirewallResponse(BaseDomain):
+ """Create Firewall Response Domain
+
+ :param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
+ The Firewall which was created
+ :param actions: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ The Action which shows the progress of the Firewall Creation
+ """
+
+ __slots__ = ("firewall", "actions")
+
+ def __init__(
+ self,
+ firewall: BoundFirewall,
+ actions: list[BoundAction] | None,
+ ):
+ self.firewall = firewall
+ self.actions = actions
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/__init__.py
new file mode 100644
index 000000000..4e55bf5fb
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/__init__.py
@@ -0,0 +1,8 @@
+from __future__ import annotations
+
+from .client import ( # noqa: F401
+ BoundFloatingIP,
+ FloatingIPsClient,
+ FloatingIPsPageResult,
+)
+from .domain import CreateFloatingIPResponse, FloatingIP # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/client.py
new file mode 100644
index 000000000..00600e48b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/client.py
@@ -0,0 +1,459 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from ..locations import BoundLocation
+from .domain import CreateFloatingIPResponse, FloatingIP
+
+if TYPE_CHECKING:
+ from .._client import Client
+ from ..locations import Location
+ from ..servers import BoundServer, Server
+
+
+class BoundFloatingIP(BoundModelBase, FloatingIP):
+ _client: FloatingIPsClient
+
+ model = FloatingIP
+
+ def __init__(self, client: FloatingIPsClient, data: dict, complete: bool = True):
+ # pylint: disable=import-outside-toplevel
+ from ..servers import BoundServer
+
+ server = data.get("server")
+ if server is not None:
+ data["server"] = BoundServer(
+ client._client.servers, {"id": server}, complete=False
+ )
+
+ home_location = data.get("home_location")
+ if home_location is not None:
+ data["home_location"] = BoundLocation(
+ client._client.locations, home_location
+ )
+
+ super().__init__(client, data, complete)
+
+ def get_actions_list(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a Floating IP.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ return self._client.get_actions_list(self, status, sort, page, per_page)
+
+ def get_actions(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a Floating IP.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.get_actions(self, status, sort)
+
+ def update(
+ self,
+ description: str | None = None,
+ labels: dict[str, str] | None = None,
+ name: str | None = None,
+ ) -> BoundFloatingIP:
+ """Updates the description or labels of a Floating IP.
+
+ :param description: str (optional)
+ New Description to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param name: str (optional)
+ New Name to set
+ :return: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
+ """
+ return self._client.update(self, description, labels, name)
+
+ def delete(self) -> bool:
+ """Deletes a Floating IP. If it is currently assigned to a server it will automatically get unassigned.
+
+ :return: boolean
+ """
+ return self._client.delete(self)
+
+ def change_protection(self, delete: bool | None = None) -> BoundAction:
+ """Changes the protection configuration of the Floating IP.
+
+ :param delete: boolean
+ If true, prevents the Floating IP from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_protection(self, delete)
+
+ def assign(self, server: Server | BoundServer) -> BoundAction:
+ """Assigns a Floating IP to a server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ Server the Floating IP shall be assigned to
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.assign(self, server)
+
+ def unassign(self) -> BoundAction:
+ """Unassigns a Floating IP, resulting in it being unreachable. You may assign it to a server again at a later time.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.unassign(self)
+
+ def change_dns_ptr(self, ip: str, dns_ptr: str) -> BoundAction:
+ """Changes the hostname that will appear when getting the hostname belonging to this Floating IP.
+
+ :param ip: str
+ The IP address for which to set the reverse DNS entry
+ :param dns_ptr: str
+ Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_dns_ptr(self, ip, dns_ptr)
+
+
+class FloatingIPsPageResult(NamedTuple):
+ floating_ips: list[BoundFloatingIP]
+ meta: Meta | None
+
+
+class FloatingIPsClient(ClientEntityBase):
+ _client: Client
+
+ actions: ResourceActionsClient
+ """Floating IPs scoped actions client
+
+ :type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
+ """
+
+ def __init__(self, client: Client):
+ super().__init__(client)
+ self.actions = ResourceActionsClient(client, "/floating_ips")
+
+ def get_actions_list(
+ self,
+ floating_ip: FloatingIP | BoundFloatingIP,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a Floating IP.
+
+ :param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if status is not None:
+ params["status"] = status
+ if sort is not None:
+ params["sort"] = sort
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+ response = self._client.request(
+ url=f"/floating_ips/{floating_ip.id}/actions",
+ method="GET",
+ params=params,
+ )
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+ return ActionsPageResult(actions, Meta.parse_meta(response))
+
+ def get_actions(
+ self,
+ floating_ip: FloatingIP | BoundFloatingIP,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a Floating IP.
+
+ :param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._iter_pages(
+ self.get_actions_list,
+ floating_ip,
+ status=status,
+ sort=sort,
+ )
+
+ def get_by_id(self, id: int) -> BoundFloatingIP:
+ """Returns a specific Floating IP object.
+
+ :param id: int
+ :return: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
+ """
+ response = self._client.request(url=f"/floating_ips/{id}", method="GET")
+ return BoundFloatingIP(self, response["floating_ip"])
+
+ def get_list(
+ self,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ name: str | None = None,
+ ) -> FloatingIPsPageResult:
+ """Get a list of floating ips from this account
+
+ :param label_selector: str (optional)
+ Can be used to filter Floating IPs by labels. The response will only contain Floating IPs matching the label selector.able values.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :param name: str (optional)
+ Can be used to filter networks by their name.
+ :return: (List[:class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+ if name is not None:
+ params["name"] = name
+
+ response = self._client.request(
+ url="/floating_ips", method="GET", params=params
+ )
+ floating_ips = [
+ BoundFloatingIP(self, floating_ip_data)
+ for floating_ip_data in response["floating_ips"]
+ ]
+
+ return FloatingIPsPageResult(floating_ips, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ label_selector: str | None = None,
+ name: str | None = None,
+ ) -> list[BoundFloatingIP]:
+ """Get all floating ips from this account
+
+ :param label_selector: str (optional)
+ Can be used to filter Floating IPs by labels. The response will only contain Floating IPs matching the label selector.able values.
+ :param name: str (optional)
+ Can be used to filter networks by their name.
+ :return: List[:class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`]
+ """
+ return self._iter_pages(self.get_list, label_selector=label_selector, name=name)
+
+ def get_by_name(self, name: str) -> BoundFloatingIP | None:
+ """Get Floating IP by name
+
+ :param name: str
+ Used to get Floating IP by name.
+ :return: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
+ """
+ return self._get_first_by(name=name)
+
+ def create(
+ self,
+ type: str,
+ description: str | None = None,
+ labels: str | None = None,
+ home_location: Location | BoundLocation | None = None,
+ server: Server | BoundServer | None = None,
+ name: str | None = None,
+ ) -> CreateFloatingIPResponse:
+ """Creates a new Floating IP assigned to a server.
+
+ :param type: str
+ Floating IP type Choices: ipv4, ipv6
+ :param description: str (optional)
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param home_location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>` or :class:`Location <hcloud.locations.domain.Location>` (
+ Home location (routing is optimized for that location). Only optional if server argument is passed.
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ Server to assign the Floating IP to
+ :param name: str (optional)
+ :return: :class:`CreateFloatingIPResponse <hcloud.floating_ips.domain.CreateFloatingIPResponse>`
+ """
+
+ data: dict[str, Any] = {"type": type}
+ if description is not None:
+ data["description"] = description
+ if labels is not None:
+ data["labels"] = labels
+ if home_location is not None:
+ data["home_location"] = home_location.id_or_name
+ if server is not None:
+ data["server"] = server.id
+ if name is not None:
+ data["name"] = name
+
+ response = self._client.request(url="/floating_ips", json=data, method="POST")
+
+ action = None
+ if response.get("action") is not None:
+ action = BoundAction(self._client.actions, response["action"])
+
+ result = CreateFloatingIPResponse(
+ floating_ip=BoundFloatingIP(self, response["floating_ip"]), action=action
+ )
+ return result
+
+ def update(
+ self,
+ floating_ip: FloatingIP | BoundFloatingIP,
+ description: str | None = None,
+ labels: dict[str, str] | None = None,
+ name: str | None = None,
+ ) -> BoundFloatingIP:
+ """Updates the description or labels of a Floating IP.
+
+ :param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
+ :param description: str (optional)
+ New Description to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param name: str (optional)
+ New name to set
+ :return: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
+ """
+ data: dict[str, Any] = {}
+ if description is not None:
+ data["description"] = description
+ if labels is not None:
+ data["labels"] = labels
+ if name is not None:
+ data["name"] = name
+
+ response = self._client.request(
+ url=f"/floating_ips/{floating_ip.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundFloatingIP(self, response["floating_ip"])
+
+ def delete(self, floating_ip: FloatingIP | BoundFloatingIP) -> bool:
+ """Deletes a Floating IP. If it is currently assigned to a server it will automatically get unassigned.
+
+ :param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
+ :return: boolean
+ """
+ self._client.request(
+ url=f"/floating_ips/{floating_ip.id}",
+ method="DELETE",
+ )
+ # Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
+ return True
+
+ def change_protection(
+ self,
+ floating_ip: FloatingIP | BoundFloatingIP,
+ delete: bool | None = None,
+ ) -> BoundAction:
+ """Changes the protection configuration of the Floating IP.
+
+ :param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
+ :param delete: boolean
+ If true, prevents the Floating IP from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {}
+ if delete is not None:
+ data.update({"delete": delete})
+
+ response = self._client.request(
+ url=f"/floating_ips/{floating_ip.id}/actions/change_protection",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def assign(
+ self,
+ floating_ip: FloatingIP | BoundFloatingIP,
+ server: Server | BoundServer,
+ ) -> BoundAction:
+ """Assigns a Floating IP to a server.
+
+ :param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ Server the Floating IP shall be assigned to
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/floating_ips/{floating_ip.id}/actions/assign",
+ method="POST",
+ json={"server": server.id},
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def unassign(self, floating_ip: FloatingIP | BoundFloatingIP) -> BoundAction:
+ """Unassigns a Floating IP, resulting in it being unreachable. You may assign it to a server again at a later time.
+
+ :param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/floating_ips/{floating_ip.id}/actions/unassign",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_dns_ptr(
+ self,
+ floating_ip: FloatingIP | BoundFloatingIP,
+ ip: str,
+ dns_ptr: str,
+ ) -> BoundAction:
+ """Changes the hostname that will appear when getting the hostname belonging to this Floating IP.
+
+ :param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
+ :param ip: str
+ The IP address for which to set the reverse DNS entry
+ :param dns_ptr: str
+ Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/floating_ips/{floating_ip.id}/actions/change_dns_ptr",
+ method="POST",
+ json={"ip": ip, "dns_ptr": dns_ptr},
+ )
+ return BoundAction(self._client.actions, response["action"])
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/domain.py
new file mode 100644
index 000000000..e1f295bd6
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/floating_ips/domain.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from ..locations import BoundLocation
+ from ..servers import BoundServer
+ from .client import BoundFloatingIP
+
+
+class FloatingIP(BaseDomain):
+ """Floating IP Domain
+
+ :param id: int
+ ID of the Floating IP
+ :param description: str, None
+ Description of the Floating IP
+ :param ip: str
+ IP address of the Floating IP
+ :param type: str
+ Type of Floating IP. Choices: `ipv4`, `ipv6`
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>`, None
+ Server the Floating IP is assigned to, None if it is not assigned at all
+ :param dns_ptr: List[Dict]
+ Array of reverse DNS entries
+ :param home_location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
+ Location the Floating IP was created in. Routing is optimized for this location.
+ :param blocked: boolean
+ Whether the IP is blocked
+ :param protection: dict
+ Protection configuration for the Floating IP
+ :param labels: dict
+ User-defined labels (key-value pairs)
+ :param created: datetime
+ Point in time when the Floating IP was created
+ :param name: str
+ Name of the Floating IP
+ """
+
+ __slots__ = (
+ "id",
+ "type",
+ "description",
+ "ip",
+ "server",
+ "dns_ptr",
+ "home_location",
+ "blocked",
+ "protection",
+ "labels",
+ "name",
+ "created",
+ )
+
+ def __init__(
+ self,
+ id: int | None = None,
+ type: str | None = None,
+ description: str | None = None,
+ ip: str | None = None,
+ server: BoundServer | None = None,
+ dns_ptr: list[dict] | None = None,
+ home_location: BoundLocation | None = None,
+ blocked: bool | None = None,
+ protection: dict | None = None,
+ labels: dict[str, str] | None = None,
+ created: str | None = None,
+ name: str | None = None,
+ ):
+ self.id = id
+ self.type = type
+ self.description = description
+ self.ip = ip
+ self.server = server
+ self.dns_ptr = dns_ptr
+ self.home_location = home_location
+ self.blocked = blocked
+ self.protection = protection
+ self.labels = labels
+ self.created = isoparse(created) if created else None
+ self.name = name
+
+
+class CreateFloatingIPResponse(BaseDomain):
+ """Create Floating IP Response Domain
+
+ :param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
+ The Floating IP which was created
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ The Action which shows the progress of the Floating IP Creation
+ """
+
+ __slots__ = ("floating_ip", "action")
+
+ def __init__(
+ self,
+ floating_ip: BoundFloatingIP,
+ action: BoundAction | None,
+ ):
+ self.floating_ip = floating_ip
+ self.action = action
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/hcloud.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/hcloud.py
new file mode 100644
index 000000000..9de1cfe5b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/hcloud.py
@@ -0,0 +1,12 @@
+from __future__ import annotations
+
+import warnings
+
+warnings.warn(
+ "The 'hcloud.hcloud' module is deprecated, please import from the 'hcloud' module instead (e.g. 'from hcloud import Client').",
+ DeprecationWarning,
+ stacklevel=2,
+)
+
+# pylint: disable=wildcard-import,wrong-import-position,unused-wildcard-import
+from ._client import * # noqa
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/helpers/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/helpers/__init__.py
new file mode 100644
index 000000000..b6a4cd73d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/helpers/__init__.py
@@ -0,0 +1,3 @@
+from __future__ import annotations
+
+from .labels import LabelValidator # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/helpers/labels.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/helpers/labels.py
new file mode 100644
index 000000000..360415784
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/helpers/labels.py
@@ -0,0 +1,46 @@
+from __future__ import annotations
+
+import re
+
+
+class LabelValidator:
+ KEY_REGEX = re.compile(
+ r"^([a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]){0,253}[a-z0-9A-Z])?/)?[a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]|){0,61}[a-z0-9A-Z])?$"
+ )
+ VALUE_REGEX = re.compile(
+ r"^(([a-z0-9A-Z](?:[\-_.]|[a-z0-9A-Z]){0,61})?[a-z0-9A-Z]$|$)"
+ )
+
+ @staticmethod
+ def validate(labels: dict[str, str]) -> bool:
+ """Validates Labels. If you want to know which key/value pair of the dict is not correctly formatted
+ use :func:`~hcloud.helpers.labels.validate_verbose`.
+
+ :return: bool
+ """
+ for key, value in labels.items():
+ if LabelValidator.KEY_REGEX.match(key) is None:
+ return False
+ if LabelValidator.VALUE_REGEX.match(value) is None:
+ return False
+ return True
+
+ @staticmethod
+ def validate_verbose(labels: dict[str, str]) -> tuple[bool, str]:
+ """Validates Labels and returns the corresponding error message if something is wrong. Returns True, <empty string>
+ if everything is fine.
+
+ :return: bool, str
+ """
+ for key, value in labels.items():
+ if LabelValidator.KEY_REGEX.match(key) is None:
+ return (
+ False,
+ f"label key {key} is not correctly formatted",
+ )
+ if LabelValidator.VALUE_REGEX.match(value) is None:
+ return (
+ False,
+ f"label value {value} (key: {key}) is not correctly formatted",
+ )
+ return True, ""
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/__init__.py
new file mode 100644
index 000000000..78cb6868f
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/__init__.py
@@ -0,0 +1,4 @@
+from __future__ import annotations
+
+from .client import BoundImage, ImagesClient, ImagesPageResult # noqa: F401
+from .domain import CreateImageResponse, Image # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/client.py
new file mode 100644
index 000000000..65b7546a8
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/client.py
@@ -0,0 +1,393 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import Image
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundImage(BoundModelBase, Image):
+ _client: ImagesClient
+
+ model = Image
+
+ def __init__(self, client: ImagesClient, data: dict):
+ # pylint: disable=import-outside-toplevel
+ from ..servers import BoundServer
+
+ created_from = data.get("created_from")
+ if created_from is not None:
+ data["created_from"] = BoundServer(
+ client._client.servers, created_from, complete=False
+ )
+ bound_to = data.get("bound_to")
+ if bound_to is not None:
+ data["bound_to"] = BoundServer(
+ client._client.servers, {"id": bound_to}, complete=False
+ )
+
+ super().__init__(client, data)
+
+ def get_actions_list(
+ self,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ status: list[str] | None = None,
+ ) -> ActionsPageResult:
+ """Returns a list of action objects for the image.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ return self._client.get_actions_list(
+ self, sort=sort, page=page, per_page=per_page, status=status
+ )
+
+ def get_actions(
+ self,
+ sort: list[str] | None = None,
+ status: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for the image.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.get_actions(self, status=status, sort=sort)
+
+ def update(
+ self,
+ description: str | None = None,
+ type: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundImage:
+ """Updates the Image. You may change the description, convert a Backup image to a Snapshot Image or change the image labels.
+
+ :param description: str (optional)
+ New description of Image
+ :param type: str (optional)
+ Destination image type to convert to
+ Choices: snapshot
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundImage <hcloud.images.client.BoundImage>`
+ """
+ return self._client.update(self, description, type, labels)
+
+ def delete(self) -> bool:
+ """Deletes an Image. Only images of type snapshot and backup can be deleted.
+
+ :return: bool
+ """
+ return self._client.delete(self)
+
+ def change_protection(self, delete: bool | None = None) -> BoundAction:
+ """Changes the protection configuration of the image. Can only be used on snapshots.
+
+ :param delete: bool
+ If true, prevents the snapshot from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_protection(self, delete)
+
+
+class ImagesPageResult(NamedTuple):
+ images: list[BoundImage]
+ meta: Meta | None
+
+
+class ImagesClient(ClientEntityBase):
+ _client: Client
+
+ actions: ResourceActionsClient
+ """Images scoped actions client
+
+ :type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
+ """
+
+ def __init__(self, client: Client):
+ super().__init__(client)
+ self.actions = ResourceActionsClient(client, "/images")
+
+ def get_actions_list(
+ self,
+ image: Image | BoundImage,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ status: list[str] | None = None,
+ ) -> ActionsPageResult:
+ """Returns a list of action objects for an image.
+
+ :param image: :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if sort is not None:
+ params["sort"] = sort
+ if status is not None:
+ params["status"] = status
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+ response = self._client.request(
+ url=f"/images/{image.id}/actions",
+ method="GET",
+ params=params,
+ )
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+ return ActionsPageResult(actions, Meta.parse_meta(response))
+
+ def get_actions(
+ self,
+ image: Image | BoundImage,
+ sort: list[str] | None = None,
+ status: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for an image.
+
+ :param image: :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `command` `status` `progress` `started` `finished` . You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default)
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._iter_pages(
+ self.get_actions_list,
+ image,
+ sort=sort,
+ status=status,
+ )
+
+ def get_by_id(self, id: int) -> BoundImage:
+ """Get a specific Image
+
+ :param id: int
+ :return: :class:`BoundImage <hcloud.images.client.BoundImage`
+ """
+ response = self._client.request(url=f"/images/{id}", method="GET")
+ return BoundImage(self, response["image"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ bound_to: list[str] | None = None,
+ type: list[str] | None = None,
+ architecture: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ status: list[str] | None = None,
+ include_deprecated: bool | None = None,
+ ) -> ImagesPageResult:
+ """Get all images
+
+ :param name: str (optional)
+ Can be used to filter images by their name.
+ :param label_selector: str (optional)
+ Can be used to filter servers by labels. The response will only contain servers matching the label selector.
+ :param bound_to: List[str] (optional)
+ Server Id linked to the image. Only available for images of type backup
+ :param type: List[str] (optional)
+ Choices: system snapshot backup
+ :param architecture: List[str] (optional)
+ Choices: x86 arm
+ :param status: List[str] (optional)
+ Can be used to filter images by their status. The response will only contain images matching the status.
+ :param sort: List[str] (optional)
+ Choices: id id:asc id:desc name name:asc name:desc created created:asc created:desc
+ :param include_deprecated: bool (optional)
+ Include deprecated images in the response. Default: False
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundImage <hcloud.images.client.BoundImage>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if bound_to is not None:
+ params["bound_to"] = bound_to
+ if type is not None:
+ params["type"] = type
+ if architecture is not None:
+ params["architecture"] = architecture
+ if sort is not None:
+ params["sort"] = sort
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+ if status is not None:
+ params["status"] = per_page
+ if include_deprecated is not None:
+ params["include_deprecated"] = include_deprecated
+ response = self._client.request(url="/images", method="GET", params=params)
+ images = [BoundImage(self, image_data) for image_data in response["images"]]
+
+ return ImagesPageResult(images, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ bound_to: list[str] | None = None,
+ type: list[str] | None = None,
+ architecture: list[str] | None = None,
+ sort: list[str] | None = None,
+ status: list[str] | None = None,
+ include_deprecated: bool | None = None,
+ ) -> list[BoundImage]:
+ """Get all images
+
+ :param name: str (optional)
+ Can be used to filter images by their name.
+ :param label_selector: str (optional)
+ Can be used to filter servers by labels. The response will only contain servers matching the label selector.
+ :param bound_to: List[str] (optional)
+ Server Id linked to the image. Only available for images of type backup
+ :param type: List[str] (optional)
+ Choices: system snapshot backup
+ :param architecture: List[str] (optional)
+ Choices: x86 arm
+ :param status: List[str] (optional)
+ Can be used to filter images by their status. The response will only contain images matching the status.
+ :param sort: List[str] (optional)
+ Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
+ :param include_deprecated: bool (optional)
+ Include deprecated images in the response. Default: False
+ :return: List[:class:`BoundImage <hcloud.images.client.BoundImage>`]
+ """
+ return self._iter_pages(
+ self.get_list,
+ name=name,
+ label_selector=label_selector,
+ bound_to=bound_to,
+ type=type,
+ architecture=architecture,
+ sort=sort,
+ status=status,
+ include_deprecated=include_deprecated,
+ )
+
+ def get_by_name(self, name: str) -> BoundImage | None:
+ """Get image by name
+
+ Deprecated: Use get_by_name_and_architecture instead.
+
+ :param name: str
+ Used to get image by name.
+ :return: :class:`BoundImage <hcloud.images.client.BoundImage>`
+ """
+ return self._get_first_by(name=name)
+
+ def get_by_name_and_architecture(
+ self,
+ name: str,
+ architecture: str,
+ ) -> BoundImage | None:
+ """Get image by name
+
+ :param name: str
+ Used to identify the image.
+ :param architecture: str
+ Used to identify the image.
+ :return: :class:`BoundImage <hcloud.images.client.BoundImage>`
+ """
+ return self._get_first_by(name=name, architecture=[architecture])
+
+ def update(
+ self,
+ image: Image | BoundImage,
+ description: str | None = None,
+ type: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundImage:
+ """Updates the Image. You may change the description, convert a Backup image to a Snapshot Image or change the image labels.
+
+ :param image: :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
+ :param description: str (optional)
+ New description of Image
+ :param type: str (optional)
+ Destination image type to convert to
+ Choices: snapshot
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundImage <hcloud.images.client.BoundImage>`
+ """
+ data: dict[str, Any] = {}
+ if description is not None:
+ data.update({"description": description})
+ if type is not None:
+ data.update({"type": type})
+ if labels is not None:
+ data.update({"labels": labels})
+ response = self._client.request(
+ url=f"/images/{image.id}", method="PUT", json=data
+ )
+ return BoundImage(self, response["image"])
+
+ def delete(self, image: Image | BoundImage) -> bool:
+ """Deletes an Image. Only images of type snapshot and backup can be deleted.
+
+ :param :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
+ :return: bool
+ """
+ self._client.request(url=f"/images/{image.id}", method="DELETE")
+ # Return allays true, because the API does not return an action for it. When an error occurs a APIException will be raised
+ return True
+
+ def change_protection(
+ self,
+ image: Image | BoundImage,
+ delete: bool | None = None,
+ ) -> BoundAction:
+ """Changes the protection configuration of the image. Can only be used on snapshots.
+
+ :param image: :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
+ :param delete: bool
+ If true, prevents the snapshot from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {}
+ if delete is not None:
+ data.update({"delete": delete})
+
+ response = self._client.request(
+ url=f"/images/{image.id}/actions/change_protection",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/domain.py
new file mode 100644
index 000000000..9a58a3cc2
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/images/domain.py
@@ -0,0 +1,134 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain, DomainIdentityMixin
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from ..servers import BoundServer, Server
+ from .client import BoundImage
+
+
+class Image(BaseDomain, DomainIdentityMixin):
+ """Image Domain
+
+ :param id: int
+ ID of the image
+ :param type: str
+ Type of the image Choices: `system`, `snapshot`, `backup`, `app`
+ :param status: str
+ Whether the image can be used or if it’s still being created Choices: `available`, `creating`
+ :param name: str, None
+ Unique identifier of the image. This value is only set for system images.
+ :param description: str
+ Description of the image
+ :param image_size: number, None
+ Size of the image file in our storage in GB. For snapshot images this is the value relevant for calculating costs for the image.
+ :param disk_size: number
+ Size of the disk contained in the image in GB.
+ :param created: datetime
+ Point in time when the image was created
+ :param created_from: :class:`BoundServer <hcloud.servers.client.BoundServer>`, None
+ Information about the server the image was created from
+ :param bound_to: :class:`BoundServer <hcloud.servers.client.BoundServer>`, None
+ ID of server the image is bound to. Only set for images of type `backup`.
+ :param os_flavor: str
+ Flavor of operating system contained in the image Choices: `ubuntu`, `centos`, `debian`, `fedora`, `unknown`
+ :param os_version: str, None
+ Operating system version
+ :param architecture: str
+ CPU Architecture that the image is compatible with. Choices: `x86`, `arm`
+ :param rapid_deploy: bool
+ Indicates that rapid deploy of the image is available
+ :param protection: dict
+ Protection configuration for the image
+ :param deprecated: datetime, None
+ Point in time when the image is considered to be deprecated (in ISO-8601 format)
+ :param labels: Dict
+ User-defined labels (key-value pairs)
+ """
+
+ __slots__ = (
+ "id",
+ "name",
+ "type",
+ "description",
+ "image_size",
+ "disk_size",
+ "bound_to",
+ "os_flavor",
+ "os_version",
+ "architecture",
+ "rapid_deploy",
+ "created_from",
+ "status",
+ "protection",
+ "labels",
+ "created",
+ "deprecated",
+ )
+
+ # pylint: disable=too-many-locals
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ type: str | None = None,
+ created: str | None = None,
+ description: str | None = None,
+ image_size: int | None = None,
+ disk_size: int | None = None,
+ deprecated: str | None = None,
+ bound_to: Server | BoundServer | None = None,
+ os_flavor: str | None = None,
+ os_version: str | None = None,
+ architecture: str | None = None,
+ rapid_deploy: bool | None = None,
+ created_from: Server | BoundServer | None = None,
+ protection: dict | None = None,
+ labels: dict[str, str] | None = None,
+ status: str | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.type = type
+ self.created = isoparse(created) if created else None
+ self.description = description
+ self.image_size = image_size
+ self.disk_size = disk_size
+ self.deprecated = isoparse(deprecated) if deprecated else None
+ self.bound_to = bound_to
+ self.os_flavor = os_flavor
+ self.os_version = os_version
+ self.architecture = architecture
+ self.rapid_deploy = rapid_deploy
+ self.created_from = created_from
+ self.protection = protection
+ self.labels = labels
+ self.status = status
+
+
+class CreateImageResponse(BaseDomain):
+ """Create Image Response Domain
+
+ :param image: :class:`BoundImage <hcloud.images.client.BoundImage>`
+ The Image which was created
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ The Action which shows the progress of the Floating IP Creation
+ """
+
+ __slots__ = ("action", "image")
+
+ def __init__(
+ self,
+ action: BoundAction,
+ image: BoundImage,
+ ):
+ self.action = action
+ self.image = image
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/__init__.py
new file mode 100644
index 000000000..0d5e38fae
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/__init__.py
@@ -0,0 +1,4 @@
+from __future__ import annotations
+
+from .client import BoundIso, IsosClient, IsosPageResult # noqa: F401
+from .domain import Iso # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/client.py
new file mode 100644
index 000000000..cc46af7f9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/client.py
@@ -0,0 +1,128 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+from warnings import warn
+
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import Iso
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundIso(BoundModelBase, Iso):
+ _client: IsosClient
+
+ model = Iso
+
+
+class IsosPageResult(NamedTuple):
+ isos: list[BoundIso]
+ meta: Meta | None
+
+
+class IsosClient(ClientEntityBase):
+ _client: Client
+
+ def get_by_id(self, id: int) -> BoundIso:
+ """Get a specific ISO by its id
+
+ :param id: int
+ :return: :class:`BoundIso <hcloud.isos.client.BoundIso>`
+ """
+ response = self._client.request(url=f"/isos/{id}", method="GET")
+ return BoundIso(self, response["iso"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ architecture: list[str] | None = None,
+ include_wildcard_architecture: bool | None = None,
+ include_architecture_wildcard: bool | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> IsosPageResult:
+ """Get a list of ISOs
+
+ :param name: str (optional)
+ Can be used to filter ISOs by their name.
+ :param architecture: List[str] (optional)
+ Can be used to filter ISOs by their architecture. Choices: x86 arm
+ :param include_wildcard_architecture: bool (optional)
+ Deprecated, please use `include_architecture_wildcard` instead.
+ :param include_architecture_wildcard: bool (optional)
+ Custom ISOs do not have an architecture set. You must also set this flag to True if you are filtering by
+ architecture and also want custom ISOs.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundIso <hcloud.isos.client.BoundIso>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+
+ if include_wildcard_architecture is not None:
+ warn(
+ "The `include_wildcard_architecture` argument is deprecated, please use the `include_architecture_wildcard` argument instead.",
+ DeprecationWarning,
+ )
+ include_architecture_wildcard = include_wildcard_architecture
+
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if architecture is not None:
+ params["architecture"] = architecture
+ if include_architecture_wildcard is not None:
+ params["include_architecture_wildcard"] = include_architecture_wildcard
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(url="/isos", method="GET", params=params)
+ isos = [BoundIso(self, iso_data) for iso_data in response["isos"]]
+ return IsosPageResult(isos, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ name: str | None = None,
+ architecture: list[str] | None = None,
+ include_wildcard_architecture: bool | None = None,
+ include_architecture_wildcard: bool | None = None,
+ ) -> list[BoundIso]:
+ """Get all ISOs
+
+ :param name: str (optional)
+ Can be used to filter ISOs by their name.
+ :param architecture: List[str] (optional)
+ Can be used to filter ISOs by their architecture. Choices: x86 arm
+ :param include_wildcard_architecture: bool (optional)
+ Deprecated, please use `include_architecture_wildcard` instead.
+ :param include_architecture_wildcard: bool (optional)
+ Custom ISOs do not have an architecture set. You must also set this flag to True if you are filtering by
+ architecture and also want custom ISOs.
+ :return: List[:class:`BoundIso <hcloud.isos.client.BoundIso>`]
+ """
+
+ if include_wildcard_architecture is not None:
+ warn(
+ "The `include_wildcard_architecture` argument is deprecated, please use the `include_architecture_wildcard` argument instead.",
+ DeprecationWarning,
+ )
+ include_architecture_wildcard = include_wildcard_architecture
+
+ return self._iter_pages(
+ self.get_list,
+ name=name,
+ architecture=architecture,
+ include_architecture_wildcard=include_architecture_wildcard,
+ )
+
+ def get_by_name(self, name: str) -> BoundIso | None:
+ """Get iso by name
+
+ :param name: str
+ Used to get iso by name.
+ :return: :class:`BoundIso <hcloud.isos.client.BoundIso>`
+ """
+ return self._get_first_by(name=name)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/domain.py
new file mode 100644
index 000000000..b2f4d30cf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/isos/domain.py
@@ -0,0 +1,69 @@
+from __future__ import annotations
+
+from datetime import datetime
+from warnings import warn
+
+from ..core import BaseDomain, DomainIdentityMixin
+from ..deprecation import DeprecationInfo
+
+
+class Iso(BaseDomain, DomainIdentityMixin):
+ """Iso Domain
+
+ :param id: int
+ ID of the ISO
+ :param name: str, None
+ Unique identifier of the ISO. Only set for public ISOs
+ :param description: str
+ Description of the ISO
+ :param type: str
+ Type of the ISO. Choices: `public`, `private`
+ :param architecture: str, None
+ CPU Architecture that the ISO is compatible with. None means that the compatibility is unknown. Choices: `x86`, `arm`
+ :param deprecated: datetime, None
+ ISO 8601 timestamp of deprecation, None if ISO is still available. After the deprecation time it will no longer be possible to attach the ISO to servers. This field is deprecated. Use `deprecation` instead.
+ :param deprecation: :class:`DeprecationInfo <hcloud.deprecation.domain.DeprecationInfo>`, None
+ Describes if, when & how the resources was deprecated. If this field is set to None the resource is not
+ deprecated. If it has a value, it is considered deprecated.
+ """
+
+ __slots__ = (
+ "id",
+ "name",
+ "type",
+ "architecture",
+ "description",
+ "deprecation",
+ )
+
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ type: str | None = None,
+ architecture: str | None = None,
+ description: str | None = None,
+ deprecated: str | None = None, # pylint: disable=unused-argument
+ deprecation: dict | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.type = type
+ self.architecture = architecture
+ self.description = description
+ self.deprecation = (
+ DeprecationInfo.from_dict(deprecation) if deprecation is not None else None
+ )
+
+ @property
+ def deprecated(self) -> datetime | None:
+ """
+ ISO 8601 timestamp of deprecation, None if ISO is still available.
+ """
+ warn(
+ "The `deprecated` field is deprecated, please use the `deprecation` field instead.",
+ DeprecationWarning,
+ )
+ if self.deprecation is None:
+ return None
+ return self.deprecation.unavailable_after
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/__init__.py
new file mode 100644
index 000000000..fa1dc33c7
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/__init__.py
@@ -0,0 +1,8 @@
+from __future__ import annotations
+
+from .client import ( # noqa: F401
+ BoundLoadBalancerType,
+ LoadBalancerTypesClient,
+ LoadBalancerTypesPageResult,
+)
+from .domain import LoadBalancerType # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/client.py
new file mode 100644
index 000000000..9a83dc707
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/client.py
@@ -0,0 +1,89 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import LoadBalancerType
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundLoadBalancerType(BoundModelBase, LoadBalancerType):
+ _client: LoadBalancerTypesClient
+
+ model = LoadBalancerType
+
+
+class LoadBalancerTypesPageResult(NamedTuple):
+ load_balancer_types: list[BoundLoadBalancerType]
+ meta: Meta | None
+
+
+class LoadBalancerTypesClient(ClientEntityBase):
+ _client: Client
+
+ def get_by_id(self, id: int) -> BoundLoadBalancerType:
+ """Returns a specific Load Balancer Type.
+
+ :param id: int
+ :return: :class:`BoundLoadBalancerType <hcloud.load_balancer_type.client.BoundLoadBalancerType>`
+ """
+ response = self._client.request(
+ url=f"/load_balancer_types/{id}",
+ method="GET",
+ )
+ return BoundLoadBalancerType(self, response["load_balancer_type"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> LoadBalancerTypesPageResult:
+ """Get a list of Load Balancer types
+
+ :param name: str (optional)
+ Can be used to filter Load Balancer type by their name.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url="/load_balancer_types", method="GET", params=params
+ )
+ load_balancer_types = [
+ BoundLoadBalancerType(self, load_balancer_type_data)
+ for load_balancer_type_data in response["load_balancer_types"]
+ ]
+ return LoadBalancerTypesPageResult(
+ load_balancer_types, Meta.parse_meta(response)
+ )
+
+ def get_all(self, name: str | None = None) -> list[BoundLoadBalancerType]:
+ """Get all Load Balancer types
+
+ :param name: str (optional)
+ Can be used to filter Load Balancer type by their name.
+ :return: List[:class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>`]
+ """
+ return self._iter_pages(self.get_list, name=name)
+
+ def get_by_name(self, name: str) -> BoundLoadBalancerType | None:
+ """Get Load Balancer type by name
+
+ :param name: str
+ Used to get Load Balancer type by name.
+ :return: :class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>`
+ """
+ return self._get_first_by(name=name)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py
new file mode 100644
index 000000000..35719dba3
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py
@@ -0,0 +1,57 @@
+from __future__ import annotations
+
+from ..core import BaseDomain, DomainIdentityMixin
+
+
+class LoadBalancerType(BaseDomain, DomainIdentityMixin):
+ """LoadBalancerType Domain
+
+ :param id: int
+ ID of the Load Balancer type
+ :param name: str
+ Name of the Load Balancer type
+ :param description: str
+ Description of the Load Balancer type
+ :param max_connections: int
+ Max amount of connections the Load Balancer can handle
+ :param max_services: int
+ Max amount of services the Load Balancer can handle
+ :param max_targets: int
+ Max amount of targets the Load Balancer can handle
+ :param max_assigned_certificates: int
+ Max amount of certificates the Load Balancer can serve
+ :param prices: Dict
+ Prices in different locations
+
+ """
+
+ __slots__ = (
+ "id",
+ "name",
+ "description",
+ "max_connections",
+ "max_services",
+ "max_targets",
+ "max_assigned_certificates",
+ "prices",
+ )
+
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ description: str | None = None,
+ max_connections: int | None = None,
+ max_services: int | None = None,
+ max_targets: int | None = None,
+ max_assigned_certificates: int | None = None,
+ prices: dict | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.description = description
+ self.max_connections = max_connections
+ self.max_services = max_services
+ self.max_targets = max_targets
+ self.max_assigned_certificates = max_assigned_certificates
+ self.prices = prices
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/__init__.py
new file mode 100644
index 000000000..4bfd79940
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/__init__.py
@@ -0,0 +1,25 @@
+from __future__ import annotations
+
+from .client import ( # noqa: F401
+ BoundLoadBalancer,
+ LoadBalancersClient,
+ LoadBalancersPageResult,
+)
+from .domain import ( # noqa: F401
+ CreateLoadBalancerResponse,
+ GetMetricsResponse,
+ IPv4Address,
+ IPv6Network,
+ LoadBalancer,
+ LoadBalancerAlgorithm,
+ LoadBalancerHealtCheckHttp,
+ LoadBalancerHealthCheck,
+ LoadBalancerService,
+ LoadBalancerServiceHttp,
+ LoadBalancerTarget,
+ LoadBalancerTargetHealthStatus,
+ LoadBalancerTargetIP,
+ LoadBalancerTargetLabelSelector,
+ PrivateNet,
+ PublicNetwork,
+)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/client.py
new file mode 100644
index 000000000..492121354
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/client.py
@@ -0,0 +1,939 @@
+from __future__ import annotations
+
+from datetime import datetime
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
+from ..certificates import BoundCertificate
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from ..load_balancer_types import BoundLoadBalancerType
+from ..locations import BoundLocation
+from ..metrics import Metrics
+from ..networks import BoundNetwork
+from ..servers import BoundServer
+from .domain import (
+ CreateLoadBalancerResponse,
+ GetMetricsResponse,
+ IPv4Address,
+ IPv6Network,
+ LoadBalancer,
+ LoadBalancerAlgorithm,
+ LoadBalancerHealtCheckHttp,
+ LoadBalancerHealthCheck,
+ LoadBalancerService,
+ LoadBalancerServiceHttp,
+ LoadBalancerTarget,
+ LoadBalancerTargetHealthStatus,
+ LoadBalancerTargetIP,
+ LoadBalancerTargetLabelSelector,
+ MetricsType,
+ PrivateNet,
+ PublicNetwork,
+)
+
+if TYPE_CHECKING:
+ from .._client import Client
+ from ..load_balancer_types import LoadBalancerType
+ from ..locations import Location
+ from ..networks import Network
+
+
+class BoundLoadBalancer(BoundModelBase, LoadBalancer):
+ _client: LoadBalancersClient
+
+ model = LoadBalancer
+
+ # pylint: disable=too-many-branches,too-many-locals
+ def __init__(self, client: LoadBalancersClient, data: dict, complete: bool = True):
+ algorithm = data.get("algorithm")
+ if algorithm:
+ data["algorithm"] = LoadBalancerAlgorithm(type=algorithm["type"])
+
+ public_net = data.get("public_net")
+ if public_net:
+ ipv4_address = IPv4Address.from_dict(public_net["ipv4"])
+ ipv6_network = IPv6Network.from_dict(public_net["ipv6"])
+ data["public_net"] = PublicNetwork(
+ ipv4=ipv4_address, ipv6=ipv6_network, enabled=public_net["enabled"]
+ )
+
+ private_nets = data.get("private_net")
+ if private_nets:
+ private_nets = [
+ PrivateNet(
+ network=BoundNetwork(
+ client._client.networks,
+ {"id": private_net["network"]},
+ complete=False,
+ ),
+ ip=private_net["ip"],
+ )
+ for private_net in private_nets
+ ]
+ data["private_net"] = private_nets
+
+ targets = data.get("targets")
+ if targets:
+ tmp_targets = []
+ for target in targets:
+ tmp_target = LoadBalancerTarget(type=target["type"])
+ if target["type"] == "server":
+ tmp_target.server = BoundServer(
+ client._client.servers, data=target["server"], complete=False
+ )
+ tmp_target.use_private_ip = target["use_private_ip"]
+ elif target["type"] == "label_selector":
+ tmp_target.label_selector = LoadBalancerTargetLabelSelector(
+ selector=target["label_selector"]["selector"]
+ )
+ tmp_target.use_private_ip = target["use_private_ip"]
+ elif target["type"] == "ip":
+ tmp_target.ip = LoadBalancerTargetIP(ip=target["ip"]["ip"])
+
+ target_health_status = target.get("health_status")
+ if target_health_status is not None:
+ tmp_target.health_status = [
+ LoadBalancerTargetHealthStatus(
+ listen_port=target_health_status_item["listen_port"],
+ status=target_health_status_item["status"],
+ )
+ for target_health_status_item in target_health_status
+ ]
+
+ tmp_targets.append(tmp_target)
+ data["targets"] = tmp_targets
+
+ services = data.get("services")
+ if services:
+ tmp_services = []
+ for service in services:
+ tmp_service = LoadBalancerService(
+ protocol=service["protocol"],
+ listen_port=service["listen_port"],
+ destination_port=service["destination_port"],
+ proxyprotocol=service["proxyprotocol"],
+ )
+ if service["protocol"] != "tcp":
+ tmp_service.http = LoadBalancerServiceHttp(
+ sticky_sessions=service["http"]["sticky_sessions"],
+ redirect_http=service["http"]["redirect_http"],
+ cookie_name=service["http"]["cookie_name"],
+ cookie_lifetime=service["http"]["cookie_lifetime"],
+ )
+ tmp_service.http.certificates = [
+ BoundCertificate(
+ client._client.certificates,
+ {"id": certificate},
+ complete=False,
+ )
+ for certificate in service["http"]["certificates"]
+ ]
+
+ tmp_service.health_check = LoadBalancerHealthCheck(
+ protocol=service["health_check"]["protocol"],
+ port=service["health_check"]["port"],
+ interval=service["health_check"]["interval"],
+ retries=service["health_check"]["retries"],
+ timeout=service["health_check"]["timeout"],
+ )
+ if tmp_service.health_check.protocol != "tcp":
+ tmp_service.health_check.http = LoadBalancerHealtCheckHttp(
+ domain=service["health_check"]["http"]["domain"],
+ path=service["health_check"]["http"]["path"],
+ response=service["health_check"]["http"]["response"],
+ tls=service["health_check"]["http"]["tls"],
+ status_codes=service["health_check"]["http"]["status_codes"],
+ )
+ tmp_services.append(tmp_service)
+ data["services"] = tmp_services
+
+ load_balancer_type = data.get("load_balancer_type")
+ if load_balancer_type is not None:
+ data["load_balancer_type"] = BoundLoadBalancerType(
+ client._client.load_balancer_types, load_balancer_type
+ )
+
+ location = data.get("location")
+ if location is not None:
+ data["location"] = BoundLocation(client._client.locations, location)
+
+ super().__init__(client, data, complete)
+
+ def update(
+ self,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundLoadBalancer:
+ """Updates a Load Balancer. You can update a Load Balancers name and a Load Balancers labels.
+
+ :param name: str (optional)
+ New name to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
+ """
+ return self._client.update(self, name, labels)
+
+ def delete(self) -> bool:
+ """Deletes a Load Balancer.
+
+ :return: boolean
+ """
+ return self._client.delete(self)
+
+ def get_metrics(
+ self,
+ type: MetricsType,
+ start: datetime | str,
+ end: datetime | str,
+ step: float | None = None,
+ ) -> GetMetricsResponse:
+ """Get Metrics for a LoadBalancer.
+
+ :param type: Type of metrics to get.
+ :param start: Start of period to get Metrics for (in ISO-8601 format).
+ :param end: End of period to get Metrics for (in ISO-8601 format).
+ :param step: Resolution of results in seconds.
+ """
+ return self._client.get_metrics(
+ self,
+ type=type,
+ start=start,
+ end=end,
+ step=step,
+ )
+
+ def get_actions_list(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a Load Balancer.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ return self._client.get_actions_list(self, status, sort, page, per_page)
+
+ def get_actions(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a Load Balancer.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.get_actions(self, status, sort)
+
+ def add_service(self, service: LoadBalancerService) -> BoundAction:
+ """Adds a service to a Load Balancer.
+
+ :param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
+ The LoadBalancerService you want to add to the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.add_service(self, service=service)
+
+ def update_service(self, service: LoadBalancerService) -> BoundAction:
+ """Updates a service of an Load Balancer.
+
+ :param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
+ The LoadBalancerService you want to update
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.update_service(self, service=service)
+
+ def delete_service(self, service: LoadBalancerService) -> BoundAction:
+ """Deletes a service from a Load Balancer.
+
+ :param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
+ The LoadBalancerService you want to delete from the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.delete_service(self, service)
+
+ def add_target(self, target: LoadBalancerTarget) -> BoundAction:
+ """Adds a target to a Load Balancer.
+
+ :param target: :class:`LoadBalancerTarget <hcloud.load_balancers.domain.LoadBalancerTarget>`
+ The LoadBalancerTarget you want to add to the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.add_target(self, target)
+
+ def remove_target(self, target: LoadBalancerTarget) -> BoundAction:
+ """Removes a target from a Load Balancer.
+
+ :param target: :class:`LoadBalancerTarget <hcloud.load_balancers.domain.LoadBalancerTarget>`
+ The LoadBalancerTarget you want to remove from the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.remove_target(self, target)
+
+ def change_algorithm(self, algorithm: LoadBalancerAlgorithm) -> BoundAction:
+ """Changes the algorithm used by the Load Balancer
+
+ :param algorithm: :class:`LoadBalancerAlgorithm <hcloud.load_balancers.domain.LoadBalancerAlgorithm>`
+ The LoadBalancerAlgorithm you want to use
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_algorithm(self, algorithm)
+
+ def change_dns_ptr(self, ip: str, dns_ptr: str) -> BoundAction:
+ """Changes the hostname that will appear when getting the hostname belonging to the public IPs (IPv4 and IPv6) of this Load Balancer.
+
+ :param ip: str
+ The IP address for which to set the reverse DNS entry
+ :param dns_ptr: str
+ Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_dns_ptr(self, ip, dns_ptr)
+
+ def change_protection(self, delete: bool) -> BoundAction:
+ """Changes the protection configuration of a Load Balancer.
+
+ :param delete: boolean
+ If True, prevents the Load Balancer from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_protection(self, delete)
+
+ def attach_to_network(
+ self,
+ network: Network | BoundNetwork,
+ ip: str | None = None,
+ ) -> BoundAction:
+ """Attaches a Load Balancer to a Network
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param ip: str
+ IP to request to be assigned to this Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.attach_to_network(self, network, ip)
+
+ def detach_from_network(self, network: Network | BoundNetwork) -> BoundAction:
+ """Detaches a Load Balancer from a Network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.detach_from_network(self, network)
+
+ def enable_public_interface(self) -> BoundAction:
+ """Enables the public interface of a Load Balancer.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.enable_public_interface(self)
+
+ def disable_public_interface(self) -> BoundAction:
+ """Disables the public interface of a Load Balancer.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.disable_public_interface(self)
+
+ def change_type(
+ self,
+ load_balancer_type: LoadBalancerType | BoundLoadBalancerType,
+ ) -> BoundAction:
+ """Changes the type of a Load Balancer.
+
+ :param load_balancer_type: :class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>` or :class:`LoadBalancerType <hcloud.load_balancer_types.domain.LoadBalancerType>`
+ Load Balancer type the Load Balancer should migrate to
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_type(self, load_balancer_type)
+
+
+class LoadBalancersPageResult(NamedTuple):
+ load_balancers: list[BoundLoadBalancer]
+ meta: Meta | None
+
+
+class LoadBalancersClient(ClientEntityBase):
+ _client: Client
+
+ actions: ResourceActionsClient
+ """Load Balancers scoped actions client
+
+ :type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
+ """
+
+ def __init__(self, client: Client):
+ super().__init__(client)
+ self.actions = ResourceActionsClient(client, "/load_balancers")
+
+ def get_by_id(self, id: int) -> BoundLoadBalancer:
+ """Get a specific Load Balancer
+
+ :param id: int
+ :return: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
+ """
+ response = self._client.request(
+ url=f"/load_balancers/{id}",
+ method="GET",
+ )
+ return BoundLoadBalancer(self, response["load_balancer"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> LoadBalancersPageResult:
+ """Get a list of Load Balancers from this account
+
+ :param name: str (optional)
+ Can be used to filter Load Balancers by their name.
+ :param label_selector: str (optional)
+ Can be used to filter Load Balancers by labels. The response will only contain Load Balancers matching the label selector.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url="/load_balancers", method="GET", params=params
+ )
+
+ load_balancers = [
+ BoundLoadBalancer(self, load_balancer_data)
+ for load_balancer_data in response["load_balancers"]
+ ]
+ return LoadBalancersPageResult(load_balancers, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ ) -> list[BoundLoadBalancer]:
+ """Get all Load Balancers from this account
+
+ :param name: str (optional)
+ Can be used to filter Load Balancers by their name.
+ :param label_selector: str (optional)
+ Can be used to filter Load Balancers by labels. The response will only contain Load Balancers matching the label selector.
+ :return: List[:class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`]
+ """
+ return self._iter_pages(self.get_list, name=name, label_selector=label_selector)
+
+ def get_by_name(self, name: str) -> BoundLoadBalancer | None:
+ """Get Load Balancer by name
+
+ :param name: str
+ Used to get Load Balancer by name.
+ :return: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
+ """
+ return self._get_first_by(name=name)
+
+ def create(
+ self,
+ name: str,
+ load_balancer_type: LoadBalancerType | BoundLoadBalancerType,
+ algorithm: LoadBalancerAlgorithm | None = None,
+ services: list[LoadBalancerService] | None = None,
+ targets: list[LoadBalancerTarget] | None = None,
+ labels: dict[str, str] | None = None,
+ location: Location | BoundLocation | None = None,
+ network_zone: str | None = None,
+ public_interface: bool | None = None,
+ network: Network | BoundNetwork | None = None,
+ ) -> CreateLoadBalancerResponse:
+ """Creates a Load Balancer .
+
+ :param name: str
+ Name of the Load Balancer
+ :param load_balancer_type: LoadBalancerType
+ Type of the Load Balancer
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param location: Location
+ Location of the Load Balancer
+ :param network_zone: str
+ Network Zone of the Load Balancer
+ :param algorithm: LoadBalancerAlgorithm (optional)
+ The algorithm the Load Balancer is currently using
+ :param services: LoadBalancerService
+ The services the Load Balancer is currently serving
+ :param targets: LoadBalancerTarget
+ The targets the Load Balancer is currently serving
+ :param public_interface: bool
+ Enable or disable the public interface of the Load Balancer
+ :param network: Network
+ Adds the Load Balancer to a Network
+ :return: :class:`CreateLoadBalancerResponse <hcloud.load_balancers.domain.CreateLoadBalancerResponse>`
+ """
+ data: dict[str, Any] = {
+ "name": name,
+ "load_balancer_type": load_balancer_type.id_or_name,
+ }
+ if network is not None:
+ data["network"] = network.id
+ if public_interface is not None:
+ data["public_interface"] = public_interface
+ if labels is not None:
+ data["labels"] = labels
+ if algorithm is not None:
+ data["algorithm"] = {"type": algorithm.type}
+ if services is not None:
+ data["services"] = [service.to_payload() for service in services]
+ if targets is not None:
+ data["targets"] = [target.to_payload() for target in targets]
+ if network_zone is not None:
+ data["network_zone"] = network_zone
+ if location is not None:
+ data["location"] = location.id_or_name
+
+ response = self._client.request(url="/load_balancers", method="POST", json=data)
+
+ return CreateLoadBalancerResponse(
+ load_balancer=BoundLoadBalancer(self, response["load_balancer"]),
+ action=BoundAction(self._client.actions, response["action"]),
+ )
+
+ def update(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundLoadBalancer:
+ """Updates a LoadBalancer. You can update a LoadBalancer’s name and a LoadBalancer’s labels.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param name: str (optional)
+ New name to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
+ """
+ data: dict[str, Any] = {}
+ if name is not None:
+ data.update({"name": name})
+ if labels is not None:
+ data.update({"labels": labels})
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundLoadBalancer(self, response["load_balancer"])
+
+ def delete(self, load_balancer: LoadBalancer | BoundLoadBalancer) -> bool:
+ """Deletes a Load Balancer.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :return: boolean
+ """
+ self._client.request(
+ url=f"/load_balancers/{load_balancer.id}",
+ method="DELETE",
+ )
+ return True
+
+ def get_metrics(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ type: MetricsType | list[MetricsType],
+ start: datetime | str,
+ end: datetime | str,
+ step: float | None = None,
+ ) -> GetMetricsResponse:
+ """Get Metrics for a LoadBalancer.
+
+ :param load_balancer: The Load Balancer to get the metrics for.
+ :param type: Type of metrics to get.
+ :param start: Start of period to get Metrics for (in ISO-8601 format).
+ :param end: End of period to get Metrics for (in ISO-8601 format).
+ :param step: Resolution of results in seconds.
+ """
+ if not isinstance(type, list):
+ type = [type]
+ if isinstance(start, str):
+ start = isoparse(start)
+ if isinstance(end, str):
+ end = isoparse(end)
+
+ params: dict[str, Any] = {
+ "type": ",".join(type),
+ "start": start.isoformat(),
+ "end": end.isoformat(),
+ }
+ if step is not None:
+ params["step"] = step
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/metrics",
+ method="GET",
+ params=params,
+ )
+ return GetMetricsResponse(
+ metrics=Metrics(**response["metrics"]),
+ )
+
+ def get_actions_list(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a Load Balancer.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if status is not None:
+ params["status"] = status
+ if sort is not None:
+ params["sort"] = sort
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions",
+ method="GET",
+ params=params,
+ )
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+ return ActionsPageResult(actions, Meta.parse_meta(response))
+
+ def get_actions(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a Load Balancer.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._iter_pages(
+ self.get_actions_list,
+ load_balancer,
+ status=status,
+ sort=sort,
+ )
+
+ def add_service(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ service: LoadBalancerService,
+ ) -> BoundAction:
+ """Adds a service to a Load Balancer.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
+ The LoadBalancerService you want to add to the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = service.to_payload()
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/add_service",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def update_service(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ service: LoadBalancerService,
+ ) -> BoundAction:
+ """Updates a service of an Load Balancer.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
+ The LoadBalancerService with updated values within for the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = service.to_payload()
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/update_service",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def delete_service(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ service: LoadBalancerService,
+ ) -> BoundAction:
+ """Deletes a service from a Load Balancer.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
+ The LoadBalancerService you want to delete from the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"listen_port": service.listen_port}
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/delete_service",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def add_target(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ target: LoadBalancerTarget,
+ ) -> BoundAction:
+ """Adds a target to a Load Balancer.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param target: :class:`LoadBalancerTarget <hcloud.load_balancers.domain.LoadBalancerTarget>`
+ The LoadBalancerTarget you want to add to the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = target.to_payload()
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/add_target",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def remove_target(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ target: LoadBalancerTarget,
+ ) -> BoundAction:
+ """Removes a target from a Load Balancer.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param target: :class:`LoadBalancerTarget <hcloud.load_balancers.domain.LoadBalancerTarget>`
+ The LoadBalancerTarget you want to remove from the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = target.to_payload()
+ # Do not send use_private_ip on remove_target
+ data.pop("use_private_ip", None)
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/remove_target",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_algorithm(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ algorithm: LoadBalancerAlgorithm,
+ ) -> BoundAction:
+ """Changes the algorithm used by the Load Balancer
+
+ :param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param algorithm: :class:`LoadBalancerAlgorithm <hcloud.load_balancers.domain.LoadBalancerAlgorithm>`
+ The LoadBalancerSubnet you want to add to the Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"type": algorithm.type}
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/change_algorithm",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_dns_ptr(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ ip: str,
+ dns_ptr: str,
+ ) -> BoundAction:
+ """Changes the hostname that will appear when getting the hostname belonging to the public IPs (IPv4 and IPv6) of this Load Balancer.
+
+ :param ip: str
+ The IP address for which to set the reverse DNS entry
+ :param dns_ptr: str
+ Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/change_dns_ptr",
+ method="POST",
+ json={"ip": ip, "dns_ptr": dns_ptr},
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_protection(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ delete: bool | None = None,
+ ) -> BoundAction:
+ """Changes the protection configuration of a Load Balancer.
+
+ :param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param delete: boolean
+ If True, prevents the Load Balancer from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {}
+ if delete is not None:
+ data.update({"delete": delete})
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/change_protection",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def attach_to_network(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ network: Network | BoundNetwork,
+ ip: str | None = None,
+ ) -> BoundAction:
+ """Attach a Load Balancer to a Network.
+
+ :param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param ip: str
+ IP to request to be assigned to this Load Balancer
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"network": network.id}
+ if ip is not None:
+ data.update({"ip": ip})
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/attach_to_network",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def detach_from_network(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ network: Network | BoundNetwork,
+ ) -> BoundAction:
+ """Detaches a Load Balancer from a Network.
+
+ :param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"network": network.id}
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/detach_from_network",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def enable_public_interface(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ ) -> BoundAction:
+ """Enables the public interface of a Load Balancer.
+
+ :param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/enable_public_interface",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def disable_public_interface(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ ) -> BoundAction:
+ """Disables the public interface of a Load Balancer.
+
+ :param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/disable_public_interface",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_type(
+ self,
+ load_balancer: LoadBalancer | BoundLoadBalancer,
+ load_balancer_type: LoadBalancerType | BoundLoadBalancerType,
+ ) -> BoundAction:
+ """Changes the type of a Load Balancer.
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
+ :param load_balancer_type: :class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>` or :class:`LoadBalancerType <hcloud.load_balancer_types.domain.LoadBalancerType>`
+ Load Balancer type the Load Balancer should migrate to
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"load_balancer_type": load_balancer_type.id_or_name}
+ response = self._client.request(
+ url=f"/load_balancers/{load_balancer.id}/actions/change_type",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/domain.py
new file mode 100644
index 000000000..6d6f0700a
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/load_balancers/domain.py
@@ -0,0 +1,537 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, Literal
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from ..certificates import BoundCertificate
+ from ..load_balancer_types import BoundLoadBalancerType
+ from ..locations import BoundLocation
+ from ..metrics import Metrics
+ from ..networks import BoundNetwork
+ from ..servers import BoundServer
+ from .client import BoundLoadBalancer
+
+
+class LoadBalancer(BaseDomain):
+ """LoadBalancer Domain
+
+ :param id: int
+ ID of the Load Balancer
+ :param name: str
+ Name of the Load Balancer (must be unique per project)
+ :param created: datetime
+ Point in time when the Load Balancer was created
+ :param protection: dict
+ Protection configuration for the Load Balancer
+ :param labels: dict
+ User-defined labels (key-value pairs)
+ :param location: Location
+ Location of the Load Balancer
+ :param public_net: :class:`PublicNetwork <hcloud.load_balancers.domain.PublicNetwork>`
+ Public network information.
+ :param private_net: List[:class:`PrivateNet <hcloud.load_balancers.domain.PrivateNet`]
+ Private networks information.
+ :param algorithm: LoadBalancerAlgorithm
+ The algorithm the Load Balancer is currently using
+ :param services: List[LoadBalancerService]
+ The services the LoadBalancer is currently serving
+ :param targets: LoadBalancerTarget
+ The targets the LoadBalancer is currently serving
+ :param load_balancer_type: LoadBalancerType
+ The type of the Load Balancer
+ :param outgoing_traffic: int, None
+ Outbound Traffic for the current billing period in bytes
+ :param ingoing_traffic: int, None
+ Inbound Traffic for the current billing period in bytes
+ :param included_traffic: int
+ Free Traffic for the current billing period in bytes
+ """
+
+ __slots__ = (
+ "id",
+ "name",
+ "public_net",
+ "private_net",
+ "location",
+ "algorithm",
+ "services",
+ "load_balancer_type",
+ "protection",
+ "labels",
+ "targets",
+ "created",
+ "outgoing_traffic",
+ "ingoing_traffic",
+ "included_traffic",
+ )
+
+ # pylint: disable=too-many-locals
+ def __init__(
+ self,
+ id: int,
+ name: str | None = None,
+ public_net: PublicNetwork | None = None,
+ private_net: PrivateNet | None = None,
+ location: BoundLocation | None = None,
+ algorithm: LoadBalancerAlgorithm | None = None,
+ services: list[LoadBalancerService] | None = None,
+ load_balancer_type: BoundLoadBalancerType | None = None,
+ protection: dict | None = None,
+ labels: dict[str, str] | None = None,
+ targets: list[LoadBalancerTarget] | None = None,
+ created: str | None = None,
+ outgoing_traffic: int | None = None,
+ ingoing_traffic: int | None = None,
+ included_traffic: int | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.created = isoparse(created) if created else None
+ self.public_net = public_net
+ self.private_net = private_net
+ self.location = location
+ self.algorithm = algorithm
+ self.services = services
+ self.load_balancer_type = load_balancer_type
+ self.targets = targets
+ self.protection = protection
+ self.labels = labels
+ self.outgoing_traffic = outgoing_traffic
+ self.ingoing_traffic = ingoing_traffic
+ self.included_traffic = included_traffic
+
+
+class LoadBalancerService(BaseDomain):
+ """LoadBalancerService Domain
+
+ :param protocol: str
+ Protocol of the service Choices: tcp, http, https
+ :param listen_port: int
+ Required when protocol is tcp, must be unique per Load Balancer.
+ :param destination_port: int
+ Required when protocol is tcp
+ :param proxyprotocol: bool
+ Enable proxyprotocol
+ :param health_check: LoadBalancerHealthCheck
+ Configuration for health checks
+ :param http: LoadBalancerServiceHttp
+ Configuration for http/https protocols, required when protocol is http/https
+ """
+
+ def __init__(
+ self,
+ protocol: str | None = None,
+ listen_port: int | None = None,
+ destination_port: int | None = None,
+ proxyprotocol: bool | None = None,
+ health_check: LoadBalancerHealthCheck | None = None,
+ http: LoadBalancerServiceHttp | None = None,
+ ):
+ self.protocol = protocol
+ self.listen_port = listen_port
+ self.destination_port = destination_port
+ self.proxyprotocol = proxyprotocol
+ self.health_check = health_check
+ self.http = http
+
+ # pylint: disable=too-many-branches
+ def to_payload(self) -> dict[str, Any]:
+ """
+ Generates the request payload from this domain object.
+ """
+ payload: dict[str, Any] = {}
+
+ if self.protocol is not None:
+ payload["protocol"] = self.protocol
+ if self.listen_port is not None:
+ payload["listen_port"] = self.listen_port
+ if self.destination_port is not None:
+ payload["destination_port"] = self.destination_port
+ if self.proxyprotocol is not None:
+ payload["proxyprotocol"] = self.proxyprotocol
+
+ if self.http is not None:
+ http: dict[str, Any] = {}
+ if self.http.cookie_name is not None:
+ http["cookie_name"] = self.http.cookie_name
+ if self.http.cookie_lifetime is not None:
+ http["cookie_lifetime"] = self.http.cookie_lifetime
+ if self.http.redirect_http is not None:
+ http["redirect_http"] = self.http.redirect_http
+ if self.http.sticky_sessions is not None:
+ http["sticky_sessions"] = self.http.sticky_sessions
+
+ http["certificates"] = [
+ certificate.id for certificate in self.http.certificates or []
+ ]
+
+ payload["http"] = http
+
+ if self.health_check is not None:
+ health_check: dict[str, Any] = {
+ "protocol": self.health_check.protocol,
+ "port": self.health_check.port,
+ "interval": self.health_check.interval,
+ "timeout": self.health_check.timeout,
+ "retries": self.health_check.retries,
+ }
+ if self.health_check.protocol is not None:
+ health_check["protocol"] = self.health_check.protocol
+ if self.health_check.port is not None:
+ health_check["port"] = self.health_check.port
+ if self.health_check.interval is not None:
+ health_check["interval"] = self.health_check.interval
+ if self.health_check.timeout is not None:
+ health_check["timeout"] = self.health_check.timeout
+ if self.health_check.retries is not None:
+ health_check["retries"] = self.health_check.retries
+
+ if self.health_check.http is not None:
+ health_check_http: dict[str, Any] = {}
+ if self.health_check.http.domain is not None:
+ health_check_http["domain"] = self.health_check.http.domain
+ if self.health_check.http.path is not None:
+ health_check_http["path"] = self.health_check.http.path
+ if self.health_check.http.response is not None:
+ health_check_http["response"] = self.health_check.http.response
+ if self.health_check.http.status_codes is not None:
+ health_check_http[
+ "status_codes"
+ ] = self.health_check.http.status_codes
+ if self.health_check.http.tls is not None:
+ health_check_http["tls"] = self.health_check.http.tls
+
+ health_check["http"] = health_check_http
+
+ payload["health_check"] = health_check
+ return payload
+
+
+class LoadBalancerServiceHttp(BaseDomain):
+ """LoadBalancerServiceHttp Domain
+
+ :param cookie_name: str
+ Name of the cookie used for Session Stickness
+ :param cookie_lifetime: str
+ Lifetime of the cookie used for Session Stickness
+ :param certificates: list
+ IDs of the Certificates to use for TLS/SSL termination by the Load Balancer; empty for TLS/SSL passthrough or if protocol is "http"
+ :param redirect_http: bool
+ Redirect traffic from http port 80 to port 443
+ :param sticky_sessions: bool
+ Use sticky sessions. Only available if protocol is "http" or "https".
+ """
+
+ def __init__(
+ self,
+ cookie_name: str | None = None,
+ cookie_lifetime: str | None = None,
+ certificates: list[BoundCertificate] | None = None,
+ redirect_http: bool | None = None,
+ sticky_sessions: bool | None = None,
+ ):
+ self.cookie_name = cookie_name
+ self.cookie_lifetime = cookie_lifetime
+ self.certificates = certificates
+ self.redirect_http = redirect_http
+ self.sticky_sessions = sticky_sessions
+
+
+class LoadBalancerHealthCheck(BaseDomain):
+ """LoadBalancerHealthCheck Domain
+
+ :param protocol: str
+ Protocol of the service Choices: tcp, http, https
+ :param port: int
+ Port the healthcheck will be performed on
+ :param interval: int
+ Interval we trigger health check in
+ :param timeout: int
+ Timeout in sec after a try is assumed as timeout
+ :param retries: int
+ Retries we perform until we assume a target as unhealthy
+ :param http: LoadBalancerHealtCheckHttp
+ HTTP Config
+ """
+
+ def __init__(
+ self,
+ protocol: str | None = None,
+ port: int | None = None,
+ interval: int | None = None,
+ timeout: int | None = None,
+ retries: int | None = None,
+ http: LoadBalancerHealtCheckHttp | None = None,
+ ):
+ self.protocol = protocol
+ self.port = port
+ self.interval = interval
+ self.timeout = timeout
+ self.retries = retries
+ self.http = http
+
+
+class LoadBalancerHealtCheckHttp(BaseDomain):
+ """LoadBalancerHealtCheckHttp Domain
+
+ :param domain: str
+ Domain name to send in HTTP request. Can be null: In that case we will not send a domain name
+ :param path: str
+ HTTP Path send in Request
+ :param response: str
+ Optional HTTP response to receive in order to pass the health check
+ :param status_codes: list
+ List of HTTP status codes to receive in order to pass the health check
+ :param tls: bool
+ Type of health check
+ """
+
+ def __init__(
+ self,
+ domain: str | None = None,
+ path: str | None = None,
+ response: str | None = None,
+ status_codes: list | None = None,
+ tls: bool | None = None,
+ ):
+ self.domain = domain
+ self.path = path
+ self.response = response
+ self.status_codes = status_codes
+ self.tls = tls
+
+
+class LoadBalancerTarget(BaseDomain):
+ """LoadBalancerTarget Domain
+
+ :param type: str
+ Type of the resource, can be server or label_selector
+ :param server: Server
+ Target server
+ :param label_selector: LoadBalancerTargetLabelSelector
+ Target label selector
+ :param ip: LoadBalancerTargetIP
+ Target IP
+ :param use_private_ip: bool
+ use the private IP instead of primary public IP
+ :param health_status: list
+ List of health statuses of the services on this target. Only present for target types "server" and "ip".
+ """
+
+ def __init__(
+ self,
+ type: str | None = None,
+ server: BoundServer | None = None,
+ label_selector: LoadBalancerTargetLabelSelector | None = None,
+ ip: LoadBalancerTargetIP | None = None,
+ use_private_ip: bool | None = None,
+ health_status: list[LoadBalancerTargetHealthStatus] | None = None,
+ ):
+ self.type = type
+ self.server = server
+ self.label_selector = label_selector
+ self.ip = ip
+ self.use_private_ip = use_private_ip
+ self.health_status = health_status
+
+ def to_payload(self) -> dict[str, Any]:
+ """
+ Generates the request payload from this domain object.
+ """
+ payload: dict[str, Any] = {
+ "type": self.type,
+ }
+ if self.use_private_ip is not None:
+ payload["use_private_ip"] = self.use_private_ip
+
+ if self.type == "server":
+ if self.server is None:
+ raise ValueError(f"server is not defined in target {self!r}")
+ payload["server"] = {"id": self.server.id}
+
+ elif self.type == "label_selector":
+ if self.label_selector is None:
+ raise ValueError(f"label_selector is not defined in target {self!r}")
+ payload["label_selector"] = {"selector": self.label_selector.selector}
+
+ elif self.type == "ip":
+ if self.ip is None:
+ raise ValueError(f"ip is not defined in target {self!r}")
+ payload["ip"] = {"ip": self.ip.ip}
+
+ return payload
+
+
+class LoadBalancerTargetHealthStatus(BaseDomain):
+ """LoadBalancerTargetHealthStatus Domain
+
+ :param listen_port: Load Balancer Target listen port
+ :param status: Load Balancer Target status. Choices: healthy, unhealthy, unknown
+ """
+
+ def __init__(
+ self,
+ listen_port: int | None = None,
+ status: str | None = None,
+ ):
+ self.listen_port = listen_port
+ self.status = status
+
+
+class LoadBalancerTargetLabelSelector(BaseDomain):
+ """LoadBalancerTargetLabelSelector Domain
+
+ :param selector: str Target label selector
+ """
+
+ def __init__(self, selector: str | None = None):
+ self.selector = selector
+
+
+class LoadBalancerTargetIP(BaseDomain):
+ """LoadBalancerTargetIP Domain
+
+ :param ip: str Target IP
+ """
+
+ def __init__(self, ip: str | None = None):
+ self.ip = ip
+
+
+class LoadBalancerAlgorithm(BaseDomain):
+ """LoadBalancerAlgorithm Domain
+
+ :param type: str
+ Algorithm of the Load Balancer. Choices: round_robin, least_connections
+ """
+
+ def __init__(self, type: str | None = None):
+ self.type = type
+
+
+class PublicNetwork(BaseDomain):
+ """Public Network Domain
+
+ :param ipv4: :class:`IPv4Address <hcloud.load_balancers.domain.IPv4Address>`
+ :param ipv6: :class:`IPv6Network <hcloud.load_balancers.domain.IPv6Network>`
+ :param enabled: boolean
+ """
+
+ __slots__ = ("ipv4", "ipv6", "enabled")
+
+ def __init__(
+ self,
+ ipv4: IPv4Address,
+ ipv6: IPv6Network,
+ enabled: bool,
+ ):
+ self.ipv4 = ipv4
+ self.ipv6 = ipv6
+ self.enabled = enabled
+
+
+class IPv4Address(BaseDomain):
+ """IPv4 Address Domain
+
+ :param ip: str
+ The IPv4 Address
+ """
+
+ __slots__ = ("ip", "dns_ptr")
+
+ def __init__(
+ self,
+ ip: str,
+ dns_ptr: str,
+ ):
+ self.ip = ip
+ self.dns_ptr = dns_ptr
+
+
+class IPv6Network(BaseDomain):
+ """IPv6 Network Domain
+
+ :param ip: str
+ The IPv6 Network as CIDR Notation
+ """
+
+ __slots__ = ("ip", "dns_ptr")
+
+ def __init__(
+ self,
+ ip: str,
+ dns_ptr: str,
+ ):
+ self.ip = ip
+ self.dns_ptr = dns_ptr
+
+
+class PrivateNet(BaseDomain):
+ """PrivateNet Domain
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
+ The Network the LoadBalancer is attached to
+ :param ip: str
+ The main IP Address of the LoadBalancer in the Network
+ """
+
+ __slots__ = ("network", "ip")
+
+ def __init__(
+ self,
+ network: BoundNetwork,
+ ip: str,
+ ):
+ self.network = network
+ self.ip = ip
+
+
+class CreateLoadBalancerResponse(BaseDomain):
+ """Create Load Balancer Response Domain
+
+ :param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
+ The created Load Balancer
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ Shows the progress of the Load Balancer creation
+ """
+
+ __slots__ = ("load_balancer", "action")
+
+ def __init__(
+ self,
+ load_balancer: BoundLoadBalancer,
+ action: BoundAction,
+ ):
+ self.load_balancer = load_balancer
+ self.action = action
+
+
+MetricsType = Literal[
+ "open_connections",
+ "connections_per_second",
+ "requests_per_second",
+ "bandwidth",
+]
+
+
+class GetMetricsResponse(BaseDomain):
+ """Get a Load Balancer Metrics Response Domain
+
+ :param metrics: The Load Balancer metrics
+ """
+
+ __slots__ = ("metrics",)
+
+ def __init__(
+ self,
+ metrics: Metrics,
+ ):
+ self.metrics = metrics
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/__init__.py
new file mode 100644
index 000000000..1c23a5178
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/__init__.py
@@ -0,0 +1,4 @@
+from __future__ import annotations
+
+from .client import BoundLocation, LocationsClient, LocationsPageResult # noqa: F401
+from .domain import Location # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/client.py
new file mode 100644
index 000000000..047ad9d4b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/client.py
@@ -0,0 +1,82 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import Location
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundLocation(BoundModelBase, Location):
+ _client: LocationsClient
+
+ model = Location
+
+
+class LocationsPageResult(NamedTuple):
+ locations: list[BoundLocation]
+ meta: Meta | None
+
+
+class LocationsClient(ClientEntityBase):
+ _client: Client
+
+ def get_by_id(self, id: int) -> BoundLocation:
+ """Get a specific location by its ID.
+
+ :param id: int
+ :return: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
+ """
+ response = self._client.request(url=f"/locations/{id}", method="GET")
+ return BoundLocation(self, response["location"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> LocationsPageResult:
+ """Get a list of locations
+
+ :param name: str (optional)
+ Can be used to filter locations by their name.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundLocation <hcloud.locations.client.BoundLocation>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(url="/locations", method="GET", params=params)
+ locations = [
+ BoundLocation(self, location_data)
+ for location_data in response["locations"]
+ ]
+ return LocationsPageResult(locations, Meta.parse_meta(response))
+
+ def get_all(self, name: str | None = None) -> list[BoundLocation]:
+ """Get all locations
+
+ :param name: str (optional)
+ Can be used to filter locations by their name.
+ :return: List[:class:`BoundLocation <hcloud.locations.client.BoundLocation>`]
+ """
+ return self._iter_pages(self.get_list, name=name)
+
+ def get_by_name(self, name: str) -> BoundLocation | None:
+ """Get location by name
+
+ :param name: str
+ Used to get location by name.
+ :return: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
+ """
+ return self._get_first_by(name=name)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/domain.py
new file mode 100644
index 000000000..7d4af2230
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/locations/domain.py
@@ -0,0 +1,56 @@
+from __future__ import annotations
+
+from ..core import BaseDomain, DomainIdentityMixin
+
+
+class Location(BaseDomain, DomainIdentityMixin):
+ """Location Domain
+
+ :param id: int
+ ID of location
+ :param name: str
+ Name of location
+ :param description: str
+ Description of location
+ :param country: str
+ ISO 3166-1 alpha-2 code of the country the location resides in
+ :param city: str
+ City the location is closest to
+ :param latitude: float
+ Latitude of the city closest to the location
+ :param longitude: float
+ Longitude of the city closest to the location
+ :param network_zone: str
+ Name of network zone this location resides in
+ """
+
+ __slots__ = (
+ "id",
+ "name",
+ "description",
+ "country",
+ "city",
+ "latitude",
+ "longitude",
+ "network_zone",
+ )
+
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ description: str | None = None,
+ country: str | None = None,
+ city: str | None = None,
+ latitude: float | None = None,
+ longitude: float | None = None,
+ network_zone: str | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.description = description
+ self.country = country
+ self.city = city
+ self.latitude = latitude
+ self.longitude = longitude
+ self.network_zone = network_zone
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/metrics/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/metrics/__init__.py
new file mode 100644
index 000000000..65d393c8a
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/metrics/__init__.py
@@ -0,0 +1,3 @@
+from __future__ import annotations
+
+from .domain import Metrics, TimeSeries # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/metrics/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/metrics/domain.py
new file mode 100644
index 000000000..a9e737774
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/metrics/domain.py
@@ -0,0 +1,49 @@
+from __future__ import annotations
+
+from datetime import datetime
+from typing import Dict, List, Literal, Tuple
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain
+
+TimeSeries = Dict[str, Dict[Literal["values"], List[Tuple[float, str]]]]
+
+
+class Metrics(BaseDomain):
+ """Metrics Domain
+
+ :param start: Start of period of metrics reported.
+ :param end: End of period of metrics reported.
+ :param step: Resolution of results in seconds.
+ :param time_series: Dict with time series data, using the name of the time series as
+ key. The metrics timestamps and values are stored in a list of tuples
+ ``[(timestamp, value), ...]``.
+ """
+
+ start: datetime
+ end: datetime
+ step: float
+ time_series: TimeSeries
+
+ __slots__ = (
+ "start",
+ "end",
+ "step",
+ "time_series",
+ )
+
+ def __init__(
+ self,
+ start: str,
+ end: str,
+ step: float,
+ time_series: TimeSeries,
+ ):
+ self.start = isoparse(start)
+ self.end = isoparse(end)
+ self.step = step
+ self.time_series = time_series
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/__init__.py
new file mode 100644
index 000000000..5bf4a88f0
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/__init__.py
@@ -0,0 +1,9 @@
+from __future__ import annotations
+
+from .client import BoundNetwork, NetworksClient, NetworksPageResult # noqa: F401
+from .domain import ( # noqa: F401
+ CreateNetworkResponse,
+ Network,
+ NetworkRoute,
+ NetworkSubnet,
+)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/client.py
new file mode 100644
index 000000000..d819d5805
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/client.py
@@ -0,0 +1,556 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import Network, NetworkRoute, NetworkSubnet
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundNetwork(BoundModelBase, Network):
+ _client: NetworksClient
+
+ model = Network
+
+ def __init__(self, client: NetworksClient, data: dict, complete: bool = True):
+ subnets = data.get("subnets", [])
+ if subnets is not None:
+ subnets = [NetworkSubnet.from_dict(subnet) for subnet in subnets]
+ data["subnets"] = subnets
+
+ routes = data.get("routes", [])
+ if routes is not None:
+ routes = [NetworkRoute.from_dict(route) for route in routes]
+ data["routes"] = routes
+
+ # pylint: disable=import-outside-toplevel
+ from ..servers import BoundServer
+
+ servers = data.get("servers", [])
+ if servers is not None:
+ servers = [
+ BoundServer(client._client.servers, {"id": server}, complete=False)
+ for server in servers
+ ]
+ data["servers"] = servers
+
+ super().__init__(client, data, complete)
+
+ def update(
+ self,
+ name: str | None = None,
+ expose_routes_to_vswitch: bool | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundNetwork:
+ """Updates a network. You can update a network’s name and a networks’s labels.
+
+ :param name: str (optional)
+ New name to set
+ :param expose_routes_to_vswitch: Optional[bool]
+ Indicates if the routes from this network should be exposed to the vSwitch connection.
+ The exposing only takes effect if a vSwitch connection is active.
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
+ """
+ return self._client.update(
+ self,
+ name=name,
+ expose_routes_to_vswitch=expose_routes_to_vswitch,
+ labels=labels,
+ )
+
+ def delete(self) -> bool:
+ """Deletes a network.
+
+ :return: boolean
+ """
+ return self._client.delete(self)
+
+ def get_actions_list(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a network.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ return self._client.get_actions_list(self, status, sort, page, per_page)
+
+ def get_actions(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a network.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.get_actions(self, status, sort)
+
+ def add_subnet(self, subnet: NetworkSubnet) -> BoundAction:
+ """Adds a subnet entry to a network.
+
+ :param subnet: :class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`
+ The NetworkSubnet you want to add to the Network
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.add_subnet(self, subnet=subnet)
+
+ def delete_subnet(self, subnet: NetworkSubnet) -> BoundAction:
+ """Removes a subnet entry from a network
+
+ :param subnet: :class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`
+ The NetworkSubnet you want to remove from the Network
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.delete_subnet(self, subnet=subnet)
+
+ def add_route(self, route: NetworkRoute) -> BoundAction:
+ """Adds a route entry to a network.
+
+ :param route: :class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`
+ The NetworkRoute you want to add to the Network
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.add_route(self, route=route)
+
+ def delete_route(self, route: NetworkRoute) -> BoundAction:
+ """Removes a route entry to a network.
+
+ :param route: :class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`
+ The NetworkRoute you want to remove from the Network
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.delete_route(self, route=route)
+
+ def change_ip_range(self, ip_range: str) -> BoundAction:
+ """Changes the IP range of a network.
+
+ :param ip_range: str
+ The new prefix for the whole network.
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_ip_range(self, ip_range=ip_range)
+
+ def change_protection(self, delete: bool | None = None) -> BoundAction:
+ """Changes the protection configuration of a network.
+
+ :param delete: boolean
+ If True, prevents the network from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_protection(self, delete=delete)
+
+
+class NetworksPageResult(NamedTuple):
+ networks: list[BoundNetwork]
+ meta: Meta | None
+
+
+class NetworksClient(ClientEntityBase):
+ _client: Client
+
+ actions: ResourceActionsClient
+ """Networks scoped actions client
+
+ :type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
+ """
+
+ def __init__(self, client: Client):
+ super().__init__(client)
+ self.actions = ResourceActionsClient(client, "/networks")
+
+ def get_by_id(self, id: int) -> BoundNetwork:
+ """Get a specific network
+
+ :param id: int
+ :return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
+ """
+ response = self._client.request(url=f"/networks/{id}", method="GET")
+ return BoundNetwork(self, response["network"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> NetworksPageResult:
+ """Get a list of networks from this account
+
+ :param name: str (optional)
+ Can be used to filter networks by their name.
+ :param label_selector: str (optional)
+ Can be used to filter networks by labels. The response will only contain networks matching the label selector.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(url="/networks", method="GET", params=params)
+
+ networks = [
+ BoundNetwork(self, network_data) for network_data in response["networks"]
+ ]
+ return NetworksPageResult(networks, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ ) -> list[BoundNetwork]:
+ """Get all networks from this account
+
+ :param name: str (optional)
+ Can be used to filter networks by their name.
+ :param label_selector: str (optional)
+ Can be used to filter networks by labels. The response will only contain networks matching the label selector.
+ :return: List[:class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`]
+ """
+ return self._iter_pages(self.get_list, name=name, label_selector=label_selector)
+
+ def get_by_name(self, name: str) -> BoundNetwork | None:
+ """Get network by name
+
+ :param name: str
+ Used to get network by name.
+ :return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
+ """
+ return self._get_first_by(name=name)
+
+ def create(
+ self,
+ name: str,
+ ip_range: str,
+ subnets: list[NetworkSubnet] | None = None,
+ routes: list[NetworkRoute] | None = None,
+ expose_routes_to_vswitch: bool | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundNetwork:
+ """Creates a network with range ip_range.
+
+ :param name: str
+ Name of the network
+ :param ip_range: str
+ IP range of the whole network which must span all included subnets and route destinations
+ :param subnets: List[:class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`]
+ Array of subnets allocated
+ :param routes: List[:class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`]
+ Array of routes set in this network
+ :param expose_routes_to_vswitch: Optional[bool]
+ Indicates if the routes from this network should be exposed to the vSwitch connection.
+ The exposing only takes effect if a vSwitch connection is active.
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
+ """
+ data: dict[str, Any] = {"name": name, "ip_range": ip_range}
+ if subnets is not None:
+ data_subnets = []
+ for subnet in subnets:
+ data_subnet: dict[str, Any] = {
+ "type": subnet.type,
+ "ip_range": subnet.ip_range,
+ "network_zone": subnet.network_zone,
+ }
+ if subnet.vswitch_id is not None:
+ data_subnet["vswitch_id"] = subnet.vswitch_id
+
+ data_subnets.append(data_subnet)
+ data["subnets"] = data_subnets
+
+ if routes is not None:
+ data["routes"] = [
+ {"destination": route.destination, "gateway": route.gateway}
+ for route in routes
+ ]
+
+ if expose_routes_to_vswitch is not None:
+ data["expose_routes_to_vswitch"] = expose_routes_to_vswitch
+
+ if labels is not None:
+ data["labels"] = labels
+
+ response = self._client.request(url="/networks", method="POST", json=data)
+
+ return BoundNetwork(self, response["network"])
+
+ def update(
+ self,
+ network: Network | BoundNetwork,
+ name: str | None = None,
+ expose_routes_to_vswitch: bool | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundNetwork:
+ """Updates a network. You can update a network’s name and a network’s labels.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param name: str (optional)
+ New name to set
+ :param expose_routes_to_vswitch: Optional[bool]
+ Indicates if the routes from this network should be exposed to the vSwitch connection.
+ The exposing only takes effect if a vSwitch connection is active.
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
+ """
+ data: dict[str, Any] = {}
+ if name is not None:
+ data.update({"name": name})
+
+ if expose_routes_to_vswitch is not None:
+ data["expose_routes_to_vswitch"] = expose_routes_to_vswitch
+
+ if labels is not None:
+ data.update({"labels": labels})
+
+ response = self._client.request(
+ url=f"/networks/{network.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundNetwork(self, response["network"])
+
+ def delete(self, network: Network | BoundNetwork) -> bool:
+ """Deletes a network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :return: boolean
+ """
+ self._client.request(url=f"/networks/{network.id}", method="DELETE")
+ return True
+
+ def get_actions_list(
+ self,
+ network: Network | BoundNetwork,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if status is not None:
+ params["status"] = status
+ if sort is not None:
+ params["sort"] = sort
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url=f"/networks/{network.id}/actions",
+ method="GET",
+ params=params,
+ )
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+ return ActionsPageResult(actions, Meta.parse_meta(response))
+
+ def get_actions(
+ self,
+ network: Network | BoundNetwork,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._iter_pages(
+ self.get_actions_list,
+ network,
+ status=status,
+ sort=sort,
+ )
+
+ def add_subnet(
+ self,
+ network: Network | BoundNetwork,
+ subnet: NetworkSubnet,
+ ) -> BoundAction:
+ """Adds a subnet entry to a network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param subnet: :class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`
+ The NetworkSubnet you want to add to the Network
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {
+ "type": subnet.type,
+ "network_zone": subnet.network_zone,
+ }
+ if subnet.ip_range is not None:
+ data["ip_range"] = subnet.ip_range
+ if subnet.vswitch_id is not None:
+ data["vswitch_id"] = subnet.vswitch_id
+
+ response = self._client.request(
+ url=f"/networks/{network.id}/actions/add_subnet",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def delete_subnet(
+ self,
+ network: Network | BoundNetwork,
+ subnet: NetworkSubnet,
+ ) -> BoundAction:
+ """Removes a subnet entry from a network
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param subnet: :class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`
+ The NetworkSubnet you want to remove from the Network
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"ip_range": subnet.ip_range}
+
+ response = self._client.request(
+ url=f"/networks/{network.id}/actions/delete_subnet",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def add_route(
+ self,
+ network: Network | BoundNetwork,
+ route: NetworkRoute,
+ ) -> BoundAction:
+ """Adds a route entry to a network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param route: :class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`
+ The NetworkRoute you want to add to the Network
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {
+ "destination": route.destination,
+ "gateway": route.gateway,
+ }
+
+ response = self._client.request(
+ url=f"/networks/{network.id}/actions/add_route",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def delete_route(
+ self,
+ network: Network | BoundNetwork,
+ route: NetworkRoute,
+ ) -> BoundAction:
+ """Removes a route entry to a network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param route: :class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`
+ The NetworkRoute you want to remove from the Network
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {
+ "destination": route.destination,
+ "gateway": route.gateway,
+ }
+
+ response = self._client.request(
+ url=f"/networks/{network.id}/actions/delete_route",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_ip_range(
+ self,
+ network: Network | BoundNetwork,
+ ip_range: str,
+ ) -> BoundAction:
+ """Changes the IP range of a network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param ip_range: str
+ The new prefix for the whole network.
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"ip_range": ip_range}
+
+ response = self._client.request(
+ url=f"/networks/{network.id}/actions/change_ip_range",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_protection(
+ self,
+ network: Network | BoundNetwork,
+ delete: bool | None = None,
+ ) -> BoundAction:
+ """Changes the protection configuration of a network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param delete: boolean
+ If True, prevents the network from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {}
+ if delete is not None:
+ data.update({"delete": delete})
+
+ response = self._client.request(
+ url=f"/networks/{network.id}/actions/change_protection",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/domain.py
new file mode 100644
index 000000000..c307bf989
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/networks/domain.py
@@ -0,0 +1,150 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from ..servers import BoundServer
+ from .client import BoundNetwork
+
+
+class Network(BaseDomain):
+ """Network Domain
+
+ :param id: int
+ ID of the network
+ :param name: str
+ Name of the network
+ :param ip_range: str
+ IPv4 prefix of the whole network
+ :param subnets: List[:class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`]
+ Subnets allocated in this network
+ :param routes: List[:class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`]
+ Routes set in this network
+ :param expose_routes_to_vswitch: bool
+ Indicates if the routes from this network should be exposed to the vSwitch connection.
+ :param servers: List[:class:`BoundServer <hcloud.servers.client.BoundServer>`]
+ Servers attached to this network
+ :param protection: dict
+ Protection configuration for the network
+ :param labels: dict
+ User-defined labels (key-value pairs)
+ """
+
+ __slots__ = (
+ "id",
+ "name",
+ "ip_range",
+ "subnets",
+ "routes",
+ "expose_routes_to_vswitch",
+ "servers",
+ "protection",
+ "labels",
+ "created",
+ )
+
+ def __init__(
+ self,
+ id: int,
+ name: str | None = None,
+ created: str | None = None,
+ ip_range: str | None = None,
+ subnets: list[NetworkSubnet] | None = None,
+ routes: list[NetworkRoute] | None = None,
+ expose_routes_to_vswitch: bool | None = None,
+ servers: list[BoundServer] | None = None,
+ protection: dict | None = None,
+ labels: dict[str, str] | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.created = isoparse(created) if created else None
+ self.ip_range = ip_range
+ self.subnets = subnets
+ self.routes = routes
+ self.expose_routes_to_vswitch = expose_routes_to_vswitch
+ self.servers = servers
+ self.protection = protection
+ self.labels = labels
+
+
+class NetworkSubnet(BaseDomain):
+ """Network Subnet Domain
+
+ :param type: str
+ Type of sub network.
+ :param ip_range: str
+ Range to allocate IPs from.
+ :param network_zone: str
+ Name of network zone.
+ :param gateway: str
+ Gateway for the route.
+ :param vswitch_id: int
+ ID of the vSwitch.
+ """
+
+ TYPE_SERVER = "server"
+ """Subnet Type server, deprecated, use TYPE_CLOUD instead"""
+ TYPE_CLOUD = "cloud"
+ """Subnet Type cloud"""
+ TYPE_VSWITCH = "vswitch"
+ """Subnet Type vSwitch"""
+ __slots__ = ("type", "ip_range", "network_zone", "gateway", "vswitch_id")
+
+ def __init__(
+ self,
+ ip_range: str,
+ type: str | None = None,
+ network_zone: str | None = None,
+ gateway: str | None = None,
+ vswitch_id: int | None = None,
+ ):
+ self.type = type
+ self.ip_range = ip_range
+ self.network_zone = network_zone
+ self.gateway = gateway
+ self.vswitch_id = vswitch_id
+
+
+class NetworkRoute(BaseDomain):
+ """Network Route Domain
+
+ :param destination: str
+ Destination network or host of this route.
+ :param gateway: str
+ Gateway for the route.
+ """
+
+ __slots__ = ("destination", "gateway")
+
+ def __init__(self, destination: str, gateway: str):
+ self.destination = destination
+ self.gateway = gateway
+
+
+class CreateNetworkResponse(BaseDomain):
+ """Create Network Response Domain
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
+ The network which was created
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ The Action which shows the progress of the network Creation
+ """
+
+ __slots__ = ("network", "action")
+
+ def __init__(
+ self,
+ network: BoundNetwork,
+ action: BoundAction,
+ ):
+ self.network = network
+ self.action = action
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/__init__.py
new file mode 100644
index 000000000..9c25dd7f6
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/__init__.py
@@ -0,0 +1,8 @@
+from __future__ import annotations
+
+from .client import ( # noqa: F401
+ BoundPlacementGroup,
+ PlacementGroupsClient,
+ PlacementGroupsPageResult,
+)
+from .domain import CreatePlacementGroupResponse, PlacementGroup # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/client.py
new file mode 100644
index 000000000..fcfd86aec
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/client.py
@@ -0,0 +1,214 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..actions import BoundAction
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import CreatePlacementGroupResponse, PlacementGroup
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundPlacementGroup(BoundModelBase, PlacementGroup):
+ _client: PlacementGroupsClient
+
+ model = PlacementGroup
+
+ def update(
+ self,
+ labels: dict[str, str] | None = None,
+ name: str | None = None,
+ ) -> BoundPlacementGroup:
+ """Updates the name or labels of a Placement Group
+
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param name: str, (optional)
+ New Name to set
+ :return: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
+ """
+ return self._client.update(self, labels, name)
+
+ def delete(self) -> bool:
+ """Deletes a Placement Group
+
+ :return: boolean
+ """
+ return self._client.delete(self)
+
+
+class PlacementGroupsPageResult(NamedTuple):
+ placement_groups: list[BoundPlacementGroup]
+ meta: Meta | None
+
+
+class PlacementGroupsClient(ClientEntityBase):
+ _client: Client
+
+ def get_by_id(self, id: int) -> BoundPlacementGroup:
+ """Returns a specific Placement Group object
+
+ :param id: int
+ :return: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
+ """
+ response = self._client.request(
+ url=f"/placement_groups/{id}",
+ method="GET",
+ )
+ return BoundPlacementGroup(self, response["placement_group"])
+
+ def get_list(
+ self,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ name: str | None = None,
+ sort: list[str] | None = None,
+ type: str | None = None,
+ ) -> PlacementGroupsPageResult:
+ """Get a list of Placement Groups
+
+ :param label_selector: str (optional)
+ Can be used to filter Placement Groups by labels. The response will only contain Placement Groups matching the label selector values.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :param name: str (optional)
+ Can be used to filter Placement Groups by their name.
+ :param sort: List[str] (optional)
+ Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
+ :return: (List[:class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+
+ params: dict[str, Any] = {}
+
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+ if name is not None:
+ params["name"] = name
+ if sort is not None:
+ params["sort"] = sort
+ if type is not None:
+ params["type"] = type
+ response = self._client.request(
+ url="/placement_groups", method="GET", params=params
+ )
+ placement_groups = [
+ BoundPlacementGroup(self, placement_group_data)
+ for placement_group_data in response["placement_groups"]
+ ]
+
+ return PlacementGroupsPageResult(placement_groups, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ label_selector: str | None = None,
+ name: str | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundPlacementGroup]:
+ """Get all Placement Groups
+
+ :param label_selector: str (optional)
+ Can be used to filter Placement Groups by labels. The response will only contain Placement Groups matching the label selector values.
+ :param name: str (optional)
+ Can be used to filter Placement Groups by their name.
+ :param sort: List[str] (optional)
+ Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
+ :return: List[:class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`]
+ """
+ return self._iter_pages(
+ self.get_list,
+ label_selector=label_selector,
+ name=name,
+ sort=sort,
+ )
+
+ def get_by_name(self, name: str) -> BoundPlacementGroup | None:
+ """Get Placement Group by name
+
+ :param name: str
+ Used to get Placement Group by name
+ :return: class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
+ """
+ return self._get_first_by(name=name)
+
+ def create(
+ self,
+ name: str,
+ type: str,
+ labels: dict[str, str] | None = None,
+ ) -> CreatePlacementGroupResponse:
+ """Creates a new Placement Group.
+
+ :param name: str
+ Placement Group Name
+ :param type: str
+ Type of the Placement Group
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+
+ :return: :class:`CreatePlacementGroupResponse <hcloud.placement_groups.domain.CreatePlacementGroupResponse>`
+ """
+ data: dict[str, Any] = {"name": name, "type": type}
+ if labels is not None:
+ data["labels"] = labels
+ response = self._client.request(
+ url="/placement_groups", json=data, method="POST"
+ )
+
+ action = None
+ if response.get("action") is not None:
+ action = BoundAction(self._client.actions, response["action"])
+
+ result = CreatePlacementGroupResponse(
+ placement_group=BoundPlacementGroup(self, response["placement_group"]),
+ action=action,
+ )
+ return result
+
+ def update(
+ self,
+ placement_group: PlacementGroup | BoundPlacementGroup,
+ labels: dict[str, str] | None = None,
+ name: str | None = None,
+ ) -> BoundPlacementGroup:
+ """Updates the description or labels of a Placement Group.
+
+ :param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>` or :class:`PlacementGroup <hcloud.placement_groups.domain.PlacementGroup>`
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param name: str (optional)
+ New name to set
+ :return: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
+ """
+
+ data: dict[str, Any] = {}
+ if labels is not None:
+ data["labels"] = labels
+ if name is not None:
+ data["name"] = name
+
+ response = self._client.request(
+ url=f"/placement_groups/{placement_group.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundPlacementGroup(self, response["placement_group"])
+
+ def delete(self, placement_group: PlacementGroup | BoundPlacementGroup) -> bool:
+ """Deletes a Placement Group.
+
+ :param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>` or :class:`PlacementGroup <hcloud.placement_groups.domain.PlacementGroup>`
+ :return: boolean
+ """
+ self._client.request(
+ url=f"/placement_groups/{placement_group.id}",
+ method="DELETE",
+ )
+ return True
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/domain.py
new file mode 100644
index 000000000..16b2a390d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/placement_groups/domain.py
@@ -0,0 +1,75 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from .client import BoundPlacementGroup
+
+
+class PlacementGroup(BaseDomain):
+ """Placement Group Domain
+
+ :param id: int
+ ID of the Placement Group
+ :param name: str
+ Name of the Placement Group
+ :param labels: dict
+ User-defined labels (key-value pairs)
+ :param servers: List[ int ]
+ List of server IDs assigned to the Placement Group
+ :param type: str
+ Type of the Placement Group
+ :param created: datetime
+ Point in time when the image was created
+ """
+
+ __slots__ = ("id", "name", "labels", "servers", "type", "created")
+
+ """Placement Group type spread
+ spreads all servers in the group on different vhosts
+ """
+ TYPE_SPREAD = "spread"
+
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ servers: list[int] | None = None,
+ type: str | None = None,
+ created: str | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.labels = labels
+ self.servers = servers
+ self.type = type
+ self.created = isoparse(created) if created else None
+
+
+class CreatePlacementGroupResponse(BaseDomain):
+ """Create Placement Group Response Domain
+
+ :param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
+ The Placement Group which was created
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ The Action which shows the progress of the Placement Group Creation
+ """
+
+ __slots__ = ("placement_group", "action")
+
+ def __init__(
+ self,
+ placement_group: BoundPlacementGroup,
+ action: BoundAction | None,
+ ):
+ self.placement_group = placement_group
+ self.action = action
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/__init__.py
new file mode 100644
index 000000000..d079a23b1
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/__init__.py
@@ -0,0 +1,4 @@
+from __future__ import annotations
+
+from .client import BoundPrimaryIP, PrimaryIPsClient, PrimaryIPsPageResult # noqa: F401
+from .domain import CreatePrimaryIPResponse, PrimaryIP # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/client.py
new file mode 100644
index 000000000..ece8d88f4
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/client.py
@@ -0,0 +1,361 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..actions import BoundAction, ResourceActionsClient
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import CreatePrimaryIPResponse, PrimaryIP
+
+if TYPE_CHECKING:
+ from .._client import Client
+ from ..datacenters import BoundDatacenter, Datacenter
+
+
+class BoundPrimaryIP(BoundModelBase, PrimaryIP):
+ _client: PrimaryIPsClient
+
+ model = PrimaryIP
+
+ def __init__(self, client: PrimaryIPsClient, data: dict, complete: bool = True):
+ # pylint: disable=import-outside-toplevel
+ from ..datacenters import BoundDatacenter
+
+ datacenter = data.get("datacenter", {})
+ if datacenter:
+ data["datacenter"] = BoundDatacenter(client._client.datacenters, datacenter)
+
+ super().__init__(client, data, complete)
+
+ def update(
+ self,
+ auto_delete: bool | None = None,
+ labels: dict[str, str] | None = None,
+ name: str | None = None,
+ ) -> BoundPrimaryIP:
+ """Updates the description or labels of a Primary IP.
+
+ :param auto_delete: bool (optional)
+ Auto delete IP when assignee gets deleted
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param name: str (optional)
+ New Name to set
+ :return: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
+ """
+ return self._client.update(
+ self, auto_delete=auto_delete, labels=labels, name=name
+ )
+
+ def delete(self) -> bool:
+ """Deletes a Primary IP. If it is currently assigned to a server it will automatically get unassigned.
+
+ :return: boolean
+ """
+ return self._client.delete(self)
+
+ def change_protection(self, delete: bool | None = None) -> BoundAction:
+ """Changes the protection configuration of the Primary IP.
+
+ :param delete: boolean
+ If true, prevents the Primary IP from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_protection(self, delete)
+
+ def assign(self, assignee_id: int, assignee_type: str) -> BoundAction:
+ """Assigns a Primary IP to a assignee.
+
+ :param assignee_id: int`
+ Id of an assignee the Primary IP shall be assigned to
+ :param assignee_type: string`
+ Assignee type (e.g server) the Primary IP shall be assigned to
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.assign(self, assignee_id, assignee_type)
+
+ def unassign(self) -> BoundAction:
+ """Unassigns a Primary IP, resulting in it being unreachable. You may assign it to a server again at a later time.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.unassign(self)
+
+ def change_dns_ptr(self, ip: str, dns_ptr: str) -> BoundAction:
+ """Changes the hostname that will appear when getting the hostname belonging to this Primary IP.
+
+ :param ip: str
+ The IP address for which to set the reverse DNS entry
+ :param dns_ptr: str
+ Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_dns_ptr(self, ip, dns_ptr)
+
+
+class PrimaryIPsPageResult(NamedTuple):
+ primary_ips: list[BoundPrimaryIP]
+ meta: Meta | None
+
+
+class PrimaryIPsClient(ClientEntityBase):
+ _client: Client
+
+ actions: ResourceActionsClient
+ """Primary IPs scoped actions client
+
+ :type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
+ """
+
+ def __init__(self, client: Client):
+ super().__init__(client)
+ self.actions = ResourceActionsClient(client, "/primary_ips")
+
+ def get_by_id(self, id: int) -> BoundPrimaryIP:
+ """Returns a specific Primary IP object.
+
+ :param id: int
+ :return: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
+ """
+ response = self._client.request(url=f"/primary_ips/{id}", method="GET")
+ return BoundPrimaryIP(self, response["primary_ip"])
+
+ def get_list(
+ self,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ name: str | None = None,
+ ip: str | None = None,
+ ) -> PrimaryIPsPageResult:
+ """Get a list of primary ips from this account
+
+ :param label_selector: str (optional)
+ Can be used to filter Primary IPs by labels. The response will only contain Primary IPs matching the label selectorable values.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :param name: str (optional)
+ Can be used to filter networks by their name.
+ :param ip: str (optional)
+ Can be used to filter resources by their ip. The response will only contain the resources matching the specified ip.
+ :return: (List[:class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+ if name is not None:
+ params["name"] = name
+ if ip is not None:
+ params["ip"] = ip
+
+ response = self._client.request(url="/primary_ips", method="GET", params=params)
+ primary_ips = [
+ BoundPrimaryIP(self, primary_ip_data)
+ for primary_ip_data in response["primary_ips"]
+ ]
+
+ return PrimaryIPsPageResult(primary_ips, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ label_selector: str | None = None,
+ name: str | None = None,
+ ) -> list[BoundPrimaryIP]:
+ """Get all primary ips from this account
+
+ :param label_selector: str (optional)
+ Can be used to filter Primary IPs by labels. The response will only contain Primary IPs matching the label selector.able values.
+ :param name: str (optional)
+ Can be used to filter networks by their name.
+ :return: List[:class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`]
+ """
+ return self._iter_pages(self.get_list, label_selector=label_selector, name=name)
+
+ def get_by_name(self, name: str) -> BoundPrimaryIP | None:
+ """Get Primary IP by name
+
+ :param name: str
+ Used to get Primary IP by name.
+ :return: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
+ """
+ return self._get_first_by(name=name)
+
+ def create(
+ self,
+ type: str,
+ # TODO: Make the datacenter argument optional
+ datacenter: Datacenter | BoundDatacenter | None,
+ name: str,
+ assignee_type: str | None = "server",
+ assignee_id: int | None = None,
+ auto_delete: bool | None = False,
+ labels: dict | None = None,
+ ) -> CreatePrimaryIPResponse:
+ """Creates a new Primary IP assigned to a server.
+
+ :param type: str
+ Primary IP type Choices: ipv4, ipv6
+ :param assignee_type: str
+ :param assignee_id: int (optional)
+ :param datacenter: Datacenter
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param name: str
+ :param auto_delete: bool (optional)
+ :return: :class:`CreatePrimaryIPResponse <hcloud.primary_ips.domain.CreatePrimaryIPResponse>`
+ """
+
+ data: dict[str, Any] = {
+ "type": type,
+ "assignee_type": assignee_type,
+ "auto_delete": auto_delete,
+ "name": name,
+ }
+ if datacenter is not None:
+ data["datacenter"] = datacenter.id_or_name
+ if assignee_id is not None:
+ data["assignee_id"] = assignee_id
+ if labels is not None:
+ data["labels"] = labels
+
+ response = self._client.request(url="/primary_ips", json=data, method="POST")
+
+ action = None
+ if response.get("action") is not None:
+ action = BoundAction(self._client.actions, response["action"])
+
+ result = CreatePrimaryIPResponse(
+ primary_ip=BoundPrimaryIP(self, response["primary_ip"]), action=action
+ )
+ return result
+
+ def update(
+ self,
+ primary_ip: PrimaryIP | BoundPrimaryIP,
+ auto_delete: bool | None = None,
+ labels: dict[str, str] | None = None,
+ name: str | None = None,
+ ) -> BoundPrimaryIP:
+ """Updates the name, auto_delete or labels of a Primary IP.
+
+ :param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
+ :param auto_delete: bool (optional)
+ Delete this Primary IP when the resource it is assigned to is deleted
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :param name: str (optional)
+ New name to set
+ :return: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
+ """
+ data: dict[str, Any] = {}
+ if auto_delete is not None:
+ data["auto_delete"] = auto_delete
+ if labels is not None:
+ data["labels"] = labels
+ if name is not None:
+ data["name"] = name
+
+ response = self._client.request(
+ url=f"/primary_ips/{primary_ip.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundPrimaryIP(self, response["primary_ip"])
+
+ def delete(self, primary_ip: PrimaryIP | BoundPrimaryIP) -> bool:
+ """Deletes a Primary IP. If it is currently assigned to an assignee it will automatically get unassigned.
+
+ :param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
+ :return: boolean
+ """
+ self._client.request(
+ url=f"/primary_ips/{primary_ip.id}",
+ method="DELETE",
+ )
+ # Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
+ return True
+
+ def change_protection(
+ self,
+ primary_ip: PrimaryIP | BoundPrimaryIP,
+ delete: bool | None = None,
+ ) -> BoundAction:
+ """Changes the protection configuration of the Primary IP.
+
+ :param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
+ :param delete: boolean
+ If true, prevents the Primary IP from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {}
+ if delete is not None:
+ data.update({"delete": delete})
+
+ response = self._client.request(
+ url=f"/primary_ips/{primary_ip.id}/actions/change_protection",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def assign(
+ self,
+ primary_ip: PrimaryIP | BoundPrimaryIP,
+ assignee_id: int,
+ assignee_type: str = "server",
+ ) -> BoundAction:
+ """Assigns a Primary IP to a assignee_id.
+
+ :param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
+ :param assignee_id: int
+ Assignee the Primary IP shall be assigned to
+ :param assignee_type: str
+ Assignee the Primary IP shall be assigned to
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/primary_ips/{primary_ip.id}/actions/assign",
+ method="POST",
+ json={"assignee_id": assignee_id, "assignee_type": assignee_type},
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def unassign(self, primary_ip: PrimaryIP | BoundPrimaryIP) -> BoundAction:
+ """Unassigns a Primary IP, resulting in it being unreachable. You may assign it to a server again at a later time.
+
+ :param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/primary_ips/{primary_ip.id}/actions/unassign",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_dns_ptr(
+ self,
+ primary_ip: PrimaryIP | BoundPrimaryIP,
+ ip: str,
+ dns_ptr: str,
+ ) -> BoundAction:
+ """Changes the dns ptr that will appear when getting the dns ptr belonging to this Primary IP.
+
+ :param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
+ :param ip: str
+ The IP address for which to set the reverse DNS entry
+ :param dns_ptr: str
+ Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/primary_ips/{primary_ip.id}/actions/change_dns_ptr",
+ method="POST",
+ json={"ip": ip, "dns_ptr": dns_ptr},
+ )
+ return BoundAction(self._client.actions, response["action"])
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/domain.py
new file mode 100644
index 000000000..aeb943f0a
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/primary_ips/domain.py
@@ -0,0 +1,113 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from ..datacenters import BoundDatacenter
+ from .client import BoundPrimaryIP
+
+
+class PrimaryIP(BaseDomain):
+ """Primary IP Domain
+
+ :param id: int
+ ID of the Primary IP
+ :param ip: str
+ IP address of the Primary IP
+ :param type: str
+ Type of Primary IP. Choices: `ipv4`, `ipv6`
+ :param dns_ptr: List[Dict]
+ Array of reverse DNS entries
+ :param datacenter: :class:`Datacenter <hcloud.datacenters.client.BoundDatacenter>`
+ Datacenter the Primary IP was created in.
+ :param blocked: boolean
+ Whether the IP is blocked
+ :param protection: dict
+ Protection configuration for the Primary IP
+ :param labels: dict
+ User-defined labels (key-value pairs)
+ :param created: datetime
+ Point in time when the Primary IP was created
+ :param name: str
+ Name of the Primary IP
+ :param assignee_id: int
+ Assignee ID the Primary IP is assigned to
+ :param assignee_type: str
+ Assignee Type of entity the Primary IP is assigned to
+ :param auto_delete: bool
+ Delete the Primary IP when the Assignee it is assigned to is deleted.
+ """
+
+ __slots__ = (
+ "id",
+ "ip",
+ "type",
+ "dns_ptr",
+ "datacenter",
+ "blocked",
+ "protection",
+ "labels",
+ "created",
+ "name",
+ "assignee_id",
+ "assignee_type",
+ "auto_delete",
+ )
+
+ def __init__(
+ self,
+ id: int | None = None,
+ type: str | None = None,
+ ip: str | None = None,
+ dns_ptr: list[dict] | None = None,
+ datacenter: BoundDatacenter | None = None,
+ blocked: bool | None = None,
+ protection: dict | None = None,
+ labels: dict[str, dict] | None = None,
+ created: str | None = None,
+ name: str | None = None,
+ assignee_id: int | None = None,
+ assignee_type: str | None = None,
+ auto_delete: bool | None = None,
+ ):
+ self.id = id
+ self.type = type
+ self.ip = ip
+ self.dns_ptr = dns_ptr
+ self.datacenter = datacenter
+ self.blocked = blocked
+ self.protection = protection
+ self.labels = labels
+ self.created = isoparse(created) if created else None
+ self.name = name
+ self.assignee_id = assignee_id
+ self.assignee_type = assignee_type
+ self.auto_delete = auto_delete
+
+
+class CreatePrimaryIPResponse(BaseDomain):
+ """Create Primary IP Response Domain
+
+ :param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
+ The Primary IP which was created
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ The Action which shows the progress of the Primary IP Creation
+ """
+
+ __slots__ = ("primary_ip", "action")
+
+ def __init__(
+ self,
+ primary_ip: BoundPrimaryIP,
+ action: BoundAction | None,
+ ):
+ self.primary_ip = primary_ip
+ self.action = action
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/py.typed b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/py.typed
new file mode 100644
index 000000000..1242d4327
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/py.typed
@@ -0,0 +1 @@
+# Marker file for PEP 561.
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/__init__.py
new file mode 100644
index 000000000..1e978d094
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/__init__.py
@@ -0,0 +1,8 @@
+from __future__ import annotations
+
+from .client import ( # noqa: F401
+ BoundServerType,
+ ServerTypesClient,
+ ServerTypesPageResult,
+)
+from .domain import ServerType # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/client.py
new file mode 100644
index 000000000..31f56a20c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/client.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import ServerType
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundServerType(BoundModelBase, ServerType):
+ _client: ServerTypesClient
+
+ model = ServerType
+
+
+class ServerTypesPageResult(NamedTuple):
+ server_types: list[BoundServerType]
+ meta: Meta | None
+
+
+class ServerTypesClient(ClientEntityBase):
+ _client: Client
+
+ def get_by_id(self, id: int) -> BoundServerType:
+ """Returns a specific Server Type.
+
+ :param id: int
+ :return: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>`
+ """
+ response = self._client.request(url=f"/server_types/{id}", method="GET")
+ return BoundServerType(self, response["server_type"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ServerTypesPageResult:
+ """Get a list of Server types
+
+ :param name: str (optional)
+ Can be used to filter server type by their name.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundServerType <hcloud.server_types.client.BoundServerType>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url="/server_types", method="GET", params=params
+ )
+ server_types = [
+ BoundServerType(self, server_type_data)
+ for server_type_data in response["server_types"]
+ ]
+ return ServerTypesPageResult(server_types, Meta.parse_meta(response))
+
+ def get_all(self, name: str | None = None) -> list[BoundServerType]:
+ """Get all Server types
+
+ :param name: str (optional)
+ Can be used to filter server type by their name.
+ :return: List[:class:`BoundServerType <hcloud.server_types.client.BoundServerType>`]
+ """
+ return self._iter_pages(self.get_list, name=name)
+
+ def get_by_name(self, name: str) -> BoundServerType | None:
+ """Get Server type by name
+
+ :param name: str
+ Used to get Server type by name.
+ :return: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>`
+ """
+ return self._get_first_by(name=name)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/domain.py
new file mode 100644
index 000000000..ab2553b10
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/server_types/domain.py
@@ -0,0 +1,85 @@
+from __future__ import annotations
+
+from ..core import BaseDomain, DomainIdentityMixin
+from ..deprecation import DeprecationInfo
+
+
+class ServerType(BaseDomain, DomainIdentityMixin):
+ """ServerType Domain
+
+ :param id: int
+ ID of the server type
+ :param name: str
+ Unique identifier of the server type
+ :param description: str
+ Description of the server type
+ :param cores: int
+ Number of cpu cores a server of this type will have
+ :param memory: int
+ Memory a server of this type will have in GB
+ :param disk: int
+ Disk size a server of this type will have in GB
+ :param prices: Dict
+ Prices in different locations
+ :param storage_type: str
+ Type of server boot drive. Local has higher speed. Network has better availability. Choices: `local`, `network`
+ :param cpu_type: string
+ Type of cpu. Choices: `shared`, `dedicated`
+ :param architecture: string
+ Architecture of cpu. Choices: `x86`, `arm`
+ :param deprecated: bool
+ True if server type is deprecated. This field is deprecated. Use `deprecation` instead.
+ :param deprecation: :class:`DeprecationInfo <hcloud.deprecation.domain.DeprecationInfo>`, None
+ Describes if, when & how the resources was deprecated. If this field is set to None the resource is not
+ deprecated. If it has a value, it is considered deprecated.
+ :param included_traffic: int
+ Free traffic per month in bytes
+ """
+
+ __slots__ = (
+ "id",
+ "name",
+ "description",
+ "cores",
+ "memory",
+ "disk",
+ "prices",
+ "storage_type",
+ "cpu_type",
+ "architecture",
+ "deprecated",
+ "deprecation",
+ "included_traffic",
+ )
+
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ description: str | None = None,
+ cores: int | None = None,
+ memory: int | None = None,
+ disk: int | None = None,
+ prices: dict | None = None,
+ storage_type: str | None = None,
+ cpu_type: str | None = None,
+ architecture: str | None = None,
+ deprecated: bool | None = None,
+ deprecation: dict | None = None,
+ included_traffic: int | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.description = description
+ self.cores = cores
+ self.memory = memory
+ self.disk = disk
+ self.prices = prices
+ self.storage_type = storage_type
+ self.cpu_type = cpu_type
+ self.architecture = architecture
+ self.deprecated = deprecated
+ self.deprecation = (
+ DeprecationInfo.from_dict(deprecation) if deprecation is not None else None
+ )
+ self.included_traffic = included_traffic
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/__init__.py
new file mode 100644
index 000000000..58c811e51
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/__init__.py
@@ -0,0 +1,17 @@
+from __future__ import annotations
+
+from .client import BoundServer, ServersClient, ServersPageResult # noqa: F401
+from .domain import ( # noqa: F401
+ CreateServerResponse,
+ EnableRescueResponse,
+ GetMetricsResponse,
+ IPv4Address,
+ IPv6Network,
+ PrivateNet,
+ PublicNetwork,
+ PublicNetworkFirewall,
+ RequestConsoleResponse,
+ ResetPasswordResponse,
+ Server,
+ ServerCreatePublicNetwork,
+)
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/client.py
new file mode 100644
index 000000000..b959b9d87
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/client.py
@@ -0,0 +1,1265 @@
+from __future__ import annotations
+
+import warnings
+from datetime import datetime
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from ..datacenters import BoundDatacenter
+from ..firewalls import BoundFirewall
+from ..floating_ips import BoundFloatingIP
+from ..images import BoundImage, CreateImageResponse
+from ..isos import BoundIso
+from ..metrics import Metrics
+from ..placement_groups import BoundPlacementGroup
+from ..primary_ips import BoundPrimaryIP
+from ..server_types import BoundServerType
+from ..volumes import BoundVolume
+from .domain import (
+ CreateServerResponse,
+ EnableRescueResponse,
+ GetMetricsResponse,
+ IPv4Address,
+ IPv6Network,
+ MetricsType,
+ PrivateNet,
+ PublicNetwork,
+ PublicNetworkFirewall,
+ RebuildResponse,
+ RequestConsoleResponse,
+ ResetPasswordResponse,
+ Server,
+)
+
+if TYPE_CHECKING:
+ from .._client import Client
+ from ..datacenters import Datacenter
+ from ..firewalls import Firewall
+ from ..images import Image
+ from ..isos import Iso
+ from ..locations import BoundLocation, Location
+ from ..networks import BoundNetwork, Network
+ from ..placement_groups import PlacementGroup
+ from ..server_types import ServerType
+ from ..ssh_keys import BoundSSHKey, SSHKey
+ from ..volumes import Volume
+ from .domain import ServerCreatePublicNetwork
+
+
+class BoundServer(BoundModelBase, Server):
+ _client: ServersClient
+
+ model = Server
+
+ # pylint: disable=too-many-locals
+ def __init__(self, client: ServersClient, data: dict, complete: bool = True):
+ datacenter = data.get("datacenter")
+ if datacenter is not None:
+ data["datacenter"] = BoundDatacenter(client._client.datacenters, datacenter)
+
+ volumes = data.get("volumes", [])
+ if volumes:
+ volumes = [
+ BoundVolume(client._client.volumes, {"id": volume}, complete=False)
+ for volume in volumes
+ ]
+ data["volumes"] = volumes
+
+ image = data.get("image", None)
+ if image is not None:
+ data["image"] = BoundImage(client._client.images, image)
+
+ iso = data.get("iso", None)
+ if iso is not None:
+ data["iso"] = BoundIso(client._client.isos, iso)
+
+ server_type = data.get("server_type")
+ if server_type is not None:
+ data["server_type"] = BoundServerType(
+ client._client.server_types, server_type
+ )
+
+ public_net = data.get("public_net")
+ if public_net:
+ ipv4_address = (
+ IPv4Address.from_dict(public_net["ipv4"])
+ if public_net["ipv4"] is not None
+ else None
+ )
+ ipv4_primary_ip = (
+ BoundPrimaryIP(
+ client._client.primary_ips,
+ {"id": public_net["ipv4"]["id"]},
+ complete=False,
+ )
+ if public_net["ipv4"] is not None
+ else None
+ )
+ ipv6_network = (
+ IPv6Network.from_dict(public_net["ipv6"])
+ if public_net["ipv6"] is not None
+ else None
+ )
+ ipv6_primary_ip = (
+ BoundPrimaryIP(
+ client._client.primary_ips,
+ {"id": public_net["ipv6"]["id"]},
+ complete=False,
+ )
+ if public_net["ipv6"] is not None
+ else None
+ )
+ floating_ips = [
+ BoundFloatingIP(
+ client._client.floating_ips, {"id": floating_ip}, complete=False
+ )
+ for floating_ip in public_net["floating_ips"]
+ ]
+ firewalls = [
+ PublicNetworkFirewall(
+ BoundFirewall(
+ client._client.firewalls, {"id": firewall["id"]}, complete=False
+ ),
+ status=firewall["status"],
+ )
+ for firewall in public_net.get("firewalls", [])
+ ]
+ data["public_net"] = PublicNetwork(
+ ipv4=ipv4_address,
+ ipv6=ipv6_network,
+ primary_ipv4=ipv4_primary_ip,
+ primary_ipv6=ipv6_primary_ip,
+ floating_ips=floating_ips,
+ firewalls=firewalls,
+ )
+
+ private_nets = data.get("private_net")
+ if private_nets:
+ # pylint: disable=import-outside-toplevel
+ from ..networks import BoundNetwork
+
+ private_nets = [
+ PrivateNet(
+ network=BoundNetwork(
+ client._client.networks,
+ {"id": private_net["network"]},
+ complete=False,
+ ),
+ ip=private_net["ip"],
+ alias_ips=private_net["alias_ips"],
+ mac_address=private_net["mac_address"],
+ )
+ for private_net in private_nets
+ ]
+ data["private_net"] = private_nets
+
+ placement_group = data.get("placement_group")
+ if placement_group:
+ placement_group = BoundPlacementGroup(
+ client._client.placement_groups, placement_group
+ )
+ data["placement_group"] = placement_group
+
+ super().__init__(client, data, complete)
+
+ def get_actions_list(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a server.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ return self._client.get_actions_list(self, status, sort, page, per_page)
+
+ def get_actions(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a server.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.get_actions(self, status, sort)
+
+ def update(
+ self,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundServer:
+ """Updates a server. You can update a server’s name and a server’s labels.
+
+ :param name: str (optional)
+ New name to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundServer <hcloud.servers.client.BoundServer>`
+ """
+ return self._client.update(self, name, labels)
+
+ def get_metrics(
+ self,
+ type: MetricsType | list[MetricsType],
+ start: datetime | str,
+ end: datetime | str,
+ step: float | None = None,
+ ) -> GetMetricsResponse:
+ """Get Metrics for a Server.
+
+ :param server: The Server to get the metrics for.
+ :param type: Type of metrics to get.
+ :param start: Start of period to get Metrics for (in ISO-8601 format).
+ :param end: End of period to get Metrics for (in ISO-8601 format).
+ :param step: Resolution of results in seconds.
+ """
+ return self._client.get_metrics(
+ self,
+ type=type,
+ start=start,
+ end=end,
+ step=step,
+ )
+
+ def delete(self) -> BoundAction:
+ """Deletes a server. This immediately removes the server from your account, and it is no longer accessible.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.delete(self)
+
+ def power_off(self) -> BoundAction:
+ """Cuts power to the server. This forcefully stops it without giving the server operating system time to gracefully stop
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.power_off(self)
+
+ def power_on(self) -> BoundAction:
+ """Starts a server by turning its power on.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.power_on(self)
+
+ def reboot(self) -> BoundAction:
+ """Reboots a server gracefully by sending an ACPI request.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.reboot(self)
+
+ def reset(self) -> BoundAction:
+ """Cuts power to a server and starts it again.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.reset(self)
+
+ def shutdown(self) -> BoundAction:
+ """Shuts down a server gracefully by sending an ACPI shutdown request.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.shutdown(self)
+
+ def reset_password(self) -> ResetPasswordResponse:
+ """Resets the root password. Only works for Linux systems that are running the qemu guest agent.
+
+ :return: :class:`ResetPasswordResponse <hcloud.servers.domain.ResetPasswordResponse>`
+ """
+ return self._client.reset_password(self)
+
+ def enable_rescue(
+ self,
+ type: str | None = None,
+ ssh_keys: list[str] | None = None,
+ ) -> EnableRescueResponse:
+ """Enable the Hetzner Rescue System for this server.
+
+ :param type: str
+ Type of rescue system to boot (default: linux64)
+ Choices: linux64, linux32, freebsd64
+ :param ssh_keys: List[str]
+ Array of SSH key IDs which should be injected into the rescue system. Only available for types: linux64 and linux32.
+ :return: :class:`EnableRescueResponse <hcloud.servers.domain.EnableRescueResponse>`
+ """
+ return self._client.enable_rescue(self, type=type, ssh_keys=ssh_keys)
+
+ def disable_rescue(self) -> BoundAction:
+ """Disables the Hetzner Rescue System for a server.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.disable_rescue(self)
+
+ def create_image(
+ self,
+ description: str | None = None,
+ type: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> CreateImageResponse:
+ """Creates an image (snapshot) from a server by copying the contents of its disks.
+
+ :param description: str (optional)
+ Description of the image. If you do not set this we auto-generate one for you.
+ :param type: str (optional)
+ Type of image to create (default: snapshot)
+ Choices: snapshot, backup
+ :param labels: Dict[str, str]
+ User-defined labels (key-value pairs)
+ :return: :class:`CreateImageResponse <hcloud.images.domain.CreateImageResponse>`
+ """
+ return self._client.create_image(self, description, type, labels)
+
+ def rebuild(
+ self,
+ image: Image | BoundImage,
+ *,
+ return_response: bool = False,
+ ) -> RebuildResponse | BoundAction:
+ """Rebuilds a server overwriting its disk with the content of an image, thereby destroying all data on the target server.
+
+ :param image: Image to use for the rebuilt server
+ :param return_response: Whether to return the full response or only the action.
+ """
+ return self._client.rebuild(self, image, return_response=return_response)
+
+ def change_type(
+ self,
+ server_type: ServerType | BoundServerType,
+ upgrade_disk: bool,
+ ) -> BoundAction:
+ """Changes the type (Cores, RAM and disk sizes) of a server.
+
+ :param server_type: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>` or :class:`ServerType <hcloud.server_types.domain.ServerType>`
+ Server type the server should migrate to
+ :param upgrade_disk: boolean
+ If false, do not upgrade the disk. This allows downgrading the server type later.
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_type(self, server_type, upgrade_disk)
+
+ def enable_backup(self) -> BoundAction:
+ """Enables and configures the automatic daily backup option for the server. Enabling automatic backups will increase the price of the server by 20%.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.enable_backup(self)
+
+ def disable_backup(self) -> BoundAction:
+ """Disables the automatic backup option and deletes all existing Backups for a Server.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.disable_backup(self)
+
+ def attach_iso(self, iso: Iso | BoundIso) -> BoundAction:
+ """Attaches an ISO to a server.
+
+ :param iso: :class:`BoundIso <hcloud.isos.client.BoundIso>` or :class:`Server <hcloud.isos.domain.Iso>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.attach_iso(self, iso)
+
+ def detach_iso(self) -> BoundAction:
+ """Detaches an ISO from a server.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.detach_iso(self)
+
+ def change_dns_ptr(self, ip: str, dns_ptr: str | None) -> BoundAction:
+ """Changes the hostname that will appear when getting the hostname belonging to the primary IPs (ipv4 and ipv6) of this server.
+
+ :param ip: str
+ The IP address for which to set the reverse DNS entry
+ :param dns_ptr:
+ Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_dns_ptr(self, ip, dns_ptr)
+
+ def change_protection(
+ self,
+ delete: bool | None = None,
+ rebuild: bool | None = None,
+ ) -> BoundAction:
+ """Changes the protection configuration of the server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param delete: boolean
+ If true, prevents the server from being deleted (currently delete and rebuild attribute needs to have the same value)
+ :param rebuild: boolean
+ If true, prevents the server from being rebuilt (currently delete and rebuild attribute needs to have the same value)
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_protection(self, delete, rebuild)
+
+ def request_console(self) -> RequestConsoleResponse:
+ """Requests credentials for remote access via vnc over websocket to keyboard, monitor, and mouse for a server.
+
+ :return: :class:`RequestConsoleResponse <hcloud.servers.domain.RequestConsoleResponse>`
+ """
+ return self._client.request_console(self)
+
+ def attach_to_network(
+ self,
+ network: Network | BoundNetwork,
+ ip: str | None = None,
+ alias_ips: list[str] | None = None,
+ ) -> BoundAction:
+ """Attaches a server to a network
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param ip: str
+ IP to request to be assigned to this server
+ :param alias_ips: List[str]
+ New alias IPs to set for this server.
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.attach_to_network(self, network, ip, alias_ips)
+
+ def detach_from_network(self, network: Network | BoundNetwork) -> BoundAction:
+ """Detaches a server from a network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.detach_from_network(self, network)
+
+ def change_alias_ips(
+ self,
+ network: Network | BoundNetwork,
+ alias_ips: list[str],
+ ) -> BoundAction:
+ """Changes the alias IPs of an already attached network.
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param alias_ips: List[str]
+ New alias IPs to set for this server.
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_alias_ips(self, network, alias_ips)
+
+ def add_to_placement_group(
+ self,
+ placement_group: PlacementGroup | BoundPlacementGroup,
+ ) -> BoundAction:
+ """Adds a server to a placement group.
+
+ :param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>` or :class:`Network <hcloud.placement_groups.domain.PlacementGroup>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.add_to_placement_group(self, placement_group)
+
+ def remove_from_placement_group(self) -> BoundAction:
+ """Removes a server from a placement group.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.remove_from_placement_group(self)
+
+
+class ServersPageResult(NamedTuple):
+ servers: list[BoundServer]
+ meta: Meta | None
+
+
+class ServersClient(ClientEntityBase):
+ _client: Client
+
+ actions: ResourceActionsClient
+ """Servers scoped actions client
+
+ :type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
+ """
+
+ def __init__(self, client: Client):
+ super().__init__(client)
+ self.actions = ResourceActionsClient(client, "/servers")
+
+ def get_by_id(self, id: int) -> BoundServer:
+ """Get a specific server
+
+ :param id: int
+ :return: :class:`BoundServer <hcloud.servers.client.BoundServer>`
+ """
+ response = self._client.request(url=f"/servers/{id}", method="GET")
+ return BoundServer(self, response["server"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ status: list[str] | None = None,
+ ) -> ServersPageResult:
+ """Get a list of servers from this account
+
+ :param name: str (optional)
+ Can be used to filter servers by their name.
+ :param label_selector: str (optional)
+ Can be used to filter servers by labels. The response will only contain servers matching the label selector.
+ :param status: List[str] (optional)
+ Can be used to filter servers by their status. The response will only contain servers matching the status.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundServer <hcloud.servers.client.BoundServer>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if status is not None:
+ params["status"] = status
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(url="/servers", method="GET", params=params)
+
+ ass_servers = [
+ BoundServer(self, server_data) for server_data in response["servers"]
+ ]
+ return ServersPageResult(ass_servers, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ status: list[str] | None = None,
+ ) -> list[BoundServer]:
+ """Get all servers from this account
+
+ :param name: str (optional)
+ Can be used to filter servers by their name.
+ :param label_selector: str (optional)
+ Can be used to filter servers by labels. The response will only contain servers matching the label selector.
+ :param status: List[str] (optional)
+ Can be used to filter servers by their status. The response will only contain servers matching the status.
+ :return: List[:class:`BoundServer <hcloud.servers.client.BoundServer>`]
+ """
+ return self._iter_pages(
+ self.get_list,
+ name=name,
+ label_selector=label_selector,
+ status=status,
+ )
+
+ def get_by_name(self, name: str) -> BoundServer | None:
+ """Get server by name
+
+ :param name: str
+ Used to get server by name.
+ :return: :class:`BoundServer <hcloud.servers.client.BoundServer>`
+ """
+ return self._get_first_by(name=name)
+
+ # pylint: disable=too-many-branches,too-many-locals
+ def create(
+ self,
+ name: str,
+ server_type: ServerType | BoundServerType,
+ image: Image,
+ ssh_keys: list[SSHKey | BoundSSHKey] | None = None,
+ volumes: list[Volume | BoundVolume] | None = None,
+ firewalls: list[Firewall | BoundFirewall] | None = None,
+ networks: list[Network | BoundNetwork] | None = None,
+ user_data: str | None = None,
+ labels: dict[str, str] | None = None,
+ location: Location | BoundLocation | None = None,
+ datacenter: Datacenter | BoundDatacenter | None = None,
+ start_after_create: bool | None = True,
+ automount: bool | None = None,
+ placement_group: PlacementGroup | BoundPlacementGroup | None = None,
+ public_net: ServerCreatePublicNetwork | None = None,
+ ) -> CreateServerResponse:
+ """Creates a new server. Returns preliminary information about the server as well as an action that covers progress of creation.
+
+ :param name: str
+ Name of the server to create (must be unique per project and a valid hostname as per RFC 1123)
+ :param server_type: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>` or :class:`ServerType <hcloud.server_types.domain.ServerType>`
+ Server type this server should be created with
+ :param image: :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
+ Image the server is created from
+ :param ssh_keys: List[:class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>` or :class:`SSHKey <hcloud.ssh_keys.domain.SSHKey>`] (optional)
+ SSH keys which should be injected into the server at creation time
+ :param volumes: List[:class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`] (optional)
+ Volumes which should be attached to the server at the creation time. Volumes must be in the same location.
+ :param networks: List[:class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`] (optional)
+ Networks which should be attached to the server at the creation time.
+ :param user_data: str (optional)
+ Cloud-Init user data to use during server creation. This field is limited to 32KiB.
+ :param labels: Dict[str,str] (optional)
+ User-defined labels (key-value pairs)
+ :param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>` or :class:`Location <hcloud.locations.domain.Location>`
+ :param datacenter: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>` or :class:`Datacenter <hcloud.datacenters.domain.Datacenter>`
+ :param start_after_create: boolean (optional)
+ Start Server right after creation. Defaults to True.
+ :param automount: boolean (optional)
+ Auto mount volumes after attach.
+ :param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>` or :class:`Location <hcloud.placement_groups.domain.PlacementGroup>`
+ Placement Group where server should be added during creation
+ :param public_net: :class:`ServerCreatePublicNetwork <hcloud.servers.domain.ServerCreatePublicNetwork>`
+ Options to configure the public network of a server on creation
+ :return: :class:`CreateServerResponse <hcloud.servers.domain.CreateServerResponse>`
+ """
+ data: dict[str, Any] = {
+ "name": name,
+ "server_type": server_type.id_or_name,
+ "start_after_create": start_after_create,
+ "image": image.id_or_name,
+ }
+
+ if location is not None:
+ data["location"] = location.id_or_name
+ if datacenter is not None:
+ data["datacenter"] = datacenter.id_or_name
+ if ssh_keys is not None:
+ data["ssh_keys"] = [ssh_key.id_or_name for ssh_key in ssh_keys]
+ if volumes is not None:
+ data["volumes"] = [volume.id for volume in volumes]
+ if networks is not None:
+ data["networks"] = [network.id for network in networks]
+ if firewalls is not None:
+ data["firewalls"] = [{"firewall": firewall.id} for firewall in firewalls]
+ if user_data is not None:
+ data["user_data"] = user_data
+ if labels is not None:
+ data["labels"] = labels
+ if automount is not None:
+ data["automount"] = automount
+ if placement_group is not None:
+ data["placement_group"] = placement_group.id
+
+ if public_net is not None:
+ data_public_net: dict[str, Any] = {
+ "enable_ipv4": public_net.enable_ipv4,
+ "enable_ipv6": public_net.enable_ipv6,
+ }
+ if public_net.ipv4 is not None:
+ data_public_net["ipv4"] = public_net.ipv4.id
+ if public_net.ipv6 is not None:
+ data_public_net["ipv6"] = public_net.ipv6.id
+ data["public_net"] = data_public_net
+
+ response = self._client.request(url="/servers", method="POST", json=data)
+
+ result = CreateServerResponse(
+ server=BoundServer(self, response["server"]),
+ action=BoundAction(self._client.actions, response["action"]),
+ next_actions=[
+ BoundAction(self._client.actions, action)
+ for action in response["next_actions"]
+ ],
+ root_password=response["root_password"],
+ )
+ return result
+
+ def get_actions_list(
+ self,
+ server: Server | BoundServer,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if status is not None:
+ params["status"] = status
+ if sort is not None:
+ params["sort"] = sort
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions",
+ method="GET",
+ params=params,
+ )
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+ return ActionsPageResult(actions, Meta.parse_meta(response))
+
+ def get_actions(
+ self,
+ server: Server | BoundServer,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._iter_pages(
+ self.get_actions_list,
+ server,
+ status=status,
+ sort=sort,
+ )
+
+ def update(
+ self,
+ server: Server | BoundServer,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundServer:
+ """Updates a server. You can update a server’s name and a server’s labels.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param name: str (optional)
+ New name to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundServer <hcloud.servers.client.BoundServer>`
+ """
+ data: dict[str, Any] = {}
+ if name is not None:
+ data.update({"name": name})
+ if labels is not None:
+ data.update({"labels": labels})
+ response = self._client.request(
+ url=f"/servers/{server.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundServer(self, response["server"])
+
+ def get_metrics(
+ self,
+ server: Server | BoundServer,
+ type: MetricsType | list[MetricsType],
+ start: datetime | str,
+ end: datetime | str,
+ step: float | None = None,
+ ) -> GetMetricsResponse:
+ """Get Metrics for a Server.
+
+ :param server: The Server to get the metrics for.
+ :param type: Type of metrics to get.
+ :param start: Start of period to get Metrics for (in ISO-8601 format).
+ :param end: End of period to get Metrics for (in ISO-8601 format).
+ :param step: Resolution of results in seconds.
+ """
+ if not isinstance(type, list):
+ type = [type]
+ if isinstance(start, str):
+ start = isoparse(start)
+ if isinstance(end, str):
+ end = isoparse(end)
+
+ params: dict[str, Any] = {
+ "type": ",".join(type),
+ "start": start.isoformat(),
+ "end": end.isoformat(),
+ }
+ if step is not None:
+ params["step"] = step
+
+ response = self._client.request(
+ url=f"/servers/{server.id}/metrics",
+ method="GET",
+ params=params,
+ )
+ return GetMetricsResponse(
+ metrics=Metrics(**response["metrics"]),
+ )
+
+ def delete(self, server: Server | BoundServer) -> BoundAction:
+ """Deletes a server. This immediately removes the server from your account, and it is no longer accessible.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(url=f"/servers/{server.id}", method="DELETE")
+ return BoundAction(self._client.actions, response["action"])
+
+ def power_off(self, server: Server | BoundServer) -> BoundAction:
+ """Cuts power to the server. This forcefully stops it without giving the server operating system time to gracefully stop
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/poweroff",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def power_on(self, server: Server | BoundServer) -> BoundAction:
+ """Starts a server by turning its power on.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/poweron",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def reboot(self, server: Server | BoundServer) -> BoundAction:
+ """Reboots a server gracefully by sending an ACPI request.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/reboot",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def reset(self, server: Server | BoundServer) -> BoundAction:
+ """Cuts power to a server and starts it again.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/reset",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def shutdown(self, server: Server | BoundServer) -> BoundAction:
+ """Shuts down a server gracefully by sending an ACPI shutdown request.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/shutdown",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def reset_password(self, server: Server | BoundServer) -> ResetPasswordResponse:
+ """Resets the root password. Only works for Linux systems that are running the qemu guest agent.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`ResetPasswordResponse <hcloud.servers.domain.ResetPasswordResponse>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/reset_password",
+ method="POST",
+ )
+ return ResetPasswordResponse(
+ action=BoundAction(self._client.actions, response["action"]),
+ root_password=response["root_password"],
+ )
+
+ def change_type(
+ self,
+ server: Server | BoundServer,
+ server_type: ServerType | BoundServerType,
+ upgrade_disk: bool,
+ ) -> BoundAction:
+ """Changes the type (Cores, RAM and disk sizes) of a server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param server_type: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>` or :class:`ServerType <hcloud.server_types.domain.ServerType>`
+ Server type the server should migrate to
+ :param upgrade_disk: boolean
+ If false, do not upgrade the disk. This allows downgrading the server type later.
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {
+ "server_type": server_type.id_or_name,
+ "upgrade_disk": upgrade_disk,
+ }
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/change_type",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def enable_rescue(
+ self,
+ server: Server | BoundServer,
+ type: str | None = None,
+ ssh_keys: list[str] | None = None,
+ ) -> EnableRescueResponse:
+ """Enable the Hetzner Rescue System for this server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param type: str
+ Type of rescue system to boot (default: linux64)
+ Choices: linux64, linux32, freebsd64
+ :param ssh_keys: List[str]
+ Array of SSH key IDs which should be injected into the rescue system. Only available for types: linux64 and linux32.
+ :return: :class:`EnableRescueResponse <hcloud.servers.domain.EnableRescueResponse>`
+ """
+ data: dict[str, Any] = {"type": type}
+ if ssh_keys is not None:
+ data.update({"ssh_keys": ssh_keys})
+
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/enable_rescue",
+ method="POST",
+ json=data,
+ )
+ return EnableRescueResponse(
+ action=BoundAction(self._client.actions, response["action"]),
+ root_password=response["root_password"],
+ )
+
+ def disable_rescue(self, server: Server | BoundServer) -> BoundAction:
+ """Disables the Hetzner Rescue System for a server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/disable_rescue",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def create_image(
+ self,
+ server: Server | BoundServer,
+ description: str | None = None,
+ type: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> CreateImageResponse:
+ """Creates an image (snapshot) from a server by copying the contents of its disks.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param description: str (optional)
+ Description of the image. If you do not set this we auto-generate one for you.
+ :param type: str (optional)
+ Type of image to create (default: snapshot)
+ Choices: snapshot, backup
+ :param labels: Dict[str, str]
+ User-defined labels (key-value pairs)
+ :return: :class:`CreateImageResponse <hcloud.images.domain.CreateImageResponse>`
+ """
+ data: dict[str, Any] = {}
+ if description is not None:
+ data.update({"description": description})
+
+ if type is not None:
+ data.update({"type": type})
+
+ if labels is not None:
+ data.update({"labels": labels})
+
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/create_image",
+ method="POST",
+ json=data,
+ )
+ return CreateImageResponse(
+ action=BoundAction(self._client.actions, response["action"]),
+ image=BoundImage(self._client.images, response["image"]),
+ )
+
+ def rebuild(
+ self,
+ server: Server | BoundServer,
+ image: Image | BoundImage,
+ *,
+ return_response: bool = False,
+ ) -> RebuildResponse | BoundAction:
+ """Rebuilds a server overwriting its disk with the content of an image, thereby destroying all data on the target server.
+
+ :param server: Server to rebuild
+ :param image: Image to use for the rebuilt server
+ :param return_response: Whether to return the full response or only the action.
+ """
+ data: dict[str, Any] = {"image": image.id_or_name}
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/rebuild",
+ method="POST",
+ json=data,
+ )
+
+ rebuild_response = RebuildResponse(
+ action=BoundAction(self._client.actions, response["action"]),
+ root_password=response.get("root_password"),
+ )
+
+ if not return_response:
+ warnings.warn(
+ "Returning only the 'action' is deprecated, please set the "
+ "'return_response' keyword argument to 'True' to return the full "
+ "rebuild response and update your code accordingly.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return rebuild_response.action
+ return rebuild_response
+
+ def enable_backup(self, server: Server | BoundServer) -> BoundAction:
+ """Enables and configures the automatic daily backup option for the server. Enabling automatic backups will increase the price of the server by 20%.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/enable_backup",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def disable_backup(self, server: Server | BoundServer) -> BoundAction:
+ """Disables the automatic backup option and deletes all existing Backups for a Server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/disable_backup",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def attach_iso(
+ self,
+ server: Server | BoundServer,
+ iso: Iso | BoundIso,
+ ) -> BoundAction:
+ """Attaches an ISO to a server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param iso: :class:`BoundIso <hcloud.isos.client.BoundIso>` or :class:`Server <hcloud.isos.domain.Iso>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"iso": iso.id_or_name}
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/attach_iso",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def detach_iso(self, server: Server | BoundServer) -> BoundAction:
+ """Detaches an ISO from a server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/detach_iso",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_dns_ptr(
+ self,
+ server: Server | BoundServer,
+ ip: str,
+ dns_ptr: str | None,
+ ) -> BoundAction:
+ """Changes the hostname that will appear when getting the hostname belonging to the primary IPs (ipv4 and ipv6) of this server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param ip: str
+ The IP address for which to set the reverse DNS entry
+ :param dns_ptr:
+ Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"ip": ip, "dns_ptr": dns_ptr}
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/change_dns_ptr",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_protection(
+ self,
+ server: Server | BoundServer,
+ delete: bool | None = None,
+ rebuild: bool | None = None,
+ ) -> BoundAction:
+ """Changes the protection configuration of the server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param delete: boolean
+ If true, prevents the server from being deleted (currently delete and rebuild attribute needs to have the same value)
+ :param rebuild: boolean
+ If true, prevents the server from being rebuilt (currently delete and rebuild attribute needs to have the same value)
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {}
+ if delete is not None:
+ data.update({"delete": delete})
+ if rebuild is not None:
+ data.update({"rebuild": rebuild})
+
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/change_protection",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def request_console(self, server: Server | BoundServer) -> RequestConsoleResponse:
+ """Requests credentials for remote access via vnc over websocket to keyboard, monitor, and mouse for a server.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`RequestConsoleResponse <hcloud.servers.domain.RequestConsoleResponse>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/request_console",
+ method="POST",
+ )
+ return RequestConsoleResponse(
+ action=BoundAction(self._client.actions, response["action"]),
+ wss_url=response["wss_url"],
+ password=response["password"],
+ )
+
+ def attach_to_network(
+ self,
+ server: Server | BoundServer,
+ network: Network | BoundNetwork,
+ ip: str | None = None,
+ alias_ips: list[str] | None = None,
+ ) -> BoundAction:
+ """Attaches a server to a network
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param ip: str
+ IP to request to be assigned to this server
+ :param alias_ips: List[str]
+ New alias IPs to set for this server.
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"network": network.id}
+ if ip is not None:
+ data.update({"ip": ip})
+ if alias_ips is not None:
+ data.update({"alias_ips": alias_ips})
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/attach_to_network",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def detach_from_network(
+ self,
+ server: Server | BoundServer,
+ network: Network | BoundNetwork,
+ ) -> BoundAction:
+ """Detaches a server from a network.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"network": network.id}
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/detach_from_network",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def change_alias_ips(
+ self,
+ server: Server | BoundServer,
+ network: Network | BoundNetwork,
+ alias_ips: list[str],
+ ) -> BoundAction:
+ """Changes the alias IPs of an already attached network.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
+ :param alias_ips: List[str]
+ New alias IPs to set for this server.
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"network": network.id, "alias_ips": alias_ips}
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/change_alias_ips",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def add_to_placement_group(
+ self,
+ server: Server | BoundServer,
+ placement_group: PlacementGroup | BoundPlacementGroup,
+ ) -> BoundAction:
+ """Adds a server to a placement group.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>` or :class:`Network <hcloud.placement_groups.domain.PlacementGroup>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"placement_group": str(placement_group.id)}
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/add_to_placement_group",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
+
+ def remove_from_placement_group(self, server: Server | BoundServer) -> BoundAction:
+ """Removes a server from a placement group.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ response = self._client.request(
+ url=f"/servers/{server.id}/actions/remove_from_placement_group",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, response["action"])
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/domain.py
new file mode 100644
index 000000000..0a0d34688
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/servers/domain.py
@@ -0,0 +1,455 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Literal
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from ..datacenters import BoundDatacenter
+ from ..firewalls import BoundFirewall
+ from ..floating_ips import BoundFloatingIP
+ from ..images import BoundImage
+ from ..isos import BoundIso
+ from ..metrics import Metrics
+ from ..networks import BoundNetwork
+ from ..placement_groups import BoundPlacementGroup
+ from ..primary_ips import BoundPrimaryIP, PrimaryIP
+ from ..server_types import BoundServerType
+ from ..volumes import BoundVolume
+ from .client import BoundServer
+
+
+class Server(BaseDomain):
+ """Server Domain
+
+ :param id: int
+ ID of the server
+ :param name: str
+ Name of the server (must be unique per project and a valid hostname as per RFC 1123)
+ :param status: str
+ Status of the server Choices: `running`, `initializing`, `starting`, `stopping`, `off`, `deleting`, `migrating`, `rebuilding`, `unknown`
+ :param created: datetime
+ Point in time when the server was created
+ :param public_net: :class:`PublicNetwork <hcloud.servers.domain.PublicNetwork>`
+ Public network information.
+ :param server_type: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>`
+ :param datacenter: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`
+ :param image: :class:`BoundImage <hcloud.images.client.BoundImage>`, None
+ :param iso: :class:`BoundIso <hcloud.isos.client.BoundIso>`, None
+ :param rescue_enabled: bool
+ True if rescue mode is enabled: Server will then boot into rescue system on next reboot.
+ :param locked: bool
+ True if server has been locked and is not available to user.
+ :param backup_window: str, None
+ Time window (UTC) in which the backup will run, or None if the backups are not enabled
+ :param outgoing_traffic: int, None
+ Outbound Traffic for the current billing period in bytes
+ :param ingoing_traffic: int, None
+ Inbound Traffic for the current billing period in bytes
+ :param included_traffic: int
+ Free Traffic for the current billing period in bytes
+ :param primary_disk_size: int
+ Size of the primary Disk
+ :param protection: dict
+ Protection configuration for the server
+ :param labels: dict
+ User-defined labels (key-value pairs)
+ :param volumes: List[:class:`BoundVolume <hcloud.volumes.client.BoundVolume>`]
+ Volumes assigned to this server.
+ :param private_net: List[:class:`PrivateNet <hcloud.servers.domain.PrivateNet>`]
+ Private networks information.
+ """
+
+ STATUS_RUNNING = "running"
+ """Server Status running"""
+ STATUS_INIT = "initializing"
+ """Server Status initializing"""
+ STATUS_STARTING = "starting"
+ """Server Status starting"""
+ STATUS_STOPPING = "stopping"
+ """Server Status stopping"""
+ STATUS_OFF = "off"
+ """Server Status off"""
+ STATUS_DELETING = "deleting"
+ """Server Status deleting"""
+ STATUS_MIGRATING = "migrating"
+ """Server Status migrating"""
+ STATUS_REBUILDING = "rebuilding"
+ """Server Status rebuilding"""
+ STATUS_UNKNOWN = "unknown"
+ """Server Status unknown"""
+ __slots__ = (
+ "id",
+ "name",
+ "status",
+ "public_net",
+ "server_type",
+ "datacenter",
+ "image",
+ "iso",
+ "rescue_enabled",
+ "locked",
+ "backup_window",
+ "outgoing_traffic",
+ "ingoing_traffic",
+ "included_traffic",
+ "protection",
+ "labels",
+ "volumes",
+ "private_net",
+ "created",
+ "primary_disk_size",
+ "placement_group",
+ )
+
+ # pylint: disable=too-many-locals
+ def __init__(
+ self,
+ id: int,
+ name: str | None = None,
+ status: str | None = None,
+ created: str | None = None,
+ public_net: PublicNetwork | None = None,
+ server_type: BoundServerType | None = None,
+ datacenter: BoundDatacenter | None = None,
+ image: BoundImage | None = None,
+ iso: BoundIso | None = None,
+ rescue_enabled: bool | None = None,
+ locked: bool | None = None,
+ backup_window: str | None = None,
+ outgoing_traffic: int | None = None,
+ ingoing_traffic: int | None = None,
+ included_traffic: int | None = None,
+ protection: dict | None = None,
+ labels: dict[str, str] | None = None,
+ volumes: list[BoundVolume] | None = None,
+ private_net: list[PrivateNet] | None = None,
+ primary_disk_size: int | None = None,
+ placement_group: BoundPlacementGroup | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.status = status
+ self.created = isoparse(created) if created else None
+ self.public_net = public_net
+ self.server_type = server_type
+ self.datacenter = datacenter
+ self.image = image
+ self.iso = iso
+ self.rescue_enabled = rescue_enabled
+ self.locked = locked
+ self.backup_window = backup_window
+ self.outgoing_traffic = outgoing_traffic
+ self.ingoing_traffic = ingoing_traffic
+ self.included_traffic = included_traffic
+ self.protection = protection
+ self.labels = labels
+ self.volumes = volumes
+ self.private_net = private_net
+ self.primary_disk_size = primary_disk_size
+ self.placement_group = placement_group
+
+
+class CreateServerResponse(BaseDomain):
+ """Create Server Response Domain
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>`
+ The created server
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ Shows the progress of the server creation
+ :param next_actions: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ Additional actions like a `start_server` action after the server creation
+ :param root_password: str, None
+ The root password of the server if no SSH-Key was given on server creation
+ """
+
+ __slots__ = ("server", "action", "next_actions", "root_password")
+
+ def __init__(
+ self,
+ server: BoundServer,
+ action: BoundAction,
+ next_actions: list[BoundAction],
+ root_password: str | None,
+ ):
+ self.server = server
+ self.action = action
+ self.next_actions = next_actions
+ self.root_password = root_password
+
+
+class ResetPasswordResponse(BaseDomain):
+ """Reset Password Response Domain
+
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ Shows the progress of the server passwort reset action
+ :param root_password: str
+ The root password of the server
+ """
+
+ __slots__ = ("action", "root_password")
+
+ def __init__(
+ self,
+ action: BoundAction,
+ root_password: str,
+ ):
+ self.action = action
+ self.root_password = root_password
+
+
+class EnableRescueResponse(BaseDomain):
+ """Enable Rescue Response Domain
+
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ Shows the progress of the server enable rescue action
+ :param root_password: str
+ The root password of the server in the rescue mode
+ """
+
+ __slots__ = ("action", "root_password")
+
+ def __init__(
+ self,
+ action: BoundAction,
+ root_password: str,
+ ):
+ self.action = action
+ self.root_password = root_password
+
+
+class RequestConsoleResponse(BaseDomain):
+ """Request Console Response Domain
+
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ Shows the progress of the server request console action
+ :param wss_url: str
+ URL of websocket proxy to use. This includes a token which is valid for a limited time only.
+ :param password: str
+ VNC password to use for this connection. This password only works in combination with a wss_url with valid token.
+ """
+
+ __slots__ = ("action", "wss_url", "password")
+
+ def __init__(
+ self,
+ action: BoundAction,
+ wss_url: str,
+ password: str,
+ ):
+ self.action = action
+ self.wss_url = wss_url
+ self.password = password
+
+
+class RebuildResponse(BaseDomain):
+ """Rebuild Response Domain
+
+ :param action: Shows the progress of the server rebuild action
+ :param root_password: The root password of the server when not using SSH keys
+ """
+
+ __slots__ = ("action", "root_password")
+
+ def __init__(
+ self,
+ action: BoundAction,
+ root_password: str | None,
+ ):
+ self.action = action
+ self.root_password = root_password
+
+
+class PublicNetwork(BaseDomain):
+ """Public Network Domain
+
+ :param ipv4: :class:`IPv4Address <hcloud.servers.domain.IPv4Address>`
+ :param ipv6: :class:`IPv6Network <hcloud.servers.domain.IPv6Network>`
+ :param floating_ips: List[:class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`]
+ :param primary_ipv4: :class:`BoundPrimaryIP <hcloud.primary_ips.domain.BoundPrimaryIP>`
+ :param primary_ipv6: :class:`BoundPrimaryIP <hcloud.primary_ips.domain.BoundPrimaryIP>`
+ :param firewalls: List[:class:`PublicNetworkFirewall <hcloud.servers.client.PublicNetworkFirewall>`]
+ """
+
+ __slots__ = (
+ "ipv4",
+ "ipv6",
+ "floating_ips",
+ "firewalls",
+ "primary_ipv4",
+ "primary_ipv6",
+ )
+
+ def __init__(
+ self,
+ ipv4: IPv4Address,
+ ipv6: IPv6Network,
+ floating_ips: list[BoundFloatingIP],
+ primary_ipv4: BoundPrimaryIP | None,
+ primary_ipv6: BoundPrimaryIP | None,
+ firewalls: list[PublicNetworkFirewall] | None = None,
+ ):
+ self.ipv4 = ipv4
+ self.ipv6 = ipv6
+ self.floating_ips = floating_ips
+ self.firewalls = firewalls
+ self.primary_ipv4 = primary_ipv4
+ self.primary_ipv6 = primary_ipv6
+
+
+class PublicNetworkFirewall(BaseDomain):
+ """Public Network Domain
+
+ :param firewall: :class:`BoundFirewall <hcloud.firewalls.domain.BoundFirewall>`
+ :param status: str
+ """
+
+ __slots__ = ("firewall", "status")
+
+ STATUS_APPLIED = "applied"
+ """Public Network Firewall Status applied"""
+ STATUS_PENDING = "pending"
+ """Public Network Firewall Status pending"""
+
+ def __init__(
+ self,
+ firewall: BoundFirewall,
+ status: str,
+ ):
+ self.firewall = firewall
+ self.status = status
+
+
+class IPv4Address(BaseDomain):
+ """IPv4 Address Domain
+
+ :param ip: str
+ The IPv4 Address
+ :param blocked: bool
+ Determine if the IP is blocked
+ :param dns_ptr: str
+ DNS PTR for the ip
+ """
+
+ __slots__ = ("ip", "blocked", "dns_ptr")
+
+ def __init__(
+ self,
+ ip: str,
+ blocked: bool,
+ dns_ptr: str,
+ ):
+ self.ip = ip
+ self.blocked = blocked
+ self.dns_ptr = dns_ptr
+
+
+class IPv6Network(BaseDomain):
+ """IPv6 Network Domain
+
+ :param ip: str
+ The IPv6 Network as CIDR Notation
+ :param blocked: bool
+ Determine if the Network is blocked
+ :param dns_ptr: dict
+ DNS PTR Records for the Network as Dict
+ :param network: str
+ The network without the network mask
+ :param network_mask: str
+ The network mask
+ """
+
+ __slots__ = ("ip", "blocked", "dns_ptr", "network", "network_mask")
+
+ def __init__(
+ self,
+ ip: str,
+ blocked: bool,
+ dns_ptr: list,
+ ):
+ self.ip = ip
+ self.blocked = blocked
+ self.dns_ptr = dns_ptr
+ ip_parts = self.ip.split("/") # 2001:db8::/64 to 2001:db8:: and 64
+ self.network = ip_parts[0]
+ self.network_mask = ip_parts[1]
+
+
+class PrivateNet(BaseDomain):
+ """PrivateNet Domain
+
+ :param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
+ The network the server is attached to
+ :param ip: str
+ The main IP Address of the server in the Network
+ :param alias_ips: List[str]
+ The alias ips for a server
+ :param mac_address: str
+ The mac address of the interface on the server
+ """
+
+ __slots__ = ("network", "ip", "alias_ips", "mac_address")
+
+ def __init__(
+ self,
+ network: BoundNetwork,
+ ip: str,
+ alias_ips: list[str],
+ mac_address: str,
+ ):
+ self.network = network
+ self.ip = ip
+ self.alias_ips = alias_ips
+ self.mac_address = mac_address
+
+
+class ServerCreatePublicNetwork(BaseDomain):
+ """Server Create Public Network Domain
+
+ :param ipv4: Optional[:class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`]
+ :param ipv6: Optional[:class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`]
+ :param enable_ipv4: bool
+ :param enable_ipv6: bool
+ """
+
+ __slots__ = ("ipv4", "ipv6", "enable_ipv4", "enable_ipv6")
+
+ def __init__(
+ self,
+ ipv4: PrimaryIP | None = None,
+ ipv6: PrimaryIP | None = None,
+ enable_ipv4: bool = True,
+ enable_ipv6: bool = True,
+ ):
+ self.ipv4 = ipv4
+ self.ipv6 = ipv6
+ self.enable_ipv4 = enable_ipv4
+ self.enable_ipv6 = enable_ipv6
+
+
+MetricsType = Literal[
+ "cpu",
+ "disk",
+ "network",
+]
+
+
+class GetMetricsResponse(BaseDomain):
+ """Get a Server Metrics Response Domain
+
+ :param metrics: The Server metrics
+ """
+
+ __slots__ = ("metrics",)
+
+ def __init__(
+ self,
+ metrics: Metrics,
+ ):
+ self.metrics = metrics
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/__init__.py
new file mode 100644
index 000000000..251559060
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/__init__.py
@@ -0,0 +1,4 @@
+from __future__ import annotations
+
+from .client import BoundSSHKey, SSHKeysClient, SSHKeysPageResult # noqa: F401
+from .domain import SSHKey # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/client.py
new file mode 100644
index 000000000..69c1683d7
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/client.py
@@ -0,0 +1,194 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from .domain import SSHKey
+
+if TYPE_CHECKING:
+ from .._client import Client
+
+
+class BoundSSHKey(BoundModelBase, SSHKey):
+ _client: SSHKeysClient
+
+ model = SSHKey
+
+ def update(
+ self,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundSSHKey:
+ """Updates an SSH key. You can update an SSH key name and an SSH key labels.
+
+ :param description: str (optional)
+ New Description to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
+ """
+ return self._client.update(self, name, labels)
+
+ def delete(self) -> bool:
+ """Deletes an SSH key. It cannot be used anymore.
+ :return: boolean
+ """
+ return self._client.delete(self)
+
+
+class SSHKeysPageResult(NamedTuple):
+ ssh_keys: list[BoundSSHKey]
+ meta: Meta | None
+
+
+class SSHKeysClient(ClientEntityBase):
+ _client: Client
+
+ def get_by_id(self, id: int) -> BoundSSHKey:
+ """Get a specific SSH Key by its ID
+
+ :param id: int
+ :return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
+ """
+ response = self._client.request(url=f"/ssh_keys/{id}", method="GET")
+ return BoundSSHKey(self, response["ssh_key"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ fingerprint: str | None = None,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> SSHKeysPageResult:
+ """Get a list of SSH keys from the account
+
+ :param name: str (optional)
+ Can be used to filter SSH keys by their name. The response will only contain the SSH key matching the specified name.
+ :param fingerprint: str (optional)
+ Can be used to filter SSH keys by their fingerprint. The response will only contain the SSH key matching the specified fingerprint.
+ :param label_selector: str (optional)
+ Can be used to filter SSH keys by labels. The response will only contain SSH keys matching the label selector.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if fingerprint is not None:
+ params["fingerprint"] = fingerprint
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(url="/ssh_keys", method="GET", params=params)
+
+ ssh_keys = [
+ BoundSSHKey(self, server_data) for server_data in response["ssh_keys"]
+ ]
+ return SSHKeysPageResult(ssh_keys, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ name: str | None = None,
+ fingerprint: str | None = None,
+ label_selector: str | None = None,
+ ) -> list[BoundSSHKey]:
+ """Get all SSH keys from the account
+
+ :param name: str (optional)
+ Can be used to filter SSH keys by their name. The response will only contain the SSH key matching the specified name.
+ :param fingerprint: str (optional)
+ Can be used to filter SSH keys by their fingerprint. The response will only contain the SSH key matching the specified fingerprint.
+ :param label_selector: str (optional)
+ Can be used to filter SSH keys by labels. The response will only contain SSH keys matching the label selector.
+ :return: List[:class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`]
+ """
+ return self._iter_pages(
+ self.get_list,
+ name=name,
+ fingerprint=fingerprint,
+ label_selector=label_selector,
+ )
+
+ def get_by_name(self, name: str) -> BoundSSHKey | None:
+ """Get ssh key by name
+
+ :param name: str
+ Used to get ssh key by name.
+ :return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
+ """
+ return self._get_first_by(name=name)
+
+ def get_by_fingerprint(self, fingerprint: str) -> BoundSSHKey | None:
+ """Get ssh key by fingerprint
+
+ :param fingerprint: str
+ Used to get ssh key by fingerprint.
+ :return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
+ """
+ return self._get_first_by(fingerprint=fingerprint)
+
+ def create(
+ self,
+ name: str,
+ public_key: str,
+ labels: dict[str, str] | None = None,
+ ) -> BoundSSHKey:
+ """Creates a new SSH key with the given name and public_key.
+
+ :param name: str
+ :param public_key: str
+ Public Key of the SSH Key you want create
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
+ """
+ data: dict[str, Any] = {"name": name, "public_key": public_key}
+ if labels is not None:
+ data["labels"] = labels
+ response = self._client.request(url="/ssh_keys", method="POST", json=data)
+ return BoundSSHKey(self, response["ssh_key"])
+
+ def update(
+ self,
+ ssh_key: SSHKey | BoundSSHKey,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundSSHKey:
+ """Updates an SSH key. You can update an SSH key name and an SSH key labels.
+
+ :param ssh_key: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>` or :class:`SSHKey <hcloud.ssh_keys.domain.SSHKey>`
+ :param name: str (optional)
+ New Description to set
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
+ """
+ data: dict[str, Any] = {}
+ if name is not None:
+ data["name"] = name
+ if labels is not None:
+ data["labels"] = labels
+ response = self._client.request(
+ url=f"/ssh_keys/{ssh_key.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundSSHKey(self, response["ssh_key"])
+
+ def delete(self, ssh_key: SSHKey | BoundSSHKey) -> bool:
+ """Deletes an SSH key. It cannot be used anymore.
+
+ :param ssh_key: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>` or :class:`SSHKey <hcloud.ssh_keys.domain.SSHKey>`
+ :return: True
+ """
+ self._client.request(url=f"/ssh_keys/{ssh_key.id}", method="DELETE")
+ # Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
+ return True
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/domain.py
new file mode 100644
index 000000000..3c880c4d8
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/ssh_keys/domain.py
@@ -0,0 +1,44 @@
+from __future__ import annotations
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain, DomainIdentityMixin
+
+
+class SSHKey(BaseDomain, DomainIdentityMixin):
+ """SSHKey Domain
+
+ :param id: int
+ ID of the SSH key
+ :param name: str
+ Name of the SSH key (must be unique per project)
+ :param fingerprint: str
+ Fingerprint of public key
+ :param public_key: str
+ Public Key
+ :param labels: Dict
+ User-defined labels (key-value pairs)
+ :param created: datetime
+ Point in time when the SSH Key was created
+ """
+
+ __slots__ = ("id", "name", "fingerprint", "public_key", "labels", "created")
+
+ def __init__(
+ self,
+ id: int | None = None,
+ name: str | None = None,
+ fingerprint: str | None = None,
+ public_key: str | None = None,
+ labels: dict[str, str] | None = None,
+ created: str | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.fingerprint = fingerprint
+ self.public_key = public_key
+ self.labels = labels
+ self.created = isoparse(created) if created else None
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/__init__.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/__init__.py
new file mode 100644
index 000000000..dc8ccbb61
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/__init__.py
@@ -0,0 +1,4 @@
+from __future__ import annotations
+
+from .client import BoundVolume, VolumesClient, VolumesPageResult # noqa: F401
+from .domain import CreateVolumeResponse, Volume # noqa: F401
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/client.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/client.py
new file mode 100644
index 000000000..a4709748a
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/client.py
@@ -0,0 +1,458 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from ..actions import ActionsPageResult, BoundAction, ResourceActionsClient
+from ..core import BoundModelBase, ClientEntityBase, Meta
+from ..locations import BoundLocation
+from .domain import CreateVolumeResponse, Volume
+
+if TYPE_CHECKING:
+ from .._client import Client
+ from ..locations import Location
+ from ..servers import BoundServer, Server
+
+
+class BoundVolume(BoundModelBase, Volume):
+ _client: VolumesClient
+
+ model = Volume
+
+ def __init__(self, client: VolumesClient, data: dict, complete: bool = True):
+ location = data.get("location")
+ if location is not None:
+ data["location"] = BoundLocation(client._client.locations, location)
+
+ # pylint: disable=import-outside-toplevel
+ from ..servers import BoundServer
+
+ server = data.get("server")
+ if server is not None:
+ data["server"] = BoundServer(
+ client._client.servers, {"id": server}, complete=False
+ )
+ super().__init__(client, data, complete)
+
+ def get_actions_list(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a volume.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ return self._client.get_actions_list(self, status, sort, page, per_page)
+
+ def get_actions(
+ self,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a volume.
+
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._client.get_actions(self, status, sort)
+
+ def update(
+ self,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundVolume:
+ """Updates the volume properties.
+
+ :param name: str (optional)
+ New volume name
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.update(self, name, labels)
+
+ def delete(self) -> bool:
+ """Deletes a volume. All volume data is irreversibly destroyed. The volume must not be attached to a server and it must not have delete protection enabled.
+
+ :return: boolean
+ """
+ return self._client.delete(self)
+
+ def attach(
+ self,
+ server: Server | BoundServer,
+ automount: bool | None = None,
+ ) -> BoundAction:
+ """Attaches a volume to a server. Works only if the server is in the same location as the volume.
+
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param automount: boolean
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.attach(self, server, automount)
+
+ def detach(self) -> BoundAction:
+ """Detaches a volume from the server it’s attached to. You may attach it to a server again at a later time.
+
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.detach(self)
+
+ def resize(self, size: int) -> BoundAction:
+ """Changes the size of a volume. Note that downsizing a volume is not possible.
+
+ :param size: int
+ New volume size in GB (must be greater than current size)
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.resize(self, size)
+
+ def change_protection(self, delete: bool | None = None) -> BoundAction:
+ """Changes the protection configuration of a volume.
+
+ :param delete: boolean
+ If True, prevents the volume from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ return self._client.change_protection(self, delete)
+
+
+class VolumesPageResult(NamedTuple):
+ volumes: list[BoundVolume]
+ meta: Meta | None
+
+
+class VolumesClient(ClientEntityBase):
+ _client: Client
+
+ actions: ResourceActionsClient
+ """Volumes scoped actions client
+
+ :type: :class:`ResourceActionsClient <hcloud.actions.client.ResourceActionsClient>`
+ """
+
+ def __init__(self, client: Client):
+ super().__init__(client)
+ self.actions = ResourceActionsClient(client, "/volumes")
+
+ def get_by_id(self, id: int) -> BoundVolume:
+ """Get a specific volume by its id
+
+ :param id: int
+ :return: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>`
+ """
+ response = self._client.request(url=f"/volumes/{id}", method="GET")
+ return BoundVolume(self, response["volume"])
+
+ def get_list(
+ self,
+ name: str | None = None,
+ label_selector: str | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ status: list[str] | None = None,
+ ) -> VolumesPageResult:
+ """Get a list of volumes from this account
+
+ :param name: str (optional)
+ Can be used to filter volumes by their name.
+ :param label_selector: str (optional)
+ Can be used to filter volumes by labels. The response will only contain volumes matching the label selector.
+ :param status: List[str] (optional)
+ Can be used to filter volumes by their status. The response will only contain volumes matching the status.
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundVolume <hcloud.volumes.client.BoundVolume>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if name is not None:
+ params["name"] = name
+ if label_selector is not None:
+ params["label_selector"] = label_selector
+ if status is not None:
+ params["status"] = status
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(url="/volumes", method="GET", params=params)
+ volumes = [
+ BoundVolume(self, volume_data) for volume_data in response["volumes"]
+ ]
+ return VolumesPageResult(volumes, Meta.parse_meta(response))
+
+ def get_all(
+ self,
+ label_selector: str | None = None,
+ status: list[str] | None = None,
+ ) -> list[BoundVolume]:
+ """Get all volumes from this account
+
+ :param label_selector:
+ Can be used to filter volumes by labels. The response will only contain volumes matching the label selector.
+ :param status: List[str] (optional)
+ Can be used to filter volumes by their status. The response will only contain volumes matching the status.
+ :return: List[:class:`BoundVolume <hcloud.volumes.client.BoundVolume>`]
+ """
+ return self._iter_pages(
+ self.get_list,
+ label_selector=label_selector,
+ status=status,
+ )
+
+ def get_by_name(self, name: str) -> BoundVolume | None:
+ """Get volume by name
+
+ :param name: str
+ Used to get volume by name.
+ :return: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>`
+ """
+ return self._get_first_by(name=name)
+
+ def create(
+ self,
+ size: int,
+ name: str,
+ labels: str | None = None,
+ location: Location | None = None,
+ server: Server | None = None,
+ automount: bool | None = None,
+ format: str | None = None,
+ ) -> CreateVolumeResponse:
+ """Creates a new volume attached to a server.
+
+ :param size: int
+ Size of the volume in GB
+ :param name: str
+ Name of the volume
+ :param labels: Dict[str,str] (optional)
+ User-defined labels (key-value pairs)
+ :param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>` or :class:`Location <hcloud.locations.domain.Location>`
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param automount: boolean (optional)
+ Auto mount volumes after attach.
+ :param format: str (optional)
+ Format volume after creation. One of: xfs, ext4
+ :return: :class:`CreateVolumeResponse <hcloud.volumes.domain.CreateVolumeResponse>`
+ """
+
+ if size <= 0:
+ raise ValueError("size must be greater than 0")
+
+ if not bool(location) ^ bool(server):
+ raise ValueError("only one of server or location must be provided")
+
+ data: dict[str, Any] = {"name": name, "size": size}
+ if labels is not None:
+ data["labels"] = labels
+ if location is not None:
+ data["location"] = location.id_or_name
+
+ if server is not None:
+ data["server"] = server.id
+ if automount is not None:
+ data["automount"] = automount
+ if format is not None:
+ data["format"] = format
+
+ response = self._client.request(url="/volumes", json=data, method="POST")
+
+ result = CreateVolumeResponse(
+ volume=BoundVolume(self, response["volume"]),
+ action=BoundAction(self._client.actions, response["action"]),
+ next_actions=[
+ BoundAction(self._client.actions, action)
+ for action in response["next_actions"]
+ ],
+ )
+ return result
+
+ def get_actions_list(
+ self,
+ volume: Volume | BoundVolume,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ page: int | None = None,
+ per_page: int | None = None,
+ ) -> ActionsPageResult:
+ """Returns all action objects for a volume.
+
+ :param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :param page: int (optional)
+ Specifies the page to fetch
+ :param per_page: int (optional)
+ Specifies how many results are returned by page
+ :return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
+ """
+ params: dict[str, Any] = {}
+ if status is not None:
+ params["status"] = status
+ if sort is not None:
+ params["sort"] = sort
+ if page is not None:
+ params["page"] = page
+ if per_page is not None:
+ params["per_page"] = per_page
+
+ response = self._client.request(
+ url=f"/volumes/{volume.id}/actions",
+ method="GET",
+ params=params,
+ )
+ actions = [
+ BoundAction(self._client.actions, action_data)
+ for action_data in response["actions"]
+ ]
+ return ActionsPageResult(actions, Meta.parse_meta(response))
+
+ def get_actions(
+ self,
+ volume: Volume | BoundVolume,
+ status: list[str] | None = None,
+ sort: list[str] | None = None,
+ ) -> list[BoundAction]:
+ """Returns all action objects for a volume.
+
+ :param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
+ :param status: List[str] (optional)
+ Response will have only actions with specified statuses. Choices: `running` `success` `error`
+ :param sort: List[str] (optional)
+ Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
+ :return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ """
+ return self._iter_pages(
+ self.get_actions_list,
+ volume,
+ status=status,
+ sort=sort,
+ )
+
+ def update(
+ self,
+ volume: Volume | BoundVolume,
+ name: str | None = None,
+ labels: dict[str, str] | None = None,
+ ) -> BoundVolume:
+ """Updates the volume properties.
+
+ :param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
+ :param name: str (optional)
+ New volume name
+ :param labels: Dict[str, str] (optional)
+ User-defined labels (key-value pairs)
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {}
+ if name is not None:
+ data.update({"name": name})
+ if labels is not None:
+ data.update({"labels": labels})
+ response = self._client.request(
+ url=f"/volumes/{volume.id}",
+ method="PUT",
+ json=data,
+ )
+ return BoundVolume(self, response["volume"])
+
+ def delete(self, volume: Volume | BoundVolume) -> bool:
+ """Deletes a volume. All volume data is irreversibly destroyed. The volume must not be attached to a server and it must not have delete protection enabled.
+
+ :param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
+ :return: boolean
+ """
+ self._client.request(url=f"/volumes/{volume.id}", method="DELETE")
+ return True
+
+ def resize(self, volume: Volume | BoundVolume, size: int) -> BoundAction:
+ """Changes the size of a volume. Note that downsizing a volume is not possible.
+
+ :param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
+ :param size: int
+ New volume size in GB (must be greater than current size)
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data = self._client.request(
+ url=f"/volumes/{volume.id}/actions/resize",
+ json={"size": size},
+ method="POST",
+ )
+ return BoundAction(self._client.actions, data["action"])
+
+ def attach(
+ self,
+ volume: Volume | BoundVolume,
+ server: Server | BoundServer,
+ automount: bool | None = None,
+ ) -> BoundAction:
+ """Attaches a volume to a server. Works only if the server is in the same location as the volume.
+
+ :param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
+ :param automount: boolean
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {"server": server.id}
+ if automount is not None:
+ data["automount"] = automount
+
+ data = self._client.request(
+ url=f"/volumes/{volume.id}/actions/attach",
+ json=data,
+ method="POST",
+ )
+ return BoundAction(self._client.actions, data["action"])
+
+ def detach(self, volume: Volume | BoundVolume) -> BoundAction:
+ """Detaches a volume from the server it’s attached to. You may attach it to a server again at a later time.
+
+ :param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data = self._client.request(
+ url=f"/volumes/{volume.id}/actions/detach",
+ method="POST",
+ )
+ return BoundAction(self._client.actions, data["action"])
+
+ def change_protection(
+ self,
+ volume: Volume | BoundVolume,
+ delete: bool | None = None,
+ ) -> BoundAction:
+ """Changes the protection configuration of a volume.
+
+ :param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
+ :param delete: boolean
+ If True, prevents the volume from being deleted
+ :return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ """
+ data: dict[str, Any] = {}
+ if delete is not None:
+ data.update({"delete": delete})
+
+ response = self._client.request(
+ url=f"/volumes/{volume.id}/actions/change_protection",
+ method="POST",
+ json=data,
+ )
+ return BoundAction(self._client.actions, response["action"])
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/domain.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/domain.py
new file mode 100644
index 000000000..7eb544021
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/vendor/hcloud/volumes/domain.py
@@ -0,0 +1,113 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+try:
+ from dateutil.parser import isoparse
+except ImportError:
+ isoparse = None
+
+from ..core import BaseDomain, DomainIdentityMixin
+
+if TYPE_CHECKING:
+ from ..actions import BoundAction
+ from ..locations import BoundLocation, Location
+ from ..servers import BoundServer, Server
+ from .client import BoundVolume
+
+
+class Volume(BaseDomain, DomainIdentityMixin):
+ """Volume Domain
+
+ :param id: int
+ ID of the Volume
+ :param name: str
+ Name of the Volume
+ :param server: :class:`BoundServer <hcloud.servers.client.BoundServer>`, None
+ Server the Volume is attached to, None if it is not attached at all.
+ :param created: datetime
+ Point in time when the Volume was created
+ :param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
+ Location of the Volume. Volume can only be attached to Servers in the same location.
+ :param size: int
+ Size in GB of the Volume
+ :param linux_device: str
+ Device path on the file system for the Volume
+ :param protection: dict
+ Protection configuration for the Volume
+ :param labels: dict
+ User-defined labels (key-value pairs)
+ :param status: str
+ Current status of the volume Choices: `creating`, `available`
+ :param format: str, None
+ Filesystem of the volume if formatted on creation, None if not formatted on creation.
+ """
+
+ STATUS_CREATING = "creating"
+ """Volume Status creating"""
+ STATUS_AVAILABLE = "available"
+ """Volume Status available"""
+
+ __slots__ = (
+ "id",
+ "name",
+ "server",
+ "location",
+ "size",
+ "linux_device",
+ "format",
+ "protection",
+ "labels",
+ "status",
+ "created",
+ )
+
+ def __init__(
+ self,
+ id: int,
+ name: str | None = None,
+ server: Server | BoundServer | None = None,
+ created: str | None = None,
+ location: Location | BoundLocation | None = None,
+ size: int | None = None,
+ linux_device: str | None = None,
+ format: str | None = None,
+ protection: dict | None = None,
+ labels: dict[str, str] | None = None,
+ status: str | None = None,
+ ):
+ self.id = id
+ self.name = name
+ self.server = server
+ self.created = isoparse(created) if created else None
+ self.location = location
+ self.size = size
+ self.linux_device = linux_device
+ self.format = format
+ self.protection = protection
+ self.labels = labels
+ self.status = status
+
+
+class CreateVolumeResponse(BaseDomain):
+ """Create Volume Response Domain
+
+ :param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>`
+ The created volume
+ :param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
+ The action that shows the progress of the Volume Creation
+ :param next_actions: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
+ List of actions that are performed after the creation, like attaching to a server
+ """
+
+ __slots__ = ("volume", "action", "next_actions")
+
+ def __init__(
+ self,
+ volume: BoundVolume,
+ action: BoundAction,
+ next_actions: list[BoundAction],
+ ):
+ self.volume = volume
+ self.action = action
+ self.next_actions = next_actions
diff --git a/ansible_collections/hetzner/hcloud/plugins/module_utils/version.py b/ansible_collections/hetzner/hcloud/plugins/module_utils/version.py
new file mode 100644
index 000000000..e78c320a2
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/module_utils/version.py
@@ -0,0 +1,3 @@
+from __future__ import annotations
+
+version = "2.5.0" # x-release-please-version
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate.py b/ansible_collections/hetzner/hcloud/plugins/modules/certificate.py
index 0f6dcf0f2..ea39be6ca 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/certificate.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_certificate
+module: certificate
short_description: Create and manage certificates on the Hetzner Cloud.
@@ -39,17 +37,17 @@ options:
certificate:
description:
- Certificate and chain in PEM format, in order so that each record directly certifies the one preceding.
- - Required if certificate does not exist.
+ - Required if certificate does not exist and I(type=uploaded).
type: str
private_key:
description:
- Certificate key in PEM format.
- - Required if certificate does not exist.
+ - Required if certificate does not exist and I(type=uploaded).
type: str
domain_names:
description:
- - Certificate key in PEM format.
- - Required if certificate does not exist.
+ - Domains and subdomains that should be contained in the Certificate issued by Let's Encrypt.
+ - Required if I(type=managed).
type: list
default: [ ]
elements: str
@@ -68,28 +66,37 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Create a basic certificate
- hcloud_certificate:
+ hetzner.hcloud.certificate:
name: my-certificate
- certificate: "ssh-rsa AAAjjk76kgf...Xt"
- private_key: "ssh-rsa AAAjjk76kgf...Xt"
+ certificate: -----BEGIN CERTIFICATE-----...
+ private_key: -----BEGIN PRIVATE KEY-----...
state: present
- name: Create a certificate with labels
- hcloud_certificate:
+ hetzner.hcloud.certificate:
name: my-certificate
- certificate: "ssh-rsa AAAjjk76kgf...Xt"
- private_key: "ssh-rsa AAAjjk76kgf...Xt"
+ certificate: -----BEGIN CERTIFICATE-----...
+ private_key: -----BEGIN PRIVATE KEY-----...
labels:
- key: value
- mylabel: 123
+ key: value
+ mylabel: 123
+ state: present
+
+- name: Create a managed certificate
+ hetzner.hcloud.certificate:
+ name: my-certificate
+ type: managed
+ domain_names:
+ - example.com
+ - www.example.com
state: present
- name: Ensure the certificate is absent (remove if needed)
- hcloud_certificate:
+ hetzner.hcloud.certificate:
name: my-certificate
state: absent
"""
@@ -139,14 +146,17 @@ hcloud_certificate:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.certificates import BoundCertificate
-class AnsibleHcloudCertificate(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_certificate")
- self.hcloud_certificate = None
+
+class AnsibleHCloudCertificate(AnsibleHCloud):
+ represent = "hcloud_certificate"
+
+ hcloud_certificate: BoundCertificate | None = None
def _prepare_result(self):
return {
@@ -158,54 +168,44 @@ class AnsibleHcloudCertificate(Hcloud):
"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
+ "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")
- )
+ 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")
- )
+ self.hcloud_certificate = self.client.certificates.get_by_name(self.module.params.get("name"))
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_certificate(self):
- self.module.fail_on_missing_params(
- required_params=["name"]
- )
+ self.module.fail_on_missing_params(required_params=["name"])
params = {
"name": self.module.params.get("name"),
- "labels": self.module.params.get("labels")
+ "labels": self.module.params.get("labels"),
}
- if self.module.params.get('type') == 'uploaded':
- self.module.fail_on_missing_params(
- required_params=["certificate", "private_key"]
- )
+ if self.module.params.get("type") == "uploaded":
+ self.module.fail_on_missing_params(required_params=["certificate", "private_key"])
params["certificate"] = self.module.params.get("certificate")
params["private_key"] = self.module.params.get("private_key")
if not self.module.check_mode:
try:
self.client.certificates.create(**params)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
else:
- self.module.fail_on_missing_params(
- required_params=["domain_names"]
- )
+ self.module.fail_on_missing_params(required_params=["domain_names"])
params["domain_names"] = self.module.params.get("domain_names")
if not self.module.check_mode:
try:
resp = self.client.certificates.create_managed(**params)
resp.action.wait_until_finished(max_retries=1000)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_certificate()
@@ -214,9 +214,7 @@ class AnsibleHcloudCertificate(Hcloud):
try:
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"]
- )
+ 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()
@@ -226,8 +224,8 @@ class AnsibleHcloudCertificate(Hcloud):
if not self.module.check_mode:
self.hcloud_certificate.update(labels=labels)
self._mark_as_changed()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._get_certificate()
def present_certificate(self):
@@ -243,13 +241,13 @@ class AnsibleHcloudCertificate(Hcloud):
if not self.module.check_mode:
try:
self.client.certificates.delete(self.hcloud_certificate)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self.hcloud_certificate = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
@@ -266,18 +264,18 @@ class AnsibleHcloudCertificate(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name']],
- required_if=[['state', 'present', ['name']]],
+ required_one_of=[["id", "name"]],
+ required_if=[["state", "present", ["name"]]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudCertificate.define_module()
+ module = AnsibleHCloudCertificate.define_module()
- hcloud = AnsibleHcloudCertificate(module)
+ hcloud = AnsibleHCloudCertificate(module)
state = module.params.get("state")
if state == "absent":
hcloud.delete_certificate()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/certificate_info.py
index 855706f1f..e074046fd 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate_info.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/certificate_info.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_certificate_info
+module: certificate_info
short_description: Gather infos about your Hetzner Cloud certificates.
description:
- Gather facts about your Hetzner Cloud certificates.
@@ -20,6 +18,7 @@ options:
id:
description:
- The ID of the certificate you want to get.
+ - The module will fail if the provided ID is invalid.
type: int
name:
description:
@@ -32,11 +31,11 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud certificate infos
- hcloud_certificate_info:
+ hetzner.hcloud.certificate_info:
register: output
- name: Print the gathered infos
debug:
@@ -86,75 +85,76 @@ hcloud_certificate_info:
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.certificates import BoundCertificate
+
+class AnsibleHCloudCertificateInfo(AnsibleHCloud):
+ represent = "hcloud_certificate_info"
-class AnsibleHcloudCertificateInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_certificate_info")
- self.hcloud_certificate_info = None
+ hcloud_certificate_info: list[BoundCertificate] | None = 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
- })
+ 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")
- )]
+ 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")
- )]
+ 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"))
+ label_selector=self.module.params.get("label_selector")
+ )
else:
self.hcloud_certificate_info = self.client.certificates.get_all()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudCertificateInfo.define_module()
+ module = AnsibleHCloudCertificateInfo.define_module()
+ hcloud = AnsibleHCloudCertificateInfo(module)
- hcloud = AnsibleHcloudCertificateInfo(module)
hcloud.get_certificates()
result = hcloud.get_result()
- ansible_info = {
- 'hcloud_certificate_info': result['hcloud_certificate_info']
- }
+ ansible_info = {"hcloud_certificate_info": result["hcloud_certificate_info"]}
module.exit_json(**ansible_info)
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/datacenter_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/datacenter_info.py
new file mode 100644
index 000000000..f6665a6fb
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/datacenter_info.py
@@ -0,0 +1,192 @@
+#!/usr/bin/python
+
+# 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 annotations
+
+DOCUMENTATION = """
+---
+module: datacenter_info
+
+short_description: Gather info about the Hetzner Cloud datacenters.
+
+description:
+ - Gather info about your Hetzner Cloud datacenters.
+
+author:
+ - Lukas Kaemmerling (@LKaemmerling)
+
+options:
+ id:
+ description:
+ - The ID of the datacenter you want to get.
+ - The module will fail if the provided ID is invalid.
+ type: int
+ name:
+ description:
+ - The name of the datacenter you want to get.
+ type: str
+extends_documentation_fragment:
+- hetzner.hcloud.hcloud
+
+"""
+
+EXAMPLES = """
+- name: Gather hcloud datacenter info
+ hetzner.hcloud.datacenter_info:
+ register: output
+
+- name: Print the gathered info
+ debug:
+ var: output
+
+- name: List available server_types in a datacenter
+ block:
+ - name: Gather a hcloud datacenter
+ hetzner.hcloud.datacenter_info:
+ name: fsn1-dc14
+ register: output
+
+ - name: Gather a hcloud datacenter available server_types
+ hetzner.hcloud.server_type_info:
+ id: "{{ item }}"
+ loop: "{{ output.hcloud_datacenter_info[0].server_types.available }}"
+ register: available_server_types
+
+ - name: Print a hcloud datacenter available server_types
+ ansible.builtin.debug:
+ var: available_server_types.results | map(attribute='hcloud_server_type_info')
+"""
+
+RETURN = """
+hcloud_datacenter_info:
+ description:
+ - The datacenter info as list
+ returned: always
+ type: complex
+ contains:
+ id:
+ description: Numeric identifier of the datacenter
+ returned: always
+ type: int
+ sample: 1937415
+ name:
+ description: Name of the datacenter
+ returned: always
+ type: str
+ sample: fsn1-dc8
+ description:
+ description: Detail description of the datacenter
+ returned: always
+ type: str
+ sample: Falkenstein DC 8
+ location:
+ description: Name of the location where the datacenter resides in
+ returned: always
+ type: str
+ sample: fsn1
+ city:
+ description: City of the location
+ returned: always
+ type: str
+ sample: fsn1
+ server_types:
+ description: The Server types the Datacenter can handle
+ returned: always
+ type: dict
+ contains:
+ available:
+ description: IDs of Server types that are supported and for which the Datacenter has enough resources left
+ returned: always
+ type: list
+ elements: int
+ sample: [1, 2, 3]
+ available_for_migration:
+ description: IDs of Server types that are supported and for which the Datacenter has enough resources left
+ returned: always
+ type: list
+ elements: int
+ sample: [1, 2, 3]
+ supported:
+ description: IDs of Server types that are supported in the Datacenter
+ returned: always
+ type: list
+ elements: int
+ sample: [1, 2, 3]
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.datacenters import BoundDatacenter
+
+
+class AnsibleHCloudDatacenterInfo(AnsibleHCloud):
+ represent = "hcloud_datacenter_info"
+
+ hcloud_datacenter_info: list[BoundDatacenter] | None = None
+
+ def _prepare_result(self):
+ tmp = []
+
+ for datacenter in self.hcloud_datacenter_info:
+ if datacenter is None:
+ continue
+
+ tmp.append(
+ {
+ "id": to_native(datacenter.id),
+ "name": to_native(datacenter.name),
+ "description": to_native(datacenter.description),
+ "location": to_native(datacenter.location.name),
+ "server_types": {
+ "available": [o.id for o in datacenter.server_types.available],
+ "available_for_migration": [o.id for o in datacenter.server_types.available_for_migration],
+ "supported": [o.id for o in datacenter.server_types.supported],
+ },
+ }
+ )
+
+ return tmp
+
+ def get_datacenters(self):
+ try:
+ if self.module.params.get("id") is not None:
+ self.hcloud_datacenter_info = [self.client.datacenters.get_by_id(self.module.params.get("id"))]
+ elif self.module.params.get("name") is not None:
+ self.hcloud_datacenter_info = [self.client.datacenters.get_by_name(self.module.params.get("name"))]
+ else:
+ self.hcloud_datacenter_info = self.client.datacenters.get_all()
+
+ 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"},
+ **super().base_module_arguments(),
+ ),
+ supports_check_mode=True,
+ )
+
+
+def main():
+ module = AnsibleHCloudDatacenterInfo.define_module()
+ hcloud = AnsibleHCloudDatacenterInfo(module)
+
+ hcloud.get_datacenters()
+ result = hcloud.get_result()
+
+ ansible_info = {"hcloud_datacenter_info": result["hcloud_datacenter_info"]}
+ module.exit_json(**ansible_info)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_firewall.py b/ansible_collections/hetzner/hcloud/plugins/modules/firewall.py
index 34608977e..3c51b5c0a 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_firewall.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/firewall.py
@@ -1,20 +1,16 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_firewall
-
+module: firewall
short_description: Create and manage firewalls on the Hetzner Cloud.
-
description:
- Create, update and manage firewalls on the Hetzner Cloud.
@@ -24,181 +20,233 @@ author:
options:
id:
description:
- - The ID of the Hetzner Cloud firewall to manage.
- - Only required if no firewall I(name) is given
+ - The ID of the Hetzner Cloud Firewall to manage.
+ - Only required if no firewall O(name) is given.
type: int
name:
description:
- - The Name of the Hetzner Cloud firewall to manage.
- - Only required if no firewall I(id) is given, or a firewall does not exist.
+ - The Name of the Hetzner Cloud Firewall to manage.
+ - Only required if no firewall O(id) is given, or the firewall does not exist.
type: str
labels:
description:
- - User-defined labels (key-value pairs)
+ - User-defined labels (key-value pairs).
type: dict
rules:
description:
- - List of rules the firewall should contain.
+ - List of rules the firewall contain.
type: list
elements: dict
suboptions:
- direction:
+ description:
description:
- - The direction of the firewall rule.
+ - User defined description of this rule.
type: str
- choices: [ in, out ]
- port:
+ direction:
description:
- - The port of the firewall rule.
+ - The direction of the firewall rule.
type: str
+ choices: [in, out]
protocol:
description:
- The protocol of the firewall rule.
type: str
- choices: [ icmp, tcp, udp, esp, gre ]
+ choices: [icmp, tcp, udp, esp, gre]
+ port:
+ description:
+ - The port or port range allowed by this rule.
+ - A port range can be specified by separating two ports with a dash, e.g 1024-5000.
+ - Only used if O(rules[].protocol=tcp) or O(rules[].protocol=udp).
+ type: str
source_ips:
description:
- - List of CIDRs that are allowed within this rule
+ - List of CIDRs that are allowed within this rule.
+ - Use 0.0.0.0/0 to allow all IPv4 addresses and ::/0 to allow all IPv6 addresses.
+ - Only used if O(rules[].direction=in).
type: list
elements: str
- default: [ ]
+ default: []
destination_ips:
description:
- - List of CIDRs that are allowed within this rule
+ - List of CIDRs that are allowed within this rule.
+ - Use 0.0.0.0/0 to allow all IPv4 addresses and ::/0 to allow all IPv6 addresses.
+ - Only used if O(rules[].direction=out).
type: list
elements: str
- default: [ ]
- description:
- description:
- - User defined description of this rule.
- type: str
+ default: []
+ force:
+ description:
+ - Force the deletion of the Firewall when still in use.
+ type: bool
+ default: false
state:
description:
- State of the firewall.
default: present
- choices: [ absent, present ]
+ choices: [absent, present]
type: str
+
extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-'''
+ - hetzner.hcloud.hcloud
+"""
EXAMPLES = """
- name: Create a basic firewall
- hcloud_firewall:
+ hetzner.hcloud.firewall:
name: my-firewall
state: present
- name: Create a firewall with rules
- hcloud_firewall:
+ hetzner.hcloud.firewall:
name: my-firewall
rules:
- - direction: in
- protocol: icmp
- source_ips:
- - 0.0.0.0/0
- - ::/0
- description: allow icmp in
+ - description: allow icmp from everywhere
+ direction: in
+ protocol: icmp
+ source_ips:
+ - 0.0.0.0/0
+ - ::/0
state: present
- name: Create a firewall with labels
- hcloud_firewall:
+ hetzner.hcloud.firewall:
name: my-firewall
labels:
- key: value
- mylabel: 123
+ key: value
+ mylabel: 123
state: present
- name: Ensure the firewall is absent (remove if needed)
- hcloud_firewall:
+ hetzner.hcloud.firewall:
name: my-firewall
state: absent
"""
RETURN = """
hcloud_firewall:
- description: The firewall instance
- returned: Always
- type: complex
+ description: The firewall instance.
+ returned: always
+ type: dict
contains:
id:
- description: Numeric identifier of the firewall
+ description: Numeric identifier of the firewall.
returned: always
type: int
sample: 1937415
name:
- description: Name of the firewall
+ description: Name of the firewall.
returned: always
type: str
- sample: my firewall
+ sample: my-firewall
+ labels:
+ description: User-defined labels (key-value pairs).
+ returned: always
+ type: dict
rules:
- description: List of Rules within this Firewall
+ description: List of rules the firewall contain.
returned: always
- type: complex
+ type: list
+ elements: dict
contains:
+ description:
+ description: User defined description of this rule.
+ type: str
+ returned: always
+ sample: allow http from anywhere
direction:
- description: Direction of the Firewall Rule
+ description: The direction of the firewall rule.
type: str
returned: always
sample: in
protocol:
- description: Protocol of the Firewall Rule
+ description: The protocol of the firewall rule.
type: str
returned: always
- sample: icmp
+ sample: tcp
port:
- description: Port of the Firewall Rule, None/Null if protocol is icmp
+ description: The port or port range allowed by this rule.
type: str
- returned: always
- sample: in
+ returned: if RV(hcloud_firewall.rules[].protocol=tcp) or RV(hcloud_firewall.rules[].protocol=udp)
+ sample: "80"
source_ips:
- description: Source IPs of the Firewall
+ description: List of source CIDRs that are allowed within this rule.
type: list
elements: str
returned: always
+ sample: ["0.0.0.0/0", "::/0"]
destination_ips:
- description: Source IPs of the Firewall
+ description: List of destination CIDRs that are allowed within this rule.
type: list
elements: str
returned: always
- description:
- description: User defined description of the Firewall Rule
- type: str
- returned: always
- labels:
- description: User-defined labels (key-value pairs)
+ sample: []
+ applied_to:
+ description: List of Resources the Firewall is applied to.
returned: always
- type: dict
+ type: list
+ elements: dict
+ contains:
+ type:
+ description: Type of the resource.
+ type: str
+ choices: [server, label_selector]
+ sample: label_selector
+ server:
+ description: ID of the server.
+ type: int
+ sample: 12345
+ label_selector:
+ description: Label selector value.
+ type: str
+ sample: env=prod
+ applied_to_resources:
+ description: List of Resources the Firewall label selector is applied to.
+ returned: if RV(hcloud_firewall.applied_to[].type=label_selector)
+ type: list
+ elements: dict
+ contains:
+ type:
+ description: Type of resource referenced.
+ type: str
+ choices: [server]
+ sample: server
+ server:
+ description: ID of the Server.
+ type: int
+ sample: 12345
"""
-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
import time
-try:
- from hcloud.firewalls.domain import FirewallRule
- from hcloud import APIException
-except ImportError:
- APIException = None
- FirewallRule = None
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import APIException, HCloudException
+from ..module_utils.vendor.hcloud.firewalls import (
+ BoundFirewall,
+ FirewallResource,
+ FirewallRule,
+)
-class AnsibleHcloudFirewall(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_firewall")
- self.hcloud_firewall = None
+class AnsibleHCloudFirewall(AnsibleHCloud):
+ represent = "hcloud_firewall"
+
+ hcloud_firewall: BoundFirewall | None = None
def _prepare_result(self):
return {
"id": to_native(self.hcloud_firewall.id),
"name": to_native(self.hcloud_firewall.name),
"rules": [self._prepare_result_rule(rule) for rule in self.hcloud_firewall.rules],
- "labels": self.hcloud_firewall.labels
+ "labels": self.hcloud_firewall.labels,
+ "applied_to": [self._prepare_result_applied_to(resource) for resource in self.hcloud_firewall.applied_to],
}
- def _prepare_result_rule(self, rule):
+ def _prepare_result_rule(self, rule: FirewallRule):
return {
- "direction": rule.direction,
+ "direction": to_native(rule.direction),
"protocol": to_native(rule.protocol),
"port": to_native(rule.port) if rule.port is not None else None,
"source_ips": [to_native(cidr) for cidr in rule.source_ips],
@@ -206,27 +254,39 @@ class AnsibleHcloudFirewall(Hcloud):
"description": to_native(rule.description) if rule.description is not None else None,
}
+ def _prepare_result_applied_to(self, resource: FirewallResource):
+ result = {
+ "type": to_native(resource.type),
+ "server": to_native(resource.server.id) if resource.server is not None else None,
+ "label_selector": (
+ to_native(resource.label_selector.selector) if resource.label_selector is not None else None
+ ),
+ }
+ if resource.applied_to_resources is not None:
+ result["applied_to_resources"] = [
+ {
+ "type": to_native(item.type),
+ "server": to_native(item.server.id) if item.server is not None else None,
+ }
+ for item in resource.applied_to_resources
+ ]
+ return result
+
def _get_firewall(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_firewall = self.client.firewalls.get_by_id(
- self.module.params.get("id")
- )
+ self.hcloud_firewall = self.client.firewalls.get_by_id(self.module.params.get("id"))
elif self.module.params.get("name") is not None:
- self.hcloud_firewall = self.client.firewalls.get_by_name(
- self.module.params.get("name")
- )
+ self.hcloud_firewall = self.client.firewalls.get_by_name(self.module.params.get("name"))
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_firewall(self):
- self.module.fail_on_missing_params(
- required_params=["name"]
- )
+ self.module.fail_on_missing_params(required_params=["name"])
params = {
"name": self.module.params.get("name"),
- "labels": self.module.params.get("labels")
+ "labels": self.module.params.get("labels"),
}
rules = self.module.params.get("rules")
if rules is not None:
@@ -241,20 +301,20 @@ class AnsibleHcloudFirewall(Hcloud):
)
for rule in rules
]
+
if not self.module.check_mode:
try:
self.client.firewalls.create(**params)
- except Exception as e:
- self.module.fail_json(msg=e.message, **params)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception, params=params)
+
self._mark_as_changed()
self._get_firewall()
def _update_firewall(self):
name = self.module.params.get("name")
if name is not None and self.hcloud_firewall.name != name:
- self.module.fail_on_missing_params(
- required_params=["id"]
- )
+ self.module.fail_on_missing_params(required_params=["id"])
if not self.module.check_mode:
self.hcloud_firewall.update(name=name)
self._mark_as_changed()
@@ -281,6 +341,7 @@ class AnsibleHcloudFirewall(Hcloud):
]
self.hcloud_firewall.set_rules(new_rules)
self._mark_as_changed()
+
self._get_firewall()
def present_firewall(self):
@@ -294,58 +355,76 @@ class AnsibleHcloudFirewall(Hcloud):
self._get_firewall()
if self.hcloud_firewall is not None:
if not self.module.check_mode:
+ if self.hcloud_firewall.applied_to:
+ if self.module.params.get("force"):
+ actions = self.hcloud_firewall.remove_from_resources(self.hcloud_firewall.applied_to)
+ for action in actions:
+ action.wait_until_finished()
+ else:
+ self.module.warn(
+ f"Firewall {self.hcloud_firewall.name} is currently used by "
+ "other resources. You need to unassign the resources before "
+ "deleting the Firewall or use force=true."
+ )
+
retry_count = 0
- while retry_count < 10:
+ while True:
try:
- self.client.firewalls.delete(self.hcloud_firewall)
+ self.hcloud_firewall.delete()
break
- except APIException as e:
- if "is still in use" in e.message:
- retry_count = retry_count + 1
+ except APIException as exception:
+ if "is still in use" in exception.message and retry_count < 10:
+ retry_count += 1
time.sleep(0.5 * retry_count)
- else:
- self.module.fail_json(msg=e.message)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ continue
+ self.fail_json_hcloud(exception)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
+
self._mark_as_changed()
self.hcloud_firewall = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
+ labels={"type": "dict"},
rules=dict(
type="list",
elements="dict",
options=dict(
+ description={"type": "str"},
direction={"type": "str", "choices": ["in", "out"]},
protocol={"type": "str", "choices": ["icmp", "udp", "tcp", "esp", "gre"]},
port={"type": "str"},
source_ips={"type": "list", "elements": "str", "default": []},
destination_ips={"type": "list", "elements": "str", "default": []},
- description={"type": "str"},
),
required_together=[["direction", "protocol"]],
+ required_if=[
+ ["protocol", "udp", ["port"]],
+ ["protocol", "tcp", ["port"]],
+ ],
),
- labels={"type": "dict"},
+ force={"type": "bool", "default": False},
state={
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name']],
- required_if=[['state', 'present', ['name']]],
+ required_one_of=[["id", "name"]],
+ required_if=[["state", "present", ["name"]]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudFirewall.define_module()
+ module = AnsibleHCloudFirewall.define_module()
- hcloud = AnsibleHcloudFirewall(module)
+ hcloud = AnsibleHCloudFirewall(module)
state = module.params.get("state")
if state == "absent":
hcloud.delete_firewall()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/firewall_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/firewall_info.py
new file mode 100644
index 000000000..7e7a623d0
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/firewall_info.py
@@ -0,0 +1,246 @@
+#!/usr/bin/python
+
+# 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 annotations
+
+DOCUMENTATION = """
+---
+module: firewall_info
+short_description: Gather infos about the Hetzner Cloud Firewalls.
+
+description:
+ - Gather facts about your Hetzner Cloud Firewalls.
+
+author:
+ - Jonas Lammler (@jooola)
+
+options:
+ id:
+ description:
+ - The ID of the Firewall you want to get.
+ - The module will fail if the provided ID is invalid.
+ type: int
+ name:
+ description:
+ - The name for the Firewall you want to get.
+ type: str
+ label_selector:
+ description:
+ - The label selector for the Firewalls you want to get.
+ type: str
+
+extends_documentation_fragment:
+ - hetzner.hcloud.hcloud
+"""
+
+EXAMPLES = """
+- name: Gather hcloud Firewall infos
+ hetzner.hcloud.firewall_info:
+ register: output
+
+- name: Print the gathered infos
+ debug:
+ var: output
+"""
+
+RETURN = """
+hcloud_firewall_info:
+ description: List of Firewalls.
+ returned: always
+ type: list
+ elements: dict
+ contains:
+ id:
+ description: Numeric identifier of the firewall.
+ returned: always
+ type: int
+ sample: 1937415
+ name:
+ description: Name of the firewall.
+ returned: always
+ type: str
+ sample: my-firewall
+ labels:
+ description: User-defined labels (key-value pairs).
+ returned: always
+ type: dict
+ rules:
+ description: List of rules the firewall contain.
+ returned: always
+ type: list
+ elements: dict
+ contains:
+ description:
+ description: User defined description of this rule.
+ type: str
+ returned: always
+ sample: allow http from anywhere
+ direction:
+ description: The direction of the firewall rule.
+ type: str
+ returned: always
+ sample: in
+ protocol:
+ description: The protocol of the firewall rule.
+ type: str
+ returned: always
+ sample: tcp
+ port:
+ description: The port or port range allowed by this rule.
+ type: str
+ returned: if RV(hcloud_firewall_info[].rules[].protocol=tcp) or RV(hcloud_firewall_info[].rules[].protocol=udp)
+ sample: "80"
+ source_ips:
+ description: List of source CIDRs that are allowed within this rule.
+ type: list
+ elements: str
+ returned: always
+ sample: ["0.0.0.0/0", "::/0"]
+ destination_ips:
+ description: List of destination CIDRs that are allowed within this rule.
+ type: list
+ elements: str
+ returned: always
+ sample: []
+ applied_to:
+ description: List of Resources the Firewall is applied to.
+ returned: always
+ type: list
+ elements: dict
+ contains:
+ type:
+ description: Type of the resource.
+ type: str
+ choices: [server, label_selector]
+ sample: label_selector
+ server:
+ description: ID of the server.
+ type: int
+ sample: 12345
+ label_selector:
+ description: Label selector value.
+ type: str
+ sample: env=prod
+ applied_to_resources:
+ description: List of Resources the Firewall label selector is applied to.
+ returned: if RV(hcloud_firewall_info[].applied_to[].type=label_selector)
+ type: list
+ elements: dict
+ contains:
+ type:
+ description: Type of resource referenced.
+ type: str
+ choices: [server]
+ sample: server
+ server:
+ description: ID of the Server.
+ type: int
+ sample: 12345
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.firewalls import (
+ BoundFirewall,
+ FirewallResource,
+ FirewallRule,
+)
+
+
+class AnsibleHCloudFirewallInfo(AnsibleHCloud):
+ represent = "hcloud_firewall_info"
+
+ hcloud_firewall_info: list[BoundFirewall] | None = None
+
+ def _prepare_result(self):
+ tmp = []
+
+ for firewall in self.hcloud_firewall_info:
+ if firewall is None:
+ continue
+
+ tmp.append(
+ {
+ "id": to_native(firewall.id),
+ "name": to_native(firewall.name),
+ "labels": firewall.labels,
+ "rules": [self._prepare_result_rule(rule) for rule in firewall.rules],
+ "applied_to": [self._prepare_result_applied_to(resource) for resource in firewall.applied_to],
+ }
+ )
+
+ return tmp
+
+ def _prepare_result_rule(self, rule: FirewallRule):
+ return {
+ "description": to_native(rule.description) if rule.description is not None else None,
+ "direction": to_native(rule.direction),
+ "protocol": to_native(rule.protocol),
+ "port": to_native(rule.port) if rule.port is not None else None,
+ "source_ips": [to_native(cidr) for cidr in rule.source_ips],
+ "destination_ips": [to_native(cidr) for cidr in rule.destination_ips],
+ }
+
+ def _prepare_result_applied_to(self, resource: FirewallResource):
+ result = {
+ "type": to_native(resource.type),
+ "server": to_native(resource.server.id) if resource.server is not None else None,
+ "label_selector": (
+ to_native(resource.label_selector.selector) if resource.label_selector is not None else None
+ ),
+ }
+ if resource.applied_to_resources is not None:
+ result["applied_to_resources"] = [
+ {
+ "type": to_native(item.type),
+ "server": to_native(item.server.id) if item.server is not None else None,
+ }
+ for item in resource.applied_to_resources
+ ]
+ return result
+
+ def get_firewalls(self):
+ try:
+ if self.module.params.get("id") is not None:
+ self.hcloud_firewall_info = [self.client.firewalls.get_by_id(self.module.params.get("id"))]
+ elif self.module.params.get("name") is not None:
+ self.hcloud_firewall_info = [self.client.firewalls.get_by_name(self.module.params.get("name"))]
+ elif self.module.params.get("label_selector") is not None:
+ self.hcloud_firewall_info = self.client.firewalls.get_all(
+ label_selector=self.module.params.get("label_selector")
+ )
+ else:
+ self.hcloud_firewall_info = self.client.firewalls.get_all()
+
+ 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 = AnsibleHCloudFirewallInfo.define_module()
+ hcloud = AnsibleHCloudFirewallInfo(module)
+
+ hcloud.get_firewalls()
+ module.exit_json(**hcloud.get_result())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/firewall_resource.py b/ansible_collections/hetzner/hcloud/plugins/modules/firewall_resource.py
new file mode 100644
index 000000000..207f27092
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/firewall_resource.py
@@ -0,0 +1,243 @@
+#!/usr/bin/python
+
+# 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 annotations
+
+DOCUMENTATION = """
+---
+module: firewall_resource
+short_description: Manage Resources a Hetzner Cloud Firewall is applied to.
+
+description:
+ - Add and Remove Resources a Hetzner Cloud Firewall is applied to.
+
+author:
+ - Jonas Lammler (@jooola)
+
+version_added: 2.5.0
+options:
+ firewall:
+ description:
+ - Name or ID of the Hetzner Cloud Firewall.
+ type: str
+ required: true
+ servers:
+ description:
+ - List of Server Name or ID.
+ type: list
+ elements: str
+ label_selectors:
+ description:
+ - List of Label Selector.
+ type: list
+ elements: str
+ state:
+ description:
+ - State of the firewall resources.
+ default: present
+ choices: [absent, present]
+ type: str
+
+extends_documentation_fragment:
+ - hetzner.hcloud.hcloud
+"""
+
+EXAMPLES = """
+- name: Apply a firewall to a list of servers
+ hetzner.hcloud.firewall_resource:
+ name: my-firewall
+ servers:
+ - my-server
+ - 3456789
+ state: present
+
+- name: Remove a firewall from a list of servers
+ hetzner.hcloud.firewall_resource:
+ name: my-firewall
+ servers:
+ - my-server
+ - 3456789
+ state: absent
+
+- name: Apply a firewall to resources using label selectors
+ hetzner.hcloud.firewall_resource:
+ name: my-firewall
+ label_selectors:
+ - env=prod
+ state: present
+
+- name: Remove a firewall from resources using label selectors
+ hetzner.hcloud.firewall_resource:
+ name: my-firewall
+ label_selectors:
+ - env=prod
+ state: absent
+"""
+
+RETURN = """
+hcloud_firewall_resource:
+ description: The Resources a Hetzner Cloud Firewall is applied to.
+ returned: always
+ type: dict
+ contains:
+ firewall:
+ description:
+ - Name of the Hetzner Cloud Firewall.
+ type: str
+ sample: my-firewall
+ servers:
+ description:
+ - List of Server Name.
+ type: list
+ elements: str
+ sample: [my-server1, my-server2]
+ label_selectors:
+ description:
+ - List of Label Selector.
+ type: list
+ elements: str
+ sample: [env=prod]
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.firewalls import (
+ BoundFirewall,
+ FirewallResource,
+ FirewallResourceLabelSelector,
+)
+from ..module_utils.vendor.hcloud.servers import BoundServer
+
+
+class AnsibleHCloudFirewallResource(AnsibleHCloud):
+ represent = "hcloud_firewall_resource"
+
+ hcloud_firewall_resource: BoundFirewall | None = None
+
+ def _prepare_result(self):
+ servers = []
+ label_selectors = []
+ for resource in self.hcloud_firewall_resource.applied_to:
+ if resource.type == FirewallResource.TYPE_SERVER:
+ servers.append(to_native(resource.server.name))
+ elif resource.type == FirewallResource.TYPE_LABEL_SELECTOR:
+ label_selectors.append(to_native(resource.label_selector.selector))
+
+ return {
+ "firewall": to_native(self.hcloud_firewall_resource.name),
+ "servers": servers,
+ "label_selectors": label_selectors,
+ }
+
+ def _get_firewall(self):
+ try:
+ self.hcloud_firewall_resource = self._client_get_by_name_or_id(
+ "firewalls",
+ self.module.params.get("firewall"),
+ )
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
+
+ def _diff_firewall_resources(self, operator) -> list[FirewallResource]:
+ before = self._prepare_result()
+
+ resources: list[FirewallResource] = []
+
+ servers: list[str] | None = self.module.params.get("servers")
+ if servers:
+ for server_param in servers:
+ try:
+ server: BoundServer = self._client_get_by_name_or_id("servers", server_param)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
+
+ if operator(server.name, before["servers"]):
+ resources.append(
+ FirewallResource(
+ type=FirewallResource.TYPE_SERVER,
+ server=server,
+ )
+ )
+
+ label_selectors = self.module.params.get("label_selectors")
+ if label_selectors:
+ for label_selector in label_selectors:
+ if operator(label_selector, before["label_selectors"]):
+ resources.append(
+ FirewallResource(
+ type=FirewallResource.TYPE_LABEL_SELECTOR,
+ label_selector=FirewallResourceLabelSelector(selector=label_selector),
+ )
+ )
+
+ return resources
+
+ def present_firewall_resources(self):
+ self._get_firewall()
+ resources = self._diff_firewall_resources(
+ lambda to_add, before: to_add not in before,
+ )
+ if resources:
+ if not self.module.check_mode:
+ actions = self.hcloud_firewall_resource.apply_to_resources(resources=resources)
+ for action in actions:
+ action.wait_until_finished()
+
+ self.hcloud_firewall_resource.reload()
+
+ self._mark_as_changed()
+
+ def absent_firewall_resources(self):
+ self._get_firewall()
+ resources = self._diff_firewall_resources(
+ lambda to_remove, before: to_remove in before,
+ )
+ if resources:
+ if not self.module.check_mode:
+ actions = self.hcloud_firewall_resource.remove_from_resources(resources=resources)
+ for action in actions:
+ action.wait_until_finished()
+
+ self.hcloud_firewall_resource.reload()
+
+ self._mark_as_changed()
+
+ @classmethod
+ def define_module(cls):
+ return AnsibleModule(
+ argument_spec={
+ "firewall": {"type": "str", "required": True},
+ "servers": {"type": "list", "elements": "str"},
+ "label_selectors": {"type": "list", "elements": "str"},
+ "state": {
+ "choices": ["absent", "present"],
+ "default": "present",
+ },
+ **super().base_module_arguments(),
+ },
+ required_one_of=[["servers", "label_selectors"]],
+ supports_check_mode=True,
+ )
+
+
+def main():
+ module = AnsibleHCloudFirewallResource.define_module()
+
+ hcloud = AnsibleHCloudFirewallResource(module)
+ state = module.params.get("state")
+ if state == "absent":
+ hcloud.absent_firewall_resources()
+ elif state == "present":
+ hcloud.present_firewall_resources()
+
+ module.exit_json(**hcloud.get_result())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip.py b/ansible_collections/hetzner/hcloud/plugins/modules/floating_ip.py
index 1ee61ea13..e037dd7a1 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/floating_ip.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_floating_ip
+module: floating_ip
short_description: Create and manage cloud Floating IPs on the Hetzner Cloud.
@@ -71,40 +69,36 @@ options:
choices: [ absent, present ]
type: str
-requirements:
- - hcloud-python >= 1.6.0
-
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-
-'''
+"""
EXAMPLES = """
- name: Create a basic IPv4 Floating IP
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: my-floating-ip
home_location: fsn1
type: ipv4
state: present
- name: Create a basic IPv6 Floating IP
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: my-floating-ip
home_location: fsn1
type: ipv6
state: present
- name: Assign a Floating IP to a server
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: my-floating-ip
server: 1234
state: present
- name: Assign a Floating IP to another server
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: my-floating-ip
server: 1234
- force: yes
+ force: true
state: present
- name: Floating IP should be absent
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: my-floating-ip
state: absent
"""
@@ -166,14 +160,17 @@ hcloud_floating_ip:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.floating_ips import BoundFloatingIP
-class AnsibleHcloudFloatingIP(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_floating_ip")
- self.hcloud_floating_ip = None
+class AnsibleHCloudFloatingIP(AnsibleHCloud):
+ represent = "hcloud_floating_ip"
+
+ hcloud_floating_ip: BoundFloatingIP | None = None
def _prepare_result(self):
server = None
@@ -195,20 +192,14 @@ class AnsibleHcloudFloatingIP(Hcloud):
def _get_floating_ip(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_floating_ip = self.client.floating_ips.get_by_id(
- self.module.params.get("id")
- )
+ self.hcloud_floating_ip = self.client.floating_ips.get_by_id(self.module.params.get("id"))
else:
- self.hcloud_floating_ip = self.client.floating_ips.get_by_name(
- self.module.params.get("name")
- )
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ self.hcloud_floating_ip = self.client.floating_ips.get_by_name(self.module.params.get("name"))
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_floating_ip(self):
- self.module.fail_on_missing_params(
- required_params=["type"]
- )
+ self.module.fail_on_missing_params(required_params=["type"])
try:
params = {
"description": self.module.params.get("description"),
@@ -216,13 +207,9 @@ class AnsibleHcloudFloatingIP(Hcloud):
"name": self.module.params.get("name"),
}
if self.module.params.get("home_location") is not None:
- params["home_location"] = self.client.locations.get_by_name(
- self.module.params.get("home_location")
- )
+ params["home_location"] = self.client.locations.get_by_name(self.module.params.get("home_location"))
elif self.module.params.get("server") is not None:
- params["server"] = self.client.servers.get_by_name(
- self.module.params.get("server")
- )
+ params["server"] = self.client.servers.get_by_name(self.module.params.get("server"))
else:
self.module.fail_json(msg="one of the following is required: home_location, server")
@@ -235,8 +222,8 @@ class AnsibleHcloudFloatingIP(Hcloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None:
self.hcloud_floating_ip.change_protection(delete=delete_protection).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_floating_ip()
@@ -258,21 +245,18 @@ class AnsibleHcloudFloatingIP(Hcloud):
if server is not None and self.hcloud_floating_ip.server is not None:
if self.module.params.get("force") and server != self.hcloud_floating_ip.server.name:
if not self.module.check_mode:
- self.hcloud_floating_ip.assign(
- self.client.servers.get_by_name(server)
- )
+ self.hcloud_floating_ip.assign(self.client.servers.get_by_name(server))
self._mark_as_changed()
elif server != self.hcloud_floating_ip.server.name:
self.module.warn(
- "Floating IP is already assigned to another server %s. You need to unassign the Floating IP or use force=yes."
- % self.hcloud_floating_ip.server.name
+ "Floating IP is already assigned to another server "
+ f"{self.hcloud_floating_ip.server.name}. You need to "
+ "unassign the Floating IP or use force=true."
)
self._mark_as_changed()
elif server is not None and self.hcloud_floating_ip.server is None:
if not self.module.check_mode:
- self.hcloud_floating_ip.assign(
- self.client.servers.get_by_name(server)
- )
+ self.hcloud_floating_ip.assign(self.client.servers.get_by_name(server))
self._mark_as_changed()
elif server is None and self.hcloud_floating_ip.server is not None:
if not self.module.check_mode:
@@ -286,8 +270,8 @@ class AnsibleHcloudFloatingIP(Hcloud):
self._mark_as_changed()
self._get_floating_ip()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def present_floating_ip(self):
self._get_floating_ip()
@@ -305,16 +289,17 @@ class AnsibleHcloudFloatingIP(Hcloud):
self.client.floating_ips.delete(self.hcloud_floating_ip)
else:
self.module.warn(
- "Floating IP is currently assigned to server %s. You need to unassign the Floating IP or use force=yes."
- % self.hcloud_floating_ip.server.name
+ "Floating IP is currently assigned to server "
+ f"{self.hcloud_floating_ip.server.name}. You need to "
+ "unassign the Floating IP or use force=true."
)
self._mark_as_changed()
self.hcloud_floating_ip = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
@@ -330,18 +315,18 @@ class AnsibleHcloudFloatingIP(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name']],
- mutually_exclusive=[['home_location', 'server']],
+ required_one_of=[["id", "name"]],
+ mutually_exclusive=[["home_location", "server"]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudFloatingIP.define_module()
+ module = AnsibleHCloudFloatingIP.define_module()
- hcloud = AnsibleHcloudFloatingIP(module)
+ hcloud = AnsibleHCloudFloatingIP(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_floating_ip()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/floating_ip_info.py
index 2ec359600..663d29622 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_info.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/floating_ip_info.py
@@ -1,23 +1,19 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_floating_ip_info
+module: floating_ip_info
short_description: Gather infos about the Hetzner Cloud Floating IPs.
description:
- Gather facts about your Hetzner Cloud Floating IPs.
- - This module was called C(hcloud_floating_ip_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_floating_ip_facts).
- Note that the M(hetzner.hcloud.hcloud_floating_ip_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_floating_ip_info)!
author:
- Lukas Kaemmerling (@LKaemmerling)
@@ -26,7 +22,12 @@ options:
id:
description:
- The ID of the Floating IP you want to get.
+ - The module will fail if the provided ID is invalid.
type: int
+ name:
+ description:
+ - The name for the Floating IP you want to get.
+ type: str
label_selector:
description:
- The label selector for the Floating IP you want to get.
@@ -34,11 +35,11 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud Floating ip infos
- hcloud_floating_ip_info:
+ hetzner.hcloud.floating_ip_info:
register: output
- name: Print the gathered infos
debug:
@@ -99,14 +100,17 @@ hcloud_floating_ip_info:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.floating_ips import BoundFloatingIP
-class AnsibleHcloudFloatingIPInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_floating_ip_info")
- self.hcloud_floating_ip_info = None
+class AnsibleHCloudFloatingIPInfo(AnsibleHCloud):
+ represent = "hcloud_floating_ip_info"
+
+ hcloud_floating_ip_info: list[BoundFloatingIP] | None = None
def _prepare_result(self):
tmp = []
@@ -116,69 +120,60 @@ class AnsibleHcloudFloatingIPInfo(Hcloud):
server_name = None
if floating_ip.server is not None:
server_name = floating_ip.server.name
- tmp.append({
- "id": to_native(floating_ip.id),
- "name": to_native(floating_ip.name),
- "description": to_native(floating_ip.description),
- "ip": to_native(floating_ip.ip),
- "type": to_native(floating_ip.type),
- "server": to_native(server_name),
- "home_location": to_native(floating_ip.home_location.name),
- "labels": floating_ip.labels,
- "delete_protection": floating_ip.protection["delete"],
- })
+ tmp.append(
+ {
+ "id": to_native(floating_ip.id),
+ "name": to_native(floating_ip.name),
+ "description": to_native(floating_ip.description),
+ "ip": to_native(floating_ip.ip),
+ "type": to_native(floating_ip.type),
+ "server": to_native(server_name),
+ "home_location": to_native(floating_ip.home_location.name),
+ "labels": floating_ip.labels,
+ "delete_protection": floating_ip.protection["delete"],
+ }
+ )
return tmp
def get_floating_ips(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_floating_ip_info = [self.client.floating_ips.get_by_id(
- self.module.params.get("id")
- )]
+ self.hcloud_floating_ip_info = [self.client.floating_ips.get_by_id(self.module.params.get("id"))]
+ elif self.module.params.get("name") is not None:
+ self.hcloud_floating_ip_info = [self.client.floating_ips.get_by_name(self.module.params.get("name"))]
elif self.module.params.get("label_selector") is not None:
self.hcloud_floating_ip_info = self.client.floating_ips.get_all(
- label_selector=self.module.params.get("label_selector"))
+ label_selector=self.module.params.get("label_selector")
+ )
else:
self.hcloud_floating_ip_info = self.client.floating_ips.get_all()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
+ name={"type": "str"},
label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudFloatingIPInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_floating_ip_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_floating_ip_facts' module has been renamed to 'hcloud_floating_ip_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudFloatingIPInfo(module)
+ module = AnsibleHCloudFloatingIPInfo.define_module()
+ hcloud = AnsibleHCloudFloatingIPInfo(module)
hcloud.get_floating_ips()
result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_floating_ip_facts': result['hcloud_floating_ip_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_floating_ip_info': result['hcloud_floating_ip_info']
- }
- module.exit_json(**ansible_info)
+
+ ansible_info = {"hcloud_floating_ip_info": result["hcloud_floating_ip_info"]}
+ module.exit_json(**ansible_info)
if __name__ == "__main__":
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_facts.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_facts.py
deleted file mode 100644
index 8cebabf8c..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_facts.py
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/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_datacenter_info
-
-short_description: Gather info about the Hetzner Cloud datacenters.
-
-description:
- - Gather info about your Hetzner Cloud datacenters.
- - This module was called C(hcloud_datacenter_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_datacenter_facts).
- Note that the M(hetzner.hcloud.hcloud_datacenter_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_datacenter_info)!
-
-author:
- - Lukas Kaemmerling (@LKaemmerling)
-
-options:
- id:
- description:
- - The ID of the datacenter you want to get.
- type: int
- name:
- description:
- - The name of the datacenter you want to get.
- type: str
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud datacenter info
- hcloud_datacenter_info:
- register: output
-- name: Print the gathered info
- debug:
- var: output
-"""
-
-RETURN = """
-hcloud_datacenter_info:
- description:
- - The datacenter info as list
- - This module was called C(hcloud_datacenter_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_datacenter_facts).
- Note that the M(hetzner.hcloud.hcloud_datacenter_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_datacenter_info)!
- returned: always
- type: complex
- contains:
- id:
- description: Numeric identifier of the datacenter
- returned: always
- type: int
- sample: 1937415
- name:
- description: Name of the datacenter
- returned: always
- type: str
- sample: fsn1-dc8
- description:
- description: Detail description of the datacenter
- returned: always
- type: str
- sample: Falkenstein DC 8
- location:
- description: Name of the location where the datacenter resides in
- returned: always
- type: str
- sample: fsn1
- city:
- description: City of the location
- returned: always
- type: str
- sample: fsn1
-"""
-
-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
-
-
-class AnsibleHcloudDatacenterInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_datacenter_info")
- self.hcloud_datacenter_info = None
-
- def _prepare_result(self):
- tmp = []
-
- for datacenter in self.hcloud_datacenter_info:
- if datacenter is not None:
- tmp.append({
- "id": to_native(datacenter.id),
- "name": to_native(datacenter.name),
- "description": to_native(datacenter.description),
- "location": to_native(datacenter.location.name)
- })
-
- return tmp
-
- def get_datacenters(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_datacenter_info = [self.client.datacenters.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("name") is not None:
- self.hcloud_datacenter_info = [self.client.datacenters.get_by_name(
- self.module.params.get("name")
- )]
- else:
- self.hcloud_datacenter_info = self.client.datacenters.get_all()
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- name={"type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudDatacenterInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_datacenter_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_datacenter_facts' module has been renamed to 'hcloud_datacenter_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
- hcloud = AnsibleHcloudDatacenterInfo(module)
-
- hcloud.get_datacenters()
- result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_datacenter_facts': result['hcloud_datacenter_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_datacenter_info': result['hcloud_datacenter_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_info.py
deleted file mode 100644
index 8cebabf8c..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_info.py
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/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_datacenter_info
-
-short_description: Gather info about the Hetzner Cloud datacenters.
-
-description:
- - Gather info about your Hetzner Cloud datacenters.
- - This module was called C(hcloud_datacenter_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_datacenter_facts).
- Note that the M(hetzner.hcloud.hcloud_datacenter_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_datacenter_info)!
-
-author:
- - Lukas Kaemmerling (@LKaemmerling)
-
-options:
- id:
- description:
- - The ID of the datacenter you want to get.
- type: int
- name:
- description:
- - The name of the datacenter you want to get.
- type: str
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud datacenter info
- hcloud_datacenter_info:
- register: output
-- name: Print the gathered info
- debug:
- var: output
-"""
-
-RETURN = """
-hcloud_datacenter_info:
- description:
- - The datacenter info as list
- - This module was called C(hcloud_datacenter_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_datacenter_facts).
- Note that the M(hetzner.hcloud.hcloud_datacenter_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_datacenter_info)!
- returned: always
- type: complex
- contains:
- id:
- description: Numeric identifier of the datacenter
- returned: always
- type: int
- sample: 1937415
- name:
- description: Name of the datacenter
- returned: always
- type: str
- sample: fsn1-dc8
- description:
- description: Detail description of the datacenter
- returned: always
- type: str
- sample: Falkenstein DC 8
- location:
- description: Name of the location where the datacenter resides in
- returned: always
- type: str
- sample: fsn1
- city:
- description: City of the location
- returned: always
- type: str
- sample: fsn1
-"""
-
-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
-
-
-class AnsibleHcloudDatacenterInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_datacenter_info")
- self.hcloud_datacenter_info = None
-
- def _prepare_result(self):
- tmp = []
-
- for datacenter in self.hcloud_datacenter_info:
- if datacenter is not None:
- tmp.append({
- "id": to_native(datacenter.id),
- "name": to_native(datacenter.name),
- "description": to_native(datacenter.description),
- "location": to_native(datacenter.location.name)
- })
-
- return tmp
-
- def get_datacenters(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_datacenter_info = [self.client.datacenters.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("name") is not None:
- self.hcloud_datacenter_info = [self.client.datacenters.get_by_name(
- self.module.params.get("name")
- )]
- else:
- self.hcloud_datacenter_info = self.client.datacenters.get_all()
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- name={"type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudDatacenterInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_datacenter_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_datacenter_facts' module has been renamed to 'hcloud_datacenter_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
- hcloud = AnsibleHcloudDatacenterInfo(module)
-
- hcloud.get_datacenters()
- result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_datacenter_facts': result['hcloud_datacenter_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_datacenter_info': result['hcloud_datacenter_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_facts.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_facts.py
deleted file mode 100644
index 2ec359600..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_facts.py
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/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_floating_ip_info
-
-short_description: Gather infos about the Hetzner Cloud Floating IPs.
-
-description:
- - Gather facts about your Hetzner Cloud Floating IPs.
- - This module was called C(hcloud_floating_ip_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_floating_ip_facts).
- Note that the M(hetzner.hcloud.hcloud_floating_ip_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_floating_ip_info)!
-
-author:
- - Lukas Kaemmerling (@LKaemmerling)
-
-options:
- id:
- description:
- - The ID of the Floating IP you want to get.
- type: int
- label_selector:
- description:
- - The label selector for the Floating IP you want to get.
- type: str
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud Floating ip infos
- hcloud_floating_ip_info:
- register: output
-- name: Print the gathered infos
- debug:
- var: output
-"""
-
-RETURN = """
-hcloud_floating_ip_info:
- description: The Floating ip infos as list
- returned: always
- type: complex
- contains:
- id:
- description: Numeric identifier of the Floating IP
- returned: always
- type: int
- sample: 1937415
- name:
- description: Name of the Floating IP
- returned: Always
- type: str
- sample: my-floating-ip
- version_added: "0.1.0"
- description:
- description: Description of the Floating IP
- returned: always
- type: str
- sample: Falkenstein DC 8
- ip:
- description: IP address of the Floating IP
- returned: always
- type: str
- sample: 131.232.99.1
- type:
- description: Type of the Floating IP
- returned: always
- type: str
- sample: ipv4
- server:
- description: Name of the server where the Floating IP is assigned to.
- returned: always
- type: str
- sample: my-server
- home_location:
- description: Location the Floating IP was created in
- returned: always
- type: str
- sample: fsn1
- delete_protection:
- description: True if the Floating IP is protected for deletion
- returned: always
- type: bool
- version_added: "0.1.0"
- 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
-
-
-class AnsibleHcloudFloatingIPInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_floating_ip_info")
- self.hcloud_floating_ip_info = None
-
- def _prepare_result(self):
- tmp = []
-
- for floating_ip in self.hcloud_floating_ip_info:
- if floating_ip is not None:
- server_name = None
- if floating_ip.server is not None:
- server_name = floating_ip.server.name
- tmp.append({
- "id": to_native(floating_ip.id),
- "name": to_native(floating_ip.name),
- "description": to_native(floating_ip.description),
- "ip": to_native(floating_ip.ip),
- "type": to_native(floating_ip.type),
- "server": to_native(server_name),
- "home_location": to_native(floating_ip.home_location.name),
- "labels": floating_ip.labels,
- "delete_protection": floating_ip.protection["delete"],
- })
-
- return tmp
-
- def get_floating_ips(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_floating_ip_info = [self.client.floating_ips.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("label_selector") is not None:
- self.hcloud_floating_ip_info = self.client.floating_ips.get_all(
- label_selector=self.module.params.get("label_selector"))
- else:
- self.hcloud_floating_ip_info = self.client.floating_ips.get_all()
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudFloatingIPInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_floating_ip_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_floating_ip_facts' module has been renamed to 'hcloud_floating_ip_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudFloatingIPInfo(module)
-
- hcloud.get_floating_ips()
- result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_floating_ip_facts': result['hcloud_floating_ip_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_floating_ip_info': result['hcloud_floating_ip_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_facts.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_facts.py
deleted file mode 100644
index 8acd8846a..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_facts.py
+++ /dev/null
@@ -1,219 +0,0 @@
-#!/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_image_info
-
-short_description: Gather infos about your Hetzner Cloud images.
-
-
-description:
- - Gather infos about your Hetzner Cloud images.
- - This module was called C(hcloud_location_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_location_facts).
- Note that the M(hetzner.hcloud.hcloud_image_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_image_info)!
-
-author:
- - Lukas Kaemmerling (@LKaemmerling)
-
-options:
- id:
- description:
- - The ID of the image you want to get.
- type: int
- name:
- description:
- - The name of the image you want to get.
- type: str
- label_selector:
- description:
- - The label selector for the images you want to get.
- type: str
- type:
- description:
- - The type for the images you want to get.
- default: system
- choices: [ system, snapshot, backup ]
- type: str
- architecture:
- description:
- - The architecture for the images you want to get.
- type: str
- choices: [ x86, arm ]
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud image infos
- hcloud_image_info:
- register: output
-
-- name: Print the gathered infos
- debug:
- var: output
-"""
-
-RETURN = """
-hcloud_image_info:
- description: The image infos as list
- returned: always
- type: complex
- contains:
- id:
- description: Numeric identifier of the image
- returned: always
- type: int
- sample: 1937415
- type:
- description: Type of the image
- returned: always
- type: str
- sample: system
- status:
- description: Status of the image
- returned: always
- type: str
- sample: available
- name:
- description: Name of the image
- returned: always
- type: str
- sample: ubuntu-18.04
- description:
- description: Detail description of the image
- returned: always
- type: str
- sample: Ubuntu 18.04 Standard 64 bit
- os_flavor:
- description: OS flavor of the image
- returned: always
- type: str
- sample: ubuntu
- os_version:
- description: OS version of the image
- returned: always
- type: str
- sample: 18.04
- architecture:
- description: Image is compatible with this architecture
- returned: always
- type: str
- sample: x86
- 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
-
-
-class AnsibleHcloudImageInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_image_info")
- self.hcloud_image_info = None
-
- def _prepare_result(self):
- tmp = []
-
- for image in self.hcloud_image_info:
- if image is not None:
- tmp.append({
- "id": to_native(image.id),
- "status": to_native(image.status),
- "type": to_native(image.type),
- "name": to_native(image.name),
- "description": to_native(image.description),
- "os_flavor": to_native(image.os_flavor),
- "os_version": to_native(image.os_version),
- "architecture": to_native(image.architecture),
- "labels": image.labels,
- })
- return tmp
-
- def get_images(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_image_info = [self.client.images.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("name") is not None and self.module.params.get("architecture") is not None:
- self.hcloud_image_info = [self.client.images.get_by_name_and_architecture(
- self.module.params.get("name"),
- self.module.params.get("architecture")
- )]
- elif self.module.params.get("name") is not None:
- self.hcloud_image_info = [self.client.images.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
-
- image_type = self.module.params.get("type")
- if image_type:
- params["type"] = image_type
-
- architecture = self.module.params.get("architecture")
- if architecture:
- params["architecture"] = architecture
-
- self.hcloud_image_info = self.client.images.get_all(**params)
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- name={"type": "str"},
- label_selector={"type": "str"},
- type={"choices": ["system", "snapshot", "backup"], "default": "system", "type": "str"},
- architecture={"choices": ["x86", "arm"], "type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudImageInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_image_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_image_facts' module has been renamed to 'hcloud_image_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudImageInfo(module)
- hcloud.get_images()
- result = hcloud.get_result()
-
- if is_old_facts:
- ansible_info = {
- 'hcloud_imagen_facts': result['hcloud_image_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_image_info': result['hcloud_image_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_facts.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_facts.py
deleted file mode 100644
index 623c6ab68..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_facts.py
+++ /dev/null
@@ -1,159 +0,0 @@
-#!/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_location_info
-
-short_description: Gather infos about your Hetzner Cloud locations.
-
-
-description:
- - Gather infos about your Hetzner Cloud locations.
- - This module was called C(hcloud_location_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_location_facts).
- Note that the M(hetzner.hcloud.hcloud_location_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_location_info)!
-
-author:
- - Lukas Kaemmerling (@LKaemmerling)
-
-options:
- id:
- description:
- - The ID of the location you want to get.
- type: int
- name:
- description:
- - The name of the location you want to get.
- type: str
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud location infos
- hcloud_location_info:
- register: output
-
-- name: Print the gathered infos
- debug:
- var: output
-"""
-
-RETURN = """
-hcloud_location_info:
- description: The location infos as list
- returned: always
- type: complex
- contains:
- id:
- description: Numeric identifier of the location
- returned: always
- type: int
- sample: 1937415
- name:
- description: Name of the location
- returned: always
- type: str
- sample: fsn1
- description:
- description: Detail description of the location
- returned: always
- type: str
- sample: Falkenstein DC Park 1
- country:
- description: Country code of the location
- returned: always
- type: str
- sample: DE
- city:
- description: City of the location
- returned: always
- type: str
- sample: Falkenstein
-"""
-
-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
-
-
-class AnsibleHcloudLocationInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_location_info")
- self.hcloud_location_info = None
-
- def _prepare_result(self):
- tmp = []
-
- for location in self.hcloud_location_info:
- if location is not None:
- tmp.append({
- "id": to_native(location.id),
- "name": to_native(location.name),
- "description": to_native(location.description),
- "city": to_native(location.city),
- "country": to_native(location.country)
- })
- return tmp
-
- def get_locations(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_location_info = [self.client.locations.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("name") is not None:
- self.hcloud_location_info = [self.client.locations.get_by_name(
- self.module.params.get("name")
- )]
- else:
- self.hcloud_location_info = self.client.locations.get_all()
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- name={"type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudLocationInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_location_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_location_info' module has been renamed to 'hcloud_location_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudLocationInfo(module)
- hcloud.get_locations()
- result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_location_facts': result['hcloud_location_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_location_info': result['hcloud_location_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_facts.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_facts.py
deleted file mode 100644
index 102ceec0d..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_facts.py
+++ /dev/null
@@ -1,244 +0,0 @@
-#!/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_server_info
-
-short_description: Gather infos about your Hetzner Cloud servers.
-
-
-description:
- - Gather infos about your Hetzner Cloud servers.
- - This module was called C(hcloud_server_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_server_facts).
- Note that the M(hetzner.hcloud.hcloud_server_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_server_info)!
-
-author:
- - Lukas Kaemmerling (@LKaemmerling)
-
-options:
- id:
- description:
- - The ID of the server you want to get.
- type: int
- name:
- description:
- - The name of the server you want to get.
- type: str
- label_selector:
- description:
- - The label selector for the server you want to get.
- type: str
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud server infos
- hcloud_server_info:
- register: output
-
-- name: Print the gathered infos
- debug:
- var: output.hcloud_server_info
-"""
-
-RETURN = """
-hcloud_server_info:
- description: The server infos as list
- returned: always
- type: complex
- contains:
- id:
- description: Numeric identifier of the server
- returned: always
- type: int
- sample: 1937415
- name:
- description: Name of the server
- returned: always
- type: str
- sample: my-server
- status:
- description: Status of the server
- returned: always
- type: str
- sample: running
- server_type:
- description: Name of the server type of the server
- returned: always
- type: str
- sample: cx11
- ipv4_address:
- description: Public IPv4 address of the server
- returned: always
- type: str
- sample: 116.203.104.109
- ipv6:
- description: IPv6 network of the server
- returned: always
- type: str
- sample: 2a01:4f8:1c1c:c140::/64
- private_networks:
- description: List of private networks the server is attached to (name)
- returned: always
- type: list
- elements: str
- sample: ['my-network', 'another-network']
- private_networks_info:
- description: List of private networks the server is attached to (dict with name and ip)
- returned: always
- type: list
- elements: dict
- sample: [{'name': 'my-network', 'ip': '192.168.1.1'}, {'name': 'another-network', 'ip': '10.185.50.40'}]
- location:
- description: Name of the location of the server
- returned: always
- type: str
- sample: fsn1
- placement_group:
- description: Placement Group of the server
- type: str
- returned: always
- sample: 4711
- version_added: "1.5.0"
- datacenter:
- description: Name of the datacenter of the server
- returned: always
- type: str
- sample: fsn1-dc14
- rescue_enabled:
- description: True if rescue mode is enabled, Server will then boot into rescue system on next reboot
- returned: always
- type: bool
- sample: false
- backup_window:
- description: Time window (UTC) in which the backup will run, or null if the backups are not enabled
- returned: always
- type: bool
- sample: 22-02
- labels:
- description: User-defined labels (key-value pairs)
- returned: always
- type: dict
- delete_protection:
- description: True if server is protected for deletion
- type: bool
- returned: always
- sample: false
- version_added: "0.1.0"
- rebuild_protection:
- description: True if server is protected for rebuild
- type: bool
- returned: always
- sample: false
- version_added: "0.1.0"
-"""
-
-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
-
-
-class AnsibleHcloudServerInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_server_info")
- self.hcloud_server_info = None
-
- def _prepare_result(self):
- tmp = []
-
- for server in self.hcloud_server_info:
- if server is not None:
- image = None if server.image is None else to_native(server.image.name)
- placement_group = None if server.placement_group is None else to_native(server.placement_group.name)
- ipv4_address = None if server.public_net.ipv4 is None else to_native(server.public_net.ipv4.ip)
- ipv6 = None if server.public_net.ipv6 is None else to_native(server.public_net.ipv6.ip)
- backup_window = None if server.backup_window is None else to_native(server.backup_window)
- tmp.append({
- "id": to_native(server.id),
- "name": to_native(server.name),
- "ipv4_address": ipv4_address,
- "ipv6": ipv6,
- "private_networks": [to_native(net.network.name) for net in server.private_net],
- "private_networks_info": [{"name": to_native(net.network.name), "ip": net.ip} for net in server.private_net],
- "image": image,
- "server_type": to_native(server.server_type.name),
- "datacenter": to_native(server.datacenter.name),
- "location": to_native(server.datacenter.location.name),
- "placement_group": placement_group,
- "rescue_enabled": server.rescue_enabled,
- "backup_window": backup_window,
- "labels": server.labels,
- "status": to_native(server.status),
- "delete_protection": server.protection["delete"],
- "rebuild_protection": server.protection["rebuild"],
- })
- return tmp
-
- def get_servers(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_server_info = [self.client.servers.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("name") is not None:
- self.hcloud_server_info = [self.client.servers.get_by_name(
- self.module.params.get("name")
- )]
- elif self.module.params.get("label_selector") is not None:
- self.hcloud_server_info = self.client.servers.get_all(
- label_selector=self.module.params.get("label_selector"))
- else:
- self.hcloud_server_info = self.client.servers.get_all()
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- name={"type": "str"},
- label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudServerInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_server_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_server_facts' module has been renamed to 'hcloud_server_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudServerInfo(module)
- hcloud.get_servers()
- result = hcloud.get_result()
-
- if is_old_facts:
- ansible_info = {
- 'hcloud_server_facts': result['hcloud_server_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_server_info': result['hcloud_server_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_facts.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_facts.py
deleted file mode 100644
index a84067c32..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_facts.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/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_server_type_info
-
-short_description: Gather infos about the Hetzner Cloud server types.
-
-
-description:
- - Gather infos about your Hetzner Cloud server types.
- - This module was called C(hcloud_server_type_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_server_type_facts).
- Note that the M(hetzner.hcloud.hcloud_server_type_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_server_type_info)!
-
-author:
- - Lukas Kaemmerling (@LKaemmerling)
-
-options:
- id:
- description:
- - The ID of the server type you want to get.
- type: int
- name:
- description:
- - The name of the server type you want to get.
- type: str
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud server type infos
- hcloud_server_type_info:
- register: output
-
-- name: Print the gathered infos
- debug:
- var: output.hcloud_server_type_info
-"""
-
-RETURN = """
-hcloud_server_type_info:
- description: The server type infos as list
- returned: always
- type: complex
- contains:
- id:
- description: Numeric identifier of the server type
- returned: always
- type: int
- sample: 1937415
- name:
- description: Name of the server type
- returned: always
- type: str
- sample: fsn1
- description:
- description: Detail description of the server type
- returned: always
- type: str
- sample: Falkenstein DC Park 1
- cores:
- description: Number of cpu cores a server of this type will have
- returned: always
- type: int
- sample: 1
- memory:
- description: Memory a server of this type will have in GB
- returned: always
- type: int
- sample: 1
- disk:
- description: Disk size a server of this type will have in GB
- returned: always
- type: int
- sample: 25
- storage_type:
- description: Type of server boot drive
- returned: always
- type: str
- sample: local
- cpu_type:
- description: Type of cpu
- returned: always
- type: str
- sample: shared
- architecture:
- description: Architecture of cpu
- returned: always
- type: str
- sample: x86
-"""
-
-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
-
-
-class AnsibleHcloudServerTypeInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_server_type_info")
- self.hcloud_server_type_info = None
-
- def _prepare_result(self):
- tmp = []
-
- for server_type in self.hcloud_server_type_info:
- if server_type is not None:
- tmp.append({
- "id": to_native(server_type.id),
- "name": to_native(server_type.name),
- "description": to_native(server_type.description),
- "cores": server_type.cores,
- "memory": server_type.memory,
- "disk": server_type.disk,
- "storage_type": to_native(server_type.storage_type),
- "cpu_type": to_native(server_type.cpu_type),
- "architecture": to_native(server_type.architecture)
- })
- return tmp
-
- def get_server_types(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_server_type_info = [self.client.server_types.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("name") is not None:
- self.hcloud_server_type_info = [self.client.server_types.get_by_name(
- self.module.params.get("name")
- )]
- else:
- self.hcloud_server_type_info = self.client.server_types.get_all()
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- name={"type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudServerTypeInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_server_type_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_server_type_info' module has been renamed to 'hcloud_server_type_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudServerTypeInfo(module)
- hcloud.get_server_types()
- result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_server_type_info': result['hcloud_server_type_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_server_type_info': result['hcloud_server_type_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_info.py
deleted file mode 100644
index a84067c32..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_info.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/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_server_type_info
-
-short_description: Gather infos about the Hetzner Cloud server types.
-
-
-description:
- - Gather infos about your Hetzner Cloud server types.
- - This module was called C(hcloud_server_type_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_server_type_facts).
- Note that the M(hetzner.hcloud.hcloud_server_type_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_server_type_info)!
-
-author:
- - Lukas Kaemmerling (@LKaemmerling)
-
-options:
- id:
- description:
- - The ID of the server type you want to get.
- type: int
- name:
- description:
- - The name of the server type you want to get.
- type: str
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud server type infos
- hcloud_server_type_info:
- register: output
-
-- name: Print the gathered infos
- debug:
- var: output.hcloud_server_type_info
-"""
-
-RETURN = """
-hcloud_server_type_info:
- description: The server type infos as list
- returned: always
- type: complex
- contains:
- id:
- description: Numeric identifier of the server type
- returned: always
- type: int
- sample: 1937415
- name:
- description: Name of the server type
- returned: always
- type: str
- sample: fsn1
- description:
- description: Detail description of the server type
- returned: always
- type: str
- sample: Falkenstein DC Park 1
- cores:
- description: Number of cpu cores a server of this type will have
- returned: always
- type: int
- sample: 1
- memory:
- description: Memory a server of this type will have in GB
- returned: always
- type: int
- sample: 1
- disk:
- description: Disk size a server of this type will have in GB
- returned: always
- type: int
- sample: 25
- storage_type:
- description: Type of server boot drive
- returned: always
- type: str
- sample: local
- cpu_type:
- description: Type of cpu
- returned: always
- type: str
- sample: shared
- architecture:
- description: Architecture of cpu
- returned: always
- type: str
- sample: x86
-"""
-
-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
-
-
-class AnsibleHcloudServerTypeInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_server_type_info")
- self.hcloud_server_type_info = None
-
- def _prepare_result(self):
- tmp = []
-
- for server_type in self.hcloud_server_type_info:
- if server_type is not None:
- tmp.append({
- "id": to_native(server_type.id),
- "name": to_native(server_type.name),
- "description": to_native(server_type.description),
- "cores": server_type.cores,
- "memory": server_type.memory,
- "disk": server_type.disk,
- "storage_type": to_native(server_type.storage_type),
- "cpu_type": to_native(server_type.cpu_type),
- "architecture": to_native(server_type.architecture)
- })
- return tmp
-
- def get_server_types(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_server_type_info = [self.client.server_types.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("name") is not None:
- self.hcloud_server_type_info = [self.client.server_types.get_by_name(
- self.module.params.get("name")
- )]
- else:
- self.hcloud_server_type_info = self.client.server_types.get_all()
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- name={"type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudServerTypeInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_server_type_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_server_type_info' module has been renamed to 'hcloud_server_type_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudServerTypeInfo(module)
- hcloud.get_server_types()
- result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_server_type_info': result['hcloud_server_type_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_server_type_info': result['hcloud_server_type_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_info.py
deleted file mode 100644
index aab98ed60..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_info.py
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/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_ssh_key_info
-short_description: Gather infos about your Hetzner Cloud ssh_keys.
-description:
- - Gather facts about your Hetzner Cloud ssh_keys.
- - This module was called C(hcloud_ssh_key_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_ssh_key_facts).
- Note that the M(hetzner.hcloud.hcloud_ssh_key_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_ssh_key_info)!
-author:
- - Christopher Schmitt (@cschmitt-hcloud)
-options:
- id:
- description:
- - The ID of the ssh key you want to get.
- type: int
- name:
- description:
- - The name of the ssh key you want to get.
- type: str
- fingerprint:
- description:
- - The fingerprint of the ssh key you want to get.
- type: str
- label_selector:
- description:
- - The label selector for the ssh key you want to get.
- type: str
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud sshkey infos
- hcloud_ssh_key_info:
- register: output
-- name: Print the gathered infos
- debug:
- var: output.hcloud_ssh_key_info
-"""
-
-RETURN = """
-hcloud_ssh_key_info:
- description: The ssh key instances
- returned: Always
- type: complex
- contains:
- id:
- description: Numeric identifier of the ssh_key
- returned: always
- type: int
- sample: 1937415
- name:
- description: Name of the ssh_key
- returned: always
- type: str
- sample: my-ssh-key
- fingerprint:
- description: Fingerprint of the ssh key
- returned: always
- type: str
- sample: 0e:e0:bd:c7:2d:1f:69:49:94:44:91:f1:19:fd:35:f3
- public_key:
- description: The actual public key
- returned: always
- type: str
- sample: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpl/tnk74nnQJxxLAtutUApUZMRJxryKh7VXkNbd4g9 john@example.com"
- 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
-
-
-class AnsibleHcloudSSHKeyInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_ssh_key_info")
- self.hcloud_ssh_key_info = None
-
- def _prepare_result(self):
- ssh_keys = []
-
- for ssh_key in self.hcloud_ssh_key_info:
- if ssh_key:
- ssh_keys.append({
- "id": to_native(ssh_key.id),
- "name": to_native(ssh_key.name),
- "fingerprint": to_native(ssh_key.fingerprint),
- "public_key": to_native(ssh_key.public_key),
- "labels": ssh_key.labels
- })
- return ssh_keys
-
- def get_ssh_keys(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("name") is not None:
- self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_name(
- self.module.params.get("name")
- )]
- elif self.module.params.get("fingerprint") is not None:
- self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_fingerprint(
- self.module.params.get("fingerprint")
- )]
- elif self.module.params.get("label_selector") is not None:
- self.hcloud_ssh_key_info = self.client.ssh_keys.get_all(
- label_selector=self.module.params.get("label_selector"))
- else:
- self.hcloud_ssh_key_info = self.client.ssh_keys.get_all()
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- name={"type": "str"},
- fingerprint={"type": "str"},
- label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudSSHKeyInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_ssh_key_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_ssh_key_facts' module has been renamed to 'hcloud_ssh_key_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudSSHKeyInfo(module)
- hcloud.get_ssh_keys()
- result = hcloud.get_result()
-
- if is_old_facts:
- ansible_info = {
- 'hcloud_ssh_key_facts': result['hcloud_ssh_key_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_ssh_key_info': result['hcloud_ssh_key_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_facts.py b/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_facts.py
deleted file mode 100644
index 9520bfa14..000000000
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_facts.py
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/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_volume_info
-
-short_description: Gather infos about your Hetzner Cloud Volumes.
-
-description:
- - Gather infos about your Hetzner Cloud Volumes.
-
-author:
- - Lukas Kaemmerling (@LKaemmerling)
-
-options:
- id:
- description:
- - The ID of the Volume you want to get.
- type: int
- name:
- description:
- - The name of the Volume you want to get.
- type: str
- label_selector:
- description:
- - The label selector for the Volume you want to get.
- type: str
-extends_documentation_fragment:
-- hetzner.hcloud.hcloud
-
-'''
-
-EXAMPLES = """
-- name: Gather hcloud Volume infos
- hcloud_volume_info:
- register: output
-- name: Print the gathered infos
- debug:
- var: output.hcloud_volume_info
-"""
-
-RETURN = """
-hcloud_volume_info:
- description: The Volume infos as list
- returned: always
- type: complex
- contains:
- id:
- description: Numeric identifier of the Volume
- returned: always
- type: int
- sample: 1937415
- name:
- description: Name of the Volume
- returned: always
- type: str
- sample: my-volume
- size:
- description: Size of the Volume
- returned: always
- type: str
- sample: 10
- linux_device:
- description: Path to the device that contains the Volume.
- returned: always
- type: str
- sample: /dev/disk/by-id/scsi-0HC_Volume_12345
- version_added: "0.1.0"
- location:
- description: Name of the location where the Volume resides in
- returned: always
- type: str
- sample: fsn1
- server:
- description: Name of the server where the Volume is attached to
- returned: always
- type: str
- sample: my-server
- delete_protection:
- description: True if the Volume is protected for deletion
- returned: always
- type: bool
- version_added: "0.1.0"
- 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
-
-
-class AnsibleHcloudVolumeInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_volume_info")
- self.hcloud_volume_info = None
-
- def _prepare_result(self):
- tmp = []
-
- for volume in self.hcloud_volume_info:
- if volume is not None:
- server_name = None
- if volume.server is not None:
- server_name = to_native(volume.server.name)
- tmp.append({
- "id": to_native(volume.id),
- "name": to_native(volume.name),
- "size": volume.size,
- "location": to_native(volume.location.name),
- "labels": volume.labels,
- "server": server_name,
- "linux_device": to_native(volume.linux_device),
- "delete_protection": volume.protection["delete"],
- })
-
- return tmp
-
- def get_volumes(self):
- try:
- if self.module.params.get("id") is not None:
- self.hcloud_volume_info = [self.client.volumes.get_by_id(
- self.module.params.get("id")
- )]
- elif self.module.params.get("name") is not None:
- self.hcloud_volume_info = [self.client.volumes.get_by_name(
- self.module.params.get("name")
- )]
- elif self.module.params.get("label_selector") is not None:
- self.hcloud_volume_info = self.client.volumes.get_all(
- label_selector=self.module.params.get("label_selector"))
- else:
- self.hcloud_volume_info = self.client.volumes.get_all()
-
- except Exception as e:
- self.module.fail_json(msg=e.message)
-
- @staticmethod
- def define_module():
- return AnsibleModule(
- argument_spec=dict(
- id={"type": "int"},
- name={"type": "str"},
- label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
- ),
- supports_check_mode=True,
- )
-
-
-def main():
- module = AnsibleHcloudVolumeInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_volume_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_volume_facts' module has been renamed to 'hcloud_volume_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudVolumeInfo(module)
-
- hcloud.get_volumes()
- result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_volume_facts': result['hcloud_volume_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_volume_info': result['hcloud_volume_info']
- }
- module.exit_json(**ansible_info)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/image_info.py
index 8acd8846a..b0d7fc482 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_info.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/image_info.py
@@ -1,24 +1,20 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_image_info
+module: image_info
short_description: Gather infos about your Hetzner Cloud images.
description:
- Gather infos about your Hetzner Cloud images.
- - This module was called C(hcloud_location_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_location_facts).
- Note that the M(hetzner.hcloud.hcloud_image_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_image_info)!
author:
- Lukas Kaemmerling (@LKaemmerling)
@@ -27,6 +23,7 @@ options:
id:
description:
- The ID of the image you want to get.
+ - The module will fail if the provided ID is invalid.
type: int
name:
description:
@@ -50,11 +47,11 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud image infos
- hcloud_image_info:
+ hetzner.hcloud.image_info:
register: output
- name: Print the gathered infos
@@ -87,7 +84,7 @@ hcloud_image_info:
description: Name of the image
returned: always
type: str
- sample: ubuntu-18.04
+ sample: ubuntu-22.04
description:
description: Detail description of the image
returned: always
@@ -115,48 +112,54 @@ hcloud_image_info:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.images import BoundImage
-class AnsibleHcloudImageInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_image_info")
- self.hcloud_image_info = None
+class AnsibleHCloudImageInfo(AnsibleHCloud):
+ represent = "hcloud_image_info"
+
+ hcloud_image_info: list[BoundImage] | None = None
def _prepare_result(self):
tmp = []
for image in self.hcloud_image_info:
if image is not None:
- tmp.append({
- "id": to_native(image.id),
- "status": to_native(image.status),
- "type": to_native(image.type),
- "name": to_native(image.name),
- "description": to_native(image.description),
- "os_flavor": to_native(image.os_flavor),
- "os_version": to_native(image.os_version),
- "architecture": to_native(image.architecture),
- "labels": image.labels,
- })
+ tmp.append(
+ {
+ "id": to_native(image.id),
+ "status": to_native(image.status),
+ "type": to_native(image.type),
+ "name": to_native(image.name),
+ "description": to_native(image.description),
+ "os_flavor": to_native(image.os_flavor),
+ "os_version": to_native(image.os_version),
+ "architecture": to_native(image.architecture),
+ "labels": image.labels,
+ }
+ )
return tmp
def get_images(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_image_info = [self.client.images.get_by_id(
- self.module.params.get("id")
- )]
+ self.hcloud_image_info = [self.client.images.get_by_id(self.module.params.get("id"))]
elif self.module.params.get("name") is not None and self.module.params.get("architecture") is not None:
- self.hcloud_image_info = [self.client.images.get_by_name_and_architecture(
- self.module.params.get("name"),
- self.module.params.get("architecture")
- )]
+ self.hcloud_image_info = [
+ self.client.images.get_by_name_and_architecture(
+ self.module.params.get("name"),
+ self.module.params.get("architecture"),
+ )
+ ]
elif self.module.params.get("name") is not None:
- self.hcloud_image_info = [self.client.images.get_by_name(
- self.module.params.get("name")
- )]
+ self.module.warn(
+ "This module only returns x86 images by default. Please set architecture:x86|arm to hide this message."
+ )
+ self.hcloud_image_info = [self.client.images.get_by_name(self.module.params.get("name"))]
else:
params = {}
label_selector = self.module.params.get("label_selector")
@@ -173,11 +176,11 @@ class AnsibleHcloudImageInfo(Hcloud):
self.hcloud_image_info = self.client.images.get_all(**params)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
@@ -185,34 +188,21 @@ class AnsibleHcloudImageInfo(Hcloud):
label_selector={"type": "str"},
type={"choices": ["system", "snapshot", "backup"], "default": "system", "type": "str"},
architecture={"choices": ["x86", "arm"], "type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudImageInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_image_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_image_facts' module has been renamed to 'hcloud_image_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
+ module = AnsibleHCloudImageInfo.define_module()
+ hcloud = AnsibleHCloudImageInfo(module)
- hcloud = AnsibleHcloudImageInfo(module)
hcloud.get_images()
result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_imagen_facts': result['hcloud_image_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_image_info': result['hcloud_image_info']
- }
- module.exit_json(**ansible_info)
+ ansible_info = {"hcloud_image_info": result["hcloud_image_info"]}
+ module.exit_json(**ansible_info)
if __name__ == "__main__":
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/iso_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/iso_info.py
new file mode 100644
index 000000000..e623d1714
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/iso_info.py
@@ -0,0 +1,206 @@
+#!/usr/bin/python
+
+# Copyright: (c) 2022, Patrice Le Guyader
+# heavily inspired by the work of @LKaemmerling
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+from __future__ import annotations
+
+DOCUMENTATION = """
+---
+module: iso_info
+
+short_description: Gather infos about the Hetzner Cloud ISO list.
+
+description:
+ - Gather infos about the Hetzner Cloud ISO list.
+
+author:
+ - Patrice Le Guyader (@patlegu)
+ - Lukas Kaemmerling (@LKaemmerling)
+
+options:
+ id:
+ description:
+ - The ID of the ISO image you want to get.
+ - The module will fail if the provided ID is invalid.
+ type: int
+ name:
+ description:
+ - The name of the ISO you want to get.
+ type: str
+ architecture:
+ description:
+ - Filter ISOs with compatible architecture.
+ type: str
+ choices: [x86, arm]
+ include_architecture_wildcard:
+ description:
+ - Include ISOs with wildcard architecture (architecture is null).
+ - Works only if architecture filter is specified.
+ type: bool
+
+extends_documentation_fragment:
+ - hetzner.hcloud.hcloud
+"""
+
+EXAMPLES = """
+- name: Gather hcloud ISO type infos
+ hetzner.hcloud.iso_info:
+ register: output
+
+- name: Print the gathered infos
+ debug:
+ var: output.hcloud_iso_info
+"""
+
+RETURN = """
+hcloud_iso_info:
+ description: The ISO type infos as list
+ returned: always
+ type: complex
+ contains:
+ id:
+ description: ID of the ISO
+ returned: always
+ type: int
+ sample: 22110
+ name:
+ description: Unique identifier of the ISO. Only set for public ISOs
+ returned: always
+ type: str
+ sample: debian-12.0.0-amd64-netinst.iso
+ description:
+ description: Description of the ISO
+ returned: always
+ type: str
+ sample: Debian 12.0 (amd64/netinstall)
+ architecture:
+ description: >
+ Type of cpu architecture this ISO is compatible with.
+ None indicates no restriction on the architecture (wildcard).
+ returned: when supported
+ type: str
+ sample: x86
+ type:
+ description: Type of the ISO, can be one of `public`, `private`.
+ returned: always
+ type: str
+ sample: public
+ deprecated:
+ description: >
+ ISO 8601 timestamp of deprecation, None if ISO is still available.
+ After the deprecation time it will no longer be possible to attach the
+ ISO to servers. This field is deprecated. Use `deprecation` instead.
+ returned: always
+ type: str
+ sample: "2024-12-01T00:00:00+00:00"
+ deprecation:
+ description: >
+ Describes if, when & how the resources was deprecated. If this field is
+ set to None the resource is not deprecated. If it has a value, it is
+ considered deprecated.
+ returned: if the resource is deprecated
+ type: dict
+ contains:
+ announced:
+ description: Date of when the deprecation was announced.
+ returned: always
+ type: str
+ sample: "2021-11-01T00:00:00+00:00"
+ unavailable_after:
+ description: >
+ After the time in this field, the resource will not be available
+ from the general listing endpoint of the resource type, and it can
+ not be used in new resources. For example, if this is an image,
+ you can not create new servers with this image after the mentioned
+ date.
+ returned: always
+ type: str
+ sample: "2021-12-01T00:00:00+00:00"
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.isos import BoundIso
+
+
+class AnsibleHCloudIsoInfo(AnsibleHCloud):
+ represent = "hcloud_iso_info"
+
+ hcloud_iso_info: list[BoundIso] | None = None
+
+ def _prepare_result(self):
+ tmp = []
+
+ for iso_info in self.hcloud_iso_info:
+ if iso_info is None:
+ continue
+
+ tmp.append(
+ {
+ "id": to_native(iso_info.id),
+ "name": to_native(iso_info.name),
+ "description": to_native(iso_info.description),
+ "type": iso_info.type,
+ "architecture": iso_info.architecture,
+ "deprecated": (
+ iso_info.deprecation.unavailable_after if iso_info.deprecation is not None else None
+ ),
+ "deprecation": (
+ {
+ "announced": iso_info.deprecation.announced.isoformat(),
+ "unavailable_after": iso_info.deprecation.unavailable_after.isoformat(),
+ }
+ if iso_info.deprecation is not None
+ else None
+ ),
+ }
+ )
+
+ return tmp
+
+ def get_iso_infos(self):
+ try:
+ if self.module.params.get("id") is not None:
+ self.hcloud_iso_info = [self.client.isos.get_by_id(self.module.params.get("id"))]
+ elif self.module.params.get("name") is not None:
+ self.hcloud_iso_info = [self.client.isos.get_by_name(self.module.params.get("name"))]
+ else:
+ self.hcloud_iso_info = self.client.isos.get_all(
+ architecture=self.module.params.get("architecture"),
+ include_wildcard_architecture=self.module.params.get("include_wildcard_architecture"),
+ )
+
+ 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"},
+ architecture={"type": "str", "choices": ["x86", "arm"]},
+ include_architecture_wildcard={"type": "bool"},
+ **super().base_module_arguments(),
+ ),
+ supports_check_mode=True,
+ )
+
+
+def main():
+ module = AnsibleHCloudIsoInfo.define_module()
+ hcloud = AnsibleHCloudIsoInfo(module)
+ hcloud.get_iso_infos()
+ result = hcloud.get_result()
+ ansible_info = {"hcloud_iso_info": result["hcloud_iso_info"]}
+ module.exit_json(**ansible_info)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer.py b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer.py
index 9c6c2bbaf..1a0d8712a 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer.py
@@ -1,20 +1,17 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_load_balancer
+module: 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.
@@ -37,6 +34,12 @@ options:
- The Load Balancer Type of the Hetzner Cloud Load Balancer to manage.
- Required if Load Balancer does not exist.
type: str
+ algorithm:
+ description:
+ - Algorithm of the Load Balancer.
+ type: str
+ default: round_robin
+ choices: [round_robin, least_connections]
location:
description:
- Location of Load Balancer.
@@ -68,24 +71,21 @@ options:
type: str
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-
-requirements:
- - hcloud-python >= 1.8.0
-'''
+"""
EXAMPLES = """
- name: Create a basic Load Balancer
- hcloud_load_balancer:
+ hetzner.hcloud.load_balancer:
name: my-Load Balancer
load_balancer_type: lb11
+ algorithm: round_robin
location: fsn1
state: present
- name: Ensure the Load Balancer is absent (remove if needed)
- hcloud_load_balancer:
+ hetzner.hcloud.load_balancer:
name: my-Load Balancer
state: absent
-
"""
RETURN = """
@@ -114,6 +114,12 @@ hcloud_load_balancer:
returned: always
type: str
sample: cx11
+ algorithm:
+ description: Algorithm of the Load Balancer.
+ returned: always
+ type: str
+ choices: [round_robin, least_connections]
+ sample: round_robin
ipv4_address:
description: Public IPv4 address of the Load Balancer
returned: always
@@ -146,18 +152,27 @@ hcloud_load_balancer:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.load_balancers import (
+ BoundLoadBalancer,
+ LoadBalancerAlgorithm,
+)
-class AnsibleHcloudLoadBalancer(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_load_balancer")
- self.hcloud_load_balancer = None
+
+class AnsibleHCloudLoadBalancer(AnsibleHCloud):
+ represent = "hcloud_load_balancer"
+
+ hcloud_load_balancer: BoundLoadBalancer | None = 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)
+ 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),
@@ -165,6 +180,7 @@ class AnsibleHcloudLoadBalancer(Hcloud):
"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),
+ "algorithm": to_native(self.hcloud_load_balancer.algorithm.type),
"location": to_native(self.hcloud_load_balancer.location.name),
"labels": self.hcloud_load_balancer.labels,
"delete_protection": self.hcloud_load_balancer.protection["delete"],
@@ -174,24 +190,18 @@ class AnsibleHcloudLoadBalancer(Hcloud):
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")
- )
+ 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 Exception as e:
- self.module.fail_json(msg=e.message)
+ self.hcloud_load_balancer = self.client.load_balancers.get_by_name(self.module.params.get("name"))
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_load_balancer(self):
-
- self.module.fail_on_missing_params(
- required_params=["name", "load_balancer_type"]
- )
+ self.module.fail_on_missing_params(required_params=["name", "load_balancer_type"])
try:
params = {
"name": self.module.params.get("name"),
+ "algorithm": LoadBalancerAlgorithm(type=self.module.params.get("algorithm", "round_robin")),
"load_balancer_type": self.client.load_balancer_types.get_by_name(
self.module.params.get("load_balancer_type")
),
@@ -201,9 +211,7 @@ class AnsibleHcloudLoadBalancer(Hcloud):
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")
- )
+ 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")
@@ -215,8 +223,8 @@ class AnsibleHcloudLoadBalancer(Hcloud):
if delete_protection is not None:
self._get_load_balancer()
self.hcloud_load_balancer.change_protection(delete=delete_protection).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_load_balancer()
@@ -236,7 +244,9 @@ class AnsibleHcloudLoadBalancer(Hcloud):
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 != (not self.hcloud_load_balancer.public_net.enabled):
+ if disable_public_interface is not None and disable_public_interface != (
+ not 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()
@@ -245,7 +255,10 @@ class AnsibleHcloudLoadBalancer(Hcloud):
self._mark_as_changed()
load_balancer_type = self.module.params.get("load_balancer_type")
- if load_balancer_type is not None and self.hcloud_load_balancer.load_balancer_type.name != load_balancer_type:
+ if (
+ load_balancer_type is not None
+ and self.hcloud_load_balancer.load_balancer_type.name != load_balancer_type
+ ):
new_load_balancer_type = self.client.load_balancer_types.get_by_name(load_balancer_type)
if not new_load_balancer_type:
self.module.fail_json(msg="unknown load balancer type")
@@ -255,9 +268,17 @@ class AnsibleHcloudLoadBalancer(Hcloud):
).wait_until_finished(max_retries=1000)
self._mark_as_changed()
+
+ algorithm = self.module.params.get("algorithm")
+ if algorithm is not None and self.hcloud_load_balancer.algorithm.type != algorithm:
+ self.hcloud_load_balancer.change_algorithm(
+ algorithm=LoadBalancerAlgorithm(type=algorithm)
+ ).wait_until_finished()
+ self._mark_as_changed()
+
self._get_load_balancer()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def present_load_balancer(self):
self._get_load_balancer()
@@ -274,16 +295,17 @@ class AnsibleHcloudLoadBalancer(Hcloud):
self.client.load_balancers.delete(self.hcloud_load_balancer)
self._mark_as_changed()
self.hcloud_load_balancer = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
load_balancer_type={"type": "str"},
+ algorithm={"choices": ["round_robin", "least_connections"], "default": "round_robin"},
location={"type": "str"},
network_zone={"type": "str"},
labels={"type": "dict"},
@@ -293,18 +315,18 @@ class AnsibleHcloudLoadBalancer(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name']],
+ required_one_of=[["id", "name"]],
mutually_exclusive=[["location", "network_zone"]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudLoadBalancer.define_module()
+ module = AnsibleHCloudLoadBalancer.define_module()
- hcloud = AnsibleHcloudLoadBalancer(module)
+ hcloud = AnsibleHCloudLoadBalancer(module)
state = module.params.get("state")
if state == "absent":
hcloud.delete_load_balancer()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_info.py
index 159dad258..19ead98c2 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_info.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_info.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_load_balancer_info
+module: load_balancer_info
short_description: Gather infos about your Hetzner Cloud Load Balancers.
@@ -25,6 +23,7 @@ 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:
@@ -37,11 +36,11 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud load_balancer infos
- hcloud_load_balancer_info:
+ hetzner.hcloud.load_balancer_info:
register: output
- name: Print the gathered infos
@@ -137,10 +136,27 @@ hcloud_load_balancer_info:
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)
+ - 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
@@ -261,14 +277,17 @@ hcloud_load_balancer_info:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.load_balancers import BoundLoadBalancer
+
+class AnsibleHCloudLoadBalancerInfo(AnsibleHCloud):
+ represent = "hcloud_load_balancer_info"
-class AnsibleHcloudLoadBalancerInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_load_balancer_info")
- self.hcloud_load_balancer_info = None
+ hcloud_load_balancer_info: list[BoundLoadBalancer] | None = None
def _prepare_result(self):
tmp = []
@@ -278,22 +297,25 @@ class AnsibleHcloudLoadBalancerInfo(Hcloud):
services = [self._prepare_service_result(service) for service in load_balancer.services]
targets = [self._prepare_target_result(target) for target in load_balancer.targets]
- private_ipv4_address = None if len(load_balancer.private_net) == 0 else to_native(
- load_balancer.private_net[0].ip)
- tmp.append({
- "id": to_native(load_balancer.id),
- "name": to_native(load_balancer.name),
- "ipv4_address": to_native(load_balancer.public_net.ipv4.ip),
- "ipv6_address": to_native(load_balancer.public_net.ipv6.ip),
- "private_ipv4_address": private_ipv4_address,
- "load_balancer_type": to_native(load_balancer.load_balancer_type.name),
- "location": to_native(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": targets,
- "services": services
- })
+ private_ipv4_address = (
+ None if len(load_balancer.private_net) == 0 else to_native(load_balancer.private_net[0].ip)
+ )
+ tmp.append(
+ {
+ "id": to_native(load_balancer.id),
+ "name": to_native(load_balancer.name),
+ "ipv4_address": to_native(load_balancer.public_net.ipv4.ip),
+ "ipv6_address": to_native(load_balancer.public_net.ipv6.ip),
+ "private_ipv4_address": private_ipv4_address,
+ "load_balancer_type": to_native(load_balancer.load_balancer_type.name),
+ "location": to_native(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": targets,
+ "services": services,
+ }
+ )
return tmp
@staticmethod
@@ -305,8 +327,7 @@ class AnsibleHcloudLoadBalancerInfo(Hcloud):
"cookie_lifetime": service.http.cookie_name,
"redirect_http": service.http.redirect_http,
"sticky_sessions": service.http.sticky_sessions,
- "certificates": [to_native(certificate.name) for certificate in
- service.http.certificates],
+ "certificates": [to_native(certificate.name) for certificate in service.http.certificates],
}
health_check = {
"protocol": to_native(service.health_check.protocol),
@@ -320,8 +341,7 @@ class AnsibleHcloudLoadBalancerInfo(Hcloud):
"domain": to_native(service.health_check.http.domain),
"path": to_native(service.health_check.http.path),
"response": to_native(service.health_check.http.response),
- "certificates": [to_native(status_code) for status_code in
- service.health_check.http.status_codes],
+ "certificates": [to_native(status_code) for status_code in service.health_check.http.status_codes],
"tls": service.health_check.http.tls,
}
return {
@@ -337,7 +357,7 @@ class AnsibleHcloudLoadBalancerInfo(Hcloud):
def _prepare_target_result(target):
result = {
"type": to_native(target.type),
- "use_private_ip": target.use_private_ip
+ "use_private_ip": target.use_private_ip,
}
if target.type == "server":
result["server"] = to_native(target.server.name)
@@ -345,18 +365,26 @@ class AnsibleHcloudLoadBalancerInfo(Hcloud):
result["label_selector"] = to_native(target.label_selector.selector)
elif target.type == "ip":
result["ip"] = to_native(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")
- )]
+ 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")
- )]
+ 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")
@@ -365,32 +393,30 @@ class AnsibleHcloudLoadBalancerInfo(Hcloud):
self.hcloud_load_balancer_info = self.client.load_balancers.get_all(**params)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudLoadBalancerInfo.define_module()
+ module = AnsibleHCloudLoadBalancerInfo.define_module()
+ hcloud = AnsibleHCloudLoadBalancerInfo(module)
- hcloud = AnsibleHcloudLoadBalancerInfo(module)
hcloud.get_load_balancers()
result = hcloud.get_result()
- ansible_info = {
- 'hcloud_load_balancer_info': result['hcloud_load_balancer_info']
- }
+ ansible_info = {"hcloud_load_balancer_info": result["hcloud_load_balancer_info"]}
module.exit_json(**ansible_info)
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_network.py b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_network.py
index 63a7c5471..4560f8735 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_network.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_network.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_load_balancer_network
+module: load_balancer_network
short_description: Manage the relationship between Hetzner Cloud Networks and Load Balancers
@@ -24,12 +22,12 @@ version_added: 0.1.0
options:
network:
description:
- - The name of the Hetzner Cloud Networks.
+ - Name or ID of the Hetzner Cloud Networks.
type: str
required: true
load_balancer:
description:
- - The name of the Hetzner Cloud Load Balancer.
+ - Name or ID of the Hetzner Cloud Load Balancer.
type: str
required: true
ip:
@@ -43,30 +41,26 @@ options:
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:
+ hetzner.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:
+ hetzner.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:
+ hetzner.hcloud.load_balancer_network:
network: my-network
load_balancer: my-LoadBalancer
state: absent
@@ -96,16 +90,20 @@ hcloud_load_balancer_network:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.load_balancers import BoundLoadBalancer, PrivateNet
+from ..module_utils.vendor.hcloud.networks import BoundNetwork
-class AnsibleHcloudLoadBalancerNetwork(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_load_balancer_network")
- self.hcloud_network = None
- self.hcloud_load_balancer = None
- self.hcloud_load_balancer_network = None
+
+class AnsibleHCloudLoadBalancerNetwork(AnsibleHCloud):
+ represent = "hcloud_load_balancer_network"
+
+ hcloud_network: BoundNetwork | None = None
+ hcloud_load_balancer: BoundLoadBalancer | None = None
+ hcloud_load_balancer_network: PrivateNet | None = None
def _prepare_result(self):
return {
@@ -116,31 +114,26 @@ class AnsibleHcloudLoadBalancerNetwork(Hcloud):
def _get_load_balancer_and_network(self):
try:
- network = self.module.params.get("network")
- self.hcloud_network = self.client.networks.get_by_name(network)
- if not self.hcloud_network:
- self.module.fail_json(msg="Network does not exist: %s" % network)
-
- load_balancer_name = self.module.params.get("load_balancer")
- self.hcloud_load_balancer = self.client.load_balancers.get_by_name(
- load_balancer_name
+ self.hcloud_network = self._client_get_by_name_or_id(
+ "networks",
+ self.module.params.get("network"),
+ )
+ self.hcloud_load_balancer = self._client_get_by_name_or_id(
+ "load_balancers",
+ self.module.params.get("load_balancer"),
)
- if not self.hcloud_load_balancer:
- self.module.fail_json(msg="Load balancer does not exist: %s" % load_balancer_name)
self.hcloud_load_balancer_network = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
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
+ for private_net in self.hcloud_load_balancer.private_net:
+ if private_net.network.id == self.hcloud_network.id:
+ self.hcloud_load_balancer_network = private_net
def _create_load_balancer_network(self):
- params = {
- "network": self.hcloud_network
- }
+ params = {"network": self.hcloud_network}
if self.module.params.get("ip") is not None:
params["ip"] = self.module.params.get("ip")
@@ -148,8 +141,8 @@ class AnsibleHcloudLoadBalancerNetwork(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_load_balancer.attach_to_network(**params).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_load_balancer_and_network()
@@ -168,15 +161,16 @@ class AnsibleHcloudLoadBalancerNetwork(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_load_balancer.detach_from_network(
- self.hcloud_load_balancer_network.network).wait_until_finished()
+ self.hcloud_load_balancer_network.network
+ ).wait_until_finished()
self._mark_as_changed()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self.hcloud_load_balancer_network = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
network={"type": "str", "required": True},
@@ -186,16 +180,16 @@ class AnsibleHcloudLoadBalancerNetwork(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudLoadBalancerNetwork.define_module()
+ module = AnsibleHCloudLoadBalancerNetwork.define_module()
- hcloud = AnsibleHcloudLoadBalancerNetwork(module)
+ hcloud = AnsibleHCloudLoadBalancerNetwork(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_load_balancer_network()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_service.py b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_service.py
index b5edcc6b5..1fc18deef 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_service.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_service.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_load_balancer_service
+module: load_balancer_service
short_description: Create and manage the services of cloud Load Balancers on the Hetzner Cloud.
@@ -24,7 +22,7 @@ version_added: 0.1.0
options:
load_balancer:
description:
- - The Name of the Hetzner Cloud Load Balancer the service belongs to
+ - Name or ID of the Hetzner Cloud Load Balancer the service belongs to
type: str
required: true
listen_port:
@@ -137,21 +135,18 @@ options:
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:
+ hetzner.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:
+ hetzner.hcloud.load_balancer_service:
load_balancer: my-Load Balancer
protocol: http
listen_port: 80
@@ -284,22 +279,24 @@ hcloud_load_balancer_service:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import APIException, HCloudException
+from ..module_utils.vendor.hcloud.load_balancers import (
+ BoundLoadBalancer,
+ LoadBalancerHealtCheckHttp,
+ LoadBalancerHealthCheck,
+ LoadBalancerService,
+ LoadBalancerServiceHttp,
+)
-try:
- from hcloud.load_balancers.domain import LoadBalancerService, LoadBalancerServiceHttp, \
- LoadBalancerHealthCheck, LoadBalancerHealtCheckHttp
- from hcloud import APIException
-except ImportError:
- APIException = None
+class AnsibleHCloudLoadBalancerService(AnsibleHCloud):
+ represent = "hcloud_load_balancer_service"
-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
+ hcloud_load_balancer: BoundLoadBalancer | None = None
+ hcloud_load_balancer_service: LoadBalancerService | None = None
def _prepare_result(self):
http = None
@@ -309,8 +306,9 @@ class AnsibleHcloudLoadBalancerService(Hcloud):
"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],
+ "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),
@@ -324,8 +322,10 @@ class AnsibleHcloudLoadBalancerService(Hcloud):
"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],
+ "status_codes": [
+ 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.http.tls,
}
return {
@@ -340,31 +340,23 @@ class AnsibleHcloudLoadBalancerService(Hcloud):
def _get_load_balancer(self):
try:
- load_balancer_name = self.module.params.get("load_balancer")
- self.hcloud_load_balancer = self.client.load_balancers.get_by_name(
- load_balancer_name
+ self.hcloud_load_balancer = self._client_get_by_name_or_id(
+ "load_balancers",
+ self.module.params.get("load_balancer"),
)
- if not self.hcloud_load_balancer:
- self.module.fail_json(msg="Load balancer does not exist: %s" % load_balancer_name)
-
self._get_load_balancer_service()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_load_balancer_service(self):
-
- self.module.fail_on_missing_params(
- required_params=["protocol"]
- )
+ 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"]
- )
+ 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")
+ "proxyprotocol": self.module.params.get("proxyprotocol"),
}
if self.module.params.get("destination_port"):
@@ -375,14 +367,16 @@ class AnsibleHcloudLoadBalancerService(Hcloud):
if self.module.params.get("health_check"):
params["health_check"] = self.__get_service_health_checks(
- health_check=self.module.params.get("health_check"))
+ 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 Exception as e:
- self.module.fail_json(msg=e.message)
+ max_retries=1000
+ )
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_load_balancer()
self._get_load_balancer_service()
@@ -404,15 +398,11 @@ class AnsibleHcloudLoadBalancerService(Hcloud):
hcloud_cert = None
try:
try:
- hcloud_cert = self.client.certificates.get_by_name(
- certificate
- )
+ hcloud_cert = self.client.certificates.get_by_name(certificate)
except Exception:
- hcloud_cert = self.client.certificates.get_by_id(
- certificate
- )
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ hcloud_cert = self.client.certificates.get_by_id(certificate)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
service_http.certificates.append(hcloud_cert)
return service_http
@@ -473,14 +463,16 @@ class AnsibleHcloudLoadBalancerService(Hcloud):
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"))
+ 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 Exception as e:
- self.module.fail_json(msg=e.message)
+ max_retries=1000
+ )
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._get_load_balancer()
if changed:
@@ -505,16 +497,17 @@ class AnsibleHcloudLoadBalancerService(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_load_balancer.delete_service(self.hcloud_load_balancer_service).wait_until_finished(
- max_retries=1000)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ max_retries=1000
+ )
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self.hcloud_load_balancer_service = None
- except APIException as e:
- self.module.fail_json(msg=e.message)
+ except APIException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
load_balancer={"type": "str", "required": True},
@@ -528,26 +521,12 @@ class AnsibleHcloudLoadBalancerService(Hcloud):
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"
- },
-
- )
+ 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",
@@ -556,57 +535,36 @@ class AnsibleHcloudLoadBalancerService(Hcloud):
"type": "str",
"choices": ["http", "https", "tcp"],
},
- port={
- "type": "int"
- },
- interval={
- "type": "int"
- },
- timeout={
- "type": "int"
- },
- retries={
- "type": "int"
- },
+ 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
- },
- )
- }
- )
-
+ 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()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudLoadBalancerService.define_module()
+ module = AnsibleHCloudLoadBalancerService.define_module()
- hcloud = AnsibleHcloudLoadBalancerService(module)
+ hcloud = AnsibleHCloudLoadBalancerService(module)
state = module.params.get("state")
if state == "absent":
hcloud.delete_load_balancer_service()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_target.py b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_target.py
index 760884466..36e7f608f 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_target.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_target.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_load_balancer_target
+module: load_balancer_target
short_description: Manage Hetzner Cloud Load Balancer targets
@@ -30,12 +28,12 @@ options:
required: true
load_balancer:
description:
- - The name of the Hetzner Cloud Load Balancer.
+ - Name or ID of the Hetzner Cloud Load Balancer.
type: str
required: true
server:
description:
- - The name of the Hetzner Cloud Server.
+ - Name or ID of the Hetzner Cloud Server.
- Required if I(type) is server
type: str
label_selector:
@@ -51,7 +49,7 @@ options:
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)
+ - Load Balancer needs to be attached to a network. See M(hetzner.hcloud.load_balancer_network)
type: bool
default: False
state:
@@ -61,38 +59,34 @@ options:
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
- hetzner.hcloud.hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: server
load_balancer: my-LoadBalancer
server: my-server
state: present
- name: Create a label_selector Load Balancer target
- hetzner.hcloud.hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: label_selector
load_balancer: my-LoadBalancer
label_selector: application=backend
state: present
- name: Create an IP Load Balancer target
- hetzner.hcloud.hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: ip
load_balancer: my-LoadBalancer
ip: 127.0.0.1
state: present
- name: Ensure the Load Balancer target is absent (remove if needed)
- hetzner.hcloud.hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: server
load_balancer: my-LoadBalancer
server: my-server
@@ -133,36 +127,38 @@ hcloud_load_balancer_target:
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)
+ - Load Balancer needs to be attached to a network. See M(hetzner.hcloud.load_balancer_network)
type: bool
sample: true
returned: always
"""
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
+from ansible.module_utils.common.text.converters import to_native
-try:
- from hcloud.load_balancers.domain import LoadBalancerTarget, LoadBalancerTargetLabelSelector, LoadBalancerTargetIP
-except ImportError:
- LoadBalancerTarget = None
- LoadBalancerTargetLabelSelector = None
- LoadBalancerTargetIP = None
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import APIException, HCloudException
+from ..module_utils.vendor.hcloud.load_balancers import (
+ BoundLoadBalancer,
+ LoadBalancerTarget,
+ LoadBalancerTargetIP,
+ LoadBalancerTargetLabelSelector,
+)
+from ..module_utils.vendor.hcloud.servers import BoundServer
-class AnsibleHcloudLoadBalancerTarget(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_load_balancer_target")
- self.hcloud_load_balancer = None
- self.hcloud_load_balancer_target = None
- self.hcloud_server = None
+class AnsibleHCloudLoadBalancerTarget(AnsibleHCloud):
+ represent = "hcloud_load_balancer_target"
+
+ hcloud_load_balancer: BoundLoadBalancer | None = None
+ hcloud_load_balancer_target: LoadBalancerTarget | None = None
+ hcloud_server: BoundServer | None = None
def _prepare_result(self):
result = {
"type": to_native(self.hcloud_load_balancer_target.type),
"load_balancer": to_native(self.hcloud_load_balancer.name),
- "use_private_ip": self.hcloud_load_balancer_target.use_private_ip
+ "use_private_ip": self.hcloud_load_balancer_target.use_private_ip,
}
if self.hcloud_load_balancer_target.type == "server":
@@ -175,22 +171,20 @@ class AnsibleHcloudLoadBalancerTarget(Hcloud):
def _get_load_balancer_and_target(self):
try:
- load_balancer_name = self.module.params.get("load_balancer")
- self.hcloud_load_balancer = self.client.load_balancers.get_by_name(
- load_balancer_name
+ self.hcloud_load_balancer = self._client_get_by_name_or_id(
+ "load_balancers",
+ self.module.params.get("load_balancer"),
)
- if not self.hcloud_load_balancer:
- self.module.fail_json(msg="Load balancer does not exist: %s" % load_balancer_name)
if self.module.params.get("type") == "server":
- server_name = self.module.params.get("server")
- self.hcloud_server = self.client.servers.get_by_name(server_name)
- if not self.hcloud_server:
- self.module.fail_json(msg="Server not found: %s" % server_name)
+ self.hcloud_server = self._client_get_by_name_or_id(
+ "servers",
+ self.module.params.get("server"),
+ )
self.hcloud_load_balancer_target = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _get_load_balancer_target(self):
for target in self.hcloud_load_balancer.targets:
@@ -205,40 +199,40 @@ class AnsibleHcloudLoadBalancerTarget(Hcloud):
self.hcloud_load_balancer_target = target
def _create_load_balancer_target(self):
- params = {
- "target": None
- }
+ params = {"target": None}
if self.module.params.get("type") == "server":
- self.module.fail_on_missing_params(
- required_params=["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"),
)
- params["target"] = LoadBalancerTarget(type=self.module.params.get("type"), server=self.hcloud_server,
- use_private_ip=self.module.params.get("use_private_ip"))
elif self.module.params.get("type") == "label_selector":
- self.module.fail_on_missing_params(
- required_params=["label_selector"]
+ self.module.fail_on_missing_params(required_params=["label_selector"])
+ params["target"] = LoadBalancerTarget(
+ type=self.module.params.get("type"),
+ label_selector=LoadBalancerTargetLabelSelector(selector=self.module.params.get("label_selector")),
+ use_private_ip=self.module.params.get("use_private_ip"),
)
- params["target"] = LoadBalancerTarget(type=self.module.params.get("type"),
- label_selector=LoadBalancerTargetLabelSelector(
- selector=self.module.params.get("label_selector")),
- use_private_ip=self.module.params.get("use_private_ip"))
elif self.module.params.get("type") == "ip":
- self.module.fail_on_missing_params(
- required_params=["ip"]
+ self.module.fail_on_missing_params(required_params=["ip"])
+ params["target"] = LoadBalancerTarget(
+ type=self.module.params.get("type"),
+ ip=LoadBalancerTargetIP(ip=self.module.params.get("ip")),
+ use_private_ip=False,
)
- params["target"] = LoadBalancerTarget(type=self.module.params.get("type"),
- ip=LoadBalancerTargetIP(ip=self.module.params.get("ip")),
- use_private_ip=False)
if not self.module.check_mode:
try:
self.hcloud_load_balancer.add_target(**params).wait_until_finished()
- except Exception as e:
- if e.code == "locked" or e.code == "conflict":
+ except APIException as exception:
+ if exception.code == "locked" or exception.code == "conflict":
self._create_load_balancer_target()
else:
- self.module.fail_json(msg=e.message)
+ self.fail_json_hcloud(exception)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_load_balancer_and_target()
@@ -257,35 +251,33 @@ class AnsibleHcloudLoadBalancerTarget(Hcloud):
if not self.module.check_mode:
target = None
if self.module.params.get("type") == "server":
- self.module.fail_on_missing_params(
- required_params=["server"]
- )
- target = LoadBalancerTarget(type=self.module.params.get("type"),
- server=self.hcloud_server)
+ self.module.fail_on_missing_params(required_params=["server"])
+ target = LoadBalancerTarget(type=self.module.params.get("type"), server=self.hcloud_server)
elif self.module.params.get("type") == "label_selector":
- self.module.fail_on_missing_params(
- required_params=["label_selector"]
+ self.module.fail_on_missing_params(required_params=["label_selector"])
+ target = LoadBalancerTarget(
+ type=self.module.params.get("type"),
+ label_selector=LoadBalancerTargetLabelSelector(
+ selector=self.module.params.get("label_selector")
+ ),
+ use_private_ip=self.module.params.get("use_private_ip"),
)
- target = LoadBalancerTarget(type=self.module.params.get("type"),
- label_selector=LoadBalancerTargetLabelSelector(
- selector=self.module.params.get("label_selector")),
- use_private_ip=self.module.params.get("use_private_ip"))
elif self.module.params.get("type") == "ip":
- self.module.fail_on_missing_params(
- required_params=["ip"]
+ self.module.fail_on_missing_params(required_params=["ip"])
+ target = LoadBalancerTarget(
+ type=self.module.params.get("type"),
+ ip=LoadBalancerTargetIP(ip=self.module.params.get("ip")),
+ use_private_ip=False,
)
- target = LoadBalancerTarget(type=self.module.params.get("type"),
- ip=LoadBalancerTargetIP(ip=self.module.params.get("ip")),
- use_private_ip=False)
try:
self.hcloud_load_balancer.remove_target(target).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self.hcloud_load_balancer_target = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
type={"type": "str", "required": True, "choices": ["server", "label_selector", "ip"]},
@@ -298,16 +290,16 @@ class AnsibleHcloudLoadBalancerTarget(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudLoadBalancerTarget.define_module()
+ module = AnsibleHCloudLoadBalancerTarget.define_module()
- hcloud = AnsibleHcloudLoadBalancerTarget(module)
+ hcloud = AnsibleHCloudLoadBalancerTarget(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_load_balancer_target()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_type_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_type_info.py
index a481ea9c9..67feafd59 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_type_info.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/load_balancer_type_info.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_load_balancer_type_info
+module: load_balancer_type_info
short_description: Gather infos about the Hetzner Cloud Load Balancer types.
@@ -25,6 +23,7 @@ options:
id:
description:
- The ID of the Load Balancer type you want to get.
+ - The module will fail if the provided ID is invalid.
type: int
name:
description:
@@ -33,11 +32,11 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud Load Balancer type infos
- hcloud_load_balancer_type_info:
+ hetzner.hcloud.load_balancer_type_info:
register: output
- name: Print the gathered infos
@@ -89,68 +88,72 @@ hcloud_load_balancer_type_info:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.load_balancer_types import BoundLoadBalancerType
-class AnsibleHcloudLoadBalancerTypeInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_load_balancer_type_info")
- self.hcloud_load_balancer_type_info = None
+class AnsibleHCloudLoadBalancerTypeInfo(AnsibleHCloud):
+ represent = "hcloud_load_balancer_type_info"
+
+ hcloud_load_balancer_type_info: list[BoundLoadBalancerType] | None = 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
- })
+ 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")
- )]
+ 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")
- )]
+ 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 Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudLoadBalancerTypeInfo.define_module()
+ module = AnsibleHCloudLoadBalancerTypeInfo.define_module()
+ hcloud = AnsibleHCloudLoadBalancerTypeInfo(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']
- }
+
+ ansible_info = {"hcloud_load_balancer_type_info": result["hcloud_load_balancer_type_info"]}
module.exit_json(**ansible_info)
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/location_info.py
index 623c6ab68..ac495c6c8 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_info.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/location_info.py
@@ -1,24 +1,20 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_location_info
+module: location_info
short_description: Gather infos about your Hetzner Cloud locations.
description:
- Gather infos about your Hetzner Cloud locations.
- - This module was called C(hcloud_location_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_location_facts).
- Note that the M(hetzner.hcloud.hcloud_location_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_location_info)!
author:
- Lukas Kaemmerling (@LKaemmerling)
@@ -27,6 +23,7 @@ options:
id:
description:
- The ID of the location you want to get.
+ - The module will fail if the provided ID is invalid.
type: int
name:
description:
@@ -35,11 +32,11 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud location infos
- hcloud_location_info:
+ hetzner.hcloud.location_info:
register: output
- name: Print the gathered infos
@@ -81,78 +78,67 @@ hcloud_location_info:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.locations import BoundLocation
+
+class AnsibleHCloudLocationInfo(AnsibleHCloud):
+ represent = "hcloud_location_info"
-class AnsibleHcloudLocationInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_location_info")
- self.hcloud_location_info = None
+ hcloud_location_info: list[BoundLocation] | None = None
def _prepare_result(self):
tmp = []
for location in self.hcloud_location_info:
if location is not None:
- tmp.append({
- "id": to_native(location.id),
- "name": to_native(location.name),
- "description": to_native(location.description),
- "city": to_native(location.city),
- "country": to_native(location.country)
- })
+ tmp.append(
+ {
+ "id": to_native(location.id),
+ "name": to_native(location.name),
+ "description": to_native(location.description),
+ "city": to_native(location.city),
+ "country": to_native(location.country),
+ }
+ )
return tmp
def get_locations(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_location_info = [self.client.locations.get_by_id(
- self.module.params.get("id")
- )]
+ self.hcloud_location_info = [self.client.locations.get_by_id(self.module.params.get("id"))]
elif self.module.params.get("name") is not None:
- self.hcloud_location_info = [self.client.locations.get_by_name(
- self.module.params.get("name")
- )]
+ self.hcloud_location_info = [self.client.locations.get_by_name(self.module.params.get("name"))]
else:
self.hcloud_location_info = self.client.locations.get_all()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudLocationInfo.define_module()
+ module = AnsibleHCloudLocationInfo.define_module()
+ hcloud = AnsibleHCloudLocationInfo(module)
- is_old_facts = module._name == 'hcloud_location_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_location_info' module has been renamed to 'hcloud_location_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudLocationInfo(module)
hcloud.get_locations()
result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_location_facts': result['hcloud_location_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_location_info': result['hcloud_location_info']
- }
- module.exit_json(**ansible_info)
+
+ ansible_info = {"hcloud_location_info": result["hcloud_location_info"]}
+ module.exit_json(**ansible_info)
if __name__ == "__main__":
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network.py b/ansible_collections/hetzner/hcloud/plugins/modules/network.py
index 9c005d29f..24e45a48d 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/network.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_network
+module: network
short_description: Create and manage cloud Networks on the Hetzner Cloud.
@@ -38,6 +36,11 @@ options:
- IP range of the Network.
- Required if Network does not exist.
type: str
+ expose_routes_to_vswitch:
+ description:
+ - Indicates if the routes from this network should be exposed to the vSwitch connection.
+ - The exposing only takes effect if a vSwitch connection is active.
+ type: bool
labels:
description:
- User-defined labels (key-value pairs).
@@ -53,23 +56,19 @@ options:
choices: [ absent, present ]
type: str
-requirements:
- - hcloud-python >= 1.3.0
-
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-
-'''
+"""
EXAMPLES = """
- name: Create a basic network
- hcloud_network:
+ hetzner.hcloud.network:
name: my-network
ip_range: 10.0.0.0/8
state: present
- name: Ensure the Network is absent (remove if needed)
- hcloud_network:
+ hetzner.hcloud.network:
name: my-network
state: absent
"""
@@ -95,6 +94,11 @@ hcloud_network:
type: str
returned: always
sample: 10.0.0.0/8
+ expose_routes_to_vswitch:
+ description: Indicates if the routes from this network should be exposed to the vSwitch connection.
+ type: bool
+ returned: always
+ sample: false
delete_protection:
description: True if Network is protected for deletion
type: bool
@@ -111,20 +115,24 @@ hcloud_network:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.networks import BoundNetwork
-class AnsibleHcloudNetwork(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_network")
- self.hcloud_network = None
+
+class AnsibleHCloudNetwork(AnsibleHCloud):
+ represent = "hcloud_network"
+
+ hcloud_network: BoundNetwork | None = None
def _prepare_result(self):
return {
"id": to_native(self.hcloud_network.id),
"name": to_native(self.hcloud_network.name),
"ip_range": to_native(self.hcloud_network.ip_range),
+ "expose_routes_to_vswitch": self.hcloud_network.expose_routes_to_vswitch,
"delete_protection": self.hcloud_network.protection["delete"],
"labels": self.hcloud_network.labels,
}
@@ -132,26 +140,24 @@ class AnsibleHcloudNetwork(Hcloud):
def _get_network(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_network = self.client.networks.get_by_id(
- self.module.params.get("id")
- )
+ self.hcloud_network = self.client.networks.get_by_id(self.module.params.get("id"))
else:
- self.hcloud_network = self.client.networks.get_by_name(
- self.module.params.get("name")
- )
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ self.hcloud_network = self.client.networks.get_by_name(self.module.params.get("name"))
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_network(self):
-
- self.module.fail_on_missing_params(
- required_params=["name", "ip_range"]
- )
+ self.module.fail_on_missing_params(required_params=["name", "ip_range"])
params = {
"name": self.module.params.get("name"),
"ip_range": self.module.params.get("ip_range"),
"labels": self.module.params.get("labels"),
}
+
+ expose_routes_to_vswitch = self.module.params.get("expose_routes_to_vswitch")
+ if expose_routes_to_vswitch is not None:
+ params["expose_routes_to_vswitch"] = expose_routes_to_vswitch
+
try:
if not self.module.check_mode:
self.client.networks.create(**params)
@@ -160,8 +166,8 @@ class AnsibleHcloudNetwork(Hcloud):
if delete_protection is not None:
self._get_network()
self.hcloud_network.change_protection(delete=delete_protection).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_network()
@@ -179,13 +185,22 @@ class AnsibleHcloudNetwork(Hcloud):
self.hcloud_network.change_ip_range(ip_range=ip_range).wait_until_finished()
self._mark_as_changed()
+ expose_routes_to_vswitch = self.module.params.get("expose_routes_to_vswitch")
+ if (
+ expose_routes_to_vswitch is not None
+ and expose_routes_to_vswitch != self.hcloud_network.expose_routes_to_vswitch
+ ):
+ if not self.module.check_mode:
+ self.hcloud_network.update(expose_routes_to_vswitch=expose_routes_to_vswitch)
+ self._mark_as_changed()
+
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None and delete_protection != self.hcloud_network.protection["delete"]:
if not self.module.check_mode:
self.hcloud_network.change_protection(delete=delete_protection).wait_until_finished()
self._mark_as_changed()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._get_network()
def present_network(self):
@@ -202,34 +217,35 @@ class AnsibleHcloudNetwork(Hcloud):
if not self.module.check_mode:
self.client.networks.delete(self.hcloud_network)
self._mark_as_changed()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self.hcloud_network = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
ip_range={"type": "str"},
+ expose_routes_to_vswitch={"type": "bool"},
labels={"type": "dict"},
delete_protection={"type": "bool"},
state={
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name']],
+ required_one_of=[["id", "name"]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudNetwork.define_module()
+ module = AnsibleHCloudNetwork.define_module()
- hcloud = AnsibleHcloudNetwork(module)
+ hcloud = AnsibleHCloudNetwork(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_network()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/network_info.py
index 382e447aa..4008352b4 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network_info.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/network_info.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_network_info
+module: network_info
short_description: Gather info about your Hetzner Cloud networks.
@@ -25,6 +23,7 @@ options:
id:
description:
- The ID of the network you want to get.
+ - The module will fail if the provided ID is invalid.
type: int
name:
description:
@@ -37,7 +36,7 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud network info
@@ -110,6 +109,11 @@ hcloud_network_info:
returned: always
type: str
sample: 10.0.0.1
+ expose_routes_to_vswitch:
+ description: Indicates if the routes from this network should be exposed to the vSwitch connection.
+ returned: always
+ type: bool
+ sample: false
servers:
description: Servers attached to the network
returned: always
@@ -181,14 +185,17 @@ hcloud_network_info:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.networks import BoundNetwork
-class AnsibleHcloudNetworkInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_network_info")
- self.hcloud_network_info = None
+class AnsibleHCloudNetworkInfo(AnsibleHCloud):
+ represent = "hcloud_network_info"
+
+ hcloud_network_info: list[BoundNetwork] | None = None
def _prepare_result(self):
tmp = []
@@ -206,10 +213,7 @@ class AnsibleHcloudNetworkInfo(Hcloud):
subnets.append(prepared_subnet)
routes = []
for route in network.routes:
- prepared_route = {
- "destination": route.destination,
- "gateway": route.gateway
- }
+ prepared_route = {"destination": route.destination, "gateway": route.gateway}
routes.append(prepared_route)
servers = []
@@ -233,59 +237,58 @@ class AnsibleHcloudNetworkInfo(Hcloud):
}
servers.append(prepared_server)
- tmp.append({
- "id": to_native(network.id),
- "name": to_native(network.name),
- "ip_range": to_native(network.ip_range),
- "subnetworks": subnets,
- "routes": routes,
- "servers": servers,
- "labels": network.labels,
- "delete_protection": network.protection["delete"],
- })
+ tmp.append(
+ {
+ "id": to_native(network.id),
+ "name": to_native(network.name),
+ "ip_range": to_native(network.ip_range),
+ "subnetworks": subnets,
+ "routes": routes,
+ "expose_routes_to_vswitch": network.expose_routes_to_vswitch,
+ "servers": servers,
+ "labels": network.labels,
+ "delete_protection": network.protection["delete"],
+ }
+ )
return tmp
def get_networks(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_network_info = [self.client.networks.get_by_id(
- self.module.params.get("id")
- )]
+ self.hcloud_network_info = [self.client.networks.get_by_id(self.module.params.get("id"))]
elif self.module.params.get("name") is not None:
- self.hcloud_network_info = [self.client.networks.get_by_name(
- self.module.params.get("name")
- )]
+ self.hcloud_network_info = [self.client.networks.get_by_name(self.module.params.get("name"))]
elif self.module.params.get("label_selector") is not None:
self.hcloud_network_info = self.client.networks.get_all(
- label_selector=self.module.params.get("label_selector"))
+ label_selector=self.module.params.get("label_selector")
+ )
else:
self.hcloud_network_info = self.client.networks.get_all()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudNetworkInfo.define_module()
+ module = AnsibleHCloudNetworkInfo.define_module()
+ hcloud = AnsibleHCloudNetworkInfo(module)
- hcloud = AnsibleHcloudNetworkInfo(module)
hcloud.get_networks()
result = hcloud.get_result()
- info = {
- 'hcloud_network_info': result['hcloud_network_info']
- }
+
+ info = {"hcloud_network_info": result["hcloud_network_info"]}
module.exit_json(**info)
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_placement_group.py b/ansible_collections/hetzner/hcloud/plugins/modules/placement_group.py
index 522bb679d..ba26fad22 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_placement_group.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/placement_group.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
DOCUMENTATION = """
---
-module: hcloud_placement_group
+module: placement_group
short_description: Create and manage placement groups on the Hetzner Cloud.
@@ -47,31 +45,28 @@ options:
choices: [ absent, present ]
type: str
-requirements:
- - hcloud-python >= 1.15.0
-
extends_documentation_fragment:
- hetzner.hcloud.hcloud
"""
EXAMPLES = """
- name: Create a basic placement group
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
name: my-placement-group
state: present
type: spread
- name: Create a placement group with labels
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
name: my-placement-group
type: spread
labels:
- key: value
- mylabel: 123
+ key: value
+ mylabel: 123
state: present
- name: Ensure the placement group is absent (remove if needed)
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
name: my-placement-group
state: absent
"""
@@ -111,15 +106,18 @@ hcloud_placement_group:
- 4712
"""
-from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud
from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils._text import to_native
+from ansible.module_utils.common.text.converters import to_native
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.placement_groups import BoundPlacementGroup
-class AnsibleHcloudPlacementGroup(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_placement_group")
- self.hcloud_placement_group = None
+
+class AnsibleHCloudPlacementGroup(AnsibleHCloud):
+ represent = "hcloud_placement_group"
+
+ hcloud_placement_group: BoundPlacementGroup | None = None
def _prepare_result(self):
return {
@@ -133,20 +131,14 @@ class AnsibleHcloudPlacementGroup(Hcloud):
def _get_placement_group(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_placement_group = self.client.placement_groups.get_by_id(
- self.module.params.get("id")
- )
+ self.hcloud_placement_group = self.client.placement_groups.get_by_id(self.module.params.get("id"))
elif self.module.params.get("name") is not None:
- self.hcloud_placement_group = self.client.placement_groups.get_by_name(
- self.module.params.get("name")
- )
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ self.hcloud_placement_group = self.client.placement_groups.get_by_name(self.module.params.get("name"))
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_placement_group(self):
- self.module.fail_on_missing_params(
- required_params=["name"]
- )
+ self.module.fail_on_missing_params(required_params=["name"])
params = {
"name": self.module.params.get("name"),
"type": self.module.params.get("type"),
@@ -155,17 +147,15 @@ class AnsibleHcloudPlacementGroup(Hcloud):
if not self.module.check_mode:
try:
self.client.placement_groups.create(**params)
- except Exception as e:
- self.module.fail_json(msg=e.message, **params)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception, params=params)
self._mark_as_changed()
self._get_placement_group()
def _update_placement_group(self):
name = self.module.params.get("name")
if name is not None and self.hcloud_placement_group.name != name:
- self.module.fail_on_missing_params(
- required_params=["id"]
- )
+ self.module.fail_on_missing_params(required_params=["id"])
if not self.module.check_mode:
self.hcloud_placement_group.update(name=name)
self._mark_as_changed()
@@ -193,8 +183,8 @@ class AnsibleHcloudPlacementGroup(Hcloud):
self._mark_as_changed()
self.hcloud_placement_group = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
@@ -205,18 +195,18 @@ class AnsibleHcloudPlacementGroup(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name']],
- required_if=[['state', 'present', ['name']]],
+ required_one_of=[["id", "name"]],
+ required_if=[["state", "present", ["name"]]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudPlacementGroup.define_module()
+ module = AnsibleHCloudPlacementGroup.define_module()
- hcloud = AnsibleHcloudPlacementGroup(module)
+ hcloud = AnsibleHCloudPlacementGroup(module)
state = module.params.get("state")
if state == "absent":
hcloud.delete_placement_group()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_primary_ip.py b/ansible_collections/hetzner/hcloud/plugins/modules/primary_ip.py
index c192d5fec..607f6c7e1 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_primary_ip.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/primary_ip.py
@@ -1,16 +1,14 @@
#!/usr/bin/python
-# -*- coding: utf-8 -*-
# Copyright: (c) 2022, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_primary_ip
+module: primary_ip
short_description: Create and manage cloud Primary IPs on the Hetzner Cloud.
@@ -63,29 +61,25 @@ options:
choices: [ absent, present ]
type: str
-requirements:
- - hcloud-python >= 1.9.0
-
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-
-'''
+"""
EXAMPLES = """
- name: Create a basic IPv4 Primary IP
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: my-primary-ip
datacenter: fsn1-dc14
type: ipv4
state: present
- name: Create a basic IPv6 Primary IP
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: my-primary-ip
datacenter: fsn1-dc14
type: ipv6
state: present
- name: Primary IP should be absent
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: my-primary-ip
state: absent
"""
@@ -136,14 +130,17 @@ hcloud_primary_ip:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.primary_ips import BoundPrimaryIP
-class AnsibleHcloudPrimaryIP(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_primary_ip")
- self.hcloud_primary_ip = None
+
+class AnsibleHCloudPrimaryIP(AnsibleHCloud):
+ represent = "hcloud_primary_ip"
+
+ hcloud_primary_ip: BoundPrimaryIP | None = None
def _prepare_result(self):
return {
@@ -159,27 +156,19 @@ class AnsibleHcloudPrimaryIP(Hcloud):
def _get_primary_ip(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_primary_ip = self.client.primary_ips.get_by_id(
- self.module.params.get("id")
- )
+ self.hcloud_primary_ip = self.client.primary_ips.get_by_id(self.module.params.get("id"))
else:
- self.hcloud_primary_ip = self.client.primary_ips.get_by_name(
- self.module.params.get("name")
- )
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ self.hcloud_primary_ip = self.client.primary_ips.get_by_name(self.module.params.get("name"))
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_primary_ip(self):
- self.module.fail_on_missing_params(
- required_params=["type", "datacenter"]
- )
+ self.module.fail_on_missing_params(required_params=["type", "datacenter"])
try:
params = {
"type": self.module.params.get("type"),
"name": self.module.params.get("name"),
- "datacenter": self.client.datacenters.get_by_name(
- self.module.params.get("datacenter")
- )
+ "datacenter": self.client.datacenters.get_by_name(self.module.params.get("datacenter")),
}
if self.module.params.get("labels") is not None:
@@ -191,8 +180,8 @@ class AnsibleHcloudPrimaryIP(Hcloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None:
self.hcloud_primary_ip.change_protection(delete=delete_protection).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_primary_ip()
@@ -211,8 +200,8 @@ class AnsibleHcloudPrimaryIP(Hcloud):
self._mark_as_changed()
self._get_primary_ip()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def present_primary_ip(self):
self._get_primary_ip()
@@ -229,11 +218,11 @@ class AnsibleHcloudPrimaryIP(Hcloud):
self.client.primary_ips.delete(self.hcloud_primary_ip)
self._mark_as_changed()
self.hcloud_primary_ip = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
@@ -247,17 +236,17 @@ class AnsibleHcloudPrimaryIP(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name']],
+ required_one_of=[["id", "name"]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudPrimaryIP.define_module()
+ module = AnsibleHCloudPrimaryIP.define_module()
- hcloud = AnsibleHcloudPrimaryIP(module)
+ hcloud = AnsibleHCloudPrimaryIP(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_primary_ip()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/primary_ip_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/primary_ip_info.py
new file mode 100644
index 000000000..c0bfdbb35
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/primary_ip_info.py
@@ -0,0 +1,203 @@
+#!/usr/bin/python
+
+# 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 annotations
+
+DOCUMENTATION = """
+---
+module: primary_ip_info
+
+short_description: Gather infos about the Hetzner Cloud Primary IPs.
+
+description:
+ - Gather facts about your Hetzner Cloud Primary IPs.
+
+author:
+ - Lukas Kaemmerling (@LKaemmerling)
+ - Kevin Castner (@kcastner)
+
+options:
+ id:
+ description:
+ - The ID of the Primary IP you want to get.
+ - The module will fail if the provided ID is invalid.
+ type: int
+ name:
+ description:
+ - The name for the Primary IP you want to get.
+ type: str
+ label_selector:
+ description:
+ - The label selector for the Primary IP you want to get.
+ type: str
+extends_documentation_fragment:
+- hetzner.hcloud.hcloud
+
+"""
+
+EXAMPLES = """
+- name: Gather hcloud Primary IP infos
+ hetzner.hcloud.primary_ip_info:
+ register: output
+
+- name: Gather hcloud Primary IP infos by id
+ hetzner.hcloud.primary_ip_info:
+ id: 673954
+ register: output
+
+- name: Gather hcloud Primary IP infos by name
+ hetzner.hcloud.primary_ip_info:
+ name: srv1-v4
+ register: output
+
+- name: Gather hcloud Primary IP infos by label
+ hetzner.hcloud.primary_ip_info:
+ label_selector: srv03-ips
+ register: output
+
+- name: Print the gathered infos
+ debug:
+ var: output
+"""
+
+RETURN = """
+hcloud_primary_ip_info:
+ description: The Primary IP infos as list
+ returned: always
+ type: complex
+ contains:
+ id:
+ description: Numeric identifier of the Primary IP
+ returned: always
+ type: int
+ sample: 1937415
+ name:
+ description: Name of the Primary IP
+ returned: always
+ type: str
+ sample: my-primary-ip
+ ip:
+ description: IP address of the Primary IP
+ returned: always
+ type: str
+ sample: 131.232.99.1
+ type:
+ description: Type of the Primary IP
+ returned: always
+ type: str
+ sample: ipv4
+ assignee_id:
+ description: Numeric identifier of the ressource where the Primary IP is assigned to.
+ returned: always
+ type: int
+ sample: 19584637
+ assignee_type:
+ description: Name of the type where the Primary IP is assigned to.
+ returned: always
+ type: str
+ sample: server
+ home_location:
+ description: Location with datacenter where the Primary IP was created in
+ returned: always
+ type: str
+ sample: fsn1-dc1
+ dns_ptr:
+ description: Shows the DNS PTR Record for Primary IP.
+ returned: always
+ type: str
+ sample: srv01.example.com
+ labels:
+ description: User-defined labels (key-value pairs)
+ returned: always
+ type: dict
+ delete_protection:
+ description: True if the Primary IP is protected for deletion
+ returned: always
+ type: bool
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.primary_ips import BoundPrimaryIP
+
+
+class AnsibleHCloudPrimaryIPInfo(AnsibleHCloud):
+ represent = "hcloud_primary_ip_info"
+
+ hcloud_primary_ip_info: list[BoundPrimaryIP] | None = None
+
+ def _prepare_result(self):
+ tmp = []
+
+ for primary_ip in self.hcloud_primary_ip_info:
+ if primary_ip is not None:
+ dns_ptr = None
+ if len(primary_ip.dns_ptr) > 0:
+ dns_ptr = primary_ip.dns_ptr[0]["dns_ptr"]
+ tmp.append(
+ {
+ "id": to_native(primary_ip.id),
+ "name": to_native(primary_ip.name),
+ "ip": to_native(primary_ip.ip),
+ "type": to_native(primary_ip.type),
+ "assignee_id": (
+ to_native(primary_ip.assignee_id) if primary_ip.assignee_id is not None else None
+ ),
+ "assignee_type": to_native(primary_ip.assignee_type),
+ "home_location": to_native(primary_ip.datacenter.name),
+ "dns_ptr": to_native(dns_ptr) if dns_ptr is not None else None,
+ "labels": primary_ip.labels,
+ "delete_protection": primary_ip.protection["delete"],
+ }
+ )
+
+ return tmp
+
+ def get_primary_ips(self):
+ try:
+ if self.module.params.get("id") is not None:
+ self.hcloud_primary_ip_info = [self.client.primary_ips.get_by_id(self.module.params.get("id"))]
+ elif self.module.params.get("name") is not None:
+ self.hcloud_primary_ip_info = [self.client.primary_ips.get_by_name(self.module.params.get("name"))]
+ elif self.module.params.get("label_selector") is not None:
+ self.hcloud_primary_ip_info = self.client.primary_ips.get_all(
+ label_selector=self.module.params.get("label_selector")
+ )
+ else:
+ self.hcloud_primary_ip_info = self.client.primary_ips.get_all()
+
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
+
+ @classmethod
+ def define_module(cls):
+ return AnsibleModule(
+ argument_spec=dict(
+ id={"type": "int"},
+ label_selector={"type": "str"},
+ name={"type": "str"},
+ **super().base_module_arguments(),
+ ),
+ supports_check_mode=True,
+ )
+
+
+def main():
+ module = AnsibleHCloudPrimaryIPInfo.define_module()
+ hcloud = AnsibleHCloudPrimaryIPInfo(module)
+
+ hcloud.get_primary_ips()
+ result = hcloud.get_result()
+
+ ansible_info = {"hcloud_primary_ip_info": result["hcloud_primary_ip_info"]}
+ module.exit_json(**ansible_info)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_rdns.py b/ansible_collections/hetzner/hcloud/plugins/modules/rdns.py
index 9f79fbe70..b2decdec8 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_rdns.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/rdns.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_rdns
+module: rdns
short_description: Create and manage reverse DNS entries on the Hetzner Cloud.
@@ -24,19 +22,19 @@ author:
options:
server:
description:
- - The name of the Hetzner Cloud server you want to add the reverse DNS entry to.
+ - Name or ID of the Hetzner Cloud server you want to add the reverse DNS entry to.
type: str
floating_ip:
description:
- - The name of the Hetzner Cloud Floating IP you want to add the reverse DNS entry to.
+ - Name or ID of the Hetzner Cloud Floating IP you want to add the reverse DNS entry to.
type: str
primary_ip:
description:
- - The name of the Hetzner Cloud Primary IP you want to add the reverse DNS entry to.
+ - Name or ID of the Hetzner Cloud Primary IP you want to add the reverse DNS entry to.
type: str
load_balancer:
description:
- - The name of the Hetzner Cloud Load Balancer you want to add the reverse DNS entry to.
+ - Name or ID of the Hetzner Cloud Load Balancer you want to add the reverse DNS entry to.
type: str
ip_address:
description:
@@ -55,45 +53,41 @@ options:
choices: [ absent, present ]
type: str
-requirements:
- - hcloud-python >= 1.3.0
-
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-
-'''
+"""
EXAMPLES = """
- name: Create a reverse DNS entry for a server
- hcloud_rdns:
+ hetzner.hcloud.rdns:
server: my-server
ip_address: 123.123.123.123
dns_ptr: example.com
state: present
- name: Create a reverse DNS entry for a Floating IP
- hcloud_rdns:
+ hetzner.hcloud.rdns:
floating_ip: my-floating-ip
ip_address: 123.123.123.123
dns_ptr: example.com
state: present
- name: Create a reverse DNS entry for a Primary IP
- hcloud_rdns:
+ hetzner.hcloud.rdns:
primary_ip: my-primary-ip
ip_address: 123.123.123.123
dns_ptr: example.com
state: present
- name: Create a reverse DNS entry for a Load Balancer
- hcloud_rdns:
+ hetzner.hcloud.rdns:
load_balancer: my-load-balancer
ip_address: 123.123.123.123
dns_ptr: example.com
state: present
- name: Ensure the reverse DNS entry is absent (remove if needed)
- hcloud_rdns:
+ hetzner.hcloud.rdns:
server: my-server
ip_address: 123.123.123.123
dns_ptr: example.com
@@ -138,17 +132,25 @@ hcloud_rdns:
sample: example.com
"""
+import ipaddress
+from typing import Any
+
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
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+from ansible.module_utils.common.text.converters import to_native
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.floating_ips import BoundFloatingIP
+from ..module_utils.vendor.hcloud.load_balancers import BoundLoadBalancer
+from ..module_utils.vendor.hcloud.primary_ips import BoundPrimaryIP
+from ..module_utils.vendor.hcloud.servers import BoundServer
-class AnsibleHcloudReverseDNS(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_rdns")
- self.hcloud_resource = None
- self.hcloud_rdns = None
+
+class AnsibleHCloudReverseDNS(AnsibleHCloud):
+ represent = "hcloud_rdns"
+
+ hcloud_resource: BoundServer | BoundFloatingIP | BoundLoadBalancer | BoundPrimaryIP | None = None
+ hcloud_rdns: dict[str, Any] | None = None
def _prepare_result(self):
result = {
@@ -172,35 +174,37 @@ class AnsibleHcloudReverseDNS(Hcloud):
def _get_resource(self):
try:
if self.module.params.get("server"):
- self.hcloud_resource = self.client.servers.get_by_name(
- self.module.params.get("server")
+ self.hcloud_resource = self._client_get_by_name_or_id(
+ "servers",
+ self.module.params.get("server"),
)
- if self.hcloud_resource is None:
- self.module.fail_json(msg="The selected server does not exist")
elif self.module.params.get("floating_ip"):
- self.hcloud_resource = self.client.floating_ips.get_by_name(
- self.module.params.get("floating_ip")
+ self.hcloud_resource = self._client_get_by_name_or_id(
+ "floating_ips",
+ self.module.params.get("floating_ip"),
)
- if self.hcloud_resource is None:
- self.module.fail_json(msg="The selected Floating IP does not exist")
elif self.module.params.get("primary_ip"):
- self.hcloud_resource = self.client.primary_ips.get_by_name(
- self.module.params.get("primary_ip")
+ self.hcloud_resource = self._client_get_by_name_or_id(
+ "primary_ips",
+ self.module.params.get("primary_ip"),
)
- if self.hcloud_resource is None:
- self.module.fail_json(msg="The selected Floating IP does not exist")
elif self.module.params.get("load_balancer"):
- self.hcloud_resource = self.client.load_balancers.get_by_name(
- self.module.params.get("load_balancer")
+ self.hcloud_resource = self._client_get_by_name_or_id(
+ "load_balancers",
+ self.module.params.get("load_balancer"),
)
- if self.hcloud_resource is None:
- self.module.fail_json(msg="The selected Load Balancer does not exist")
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _get_rdns(self):
ip_address = self.module.params.get("ip_address")
- if utils.validate_ip_address(ip_address):
+
+ try:
+ ip_address_obj = ipaddress.ip_address(ip_address)
+ except ValueError:
+ self.module.fail_json(msg=f"The given IP address is not valid: {ip_address}")
+
+ if ip_address_obj.version == 4:
if self.module.params.get("server"):
if self.hcloud_resource.public_net.ipv4.ip == ip_address:
self.hcloud_rdns = {
@@ -234,7 +238,7 @@ class AnsibleHcloudReverseDNS(Hcloud):
else:
self.module.fail_json(msg="The selected Load Balancer does not have this IP address")
- elif utils.validate_ip_v6_address(ip_address):
+ elif ip_address_obj.version == 6:
if self.module.params.get("server"):
for ipv6_address_dns_ptr in self.hcloud_resource.public_net.ipv6.dns_ptr:
if ipv6_address_dns_ptr["ip"] == ip_address:
@@ -263,13 +267,9 @@ class AnsibleHcloudReverseDNS(Hcloud):
"ip_address": ipv6_address_dns_ptr["ip"],
"dns_ptr": ipv6_address_dns_ptr["dns_ptr"],
}
- else:
- self.module.fail_json(msg="The given IP address is not valid")
def _create_rdns(self):
- self.module.fail_on_missing_params(
- required_params=["dns_ptr"]
- )
+ self.module.fail_on_missing_params(required_params=["dns_ptr"])
params = {
"ip": self.module.params.get("ip_address"),
"dns_ptr": self.module.params.get("dns_ptr"),
@@ -278,8 +278,8 @@ class AnsibleHcloudReverseDNS(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_resource.change_dns_ptr(**params).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_resource()
self._get_rdns()
@@ -295,8 +295,8 @@ class AnsibleHcloudReverseDNS(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_resource.change_dns_ptr(**params).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_resource()
self._get_rdns()
@@ -315,14 +315,14 @@ class AnsibleHcloudReverseDNS(Hcloud):
if self.hcloud_rdns is not None:
if not self.module.check_mode:
try:
- self.hcloud_resource.change_dns_ptr(ip=self.hcloud_rdns['ip_address'], dns_ptr=None)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ self.hcloud_resource.change_dns_ptr(ip=self.hcloud_rdns["ip_address"], dns_ptr=None)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self.hcloud_rdns = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
server={"type": "str"},
@@ -335,18 +335,18 @@ class AnsibleHcloudReverseDNS(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['server', 'floating_ip', 'load_balancer', 'primary_ip']],
- mutually_exclusive=[["server", "floating_ip", 'load_balancer', 'primary_ip']],
+ required_one_of=[["server", "floating_ip", "load_balancer", "primary_ip"]],
+ mutually_exclusive=[["server", "floating_ip", "load_balancer", "primary_ip"]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudReverseDNS.define_module()
+ module = AnsibleHCloudReverseDNS.define_module()
- hcloud = AnsibleHcloudReverseDNS(module)
+ hcloud = AnsibleHCloudReverseDNS(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_rdns()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_route.py b/ansible_collections/hetzner/hcloud/plugins/modules/route.py
index c75177953..3c96a7382 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_route.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/route.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_route
+module: route
short_description: Create and delete cloud routes on the Hetzner Cloud.
@@ -24,7 +22,7 @@ author:
options:
network:
description:
- - The name of the Hetzner Cloud Network.
+ - Name or ID of the Hetzner Cloud Network.
type: str
required: true
destination:
@@ -44,24 +42,20 @@ options:
choices: [ absent, present ]
type: str
-requirements:
- - hcloud-python >= 1.3.0
-
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-
-'''
+"""
EXAMPLES = """
- name: Create a basic route
- hcloud_route:
+ hetzner.hcloud.route:
network: my-network
destination: 10.100.1.0/24
gateway: 10.0.1.1
state: present
- name: Ensure the route is absent
- hcloud_route:
+ hetzner.hcloud.route:
network: my-network
destination: 10.100.1.0/24
gateway: 10.0.1.1
@@ -92,20 +86,18 @@ hcloud_route:
"""
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
+from ansible.module_utils.common.text.converters import to_native
-try:
- from hcloud.networks.domain import NetworkRoute
-except ImportError:
- NetworkRoute = None
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.networks import BoundNetwork, NetworkRoute
-class AnsibleHcloudRoute(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_route")
- self.hcloud_network = None
- self.hcloud_route = None
+class AnsibleHCloudRoute(AnsibleHCloud):
+ represent = "hcloud_route"
+
+ hcloud_network: BoundNetwork | None = None
+ hcloud_route: NetworkRoute | None = None
def _prepare_result(self):
return {
@@ -116,10 +108,13 @@ class AnsibleHcloudRoute(Hcloud):
def _get_network(self):
try:
- self.hcloud_network = self.client.networks.get_by_name(self.module.params.get("network"))
+ self.hcloud_network = self._client_get_by_name_or_id(
+ "networks",
+ self.module.params.get("network"),
+ )
self.hcloud_route = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _get_route(self):
destination = self.module.params.get("destination")
@@ -130,15 +125,14 @@ class AnsibleHcloudRoute(Hcloud):
def _create_route(self):
route = NetworkRoute(
- destination=self.module.params.get("destination"),
- gateway=self.module.params.get('gateway')
+ destination=self.module.params.get("destination"), gateway=self.module.params.get("gateway")
)
if not self.module.check_mode:
try:
self.hcloud_network.add_route(route=route).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_network()
@@ -157,13 +151,13 @@ class AnsibleHcloudRoute(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_network.delete_route(self.hcloud_route).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self.hcloud_route = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
network={"type": "str", "required": True},
@@ -173,16 +167,16 @@ class AnsibleHcloudRoute(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudRoute.define_module()
+ module = AnsibleHCloudRoute.define_module()
- hcloud = AnsibleHcloudRoute(module)
+ hcloud = AnsibleHCloudRoute(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_route()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server.py b/ansible_collections/hetzner/hcloud/plugins/modules/server.py
index 3a77da695..f5cadb807 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/server.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_server
+module: server
short_description: Create and manage cloud servers on the Hetzner Cloud.
@@ -67,7 +65,7 @@ options:
datacenter:
description:
- Datacenter of Server.
- - Required of no I(location) is given and server does not exist.
+ - Required if no I(location) is given and server does not exist.
type: str
backups:
description:
@@ -78,17 +76,17 @@ options:
- Resize the disk size, when resizing a server.
- If you want to downgrade the server later, this value should be False.
type: bool
- default: no
+ default: false
enable_ipv4:
description:
- Enables the public ipv4 address
type: bool
- default: yes
+ default: true
enable_ipv6:
description:
- Enables the public ipv6 address
type: bool
- default: yes
+ default: true
ipv4:
description:
- ID of the ipv4 Primary IP to use. If omitted and enable_ipv4 is true, a new ipv4 Primary IP will automatically be created
@@ -110,18 +108,17 @@ options:
- Force the upgrade of the server.
- Power off the server if it is running on upgrade.
type: bool
- default: no
force:
description:
- Force the update of the server.
- May power off the server if update.
type: bool
- default: no
+ default: false
allow_deprecated_image:
description:
- Allows the creation of servers with deprecated images.
type: bool
- default: no
+ default: false
user_data:
description:
- User Data to be passed to the server on creation.
@@ -158,80 +155,80 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Create a basic server
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
server_type: cx11
- image: ubuntu-18.04
+ image: ubuntu-22.04
state: present
- name: Create a basic server with ssh key
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
server_type: cx11
- image: ubuntu-18.04
+ image: ubuntu-22.04
location: fsn1
ssh_keys:
- me@myorganisation
state: present
- name: Resize an existing server
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
server_type: cx21
- upgrade_disk: yes
+ upgrade_disk: true
state: present
- name: Ensure the server is absent (remove if needed)
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
state: absent
- name: Ensure the server is started
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
state: started
- name: Ensure the server is stopped
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
state: stopped
- name: Ensure the server is restarted
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
state: restarted
- name: Ensure the server is will be booted in rescue mode and therefore restarted
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
rescue_mode: linux64
state: restarted
- name: Ensure the server is rebuild
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
- image: ubuntu-18.04
+ image: ubuntu-22.04
state: rebuild
- name: Add server to placement group
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
placement_group: my-placement-group
- force: True
+ force: true
state: present
- name: Remove server from placement group
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
- placement_group: null
+ placement_group:
state: present
- name: Add server with private network only
- hcloud_server:
+ hetzner.hcloud.server:
name: my-server
enable_ipv4: false
enable_ipv6: false
@@ -257,6 +254,11 @@ hcloud_server:
returned: always
type: str
sample: my-server
+ created:
+ description: Point in time when the Server was created (in ISO-8601 format)
+ returned: always
+ type: str
+ sample: "2023-11-06T13:36:56+00:00"
status:
description: Status of the server
returned: always
@@ -333,44 +335,50 @@ hcloud_server:
version_added: "0.1.0"
"""
+from datetime import datetime, timedelta, timezone
+
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
-from datetime import timedelta
-
-try:
- from hcloud.volumes.domain import Volume
- from hcloud.ssh_keys.domain import SSHKey
- from hcloud.servers.domain import Server, ServerCreatePublicNetwork
- from hcloud.firewalls.domain import FirewallResource
-except ImportError:
- Volume = None
- SSHKey = None
- Server = None
- ServerCreatePublicNetwork = None
- FirewallResource = None
-
-
-class AnsibleHcloudServer(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_server")
- self.hcloud_server = None
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.firewalls import FirewallResource
+from ..module_utils.vendor.hcloud.servers import (
+ BoundServer,
+ Server,
+ ServerCreatePublicNetwork,
+)
+from ..module_utils.vendor.hcloud.ssh_keys import SSHKey
+from ..module_utils.vendor.hcloud.volumes import Volume
+
+
+class AnsibleHCloudServer(AnsibleHCloud):
+ represent = "hcloud_server"
+
+ hcloud_server: BoundServer | None = None
def _prepare_result(self):
image = None if self.hcloud_server.image is None else to_native(self.hcloud_server.image.name)
- placement_group = None if self.hcloud_server.placement_group is None else to_native(
- self.hcloud_server.placement_group.name)
- ipv4_address = None if self.hcloud_server.public_net.ipv4 is None else to_native(
- self.hcloud_server.public_net.ipv4.ip)
+ placement_group = (
+ None if self.hcloud_server.placement_group is None else to_native(self.hcloud_server.placement_group.name)
+ )
+ ipv4_address = (
+ None if self.hcloud_server.public_net.ipv4 is None else to_native(self.hcloud_server.public_net.ipv4.ip)
+ )
ipv6 = None if self.hcloud_server.public_net.ipv6 is None else to_native(self.hcloud_server.public_net.ipv6.ip)
- backup_window = None if self.hcloud_server.backup_window is None else to_native(self.hcloud_server.backup_window)
+ backup_window = (
+ None if self.hcloud_server.backup_window is None else to_native(self.hcloud_server.backup_window)
+ )
return {
"id": to_native(self.hcloud_server.id),
"name": to_native(self.hcloud_server.name),
+ "created": to_native(self.hcloud_server.created.isoformat()),
"ipv4_address": ipv4_address,
"ipv6": ipv6,
"private_networks": [to_native(net.network.name) for net in self.hcloud_server.private_net],
- "private_networks_info": [{"name": to_native(net.network.name), "ip": net.ip} for net in self.hcloud_server.private_net],
+ "private_networks_info": [
+ {"name": to_native(net.network.name), "ip": net.ip} for net in self.hcloud_server.private_net
+ ],
"image": image,
"server_type": to_native(self.hcloud_server.server_type.name),
"datacenter": to_native(self.hcloud_server.datacenter.name),
@@ -387,20 +395,14 @@ class AnsibleHcloudServer(Hcloud):
def _get_server(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_server = self.client.servers.get_by_id(
- self.module.params.get("id")
- )
+ self.hcloud_server = self.client.servers.get_by_id(self.module.params.get("id"))
else:
- self.hcloud_server = self.client.servers.get_by_name(
- self.module.params.get("name")
- )
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ self.hcloud_server = self.client.servers.get_by_name(self.module.params.get("name"))
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_server(self):
- self.module.fail_on_missing_params(
- required_params=["name", "server_type", "image"]
- )
+ self.module.fail_on_missing_params(required_params=["name", "server_type", "image"])
server_type = self._get_server_type()
@@ -413,21 +415,21 @@ class AnsibleHcloudServer(Hcloud):
"placement_group": self._get_placement_group(),
"public_net": ServerCreatePublicNetwork(
enable_ipv4=self.module.params.get("enable_ipv4"),
- enable_ipv6=self.module.params.get("enable_ipv6")
- )
+ enable_ipv6=self.module.params.get("enable_ipv6"),
+ ),
}
if self.module.params.get("ipv4") is not None:
- p = self.client.primary_ips.get_by_name(self.module.params.get("ipv4"))
- if not p:
- p = self.client.primary_ips.get_by_id(self.module.params.get("ipv4"))
- params["public_net"].ipv4 = p
+ primary_ip = self.client.primary_ips.get_by_name(self.module.params.get("ipv4"))
+ if not primary_ip:
+ primary_ip = self.client.primary_ips.get_by_id(self.module.params.get("ipv4"))
+ params["public_net"].ipv4 = primary_ip
if self.module.params.get("ipv6") is not None:
- p = self.client.primary_ips.get_by_name(self.module.params.get("ipv6"))
- if not p:
- p = self.client.primary_ips.get_by_id(self.module.params.get("ipv6"))
- params["public_net"].ipv6 = p
+ primary_ip = self.client.primary_ips.get_by_name(self.module.params.get("ipv6"))
+ if not primary_ip:
+ primary_ip = self.client.primary_ips.get_by_id(self.module.params.get("ipv6"))
+ params["public_net"].ipv6 = primary_ip
if self.module.params.get("private_networks") is not None:
_networks = []
@@ -439,37 +441,28 @@ class AnsibleHcloudServer(Hcloud):
params["networks"] = _networks
if self.module.params.get("ssh_keys") is not None:
- params["ssh_keys"] = [
- SSHKey(name=ssh_key_name)
- for ssh_key_name in self.module.params.get("ssh_keys")
- ]
+ params["ssh_keys"] = [SSHKey(name=ssh_key_name) for ssh_key_name in self.module.params.get("ssh_keys")]
if self.module.params.get("volumes") is not None:
- params["volumes"] = [
- Volume(id=volume_id) for volume_id in self.module.params.get("volumes")
- ]
+ params["volumes"] = [Volume(id=volume_id) for volume_id in self.module.params.get("volumes")]
if self.module.params.get("firewalls") is not None:
params["firewalls"] = []
- for fw in self.module.params.get("firewalls"):
- f = self.client.firewalls.get_by_name(fw)
- if f is not None:
+ for firewall_param in self.module.params.get("firewalls"):
+ firewall = self.client.firewalls.get_by_name(firewall_param)
+ if firewall is not None:
# When firewall name is not available look for id instead
- params["firewalls"].append(f)
+ params["firewalls"].append(firewall)
else:
- params["firewalls"].append(self.client.firewalls.get_by_id(fw))
+ params["firewalls"].append(self.client.firewalls.get_by_id(firewall_param))
if self.module.params.get("location") is None and self.module.params.get("datacenter") is None:
# When not given, the API will choose the location.
params["location"] = None
params["datacenter"] = None
elif self.module.params.get("location") is not None and self.module.params.get("datacenter") is None:
- params["location"] = self.client.locations.get_by_name(
- self.module.params.get("location")
- )
+ 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("datacenter") is not None:
- params["datacenter"] = self.client.datacenters.get_by_name(
- self.module.params.get("datacenter")
- )
+ params["datacenter"] = self.client.datacenters.get_by_name(self.module.params.get("datacenter"))
if self.module.params.get("state") == "stopped":
params["start_after_create"] = False
@@ -494,16 +487,22 @@ class AnsibleHcloudServer(Hcloud):
rebuild_protection = self.module.params.get("rebuild_protection")
if delete_protection is not None and rebuild_protection is not None:
self._get_server()
- self.hcloud_server.change_protection(delete=delete_protection,
- rebuild=rebuild_protection).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ self.hcloud_server.change_protection(
+ delete=delete_protection,
+ rebuild=rebuild_protection,
+ ).wait_until_finished()
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_server()
def _get_image(self, server_type):
- image_resp = self.client.images.get_list(name=self.module.params.get("image"), architecture=server_type.architecture, include_deprecated=True)
- images = getattr(image_resp, 'images')
+ image_resp = self.client.images.get_list(
+ name=self.module.params.get("image"),
+ architecture=server_type.architecture,
+ include_deprecated=True,
+ )
+ images = getattr(image_resp, "images")
image = None
if images is not None and len(images) > 0:
# If image name is not available look for id instead
@@ -511,46 +510,76 @@ class AnsibleHcloudServer(Hcloud):
else:
try:
image = self.client.images.get_by_id(self.module.params.get("image"))
- except Exception:
- self.module.fail_json(msg="Image %s was not found" % self.module.params.get('image'))
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception, msg=f"Image {self.module.params.get('image')} was not found")
if image.deprecated is not None:
available_until = image.deprecated + timedelta(days=90)
if self.module.params.get("allow_deprecated_image"):
self.module.warn(
- "You try to use a deprecated image. The image %s will continue to be available until %s.") % (
- image.name, available_until.strftime('%Y-%m-%d'))
+ f"You try to use a deprecated image. The image {image.name} will "
+ f"continue to be available until {available_until.strftime('%Y-%m-%d')}."
+ )
else:
self.module.fail_json(
- msg=("You try to use a deprecated image. The image %s will continue to be available until %s." +
- " If you want to use this image use allow_deprecated_image=yes."
- ) % (image.name, available_until.strftime('%Y-%m-%d')))
+ msg=(
+ f"You try to use a deprecated image. The image {image.name} will "
+ f"continue to be available until {available_until.strftime('%Y-%m-%d')}. "
+ "If you want to use this image use allow_deprecated_image=true."
+ )
+ )
return image
def _get_server_type(self):
- server_type = self.client.server_types.get_by_name(
- self.module.params.get("server_type")
- )
+ server_type = self.client.server_types.get_by_name(self.module.params.get("server_type"))
if server_type is None:
try:
server_type = self.client.server_types.get_by_id(self.module.params.get("server_type"))
- except Exception:
- self.module.fail_json(msg="server_type %s was not found" % self.module.params.get('server_type'))
+ except HCloudException as exception:
+ self.fail_json_hcloud(
+ exception,
+ msg=f"server_type {self.module.params.get('server_type')} was not found",
+ )
+
+ self._check_and_warn_deprecated_server(server_type)
return server_type
+ def _check_and_warn_deprecated_server(self, server_type):
+ if server_type.deprecation is None:
+ return
+
+ if server_type.deprecation.unavailable_after < datetime.now(timezone.utc):
+ self.module.warn(
+ f"Attention: The server plan {server_type.name} is deprecated and can "
+ "no longer be ordered. Existing servers of that plan will continue to "
+ "work as before and no action is required on your part. "
+ "It is possible to migrate this server to another server plan by setting "
+ "the server_type parameter on the hetzner.hcloud.server module."
+ )
+ else:
+ server_type_unavailable_date = server_type.deprecation.unavailable_after.strftime("%Y-%m-%d")
+ self.module.warn(
+ f"Attention: The server plan {server_type.name} is deprecated and will "
+ f"no longer be available for order as of {server_type_unavailable_date}. "
+ "Existing servers of that plan will continue to work as before and no "
+ "action is required on your part. "
+ "It is possible to migrate this server to another server plan by setting "
+ "the server_type parameter on the hetzner.hcloud.server module."
+ )
+
def _get_placement_group(self):
if self.module.params.get("placement_group") is None:
return None
- placement_group = self.client.placement_groups.get_by_name(
- self.module.params.get("placement_group")
- )
+ placement_group = self.client.placement_groups.get_by_name(self.module.params.get("placement_group"))
if placement_group is None:
try:
placement_group = self.client.placement_groups.get_by_id(self.module.params.get("placement_group"))
- except Exception:
- self.module.fail_json(
- msg="placement_group %s was not found" % self.module.params.get("placement_group"))
+ except HCloudException as exception:
+ self.fail_json_hcloud(
+ exception,
+ msg=f"placement_group {self.module.params.get('placement_group')} was not found",
+ )
return placement_group
@@ -558,20 +587,17 @@ class AnsibleHcloudServer(Hcloud):
if self.module.params.get(field) is None:
return None
- primary_ip = self.client.primary_ips.get_by_name(
- self.module.params.get(field)
- )
+ primary_ip = self.client.primary_ips.get_by_name(self.module.params.get(field))
if primary_ip is None:
try:
primary_ip = self.client.primary_ips.get_by_id(self.module.params.get(field))
- except Exception as e:
- self.module.fail_json(
- msg="primary_ip %s was not found" % self.module.params.get(field))
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception, msg=f"primary_ip {self.module.params.get(field)} was not found")
return primary_ip
def _update_server(self):
- if "force_upgrade" in self.module.params:
+ if "force_upgrade" in self.module.params and self.module.params.get("force_upgrade") is not None:
self.module.warn("force_upgrade is deprecated, use force instead")
try:
@@ -609,30 +635,35 @@ class AnsibleHcloudServer(Hcloud):
for current_firewall in self.hcloud_server.public_net.firewalls:
if current_firewall.firewall.name not in wanted_firewalls:
self._mark_as_changed()
- if not self.module.check_mode:
- r = FirewallResource(type="server", server=self.hcloud_server)
- actions = self.client.firewalls.remove_from_resources(current_firewall.firewall, [r])
- for a in actions:
- a.wait_until_finished()
+ if self.module.check_mode:
+ continue
+
+ firewall_resource = FirewallResource(type="server", server=self.hcloud_server)
+ actions = self.client.firewalls.remove_from_resources(
+ current_firewall.firewall,
+ [firewall_resource],
+ )
+ for action in actions:
+ action.wait_until_finished()
# Adding wanted firewalls that doesn't exist yet
- for fname in wanted_firewalls:
+ for firewall_name in wanted_firewalls:
found = False
- for f in self.hcloud_server.public_net.firewalls:
- if f.firewall.name == fname:
+ for firewall in self.hcloud_server.public_net.firewalls:
+ if firewall.firewall.name == firewall_name:
found = True
break
if not found:
self._mark_as_changed()
if not self.module.check_mode:
- fw = self.client.firewalls.get_by_name(fname)
- if fw is None:
- self.module.fail_json(msg="firewall %s was not found" % fname)
- r = FirewallResource(type="server", server=self.hcloud_server)
- actions = self.client.firewalls.apply_to_resources(fw, [r])
- for a in actions:
- a.wait_until_finished()
+ firewall = self.client.firewalls.get_by_name(firewall_name)
+ if firewall is None:
+ self.module.fail_json(msg=f"firewall {firewall_name} was not found")
+ firewall_resource = FirewallResource(type="server", server=self.hcloud_server)
+ actions = self.client.firewalls.apply_to_resources(firewall, [firewall_resource])
+ for action in actions:
+ action.wait_until_finished()
if "placement_group" in self.module.params:
if self.module.params["placement_group"] is None and self.hcloud_server.placement_group is not None:
@@ -641,12 +672,9 @@ class AnsibleHcloudServer(Hcloud):
self._mark_as_changed()
else:
placement_group = self._get_placement_group()
- if (
- placement_group is not None and
- (
- self.hcloud_server.placement_group is None or
- self.hcloud_server.placement_group.id != placement_group.id
- )
+ if placement_group is not None and (
+ self.hcloud_server.placement_group is None
+ or self.hcloud_server.placement_group.id != placement_group.id
):
self.stop_server_if_forced()
if not self.module.check_mode:
@@ -655,9 +683,9 @@ class AnsibleHcloudServer(Hcloud):
if "ipv4" in self.module.params:
if (
- self.module.params["ipv4"] is None and
- self.hcloud_server.public_net.primary_ipv4 is not None and
- not self.module.params.get("enable_ipv4")
+ self.module.params["ipv4"] is None
+ and self.hcloud_server.public_net.primary_ipv4 is not None
+ and not self.module.params.get("enable_ipv4")
):
self.stop_server_if_forced()
if not self.module.check_mode:
@@ -665,12 +693,9 @@ class AnsibleHcloudServer(Hcloud):
self._mark_as_changed()
else:
primary_ip = self._get_primary_ip("ipv4")
- if (
- primary_ip is not None and
- (
- self.hcloud_server.public_net.primary_ipv4 is None or
- self.hcloud_server.public_net.primary_ipv4.id != primary_ip.id
- )
+ if primary_ip is not None and (
+ self.hcloud_server.public_net.primary_ipv4 is None
+ or self.hcloud_server.public_net.primary_ipv4.id != primary_ip.id
):
self.stop_server_if_forced()
if not self.module.check_mode:
@@ -680,9 +705,9 @@ class AnsibleHcloudServer(Hcloud):
self._mark_as_changed()
if "ipv6" in self.module.params:
if (
- (self.module.params["ipv6"] is None or self.module.params["ipv6"] == "") and
- self.hcloud_server.public_net.primary_ipv6 is not None and
- not self.module.params.get("enable_ipv6")
+ (self.module.params["ipv6"] is None or self.module.params["ipv6"] == "")
+ and self.hcloud_server.public_net.primary_ipv6 is not None
+ and not self.module.params.get("enable_ipv6")
):
self.stop_server_if_forced()
if not self.module.check_mode:
@@ -690,12 +715,9 @@ class AnsibleHcloudServer(Hcloud):
self._mark_as_changed()
else:
primary_ip = self._get_primary_ip("ipv6")
- if (
- primary_ip is not None and
- (
- self.hcloud_server.public_net.primary_ipv6 is None or
- self.hcloud_server.public_net.primary_ipv6.id != primary_ip.id
- )
+ if primary_ip is not None and (
+ self.hcloud_server.public_net.primary_ipv6 is None
+ or self.hcloud_server.public_net.primary_ipv6.id != primary_ip.id
):
self.stop_server_if_forced()
if not self.module.check_mode:
@@ -710,11 +732,10 @@ class AnsibleHcloudServer(Hcloud):
else:
_networks = {}
for network_name_or_id in self.module.params.get("private_networks"):
- _found_network = self.client.networks.get_by_name(network_name_or_id) \
- or self.client.networks.get_by_id(network_name_or_id)
- _networks.update(
- {_found_network.id: _found_network}
- )
+ _found_network = self.client.networks.get_by_name(
+ network_name_or_id
+ ) or self.client.networks.get_by_id(network_name_or_id)
+ _networks.update({_found_network.id: _found_network})
networks_target = _networks
networks_is = dict()
for p_network in self.hcloud_server.private_net:
@@ -732,53 +753,56 @@ class AnsibleHcloudServer(Hcloud):
self._mark_as_changed()
server_type = self.module.params.get("server_type")
- if server_type is not None and self.hcloud_server.server_type.name != server_type:
- self.stop_server_if_forced()
-
- timeout = 100
- if self.module.params.get("upgrade_disk"):
- timeout = (
- 1000
- ) # When we upgrade the disk to the resize progress takes some more time.
- if not self.module.check_mode:
- self.hcloud_server.change_type(
- server_type=self._get_server_type(),
- upgrade_disk=self.module.params.get("upgrade_disk"),
- ).wait_until_finished(timeout)
- self._mark_as_changed()
+ if server_type is not None:
+ if self.hcloud_server.server_type.name == server_type:
+ # Check if we should warn for using an deprecated server type
+ self._check_and_warn_deprecated_server(self.hcloud_server.server_type)
- if (
- not self.module.check_mode and
- (
- (
- self.module.params.get("state") == "present" and
- previous_server_status == Server.STATUS_RUNNING
- ) or
- self.module.params.get("state") == "started"
- )
+ else:
+ # Server type should be changed
+ self.stop_server_if_forced()
+
+ timeout = 100
+ if self.module.params.get("upgrade_disk"):
+ timeout = 1000 # When we upgrade the disk to the resize progress takes some more time.
+ if not self.module.check_mode:
+ self.hcloud_server.change_type(
+ server_type=self._get_server_type(),
+ upgrade_disk=self.module.params.get("upgrade_disk"),
+ ).wait_until_finished(timeout)
+ self._mark_as_changed()
+
+ if not self.module.check_mode and (
+ (self.module.params.get("state") == "present" and previous_server_status == Server.STATUS_RUNNING)
+ or self.module.params.get("state") == "started"
):
self.start_server()
delete_protection = self.module.params.get("delete_protection")
rebuild_protection = self.module.params.get("rebuild_protection")
if (delete_protection is not None and rebuild_protection is not None) and (
- delete_protection != self.hcloud_server.protection["delete"] or rebuild_protection !=
- self.hcloud_server.protection["rebuild"]):
+ delete_protection != self.hcloud_server.protection["delete"]
+ or rebuild_protection != self.hcloud_server.protection["rebuild"]
+ ):
if not self.module.check_mode:
- self.hcloud_server.change_protection(delete=delete_protection,
- rebuild=rebuild_protection).wait_until_finished()
+ self.hcloud_server.change_protection(
+ delete=delete_protection,
+ rebuild=rebuild_protection,
+ ).wait_until_finished()
self._mark_as_changed()
self._get_server()
- except Exception as e:
- self.module.fail_json(msg=e)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _set_rescue_mode(self, rescue_mode):
if self.module.params.get("ssh_keys"):
- resp = self.hcloud_server.enable_rescue(type=rescue_mode,
- ssh_keys=[self.client.ssh_keys.get_by_name(ssh_key_name).id
- for
- ssh_key_name in
- self.module.params.get("ssh_keys")])
+ resp = self.hcloud_server.enable_rescue(
+ type=rescue_mode,
+ ssh_keys=[
+ self.client.ssh_keys.get_by_name(ssh_key_name).id
+ for ssh_key_name in self.module.params.get("ssh_keys")
+ ],
+ )
else:
resp = self.hcloud_server.enable_rescue(type=rescue_mode)
resp.action.wait_until_finished()
@@ -792,8 +816,8 @@ class AnsibleHcloudServer(Hcloud):
self.client.servers.power_on(self.hcloud_server).wait_until_finished()
self._mark_as_changed()
self._get_server()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def stop_server(self):
try:
@@ -803,40 +827,40 @@ class AnsibleHcloudServer(Hcloud):
self.client.servers.power_off(self.hcloud_server).wait_until_finished()
self._mark_as_changed()
self._get_server()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def stop_server_if_forced(self):
previous_server_status = self.hcloud_server.status
if previous_server_status == Server.STATUS_RUNNING and not self.module.check_mode:
if (
- self.module.params.get("force_upgrade") or
- self.module.params.get("force") or
- self.module.params.get("state") == "stopped"
+ self.module.params.get("force_upgrade")
+ or self.module.params.get("force")
+ or self.module.params.get("state") == "stopped"
):
self.stop_server() # Only stopped server can be upgraded
return previous_server_status
else:
self.module.warn(
- "You can not upgrade a running instance %s. You need to stop the instance or use force=yes."
- % self.hcloud_server.name
+ f"You can not upgrade a running instance {self.hcloud_server.name}. "
+ "You need to stop the instance or use force=true."
)
return None
def rebuild_server(self):
- self.module.fail_on_missing_params(
- required_params=["image"]
- )
+ self.module.fail_on_missing_params(required_params=["image"])
try:
if not self.module.check_mode:
image = self._get_image(self.hcloud_server.server_type)
- self.client.servers.rebuild(self.hcloud_server, image).wait_until_finished(1000) # When we rebuild the server progress takes some more time.
+ # When we rebuild the server progress takes some more time.
+ resp = self.client.servers.rebuild(self.hcloud_server, image, return_response=True)
+ resp.action.wait_until_finished(1000)
self._mark_as_changed()
self._get_server()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def present_server(self):
self._get_server()
@@ -853,11 +877,11 @@ class AnsibleHcloudServer(Hcloud):
self.client.servers.delete(self.hcloud_server).wait_until_finished()
self._mark_as_changed()
self.hcloud_server = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
@@ -879,7 +903,7 @@ class AnsibleHcloudServer(Hcloud):
ipv6={"type": "str"},
private_networks={"type": "list", "elements": "str", "default": None},
force={"type": "bool", "default": False},
- force_upgrade={"type": "bool", "default": False},
+ force_upgrade={"type": "bool"},
allow_deprecated_image={"type": "bool", "default": False},
rescue_mode={"type": "str"},
delete_protection={"type": "bool"},
@@ -889,9 +913,9 @@ class AnsibleHcloudServer(Hcloud):
"choices": ["absent", "present", "restarted", "started", "stopped", "rebuild"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name']],
+ required_one_of=[["id", "name"]],
mutually_exclusive=[["location", "datacenter"]],
required_together=[["delete_protection", "rebuild_protection"]],
supports_check_mode=True,
@@ -899,9 +923,9 @@ class AnsibleHcloudServer(Hcloud):
def main():
- module = AnsibleHcloudServer.define_module()
+ module = AnsibleHCloudServer.define_module()
- hcloud = AnsibleHcloudServer(module)
+ hcloud = AnsibleHCloudServer(module)
state = module.params.get("state")
if state == "absent":
hcloud.delete_server()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/server_info.py
index 102ceec0d..cee1634cb 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_info.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/server_info.py
@@ -1,24 +1,20 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_server_info
+module: server_info
short_description: Gather infos about your Hetzner Cloud servers.
description:
- Gather infos about your Hetzner Cloud servers.
- - This module was called C(hcloud_server_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_server_facts).
- Note that the M(hetzner.hcloud.hcloud_server_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_server_info)!
author:
- Lukas Kaemmerling (@LKaemmerling)
@@ -27,6 +23,7 @@ options:
id:
description:
- The ID of the server you want to get.
+ - The module will fail if the provided ID is invalid.
type: int
name:
description:
@@ -39,11 +36,11 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud server infos
- hcloud_server_info:
+ hetzner.hcloud.server_info:
register: output
- name: Print the gathered infos
@@ -67,6 +64,11 @@ hcloud_server_info:
returned: always
type: str
sample: my-server
+ created:
+ description: Point in time when the Server was created (in ISO-8601 format)
+ returned: always
+ type: str
+ sample: "2023-11-06T13:36:56+00:00"
status:
description: Status of the server
returned: always
@@ -144,14 +146,17 @@ hcloud_server_info:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.servers import BoundServer
-class AnsibleHcloudServerInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_server_info")
- self.hcloud_server_info = None
+
+class AnsibleHCloudServerInfo(AnsibleHCloud):
+ represent = "hcloud_server_info"
+
+ hcloud_server_info: list[BoundServer] | None = None
def _prepare_result(self):
tmp = []
@@ -163,81 +168,70 @@ class AnsibleHcloudServerInfo(Hcloud):
ipv4_address = None if server.public_net.ipv4 is None else to_native(server.public_net.ipv4.ip)
ipv6 = None if server.public_net.ipv6 is None else to_native(server.public_net.ipv6.ip)
backup_window = None if server.backup_window is None else to_native(server.backup_window)
- tmp.append({
- "id": to_native(server.id),
- "name": to_native(server.name),
- "ipv4_address": ipv4_address,
- "ipv6": ipv6,
- "private_networks": [to_native(net.network.name) for net in server.private_net],
- "private_networks_info": [{"name": to_native(net.network.name), "ip": net.ip} for net in server.private_net],
- "image": image,
- "server_type": to_native(server.server_type.name),
- "datacenter": to_native(server.datacenter.name),
- "location": to_native(server.datacenter.location.name),
- "placement_group": placement_group,
- "rescue_enabled": server.rescue_enabled,
- "backup_window": backup_window,
- "labels": server.labels,
- "status": to_native(server.status),
- "delete_protection": server.protection["delete"],
- "rebuild_protection": server.protection["rebuild"],
- })
+ tmp.append(
+ {
+ "id": to_native(server.id),
+ "name": to_native(server.name),
+ "created": to_native(server.created.isoformat()),
+ "ipv4_address": ipv4_address,
+ "ipv6": ipv6,
+ "private_networks": [to_native(net.network.name) for net in server.private_net],
+ "private_networks_info": [
+ {"name": to_native(net.network.name), "ip": net.ip} for net in server.private_net
+ ],
+ "image": image,
+ "server_type": to_native(server.server_type.name),
+ "datacenter": to_native(server.datacenter.name),
+ "location": to_native(server.datacenter.location.name),
+ "placement_group": placement_group,
+ "rescue_enabled": server.rescue_enabled,
+ "backup_window": backup_window,
+ "labels": server.labels,
+ "status": to_native(server.status),
+ "delete_protection": server.protection["delete"],
+ "rebuild_protection": server.protection["rebuild"],
+ }
+ )
return tmp
def get_servers(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_server_info = [self.client.servers.get_by_id(
- self.module.params.get("id")
- )]
+ self.hcloud_server_info = [self.client.servers.get_by_id(self.module.params.get("id"))]
elif self.module.params.get("name") is not None:
- self.hcloud_server_info = [self.client.servers.get_by_name(
- self.module.params.get("name")
- )]
+ self.hcloud_server_info = [self.client.servers.get_by_name(self.module.params.get("name"))]
elif self.module.params.get("label_selector") is not None:
self.hcloud_server_info = self.client.servers.get_all(
- label_selector=self.module.params.get("label_selector"))
+ label_selector=self.module.params.get("label_selector")
+ )
else:
self.hcloud_server_info = self.client.servers.get_all()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudServerInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_server_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_server_facts' module has been renamed to 'hcloud_server_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
+ module = AnsibleHCloudServerInfo.define_module()
+ hcloud = AnsibleHCloudServerInfo(module)
- hcloud = AnsibleHcloudServerInfo(module)
hcloud.get_servers()
result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_server_facts': result['hcloud_server_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_server_info': result['hcloud_server_info']
- }
- module.exit_json(**ansible_info)
+ ansible_info = {"hcloud_server_info": result["hcloud_server_info"]}
+ module.exit_json(**ansible_info)
if __name__ == "__main__":
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_network.py b/ansible_collections/hetzner/hcloud/plugins/modules/server_network.py
index 79f6838fd..ca80a8a76 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_network.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/server_network.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_server_network
+module: server_network
short_description: Manage the relationship between Hetzner Cloud Networks and servers
@@ -24,12 +22,12 @@ author:
options:
network:
description:
- - The name of the Hetzner Cloud Networks.
+ - Name or ID of the Hetzner Cloud Networks.
type: str
required: true
server:
description:
- - The name of the Hetzner Cloud server.
+ - Name or ID of the Hetzner Cloud server.
type: str
required: true
ip:
@@ -48,40 +46,36 @@ options:
choices: [ absent, present ]
type: str
-requirements:
- - hcloud-python >= 1.3.0
-
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-
-'''
+"""
EXAMPLES = """
- name: Create a basic server network
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: my-network
server: my-server
state: present
- name: Create a server network and specify the ip address
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: my-network
server: my-server
ip: 10.0.0.1
state: present
- name: Create a server network and add alias ips
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: my-network
server: my-server
ip: 10.0.0.1
alias_ips:
- - 10.1.0.1
- - 10.2.0.1
+ - 10.1.0.1
+ - 10.2.0.1
state: present
- name: Ensure the server network is absent (remove if needed)
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: my-network
server: my-server
state: absent
@@ -110,27 +104,27 @@ hcloud_server_network:
sample: 10.0.0.8
alias_ips:
description: Alias IPs of the server within the Network ip range
- type: str
+ type: list
+ elements: str
returned: always
sample: [10.1.0.1, ...]
"""
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
+from ansible.module_utils.common.text.converters import to_native
-try:
- from hcloud import APIException
-except ImportError:
- APIException = None
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import APIException, HCloudException
+from ..module_utils.vendor.hcloud.networks import BoundNetwork
+from ..module_utils.vendor.hcloud.servers import BoundServer, PrivateNet
-class AnsibleHcloudServerNetwork(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_server_network")
- self.hcloud_network = None
- self.hcloud_server = None
- self.hcloud_server_network = None
+class AnsibleHCloudServerNetwork(AnsibleHCloud):
+ represent = "hcloud_server_network"
+
+ hcloud_network: BoundNetwork | None = None
+ hcloud_server: BoundServer | None = None
+ hcloud_server_network: PrivateNet | None = None
def _prepare_result(self):
return {
@@ -142,20 +136,26 @@ class AnsibleHcloudServerNetwork(Hcloud):
def _get_server_and_network(self):
try:
- self.hcloud_network = self.client.networks.get_by_name(self.module.params.get("network"))
- self.hcloud_server = self.client.servers.get_by_name(self.module.params.get("server"))
+ self.hcloud_network = self._client_get_by_name_or_id(
+ "networks",
+ self.module.params.get("network"),
+ )
+ self.hcloud_server = self._client_get_by_name_or_id(
+ "servers",
+ self.module.params.get("server"),
+ )
self.hcloud_server_network = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _get_server_network(self):
- for privateNet in self.hcloud_server.private_net:
- if privateNet.network.id == self.hcloud_network.id:
- self.hcloud_server_network = privateNet
+ for private_net in self.hcloud_server.private_net:
+ if private_net.network.id == self.hcloud_network.id:
+ self.hcloud_server_network = private_net
def _create_server_network(self):
params = {
- "network": self.hcloud_network
+ "network": self.hcloud_network,
}
if self.module.params.get("ip") is not None:
@@ -166,8 +166,8 @@ class AnsibleHcloudServerNetwork(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_server.attach_to_network(**params).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_server_and_network()
@@ -175,7 +175,7 @@ class AnsibleHcloudServerNetwork(Hcloud):
def _update_server_network(self):
params = {
- "network": self.hcloud_network
+ "network": self.hcloud_network,
}
alias_ips = self.module.params.get("alias_ips")
if alias_ips is not None and sorted(self.hcloud_server_network.alias_ips) != sorted(alias_ips):
@@ -184,8 +184,8 @@ class AnsibleHcloudServerNetwork(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_server.change_alias_ips(**params).wait_until_finished()
- except APIException as e:
- self.module.fail_json(msg=e.message)
+ except APIException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_server_and_network()
@@ -206,13 +206,13 @@ class AnsibleHcloudServerNetwork(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_server.detach_from_network(self.hcloud_server_network.network).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self.hcloud_server_network = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
network={"type": "str", "required": True},
@@ -223,16 +223,16 @@ class AnsibleHcloudServerNetwork(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudServerNetwork.define_module()
+ module = AnsibleHCloudServerNetwork.define_module()
- hcloud = AnsibleHcloudServerNetwork(module)
+ hcloud = AnsibleHCloudServerNetwork(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_server_network()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/server_type_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/server_type_info.py
new file mode 100644
index 000000000..61f1f5011
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/server_type_info.py
@@ -0,0 +1,204 @@
+#!/usr/bin/python
+
+# 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 annotations
+
+DOCUMENTATION = """
+---
+module: server_type_info
+
+short_description: Gather infos about the Hetzner Cloud server types.
+
+
+description:
+ - Gather infos about your Hetzner Cloud server types.
+
+author:
+ - Lukas Kaemmerling (@LKaemmerling)
+
+options:
+ id:
+ description:
+ - The ID of the server type you want to get.
+ - The module will fail if the provided ID is invalid.
+ type: int
+ name:
+ description:
+ - The name of the server type you want to get.
+ type: str
+extends_documentation_fragment:
+- hetzner.hcloud.hcloud
+
+"""
+
+EXAMPLES = """
+- name: Gather hcloud server type infos
+ hetzner.hcloud.server_type_info:
+ register: output
+
+- name: Print the gathered infos
+ debug:
+ var: output.hcloud_server_type_info
+"""
+
+RETURN = """
+hcloud_server_type_info:
+ description: The server type infos as list
+ returned: always
+ type: complex
+ contains:
+ id:
+ description: Numeric identifier of the server type
+ returned: always
+ type: int
+ sample: 1937415
+ name:
+ description: Name of the server type
+ returned: always
+ type: str
+ sample: fsn1
+ description:
+ description: Detail description of the server type
+ returned: always
+ type: str
+ sample: Falkenstein DC Park 1
+ cores:
+ description: Number of cpu cores a server of this type will have
+ returned: always
+ type: int
+ sample: 1
+ memory:
+ description: Memory a server of this type will have in GB
+ returned: always
+ type: int
+ sample: 1
+ disk:
+ description: Disk size a server of this type will have in GB
+ returned: always
+ type: int
+ sample: 25
+ storage_type:
+ description: Type of server boot drive
+ returned: always
+ type: str
+ sample: local
+ cpu_type:
+ description: Type of cpu
+ returned: always
+ type: str
+ sample: shared
+ architecture:
+ description: Architecture of cpu
+ returned: always
+ type: str
+ sample: x86
+ included_traffic:
+ description: Free traffic per month in bytes
+ returned: always
+ type: int
+ sample: 21990232555520
+ deprecation:
+ description: |
+ Describes if, when & how the resources was deprecated.
+ If this field is set to None the resource is not deprecated. If it has a value, it is considered deprecated.
+ returned: success
+ type: dict
+ contains:
+ announced:
+ description: Date of when the deprecation was announced.
+ returned: success
+ type: str
+ sample: "2021-11-09T09:00:00+00:00"
+ unavailable_after:
+ description: |
+ After the time in this field, the resource will not be available from the general listing
+ endpoint of the resource type, and it can not be used in new resources. For example, if this is
+ an image, you can not create new servers with this image after the mentioned date.
+ returned: success
+ type: str
+ sample: "2021-12-01T00:00:00+00:00"
+
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.server_types import BoundServerType
+
+
+class AnsibleHCloudServerTypeInfo(AnsibleHCloud):
+ represent = "hcloud_server_type_info"
+
+ hcloud_server_type_info: list[BoundServerType] | None = None
+
+ def _prepare_result(self):
+ tmp = []
+
+ for server_type in self.hcloud_server_type_info:
+ if server_type is not None:
+ tmp.append(
+ {
+ "id": to_native(server_type.id),
+ "name": to_native(server_type.name),
+ "description": to_native(server_type.description),
+ "cores": server_type.cores,
+ "memory": server_type.memory,
+ "disk": server_type.disk,
+ "storage_type": to_native(server_type.storage_type),
+ "cpu_type": to_native(server_type.cpu_type),
+ "architecture": to_native(server_type.architecture),
+ "included_traffic": server_type.included_traffic,
+ "deprecation": (
+ {
+ "announced": server_type.deprecation.announced.isoformat(),
+ "unavailable_after": server_type.deprecation.unavailable_after.isoformat(),
+ }
+ if server_type.deprecation is not None
+ else None
+ ),
+ }
+ )
+ return tmp
+
+ def get_server_types(self):
+ try:
+ if self.module.params.get("id") is not None:
+ self.hcloud_server_type_info = [self.client.server_types.get_by_id(self.module.params.get("id"))]
+ elif self.module.params.get("name") is not None:
+ self.hcloud_server_type_info = [self.client.server_types.get_by_name(self.module.params.get("name"))]
+ else:
+ self.hcloud_server_type_info = self.client.server_types.get_all()
+
+ 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"},
+ **super().base_module_arguments(),
+ ),
+ supports_check_mode=True,
+ )
+
+
+def main():
+ module = AnsibleHCloudServerTypeInfo.define_module()
+ hcloud = AnsibleHCloudServerTypeInfo(module)
+
+ hcloud.get_server_types()
+ result = hcloud.get_result()
+
+ ansible_info = {"hcloud_server_type_info": result["hcloud_server_type_info"]}
+ module.exit_json(**ansible_info)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key.py b/ansible_collections/hetzner/hcloud/plugins/modules/ssh_key.py
index 59a5197f5..349c52c68 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/ssh_key.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_ssh_key
+module: ssh_key
short_description: Create and manage ssh keys on the Hetzner Cloud.
@@ -55,26 +53,26 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Create a basic ssh_key
- hcloud_ssh_key:
+ hetzner.hcloud.ssh_key:
name: my-ssh_key
- public_key: "ssh-rsa AAAjjk76kgf...Xt"
+ public_key: ssh-rsa AAAjjk76kgf...Xt
state: present
- name: Create a ssh_key with labels
- hcloud_ssh_key:
+ hetzner.hcloud.ssh_key:
name: my-ssh_key
- public_key: "ssh-rsa AAAjjk76kgf...Xt"
+ public_key: ssh-rsa AAAjjk76kgf...Xt
labels:
- key: value
- mylabel: 123
+ key: value
+ mylabel: 123
state: present
- name: Ensure the ssh_key is absent (remove if needed)
- hcloud_ssh_key:
+ hetzner.hcloud.ssh_key:
name: my-ssh_key
state: absent
"""
@@ -115,14 +113,17 @@ hcloud_ssh_key:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.ssh_keys import BoundSSHKey
-class AnsibleHcloudSSHKey(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_ssh_key")
- self.hcloud_ssh_key = None
+
+class AnsibleHCloudSSHKey(AnsibleHCloud):
+ represent = "hcloud_ssh_key"
+
+ hcloud_ssh_key: BoundSSHKey | None = None
def _prepare_result(self):
return {
@@ -136,45 +137,35 @@ class AnsibleHcloudSSHKey(Hcloud):
def _get_ssh_key(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_ssh_key = self.client.ssh_keys.get_by_id(
- self.module.params.get("id")
- )
+ self.hcloud_ssh_key = self.client.ssh_keys.get_by_id(self.module.params.get("id"))
elif self.module.params.get("fingerprint") is not None:
- self.hcloud_ssh_key = self.client.ssh_keys.get_by_fingerprint(
- self.module.params.get("fingerprint")
- )
+ self.hcloud_ssh_key = self.client.ssh_keys.get_by_fingerprint(self.module.params.get("fingerprint"))
elif self.module.params.get("name") is not None:
- self.hcloud_ssh_key = self.client.ssh_keys.get_by_name(
- self.module.params.get("name")
- )
+ self.hcloud_ssh_key = self.client.ssh_keys.get_by_name(self.module.params.get("name"))
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_ssh_key(self):
- self.module.fail_on_missing_params(
- required_params=["name", "public_key"]
- )
+ self.module.fail_on_missing_params(required_params=["name", "public_key"])
params = {
"name": self.module.params.get("name"),
"public_key": self.module.params.get("public_key"),
- "labels": self.module.params.get("labels")
+ "labels": self.module.params.get("labels"),
}
if not self.module.check_mode:
try:
self.client.ssh_keys.create(**params)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_ssh_key()
def _update_ssh_key(self):
name = self.module.params.get("name")
if name is not None and self.hcloud_ssh_key.name != name:
- self.module.fail_on_missing_params(
- required_params=["id"]
- )
+ self.module.fail_on_missing_params(required_params=["id"])
if not self.module.check_mode:
self.hcloud_ssh_key.update(name=name)
self._mark_as_changed()
@@ -200,13 +191,13 @@ class AnsibleHcloudSSHKey(Hcloud):
if not self.module.check_mode:
try:
self.client.ssh_keys.delete(self.hcloud_ssh_key)
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self.hcloud_ssh_key = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
@@ -218,18 +209,18 @@ class AnsibleHcloudSSHKey(Hcloud):
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name', 'fingerprint']],
- required_if=[['state', 'present', ['name']]],
+ required_one_of=[["id", "name", "fingerprint"]],
+ required_if=[["state", "present", ["name"]]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudSSHKey.define_module()
+ module = AnsibleHCloudSSHKey.define_module()
- hcloud = AnsibleHcloudSSHKey(module)
+ hcloud = AnsibleHCloudSSHKey(module)
state = module.params.get("state")
if state == "absent":
hcloud.delete_ssh_key()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_facts.py b/ansible_collections/hetzner/hcloud/plugins/modules/ssh_key_info.py
index aab98ed60..7a4ab5928 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_facts.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/ssh_key_info.py
@@ -1,27 +1,24 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_ssh_key_info
+module: ssh_key_info
short_description: Gather infos about your Hetzner Cloud ssh_keys.
description:
- Gather facts about your Hetzner Cloud ssh_keys.
- - This module was called C(hcloud_ssh_key_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_ssh_key_facts).
- Note that the M(hetzner.hcloud.hcloud_ssh_key_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_ssh_key_info)!
author:
- Christopher Schmitt (@cschmitt-hcloud)
options:
id:
description:
- The ID of the ssh key you want to get.
+ - The module will fail if the provided ID is invalid.
type: int
name:
description:
@@ -38,11 +35,11 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud sshkey infos
- hcloud_ssh_key_info:
+ hetzner.hcloud.ssh_key_info:
register: output
- name: Print the gathered infos
debug:
@@ -80,89 +77,79 @@ hcloud_ssh_key_info:
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.ssh_keys import BoundSSHKey
-class AnsibleHcloudSSHKeyInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_ssh_key_info")
- self.hcloud_ssh_key_info = None
+class AnsibleHCloudSSHKeyInfo(AnsibleHCloud):
+ represent = "hcloud_ssh_key_info"
+
+ hcloud_ssh_key_info: list[BoundSSHKey] | None = None
def _prepare_result(self):
ssh_keys = []
for ssh_key in self.hcloud_ssh_key_info:
if ssh_key:
- ssh_keys.append({
- "id": to_native(ssh_key.id),
- "name": to_native(ssh_key.name),
- "fingerprint": to_native(ssh_key.fingerprint),
- "public_key": to_native(ssh_key.public_key),
- "labels": ssh_key.labels
- })
+ ssh_keys.append(
+ {
+ "id": to_native(ssh_key.id),
+ "name": to_native(ssh_key.name),
+ "fingerprint": to_native(ssh_key.fingerprint),
+ "public_key": to_native(ssh_key.public_key),
+ "labels": ssh_key.labels,
+ }
+ )
return ssh_keys
def get_ssh_keys(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_id(
- self.module.params.get("id")
- )]
+ self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_id(self.module.params.get("id"))]
elif self.module.params.get("name") is not None:
- self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_name(
- self.module.params.get("name")
- )]
+ self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_name(self.module.params.get("name"))]
elif self.module.params.get("fingerprint") is not None:
- self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_fingerprint(
- self.module.params.get("fingerprint")
- )]
+ self.hcloud_ssh_key_info = [
+ self.client.ssh_keys.get_by_fingerprint(self.module.params.get("fingerprint"))
+ ]
elif self.module.params.get("label_selector") is not None:
self.hcloud_ssh_key_info = self.client.ssh_keys.get_all(
- label_selector=self.module.params.get("label_selector"))
+ label_selector=self.module.params.get("label_selector")
+ )
else:
self.hcloud_ssh_key_info = self.client.ssh_keys.get_all()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
fingerprint={"type": "str"},
label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudSSHKeyInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_ssh_key_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_ssh_key_facts' module has been renamed to 'hcloud_ssh_key_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
+ module = AnsibleHCloudSSHKeyInfo.define_module()
+ hcloud = AnsibleHCloudSSHKeyInfo(module)
- hcloud = AnsibleHcloudSSHKeyInfo(module)
hcloud.get_ssh_keys()
result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_ssh_key_facts': result['hcloud_ssh_key_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_ssh_key_info': result['hcloud_ssh_key_info']
- }
- module.exit_json(**ansible_info)
+ ansible_info = {"hcloud_ssh_key_info": result["hcloud_ssh_key_info"]}
+ module.exit_json(**ansible_info)
if __name__ == "__main__":
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_subnetwork.py b/ansible_collections/hetzner/hcloud/plugins/modules/subnetwork.py
index c2ba66d80..aea40bb13 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_subnetwork.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/subnetwork.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_subnetwork
+module: subnetwork
short_description: Manage cloud subnetworks on the Hetzner Cloud.
@@ -24,7 +22,7 @@ author:
options:
network:
description:
- - The ID or Name of the Hetzner Cloud Networks.
+ - The name or ID of the Hetzner Cloud Networks.
type: str
required: true
ip_range:
@@ -55,17 +53,13 @@ options:
choices: [ absent, present ]
type: str
-requirements:
- - hcloud-python >= 1.10.0
-
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-
-'''
+"""
EXAMPLES = """
- name: Create a basic subnetwork
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: my-network
ip_range: 10.0.0.0/16
network_zone: eu-central
@@ -73,7 +67,7 @@ EXAMPLES = """
state: present
- name: Create a basic subnetwork
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: my-vswitch-network
ip_range: 10.0.0.0/24
network_zone: eu-central
@@ -82,7 +76,7 @@ EXAMPLES = """
state: present
- name: Ensure the subnetwork is absent (remove if needed)
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: my-network
ip_range: 10.0.0.0/8
network_zone: eu-central
@@ -129,20 +123,18 @@ hcloud_subnetwork:
"""
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
+from ansible.module_utils.common.text.converters import to_native
-try:
- from hcloud.networks.domain import NetworkSubnet
-except ImportError:
- NetworkSubnet = None
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.networks import BoundNetwork, NetworkSubnet
-class AnsibleHcloudSubnetwork(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_subnetwork")
- self.hcloud_network = None
- self.hcloud_subnetwork = None
+class AnsibleHCloudSubnetwork(AnsibleHCloud):
+ represent = "hcloud_subnetwork"
+
+ hcloud_network: BoundNetwork | None = None
+ hcloud_subnetwork: NetworkSubnet | None = None
def _prepare_result(self):
return {
@@ -156,10 +148,13 @@ class AnsibleHcloudSubnetwork(Hcloud):
def _get_network(self):
try:
- self.hcloud_network = self.client.networks.get_by_name(self.module.params.get("network"))
+ self.hcloud_network = self._client_get_by_name_or_id(
+ "networks",
+ self.module.params.get("network"),
+ )
self.hcloud_subnetwork = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _get_subnetwork(self):
subnet_ip_range = self.module.params.get("ip_range")
@@ -170,20 +165,18 @@ class AnsibleHcloudSubnetwork(Hcloud):
def _create_subnetwork(self):
params = {
"ip_range": self.module.params.get("ip_range"),
- "type": self.module.params.get('type'),
- "network_zone": self.module.params.get('network_zone')
+ "type": self.module.params.get("type"),
+ "network_zone": self.module.params.get("network_zone"),
}
- if self.module.params.get('type') == NetworkSubnet.TYPE_VSWITCH:
- self.module.fail_on_missing_params(
- required_params=["vswitch_id"]
- )
- params["vswitch_id"] = self.module.params.get('vswitch_id')
+ if self.module.params.get("type") == NetworkSubnet.TYPE_VSWITCH:
+ self.module.fail_on_missing_params(required_params=["vswitch_id"])
+ params["vswitch_id"] = self.module.params.get("vswitch_id")
if not self.module.check_mode:
try:
self.hcloud_network.add_subnet(subnet=NetworkSubnet(**params)).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_network()
@@ -202,38 +195,34 @@ class AnsibleHcloudSubnetwork(Hcloud):
if not self.module.check_mode:
try:
self.hcloud_network.delete_subnet(self.hcloud_subnetwork).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self.hcloud_subnetwork = None
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
network={"type": "str", "required": True},
network_zone={"type": "str", "required": True},
- type={
- "type": "str",
- "required": True,
- "choices": ["server", "cloud", "vswitch"]
- },
+ type={"type": "str", "required": True, "choices": ["server", "cloud", "vswitch"]},
ip_range={"type": "str", "required": True},
vswitch_id={"type": "int"},
state={
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudSubnetwork.define_module()
+ module = AnsibleHCloudSubnetwork.define_module()
- hcloud = AnsibleHcloudSubnetwork(module)
+ hcloud = AnsibleHCloudSubnetwork(module)
state = module.params["state"]
if state == "absent":
hcloud.delete_subnetwork()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume.py b/ansible_collections/hetzner/hcloud/plugins/modules/volume.py
index 623a399b4..8442ed90b 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/volume.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_volume
+module: volume
short_description: Create and manage block Volume on the Hetzner Cloud.
@@ -75,36 +73,36 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Create a Volume
- hcloud_volume:
+ hetzner.hcloud.volume:
name: my-volume
location: fsn1
size: 100
state: present
- name: Create a Volume and format it with ext4
- hcloud_volume:
+ hetzner.hcloud.volume:
name: my-volume
location: fsn
format: ext4
size: 100
state: present
- name: Mount a existing Volume and automount
- hcloud_volume:
+ hetzner.hcloud.volume:
name: my-volume
server: my-server
- automount: yes
+ automount: true
state: present
- name: Mount a existing Volume and automount
- hcloud_volume:
+ hetzner.hcloud.volume:
name: my-volume
server: my-server
- automount: yes
+ automount: true
state: present
- name: Ensure the Volume is absent (remove if needed)
- hcloud_volume:
+ hetzner.hcloud.volume:
name: my-volume
state: absent
"""
@@ -162,14 +160,17 @@ hcloud_volume:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.volumes import BoundVolume
+
+class AnsibleHCloudVolume(AnsibleHCloud):
+ represent = "hcloud_volume"
-class AnsibleHcloudVolume(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_volume")
- self.hcloud_volume = None
+ hcloud_volume: BoundVolume | None = None
def _prepare_result(self):
server_name = None
@@ -190,31 +191,25 @@ class AnsibleHcloudVolume(Hcloud):
def _get_volume(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_volume = self.client.volumes.get_by_id(
- self.module.params.get("id")
- )
+ self.hcloud_volume = self.client.volumes.get_by_id(self.module.params.get("id"))
else:
- self.hcloud_volume = self.client.volumes.get_by_name(
- self.module.params.get("name")
- )
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ self.hcloud_volume = self.client.volumes.get_by_name(self.module.params.get("name"))
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def _create_volume(self):
- self.module.fail_on_missing_params(
- required_params=["name", "size"]
- )
+ self.module.fail_on_missing_params(required_params=["name", "size"])
params = {
"name": self.module.params.get("name"),
"size": self.module.params.get("size"),
"automount": self.module.params.get("automount"),
"format": self.module.params.get("format"),
- "labels": self.module.params.get("labels")
+ "labels": self.module.params.get("labels"),
}
if self.module.params.get("server") is not None:
- params['server'] = self.client.servers.get_by_name(self.module.params.get("server"))
+ params["server"] = self.client.servers.get_by_name(self.module.params.get("server"))
elif self.module.params.get("location") is not None:
- params['location'] = self.client.locations.get_by_name(self.module.params.get("location"))
+ params["location"] = self.client.locations.get_by_name(self.module.params.get("location"))
else:
self.module.fail_json(msg="server or location is required")
@@ -227,8 +222,8 @@ class AnsibleHcloudVolume(Hcloud):
if delete_protection is not None:
self._get_volume()
self.hcloud_volume.change_protection(delete=delete_protection).wait_until_finished()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
self._mark_as_changed()
self._get_volume()
@@ -270,8 +265,8 @@ class AnsibleHcloudVolume(Hcloud):
self._mark_as_changed()
self._get_volume()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
def present_volume(self):
self._get_volume()
@@ -290,11 +285,11 @@ class AnsibleHcloudVolume(Hcloud):
self.client.volumes.delete(self.hcloud_volume)
self._mark_as_changed()
self.hcloud_volume = None
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
@@ -304,31 +299,27 @@ class AnsibleHcloudVolume(Hcloud):
server={"type": "str"},
labels={"type": "dict"},
automount={"type": "bool", "default": False},
- format={"type": "str",
- "choices": ['xfs', 'ext4'],
- },
+ format={"type": "str", "choices": ["xfs", "ext4"]},
delete_protection={"type": "bool"},
state={
"choices": ["absent", "present"],
"default": "present",
},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
- required_one_of=[['id', 'name']],
+ required_one_of=[["id", "name"]],
mutually_exclusive=[["location", "server"]],
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudVolume.define_module()
+ module = AnsibleHCloudVolume.define_module()
- hcloud = AnsibleHcloudVolume(module)
+ hcloud = AnsibleHCloudVolume(module)
state = module.params.get("state")
if state == "absent":
- module.fail_on_missing_params(
- required_params=["name"]
- )
+ module.fail_on_missing_params(required_params=["name"])
hcloud.delete_volume()
else:
hcloud.present_volume()
diff --git a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_info.py b/ansible_collections/hetzner/hcloud/plugins/modules/volume_info.py
index 9520bfa14..1e507690e 100644
--- a/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_info.py
+++ b/ansible_collections/hetzner/hcloud/plugins/modules/volume_info.py
@@ -1,16 +1,14 @@
#!/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
+from __future__ import annotations
-DOCUMENTATION = '''
+DOCUMENTATION = """
---
-module: hcloud_volume_info
+module: volume_info
short_description: Gather infos about your Hetzner Cloud Volumes.
@@ -24,6 +22,7 @@ options:
id:
description:
- The ID of the Volume you want to get.
+ - The module will fail if the provided ID is invalid.
type: int
name:
description:
@@ -36,11 +35,11 @@ options:
extends_documentation_fragment:
- hetzner.hcloud.hcloud
-'''
+"""
EXAMPLES = """
- name: Gather hcloud Volume infos
- hcloud_volume_info:
+ hetzner.hcloud.volume_info:
register: output
- name: Print the gathered infos
debug:
@@ -96,14 +95,17 @@ hcloud_volume_info:
"""
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
+from ansible.module_utils.common.text.converters import to_native
+
+from ..module_utils.hcloud import AnsibleHCloud
+from ..module_utils.vendor.hcloud import HCloudException
+from ..module_utils.vendor.hcloud.volumes import BoundVolume
+
+class AnsibleHCloudVolumeInfo(AnsibleHCloud):
+ represent = "hcloud_volume_info"
-class AnsibleHcloudVolumeInfo(Hcloud):
- def __init__(self, module):
- Hcloud.__init__(self, module, "hcloud_volume_info")
- self.hcloud_volume_info = None
+ hcloud_volume_info: list[BoundVolume] | None = None
def _prepare_result(self):
tmp = []
@@ -113,73 +115,59 @@ class AnsibleHcloudVolumeInfo(Hcloud):
server_name = None
if volume.server is not None:
server_name = to_native(volume.server.name)
- tmp.append({
- "id": to_native(volume.id),
- "name": to_native(volume.name),
- "size": volume.size,
- "location": to_native(volume.location.name),
- "labels": volume.labels,
- "server": server_name,
- "linux_device": to_native(volume.linux_device),
- "delete_protection": volume.protection["delete"],
- })
+ tmp.append(
+ {
+ "id": to_native(volume.id),
+ "name": to_native(volume.name),
+ "size": volume.size,
+ "location": to_native(volume.location.name),
+ "labels": volume.labels,
+ "server": server_name,
+ "linux_device": to_native(volume.linux_device),
+ "delete_protection": volume.protection["delete"],
+ }
+ )
return tmp
def get_volumes(self):
try:
if self.module.params.get("id") is not None:
- self.hcloud_volume_info = [self.client.volumes.get_by_id(
- self.module.params.get("id")
- )]
+ self.hcloud_volume_info = [self.client.volumes.get_by_id(self.module.params.get("id"))]
elif self.module.params.get("name") is not None:
- self.hcloud_volume_info = [self.client.volumes.get_by_name(
- self.module.params.get("name")
- )]
+ self.hcloud_volume_info = [self.client.volumes.get_by_name(self.module.params.get("name"))]
elif self.module.params.get("label_selector") is not None:
self.hcloud_volume_info = self.client.volumes.get_all(
- label_selector=self.module.params.get("label_selector"))
+ label_selector=self.module.params.get("label_selector")
+ )
else:
self.hcloud_volume_info = self.client.volumes.get_all()
- except Exception as e:
- self.module.fail_json(msg=e.message)
+ except HCloudException as exception:
+ self.fail_json_hcloud(exception)
- @staticmethod
- def define_module():
+ @classmethod
+ def define_module(cls):
return AnsibleModule(
argument_spec=dict(
id={"type": "int"},
name={"type": "str"},
label_selector={"type": "str"},
- **Hcloud.base_module_arguments()
+ **super().base_module_arguments(),
),
supports_check_mode=True,
)
def main():
- module = AnsibleHcloudVolumeInfo.define_module()
-
- is_old_facts = module._name == 'hcloud_volume_facts'
- if is_old_facts:
- module.deprecate("The 'hcloud_volume_facts' module has been renamed to 'hcloud_volume_info', "
- "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud")
-
- hcloud = AnsibleHcloudVolumeInfo(module)
+ module = AnsibleHCloudVolumeInfo.define_module()
+ hcloud = AnsibleHCloudVolumeInfo(module)
hcloud.get_volumes()
result = hcloud.get_result()
- if is_old_facts:
- ansible_info = {
- 'hcloud_volume_facts': result['hcloud_volume_info']
- }
- module.exit_json(ansible_facts=ansible_info)
- else:
- ansible_info = {
- 'hcloud_volume_info': result['hcloud_volume_info']
- }
- module.exit_json(**ansible_info)
+
+ ansible_info = {"hcloud_volume_info": result["hcloud_volume_info"]}
+ module.exit_json(**ansible_info)
if __name__ == "__main__":
diff --git a/ansible_collections/hetzner/hcloud/pyproject.toml b/ansible_collections/hetzner/hcloud/pyproject.toml
new file mode 100644
index 000000000..5263580cb
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/pyproject.toml
@@ -0,0 +1,28 @@
+[tool.black]
+line-length = 120
+
+[tool.isort]
+profile = "black"
+combine_as_imports = true
+add_imports = ["from __future__ import annotations"]
+
+[tool.pylint.main]
+py-version = "3.8"
+recursive = true
+jobs = 0
+
+max-line-length = 120
+ignore-paths = [
+ "plugins/module_utils/vendor",
+]
+
+[tool.pylint.reports]
+output-format = "colorized"
+
+[tool.pylint.basic]
+good-names = ["i", "j", "k", "ex", "_", "ip", "id"]
+
+[tool.pylint.messages_control]
+disable = [
+ "wrong-import-position",
+]
diff --git a/ansible_collections/hetzner/hcloud/renovate.json b/ansible_collections/hetzner/hcloud/renovate.json
new file mode 100644
index 000000000..94c5bd199
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/renovate.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "extends": ["github>hetznercloud/.github//renovate/default"],
+ "regexManagers": [
+ {
+ "fileMatch": ["^scripts/vendor.py$"],
+ "matchStrings": ["HCLOUD_VERSION = \"v(?<currentValue>.*)\""],
+ "datasourceTemplate": "pypi",
+ "depNameTemplate": "hcloud"
+ }
+ ]
+}
diff --git a/ansible_collections/hetzner/hcloud/requirements.txt b/ansible_collections/hetzner/hcloud/requirements.txt
new file mode 100644
index 000000000..0e9148f96
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/requirements.txt
@@ -0,0 +1,12 @@
+ansible-core>=2.13
+
+# Collections requirements
+netaddr
+cryptography
+
+python-dateutil
+requests
+
+# Development requirements
+pylint
+antsibull-docs>=2.7,<2.8
diff --git a/ansible_collections/hetzner/hcloud/scripts/integration-test-files.sh b/ansible_collections/hetzner/hcloud/scripts/integration-test-files.sh
new file mode 100755
index 000000000..fbae089b5
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/scripts/integration-test-files.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+# Sync the integration test files from the template to all the integrations targets.
+
+integration_targets="tests/integration/targets/"
+integration_common="tests/integration/common"
+
+# banner
+banner() {
+ echo "#"
+ echo "# DO NOT EDIT THIS FILE! Please edit the files in $integration_common instead."
+ echo "#"
+}
+
+# copy_file <src> <dest>
+copy_file() {
+ mkdir -p "$(dirname "$2")"
+ banner > "$2"
+ cat "$1" >> "$2"
+}
+
+for target in "$integration_targets"*; do
+ if [[ "$(basename "$target")" = setup_* ]]; then
+ continue
+ fi
+ copy_file "$integration_common"/defaults/main/common.yml "$target"/defaults/main/common.yml
+ copy_file "$integration_common"/tasks/main.yml "$target"/tasks/main.yml
+done
diff --git a/ansible_collections/hetzner/hcloud/scripts/vendor.py b/ansible_collections/hetzner/hcloud/scripts/vendor.py
new file mode 100755
index 000000000..b55a66577
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/scripts/vendor.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python3
+
+"""
+Fetch and bundles the hcloud package inside the collection.
+
+Fetch the desired version `HCLOUD_VERSION` from https://github.com/hetznercloud/hcloud-python
+`HCLOUD_SOURCE_URL` using git, apply some code modifications to comply with ansible,
+move the modified files at the vendor location `HCLOUD_VENDOR_PATH`.
+"""
+
+from __future__ import annotations
+
+import logging
+import re
+from argparse import ArgumentParser
+from pathlib import Path
+from shutil import move, rmtree
+from subprocess import check_call
+from tempfile import TemporaryDirectory
+from textwrap import dedent
+
+logger = logging.getLogger("vendor")
+
+HCLOUD_SOURCE_URL = "https://github.com/hetznercloud/hcloud-python"
+HCLOUD_VERSION = "v1.33.2"
+HCLOUD_VENDOR_PATH = "plugins/module_utils/vendor/hcloud"
+
+
+def apply_code_modifications(source_path: Path):
+ # The ansible galaxy-importer consider __version___.py to be an invalid filename in module_utils/
+ # Move the __version__.py file to _version.py
+ move(source_path / "__version__.py", source_path / "_version.py")
+
+ for file in source_path.rglob("*.py"):
+ content = file.read_text()
+ content_orig = content
+
+ # Move the __version__.py file to _version.py
+ content = re.sub(
+ r"from .__version__ import VERSION",
+ r"from ._version import VERSION",
+ content,
+ )
+
+ # Wrap requests imports
+ content = re.sub(
+ r"import requests",
+ dedent(
+ r"""
+ try:
+ import requests
+ except ImportError:
+ requests = None
+ """
+ ).strip(),
+ content,
+ )
+
+ # Wrap dateutil imports
+ content = re.sub(
+ r"from dateutil.parser import isoparse",
+ dedent(
+ r"""
+ try:
+ from dateutil.parser import isoparse
+ except ImportError:
+ isoparse = None
+ """
+ ).strip(),
+ content,
+ )
+
+ # Remove requests.Response typings
+ content = re.sub(
+ r": requests\.Response",
+ r"",
+ content,
+ )
+
+ if content != content_orig:
+ logger.info("Applied code modifications on %s", file)
+
+ file.write_text(content)
+
+
+def main(check: bool = False) -> int:
+ with TemporaryDirectory() as tmp_dir:
+ tmp_dir_path = Path(tmp_dir)
+ logger.info("Created temporary directory %s", tmp_dir_path)
+
+ check_call(["git", "clone", "--depth=1", "--branch", HCLOUD_VERSION, HCLOUD_SOURCE_URL, tmp_dir_path])
+ logger.info("Cloned the source files in %s", tmp_dir_path)
+
+ apply_code_modifications(tmp_dir_path / "hcloud")
+ logger.info("Applied code modifications on the source files")
+
+ rmtree(HCLOUD_VENDOR_PATH)
+ move(tmp_dir_path / "hcloud", HCLOUD_VENDOR_PATH)
+ logger.info("Bundled the modified sources files in the collection")
+
+ if check:
+ check_call(["git", "diff", "--exit-code", "--", HCLOUD_VENDOR_PATH])
+
+ return 0
+
+
+if __name__ == "__main__":
+ logging.basicConfig(level=logging.INFO, format="%(levelname)-8s: %(message)s")
+
+ parser = ArgumentParser()
+ parser.add_argument("--check", action="store_true", default=False)
+ args = parser.parse_args()
+
+ raise SystemExit(main(check=args.check))
diff --git a/ansible_collections/hetzner/hcloud/tests/config.yml b/ansible_collections/hetzner/hcloud/tests/config.yml
new file mode 100644
index 000000000..340add1aa
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/config.yml
@@ -0,0 +1,3 @@
+---
+modules:
+ python_requires: ">=3.8"
diff --git a/ansible_collections/hetzner/hcloud/tests/constraints.txt b/ansible_collections/hetzner/hcloud/tests/constraints.txt
new file mode 100644
index 000000000..7e72ee478
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/constraints.txt
@@ -0,0 +1,2 @@
+python-dateutil>=2.7.5
+requests>=2.20
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/README.md b/ansible_collections/hetzner/hcloud/tests/integration/README.md
new file mode 100644
index 000000000..e3bb08319
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/README.md
@@ -0,0 +1,27 @@
+# Integration tests
+
+This document provides information to work with the integration tests.
+
+## Guidelines
+
+A set of guidelines to follow when writing integrations tests.
+
+### Prepare and cleanup
+
+The integration tests use a small testing framework that helps to set up and teardown any resources needed or generated by the tests. This small testing framework is located in the `tests/integration/common` directory. The files within the `common` directory are then duplicated and kept in sync in all the integration tests targets (`tests/integration/targets/hcloud_*`).
+
+- Use a `tasks/prepare.yml` file to set up resources needed during the tests.
+- Use a `tasks/cleanup.yml` file to teardown resources from the `tasts/prepare.yml` tasks **and** the resources generated by the tests.
+- Use a `tasks/test.yml` file to defines your tests.
+- You may explode the tests into multiple `tasks/test-*.yml` files and import them in the `tasks/test.yml` file.
+- The `tasks/cleanup.yml` file cannot use variables present in the `tasks/prepare.yml` file because cleanup should also run before the prepare tasks.
+
+### Naming convention
+
+The integration tests handle a lot of different variables, names, identifier. To reduce this complexity, make sure to use the following naming conventions:
+
+- Any test resources MUST be registered using the `test_<resource>` variable name (e.g. `test_server` or `test_floating_ip`) and MUST be created and cleaned in the `tasks/prepare.yml` and `tasks/cleanup.yml`. The scope of this variable is the entire target.
+- In `tasks/prepare.yml`, tasks names MUST start with: `Create test_<resource>` (e.g. `Create test_server` or `Create test_floating_ip`)
+- In `tasks/cleanup.yml`, tasks names MUST start with: `Cleanup test_<resource>` (e.g. `Cleanup test_server` or `Cleanup test_floating_ip`)
+- Any fact starting with `_` is scoped to the current file and MUST NOT be used outside of it.
+- Any test result MUST be registered using the `result` variable name unless it is required in a future test, in that case it MUST use the `<resource>` variable name as prefix.
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/common/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/common/defaults/main/common.yml
new file mode 100644
index 000000000..e45380565
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/common/defaults/main/common.yml
@@ -0,0 +1,9 @@
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/common/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/common/tasks/main.yml
new file mode 100644
index 000000000..c3f93a394
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/common/tasks/main.yml
@@ -0,0 +1,28 @@
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/constraints.txt b/ansible_collections/hetzner/hcloud/tests/integration/constraints.txt
deleted file mode 100644
index 19d5ecf28..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/constraints.txt
+++ /dev/null
@@ -1 +0,0 @@
-hcloud >= 1.10.0 # minimum version
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/requirements.txt b/ansible_collections/hetzner/hcloud/tests/integration/requirements.txt
index d3249deff..8b3801627 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/requirements.txt
+++ b/ansible_collections/hetzner/hcloud/tests/integration/requirements.txt
@@ -1,2 +1,5 @@
netaddr
-hcloud
+cryptography
+
+python-dateutil
+requests
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/defaults/main/main.yml
new file mode 100644
index 000000000..e94b57771
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/defaults/main/main.yml
@@ -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_certificate_name: "{{ hcloud_ns }}"
+hcloud_dns_test_domain: "{{ (hcloud_ns + 100 | random | string) | md5 }}.hc-integrations-test.de"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/meta/main.yml
index 34657c1c2..163f4db09 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/meta/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/meta/main.yml
@@ -1,4 +1,3 @@
+---
dependencies:
- setup_selfsigned_certificate
-collections:
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/cleanup.yml
new file mode 100644
index 000000000..2513909aa
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: cleanup test certificate
+ hetzner.hcloud.certificate:
+ name: "{{ hcloud_certificate_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/test.yml
index 615c89d0e..240e6a18c 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate/tasks/test.yml
@@ -2,10 +2,10 @@
# 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:
+ hetzner.hcloud.certificate:
name: "{{ hcloud_certificate_name }}"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing required parameters on create certificate
assert:
that:
@@ -13,22 +13,22 @@
- 'result.msg == "missing required arguments: certificate, private_key"'
- name: test create certificate with check mode
- hcloud_certificate:
+ hetzner.hcloud.certificate:
name: "{{ hcloud_certificate_name }}"
- certificate: "{{ certificate_example_com }}"
- private_key: "{{ certificate_example_com_key }}"
+ certificate: "{{ test_certificate_content }}"
+ private_key: "{{ test_certificate_privatekey_content }}"
register: result
- check_mode: yes
+ check_mode: true
- name: test create certificate with check mode
assert:
that:
- result is changed
- name: test create certificate
- hcloud_certificate:
+ hetzner.hcloud.certificate:
name: "{{ hcloud_certificate_name }}"
- certificate: "{{ certificate_example_com }}"
- private_key: "{{ certificate_example_com_key }}"
+ certificate: "{{ test_certificate_content }}"
+ private_key: "{{ test_certificate_privatekey_content }}"
labels:
key: value
my-label: label
@@ -37,15 +37,15 @@
assert:
that:
- certificate is changed
- - certificate.hcloud_certificate.name == "{{ hcloud_certificate_name }}"
+ - 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:
+ hetzner.hcloud.certificate:
name: "{{ hcloud_certificate_name }}"
- certificate: "{{ certificate_example_com }}"
- private_key: "{{ certificate_example_com_key }}"
+ certificate: "{{ test_certificate_content }}"
+ private_key: "{{ test_certificate_privatekey_content }}"
register: result
- name: verify create certificate idempotence
assert:
@@ -53,18 +53,18 @@
- result is not changed
- name: test update certificate with check mode
- hcloud_certificate:
+ hetzner.hcloud.certificate:
id: "{{ certificate.hcloud_certificate.id }}"
name: "changed-{{ hcloud_certificate_name }}"
register: result
- check_mode: yes
+ check_mode: true
- name: test create certificate with check mode
assert:
that:
- result is changed
- name: test update certificate
- hcloud_certificate:
+ hetzner.hcloud.certificate:
id: "{{ certificate.hcloud_certificate.id }}"
name: "changed-{{ hcloud_certificate_name }}"
labels:
@@ -77,7 +77,7 @@
- result.hcloud_certificate.name == "changed-{{ hcloud_certificate_name }}"
- name: test update certificate with same labels
- hcloud_certificate:
+ hetzner.hcloud.certificate:
id: "{{ certificate.hcloud_certificate.id }}"
name: "changed-{{ hcloud_certificate_name }}"
labels:
@@ -89,7 +89,7 @@
- result is not changed
- name: test update certificate with other labels
- hcloud_certificate:
+ hetzner.hcloud.certificate:
id: "{{ certificate.hcloud_certificate.id }}"
name: "changed-{{ hcloud_certificate_name }}"
labels:
@@ -102,7 +102,7 @@
- result is changed
- name: test rename certificate
- hcloud_certificate:
+ hetzner.hcloud.certificate:
id: "{{ certificate.hcloud_certificate.id }}"
name: "{{ hcloud_certificate_name }}"
register: result
@@ -110,10 +110,10 @@
assert:
that:
- result is changed
- - result.hcloud_certificate.name == "{{ hcloud_certificate_name }}"
+ - result.hcloud_certificate.name == hcloud_certificate_name
- name: absent certificate
- hcloud_certificate:
+ hetzner.hcloud.certificate:
id: "{{ certificate.hcloud_certificate.id }}"
state: absent
register: result
@@ -129,7 +129,7 @@
hcloud_dns_test_domain: "{{ hcloud_dns_test_domain }}"
- name: test create managed certificate
- hcloud_certificate:
+ hetzner.hcloud.certificate:
name: "{{ hcloud_certificate_name }}"
domain_names:
- "{{ hcloud_dns_test_domain }}"
@@ -141,15 +141,15 @@
assert:
that:
- result is changed
- - result.hcloud_certificate.name == "{{ hcloud_certificate_name }}"
- - result.hcloud_certificate.domain_names[0] == "{{ hcloud_dns_test_domain }}"
+ - result.hcloud_certificate.name == hcloud_certificate_name
+ - result.hcloud_certificate.domain_names[0] == hcloud_dns_test_domain
-- name: absent certificate
- hcloud_certificate:
+- name: test delete certificate
+ hetzner.hcloud.certificate:
id: "{{ result.hcloud_certificate.id }}"
state: absent
register: result
-- name: verify absent certificate
+- name: verify test delete certificate
assert:
that:
- result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/defaults/main/main.yml
index 05502aa91..5220424ed 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/defaults/main/main.yml
@@ -1,5 +1,4 @@
# 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_server_type_name: "cx11"
-hcloud_server_type_id: 1
+hcloud_certificate_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/meta/main.yml
new file mode 100644
index 000000000..163f4db09
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - setup_selfsigned_certificate
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/cleanup.yml
new file mode 100644
index 000000000..59a50c8f7
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_certificate
+ hetzner.hcloud.certificate:
+ name: "{{ hcloud_certificate_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/prepare.yml
new file mode 100644
index 000000000..bb1dacdc5
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/prepare.yml
@@ -0,0 +1,10 @@
+---
+- name: Create test_certificate
+ hetzner.hcloud.certificate:
+ name: "{{ hcloud_certificate_name }}"
+ certificate: "{{ test_certificate_content }}"
+ private_key: "{{ test_certificate_privatekey_content }}"
+ labels:
+ key: value
+ my-label: label
+ register: test_certificate
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/test.yml
new file mode 100644
index 000000000..d15db0aee
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/certificate_info/tasks/test.yml
@@ -0,0 +1,77 @@
+# 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: Gather hcloud_certificate_info
+ hetzner.hcloud.certificate_info:
+ register: result
+- name: Verify hcloud_certificate_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_certificate_info | list | count >= 1
+
+- name: Gather hcloud_certificate_info in check mode
+ hetzner.hcloud.certificate_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_certificate_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_certificate_info | list | count >= 1
+
+- name: Gather hcloud_certificate_info with correct id
+ hetzner.hcloud.certificate_info:
+ id: "{{ test_certificate.hcloud_certificate.id }}"
+ register: result
+- name: Verify hcloud_certificate_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_certificate_info | list | count == 1
+
+- name: Gather hcloud_certificate_info with wrong id
+ hetzner.hcloud.certificate_info:
+ id: "{{ test_certificate.hcloud_certificate.id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_certificate_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_certificate_info with correct name
+ hetzner.hcloud.certificate_info:
+ name: "{{ hcloud_certificate_name }}"
+ register: result
+- name: Verify hcloud_certificate_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_certificate_info | list | count == 1
+
+- name: Gather hcloud_certificate_info with wrong name
+ hetzner.hcloud.certificate_info:
+ name: "{{ hcloud_certificate_name }}-invalid"
+ register: result
+- name: Verify hcloud_certificate_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_certificate_info | list | count == 0
+
+- name: Gather hcloud_certificate_info with correct label selector
+ hetzner.hcloud.certificate_info:
+ label_selector: "key=value"
+ register: result
+- name: Verify hcloud_certificate_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ - >
+ result.hcloud_certificate_info
+ | selectattr('name', 'equalto', hcloud_certificate_name)
+ | list | count == 1
+
+- name: Gather hcloud_certificate_info with wrong label selector
+ hetzner.hcloud.certificate_info:
+ label_selector: "key!=value"
+ register: result
+- name: Verify hcloud_certificate_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_certificate_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/defaults/main/main.yml
index b9e045f40..61490c913 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/defaults/main/main.yml
@@ -1,6 +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_datacenter_name: "fsn1-dc14"
hcloud_datacenter_id: 4
-hcloud_location_name: "fsn1"
+hcloud_datacenter_name: fsn1-dc14
+hcloud_location_name: fsn1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/tasks/test.yml
new file mode 100644
index 000000000..530b4ddb2
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/datacenter_info/tasks/test.yml
@@ -0,0 +1,58 @@
+# 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: Gather hcloud_datacenter_info
+ hetzner.hcloud.datacenter_info:
+ register: result
+- name: Verify hcloud_datacenter_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_datacenter_info | list | count >= 5
+
+- name: Gather hcloud_datacenter_info in check mode
+ hetzner.hcloud.datacenter_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_datacenter_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_datacenter_info | list | count >= 5
+
+- name: Gather hcloud_datacenter_info with correct id
+ hetzner.hcloud.datacenter_info:
+ id: "{{ hcloud_datacenter_id }}"
+ register: result
+- name: Verify hcloud_datacenter_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_datacenter_info | list | count == 1
+ - result.hcloud_datacenter_info[0].name == hcloud_datacenter_name
+ - result.hcloud_datacenter_info[0].location == hcloud_location_name
+
+- name: Gather hcloud_datacenter_info with wrong id
+ hetzner.hcloud.datacenter_info:
+ id: "{{ hcloud_datacenter_id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_datacenter_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_datacenter_info with correct name
+ hetzner.hcloud.datacenter_info:
+ name: "{{ hcloud_datacenter_name }}"
+ register: result
+- name: Verify hcloud_datacenter_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_datacenter_info | list | count == 1
+
+- name: Gather hcloud_datacenter_info with wrong name
+ hetzner.hcloud.datacenter_info:
+ name: "{{ hcloud_datacenter_name }}-invalid"
+ register: result
+- name: Verify hcloud_datacenter_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_datacenter_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/defaults/main/main.yml
new file mode 100644
index 000000000..989e14fd1
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/defaults/main/main.yml
@@ -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_firewall_name: "{{ hcloud_ns }}"
+hcloud_server_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/cleanup.yml
new file mode 100644
index 000000000..37fbd3413
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/cleanup.yml
@@ -0,0 +1,10 @@
+---
+- name: Cleanup test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ state: absent
+
+- name: Cleanup test_firewall
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/prepare.yml
new file mode 100644
index 000000000..cf6daa322
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/prepare.yml
@@ -0,0 +1,8 @@
+---
+- name: Create test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ server_type: cx11
+ image: ubuntu-22.04
+ state: stopped
+ register: test_server
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/test.yml
new file mode 100644
index 000000000..57059848f
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall/tasks/test.yml
@@ -0,0 +1,197 @@
+# 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
+ hetzner.hcloud.firewall:
+ state: present
+ ignore_errors: true
+ register: result
+- name: Verify missing required parameters
+ ansible.builtin.assert:
+ that:
+ - result is failed
+ - 'result.msg == "one of the following is required: id, name"'
+
+- name: Test create with check mode
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ rules:
+ - description: allow icmp in
+ direction: in
+ protocol: icmp
+ source_ips: ["0.0.0.0/0", "::/0"]
+ labels:
+ key: value
+ check_mode: true
+ register: result
+- name: Verify create with check mode
+ ansible.builtin.assert:
+ that:
+ - result is changed
+
+- name: Test create
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ rules:
+ - description: allow icmp in
+ direction: in
+ protocol: icmp
+ source_ips: ["0.0.0.0/0", "::/0"]
+ labels:
+ key: value
+ register: result
+- name: Verify create
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_firewall.name == hcloud_firewall_name
+ - result.hcloud_firewall.rules | list | count == 1
+ - result.hcloud_firewall.rules[0].description == "allow icmp in"
+ - result.hcloud_firewall.rules[0].direction == "in"
+ - result.hcloud_firewall.rules[0].protocol == "icmp"
+ - result.hcloud_firewall.rules[0].source_ips == ["0.0.0.0/0", "::/0"]
+ - result.hcloud_firewall.labels.key == "value"
+ - result.hcloud_firewall.applied_to | list | count == 0
+
+- name: Test create idempotency
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ rules:
+ - description: allow icmp in
+ direction: in
+ protocol: icmp
+ source_ips: ["0.0.0.0/0", "::/0"]
+ labels:
+ key: value
+ register: result
+- name: Verify create idempotency
+ ansible.builtin.assert:
+ that:
+ - result is not changed
+
+- name: Assign firewall to test_server
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ servers: ["{{ test_server.hcloud_server.name }}"]
+ state: present
+
+- name: Test update
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ rules:
+ - description: allow icmp in
+ direction: in
+ protocol: icmp
+ source_ips: ["0.0.0.0/0", "::/0"]
+ - description: allow http in
+ direction: in
+ protocol: tcp
+ port: 80
+ source_ips: ["0.0.0.0/0", "::/0"]
+ - description: allow http out
+ direction: out
+ protocol: tcp
+ port: 80
+ destination_ips: ["0.0.0.0/0", "::/0"]
+ labels:
+ key: value
+ label: label
+ register: result
+- name: Verify update
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_firewall.name == hcloud_firewall_name
+ - result.hcloud_firewall.rules | list | count == 3
+ - result.hcloud_firewall.rules[0].description == "allow icmp in"
+ - result.hcloud_firewall.rules[0].direction == "in"
+ - result.hcloud_firewall.rules[0].protocol == "icmp"
+ - result.hcloud_firewall.rules[0].source_ips == ["0.0.0.0/0", "::/0"]
+ - result.hcloud_firewall.rules[1].description == "allow http in"
+ - result.hcloud_firewall.rules[1].direction == "in"
+ - result.hcloud_firewall.rules[1].protocol == "tcp"
+ - result.hcloud_firewall.rules[1].port == "80"
+ - result.hcloud_firewall.rules[1].source_ips == ["0.0.0.0/0", "::/0"]
+ - result.hcloud_firewall.rules[2].description == "allow http out"
+ - result.hcloud_firewall.rules[2].direction == "out"
+ - result.hcloud_firewall.rules[2].protocol == "tcp"
+ - result.hcloud_firewall.rules[2].port == "80"
+ - result.hcloud_firewall.rules[2].destination_ips == ["0.0.0.0/0", "::/0"]
+ - result.hcloud_firewall.labels.key == "value"
+ - result.hcloud_firewall.labels.label == "label"
+
+- name: Test update idempotency
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ rules:
+ - description: allow icmp in
+ direction: in
+ protocol: icmp
+ source_ips: ["0.0.0.0/0", "::/0"]
+ - description: allow http in
+ direction: in
+ protocol: tcp
+ port: 80
+ source_ips: ["0.0.0.0/0", "::/0"]
+ - description: allow http out
+ direction: out
+ protocol: tcp
+ port: 80
+ destination_ips: ["0.0.0.0/0", "::/0"]
+ labels:
+ key: value
+ label: label
+ register: result
+- name: Verify update idempotency
+ ansible.builtin.assert:
+ that:
+ - result is not changed
+
+- name: Test update name
+ hetzner.hcloud.firewall:
+ id: "{{ result.hcloud_firewall.id }}"
+ name: "changed-{{ hcloud_firewall_name }}"
+ register: result
+- name: Verify update name
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_firewall.name == "changed-" + hcloud_firewall_name
+
+- name: Test update name and labels
+ hetzner.hcloud.firewall:
+ id: "{{ result.hcloud_firewall.id }}"
+ name: "{{ hcloud_firewall_name }}"
+ labels:
+ key: value
+ register: result
+- name: Verify update name and labels
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_firewall.name == hcloud_firewall_name
+ - result.hcloud_firewall.labels.key == "value"
+ - result.hcloud_firewall.labels.label is not defined
+
+- name: Test delete
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ state: absent
+ ignore_errors: true
+ register: result
+- name: Verify delete
+ ansible.builtin.assert:
+ that:
+ - result is failed
+ - '"is still in use" in result.msg'
+
+- name: Test delete with force
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ force: true
+ state: absent
+ register: result
+- name: Verify delete with force
+ ansible.builtin.assert:
+ that:
+ - result is changed
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/aliases
index 55ec821a4..55ec821a4 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/aliases
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/aliases
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/defaults/main/main.yml
new file mode 100644
index 000000000..441e948ed
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/defaults/main/main.yml
@@ -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_server_name: "{{ hcloud_ns }}"
+hcloud_firewall_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/cleanup.yml
new file mode 100644
index 000000000..37fbd3413
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/cleanup.yml
@@ -0,0 +1,10 @@
+---
+- name: Cleanup test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ state: absent
+
+- name: Cleanup test_firewall
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/prepare.yml
new file mode 100644
index 000000000..17d4ebcc4
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/prepare.yml
@@ -0,0 +1,35 @@
+---
+- name: Create test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ server_type: cx11
+ image: ubuntu-22.04
+ labels:
+ firewall: "{{ hcloud_firewall_name }}"
+ state: stopped
+ register: test_server
+
+- name: Create test_firewall
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ labels:
+ key: value
+ rules:
+ - description: allow icmp from anywhere
+ direction: in
+ protocol: icmp
+ source_ips:
+ - 0.0.0.0/0
+ - ::/0
+ state: present
+ register: test_firewall
+
+- name: Create test_firewall_resource
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ servers:
+ - "{{ hcloud_server_name }}"
+ label_selectors:
+ - firewall={{ hcloud_firewall_name }}
+ state: present
+ register: test_firewall_resource
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/test.yml
new file mode 100644
index 000000000..fc9a38af2
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_info/tasks/test.yml
@@ -0,0 +1,93 @@
+# 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: Gather hcloud_firewall_info
+ hetzner.hcloud.firewall_info:
+ register: result
+- name: Verify hcloud_firewall_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_firewall_info | list | count >= 1
+
+- name: Gather hcloud_firewall_info in check mode
+ hetzner.hcloud.firewall_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_firewall_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_firewall_info | list | count >= 1
+
+- name: Gather hcloud_firewall_info with correct id
+ hetzner.hcloud.firewall_info:
+ id: "{{ test_firewall.hcloud_firewall.id }}"
+ register: result
+- name: Verify hcloud_firewall_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_firewall_info | list | count == 1
+ - result.hcloud_firewall_info[0].name == hcloud_firewall_name
+ - result.hcloud_firewall_info[0].labels.key == "value"
+ - result.hcloud_firewall_info[0].rules | list | count == 1
+ - result.hcloud_firewall_info[0].rules[0].description == "allow icmp from anywhere"
+ - result.hcloud_firewall_info[0].rules[0].direction == "in"
+ - result.hcloud_firewall_info[0].rules[0].protocol == "icmp"
+ - result.hcloud_firewall_info[0].rules[0].source_ips == ["0.0.0.0/0", "::/0"]
+ - result.hcloud_firewall_info[0].applied_to | list | count == 2
+ - >
+ result.hcloud_firewall_info[0].applied_to
+ | selectattr('type', 'equalto', 'label_selector')
+ | list | count == 1
+ - >
+ result.hcloud_firewall_info[0].applied_to
+ | selectattr('type', 'equalto', 'server')
+ | list | count == 1
+
+- name: Gather hcloud_firewall_info with wrong id
+ hetzner.hcloud.firewall_info:
+ id: "{{ test_firewall.hcloud_firewall.id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_firewall_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_firewall_info with correct name
+ hetzner.hcloud.firewall_info:
+ name: "{{ hcloud_firewall_name }}"
+ register: result
+- name: Verify hcloud_firewall_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_firewall_info | list | count == 1
+
+- name: Gather hcloud_firewall_info with wrong name
+ hetzner.hcloud.firewall_info:
+ name: "{{ hcloud_firewall_name }}-invalid"
+ register: result
+- name: Verify hcloud_firewall_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_firewall_info | list | count == 0
+
+- name: Gather hcloud_firewall_info with correct label selector
+ hetzner.hcloud.firewall_info:
+ label_selector: "key=value"
+ register: result
+- name: Verify hcloud_firewall_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ - >
+ result.hcloud_firewall_info
+ | selectattr('name', 'equalto', hcloud_firewall_name)
+ | list | count == 1
+
+- name: Gather hcloud_firewall_info with wrong label selector
+ hetzner.hcloud.firewall_info:
+ label_selector: "key!=value"
+ register: result
+- name: Verify hcloud_firewall_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_firewall_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/defaults/main/main.yml
new file mode 100644
index 000000000..441e948ed
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/defaults/main/main.yml
@@ -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_server_name: "{{ hcloud_ns }}"
+hcloud_firewall_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/cleanup.yml
new file mode 100644
index 000000000..37fbd3413
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/cleanup.yml
@@ -0,0 +1,10 @@
+---
+- name: Cleanup test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ state: absent
+
+- name: Cleanup test_firewall
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/prepare.yml
new file mode 100644
index 000000000..6fb6fd2df
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/prepare.yml
@@ -0,0 +1,25 @@
+---
+- name: Create test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ server_type: cx11
+ image: ubuntu-22.04
+ labels:
+ key: value
+ state: stopped
+ register: test_server
+
+- name: Create test_firewall
+ hetzner.hcloud.firewall:
+ name: "{{ hcloud_firewall_name }}"
+ labels:
+ key: value
+ rules:
+ - description: allow icmp from anywhere
+ direction: in
+ protocol: icmp
+ source_ips:
+ - 0.0.0.0/0
+ - ::/0
+ state: present
+ register: test_firewall
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/test.yml
new file mode 100644
index 000000000..088e78413
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/firewall_resource/tasks/test.yml
@@ -0,0 +1,95 @@
+# 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
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ state: present
+ ignore_errors: true
+ register: result
+- name: Verify missing required parameters
+ ansible.builtin.assert:
+ that:
+ - result is failed
+ - 'result.msg == "one of the following is required: servers, label_selectors"'
+
+- name: Test create with check mode
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ servers: ["{{ hcloud_server_name }}"]
+ check_mode: true
+ register: result
+- name: Verify create with check mode
+ ansible.builtin.assert:
+ that:
+ - result is changed
+
+- name: Test create
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ servers: ["{{ hcloud_server_name }}"]
+ register: result
+- name: Verify create
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_firewall_resource.firewall == hcloud_firewall_name
+ - result.hcloud_firewall_resource.servers | list | count == 1
+ - result.hcloud_firewall_resource.servers[0] == hcloud_server_name
+ - result.hcloud_firewall_resource.label_selectors | list | count == 0
+
+- name: Test create idempotency
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ servers: ["{{ hcloud_server_name }}"]
+ register: result
+- name: Verify create idempotency
+ ansible.builtin.assert:
+ that:
+ - result is not changed
+
+- name: Test update
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ label_selectors:
+ - key=value
+ register: result
+- name: Verify update
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_firewall_resource.label_selectors | list | count == 1
+ - result.hcloud_firewall_resource.label_selectors[0] == "key=value"
+
+- name: Test update idempotency
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ label_selectors:
+ - key=value
+ register: result
+- name: Verify update idempotency
+ ansible.builtin.assert:
+ that:
+ - result is not changed
+
+- name: Test delete servers
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ servers: ["{{ hcloud_server_name }}"]
+ state: absent
+ register: result
+- name: Verify delete
+ ansible.builtin.assert:
+ that:
+ - result is changed
+
+- name: Test delete label_selectors
+ hetzner.hcloud.firewall_resource:
+ firewall: "{{ hcloud_firewall_name }}"
+ label_selectors: ["key=value"]
+ state: absent
+ register: result
+- name: Verify delete
+ ansible.builtin.assert:
+ that:
+ - result is changed
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/aliases
new file mode 100644
index 000000000..a6a90a6bf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group3
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/defaults/main/main.yml
new file mode 100644
index 000000000..a2d33ff80
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/defaults/main/main.yml
@@ -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_floating_ip_name: "{{ hcloud_ns }}"
+hcloud_server_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/tasks/test.yml
index 8ada4172f..fba06e308 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip/tasks/test.yml
@@ -1,11 +1,26 @@
# 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 ensure server is absent
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ state: absent
+
+- name: setup ensure another server is absent
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}2"
+ state: absent
+
+- name: setup ensure floating ip is absent
+ hetzner.hcloud.floating_ip:
+ name: "{{ hcloud_floating_ip_name }}"
+ state: absent
+
- name: setup server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cx11
- image: ubuntu-18.04
+ image: ubuntu-22.04
state: started
location: "fsn1"
register: main_server
@@ -15,10 +30,10 @@
- main_server is changed
- name: setup another server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}2"
server_type: cx11
- image: ubuntu-18.04
+ image: ubuntu-22.04
state: started
register: main_server2
- name: verify setup another server
@@ -27,10 +42,10 @@
- main_server2 is changed
- name: test missing type parameter on create Floating IP
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing type parameter on create Floating IP
assert:
that:
@@ -38,11 +53,11 @@
- 'result.msg == "missing required arguments: type"'
- name: test missing required parameters on create Floating IP
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing required parameters on create Floating IP
assert:
that:
@@ -50,26 +65,25 @@
- 'result.msg == "one of the following is required: home_location, server"'
- name: test missing type parameter on delete Floating IP
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
type: ipv4
home_location: "fsn1"
state: "absent"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing type parameter on delete Floating IP
assert:
that:
- result is failed
- 'result.msg == "one of the following is required: id, name"'
-
- name: test invalid type
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv5
home_location: "fsn1"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify invalid type
assert:
that:
@@ -77,12 +91,12 @@
- 'result.msg == "value of type must be one of: ipv4, ipv6, got: ipv5"'
- name: test invalid location
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
home_location: "abc"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify invalid location
assert:
that:
@@ -90,20 +104,20 @@
- result.msg == "invalid input in fields 'server', 'home_location'"
- name: test create Floating IP with check mode
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
description: "Web Server"
type: ipv4
home_location: "fsn1"
register: floatingIP
- check_mode: yes
+ check_mode: true
- name: verify test create Floating IP with check mode
assert:
that:
- floatingIP is changed
- name: test create Floating IP
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
description: "Web Server"
type: ipv4
@@ -118,7 +132,7 @@
- floatingIP.hcloud_floating_ip.home_location == "fsn1"
- name: test create Floating IP idempotency
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
description: "Web Server"
type: ipv4
@@ -130,12 +144,12 @@
- floatingIP is not changed
- name: test update Floating IP with check mode
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
description: "changed-description"
type: ipv4
home_location: "fsn1"
- check_mode: yes
+ check_mode: true
register: floatingIP
- name: verify test create Floating IP with check mode
assert:
@@ -144,7 +158,7 @@
- floatingIP.hcloud_floating_ip.description == "Web Server"
- name: test update Floating IP
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
description: "changed-description"
type: ipv4
@@ -159,7 +173,7 @@
- floatingIP.hcloud_floating_ip.description == "changed-description"
- name: test update Floating IP idempotency
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
description: "changed-description"
type: ipv4
@@ -173,7 +187,7 @@
- floatingIP is not changed
- name: test update Floating IP with same labels
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
home_location: "fsn1"
@@ -186,7 +200,7 @@
- floatingIP is not changed
- name: test update Floating IP with other labels
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
home_location: "fsn1"
@@ -200,7 +214,7 @@
- floatingIP is changed
- name: test update Floating IP with other labels in different order
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
home_location: "fsn1"
@@ -214,21 +228,21 @@
- floatingIP is not changed
- name: test assign Floating IP with checkmode
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
description: "changed-description"
type: ipv4
server: "{{ main_server.hcloud_server.name }}"
- check_mode: yes
+ check_mode: true
register: floatingIP
- name: verify test assign Floating IP with checkmode
assert:
that:
- floatingIP is changed
- - floatingIP.hcloud_floating_ip.server != "{{ main_server.hcloud_server.name }}"
+ - floatingIP.hcloud_floating_ip.server != main_server.hcloud_server.name
- name: test assign Floating IP
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
description: "changed-description"
type: ipv4
@@ -238,10 +252,10 @@
assert:
that:
- floatingIP is changed
- - floatingIP.hcloud_floating_ip.server == "{{ main_server.hcloud_server.name }}"
+ - floatingIP.hcloud_floating_ip.server == main_server.hcloud_server.name
- name: test assign Floating IP idempotency
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
description: "changed-description"
type: ipv4
@@ -253,7 +267,7 @@
- floatingIP is not changed
- name: test unassign Floating IP
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
home_location: "fsn1"
@@ -262,10 +276,10 @@
assert:
that:
- floatingIP is changed
- - floatingIP.hcloud_floating_ip.server != "{{ main_server.hcloud_server.name }}"
+ - floatingIP.hcloud_floating_ip.server != main_server.hcloud_server.name
- name: test unassign Floating IP idempotency
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
home_location: "fsn1"
@@ -276,7 +290,7 @@
- floatingIP is not changed
- name: test assign Floating IP again
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
server: "{{ main_server.hcloud_server.name }}"
@@ -285,10 +299,10 @@
assert:
that:
- floatingIP is changed
- - floatingIP.hcloud_floating_ip.server == "{{ main_server.hcloud_server.name }}"
+ - floatingIP.hcloud_floating_ip.server == main_server.hcloud_server.name
- name: test already assigned Floating IP assign without force
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
server: "{{ main_server2.hcloud_server.name }}"
@@ -297,23 +311,23 @@
assert:
that:
- floatingIP is changed
- - floatingIP.hcloud_floating_ip.server == "{{ main_server.hcloud_server.name }}"
+ - floatingIP.hcloud_floating_ip.server == main_server.hcloud_server.name
- name: test already assigned Floating IP assign with force
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
- force: yes
+ force: true
server: "{{ main_server2.hcloud_server.name }}"
register: floatingIP
- name: verify test already assigned Floating IP assign with force
assert:
that:
- floatingIP is changed
- - floatingIP.hcloud_floating_ip.server == "{{ main_server2.hcloud_server.name }}"
+ - floatingIP.hcloud_floating_ip.server == main_server2.hcloud_server.name
- name: test update Floating IP delete protection
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
delete_protection: true
@@ -325,7 +339,7 @@
- floatingIP.hcloud_floating_ip.delete_protection is sameas true
- name: test update Floating IP delete protection idempotency
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
delete_protection: true
@@ -337,7 +351,7 @@
- floatingIP.hcloud_floating_ip.delete_protection is sameas true
- name: test Floating IP without delete protection set to be idempotent
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
register: floatingIP
@@ -348,11 +362,11 @@
- floatingIP.hcloud_floating_ip.delete_protection is sameas true
- name: test delete Floating IP fails if it is protected
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
state: "absent"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify test delete floating ip
assert:
that:
@@ -360,7 +374,7 @@
- 'result.msg == "Floating IP deletion is protected"'
- name: test update Floating IP delete protection
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
delete_protection: false
@@ -372,7 +386,7 @@
- floatingIP.hcloud_floating_ip.delete_protection is sameas false
- name: test delete floating ip
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
state: "absent"
register: result
@@ -382,7 +396,7 @@
- result is changed
- name: test create ipv6 floating ip
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv6
home_location: "fsn1"
@@ -394,7 +408,7 @@
- result is changed
- name: test delete ipv6 floating ip
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
state: "absent"
register: result
@@ -404,7 +418,7 @@
- result is changed
- name: cleanup
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
@@ -413,7 +427,7 @@
that:
- result is changed
- name: cleanup another server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ main_server2.hcloud_server.name }}"
state: absent
register: result
@@ -423,7 +437,7 @@
- result is changed
- name: test create Floating IP with delete protection
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
home_location: fsn1
@@ -436,11 +450,11 @@
- floatingIP.hcloud_floating_ip.delete_protection is sameas true
- name: test delete Floating IP fails if it is protected
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
state: "absent"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify test delete floating ip
assert:
that:
@@ -448,7 +462,7 @@
- 'result.msg == "Floating IP deletion is protected"'
- name: test update Floating IP delete protection
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
type: ipv4
delete_protection: false
@@ -460,7 +474,7 @@
- floatingIP.hcloud_floating_ip.delete_protection is sameas false
- name: test delete floating ip
- hcloud_floating_ip:
+ hetzner.hcloud.floating_ip:
name: "{{ hcloud_floating_ip_name }}"
state: "absent"
register: result
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/aliases
new file mode 100644
index 000000000..a6a90a6bf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group3
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/defaults/main/main.yml
index 15188e181..ffa5e4833 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/defaults/main/main.yml
@@ -1,5 +1,4 @@
# 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_ssh_key_name: "{{hcloud_prefix}}-f"
+hcloud_floating_ip_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/cleanup.yml
new file mode 100644
index 000000000..611d8e00c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_floating_ip
+ hetzner.hcloud.floating_ip:
+ name: "{{ hcloud_floating_ip_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/prepare.yml
new file mode 100644
index 000000000..26230ad54
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/prepare.yml
@@ -0,0 +1,9 @@
+---
+- name: Create test_floating_ip
+ hetzner.hcloud.floating_ip:
+ name: "{{ hcloud_floating_ip_name }}"
+ home_location: fsn1
+ type: ipv4
+ labels:
+ key: value
+ register: test_floating_ip
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/test.yml
new file mode 100644
index 000000000..51fb56eb3
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/floating_ip_info/tasks/test.yml
@@ -0,0 +1,77 @@
+# 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: Gather hcloud_floating_ip_info
+ hetzner.hcloud.floating_ip_info:
+ register: result
+- name: Verify hcloud_floating_ip_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_floating_ip_info | list | count >= 1
+
+- name: Gather hcloud_floating_ip_info in check mode
+ hetzner.hcloud.floating_ip_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_floating_ip_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_floating_ip_info | list | count >= 1
+
+- name: Gather hcloud_floating_ip_info with correct id
+ hetzner.hcloud.floating_ip_info:
+ id: "{{ test_floating_ip.hcloud_floating_ip.id }}"
+ register: result
+- name: Verify hcloud_floating_ip_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_floating_ip_info | list | count == 1
+
+- name: Gather hcloud_floating_ip_info with wrong id
+ hetzner.hcloud.floating_ip_info:
+ id: "{{ test_floating_ip.hcloud_floating_ip.id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_floating_ip_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_floating_ip_info with correct name
+ hetzner.hcloud.floating_ip_info:
+ name: "{{ hcloud_floating_ip_name }}"
+ register: result
+- name: Verify hcloud_floating_ip_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_floating_ip_info | list | count == 1
+
+- name: Gather hcloud_floating_ip_info with wrong name
+ hetzner.hcloud.floating_ip_info:
+ name: "{{ hcloud_floating_ip_name }}-invalid"
+ register: result
+- name: Verify hcloud_floating_ip_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_floating_ip_info | list | count == 0
+
+- name: Gather hcloud_floating_ip_info with correct label selector
+ hetzner.hcloud.floating_ip_info:
+ label_selector: "key=value"
+ register: result
+- name: Verify hcloud_floating_ip_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ - >
+ result.hcloud_floating_ip_info
+ | selectattr('name', 'equalto', hcloud_floating_ip_name)
+ | list | count == 1
+
+- name: Gather hcloud_floating_ip_info with wrong label selector
+ hetzner.hcloud.floating_ip_info:
+ label_selector: "key!=value"
+ register: result
+- name: Verify hcloud_floating_ip_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_floating_ip_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/defaults/main.yml
deleted file mode 100644
index 58312aec1..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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"
-hcloud_dns_test_domain: "{{hcloud_prefix | truncate(19, False, 'ans')}}-{{100 | random }}.hc-certs.de"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/meta/main.yml
deleted file mode 100644
index e531064ca..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/meta/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-dependencies:
- - setup_selfsigned_certificate
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/tasks/main.yml
deleted file mode 100644
index d7128db34..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/tasks/main.yml
+++ /dev/null
@@ -1,66 +0,0 @@
-# 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: 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 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
-
-- name: absent certificate
- hcloud_certificate:
- id: "{{ certificate.hcloud_certificate.id }}"
- state: absent
- register: result
-- name: verify absent certificate
- assert:
- that:
- - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/tasks/main.yml
deleted file mode 100644
index 3d144ae47..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/tasks/main.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-# 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 datacenter infos
- hcloud_datacenter_info:
- register: hcloud_datacenters
-
-- name: verify test gather hcloud datacenter infos
- assert:
- that:
- - hcloud_datacenters.hcloud_datacenter_info| list | count >= 5
-
-- name: test gather hcloud datacenter infos in check mode
- hcloud_datacenter_info:
- register: hcloud_datacenters
- check_mode: yes
-
-- name: verify test gather hcloud datacenter infos in check mode
- assert:
- that:
- - hcloud_datacenters.hcloud_datacenter_info| list | count >= 5
-
-- name: test gather hcloud datacenter infos with correct name
- hcloud_datacenter_info:
- name: "{{hcloud_datacenter_name}}"
- register: hcloud_datacenter
-- name: verify test gather hcloud datacenter with correct name
- assert:
- that:
- - hcloud_datacenter.hcloud_datacenter_info|selectattr('name','equalto','{{ hcloud_datacenter_name }}') |selectattr('location','equalto','{{ hcloud_location_name }}') | list | count == 1
-
-- name: test gather hcloud datacenter infos with correct id
- hcloud_datacenter_info:
- id: "{{hcloud_datacenter_id}}"
- register: hcloud_datacenter
-- name: verify test gather hcloud datacenter with correct id
- assert:
- that:
- - hcloud_datacenter.hcloud_datacenter_info|selectattr('name','equalto','{{ hcloud_datacenter_name }}') | list | count == 1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/tasks/main.yml
deleted file mode 100644
index f54d351b2..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/tasks/main.yml
+++ /dev/null
@@ -1,210 +0,0 @@
-# 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 firewall to be absent
- hcloud_firewall:
- name: "{{ hcloud_firewall_name }}"
- state: absent
-
-- name: test missing required parameters on create firewall
- hcloud_firewall:
- register: result
- ignore_errors: yes
-- name: verify fail test missing required parameters on create firewall
- assert:
- that:
- - result is failed
- - 'result.msg == "one of the following is required: id, name"'
-
-- name: test create firewall with check mode
- hcloud_firewall:
- name: "{{ hcloud_firewall_name }}"
- register: result
- check_mode: yes
-- name: test create firewall with check mode
- assert:
- that:
- - result is changed
-
-- name: test create firewall
- hcloud_firewall:
- name: "{{ hcloud_firewall_name }}"
- rules:
- - direction: in
- protocol: icmp
- source_ips:
- - 0.0.0.0/0
- - ::/0
- description: "allow icmp in"
- labels:
- key: value
- my-label: label
- register: firewall
-- name: verify create firewall
- assert:
- that:
- - firewall is changed
- - firewall.hcloud_firewall.name == "{{ hcloud_firewall_name }}"
- - firewall.hcloud_firewall.rules | list | count == 1
- - firewall.hcloud_firewall.rules | selectattr('direction','equalto','in') | list | count == 1
- - firewall.hcloud_firewall.rules | selectattr('protocol','equalto','icmp') | list | count == 1
- - firewall.hcloud_firewall.rules | selectattr('description', 'equalto', 'allow icmp in') | list | count == 1
-
-- name: test create firewall idempotence
- hcloud_firewall:
- name: "{{ hcloud_firewall_name }}"
- rules:
- - direction: in
- protocol: icmp
- source_ips:
- - 0.0.0.0/0
- - ::/0
- description: "allow icmp in"
- labels:
- key: value
- my-label: label
- register: result
-- name: verify create firewall idempotence
- assert:
- that:
- - result is not changed
-
-- name: test update firewall rules
- hcloud_firewall:
- name: "{{ hcloud_firewall_name }}"
- rules:
- - direction: in
- protocol: icmp
- source_ips:
- - 0.0.0.0/0
- - ::/0
- - direction: in
- protocol: tcp
- port: 80
- source_ips:
- - 0.0.0.0/0
- - ::/0
- - direction: out
- protocol: tcp
- port: 80
- destination_ips:
- - 0.0.0.0/0
- - ::/0
- description: allow tcp out
- labels:
- key: value
- my-label: label
- register: firewall
-- name: verify update firewall rules
- assert:
- that:
- - firewall is changed
- - firewall.hcloud_firewall.name == "{{ hcloud_firewall_name }}"
- - firewall.hcloud_firewall.rules | list | count == 3
- - firewall.hcloud_firewall.rules | selectattr('direction','equalto','in') | list | count == 2
- - firewall.hcloud_firewall.rules | selectattr('direction','equalto','out') | list | count == 1
- - firewall.hcloud_firewall.rules | selectattr('protocol','equalto','icmp') | list | count == 1
- - firewall.hcloud_firewall.rules | selectattr('protocol','equalto','tcp') | list | count == 2
- - firewall.hcloud_firewall.rules | selectattr('port','equalto','80') | list | count == 2
- - firewall.hcloud_firewall.rules | selectattr('description', 'equalto', 'allow tcp out') | list | count == 1
-
-- name: test update firewall rules idempotence
- hcloud_firewall:
- name: "{{ hcloud_firewall_name }}"
- rules:
- - direction: in
- protocol: icmp
- source_ips:
- - 0.0.0.0/0
- - ::/0
- - direction: in
- protocol: tcp
- port: 80
- source_ips:
- - 0.0.0.0/0
- - ::/0
- - direction: out
- protocol: tcp
- port: 80
- destination_ips:
- - 0.0.0.0/0
- - ::/0
- description: allow tcp out
- labels:
- key: value
- my-label: label
- register: result
-- name: verify update firewall rules idempotence
- assert:
- that:
- - result is not changed
-
-- name: test update firewall with check mode
- hcloud_firewall:
- id: "{{ firewall.hcloud_firewall.id }}"
- name: "changed-{{ hcloud_firewall_name }}"
- register: result
- check_mode: yes
-- name: test create firewall with check mode
- assert:
- that:
- - result is changed
-
-- name: test update firewall
- hcloud_firewall:
- id: "{{ firewall.hcloud_firewall.id }}"
- name: "changed-{{ hcloud_firewall_name }}"
- labels:
- key: value
- register: result
-- name: test update firewall
- assert:
- that:
- - result is changed
- - result.hcloud_firewall.name == "changed-{{ hcloud_firewall_name }}"
-
-- name: test update firewall with same labels
- hcloud_firewall:
- id: "{{ firewall.hcloud_firewall.id }}"
- name: "changed-{{ hcloud_firewall_name }}"
- labels:
- key: value
- register: result
-- name: test update firewall with same labels
- assert:
- that:
- - result is not changed
-
-- name: test update firewall with other labels
- hcloud_firewall:
- id: "{{ firewall.hcloud_firewall.id }}"
- name: "changed-{{ hcloud_firewall_name }}"
- labels:
- key: value
- test: "val123"
- register: result
-- name: test update firewall with other labels
- assert:
- that:
- - result is changed
-
-- name: test rename firewall
- hcloud_firewall:
- id: "{{ firewall.hcloud_firewall.id }}"
- name: "{{ hcloud_firewall_name }}"
- register: result
-- name: test rename firewall
- assert:
- that:
- - result is changed
- - result.hcloud_firewall.name == "{{ hcloud_firewall_name }}"
-
-- name: absent firewall
- hcloud_firewall:
- id: "{{ firewall.hcloud_firewall.id }}"
- state: absent
- register: result
-- name: verify absent server
- assert:
- that:
- - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/defaults/main.yml
deleted file mode 100644
index ebd5ccc38..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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_floating_ip_name: "{{hcloud_prefix}}-i"
-hcloud_server_name: "{{ hcloud_prefix | truncate(45, True, '', 0) }}-fip-t"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/tasks/main.yml
deleted file mode 100644
index 9ca1c2a4a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/tasks/main.yml
+++ /dev/null
@@ -1,87 +0,0 @@
-# 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 ensure floating ip is absent
- hcloud_floating_ip:
- name: "{{ hcloud_floating_ip_name }}"
- state: absent
-
-- name: setup floating ip
- hcloud_floating_ip:
- name: "{{ hcloud_floating_ip_name }}"
- home_location: "fsn1"
- type: ipv4
- labels:
- key: value
- register: test_floating_ip
-
-- name: verify setup floating ip
- assert:
- that:
- - test_floating_ip is changed
-
-- name: test gather hcloud floating ip infos
- hcloud_floating_ip_info:
- register: hcloud_floating_ips
-- name: verify test gather hcloud floating ip infos
- assert:
- that:
- - hcloud_floating_ips.hcloud_floating_ip_info| list | count >= 1
-
-- name: test gather hcloud floating ip infos in check mode
- hcloud_floating_ip_info:
- check_mode: yes
- register: hcloud_floating_ips
-
-- name: verify test gather hcloud floating ip infos in check mode
- assert:
- that:
- - hcloud_floating_ips.hcloud_floating_ip_info| list | count >= 1
-
-
-- name: test gather hcloud floating ip infos with correct label selector
- hcloud_floating_ip_info:
- label_selector: "key=value"
- register: hcloud_floating_ips
-- name: verify test gather hcloud floating ip with correct label selector
- assert:
- that:
- - hcloud_floating_ips.hcloud_floating_ip_info|selectattr('name','equalto','{{ test_floating_ip.hcloud_floating_ip.name }}') | list | count == 1
-
-- name: test gather hcloud floating ip infos with wrong label selector
- hcloud_floating_ip_info:
- label_selector: "key!=value"
- register: hcloud_floating_ips
-- name: verify test gather hcloud floating ip with wrong label selector
- assert:
- that:
- - hcloud_floating_ips.hcloud_floating_ip_info | list | count == 0
-
-- name: test gather hcloud floating ip infos with correct id
- hcloud_floating_ip_info:
- id: "{{test_floating_ip.hcloud_floating_ip.id}}"
- register: hcloud_floating_ips
-- name: verify test gather hcloud floating ip with correct id
- assert:
- that:
- - hcloud_floating_ips.hcloud_floating_ip_info|selectattr('name','equalto','{{ test_floating_ip.hcloud_floating_ip.name }}') | list | count == 1
-
-- name: test gather hcloud floating ip infos with wrong id
- hcloud_floating_ip_info:
- id: "{{test_floating_ip.hcloud_floating_ip.id}}1"
- register: result
- ignore_errors: yes
-- name: verify test gather hcloud floating ip with wrong id
- assert:
- that:
- - result is failed
-
-- name: cleanup
- hcloud_floating_ip:
- id: "{{ test_floating_ip.hcloud_floating_ip.id }}"
- state: absent
- register: result
-- name: verify cleanup
- assert:
- that:
- - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/defaults/main.yml
deleted file mode 100644
index 7c25d171d..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/defaults/main.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-# 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_test_image_name: "always-there-snapshot"
-hcloud_test_image_id: 10164049
-hcloud_test_image_name_os: "ubuntu-22.04"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/tasks/main.yml
deleted file mode 100644
index 16ed44a28..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/tasks/main.yml
+++ /dev/null
@@ -1,93 +0,0 @@
-# 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 image infos with type system
- hcloud_image_info:
- register: hcloud_images
-- name: verify test gather hcloud image infos in check mode
- assert:
- that:
- - hcloud_images.hcloud_image_info| list | count > 2
-
-- name: test gather hcloud image infos in check mode
- hcloud_image_info:
- check_mode: yes
- register: hcloud_images
-
-- name: verify test gather hcloud image infos in check mode
- assert:
- that:
- - hcloud_images.hcloud_image_info| list | count > 2
-
-
-- name: test gather hcloud image infos with correct label selector
- hcloud_image_info:
- label_selector: "key=value"
- type: snapshot
- register: hcloud_images
-- name: verify test gather hcloud image with correct label selector
- assert:
- that:
- - hcloud_images.hcloud_image_info|selectattr('description','equalto','{{ hcloud_test_image_name }}') | list | count == 1
-
-- name: test gather hcloud image infos with wrong label selector
- hcloud_image_info:
- label_selector: "key!=value"
- type: snapshot
- register: hcloud_images
-- name: verify test gather hcloud image with wrong label selector
- assert:
- that:
- - hcloud_images.hcloud_image_info | list | count == 0
-
-- name: test gather hcloud image infos with correct id
- hcloud_image_info:
- id: "{{hcloud_test_image_id}}"
- type: snapshot
- register: hcloud_images
-- name: verify test gather hcloud image with correct id
- assert:
- that:
- - hcloud_images.hcloud_image_info|selectattr('description','equalto','{{ hcloud_test_image_name }}') | list | count == 1
-
-- name: test gather hcloud image infos with wrong id
- hcloud_image_info:
- id: "{{hcloud_test_image_id}}1"
- type: snapshot
- ignore_errors: yes
- register: result
-- name: verify test gather hcloud image with wrong id
- assert:
- that:
- - result is failed
-
-- name: test gather hcloud image infos with name
- hcloud_image_info:
- name: "{{ hcloud_test_image_name_os }}"
- register: hcloud_images
-- name: verify test gather hcloud image infos with name
- assert:
- that:
- - hcloud_images.hcloud_image_info | list | count == 1
- - hcloud_images.hcloud_image_info[0].architecture == "x86"
-
-- name: test gather hcloud image infos with name and architecture
- hcloud_image_info:
- name: "{{ hcloud_test_image_name_os }}"
- architecture: arm
- register: hcloud_images
-- name: verify test gather hcloud image infos with name
- assert:
- that:
- - hcloud_images.hcloud_image_info | list | count == 1
- - hcloud_images.hcloud_image_info[0].architecture == "arm"
-
-- name: test gather hcloud image infos with architecture
- hcloud_image_info:
- architecture: arm
- register: hcloud_images
-- name: verify test gather hcloud image infos with name
- assert:
- that:
- - hcloud_images.hcloud_image_info | selectattr('architecture','equalto','x86') | list | count == 0
- - hcloud_images.hcloud_image_info | selectattr('architecture','equalto','arm') | list | count > 2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/aliases
deleted file mode 100644
index 18dc30b6c..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/tasks/main.yml
deleted file mode 100644
index a25e550d0..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/tasks/main.yml
+++ /dev/null
@@ -1,247 +0,0 @@
-# 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 with check mode
- 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 }}"
- load_balancer_type: lb11
- network_zone: eu-central
- state: present
- register: result
-- name: verify create Load Balancer idempotence
- assert:
- that:
- - result is not changed
-
-- name: test change Load Balancer type
- hcloud_load_balancer:
- name: "{{ hcloud_load_balancer_name }}"
- load_balancer_type: lb21
- state: present
- register: result_after_test
- ignore_errors: true
-- name: verify change Load Balancer type
- assert:
- that:
- - result_after_test is changed
- - result_after_test.hcloud_load_balancer.load_balancer_type == "lb21"
-
-- name: test Load Balancer without type set to be idempotent
- hcloud_load_balancer:
- name: "{{hcloud_load_balancer_name}}"
- register: result_after_test
-- name: verify test Load Balancer without type set to be idempotent
- assert:
- that:
- - result_after_test is not changed
- - result_after_test.hcloud_load_balancer.load_balancer_type == "lb21"
-
-- 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
-
-- name: test create Load Balancer with delete protection
- hcloud_load_balancer:
- name: "{{ hcloud_load_balancer_name }}"
- load_balancer_type: lb11
- network_zone: eu-central
- delete_protection: true
- register: main_load_balancer
-- name: verify create Load Balancer with delete protection
- assert:
- that:
- - main_load_balancer is changed
- - main_load_balancer.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"
- register: result
- ignore_errors: yes
-- name: verify test delete Load Balancer
- assert:
- that:
- - result is failed
- - 'result.msg == "load balancer deletion is protected"'
-
-- name: test update Load Balancer delete protection
- hcloud_load_balancer:
- name: "{{ hcloud_load_balancer_name }}"
- delete_protection: false
- register: main_load_balancer
-- name: verify update Load Balancer delete protection
- assert:
- that:
- - main_load_balancer is changed
- - main_load_balancer.hcloud_load_balancer.delete_protection is sameas false
-
-- name: test delete Load Balancer
- hcloud_load_balancer:
- name: "{{ hcloud_load_balancer_name }}"
- state: "absent"
- register: result
-- name: verify test delete Load Balancer
- assert:
- that:
- - result is changed
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/aliases
deleted file mode 100644
index 18dc30b6c..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/defaults/main.yml
deleted file mode 100644
index 326973a78..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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}}-i"
-hcloud_server_name: "{{ hcloud_prefix | truncate(45, True, '', 0) }}-lb-i"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/tasks/main.yml
deleted file mode 100644
index 9e6528858..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/tasks/main.yml
+++ /dev/null
@@ -1,128 +0,0 @@
-# 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 ensure Load Balancer is absent
- hcloud_load_balancer:
- name: "{{ hcloud_load_balancer_name }}"
- state: absent
-- name: setup server
- hcloud_server:
- name: "{{hcloud_server_name}}"
- server_type: cx11
- image: ubuntu-20.04
- state: started
- 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
- network_zone: eu-central
- labels:
- key: value
- register: test_load_balancer
-
-- name: verify setup Load Balancer
- assert:
- that:
- - test_load_balancer 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 success
-- 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 success
-
-- name: test gather hcloud Load Balancer infos
- hcloud_load_balancer_info:
- id: "{{test_load_balancer.hcloud_load_balancer.id}}"
- register: hcloud_load_balancers
-- name: verify test gather hcloud Load Balancer infos
- assert:
- that:
- - hcloud_load_balancers.hcloud_load_balancer_info| list | count >= 1
- - hcloud_load_balancers.hcloud_load_balancer_info[0].targets | list | count == 1
- - hcloud_load_balancers.hcloud_load_balancer_info[0].targets | selectattr('type','equalto','server') | list | count == 1
- - hcloud_load_balancers.hcloud_load_balancer_info[0].targets | selectattr('server','equalto','{{ hcloud_server_name }}') | list | count == 1
- - hcloud_load_balancers.hcloud_load_balancer_info[0].services | list | count == 1
- - hcloud_load_balancers.hcloud_load_balancer_info[0].services | selectattr('protocol','equalto','http') | list | count == 1
- - hcloud_load_balancers.hcloud_load_balancer_info[0].services | selectattr('listen_port','equalto',80) | list | count == 1
- - hcloud_load_balancers.hcloud_load_balancer_info[0].services | selectattr('destination_port','equalto',80) | list | count == 1
-
-- name: test gather hcloud Load Balancer infos in check mode
- hcloud_load_balancer_info:
- check_mode: yes
- register: hcloud_load_balancers
-
-- name: verify test gather hcloud Load Balancer infos in check mode
- assert:
- that:
- - hcloud_load_balancers.hcloud_load_balancer_info| list | count >= 1
-
-
-- name: test gather hcloud Load Balancer infos with correct label selector
- hcloud_load_balancer_info:
- label_selector: "key=value"
- register: hcloud_load_balancers
-- name: verify test gather hcloud Load Balancer with correct label selector
- assert:
- that:
- - hcloud_load_balancers.hcloud_load_balancer_info|selectattr('name','equalto','{{ test_load_balancer.hcloud_load_balancer.name }}') | list | count == 1
-
-- name: test gather hcloud Load Balancer infos with wrong label selector
- hcloud_load_balancer_info:
- label_selector: "key!=value"
- register: hcloud_load_balancers
-- name: verify test gather hcloud Load Balancer with wrong label selector
- assert:
- that:
- - hcloud_load_balancers.hcloud_load_balancer_info | list | count == 0
-
-- name: test gather hcloud Load Balancer infos with correct id
- hcloud_load_balancer_info:
- id: "{{test_load_balancer.hcloud_load_balancer.id}}"
- register: hcloud_load_balancers
-- name: verify test gather hcloud Load Balancer with correct id
- assert:
- that:
- - hcloud_load_balancers.hcloud_load_balancer_info|selectattr('name','equalto','{{ test_load_balancer.hcloud_load_balancer.name }}') | list | count == 1
-
-- name: test gather hcloud Load Balancer infos with wrong id
- hcloud_load_balancer_info:
- id: "{{test_load_balancer.hcloud_load_balancer.id}}1"
- register: result
- ignore_errors: yes
-- name: verify test gather hcloud Load Balancer with wrong id
- assert:
- that:
- - result is failed
-
-- name: cleanup
- hcloud_load_balancer:
- id: "{{ test_load_balancer.hcloud_load_balancer.id }}"
- state: absent
- register: result
-- name: verify cleanup
- assert:
- that:
- - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/aliases
deleted file mode 100644
index 18dc30b6c..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/defaults/main.yml
deleted file mode 100644
index 6abf9ceec..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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}}-lb-n"
-hcloud_load_balancer_name: "{{hcloud_prefix}}-lb-n"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/aliases
deleted file mode 100644
index 18dc30b6c..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/aliases
deleted file mode 100644
index 18dc30b6c..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/defaults/main.yml
deleted file mode 100644
index 180133fde..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/defaults/main.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-# 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 | truncate(45, True, '', 0) }}-lb-t"
-hcloud_load_balancer_name: "{{hcloud_prefix}}-lb-target"
-hcloud_testing_ip: "176.9.59.39"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/tasks/main.yml
deleted file mode 100644
index bcd805a83..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/tasks/main.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-# 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
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/tasks/main.yml
deleted file mode 100644
index 99d5880ab..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/tasks/main.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-# 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 location infos
- hcloud_location_info:
- register: hcloud_location
-
-- name: verify test gather hcloud location infos
- assert:
- that:
- - hcloud_location.hcloud_location_info | list | count >= 5
-
-- name: test gather hcloud location infos in check mode
- hcloud_location_info:
- check_mode: yes
- register: hcloud_location
-
-- name: verify test gather hcloud location infos in check mode
- assert:
- that:
- - hcloud_location.hcloud_location_info | list | count >= 5
-
-- name: test gather hcloud location infos with correct name
- hcloud_location_info:
- name: "{{hcloud_location_name}}"
- register: hcloud_location
-- name: verify test gather hcloud location with correct name
- assert:
- that:
- - hcloud_location.hcloud_location_info|selectattr('name','equalto','{{ hcloud_location_name }}') | list | count == 1
-
-- name: test gather hcloud location infos with wrong name
- hcloud_location_info:
- name: "{{hcloud_location_name}}1"
- register: hcloud_location
-- name: verify test gather hcloud location with wrong name
- assert:
- that:
- - hcloud_location.hcloud_location_info | list | count == 0
-
-- name: test gather hcloud location infos with correct id
- hcloud_location_info:
- id: "{{hcloud_location_id}}"
- register: hcloud_location
-- name: verify test gather hcloud location with correct id
- assert:
- that:
- - hcloud_location.hcloud_location_info|selectattr('name','equalto','{{ hcloud_location_name }}') | list | count == 1
-
-- name: test gather hcloud location infos with wrong id
- hcloud_location_info:
- name: "4711"
- register: hcloud_location
-- name: verify test gather hcloud location with wrong id
- assert:
- that:
- - hcloud_location.hcloud_location_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/aliases
deleted file mode 100644
index 4b3a9b36f..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/aliases
+++ /dev/null
@@ -1,3 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
-disabled
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/aliases
deleted file mode 100644
index 18dc30b6c..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/defaults/main.yml
deleted file mode 100644
index f8a5279fb..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/defaults/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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}}-integration"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/tasks/main.yml
deleted file mode 100644
index e7924a8d0..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/tasks/main.yml
+++ /dev/null
@@ -1,117 +0,0 @@
-# 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 ensure network is absent
- hcloud_network:
- name: "{{ hcloud_network_name }}"
- state: absent
- register: result
-
-- name: create network
- hcloud_network:
- name: "{{ hcloud_network_name }}"
- ip_range: "10.0.0.0/16"
- labels:
- key: value
- register: main_network
-- name: verify create network
- assert:
- that:
- - main_network is changed
- - main_network.hcloud_network.name == "{{ hcloud_network_name }}"
- - main_network.hcloud_network.ip_range == "10.0.0.0/16"
-- name: create subnetwork
- hcloud_subnetwork:
- network: "{{ hcloud_network_name }}"
- type: server
- network_zone: eu-central
- ip_range: "10.0.1.0/24"
- register: main_subnetwork
-- name: verify create subnetwork
- assert:
- that:
- - main_subnetwork is changed
- - main_subnetwork.hcloud_subnetwork.network == "{{ hcloud_network_name }}"
-- name: create route
- hcloud_route:
- network: "{{ hcloud_network_name }}"
- destination: "10.0.3.0/24"
- gateway: "10.0.2.1"
- register: main_route
-- name: verify create route
- assert:
- that:
- - main_route is changed
- - main_route.hcloud_route.network == "{{ hcloud_network_name }}"
-
-- name: test gather hcloud network info in check mode
- hcloud_network_info:
- check_mode: yes
- register: hcloud_network
-- name: verify test gather hcloud network info in check mode
- assert:
- that:
- - hcloud_network.hcloud_network_info | selectattr('name','equalto','{{ hcloud_network_name }}') | list | count >= 1
-
-
-- name: test gather hcloud network info with correct label selector
- hcloud_network_info:
- label_selector: "key=value"
- register: hcloud_network
-- name: verify test gather hcloud network with correct label selector
- assert:
- that:
- - hcloud_network.hcloud_network_info | selectattr('name','equalto','{{ hcloud_network_name }}') | list | count >= 1
-
-- name: test gather hcloud network info with wrong label selector
- hcloud_network_info:
- label_selector: "key!=value"
- register: hcloud_network
-- name: verify test gather hcloud network with wrong label selector
- assert:
- that:
- - hcloud_network.hcloud_network_info | list | count == 0
-
-- name: test gather hcloud network info with correct name
- hcloud_network_info:
- name: "{{hcloud_network_name}}"
- register: hcloud_network
-- name: verify test gather hcloud network with correct name
- assert:
- that:
- - hcloud_network.hcloud_network_info | selectattr('name','equalto','{{ hcloud_network_name }}') | list | count == 1
- - hcloud_network.hcloud_network_info[0].subnetworks | list | count >= 1
- - hcloud_network.hcloud_network_info[0].routes | list | count >= 1
-
-- name: test gather hcloud network info with wrong name
- hcloud_network_info:
- name: "{{hcloud_network_name}}1"
- register: hcloud_network
-- name: verify test gather hcloud network with wrong name
- assert:
- that:
- - hcloud_network.hcloud_network_info | list | count == 0
-
-- name: test gather hcloud network info with correct id
- hcloud_network_info:
- id: "{{main_network.hcloud_network.id}}"
- register: hcloud_network
-- name: verify test gather hcloud network with correct id
- assert:
- that:
- - hcloud_network.hcloud_network_info | selectattr('name','equalto','{{ hcloud_network_name }}') | list | count == 1
-
-- name: test gather hcloud network info with wrong id
- hcloud_network_info:
- name: "4711"
- register: hcloud_network
-- name: verify test gather hcloud network with wrong id
- assert:
- that:
- - hcloud_network.hcloud_network_info | list | count == 0
-
-- name: cleanup
- hcloud_network:
- name: "{{ hcloud_network_name }}"
- state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/defaults/main.yml
deleted file mode 100644
index 21ce3429a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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_placement_group_name: "{{hcloud_prefix}}-i"
-hcloud_server_name: "{{ hcloud_prefix | truncate(45, True, '', 0) }}-i"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/defaults/main.yml
deleted file mode 100644
index 98aa28eea..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
----
-hcloud_prefix: "tests"
-hcloud_primary_ip_name: "{{hcloud_prefix}}-i"
-hcloud_server_name: "{{ hcloud_prefix | truncate(45, True, '', 0) }}-fip-t"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/aliases
deleted file mode 100644
index 18dc30b6c..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/defaults/main.yml
deleted file mode 100644
index 50117a8a5..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/defaults/main.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-# 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 | truncate(45, True, '', 0) }}"
-hcloud_floating_ip_name: "{{hcloud_prefix}}"
-hcloud_primary_ip_name: "{{hcloud_prefix}}"
-hcloud_load_balancer_name: "{{hcloud_prefix}}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/meta/main.yml
deleted file mode 100644
index 67d54d732..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - ansible.netcommon
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/tasks/main.yml
deleted file mode 100644
index dddbac0d0..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/tasks/main.yml
+++ /dev/null
@@ -1,224 +0,0 @@
-# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
----
-- name: setup
- hcloud_server:
- name: "{{ hcloud_server_name }}"
- server_type: cx11
- image: "ubuntu-22.04"
- ssh_keys:
- - ci@ansible.hetzner.cloud
- state: present
- register: setup
-- name: verify setup
- assert:
- that:
- - setup is success
-
-- name: setup Floating IP
- hcloud_floating_ip:
- name: "{{ hcloud_floating_ip_name }}"
- type: ipv4
- home_location: "fsn1"
- register: floatingIP
-- name: verify setup Floating IP
- assert:
- that:
- - floatingIP is success
-
-- name: setup Load Balancer
- hcloud_load_balancer:
- name: "{{ hcloud_load_balancer_name}}"
- load_balancer_type: lb11
- network_zone: eu-central
- state: present
- register: load_balancer
-- name: verify setup
- assert:
- that:
- - load_balancer is success
-
-- name: setup Primary IP
- hcloud_primary_ip:
- name: "{{ hcloud_primary_ip_name }}"
- type: ipv4
- datacenter: "fsn1-dc14"
- register: primaryIP
-- name: verify setup Primary IP
- assert:
- that:
- - primaryIP is success
-
-- name: test missing required parameter
- hcloud_rdns:
- state: present
- register: result
- ignore_errors: yes
-- name: verify fail test missing required parameters
- assert:
- that:
- - result is failed
- - 'result.msg == "missing required arguments: ip_address"'
-- name: test fail on not existing resource
- hcloud_rdns:
- server: "not-existing"
- ip_address: "127.0.0.1"
- state: present
- register: result
- ignore_errors: yes
-- name: verify fail on not existing resou
- assert:
- that:
- - result is failed
- - 'result.msg == "The selected server does not exist"'
-- name: test create rdns
- hcloud_rdns:
- server: "{{ hcloud_server_name }}"
- ip_address: "{{ setup.hcloud_server.ipv6 | ansible.netcommon.ipaddr('next_usable') }}"
- dns_ptr: "example.com"
- state: present
- register: rdns
-- name: verify create rdns
- assert:
- that:
- - rdns is changed
- - rdns.hcloud_rdns.server == "{{ hcloud_server_name }}"
- - rdns.hcloud_rdns.ip_address == "{{ setup.hcloud_server.ipv6 | ansible.netcommon.ipaddr('next_usable') }}"
- - rdns.hcloud_rdns.dns_ptr == "example.com"
-
-- name: test create rdns idempotency
- hcloud_rdns:
- server: "{{ hcloud_server_name }}"
- ip_address: "{{ setup.hcloud_server.ipv6 | ansible.netcommon.ipaddr('next_usable') }}"
- dns_ptr: "example.com"
- state: present
- register: result
-- name: verify create rdns idempotency
- assert:
- that:
- - result is not changed
-
-- name: test absent rdns
- hcloud_rdns:
- server: "{{ hcloud_server_name }}"
- ip_address: "{{ setup.hcloud_server.ipv6 | ansible.netcommon.ipaddr('next_usable') }}"
- state: absent
- register: result
-- name: verify test absent rdns
- assert:
- that:
- - result is changed
-
-- name: test update rdns
- hcloud_rdns:
- server: "{{ hcloud_server_name }}"
- ip_address: "{{ setup.hcloud_server.ipv4_address }}"
- dns_ptr: "example.com"
- state: present
- register: rdns
-- name: verify update rdns
- assert:
- that:
- - rdns is changed
- - rdns.hcloud_rdns.server == "{{ hcloud_server_name }}"
- - rdns.hcloud_rdns.ip_address == "{{ setup.hcloud_server.ipv4_address }}"
- - rdns.hcloud_rdns.dns_ptr == "example.com"
-
-- name: test reset rdns
- hcloud_rdns:
- server: "{{ hcloud_server_name }}"
- ip_address: "{{ setup.hcloud_server.ipv4_address }}"
- state: present
- register: rdns
-- name: verify reset rdns
- assert:
- that:
- - rdns is changed
- - rdns.hcloud_rdns.server == "{{ hcloud_server_name }}"
- - rdns.hcloud_rdns.ip_address == "{{ setup.hcloud_server.ipv4_address }}"
- - rdns.hcloud_rdns.dns_ptr != "example.com"
-
-- name: test create rdns with floating IP
- hcloud_rdns:
- floating_ip: "{{ hcloud_floating_ip_name }}"
- ip_address: "{{ floatingIP.hcloud_floating_ip.ip}}"
- dns_ptr: "example.com"
- state: present
- register: rdns
-- name: verify create rdns
- assert:
- that:
- - rdns is changed
- - rdns.hcloud_rdns.floating_ip == "{{ hcloud_floating_ip_name }}"
- - rdns.hcloud_rdns.ip_address == "{{ floatingIP.hcloud_floating_ip.ip}}"
- - rdns.hcloud_rdns.dns_ptr == "example.com"
-
-- name: test create rdns with primary IP
- hcloud_rdns:
- primary_ip: "{{ hcloud_primary_ip_name }}"
- ip_address: "{{ primaryIP.hcloud_primary_ip.ip}}"
- dns_ptr: "example.com"
- state: present
- register: rdns
-- name: verify create rdns
- assert:
- that:
- - rdns is changed
- - rdns.hcloud_rdns.primary_ip == "{{ hcloud_primary_ip_name }}"
- - rdns.hcloud_rdns.ip_address == "{{ primaryIP.hcloud_primary_ip.ip}}"
- - rdns.hcloud_rdns.dns_ptr == "example.com"
-
-- name: test create rdns with load balancer
- hcloud_rdns:
- load_balancer: "{{ hcloud_load_balancer_name }}"
- ip_address: "{{ load_balancer.hcloud_load_balancer.ipv4_address }}"
- dns_ptr: "example.com"
- state: present
- register: rdns
-- name: verify create rdns with load balancer
- assert:
- that:
- - rdns is changed
- - rdns.hcloud_rdns.load_balancer == "{{ hcloud_load_balancer_name }}"
- - rdns.hcloud_rdns.ip_address == "{{ load_balancer.hcloud_load_balancer.ipv4_address }}"
- - rdns.hcloud_rdns.dns_ptr == "example.com"
-
-- name: cleanup
- hcloud_server:
- name: "{{ hcloud_server_name }}"
- state: absent
- register: result
-- name: verify cleanup
- assert:
- that:
- - result is success
-
-- name: cleanup
- hcloud_floating_ip:
- name: "{{ hcloud_floating_ip_name }}"
- state: absent
- register: result
-- name: verify cleanup
- assert:
- that:
- - result is success
-
-- name: cleanup
- hcloud_primary_ip:
- name: "{{ hcloud_primary_ip_name }}"
- state: absent
- register: result
-- name: verify cleanup
- assert:
- that:
- - result is success
-
-- name: cleanup
- hcloud_load_balancer:
- name: "{{ hcloud_load_balancer_name }}"
- state: absent
- register: result
-- name: verify cleanup
- assert:
- that:
- - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/aliases
deleted file mode 100644
index 18dc30b6c..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/defaults/main.yml
deleted file mode 100644
index c93c7495e..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/defaults/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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}}-ro"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/meta/main.yml
deleted file mode 100644
index 67d54d732..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - ansible.netcommon
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/aliases
deleted file mode 100644
index 18dc30b6c..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/defaults/main.yml
deleted file mode 100644
index 4e1c4dc45..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/defaults/main.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-# 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 | truncate(45, True, '', 0) }}-i"
-hcloud_firewall_name: "{{hcloud_prefix}}-i"
-hcloud_primary_ip_name: "{{hcloud_prefix}}-i"
-hcloud_network_name: "{{hcloud_prefix}}-i"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/main.yml
deleted file mode 100644
index 209d9bd48..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/main.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright: (c) 2022, Hetzner Cloud GmbH <info@hetzner-cloud.de>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
----
-#- ansible.builtin.include_tasks: validation.yml
-- ansible.builtin.include_tasks: basic.yml
-#- ansible.builtin.include_tasks: firewalls.yml
-- ansible.builtin.include_tasks: primary_ips.yml
-- ansible.builtin.include_tasks: private_network_only.yml
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/defaults/main.yml
deleted file mode 100644
index aa27d6452..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/defaults/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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 | truncate(45, True, '', 0) }}-ii"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/tasks/main.yml
deleted file mode 100644
index b425b4127..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/tasks/main.yml
+++ /dev/null
@@ -1,128 +0,0 @@
-# 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 ensure server is absent
- hcloud_server:
- name: "{{ hcloud_server_name }}"
- state: absent
- register: result
-
-- name: create server
- hcloud_server:
- name: "{{ hcloud_server_name }}"
- server_type: cx11
- image: ubuntu-22.04
- state: started
- labels:
- key: value
- register: main_server
-- name: verify create server
- assert:
- that:
- - main_server is changed
- - main_server.hcloud_server.name == "{{ hcloud_server_name }}"
- - main_server.hcloud_server.server_type == "cx11"
- - main_server.hcloud_server.status == "running"
- - main_server.root_password != ""
-
-
-- name: test gather hcloud server infos in check mode
- hcloud_server_info:
- register: server
- check_mode: yes
-
-- name: verify test gather hcloud server infos in check mode
- assert:
- that:
- - server.hcloud_server_info|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1
-
-
-- name: test gather hcloud server infos with correct label selector
- hcloud_server_info:
- label_selector: "key=value"
- register: server
-- name: verify test gather hcloud server infos with correct label selector
- assert:
- that:
- - server.hcloud_server_info|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1
-
-- name: test gather hcloud server infos with wrong label selector
- hcloud_server_info:
- label_selector: "key!=value"
- register: server
-- name: verify test gather hcloud server infos with wrong label selector
- assert:
- that:
- - server.hcloud_server_info | list | count == 0
-
-- name: test gather hcloud server infos with correct name
- hcloud_server_info:
- name: "{{hcloud_server_name}}"
- register: server
-- name: verify test gather hcloud server infos with correct name
- assert:
- that:
- - server.hcloud_server_info|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1
-
-- name: test gather hcloud server infos with wrong name
- hcloud_server_info:
- name: "{{hcloud_server_name}}1"
- register: server
-- name: verify test gather hcloud server infos with wrong name
- assert:
- that:
- - server.hcloud_server_info | list | count == 0
-
-- name: test gather hcloud server infos with correct id
- hcloud_server_info:
- id: "{{main_server.hcloud_server.id}}"
- register: server
-- name: verify test gather hcloud server infos with correct id
- assert:
- that:
- - server.hcloud_server_info|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1
-
-- name: test gather hcloud server infos with wrong id
- hcloud_server_info:
- name: "4711"
- register: server
-- name: verify test gather hcloud server infos with wrong id
- assert:
- that:
- - server.hcloud_server_info | list | count == 0
-
-- name: cleanup
- hcloud_server:
- name: "{{ hcloud_server_name }}"
- state: absent
-
-- name: create server without ips
- hcloud_server:
- name: "{{ hcloud_server_name }}"
- server_type: cx11
- image: ubuntu-22.04
- state: stopped
- labels:
- key: value
- enable_ipv4: no
- enable_ipv6: no
- register: main_server
-- name: verify create server
- assert:
- that:
- - main_server is changed
- - main_server.hcloud_server.name == "{{ hcloud_server_name }}"
- - main_server.hcloud_server.server_type == "cx11"
- - main_server.root_password != ""
-- name: test gather hcloud server infos with correct id
- hcloud_server_info:
- id: "{{main_server.hcloud_server.id}}"
- register: server
-- name: verify test gather hcloud server infos with correct id
- assert:
- that:
- - server.hcloud_server_info|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1
-- name: cleanup
- hcloud_server:
- name: "{{ hcloud_server_name }}"
- state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/aliases
deleted file mode 100644
index 7f17468b0..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/aliases
+++ /dev/null
@@ -1,3 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
-disabled
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/defaults/main.yml
deleted file mode 100644
index 2e020c495..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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}}-sn"
-hcloud_server_name: "{{ hcloud_prefix | truncate(45, True, '', 0) }}-sn"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/tasks/main.yml
deleted file mode 100644
index 3c1fce8c0..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/tasks/main.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-# 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 server type infos
- hcloud_server_type_info:
- register: hcloud_server_types
-- name: verify test gather hcloud server type infos
- assert:
- that:
- - hcloud_server_types.hcloud_server_type_info| list | count > 2
-
-- name: test gather hcloud server type infos in check mode
- hcloud_server_type_info:
- check_mode: yes
- register: hcloud_server_types
-
-- name: verify test gather hcloud server type infos in check mode
- assert:
- that:
- - hcloud_server_types.hcloud_server_type_info| list | count > 2
-
-- name: test gather hcloud server type infos with name
- hcloud_server_type_info:
- name: "{{hcloud_server_type_name}}"
- register: hcloud_server_types
-- name: verify test gather hcloud server type with name
- assert:
- that:
- - hcloud_server_types.hcloud_server_type_info|selectattr('name','equalto','{{ hcloud_server_type_name }}') | list | count == 1
-
-- name: test gather hcloud server type infos with correct id
- hcloud_server_type_info:
- id: "{{hcloud_server_type_id}}"
- register: hcloud_server_types
-- name: verify test gather hcloud server type with correct id
- assert:
- that:
- - hcloud_server_types.hcloud_server_type_info|selectattr('name','equalto','{{ hcloud_server_type_name }}') | list | count == 1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/defaults/main.yml
deleted file mode 100644
index cee1d4691..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/defaults/main.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-# 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 | truncate(45, True, '', 0) }}"
-hcloud_ssh_key_name: "{{hcloud_prefix}}"
-hcloud_ssh_key_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDnaTPfKaX1QKcRLOfr34buVLh5FhJAThI9NYB0xNdXsMd4Y0zLyyCQzHbx4eWCVZxym/s6csWSeLaAhO1GOHeAw3hQFMqf1oTBx6Y8g0pKpeotKPa/PDSUzdZF9Lc+DadtpQd8kFVHAu1Kd3zoEUnk1u6kP7I4qu4Z/6F9qBDF+M3aobiPVxdS7GwaVRW3nZu+FcQDLiBiNOjuRDyjHcDfEUkoh2SOu25RrFtGPzFu5mGmBJwotKpWAocLGfHzyn/fAHxgw3jKZVH/t+XWQFnl82Ie8yE3Z1EZ7oDkNRqFQT9AdXEQOLycTTYTQMJZpgeFTv3sAo6lPRCusiFmmLcf ci@ansible.hetzner.cloud"
-hcloud_ssh_key_fingerprint: "56:89:c4:d6:a7:4a:79:82:f4:c2:58:9c:e1:d2:2d:4e"
-
-hcloud_doubled_ssh_key_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1AiuN3UMQKzOs4tNudmlDSkSebC+savc6CivoHGflUKeli7nKb5pKgGiqH+zeWZc+8+flUa2BxsJWmi7d1nGJ++W4BnzmqW78ApelpJnGtuX8IKNcq/trhVTQyaShPiLluoBs7bXyyZpAKNGkk3jHrgwwYD/QQDN0CJnQUM18fjH5CUes2vmaG/kkhn7ctuVHDOvDcEy8KdBX3fYyrtXw5GgWDC5borG6yT1f3E9AXfRPL9OQjMTeC+G4FHscJAZjNnYav+jLrQLdV1xJ0JgbjRyBgTAfBszx9oKIjzCUPvpj4npju0WFGu10pIh0w7bluMoVn1tS6Y3gxE/Cepwt ci@ansible.hetzner.cloud"
-hcloud_doubled_ssh_key_fingerprint: "f9:33:40:ff:77:f3:3e:85:f2:9e:8f:98:71:fd:a0:58"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/meta/main.yml
deleted file mode 100644
index 5dcc0725d..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/meta/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-dependencies:
- - setup_sshkey
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/meta/main.yml
deleted file mode 100644
index 5dcc0725d..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/meta/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-dependencies:
- - setup_sshkey
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/tasks/main.yml
deleted file mode 100644
index 87cbd2626..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/tasks/main.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-# 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 ensure ssh key is absent
- hcloud_ssh_key:
- name: "{{ hcloud_ssh_key_name }}"
- state: absent
- register: result
-
-- name: setup test ssh_key
- hcloud_ssh_key:
- name: "{{hcloud_ssh_key_name}}"
- public_key: "{{ key_material }}"
- labels:
- key: value
- register: result
-- name: verify create test ssh_key
- assert:
- that:
- - result is changed
- - result.hcloud_ssh_key.public_key == "{{ key_material }}"
-
-- name: test gather hcloud ssh key infos in check mode
- hcloud_ssh_key_info:
- register: hcloud_ssh_key
- check_mode: yes
-- name: verify test gather hcloud ssh key infos in check mode
- assert:
- that:
- - hcloud_ssh_key.hcloud_ssh_key_info| list | count >= 1
-
-- name: test gather hcloud ssh key infos
- hcloud_ssh_key_info:
- register: hcloud_ssh_key
- check_mode: yes
-- name: verify test gather hcloud ssh key infos
- assert:
- that:
- - hcloud_ssh_key.hcloud_ssh_key_info| list | count >= 1
-
-- name: test gather hcloud ssh key infos with correct label selector
- hcloud_ssh_key_info:
- label_selector: "key=value"
- register: hcloud_ssh_key
-- name: verify test gather hcloud ssh key infos with correct label selector
- assert:
- that:
- - hcloud_ssh_key.hcloud_ssh_key_info|selectattr('name','equalto','{{ hcloud_ssh_key_name }}') | list | count == 1
-
-- name: test gather hcloud ssh key infos with wrong label selector
- hcloud_ssh_key_info:
- label_selector: "key!=value"
- register: hcloud_ssh_key
-- name: verify test gather hcloud ssh key infos with wrong label selector
- assert:
- that:
- - hcloud_ssh_key.hcloud_ssh_key_info | list | count == 0
-
-- name: cleanup
- hcloud_ssh_key:
- name: "{{hcloud_ssh_key_name}}"
- state: absent
- register: result
-- name: verify cleanup
- assert:
- that:
- - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/aliases
deleted file mode 100644
index af1d98c3d..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group3
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/defaults/main.yml
deleted file mode 100644
index 79f0d8783..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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}}-s"
-hetzner_vswitch_id: 15311
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/tasks/main.yml
deleted file mode 100644
index 0453f9d13..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/tasks/main.yml
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
----
-- name: setup
- hcloud_network:
- name: "{{ hcloud_network_name }}"
- ip_range: "10.0.0.0/8"
- state: present
- register: network
-- name: verify setup
- assert:
- that:
- - network is success
-
-- name: test missing required parameters on create route
- hcloud_subnetwork:
- network: "{{ hcloud_network_name }}"
- state: present
- register: result
- ignore_errors: yes
-- name: verify fail test missing required parameters on create route
- assert:
- that:
- - result is failed
- - 'result.msg == "missing required arguments: ip_range, network_zone, type"'
-
-- name: test create subnetwork with checkmode
- hcloud_subnetwork:
- network: "{{ hcloud_network_name }}"
- ip_range: "10.0.0.0/16"
- type: "server"
- network_zone: "eu-central"
- state: present
- register: result
- check_mode: yes
-- name: verify test create subnetwork with checkmode
- assert:
- that:
- - result is changed
-
-- name: test create subnetwork
- hcloud_subnetwork:
- network: "{{ hcloud_network_name }}"
- ip_range: "10.0.0.0/16"
- type: "cloud"
- network_zone: "eu-central"
- state: present
- register: subnet
-- name: verify create subnetwork
- assert:
- that:
- - subnet is changed
- - subnet.hcloud_subnetwork.network == "{{ hcloud_network_name }}"
- - subnet.hcloud_subnetwork.ip_range == "10.0.0.0/16"
- - subnet.hcloud_subnetwork.type == "cloud"
- - subnet.hcloud_subnetwork.network_zone == "eu-central"
-
-- name: test create subnetwork idempotency
- hcloud_subnetwork:
- network: "{{ hcloud_network_name }}"
- ip_range: "10.0.0.0/16"
- type: "cloud"
- network_zone: "eu-central"
- state: present
- register: result
-- name: verify create subnetwork idempotency
- assert:
- that:
- - result is not changed
-
-- name: test absent subnetwork
- hcloud_subnetwork:
- network: "{{ hcloud_network_name }}"
- ip_range: "10.0.0.0/16"
- type: "cloud"
- network_zone: "eu-central"
- state: absent
- register: result
-- name: verify test absent subnetwork
- assert:
- that:
- - result is changed
-
-- name: test vswitch subnetwork
- hcloud_subnetwork:
- network: "{{ hcloud_network_name }}"
- ip_range: "10.0.0.0/16"
- type: "vswitch"
- network_zone: "eu-central"
- vswitch_id: "{{ hetzner_vswitch_id }}"
- state: present
- register: subnet
-- name: verify test vswitch subnetwork
- assert:
- that:
- - subnet is changed
- - subnet.hcloud_subnetwork.network == "{{ hcloud_network_name }}"
- - subnet.hcloud_subnetwork.ip_range == "10.0.0.0/16"
- - subnet.hcloud_subnetwork.type == "vswitch"
- - subnet.hcloud_subnetwork.network_zone == "eu-central"
- - subnet.hcloud_subnetwork.vswitch_id == hetzner_vswitch_id
-
-- name: test absent subnetwork
- hcloud_subnetwork:
- network: "{{ hcloud_network_name }}"
- ip_range: "10.0.0.0/16"
- type: "vswitch"
- network_zone: "eu-central"
- vswitch_id: "{{ hetzner_vswitch_id }}"
- state: absent
- register: subnet
-- name: verify test absent 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
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/defaults/main.yml
deleted file mode 100644
index ff16ce28f..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/defaults/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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_volume_name: "{{ hcloud_prefix | truncate(60, True, '', 0) }}-i"
-hcloud_server_name: "{{ hcloud_prefix | truncate(45, True, '', 0) }}-vs"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/aliases
deleted file mode 100644
index 55ec821a4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/aliases
+++ /dev/null
@@ -1,2 +0,0 @@
-cloud/hcloud
-shippable/hcloud/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/defaults/main.yml
deleted file mode 100644
index 52c468eeb..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/defaults/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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_volume_name: "{{ hcloud_prefix | truncate(60, True, '', 0) }}-i"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/meta/main.yml
deleted file mode 100644
index 407c9018a..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/meta/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-collections:
- - community.general.ipfilter
- - hetzner.cloud
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/tasks/main.yml
deleted file mode 100644
index ecea7ad31..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/tasks/main.yml
+++ /dev/null
@@ -1,101 +0,0 @@
-# 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 ensure volume is absent
- hcloud_volume:
- name: "{{ hcloud_volume_name }}"
- state: absent
- register: result
-
-- name: setup volume
- hcloud_volume:
- name: "{{hcloud_volume_name}}"
- size: 10
- location: "fsn1"
- labels:
- key: value
- register: main_volume
-- name: verify setup volume
- assert:
- that:
- - main_volume is changed
-
-- name: test gather hcloud volume infos in check mode
- hcloud_volume_info:
- register: hcloud_volume
- check_mode: yes
-
-- name: verify test gather hcloud volume infos in check mode
- vars:
- volume: "{{ hcloud_volume.hcloud_volume_info|selectattr('name','equalto',hcloud_volume_name) | first }}"
- assert:
- that:
- - hcloud_volume.hcloud_volume_info|selectattr('name','equalto','{{ hcloud_volume_name }}') | list | count == 1
- - volume.name == "{{hcloud_volume_name}}"
- - volume.location == "fsn1"
- - volume.size == 10
- - volume.linux_device is defined
-
-- name: test gather hcloud volume infos with correct label selector
- hcloud_volume_info:
- label_selector: "key=value"
- register: hcloud_volume
-- name: verify test gather hcloud volume infos with correct label selector
- assert:
- that:
- - hcloud_volume.hcloud_volume_info|selectattr('name','equalto','{{ hcloud_volume_name }}') | list | count == 1
-
-- name: test gather hcloud volume infos with wrong label selector
- hcloud_volume_info:
- label_selector: "key!=value"
- register: hcloud_volume
-- name: verify test gather hcloud volume infos with wrong label selector
- assert:
- that:
- - hcloud_volume.hcloud_volume_info | list | count == 0
-
-- name: test gather hcloud volume infos with correct name
- hcloud_volume_info:
- name: "{{hcloud_volume_name}}"
- register: hcloud_volume
-- name: verify test gather hcloud volume infos with correct name
- assert:
- that:
- - hcloud_volume.hcloud_volume_info|selectattr('name','equalto','{{ hcloud_volume_name }}') | list | count == 1
-
-- name: test gather hcloud volume infos with wrong name
- hcloud_volume_info:
- name: "{{hcloud_volume_name}}1"
- register: hcloud_volume
-- name: verify test gather hcloud volume infos with wrong name
- assert:
- that:
- - hcloud_volume.hcloud_volume_info | list | count == 0
-
-- name: test gather hcloud volume facts with correct id
- hcloud_volume_info:
- id: "{{main_volume.hcloud_volume.id}}"
- register: hcloud_volume
-- name: verify test gather hcloud volume with correct id
- assert:
- that:
- - hcloud_volume.hcloud_volume_info|selectattr('name','equalto','{{ hcloud_volume_name }}') | list | count == 1
-
-- name: test gather hcloud volume infos with wrong id
- hcloud_volume_info:
- name: "4711"
- register: hcloud_volume
-- name: verify test gather hcloud volume infos with wrong id
- assert:
- that:
- - hcloud_volume.hcloud_volume_info | list | count == 0
-
-- name: cleanup
- hcloud_volume:
- name: "{{ hcloud_volume_name }}"
- state: absent
- register: result
-- name: verify cleanup
- assert:
- that:
- - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/defaults/main/main.yml
new file mode 100644
index 000000000..d7a350577
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/defaults/main/main.yml
@@ -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_server_name: "{{ hcloud_ns }}"
+hcloud_snapshot_name: "{{ hcloud_ns }}"
+hcloud_image_name: ubuntu-22.04
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/meta/main.yml
new file mode 100644
index 000000000..49f5c0c4b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - setup_hcloud_cli
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/cleanup.yml
new file mode 100644
index 000000000..a99c36549
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/prepare.yml
new file mode 100644
index 000000000..9c65ae86d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/prepare.yml
@@ -0,0 +1,23 @@
+---
+- name: Create test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ server_type: cx11
+ image: ubuntu-22.04
+ state: stopped
+ register: test_server
+
+- name: Create test_snapshot
+ ansible.builtin.script:
+ cmd: >
+ {{ hcloud_cli_path }} server create-image
+ --type snapshot
+ --description "{{ hcloud_snapshot_name }}"
+ --label key=value
+ "{{ test_server.hcloud_server.id }}"
+ | awk '{print $2}'
+ register: test_snapshot
+
+- name: Set test_snapshot_id
+ ansible.builtin.set_fact:
+ test_snapshot_id: "{{ test_snapshot.stdout_lines[0] }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/test.yml
new file mode 100644
index 000000000..270285e9c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/image_info/tasks/test.yml
@@ -0,0 +1,104 @@
+# 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: Gather hcloud_image_info
+ hetzner.hcloud.image_info:
+ register: result
+- name: Verify hcloud_image_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_image_info | list | count >= 3
+
+- name: Gather hcloud_image_info with architecture
+ hetzner.hcloud.image_info:
+ architecture: arm
+ register: result
+- name: Verify hcloud_image_info with architecture
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_image_info | selectattr('architecture', 'equalto', 'x86') | list | count == 0
+ - result.hcloud_image_info | selectattr('architecture', 'equalto', 'arm') | list | count > 2
+
+- name: Gather hcloud_image_info in check mode
+ hetzner.hcloud.image_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_image_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_image_info | list | count >= 3
+
+- name: Gather hcloud_image_info with correct id
+ hetzner.hcloud.image_info:
+ id: "{{ test_snapshot_id }}"
+ type: snapshot
+ register: result
+- name: Verify hcloud_image_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_image_info | list | count == 1
+
+- name: Gather hcloud_image_info with wrong id
+ hetzner.hcloud.image_info:
+ id: "{{ test_snapshot_id }}4321"
+ type: snapshot
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_image_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_image_info with correct name
+ hetzner.hcloud.image_info:
+ name: "{{ hcloud_image_name }}"
+ register: result
+- name: Verify hcloud_image_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_image_info | list | count == 1
+ - result.hcloud_image_info[0].architecture == "x86"
+
+- name: Gather hcloud_image_info with wrong name
+ hetzner.hcloud.image_info:
+ name: "{{ hcloud_image_name }}-invalid"
+ register: result
+- name: Verify hcloud_image_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_image_info | list | count == 0
+
+- name: Gather hcloud_image_info with correct name and architecture
+ hetzner.hcloud.image_info:
+ name: "{{ hcloud_image_name }}"
+ architecture: arm
+ register: result
+- name: Verify hcloud_image_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_image_info | list | count == 1
+ - result.hcloud_image_info[0].architecture == "arm"
+
+- name: Gather hcloud_image_info with correct label selector
+ hetzner.hcloud.image_info:
+ label_selector: "key=value"
+ type: snapshot
+ register: result
+- name: Verify hcloud_image_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ # Snapshot names are stored in the description field
+ - >
+ result.hcloud_image_info
+ | selectattr('description', 'equalto', hcloud_snapshot_name)
+ | list | count == 1
+
+- name: Gather hcloud_image_info with wrong label selector
+ hetzner.hcloud.image_info:
+ label_selector: "key!=value"
+ type: snapshot
+ register: result
+- name: Verify hcloud_image_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_image_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/aliases
new file mode 100644
index 000000000..a6a90a6bf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group3
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/defaults/main/main.yml
new file mode 100644
index 000000000..9e3c30d01
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/defaults/main/main.yml
@@ -0,0 +1,7 @@
+# Copyright: (c) 2023, 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_iso_id: 551
+hcloud_iso_name: systemrescuecd-x86-5.2.2.iso
+hcloud_iso_type: public
+hcloud_iso_architecture: x86
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/tasks/test.yml
new file mode 100644
index 000000000..5a4a42da1
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/iso_info/tasks/test.yml
@@ -0,0 +1,73 @@
+# Copyright: (c) 2023, 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: Gather hcloud_iso_info
+ hetzner.hcloud.iso_info:
+ register: result
+- name: Verify hcloud_iso_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_iso_info | list | count >= 1
+
+- name: Gather hcloud_iso_info in check mode
+ hetzner.hcloud.iso_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_iso_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_iso_info | list | count >= 1
+
+- name: Gather hcloud_iso_info with correct id
+ hetzner.hcloud.iso_info:
+ id: "{{ hcloud_iso_id }}"
+ register: result
+- name: Verify hcloud_iso_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_iso_info | list | count == 1
+ - result.hcloud_iso_info[0].id == hcloud_iso_id | string
+ - result.hcloud_iso_info[0].name == hcloud_iso_name
+ - result.hcloud_iso_info[0].architecture == hcloud_iso_architecture
+ - result.hcloud_iso_info[0].type == hcloud_iso_type
+ - result.hcloud_iso_info[0].deprecated is none
+ - result.hcloud_iso_info[0].deprecation is none
+
+- name: Gather hcloud_iso_info with wrong id
+ hetzner.hcloud.iso_info:
+ id: "{{ hcloud_iso_id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_iso_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_iso_info with correct name
+ hetzner.hcloud.iso_info:
+ name: "{{ hcloud_iso_name }}"
+ register: result
+- name: Verify hcloud_iso_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_iso_info | list | count == 1
+
+- name: Gather hcloud_iso_info with wrong name
+ hetzner.hcloud.iso_info:
+ name: "{{ hcloud_iso_name }}-invalid"
+ register: result
+- name: Verify hcloud_iso_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_iso_info | list | count == 0
+
+- name: Gather hcloud_iso_info with architecture
+ hetzner.hcloud.iso_info:
+ architecture: arm
+ register: result
+- name: Verify hcloud_iso_info with architecture
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_iso_info | list | count > 2
+ - result.hcloud_iso_info | selectattr('architecture', 'equalto', 'x86') | list | count == 0
+ - result.hcloud_iso_info | selectattr('architecture', 'equalto', 'arm') | list | count > 2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/aliases
new file mode 100644
index 000000000..62828d1e9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/defaults/main/main.yml
index 7f431cd8d..458094e95 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/defaults/main/main.yml
@@ -1,5 +1,4 @@
# 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}}-i"
+hcloud_load_balancer_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/cleanup.yml
new file mode 100644
index 000000000..b9ad6d254
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_load_balancer
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/test.yml
new file mode 100644
index 000000000..343f15672
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer/tasks/test.yml
@@ -0,0 +1,145 @@
+# 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
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ state: present
+ ignore_errors: true
+ register: result
+- name: Verify missing required parameters
+ ansible.builtin.assert:
+ that:
+ - result is failed
+ - 'result.msg == "missing required arguments: load_balancer_type"'
+
+- name: Test create with check mode
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ load_balancer_type: lb11
+ network_zone: eu-central
+ state: present
+ check_mode: true
+ register: result
+- name: Verify create with check mode
+ ansible.builtin.assert:
+ that:
+ - result is changed
+
+- name: Test create
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ load_balancer_type: lb11
+ network_zone: eu-central
+ labels:
+ key: value
+ label: value123
+ state: present
+ register: result
+- name: Verify create
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_load_balancer.name == hcloud_load_balancer_name
+ - result.hcloud_load_balancer.load_balancer_type == "lb11"
+ - result.hcloud_load_balancer.algorithm == "round_robin"
+ - result.hcloud_load_balancer.labels.key == "value"
+ - result.hcloud_load_balancer.labels.label == "value123"
+ - result.hcloud_load_balancer.delete_protection == false
+
+- name: Test create idempotency
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ load_balancer_type: lb11
+ network_zone: eu-central
+ state: present
+ register: result
+- name: Verify create idempotency
+ ansible.builtin.assert:
+ that:
+ - result is not changed
+
+- name: Test update algorithm
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ algorithm: least_connections
+ state: present
+ register: result
+- name: Verify update algorithm
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_load_balancer.algorithm == "least_connections"
+
+- name: Test update load_balancer_type
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ load_balancer_type: lb21
+ state: present
+ register: result
+- name: Verify update load_balancer_type
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_load_balancer.load_balancer_type == "lb21"
+
+- name: Test update labels
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ labels:
+ key: changed
+ label: changed123
+ state: present
+ register: result
+- name: Verify update load_balancer_type
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_load_balancer.labels.key == "changed"
+ - result.hcloud_load_balancer.labels.label == "changed123"
+
+- name: Test update delete_protection
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ delete_protection: true
+ state: present
+ register: result
+- name: Verify update load_balancer_type
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_load_balancer.delete_protection == true
+
+- name: Test delete with protection
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ state: absent
+ register: result
+ ignore_errors: true
+- name: Verify delete with protection
+ ansible.builtin.assert:
+ that:
+ - result is failed
+ - 'result.msg == "load balancer deletion is protected"'
+
+- name: Test update delete_protection
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ delete_protection: false
+ state: present
+ register: result
+- name: Verify update delete_protection
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_load_balancer.delete_protection == false
+
+- name: Test delete
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ state: absent
+ register: result
+- name: Verify delete
+ ansible.builtin.assert:
+ that:
+ - result is changed
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/aliases
new file mode 100644
index 000000000..62828d1e9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/defaults/main/main.yml
new file mode 100644
index 000000000..63c342baf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/defaults/main/main.yml
@@ -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_load_balancer_name: "{{ hcloud_ns }}"
+hcloud_server_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/meta/main.yml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/meta/main.yml
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/cleanup.yml
new file mode 100644
index 000000000..b99d2cd58
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/cleanup.yml
@@ -0,0 +1,10 @@
+---
+- name: Cleanup test_load_balancer
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ state: absent
+
+- name: Cleanup test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/prepare.yml
new file mode 100644
index 000000000..bfad755df
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/prepare.yml
@@ -0,0 +1,33 @@
+---
+- name: Create test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ server_type: cx11
+ image: ubuntu-22.04
+ state: started
+ register: test_server
+
+- name: Create test_load_balancer
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ load_balancer_type: lb11
+ network_zone: eu-central
+ labels:
+ key: value
+ register: test_load_balancer
+
+- name: Create test_load_balancer_target
+ hetzner.hcloud.load_balancer_target:
+ type: "server"
+ load_balancer: "{{ hcloud_load_balancer_name }}"
+ server: "{{ hcloud_server_name }}"
+ state: present
+ register: test_load_balancer_target
+
+- name: Create test_load_balancer_service
+ hetzner.hcloud.load_balancer_service:
+ load_balancer: "{{ hcloud_load_balancer_name }}"
+ protocol: "http"
+ listen_port: 80
+ state: present
+ register: test_load_balancer_service
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/test.yml
new file mode 100644
index 000000000..36ad43b40
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_info/tasks/test.yml
@@ -0,0 +1,86 @@
+# 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: Gather hcloud_load_balancer_info
+ hetzner.hcloud.load_balancer_info:
+ register: result
+- name: Verify hcloud_load_balancer_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_info | list | count >= 1
+
+- name: Gather hcloud_load_balancer_info in check mode
+ hetzner.hcloud.load_balancer_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_load_balancer_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_info | list | count >= 1
+
+- name: Gather hcloud_load_balancer_info with correct id
+ hetzner.hcloud.load_balancer_info:
+ id: "{{ test_load_balancer.hcloud_load_balancer.id }}"
+ register: result
+- name: Verify hcloud_load_balancer_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_info | list | count == 1
+ - result.hcloud_load_balancer_info[0].targets | list | count == 1
+ - result.hcloud_load_balancer_info[0].targets | selectattr('type', 'equalto', 'server') | list | count == 1
+ - result.hcloud_load_balancer_info[0].targets | selectattr('server', 'equalto', hcloud_server_name) | list | count == 1
+ - result.hcloud_load_balancer_info[0].targets[0].health_status[0].listen_port == 80
+ - result.hcloud_load_balancer_info[0].targets[0].health_status[0].status in ['healthy', 'unhealthy', 'unknown']
+ - result.hcloud_load_balancer_info[0].services | list | count == 1
+ - result.hcloud_load_balancer_info[0].services | selectattr('protocol', 'equalto', 'http') | list | count == 1
+ - result.hcloud_load_balancer_info[0].services | selectattr('listen_port', 'equalto', 80) | list | count == 1
+ - result.hcloud_load_balancer_info[0].services | selectattr('destination_port', 'equalto', 80) | list | count == 1
+
+- name: Gather hcloud_load_balancer_info with wrong id
+ hetzner.hcloud.load_balancer_info:
+ id: "{{ test_load_balancer.hcloud_load_balancer.id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_load_balancer_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_load_balancer_info with correct name
+ hetzner.hcloud.load_balancer_info:
+ name: "{{ hcloud_load_balancer_name }}"
+ register: result
+- name: Verify hcloud_load_balancer_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_info | list | count == 1
+
+- name: Gather hcloud_load_balancer_info with wrong name
+ hetzner.hcloud.load_balancer_info:
+ name: "{{ hcloud_load_balancer_name }}-invalid"
+ register: result
+- name: Verify hcloud_load_balancer_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_info | list | count == 0
+
+- name: Gather hcloud_load_balancer_info with correct label selector
+ hetzner.hcloud.load_balancer_info:
+ label_selector: "key=value"
+ register: result
+- name: Verify hcloud_load_balancer_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ - >
+ result.hcloud_load_balancer_info
+ | selectattr('name', 'equalto', hcloud_load_balancer_name)
+ | list | count == 1
+
+- name: Gather hcloud_load_balancer_info with wrong label selector
+ hetzner.hcloud.load_balancer_info:
+ label_selector: "key!=value"
+ register: result
+- name: Verify hcloud_load_balancer_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/aliases
new file mode 100644
index 000000000..62828d1e9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/defaults/main/main.yml
new file mode 100644
index 000000000..d7a9d233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/defaults/main/main.yml
@@ -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_network_name: "{{ hcloud_ns }}"
+hcloud_load_balancer_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/tasks/test.yml
index 9a1bf5175..06e469619 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_network/tasks/test.yml
@@ -2,7 +2,7 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup network
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{ hcloud_network_name }}"
ip_range: "10.0.0.0/8"
state: present
@@ -10,10 +10,10 @@
- name: verify setup network
assert:
that:
- - network is success
+ - network is success
- name: setup subnetwork
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: "{{ hcloud_network_name }}"
ip_range: "10.0.0.0/16"
type: "cloud"
@@ -23,10 +23,10 @@
- name: verify subnetwork
assert:
that:
- - subnetwork is success
+ - subnetwork is success
- name: setup load_balancer
- hcloud_load_balancer:
+ hetzner.hcloud.load_balancer:
name: "{{hcloud_load_balancer_name}}"
load_balancer_type: lb11
state: present
@@ -38,10 +38,10 @@
- load_balancer is success
- name: test missing required parameters on create load_balancer network
- hcloud_load_balancer_network:
+ hetzner.hcloud.load_balancer_network:
state: present
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing required parameters on create load_balancer network
assert:
that:
@@ -49,7 +49,7 @@
- '"missing required arguments:" in result.msg'
- name: test fail load balancer does not exist
- hetzner.hcloud.hcloud_load_balancer_network:
+ hetzner.hcloud.load_balancer_network:
network: "{{ hcloud_network_name }}"
load_balancer: does-not-exist
state: present
@@ -59,10 +59,10 @@
assert:
that:
- result is failed
- - "result.msg == 'Load balancer does not exist: does-not-exist'"
+ - "result.msg == 'resource (load_balancer) does not exist: does-not-exist'"
- name: test fail network does not exist
- hetzner.hcloud.hcloud_load_balancer_network:
+ hetzner.hcloud.load_balancer_network:
network: does-not-exist
load_balancer: "{{ hcloud_load_balancer_name }}"
state: present
@@ -72,22 +72,22 @@
assert:
that:
- result is failed
- - "result.msg == 'Network does not exist: does-not-exist'"
+ - "result.msg == 'resource (network) does not exist: does-not-exist'"
- name: test create load_balancer network with checkmode
- hcloud_load_balancer_network:
+ hetzner.hcloud.load_balancer_network:
network: "{{ hcloud_network_name }}"
load_balancer: "{{hcloud_load_balancer_name}}"
state: present
register: result
- check_mode: yes
+ check_mode: true
- name: verify test create load_balancer network with checkmode
assert:
that:
- - result is changed
+ - result is changed
- name: test create load_balancer network
- hcloud_load_balancer_network:
+ hetzner.hcloud.load_balancer_network:
network: "{{ hcloud_network_name }}"
load_balancer: "{{hcloud_load_balancer_name}}"
state: present
@@ -95,12 +95,12 @@
- 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
+ - 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:
+ hetzner.hcloud.load_balancer_network:
network: "{{ hcloud_network_name }}"
load_balancer: "{{hcloud_load_balancer_name}}"
state: present
@@ -108,10 +108,10 @@
- name: verify create load_balancer network idempotency
assert:
that:
- - load_balancerNetwork is not changed
+ - load_balancerNetwork is not changed
- name: test absent load_balancer network
- hcloud_load_balancer_network:
+ hetzner.hcloud.load_balancer_network:
network: "{{ hcloud_network_name }}"
load_balancer: "{{hcloud_load_balancer_name}}"
state: absent
@@ -119,10 +119,10 @@
- name: verify test absent load_balancer network
assert:
that:
- - result is changed
+ - result is changed
- name: test create load_balancer network with specified ip
- hcloud_load_balancer_network:
+ hetzner.hcloud.load_balancer_network:
network: "{{ hcloud_network_name }}"
load_balancer: "{{hcloud_load_balancer_name}}"
ip: "10.0.0.2"
@@ -131,13 +131,13 @@
- 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"
+ - 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:
+ hetzner.hcloud.load_balancer_network:
network: "{{ hcloud_network_name }}"
load_balancer: "{{hcloud_load_balancer_name}}"
state: absent
@@ -145,20 +145,20 @@
- name: verify cleanup create load_balancer network with specified ip
assert:
that:
- - result is changed
+ - result is changed
- name: cleanup load_balancer
- hcloud_load_balancer:
+ hetzner.hcloud.load_balancer:
name: "{{ hcloud_load_balancer_name }}"
state: absent
register: result
- name: verify cleanup load_balancer
assert:
that:
- - result is success
+ - result is success
- name: cleanup subnetwork
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: "{{ hcloud_network_name }}"
ip_range: "10.0.0.0/16"
type: "cloud"
@@ -168,10 +168,10 @@
- name: verify cleanup subnetwork
assert:
that:
- - result is changed
+ - result is changed
- name: cleanup
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
state: absent
register: result
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/aliases
new file mode 100644
index 000000000..62828d1e9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/defaults/main/main.yml
index 081eb1472..f6a05e8d1 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/defaults/main/main.yml
@@ -1,5 +1,4 @@
# 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}}-i"
+hcloud_load_balancer_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/tasks/test.yml
index b0db6bb63..173709a67 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_service/tasks/test.yml
@@ -2,7 +2,7 @@
# 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:
+ hetzner.hcloud.load_balancer:
name: "{{hcloud_load_balancer_name}}"
load_balancer_type: lb11
state: present
@@ -14,7 +14,7 @@
- load_balancer is success
- name: test fail load balancer does not exist
- hetzner.hcloud.hcloud_load_balancer_service:
+ hetzner.hcloud.load_balancer_service:
load_balancer: does-not-exist
protocol: http
listen_port: 80
@@ -25,23 +25,23 @@
assert:
that:
- result is failed
- - "result.msg == 'Load balancer does not exist: does-not-exist'"
+ - "result.msg == 'resource (load_balancer) does not exist: does-not-exist'"
- name: test create load_balancer service with checkmode
- hcloud_load_balancer_service:
+ hetzner.hcloud.load_balancer_service:
load_balancer: "{{hcloud_load_balancer_name}}"
protocol: "http"
listen_port: 80
state: present
register: result
- check_mode: yes
+ check_mode: true
- name: verify test create load_balancer service with checkmode
assert:
that:
- - result is changed
+ - result is changed
- name: test create load_balancer service
- hcloud_load_balancer_service:
+ hetzner.hcloud.load_balancer_service:
load_balancer: "{{hcloud_load_balancer_name}}"
protocol: "http"
listen_port: 80
@@ -50,14 +50,14 @@
- 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
+ - 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:
+ hetzner.hcloud.load_balancer_service:
load_balancer: "{{hcloud_load_balancer_name}}"
protocol: "http"
listen_port: 80
@@ -66,10 +66,10 @@
- name: verify create load_balancer service idempotency
assert:
that:
- - load_balancer_service is not changed
+ - load_balancer_service is not changed
- name: test update load_balancer service
- hcloud_load_balancer_service:
+ hetzner.hcloud.load_balancer_service:
load_balancer: "{{hcloud_load_balancer_name}}"
protocol: "tcp"
listen_port: 80
@@ -78,14 +78,14 @@
- 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
+ - 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:
+ hetzner.hcloud.load_balancer_service:
load_balancer: "{{hcloud_load_balancer_name}}"
protocol: "http"
listen_port: 80
@@ -94,33 +94,33 @@
- name: verify test absent load_balancer service
assert:
that:
- - result is changed
+ - result is changed
- name: test create load_balancer service with http
- hcloud_load_balancer_service:
+ hetzner.hcloud.load_balancer_service:
load_balancer: "{{hcloud_load_balancer_name}}"
protocol: "http"
listen_port: 80
http:
cookie_name: "Test"
- sticky_sessions: yes
+ sticky_sessions: true
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
+ - 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:
+ hetzner.hcloud.load_balancer:
name: "{{ hcloud_load_balancer_name }}"
state: absent
register: result
- name: verify cleanup load_balancer
assert:
that:
- - result is success
+ - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/aliases
new file mode 100644
index 000000000..62828d1e9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/defaults/main/main.yml
new file mode 100644
index 000000000..2d60910e9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/defaults/main/main.yml
@@ -0,0 +1,7 @@
+# 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_server_name: "{{ hcloud_ns }}"
+hcloud_load_balancer_name: "{{ hcloud_ns }}"
+
+hetzner_server_ip: 142.132.203.104
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/tasks/test.yml
index bd96c1a54..19fd0e9af 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_target/tasks/test.yml
@@ -2,10 +2,10 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{hcloud_server_name}}"
server_type: cx11
- image: ubuntu-20.04
+ image: ubuntu-22.04
state: started
location: "fsn1"
register: server
@@ -15,7 +15,7 @@
- server is success
- name: setup load_balancer
- hcloud_load_balancer:
+ hetzner.hcloud.load_balancer:
name: "{{hcloud_load_balancer_name}}"
load_balancer_type: lb11
state: present
@@ -27,7 +27,7 @@
- load_balancer is success
- name: test fail load balancer does not exist
- hetzner.hcloud.hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: server
load_balancer: does-not-exist
server: "{{ hcloud_server_name }}"
@@ -37,10 +37,10 @@
assert:
that:
- result is failed
- - "result.msg == 'Load balancer does not exist: does-not-exist'"
+ - "result.msg == 'resource (load_balancer) does not exist: does-not-exist'"
- name: test fail server does not exist
- hetzner.hcloud.hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: server
load_balancer: "{{ hcloud_load_balancer_name }}"
server: does-not-exist
@@ -50,23 +50,23 @@
assert:
that:
- result is failed
- - "result.msg == 'Server not found: does-not-exist'"
+ - "result.msg == 'resource (server) does not exist: does-not-exist'"
- name: test create load_balancer target with checkmode
- hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: "server"
load_balancer: "{{hcloud_load_balancer_name}}"
server: "{{hcloud_server_name}}"
state: present
register: result
- check_mode: yes
+ check_mode: true
- name: verify test create load_balancer target with checkmode
assert:
that:
- - result is changed
+ - result is changed
- name: test create load_balancer target
- hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: "server"
load_balancer: "{{hcloud_load_balancer_name}}"
server: "{{hcloud_server_name}}"
@@ -75,13 +75,13 @@
- 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
+ - 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:
+ hetzner.hcloud.load_balancer_target:
type: "server"
load_balancer: "{{hcloud_load_balancer_name}}"
server: "{{hcloud_server_name}}"
@@ -90,10 +90,10 @@
- name: verify create load_balancer target idempotency
assert:
that:
- - load_balancer_target is not changed
+ - load_balancer_target is not changed
- name: test absent load_balancer target
- hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: "server"
load_balancer: "{{hcloud_load_balancer_name}}"
server: "{{hcloud_server_name}}"
@@ -102,10 +102,10 @@
- name: verify test absent load_balancer target
assert:
that:
- - result is changed
+ - result is changed
- name: test create label_selector target
- hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: "label_selector"
load_balancer: "{{hcloud_load_balancer_name}}"
label_selector: "application=backend"
@@ -114,28 +114,28 @@
- name: verify create label_selector target
assert:
that:
- - load_balancer_target is changed
- - load_balancer_target.hcloud_load_balancer_target.type == "label_selector"
- - load_balancer_target.hcloud_load_balancer_target.label_selector == "application=backend"
- - load_balancer_target.hcloud_load_balancer_target.load_balancer == hcloud_load_balancer_name
+ - load_balancer_target is changed
+ - load_balancer_target.hcloud_load_balancer_target.type == "label_selector"
+ - load_balancer_target.hcloud_load_balancer_target.label_selector == "application=backend"
+ - load_balancer_target.hcloud_load_balancer_target.load_balancer == hcloud_load_balancer_name
- name: test create ip target
- hcloud_load_balancer_target:
+ hetzner.hcloud.load_balancer_target:
type: "ip"
- load_balancer: "{{hcloud_load_balancer_name}}"
- ip: "{{hcloud_testing_ip}}"
+ load_balancer: "{{ hcloud_load_balancer_name }}"
+ ip: "{{ hetzner_server_ip }}"
state: present
register: load_balancer_target
- name: verify create ip target
assert:
that:
- - load_balancer_target is changed
- - load_balancer_target.hcloud_load_balancer_target.type == "ip"
- - load_balancer_target.hcloud_load_balancer_target.ip == hcloud_testing_ip
- - load_balancer_target.hcloud_load_balancer_target.load_balancer == hcloud_load_balancer_name
+ - load_balancer_target is changed
+ - load_balancer_target.hcloud_load_balancer_target.type == "ip"
+ - load_balancer_target.hcloud_load_balancer_target.ip == hetzner_server_ip
+ - load_balancer_target.hcloud_load_balancer_target.load_balancer == hcloud_load_balancer_name
- name: cleanup load_balancer
- hcloud_load_balancer:
+ hetzner.hcloud.load_balancer:
name: "{{ hcloud_load_balancer_name }}"
state: absent
register: result
@@ -144,7 +144,7 @@
delay: 2
- name: cleanup
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{hcloud_server_name}}"
state: absent
register: result
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/defaults/main/main.yml
index b7fd86316..473035974 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/defaults/main/main.yml
@@ -1,5 +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
+hcloud_load_balancer_type_name: lb11
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/tasks/test.yml
new file mode 100644
index 000000000..980b8a274
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/load_balancer_type_info/tasks/test.yml
@@ -0,0 +1,56 @@
+# 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: Gather hcloud_load_balancer_type_info
+ hetzner.hcloud.load_balancer_type_info:
+ register: result
+- name: Verify hcloud_load_balancer_type_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_type_info | list | count >= 1
+
+- name: Gather hcloud_load_balancer_type_info in check mode
+ hetzner.hcloud.load_balancer_type_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_load_balancer_type_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_type_info | list | count >= 1
+
+- name: Gather hcloud_load_balancer_type_info with correct id
+ hetzner.hcloud.load_balancer_type_info:
+ id: "{{ hcloud_load_balancer_type_id }}"
+ register: result
+- name: Verify hcloud_load_balancer_type_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_type_info | list | count == 1
+
+- name: Gather hcloud_load_balancer_type_info with wrong id
+ hetzner.hcloud.load_balancer_type_info:
+ id: "{{ hcloud_load_balancer_type_id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_load_balancer_type_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_load_balancer_type_info with correct name
+ hetzner.hcloud.load_balancer_type_info:
+ name: "{{ hcloud_load_balancer_type_name }}"
+ register: result
+- name: Verify hcloud_load_balancer_type_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_type_info | list | count == 1
+
+- name: Gather hcloud_load_balancer_type_info with wrong name
+ hetzner.hcloud.load_balancer_type_info:
+ name: "{{ hcloud_load_balancer_type_name }}-invalid"
+ register: result
+- name: Verify hcloud_load_balancer_type_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_load_balancer_type_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/aliases
new file mode 100644
index 000000000..a6a90a6bf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group3
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/defaults/main/main.yml
index 0d72a75c2..72f0db5bc 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/defaults/main/main.yml
@@ -1,5 +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_location_name: "fsn1"
hcloud_location_id: 1
+hcloud_location_name: fsn1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/tasks/test.yml
new file mode 100644
index 000000000..12ad679b8
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/location_info/tasks/test.yml
@@ -0,0 +1,56 @@
+# 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: Gather hcloud_location_info
+ hetzner.hcloud.location_info:
+ register: result
+- name: Verify hcloud_location_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_location_info | list | count >= 5
+
+- name: Gather hcloud_location_info in check mode
+ hetzner.hcloud.location_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_location_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_location_info | list | count >= 5
+
+- name: Gather hcloud_location_info with correct id
+ hetzner.hcloud.location_info:
+ id: "{{ hcloud_location_id }}"
+ register: result
+- name: Verify hcloud_location_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_location_info | list | count == 1
+
+- name: Gather hcloud_location_info with wrong id
+ hetzner.hcloud.location_info:
+ id: "{{ hcloud_location_id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_location_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_location_info with correct name
+ hetzner.hcloud.location_info:
+ name: "{{ hcloud_location_name }}"
+ register: result
+- name: Verify hcloud_location_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_location_info | list | count == 1
+
+- name: Gather hcloud_location_info with wrong name
+ hetzner.hcloud.location_info:
+ name: "{{ hcloud_location_name }}-invalid"
+ register: result
+- name: Verify hcloud_location_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_location_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/aliases
new file mode 100644
index 000000000..f150235ee
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/aliases
@@ -0,0 +1,3 @@
+cloud/hcloud
+azp/group1
+disabled
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/defaults/main/main.yml
new file mode 100644
index 000000000..a8320602c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/defaults/main/main.yml
@@ -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_network_name: "{{ hcloud_ns }}"
+hcloud_network_name_with_vswitch: "{{ hcloud_ns }}-vswitch"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/tasks/test.yml
index 6c40e4e01..b4f3de284 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network/tasks/test.yml
@@ -1,21 +1,19 @@
# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
-- name: setup
- hcloud_network:
- name: "{{ hcloud_network_name }}"
+- name: setup ensure network is absent
+ hetzner.hcloud.network:
+ name: "{{ item }}"
state: absent
- register: result
-- name: verify setup
- assert:
- that:
- - result is success
+ with_items:
+ - "{{ hcloud_network_name }}"
+ - "{{ hcloud_network_name_with_vswitch }}"
- name: test missing ip_range parameter on create Network
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail missing ip_range parameter on create Network result
assert:
that:
@@ -23,18 +21,18 @@
- 'result.msg == "missing required arguments: ip_range"'
- name: test create Network with check mode
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/16"
register: result
- check_mode: yes
+ check_mode: true
- name: verify create Network with check mode result
assert:
that:
- result is changed
- name: test create Network
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/16"
register: network
@@ -42,11 +40,11 @@
assert:
that:
- network is changed
- - network.hcloud_network.name == "{{hcloud_network_name}}"
+ - network.hcloud_network.name == hcloud_network_name
- network.hcloud_network.ip_range == "10.0.0.0/16"
- name: test create Network idempotence
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/16"
register: network
@@ -55,8 +53,33 @@
that:
- network is not changed
+- name: test create Network with expose_routes_to_vswitch
+ hetzner.hcloud.network:
+ name: "{{hcloud_network_name_with_vswitch}}"
+ ip_range: "10.0.0.0/16"
+ expose_routes_to_vswitch: true
+ register: network
+- name: verify test create Network with vSwitch result
+ assert:
+ that:
+ - network is changed
+ - network.hcloud_network.name == hcloud_network_name_with_vswitch
+ - network.hcloud_network.ip_range == "10.0.0.0/16"
+ - network.hcloud_network.expose_routes_to_vswitch is true
+
+- name: test create Network with expose_routes_to_vswitch idempotence
+ hetzner.hcloud.network:
+ name: "{{hcloud_network_name_with_vswitch}}"
+ ip_range: "10.0.0.0/16"
+ expose_routes_to_vswitch: true
+ register: network
+- name: verify test create network idempotency
+ assert:
+ that:
+ - network is not changed
+
- name: test update Network label
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
labels:
key: value
@@ -68,7 +91,7 @@
- network.hcloud_network.labels.key == "value"
- name: test update Network label idempotency
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
labels:
key: value
@@ -79,7 +102,7 @@
- network is not changed
- name: test update Network ip range
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/8"
register: network
@@ -90,7 +113,7 @@
- network.hcloud_network.ip_range == "10.0.0.0/8"
- name: test update Network ip range idempotency
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/8"
register: network
@@ -99,8 +122,29 @@
that:
- network is not changed
+- name: test update Network expose_routes_to_vswitch
+ hetzner.hcloud.network:
+ name: "{{hcloud_network_name_with_vswitch}}"
+ expose_routes_to_vswitch: false
+ register: network
+- name: verify test update Network expose_routes_to_vswitch
+ assert:
+ that:
+ - network is changed
+ - network.hcloud_network.expose_routes_to_vswitch is false
+
+- name: test update Network expose_routes_to_vswitch idempotency
+ hetzner.hcloud.network:
+ name: "{{hcloud_network_name_with_vswitch}}"
+ expose_routes_to_vswitch: false
+ register: network
+- name: verify test update Network expose_routes_to_vswitch idempotency
+ assert:
+ that:
+ - network is not changed
+
- name: test update Network delete protection
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/8"
delete_protection: true
@@ -112,7 +156,7 @@
- network.hcloud_network.delete_protection is sameas true
- name: test update Network delete protection idempotency
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/8"
delete_protection: true
@@ -124,7 +168,7 @@
- network.hcloud_network.delete_protection is sameas true
- name: test Network without delete protection set to be idempotent
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/8"
register: network
@@ -135,10 +179,10 @@
- network.hcloud_network.delete_protection is sameas true
- name: test delete Network fails if it is protected
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
state: absent
- ignore_errors: yes
+ ignore_errors: true
register: result
- name: verify delete Network
assert:
@@ -147,7 +191,7 @@
- 'result.msg == "network deletion is protected"'
- name: test update Network delete protection
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/8"
delete_protection: false
@@ -159,7 +203,7 @@
- network.hcloud_network.delete_protection is sameas false
- name: test delete Network
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
state: absent
register: result
@@ -168,9 +212,8 @@
that:
- result is success
-
- name: test create Network with delete protection
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
ip_range: "10.0.0.0/8"
delete_protection: true
@@ -182,10 +225,10 @@
- network.hcloud_network.delete_protection is sameas true
- name: test delete Network fails if it is protected
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
state: absent
- ignore_errors: yes
+ ignore_errors: true
register: result
- name: verify delete Network
assert:
@@ -194,7 +237,7 @@
- 'result.msg == "network deletion is protected"'
- name: test update Network delete protection
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
delete_protection: false
register: network
@@ -205,7 +248,7 @@
- network.hcloud_network.delete_protection is sameas false
- name: test delete Network
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
state: absent
register: result
@@ -213,3 +256,13 @@
assert:
that:
- result is success
+
+- name: test delete Network with expose_routes_to_vswitch
+ hetzner.hcloud.network:
+ name: "{{hcloud_network_name_with_vswitch}}"
+ state: absent
+ register: result
+- name: verify delete Network with expose_routes_to_vswitch
+ assert:
+ that:
+ - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/aliases
new file mode 100644
index 000000000..62828d1e9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/defaults/main/main.yml
new file mode 100644
index 000000000..a01c6d60c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/defaults/main/main.yml
@@ -0,0 +1,4 @@
+# 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_network_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/cleanup.yml
new file mode 100644
index 000000000..989d01b80
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_network
+ hetzner.hcloud.network:
+ name: "{{ hcloud_network_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/prepare.yml
new file mode 100644
index 000000000..9a6e61862
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/prepare.yml
@@ -0,0 +1,23 @@
+---
+- name: Create test_network
+ hetzner.hcloud.network:
+ name: "{{ hcloud_network_name }}"
+ ip_range: 10.0.0.0/16
+ labels:
+ key: value
+ register: test_network
+
+- name: Create test_subnetwork
+ hetzner.hcloud.subnetwork:
+ network: "{{ hcloud_network_name }}"
+ type: server
+ network_zone: eu-central
+ ip_range: 10.0.1.0/24
+ register: test_subnetwork
+
+- name: Create test_route
+ hetzner.hcloud.route:
+ network: "{{ hcloud_network_name }}"
+ destination: 10.0.3.0/24
+ gateway: 10.0.2.1
+ register: test_route
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/test.yml
new file mode 100644
index 000000000..cf7367d5f
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/network_info/tasks/test.yml
@@ -0,0 +1,79 @@
+# 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: Gather hcloud_network_info
+ hetzner.hcloud.network_info:
+ register: result
+- name: Verify hcloud_network_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_network_info | list | count >= 1
+
+- name: Gather hcloud_network_info in check mode
+ hetzner.hcloud.network_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_network_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_network_info | list | count >= 1
+
+- name: Gather hcloud_network_info with correct id
+ hetzner.hcloud.network_info:
+ id: "{{ test_network.hcloud_network.id }}"
+ register: result
+- name: Verify hcloud_network_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_network_info | list | count == 1
+ - result.hcloud_network_info[0].subnetworks | list | count >= 1
+ - result.hcloud_network_info[0].routes | list | count >= 1
+
+- name: Gather hcloud_network_info with wrong id
+ hetzner.hcloud.network_info:
+ id: "{{ test_network.hcloud_network.id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_network_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_network_info with correct name
+ hetzner.hcloud.network_info:
+ name: "{{ hcloud_network_name }}"
+ register: result
+- name: Verify hcloud_network_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_network_info | list | count == 1
+
+- name: Gather hcloud_network_info with wrong name
+ hetzner.hcloud.network_info:
+ name: "{{ hcloud_network_name }}-invalid"
+ register: result
+- name: Verify hcloud_network_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_network_info | list | count == 0
+
+- name: Gather hcloud_network_info with correct label selector
+ hetzner.hcloud.network_info:
+ label_selector: "key=value"
+ register: result
+- name: Verify hcloud_network_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ - >
+ result.hcloud_network_info
+ | selectattr('name', 'equalto', hcloud_network_name)
+ | list | count == 1
+
+- name: Gather hcloud_network_info with wrong label selector
+ hetzner.hcloud.network_info:
+ label_selector: "key!=value"
+ register: result
+- name: Verify hcloud_network_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_network_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/defaults/main/main.yml
new file mode 100644
index 000000000..a4439afbd
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/defaults/main/main.yml
@@ -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_placement_group_name: "{{ hcloud_ns }}"
+hcloud_server_name: "{{ hcloud_ns }}"
+hcloud_ssh_key_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/meta/main.yml
new file mode 100644
index 000000000..3a96ecb2d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - setup_ssh_keypair
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/cleanup.yml
new file mode 100644
index 000000000..8066c4115
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_ssh_key
+ hetzner.hcloud.ssh_key:
+ name: "{{ hcloud_ssh_key_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/prepare.yml
new file mode 100644
index 000000000..4bdb95996
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/prepare.yml
@@ -0,0 +1,6 @@
+---
+- name: Create test_ssh_key
+ hetzner.hcloud.ssh_key:
+ name: "{{ hcloud_ssh_key_name }}"
+ public_key: "{{ test_ssh_keypair.public_key }}"
+ register: test_ssh_key
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/test.yml
index d79aa0c35..3694c846f 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_placement_group/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/placement_group/tasks/test.yml
@@ -2,19 +2,19 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup placement group to be absent
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
name: "{{ hcloud_placement_group_name }}"
state: absent
- name: setup server to be absent
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
- name: test missing required parameters on create placement group
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing required parameters on create placement group
assert:
that:
@@ -22,18 +22,18 @@
- 'result.msg == "one of the following is required: id, name"'
- name: test create placement group with check mode
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
name: "{{ hcloud_placement_group_name }}"
type: spread
register: result
- check_mode: yes
+ check_mode: true
- name: test create placement group with check mode
assert:
that:
- result is changed
- name: test create placement group
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
name: "{{ hcloud_placement_group_name }}"
type: spread
labels:
@@ -44,12 +44,12 @@
assert:
that:
- placement_group is changed
- - placement_group.hcloud_placement_group.name == "{{ hcloud_placement_group_name }}"
+ - placement_group.hcloud_placement_group.name == hcloud_placement_group_name
- placement_group.hcloud_placement_group.type == "spread"
- placement_group.hcloud_placement_group.servers | list | count == 0
- name: test create placement group idempotence
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
name: "{{ hcloud_placement_group_name }}"
type: spread
labels:
@@ -62,23 +62,23 @@
- result is not changed
- name: test create server with placement group
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
placement_group: "{{ hcloud_placement_group_name }}"
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: server
- name: verify create server with placement group
assert:
that:
- server is changed
- - server.hcloud_server.placement_group == "{{ hcloud_placement_group_name }}"
+ - server.hcloud_server.placement_group == hcloud_placement_group_name
- name: test remove server from placement group
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
placement_group: null
state: present
@@ -90,7 +90,7 @@
- result.hcloud_server.placement_group == None
- name: test add server to placement group
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
placement_group: "{{ hcloud_placement_group_name }}"
force: True
@@ -100,11 +100,11 @@
assert:
that:
- result is changed
- - result.hcloud_server.placement_group == "{{ hcloud_placement_group_name }}"
+ - result.hcloud_server.placement_group == hcloud_placement_group_name
- result.hcloud_server.status == "running"
- name: test add server to placement group idempotence
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
placement_group: "{{ hcloud_placement_group_name }}"
force: True
@@ -114,22 +114,22 @@
assert:
that:
- result is not changed
- - result.hcloud_server.placement_group == "{{ hcloud_placement_group_name }}"
+ - result.hcloud_server.placement_group == hcloud_placement_group_name
- result.hcloud_server.status == "running"
- name: test update placement group with check mode
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
id: "{{ placement_group.hcloud_placement_group.id }}"
name: "changed-{{ hcloud_placement_group_name }}"
register: result
- check_mode: yes
+ check_mode: true
- name: verify update placement group with check mode
assert:
that:
- result is changed
- name: test update placement group
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
id: "{{ placement_group.hcloud_placement_group.id }}"
name: "changed-{{ hcloud_placement_group_name }}"
labels:
@@ -142,7 +142,7 @@
- result.hcloud_placement_group.name == "changed-{{ hcloud_placement_group_name }}"
- name: test update placement group idempotence
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
id: "{{ placement_group.hcloud_placement_group.id }}"
name: "changed-{{ hcloud_placement_group_name }}"
labels:
@@ -154,12 +154,12 @@
- result is not changed
- name: absent server
- hcloud_server:
+ hetzner.hcloud.server:
id: "{{ server.hcloud_server.id }}"
state: absent
- name: absent placement group
- hcloud_placement_group:
+ hetzner.hcloud.placement_group:
id: "{{ placement_group.hcloud_placement_group.id }}"
state: absent
register: result
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/aliases
new file mode 100644
index 000000000..a6a90a6bf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group3
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/defaults/main/main.yml
index ebf456312..7944d5b25 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/defaults/main/main.yml
@@ -1,5 +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}}-lb-target"
+hcloud_primary_ip_name: "{{ hcloud_ns }}"
+hcloud_server_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/tasks/test.yml
index d4efc606b..4c0fd2e5f 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_primary_ip/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip/tasks/test.yml
@@ -1,20 +1,25 @@
# 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 ensure primary ip is absent
+ hetzner.hcloud.primary_ip:
+ name: "{{ hcloud_primary_ip_name }}"
+ state: absent
+
- name: test create Primary IP with check mode
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
register: primaryIP
- check_mode: yes
+ check_mode: true
- name: verify test create Primary IP with check mode
assert:
that:
- primaryIP is changed
- name: test create Primary IP
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
@@ -27,7 +32,7 @@
- primaryIP.hcloud_primary_ip.datacenter == "fsn1-dc14"
- name: test create Primary IP idempotency
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
@@ -38,7 +43,7 @@
- primaryIP is not changed
- name: test update Primary IP
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
@@ -51,7 +56,7 @@
- primaryIP is changed
- name: test update Primary IP idempotency
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
@@ -64,7 +69,7 @@
- primaryIP is not changed
- name: test update Primary IP with same labels
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
@@ -77,7 +82,7 @@
- primaryIP is not changed
- name: test update Primary IP with other labels
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
@@ -91,7 +96,7 @@
- primaryIP is changed
- name: test update Primary IP with other labels in different order
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: "fsn1-dc14"
@@ -105,7 +110,7 @@
- primaryIP is not changed
- name: test update Primary IP delete protection
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
delete_protection: true
@@ -117,7 +122,7 @@
- primaryIP.hcloud_primary_ip.delete_protection is sameas true
- name: test update Primary IP delete protection idempotency
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
delete_protection: true
@@ -129,7 +134,7 @@
- primaryIP.hcloud_primary_ip.delete_protection is sameas true
- name: test Primary IP without delete protection set to be idempotent
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
register: primaryIP
@@ -140,11 +145,11 @@
- primaryIP.hcloud_primary_ip.delete_protection is sameas true
- name: test delete Primary IP fails if it is protected
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify test delete primary ip
assert:
that:
@@ -152,7 +157,7 @@
- 'result.msg == "Primary IP deletion is protected"'
- name: test update Primary IP delete protection
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
delete_protection: false
@@ -164,7 +169,7 @@
- primaryIP.hcloud_primary_ip.delete_protection is sameas false
- name: test delete primary ip
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
@@ -174,7 +179,7 @@
- result is changed
- name: test create ipv6 primary ip
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv6
datacenter: "fsn1-dc14"
@@ -186,7 +191,7 @@
- result is changed
- name: test delete ipv6 primary ip
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
@@ -196,7 +201,7 @@
- result is changed
- name: test create Primary IP with delete protection
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
datacenter: fsn1-dc14
@@ -209,11 +214,11 @@
- primaryIP.hcloud_primary_ip.delete_protection is sameas true
- name: test delete Primary IP fails if it is protected
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify test delete primary ip
assert:
that:
@@ -221,7 +226,7 @@
- 'result.msg == "Primary IP deletion is protected"'
- name: test update Primary IP delete protection
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
type: ipv4
delete_protection: false
@@ -233,7 +238,7 @@
- primaryIP.hcloud_primary_ip.delete_protection is sameas false
- name: test delete primary ip
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}"
state: "absent"
register: result
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/aliases
new file mode 100644
index 000000000..a6a90a6bf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group3
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/defaults/main/main.yml
new file mode 100644
index 000000000..9527ca2cd
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/defaults/main/main.yml
@@ -0,0 +1,4 @@
+# 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_primary_ip_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/cleanup.yml
new file mode 100644
index 000000000..8fc48059e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_primary_ip
+ hetzner.hcloud.primary_ip:
+ name: "{{ hcloud_primary_ip_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/prepare.yml
new file mode 100644
index 000000000..4c96ee87d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/prepare.yml
@@ -0,0 +1,9 @@
+---
+- name: Create test_primary_ip
+ hetzner.hcloud.primary_ip:
+ name: "{{ hcloud_primary_ip_name }}"
+ datacenter: fsn1-dc14
+ type: ipv4
+ labels:
+ key: value
+ register: test_primary_ip
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/test.yml
new file mode 100644
index 000000000..902e34153
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/primary_ip_info/tasks/test.yml
@@ -0,0 +1,77 @@
+# 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: Gather hcloud_primary_ip_info
+ hetzner.hcloud.primary_ip_info:
+ register: result
+- name: Verify hcloud_primary_ip_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_primary_ip_info | list | count >= 1
+
+- name: Gather hcloud_primary_ip_info in check mode
+ hetzner.hcloud.primary_ip_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_primary_ip_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_primary_ip_info | list | count >= 1
+
+- name: Gather hcloud_primary_ip_info with correct id
+ hetzner.hcloud.primary_ip_info:
+ id: "{{ test_primary_ip.hcloud_primary_ip.id }}"
+ register: result
+- name: Verify hcloud_primary_ip_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_primary_ip_info | list | count == 1
+
+- name: Gather hcloud_primary_ip_info with wrong id
+ hetzner.hcloud.primary_ip_info:
+ id: "{{ test_primary_ip.hcloud_primary_ip.id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_primary_ip_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_primary_ip_info with correct name
+ hetzner.hcloud.primary_ip_info:
+ name: "{{ hcloud_primary_ip_name }}"
+ register: result
+- name: Verify hcloud_primary_ip_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_primary_ip_info | list | count == 1
+
+- name: Gather hcloud_primary_ip_info with wrong name
+ hetzner.hcloud.primary_ip_info:
+ name: "{{ hcloud_primary_ip_name }}-invalid"
+ register: result
+- name: Verify hcloud_primary_ip_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_primary_ip_info | list | count == 0
+
+- name: Gather hcloud_primary_ip_info with correct label selector
+ hetzner.hcloud.primary_ip_info:
+ label_selector: "key=value"
+ register: result
+- name: Verify hcloud_primary_ip_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ - >
+ result.hcloud_primary_ip_info
+ | selectattr('name', 'equalto', hcloud_primary_ip_name)
+ | list | count == 1
+
+- name: Gather hcloud_primary_ip_info with wrong label selector
+ hetzner.hcloud.primary_ip_info:
+ label_selector: "key!=value"
+ register: result
+- name: Verify hcloud_primary_ip_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_primary_ip_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/aliases
new file mode 100644
index 000000000..62828d1e9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/defaults/main/main.yml
new file mode 100644
index 000000000..6249a9bd6
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/defaults/main/main.yml
@@ -0,0 +1,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)
+---
+hcloud_server_name: "{{ hcloud_ns }}"
+hcloud_floating_ip_name: "{{ hcloud_ns }}"
+hcloud_primary_ip_name: "{{ hcloud_ns }}"
+hcloud_load_balancer_name: "{{ hcloud_ns }}"
+hcloud_ssh_key_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/cleanup.yml
new file mode 100644
index 000000000..0df360a33
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/cleanup.yml
@@ -0,0 +1,20 @@
+---
+- name: Cleanup test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ state: absent
+
+- name: Cleanup test_primary_ip
+ hetzner.hcloud.primary_ip:
+ name: "{{ hcloud_primary_ip_name }}"
+ state: absent
+
+- name: Cleanup test_floating_ip
+ hetzner.hcloud.floating_ip:
+ name: "{{ hcloud_floating_ip_name }}"
+ state: absent
+
+- name: Cleanup test_load_balancer
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/prepare.yml
new file mode 100644
index 000000000..ea36b6dbc
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/prepare.yml
@@ -0,0 +1,32 @@
+---
+- name: Create test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ server_type: cx11
+ image: ubuntu-22.04
+ state: present
+ register: test_server
+
+- name: Create test_primary_ip
+ hetzner.hcloud.primary_ip:
+ name: "{{ hcloud_primary_ip_name }}"
+ type: ipv4
+ datacenter: fsn1-dc14
+ state: present
+ register: test_primary_ip
+
+- name: Create test_floating_ip
+ hetzner.hcloud.floating_ip:
+ name: "{{ hcloud_floating_ip_name }}"
+ type: ipv4
+ home_location: fsn1
+ state: present
+ register: test_floating_ip
+
+- name: Create test_load_balancer
+ hetzner.hcloud.load_balancer:
+ name: "{{ hcloud_load_balancer_name }}"
+ load_balancer_type: lb11
+ network_zone: eu-central
+ state: present
+ register: test_load_balancer
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/test.yml
new file mode 100644
index 000000000..342716897
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/rdns/tasks/test.yml
@@ -0,0 +1,148 @@
+# 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 missing required parameters
+ hetzner.hcloud.rdns:
+ state: present
+ ignore_errors: true
+ register: result
+- name: Verify missing required parameters
+ ansible.builtin.assert:
+ that:
+ - result is failed
+ - 'result.msg == "missing required arguments: ip_address"'
+
+- name: Test create with checkmode
+ hetzner.hcloud.rdns:
+ server: "{{ hcloud_server_name }}"
+ ip_address: "{{ test_server.hcloud_server.ipv6 | ansible.utils.ipaddr('next_usable') }}"
+ dns_ptr: example.com
+ state: present
+ check_mode: true
+ register: result
+- name: Verify create with checkmode
+ ansible.builtin.assert:
+ that:
+ - result is changed
+
+- name: Test create
+ hetzner.hcloud.rdns:
+ server: "{{ hcloud_server_name }}"
+ ip_address: "{{ test_server.hcloud_server.ipv6 | ansible.utils.ipaddr('next_usable') }}"
+ dns_ptr: example.com
+ state: present
+ register: result
+- name: Verify create
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_rdns.server == hcloud_server_name
+ - result.hcloud_rdns.ip_address == test_server.hcloud_server.ipv6 | ansible.utils.ipaddr('next_usable')
+ - result.hcloud_rdns.dns_ptr == "example.com"
+
+- name: Test create idempotency
+ hetzner.hcloud.rdns:
+ server: "{{ hcloud_server_name }}"
+ ip_address: "{{ test_server.hcloud_server.ipv6 | ansible.utils.ipaddr('next_usable') }}"
+ dns_ptr: example.com
+ state: present
+ register: result
+- name: Verify create idempotency
+ ansible.builtin.assert:
+ that:
+ - result is not changed
+
+- name: Test create with not existing server
+ hetzner.hcloud.rdns:
+ server: not-existing
+ ip_address: "127.0.0.1"
+ dns_ptr: example.com
+ state: present
+ ignore_errors: true
+ register: result
+- name: Verify create with not existing server
+ ansible.builtin.assert:
+ that:
+ - result is failed
+ - 'result.msg == "resource (server) does not exist: not-existing"'
+
+- name: Test update
+ hetzner.hcloud.rdns:
+ server: "{{ hcloud_server_name }}"
+ ip_address: "{{ test_server.hcloud_server.ipv4_address }}"
+ dns_ptr: example.com
+ state: present
+ register: result
+- name: Verify update
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_rdns.ip_address == test_server.hcloud_server.ipv4_address
+
+- name: Test update reset
+ hetzner.hcloud.rdns:
+ server: "{{ hcloud_server_name }}"
+ ip_address: "{{ test_server.hcloud_server.ipv4_address }}"
+ state: present
+ register: result
+- name: Verify update reset
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_rdns.dns_ptr != "example.com"
+
+- name: Test delete
+ hetzner.hcloud.rdns:
+ server: "{{ hcloud_server_name }}"
+ ip_address: "{{ test_server.hcloud_server.ipv6 | ansible.utils.ipaddr('next_usable') }}"
+ state: absent
+ register: result
+- name: Verify delete
+ ansible.builtin.assert:
+ that:
+ - result is changed
+
+- name: Test create with primary ip
+ hetzner.hcloud.rdns:
+ primary_ip: "{{ hcloud_primary_ip_name }}"
+ ip_address: "{{ test_primary_ip.hcloud_primary_ip.ip }}"
+ dns_ptr: example.com
+ state: present
+ register: result
+- name: Verify create with primary ip
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_rdns.primary_ip == hcloud_primary_ip_name
+ - result.hcloud_rdns.ip_address == test_primary_ip.hcloud_primary_ip.ip
+ - result.hcloud_rdns.dns_ptr == "example.com"
+
+- name: Test create with floating ip
+ hetzner.hcloud.rdns:
+ floating_ip: "{{ hcloud_floating_ip_name }}"
+ ip_address: "{{ test_floating_ip.hcloud_floating_ip.ip }}"
+ dns_ptr: example.com
+ state: present
+ register: result
+- name: Verify create with floating ip
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_rdns.floating_ip == hcloud_floating_ip_name
+ - result.hcloud_rdns.ip_address == test_floating_ip.hcloud_floating_ip.ip
+ - result.hcloud_rdns.dns_ptr == "example.com"
+
+- name: Test create with load balancer
+ hetzner.hcloud.rdns:
+ load_balancer: "{{ hcloud_load_balancer_name }}"
+ ip_address: "{{ test_load_balancer.hcloud_load_balancer.ipv4_address }}"
+ dns_ptr: example.com
+ state: present
+ register: result
+- name: Verify create with load balancer
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_rdns.load_balancer == hcloud_load_balancer_name
+ - result.hcloud_rdns.ip_address == test_load_balancer.hcloud_load_balancer.ipv4_address
+ - result.hcloud_rdns.dns_ptr == "example.com"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/route/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/aliases
new file mode 100644
index 000000000..62828d1e9
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group1
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/route/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/route/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/defaults/main/main.yml
new file mode 100644
index 000000000..a01c6d60c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/defaults/main/main.yml
@@ -0,0 +1,4 @@
+# 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_network_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/route/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/tasks/test.yml
index 7d816bf5c..571f29a86 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/route/tasks/test.yml
@@ -2,7 +2,7 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{ hcloud_network_name }}"
ip_range: "10.0.0.0/8"
state: present
@@ -10,13 +10,13 @@
- name: verify setup
assert:
that:
- - network is success
+ - network is success
- name: test missing required parameters on create route
- hcloud_route:
+ hetzner.hcloud.route:
state: present
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing required parameters on create route
assert:
that:
@@ -24,20 +24,20 @@
- 'result.msg == "missing required arguments: destination, gateway, network"'
- name: test create route with checkmode
- hcloud_route:
+ hetzner.hcloud.route:
network: "{{ hcloud_network_name }}"
destination: "10.100.1.0/24"
gateway: "10.0.1.1"
state: present
register: result
- check_mode: yes
+ check_mode: true
- name: verify test create route with checkmode
assert:
that:
- - result is changed
+ - result is changed
- name: test create route
- hcloud_route:
+ hetzner.hcloud.route:
network: "{{ hcloud_network_name }}"
destination: "10.100.1.0/24"
gateway: "10.0.1.1"
@@ -46,13 +46,13 @@
- name: verify create route
assert:
that:
- - route is changed
- - route.hcloud_route.network == "{{ hcloud_network_name }}"
- - route.hcloud_route.destination == "10.100.1.0/24"
- - route.hcloud_route.gateway == "10.0.1.1"
+ - route is changed
+ - route.hcloud_route.network == hcloud_network_name
+ - route.hcloud_route.destination == "10.100.1.0/24"
+ - route.hcloud_route.gateway == "10.0.1.1"
- name: test create route idempotency
- hcloud_route:
+ hetzner.hcloud.route:
network: "{{ hcloud_network_name }}"
destination: "10.100.1.0/24"
gateway: "10.0.1.1"
@@ -61,23 +61,23 @@
- name: verify create route idempotency
assert:
that:
- - result is not changed
+ - result is not changed
- name: test fail create route with wrong gateway
- hcloud_route:
+ hetzner.hcloud.route:
network: "{{ hcloud_network_name }}"
destination: "10.100.1.0/24"
gateway: "10.0.1.2"
state: present
register: route
- ignore_errors: yes
+ ignore_errors: true
- name: verfiy fail create route with wrong gateway
assert:
that:
- - route is failed
+ - route is failed
- name: test absent route
- hcloud_route:
+ hetzner.hcloud.route:
network: "{{ hcloud_network_name }}"
destination: "10.100.1.0/24"
gateway: "10.0.1.1"
@@ -86,10 +86,10 @@
- name: verify test absent route
assert:
that:
- - result is changed
+ - result is changed
- name: cleanup
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
state: absent
register: result
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/aliases
new file mode 100644
index 000000000..a6a90a6bf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group3
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/defaults/main/main.yml
new file mode 100644
index 000000000..d9b84598a
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/defaults/main/main.yml
@@ -0,0 +1,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)
+---
+hcloud_ssh_key_name: "{{ hcloud_ns }}"
+hcloud_server_name: "{{ hcloud_ns }}"
+hcloud_firewall_name: "{{ hcloud_ns }}"
+hcloud_primary_ip_name: "{{ hcloud_ns }}"
+hcloud_network_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/meta/main.yml
new file mode 100644
index 000000000..3a96ecb2d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - setup_ssh_keypair
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/cleanup.yml
new file mode 100644
index 000000000..8066c4115
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_ssh_key
+ hetzner.hcloud.ssh_key:
+ name: "{{ hcloud_ssh_key_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/prepare.yml
new file mode 100644
index 000000000..4bdb95996
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/prepare.yml
@@ -0,0 +1,6 @@
+---
+- name: Create test_ssh_key
+ hetzner.hcloud.ssh_key:
+ name: "{{ hcloud_ssh_key_name }}"
+ public_key: "{{ test_ssh_keypair.public_key }}"
+ register: test_ssh_key
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test.yml
new file mode 100644
index 000000000..e00bcce50
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test.yml
@@ -0,0 +1,8 @@
+# Copyright: (c) 2022, Hetzner Cloud GmbH <info@hetzner-cloud.de>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+---
+#- ansible.builtin.include_tasks: test_validation.yml
+- ansible.builtin.include_tasks: test_basic.yml
+#- ansible.builtin.include_tasks: test_firewalls.yml
+- ansible.builtin.include_tasks: test_primary_ips.yml
+- ansible.builtin.include_tasks: test_private_network_only.yml
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/basic.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_basic.yml
index ac609fc6c..1e94d67af 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/basic.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_basic.yml
@@ -1,21 +1,21 @@
- name: test create server with check mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cx11
- image: ubuntu-20.04
+ image: ubuntu-22.04
state: present
register: result
- check_mode: yes
+ check_mode: true
- name: test create server server
assert:
that:
- result is changed
- name: test create server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name}}"
server_type: cx11
- image: ubuntu-20.04
+ image: ubuntu-22.04
enable_ipv6: False
state: started
register: main_server
@@ -23,13 +23,13 @@
assert:
that:
- main_server is changed
- - main_server.hcloud_server.name == "{{ hcloud_server_name }}"
+ - main_server.hcloud_server.name == hcloud_server_name
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
- name: test create server idempotence
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: started
register: result
@@ -39,11 +39,11 @@
- result is not changed
- name: test stop server with check mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: stopped
register: result
- check_mode: yes
+ check_mode: true
- name: verify stop server with check mode
assert:
that:
@@ -51,7 +51,7 @@
- result.hcloud_server.status == "running"
- name: test stop server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: stopped
register: result
@@ -62,7 +62,7 @@
- result.hcloud_server.status == "off"
- name: test start server with check mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: started
register: result
@@ -73,7 +73,7 @@
- result is changed
- name: test start server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: started
register: result
@@ -84,7 +84,7 @@
- result.hcloud_server.status == "running"
- name: test start server idempotence
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: started
register: result
@@ -95,7 +95,7 @@
- result.hcloud_server.status == "running"
- name: test stop server by its id
- hcloud_server:
+ hetzner.hcloud.server:
id: "{{ main_server.hcloud_server.id }}"
state: stopped
register: result
@@ -106,7 +106,7 @@
- result.hcloud_server.status == "off"
- name: test resize server running without force
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: present
@@ -119,7 +119,7 @@
- result.hcloud_server.server_type == "cx11"
- name: test resize server with check mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: stopped
@@ -131,7 +131,7 @@
- result is changed
- name: test resize server without disk
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: stopped
@@ -143,7 +143,7 @@
- result.hcloud_server.server_type == "cx21"
- name: test resize server idempotence
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
state: stopped
@@ -154,7 +154,7 @@
- result is not changed
- name: test resize server to smaller plan
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: "cx11"
state: stopped
@@ -166,7 +166,7 @@
- result.hcloud_server.server_type == "cx11"
- name: test resize server with disk
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: "cx21"
upgrade_disk: true
@@ -179,7 +179,7 @@
- result.hcloud_server.server_type == "cx21"
- name: test enable backups with check mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
backups: true
state: stopped
@@ -191,7 +191,7 @@
- result is changed
- name: test enable backups
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
backups: true
state: stopped
@@ -203,7 +203,7 @@
- result.hcloud_server.backup_window != ""
- name: test enable backups idempotence
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
backups: true
state: stopped
@@ -215,7 +215,7 @@
- result.hcloud_server.backup_window != ""
- name: test backups are not accidentally disabled
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
# Make sure that backups are not disabled because a partial server object without "backups" was supplied somewhere
# to update some unrelated properties.
@@ -230,9 +230,9 @@
- result.hcloud_server.backup_window != ""
- name: test rebuild server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
- image: ubuntu-20.04
+ image: ubuntu-22.04
state: rebuild
register: result_after_test
- name: verify rebuild server
@@ -242,9 +242,9 @@
- result.hcloud_server.id == result_after_test.hcloud_server.id
- name: test rebuild server with check mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
- image: ubuntu-20.04
+ image: ubuntu-22.04
state: rebuild
register: result_after_test
check_mode: true
@@ -254,7 +254,7 @@
- result_after_test is changed
- name: test update server protection booth protection arguments are required
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
delete_protection: true
state: present
@@ -267,7 +267,7 @@
- 'result_after_test.msg == "parameters are required together: delete_protection, rebuild_protection"'
- name: test update server protection fails if they are not the same
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
delete_protection: true
rebuild_protection: false
@@ -280,7 +280,7 @@
- result_after_test is failed
- name: test update server protection
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
delete_protection: true
rebuild_protection: true
@@ -295,7 +295,7 @@
- result_after_test.hcloud_server.rebuild_protection is sameas true
- name: test server without protection set to be idempotent
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{hcloud_server_name}}"
register: result_after_test
- name: verify test server without protection set to be idempotent
@@ -306,10 +306,10 @@
- result_after_test.hcloud_server.rebuild_protection is sameas true
- name: test delete server fails if it is protected
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{hcloud_server_name}}"
state: absent
- ignore_errors: yes
+ ignore_errors: true
register: result
- name: verify delete server fails if it is protected
assert:
@@ -318,11 +318,11 @@
- 'result.msg == "server deletion is protected"'
- name: test rebuild server fails if it is protected
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{hcloud_server_name}}"
- image: ubuntu-20.04
+ image: ubuntu-22.04
state: rebuild
- ignore_errors: yes
+ ignore_errors: true
register: result
- name: verify rebuild server fails if it is protected
assert:
@@ -331,7 +331,7 @@
- 'result.msg == "server rebuild is protected"'
- name: test remove server protection
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
delete_protection: false
rebuild_protection: false
@@ -346,40 +346,39 @@
- result_after_test.hcloud_server.rebuild_protection is sameas false
- name: absent server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify absent server
assert:
that:
- - result is success
+ - result is success
- name: test create server with ssh key
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name}}"
server_type: cx11
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: started
register: main_server
- name: verify create server with ssh key
assert:
that:
- main_server is changed
- - main_server.hcloud_server.name == "{{ hcloud_server_name }}"
+ - main_server.hcloud_server.name == hcloud_server_name
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
-
- name: test activate rescue mode with check_mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
rescue_mode: "linux64"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: main_server
check_mode: true
@@ -389,11 +388,11 @@
- main_server is changed
- name: test activate rescue mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
rescue_mode: "linux64"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: main_server
- name: verify activate rescue mode
@@ -403,10 +402,10 @@
- main_server.hcloud_server.rescue_enabled is sameas true
- name: test disable rescue mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: main_server
- name: verify activate rescue mode
@@ -416,7 +415,7 @@
- main_server.hcloud_server.rescue_enabled is sameas false
- name: test activate rescue mode without ssh keys
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
rescue_mode: "linux64"
state: present
@@ -428,22 +427,22 @@
- main_server.hcloud_server.rescue_enabled is sameas true
- name: absent server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify absent server
assert:
that:
- - result is success
+ - result is success
- name: test create server with rescue_mode
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name}}"
server_type: cx11
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
rescue_mode: "linux64"
state: started
register: main_server
@@ -451,29 +450,28 @@
assert:
that:
- main_server is changed
- - main_server.hcloud_server.name == "{{ hcloud_server_name }}"
+ - main_server.hcloud_server.name == hcloud_server_name
- main_server.hcloud_server.server_type == "cx11"
- main_server.hcloud_server.status == "running"
- main_server.root_password != ""
- main_server.hcloud_server.rescue_enabled is sameas true
-
- name: absent server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify absent server
assert:
that:
- - result is success
+ - result is success
- name: test create server with labels
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name}}"
server_type: cx11
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
labels:
key: value
mylabel: "val123"
@@ -487,12 +485,12 @@
- main_server.hcloud_server.labels.mylabel == "val123"
- name: test update server with labels
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name}}"
server_type: cx11
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
labels:
key: other
mylabel: "val123"
@@ -506,12 +504,12 @@
- main_server.hcloud_server.labels.mylabel == "val123"
- name: test update server with labels in other order
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name}}"
server_type: cx11
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
labels:
mylabel: "val123"
key: other
@@ -523,23 +521,23 @@
- main_server is not changed
- name: cleanup with labels
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- - result is success
+ - result is success
- name: test create server with enabled backups
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
backups: true
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: result
- name: verify enable backups
@@ -549,24 +547,24 @@
- result.hcloud_server.backup_window != ""
- name: cleanup test create server with enabled backups
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- - result is success
+ - result is success
- name: test create server with protection
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
delete_protection: true
rebuild_protection: true
server_type: cpx11
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: result_after_test
ignore_errors: true
@@ -578,10 +576,10 @@
- result_after_test.hcloud_server.rebuild_protection is sameas true
- name: test delete server fails if it is protected
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{hcloud_server_name}}"
state: absent
- ignore_errors: yes
+ ignore_errors: true
register: result
- name: verify delete server fails if it is protected
assert:
@@ -590,7 +588,7 @@
- 'result.msg == "server deletion is protected"'
- name: remove protection from server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
delete_protection: false
rebuild_protection: false
@@ -605,11 +603,11 @@
- result_after_test.hcloud_server.rebuild_protection is sameas false
- name: cleanup
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- - result is success
+ - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/firewalls.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_firewalls.yml
index 18fa89e25..896a6c5cf 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/firewalls.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_firewalls.yml
@@ -2,12 +2,12 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: test add not existing firewall should fail
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
firewalls:
- not-existing
state: present
- ignore_errors: yes
+ ignore_errors: true
register: result
- name: verify add not existing firewall should fail
assert:
@@ -15,7 +15,7 @@
- result is failed
- 'result.msg == "firewall not-existing was not found"'
- name: setup create firewalls
- hcloud_firewall:
+ hetzner.hcloud.firewall:
name: "{{ item }}"
rules:
- direction: in
@@ -28,14 +28,14 @@
- "{{ hcloud_firewall_name }}2"
- name: test create server with firewalls
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}"
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: result
- name: verify test create server with firewalls
@@ -44,14 +44,14 @@
- result is changed
- name: test create server with firewalls idempotence
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}"
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: result
- name: verify test create server with firewalls idempotence
@@ -60,14 +60,14 @@
- result is not changed
- name: test update server with firewalls
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}2"
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: result
- name: verify test update server with firewalls
@@ -76,14 +76,14 @@
- result is changed
- name: test update server with firewalls idempotence
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
firewalls:
- "{{ hcloud_firewall_name }}2"
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: present
register: result
- name: verify test update server with firewalls idempotence
@@ -92,12 +92,12 @@
- result is not changed
- name: cleanup server with firewalls
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
- name: cleanup test create firewall
- hcloud_firewall:
+ hetzner.hcloud.firewall:
name: "{{ item }}"
state: absent
with_items:
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/primary_ips.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_primary_ips.yml
index 000c294de..034da9f74 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/primary_ips.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_primary_ips.yml
@@ -2,36 +2,36 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup create primary ipv4
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}v4"
type: ipv4
datacenter: "fsn1-dc14"
register: primaryIPv4
- name: setup create second primary ipv4
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}v42"
type: ipv4
datacenter: "fsn1-dc14"
register: secondPrimaryIPv4
- name: setup create primary ipv6
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_primary_ip_name }}v6"
type: ipv6
datacenter: "fsn1-dc14"
register: primaryIPv6
- name: test create server with primary ips
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ipv4: "{{primaryIPv4.hcloud_primary_ip.id}}"
ipv6: "{{primaryIPv6.hcloud_primary_ip.id}}"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: stopped
register: result
- name: verify test create server with primary ips
@@ -40,16 +40,16 @@
- result is changed
- name: test update server with primary ips
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ipv4: "{{secondPrimaryIPv4.hcloud_primary_ip.id}}"
ipv6: ""
- enable_ipv6: no
+ enable_ipv6: false
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: stopped
register: result
- name: verify test create server with primary ips
@@ -58,23 +58,23 @@
- result is changed
- name: cleanup server with primary ips
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
- name: cleanup test create primary ips
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_server_name }}v4"
state: absent
- name: cleanup test create primary ips
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_server_name }}v42"
state: absent
until: result is not failed
retries: 5
delay: 2
- name: cleanup test create primary ips
- hcloud_primary_ip:
+ hetzner.hcloud.primary_ip:
name: "{{ hcloud_server_name }}v6"
state: absent
until: result is not failed
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/private_network_only.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_private_network_only.yml
index a56832873..a4219a00f 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/private_network_only.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_private_network_only.yml
@@ -2,28 +2,28 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup network 1 to be absent
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{ hcloud_network_name }}-1"
state: absent
- name: setup network 2 to be absent
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{ hcloud_network_name }}-2"
state: absent
- name: setup server to be absent
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
- name: setup create network
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{ hcloud_network_name }}-1"
ip_range: 192.168.0.0/23
register: primaryNetwork
- name: setup create network subnet 1
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: "{{ hcloud_network_name }}-1"
ip_range: 192.168.0.0/24
network_zone: eu-central
@@ -31,7 +31,7 @@
state: present
- name: setup create network subnet 2
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: "{{ hcloud_network_name }}-1"
ip_range: 192.168.1.0/24
network_zone: eu-central
@@ -39,13 +39,13 @@
state: present
- name: setup create secondary network
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{ hcloud_network_name }}-2"
ip_range: 192.168.2.0/23
register: secondaryNetwork
- name: setup create secondary network subnet 1
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: "{{ hcloud_network_name }}-2"
ip_range: 192.168.2.0/24
network_zone: eu-central
@@ -53,7 +53,7 @@
state: present
- name: setup create secondary network subnet 2
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: "{{ hcloud_network_name }}-2"
ip_range: 192.168.3.0/24
network_zone: eu-central
@@ -61,17 +61,17 @@
state: present
- name: test create server with primary network and no internet
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
- image: "ubuntu-20.04"
- enable_ipv4: no
- enable_ipv6: no
+ image: "ubuntu-22.04"
+ enable_ipv4: false
+ enable_ipv6: false
private_networks:
- "{{ primaryNetwork.hcloud_network.name }}"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: stopped
register: result
- name: verify test create server with primary network
@@ -80,18 +80,18 @@
- result is changed
- name: test update server by adding secondary network
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
- image: "ubuntu-20.04"
- enable_ipv4: no
- enable_ipv6: no
+ image: "ubuntu-22.04"
+ enable_ipv4: false
+ enable_ipv6: false
private_networks:
- "{{ primaryNetwork.hcloud_network.name }}"
- "{{ secondaryNetwork.hcloud_network.id }}"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: stopped
register: result
- name: verify test update server by adding secondary network
@@ -100,18 +100,18 @@
- result is changed
- name: test update server idem
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cpx11
datacenter: "fsn1-dc14"
- image: "ubuntu-20.04"
- enable_ipv4: no
- enable_ipv6: no
+ image: "ubuntu-22.04"
+ enable_ipv4: false
+ enable_ipv6: false
private_networks:
- "{{ primaryNetwork.hcloud_network.name }}"
- "{{ secondaryNetwork.hcloud_network.id }}"
ssh_keys:
- - ci@ansible.hetzner.cloud
+ - "{{ hcloud_ssh_key_name }}"
state: stopped
register: result
- name: verify test update server idem
@@ -120,11 +120,11 @@
- result is not changed
- name: cleanup server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
- name: cleanup networks
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{ item }}"
state: absent
with_items:
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/validation.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_validation.yml
index f507e87cf..d4e0ef8b4 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/validation.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server/tasks/test_validation.yml
@@ -2,20 +2,20 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify setup
assert:
that:
- - result is success
+ - result is success
- name: test missing required parameters on create server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing required parameters on create server
assert:
that:
@@ -23,13 +23,13 @@
- 'result.msg == "missing required arguments: server_type, image"'
- name: test create server with not existing server type
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: not-existing-server-type
- image: ubuntu-20.04
+ image: ubuntu-22.04
state: present
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test create server with not existing server type
assert:
that:
@@ -37,13 +37,13 @@
- 'result.msg == "server_type not-existing-server-type was not found"'
- name: test create server with not existing image
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cx11
image: my-not-existing-image-20.04
state: present
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test create server with not existing image
assert:
that:
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/defaults/main/main.yml
new file mode 100644
index 000000000..a85dafcfc
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/defaults/main/main.yml
@@ -0,0 +1,4 @@
+# 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_server_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/cleanup.yml
new file mode 100644
index 000000000..0c95d2c65
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/cleanup.yml
@@ -0,0 +1,10 @@
+---
+- name: Cleanup test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ state: absent
+
+- name: Cleanup test_server2
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}2"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/prepare.yml
new file mode 100644
index 000000000..9e8aa2c9f
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/prepare.yml
@@ -0,0 +1,22 @@
+---
+- name: Create test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ server_type: cx11
+ image: ubuntu-22.04
+ state: started
+ labels:
+ key: value
+ register: test_server
+
+- name: Create test_server2 (stopped + without ip)
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}2"
+ server_type: cx11
+ image: ubuntu-22.04
+ state: stopped
+ labels:
+ key: value
+ enable_ipv4: false
+ enable_ipv6: false
+ register: test_server2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/test.yml
new file mode 100644
index 000000000..534c50a70
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_info/tasks/test.yml
@@ -0,0 +1,89 @@
+# 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: Gather hcloud_server_info
+ hetzner.hcloud.server_info:
+ register: result
+- name: Verify hcloud_server_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_info | list | count >= 2
+
+- name: Gather hcloud_server_info in check mode
+ hetzner.hcloud.server_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_server_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_info | list | count >= 2
+
+- name: Gather hcloud_server_info with correct id
+ hetzner.hcloud.server_info:
+ id: "{{ test_server.hcloud_server.id }}"
+ register: result
+- name: Verify hcloud_server_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_info | list | count == 1
+ - result.hcloud_server_info[0].name == hcloud_server_name
+
+- name: Gather hcloud_server_info with wrong id
+ hetzner.hcloud.server_info:
+ id: "{{ test_server.hcloud_server.id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_server_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_server_info with correct name
+ hetzner.hcloud.server_info:
+ name: "{{ hcloud_server_name }}"
+ register: result
+- name: Verify hcloud_server_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_info | list | count == 1
+ - result.hcloud_server_info[0].name == hcloud_server_name
+
+- name: Gather hcloud_server_info with wrong name
+ hetzner.hcloud.server_info:
+ name: "{{ hcloud_server_name }}-invalid"
+ register: result
+- name: Verify hcloud_server_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_info | list | count == 0
+
+- name: Gather hcloud_server_info with correct label selector
+ hetzner.hcloud.server_info:
+ label_selector: "key=value"
+ register: result
+- name: Verify hcloud_server_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ - >
+ result.hcloud_server_info
+ | selectattr('name', 'equalto', hcloud_server_name)
+ | list | count == 1
+
+- name: Gather hcloud_server_info with wrong label selector
+ hetzner.hcloud.server_info:
+ label_selector: "key!=value"
+ register: result
+- name: Verify hcloud_server_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_info | list | count == 0
+
+- name: Gather hcloud_server_info (without ip)
+ hetzner.hcloud.server_info:
+ id: "{{ test_server2.hcloud_server.id }}"
+ register: result
+- name: Verify hcloud_server_info (without ip)
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_info | list | count == 1
+ - result.hcloud_server_info[0].name == hcloud_server_name + '2'
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/aliases
new file mode 100644
index 000000000..6e9b68657
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/aliases
@@ -0,0 +1,3 @@
+cloud/hcloud
+azp/group2
+disabled
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/defaults/main/main.yml
index e7eff02a7..c9a119410 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_firewall/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/defaults/main/main.yml
@@ -1,5 +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_firewall_name: "{{hcloud_prefix}}-integration"
+hcloud_network_name: "{{ hcloud_ns }}"
+hcloud_server_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/tasks/test.yml
index 754018a66..a77f2e30a 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_network/tasks/test.yml
@@ -2,7 +2,7 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup network
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{ hcloud_network_name }}"
ip_range: "10.0.0.0/8"
state: present
@@ -10,10 +10,10 @@
- name: verify setup network
assert:
that:
- - network is success
+ - network is success
- name: setup subnetwork
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: "{{ hcloud_network_name }}"
ip_range: "10.0.0.0/16"
type: "server"
@@ -23,13 +23,13 @@
- name: verify subnetwork
assert:
that:
- - subnetwork is success
+ - subnetwork is success
- name: setup server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{hcloud_server_name}}"
server_type: cx11
- image: ubuntu-18.04
+ image: ubuntu-22.04
state: started
location: "fsn1"
register: server
@@ -39,10 +39,10 @@
- server is success
- name: test missing required parameters on create server network
- hcloud_server_network:
+ hetzner.hcloud.server_network:
state: present
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing required parameters on create server network
assert:
that:
@@ -50,19 +50,19 @@
- 'result.msg == "missing required arguments: network, server"'
- name: test create server network with checkmode
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
state: present
register: result
- check_mode: yes
+ check_mode: true
- name: verify test create server network with checkmode
assert:
that:
- - result is changed
+ - result is changed
- name: test create server network
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
state: present
@@ -70,12 +70,12 @@
- name: verify create server network
assert:
that:
- - serverNetwork is changed
- - serverNetwork.hcloud_server_network.network == hcloud_network_name
- - serverNetwork.hcloud_server_network.server == hcloud_server_name
+ - serverNetwork is changed
+ - serverNetwork.hcloud_server_network.network == hcloud_network_name
+ - serverNetwork.hcloud_server_network.server == hcloud_server_name
- name: test create server network idempotency
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
state: present
@@ -83,10 +83,10 @@
- name: verify create server network idempotency
assert:
that:
- - serverNetwork is not changed
+ - serverNetwork is not changed
- name: test absent server network
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
state: absent
@@ -94,10 +94,10 @@
- name: verify test absent server network
assert:
that:
- - result is changed
+ - result is changed
- name: test create server network with specified ip
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
ip: "10.0.0.2"
@@ -106,13 +106,13 @@
- name: verify create server network with specified ip
assert:
that:
- - serverNetwork is changed
- - serverNetwork.hcloud_server_network.network == hcloud_network_name
- - serverNetwork.hcloud_server_network.server == hcloud_server_name
- - serverNetwork.hcloud_server_network.ip == "10.0.0.2"
+ - serverNetwork is changed
+ - serverNetwork.hcloud_server_network.network == hcloud_network_name
+ - serverNetwork.hcloud_server_network.server == hcloud_server_name
+ - serverNetwork.hcloud_server_network.ip == "10.0.0.2"
- name: cleanup create server network with specified ip
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
state: absent
@@ -120,10 +120,10 @@
- name: verify cleanup create server network with specified ip
assert:
that:
- - result is changed
+ - result is changed
- name: test create server network with alias ips
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
ip: "10.0.0.2"
@@ -135,15 +135,15 @@
- name: verify create server network with alias ips
assert:
that:
- - serverNetwork is changed
- - serverNetwork.hcloud_server_network.network == hcloud_network_name
- - serverNetwork.hcloud_server_network.server == hcloud_server_name
- - serverNetwork.hcloud_server_network.ip == "10.0.0.2"
- - 'serverNetwork.hcloud_server_network.alias_ips[0] == "10.0.2.3"'
- - 'serverNetwork.hcloud_server_network.alias_ips[1] == "10.0.1.2"'
+ - serverNetwork is changed
+ - serverNetwork.hcloud_server_network.network == hcloud_network_name
+ - serverNetwork.hcloud_server_network.server == hcloud_server_name
+ - serverNetwork.hcloud_server_network.ip == "10.0.0.2"
+ - 'serverNetwork.hcloud_server_network.alias_ips[0] == "10.0.2.3"'
+ - 'serverNetwork.hcloud_server_network.alias_ips[1] == "10.0.1.2"'
- name: test update server network with alias ips
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
ip: "10.0.0.2"
@@ -155,15 +155,15 @@
- name: verify create server network with alias ips
assert:
that:
- - serverNetwork is changed
- - serverNetwork.hcloud_server_network.network == hcloud_network_name
- - serverNetwork.hcloud_server_network.server == hcloud_server_name
- - serverNetwork.hcloud_server_network.ip == "10.0.0.2"
- - 'serverNetwork.hcloud_server_network.alias_ips[0] == "10.0.2.3"'
- - 'serverNetwork.hcloud_server_network.alias_ips[1] == "10.0.3.1"'
+ - serverNetwork is changed
+ - serverNetwork.hcloud_server_network.network == hcloud_network_name
+ - serverNetwork.hcloud_server_network.server == hcloud_server_name
+ - serverNetwork.hcloud_server_network.ip == "10.0.0.2"
+ - 'serverNetwork.hcloud_server_network.alias_ips[0] == "10.0.2.3"'
+ - 'serverNetwork.hcloud_server_network.alias_ips[1] == "10.0.3.1"'
- name: test update server network with alias ips idempotency
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
ip: "10.0.0.2"
@@ -175,10 +175,10 @@
- name: verify create server network with alias ips idempotency
assert:
that:
- - serverNetwork is not changed
+ - serverNetwork is not changed
- name: cleanup create server network with alias ips
- hcloud_server_network:
+ hetzner.hcloud.server_network:
network: "{{ hcloud_network_name }}"
server: "{{hcloud_server_name}}"
state: absent
@@ -186,20 +186,20 @@
- name: verify cleanup create server network with alias ips
assert:
that:
- - result is changed
+ - result is changed
- name: cleanup server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup server
assert:
that:
- - result is success
+ - result is success
- name: cleanup subnetwork
- hcloud_subnetwork:
+ hetzner.hcloud.subnetwork:
network: "{{ hcloud_network_name }}"
ip_range: "10.0.0.0/16"
type: "server"
@@ -209,10 +209,10 @@
- name: verify cleanup subnetwork
assert:
that:
- - result is changed
+ - result is changed
- name: cleanup
- hcloud_network:
+ hetzner.hcloud.network:
name: "{{hcloud_network_name}}"
state: absent
register: result
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/defaults/main/main.yml
new file mode 100644
index 000000000..c488c4dfc
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/defaults/main/main.yml
@@ -0,0 +1,7 @@
+# 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_server_type_name: cx11
+hcloud_server_type_id: 1
+
+hcloud_server_type_id_deprecated: 2 # cx11-ceph
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/tasks/test.yml
new file mode 100644
index 000000000..9c51e09c1
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/server_type_info/tasks/test.yml
@@ -0,0 +1,69 @@
+# 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: Gather hcloud_server_type_info
+ hetzner.hcloud.server_type_info:
+ register: result
+- name: Verify hcloud_server_type_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_type_info | list | count >= 3
+
+- name: Gather hcloud_server_type_info in check mode
+ hetzner.hcloud.server_type_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_server_type_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_type_info | list | count >= 3
+
+- name: Gather hcloud_server_type_info with correct id
+ hetzner.hcloud.server_type_info:
+ id: "{{ hcloud_server_type_id }}"
+ register: result
+- name: Verify hcloud_server_type_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_type_info | list | count == 1
+ - result.hcloud_server_type_info[0].deprecation is none # fails if cx11 is ever deprecated
+
+- name: Gather hcloud_server_type_info with wrong id
+ hetzner.hcloud.server_type_info:
+ id: "{{ hcloud_server_type_id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_server_type_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_server_type_info with correct name
+ hetzner.hcloud.server_type_info:
+ name: "{{ hcloud_server_type_name }}"
+ register: result
+- name: Verify hcloud_server_type_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_type_info | list | count == 1
+
+- name: Gather hcloud_server_type_info with wrong name
+ hetzner.hcloud.server_type_info:
+ name: "{{ hcloud_server_type_name }}-invalid"
+ register: result
+- name: Verify hcloud_server_type_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_type_info | list | count == 0
+
+- name: Gather hcloud_server_type_info with deprecated field
+ hetzner.hcloud.server_type_info:
+ id: "{{ hcloud_server_type_id_deprecated }}"
+ register: result
+- name: Verify hcloud_server_type_info with deprecated field
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_server_type_info | list | count == 1
+ - result.hcloud_server_type_info[0].deprecation is not none
+ - result.hcloud_server_type_info[0].deprecation.announced == '2021-11-09T09:00:00+00:00'
+ - result.hcloud_server_type_info[0].deprecation.unavailable_after == '2021-12-01T00:00:00+00:00'
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_hcloud_cli/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_hcloud_cli/tasks/main.yml
new file mode 100644
index 000000000..7b5356b41
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_hcloud_cli/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+- name: Create temporary file for hcloud_cli_path
+ ansible.builtin.tempfile:
+ state: directory
+ register: _tmp_hcloud_cli
+
+- name: Download hcloud cli from Github releases
+ ansible.builtin.unarchive:
+ src: https://github.com/hetznercloud/cli/releases/download/v1.37.0/hcloud-linux-amd64.tar.gz
+ dest: "{{ _tmp_hcloud_cli.path }}"
+ remote_src: true
+ extra_opts: [hcloud]
+
+- name: Set hcloud_cli_path
+ ansible.builtin.set_fact:
+ hcloud_cli_path: "{{ _tmp_hcloud_cli.path }}/hcloud"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml
index 27defe44c..76d6e1791 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml
@@ -1,27 +1,35 @@
-# 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 temporary file for test_certificate
+ ansible.builtin.tempfile:
+ suffix: "{{ hcloud_certificate_name }}"
+ register: _tmp_certificate_file
-- 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: Create certificate privatekey file
+ community.crypto.openssl_privatekey:
+ path: "{{ _tmp_certificate_file.path }}.key"
+ return_content: true
+ register: _certificate_privatekey_file
-- 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
+- name: Create certificate signing request file
+ community.crypto.openssl_csr:
+ privatekey_path: "{{ _tmp_certificate_file.path }}.key"
+ path: "{{ _tmp_certificate_file.path }}.csr"
+ country_name: DE
+ locality_name: Bavaria
+ state_or_province_name: Munich
+ organization_name: Dis
+ common_name: www.example.com
+
+- name: Create certificate file
+ community.crypto.x509_certificate:
+ privatekey_path: "{{ _tmp_certificate_file.path }}.key"
+ csr_path: "{{ _tmp_certificate_file.path }}.csr"
+ path: "{{ _tmp_certificate_file.path }}.crt"
+ provider: selfsigned
+ return_content: true
+ register: _certificate_file
+
+- name: Save certificate files content
+ ansible.builtin.set_fact:
+ test_certificate_privatekey_content: "{{ _certificate_privatekey_file.privatekey }}"
+ test_certificate_content: "{{ _certificate_file.certificate }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_ssh_keypair/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_ssh_keypair/tasks/main.yml
new file mode 100644
index 000000000..c51b42863
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_ssh_keypair/tasks/main.yml
@@ -0,0 +1,19 @@
+---
+# https://github.com/ansible-collections/community.crypto/pull/504
+- name: Create temporary directory for test_ssh_keypair
+ ansible.builtin.file:
+ state: directory
+ path: ~/tmp
+ mode: "0755"
+
+- name: Create temporary file for test_ssh_keypair
+ ansible.builtin.tempfile:
+ path: ~/tmp
+ suffix: "{{ hcloud_ssh_key_name }}"
+ register: _tmp_ssh_key_file
+
+- name: Create test_ssh_keypair
+ community.crypto.openssh_keypair:
+ path: "{{ _tmp_ssh_key_file.path }}"
+ force: true
+ register: test_ssh_keypair
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_sshkey/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_sshkey/tasks/main.yml
deleted file mode 100644
index 18c571b67..000000000
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_sshkey/tasks/main.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-# (c) 2014, James Laska <jlaska@ansible.com>
-
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-
-- name: create a temp file
- tempfile:
- state: file
- register: sshkey_file
- tags:
- - prepare
-
-- name: generate sshkey
- shell: echo 'y' | ssh-keygen -P '' -f {{ sshkey_file.path }}
- tags:
- - prepare
-
-- name: create another temp file
- tempfile:
- state: file
- register: another_sshkey_file
- tags:
- - prepare
-
-- name: generate another_sshkey
- shell: echo 'y' | ssh-keygen -P '' -f {{ another_sshkey_file.path }}
- tags:
- - prepare
-
-- name: record fingerprint
- shell: openssl rsa -in {{ sshkey_file.path }} -pubout -outform DER 2>/dev/null | openssl md5 -c
- register: fingerprint
- tags:
- - prepare
-
-- name: set facts for future roles
- set_fact:
- sshkey: '{{ sshkey_file.path }}'
- key_material: "{{ lookup('file', sshkey_file.path ~ '.pub') }}"
- another_key_material: "{{ lookup('file', another_sshkey_file.path ~ '.pub') }}"
- fingerprint: '{{ fingerprint.stdout.split()[1] }}'
- tags:
- - prepare
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/defaults/main/main.yml
index 6205b19b4..87c4d8e31 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/defaults/main/main.yml
@@ -1,5 +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"
+hcloud_server_name: "{{ hcloud_ns }}"
+hcloud_ssh_key_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/meta/main.yml
new file mode 100644
index 000000000..3a96ecb2d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - setup_ssh_keypair
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/cleanup.yml
new file mode 100644
index 000000000..fea3ff06d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/cleanup.yml
@@ -0,0 +1,10 @@
+---
+- name: Cleanup test_ssh_key
+ hetzner.hcloud.ssh_key:
+ name: "{{ hcloud_ssh_key_name }}"
+ state: absent
+
+- name: Cleanup test_server
+ hetzner.hcloud.server:
+ name: "{{ hcloud_server_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/test.yml
index 9208e143d..41b9c351d 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key/tasks/test.yml
@@ -2,10 +2,10 @@
# 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 ssh_key
- hcloud_ssh_key:
+ hetzner.hcloud.ssh_key:
name: "{{ hcloud_ssh_key_name }}"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing required parameters on create ssh_key
assert:
that:
@@ -13,36 +13,36 @@
- 'result.msg == "missing required arguments: public_key"'
- name: test create ssh key with check mode
- hcloud_ssh_key:
+ hetzner.hcloud.ssh_key:
name: "{{ hcloud_ssh_key_name }}"
- public_key: "{{ key_material }}"
+ public_key: "{{ test_ssh_keypair.public_key }}"
register: result
- check_mode: yes
+ check_mode: true
- name: test create ssh key with check mode
assert:
that:
- result is changed
- name: test create ssh key
- hcloud_ssh_key:
+ hetzner.hcloud.ssh_key:
name: "{{ hcloud_ssh_key_name }}"
- public_key: "{{ key_material }}"
+ public_key: "{{ test_ssh_keypair.public_key }}"
labels:
key: value
my-label: label
- register: sshKey
+ register: ssh_key
- name: verify create ssh key
assert:
that:
- - sshKey is changed
- - sshKey.hcloud_ssh_key.name == "{{ hcloud_ssh_key_name }}"
- - sshKey.hcloud_ssh_key.public_key == "{{ key_material }}"
- - sshKey.hcloud_ssh_key.labels.key == "value"
+ - ssh_key is changed
+ - ssh_key.hcloud_ssh_key.name == hcloud_ssh_key_name
+ - ssh_key.hcloud_ssh_key.public_key == test_ssh_keypair.public_key
+ - ssh_key.hcloud_ssh_key.labels.key == "value"
- name: test create ssh key idempotence
- hcloud_ssh_key:
+ hetzner.hcloud.ssh_key:
name: "{{ hcloud_ssh_key_name }}"
- public_key: "{{ key_material }}"
+ public_key: "{{ test_ssh_keypair.public_key }}"
register: result
- name: verify create ssh key idempotence
assert:
@@ -50,19 +50,19 @@
- result is not changed
- name: test update ssh key with check mode
- hcloud_ssh_key:
- id: "{{ sshKey.hcloud_ssh_key.id }}"
+ hetzner.hcloud.ssh_key:
+ id: "{{ ssh_key.hcloud_ssh_key.id }}"
name: "changed-{{ hcloud_ssh_key_name }}"
register: result
- check_mode: yes
+ check_mode: true
- name: test create ssh key with check mode
assert:
that:
- result is changed
- name: test update ssh key
- hcloud_ssh_key:
- id: "{{ sshKey.hcloud_ssh_key.id }}"
+ hetzner.hcloud.ssh_key:
+ id: "{{ ssh_key.hcloud_ssh_key.id }}"
name: "changed-{{ hcloud_ssh_key_name }}"
labels:
key: value
@@ -74,8 +74,8 @@
- result.hcloud_ssh_key.name == "changed-{{ hcloud_ssh_key_name }}"
- name: test update ssh key with same labels
- hcloud_ssh_key:
- id: "{{ sshKey.hcloud_ssh_key.id }}"
+ hetzner.hcloud.ssh_key:
+ id: "{{ ssh_key.hcloud_ssh_key.id }}"
name: "changed-{{ hcloud_ssh_key_name }}"
labels:
key: value
@@ -86,8 +86,8 @@
- result is not changed
- name: test update ssh key with other labels
- hcloud_ssh_key:
- id: "{{ sshKey.hcloud_ssh_key.id }}"
+ hetzner.hcloud.ssh_key:
+ id: "{{ ssh_key.hcloud_ssh_key.id }}"
name: "changed-{{ hcloud_ssh_key_name }}"
labels:
key: value
@@ -99,21 +99,21 @@
- result is changed
- name: test rename ssh key
- hcloud_ssh_key:
- id: "{{ sshKey.hcloud_ssh_key.id }}"
+ hetzner.hcloud.ssh_key:
+ id: "{{ ssh_key.hcloud_ssh_key.id }}"
name: "{{ hcloud_ssh_key_name }}"
register: result
- name: test rename ssh key
assert:
that:
- result is changed
- - result.hcloud_ssh_key.name == "{{ hcloud_ssh_key_name }}"
+ - result.hcloud_ssh_key.name == hcloud_ssh_key_name
- name: test create server with ssh key
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
server_type: cx11
- image: "ubuntu-20.04"
+ image: "ubuntu-22.04"
ssh_keys:
- "{{ hcloud_ssh_key_name }}"
state: started
@@ -123,34 +123,24 @@
that:
- main_server is changed
-- name: absent ssh key
- hcloud_ssh_key:
- id: "{{ sshKey.hcloud_ssh_key.id }}"
- state: absent
- register: result
-- name: verify absent sshkey
- assert:
- that:
- - result is success
-
- name: test fail cleanly on double created ssh key
- hcloud_ssh_key:
- name: "{{ hcloud_ssh_key_name }}othername"
- public_key: "{{ hcloud_doubled_ssh_key_public_key }}"
+ hetzner.hcloud.ssh_key:
+ name: "{{ hcloud_ssh_key_name }}-other-name"
+ public_key: "{{ test_ssh_keypair.public_key }}"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify failed correctly
assert:
that:
- result is failed
- 'result.msg == "SSH key with the same fingerprint already exists"'
-- name: cleanup
- hcloud_server:
- name: "{{ hcloud_server_name }}"
+- name: test delete ssh key
+ hetzner.hcloud.ssh_key:
+ id: "{{ ssh_key.hcloud_ssh_key.id }}"
state: absent
register: result
-- name: verify cleanup
+- name: verify absent ssh_key
assert:
that:
- result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/defaults/main/main.yml
new file mode 100644
index 000000000..68a7f5a35
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/defaults/main/main.yml
@@ -0,0 +1,4 @@
+# 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_ssh_key_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/meta/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/meta/main.yml
new file mode 100644
index 000000000..3a96ecb2d
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - setup_ssh_keypair
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/cleanup.yml
new file mode 100644
index 000000000..8066c4115
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_ssh_key
+ hetzner.hcloud.ssh_key:
+ name: "{{ hcloud_ssh_key_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/prepare.yml
new file mode 100644
index 000000000..519bc8526
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/prepare.yml
@@ -0,0 +1,8 @@
+---
+- name: Create test_ssh_key
+ hetzner.hcloud.ssh_key:
+ name: "{{ hcloud_ssh_key_name }}"
+ public_key: "{{ test_ssh_keypair.public_key }}"
+ labels:
+ key: value
+ register: test_ssh_key
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/test.yml
new file mode 100644
index 000000000..d8ea7cb37
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/ssh_key_info/tasks/test.yml
@@ -0,0 +1,77 @@
+# 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: Gather hcloud_ssh_key_info
+ hetzner.hcloud.ssh_key_info:
+ register: result
+- name: Verify hcloud_ssh_key_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_ssh_key_info | list | count >= 1
+
+- name: Gather hcloud_ssh_key_info in check mode
+ hetzner.hcloud.ssh_key_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_ssh_key_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_ssh_key_info | list | count >= 1
+
+- name: Gather hcloud_ssh_key_info with correct id
+ hetzner.hcloud.ssh_key_info:
+ id: "{{ test_ssh_key.hcloud_ssh_key.id }}"
+ register: result
+- name: Verify hcloud_ssh_key_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_ssh_key_info | list | count == 1
+
+- name: Gather hcloud_ssh_key_info with wrong id
+ hetzner.hcloud.ssh_key_info:
+ id: "{{ test_ssh_key.hcloud_ssh_key.id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_ssh_key_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_ssh_key_info with correct name
+ hetzner.hcloud.ssh_key_info:
+ name: "{{ hcloud_ssh_key_name }}"
+ register: result
+- name: Verify hcloud_ssh_key_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_ssh_key_info | list | count == 1
+
+- name: Gather hcloud_ssh_key_info with wrong name
+ hetzner.hcloud.ssh_key_info:
+ name: "{{ hcloud_ssh_key_name }}-invalid"
+ register: result
+- name: Verify hcloud_ssh_key_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_ssh_key_info | list | count == 0
+
+- name: Gather hcloud_ssh_key_info with correct label selector
+ hetzner.hcloud.ssh_key_info:
+ label_selector: "key=value"
+ register: result
+- name: Verify hcloud_ssh_key_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ - >
+ result.hcloud_ssh_key_info
+ | selectattr('name', 'equalto', hcloud_ssh_key_name)
+ | list | count == 1
+
+- name: Gather hcloud_ssh_key_info with wrong label selector
+ hetzner.hcloud.ssh_key_info:
+ label_selector: "key!=value"
+ register: result
+- name: Verify hcloud_ssh_key_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_ssh_key_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/aliases
new file mode 100644
index 000000000..a6a90a6bf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group3
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/defaults/main/main.yml
new file mode 100644
index 000000000..afaa77652
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/defaults/main/main.yml
@@ -0,0 +1,23 @@
+# 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_network_name: "{{ hcloud_ns }}"
+# Pool of external Hetzner vSwitch ID, this prevents using the same vSwitch id twice in
+# different jobs.
+hetzner_vswitch_ids:
+ - 43065
+ - 44166
+ - 44167
+ - 44168
+ - 44170
+ - 44171
+ - 44172
+ - 44173
+ - 44174
+ - 44175
+ - 44176
+ - 44177
+ - 44178
+ - 44179
+ - 44180
+ - 44181
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/cleanup.yml
new file mode 100644
index 000000000..989d01b80
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_network
+ hetzner.hcloud.network:
+ name: "{{ hcloud_network_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/prepare.yml
new file mode 100644
index 000000000..69a709ddf
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/prepare.yml
@@ -0,0 +1,11 @@
+---
+- name: Create test_network
+ hetzner.hcloud.network:
+ name: "{{ hcloud_network_name }}"
+ ip_range: "10.0.0.0/16"
+ state: present
+ register: test_network
+
+- name: Select hetzner vswitch id from pool
+ ansible.builtin.set_fact:
+ test_vswitch_id: "{{ hetzner_vswitch_ids | random }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/test.yml
new file mode 100644
index 000000000..acde98f7b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/subnetwork/tasks/test.yml
@@ -0,0 +1,103 @@
+# 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 missing required parameters
+ hetzner.hcloud.subnetwork:
+ network: "{{ hcloud_network_name }}"
+ state: present
+ ignore_errors: true
+ register: result
+- name: Verify missing required parameters
+ ansible.builtin.assert:
+ that:
+ - result is failed
+ - 'result.msg == "missing required arguments: ip_range, network_zone, type"'
+
+- name: Test create with checkmode
+ hetzner.hcloud.subnetwork:
+ network: "{{ hcloud_network_name }}"
+ network_zone: eu-central
+ type: cloud
+ ip_range: 10.0.0.0/24
+ state: present
+ check_mode: true
+ register: result
+- name: Verify create with checkmode
+ ansible.builtin.assert:
+ that:
+ - result is changed
+
+- name: Test create
+ hetzner.hcloud.subnetwork:
+ network: "{{ hcloud_network_name }}"
+ network_zone: eu-central
+ type: cloud
+ ip_range: 10.0.0.0/24
+ state: present
+ register: result
+- name: Verify create
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_subnetwork.network == hcloud_network_name
+ - result.hcloud_subnetwork.network_zone == "eu-central"
+ - result.hcloud_subnetwork.type == "cloud"
+ - result.hcloud_subnetwork.ip_range == "10.0.0.0/24"
+
+- name: Test create idempotency
+ hetzner.hcloud.subnetwork:
+ network: "{{ hcloud_network_name }}"
+ network_zone: eu-central
+ type: cloud
+ ip_range: 10.0.0.0/24
+ state: present
+ register: result
+- name: Verify create idempotency
+ ansible.builtin.assert:
+ that:
+ - result is not changed
+
+- name: Test delete
+ hetzner.hcloud.subnetwork:
+ network: "{{ hcloud_network_name }}"
+ network_zone: eu-central
+ type: cloud
+ ip_range: 10.0.0.0/24
+ state: absent
+ register: result
+- name: Verify delete
+ ansible.builtin.assert:
+ that:
+ - result is changed
+
+- name: Test create with vswitch
+ hetzner.hcloud.subnetwork:
+ network: "{{ hcloud_network_name }}"
+ network_zone: eu-central
+ type: vswitch
+ ip_range: 10.0.1.0/24
+ vswitch_id: "{{ test_vswitch_id }}"
+ state: present
+ register: result
+- name: Verify create with vswitch
+ ansible.builtin.assert:
+ that:
+ - result is changed
+ - result.hcloud_subnetwork.network == hcloud_network_name
+ - result.hcloud_subnetwork.network_zone == "eu-central"
+ - result.hcloud_subnetwork.type == "vswitch"
+ - result.hcloud_subnetwork.ip_range == "10.0.1.0/24"
+ - result.hcloud_subnetwork.vswitch_id | string == test_vswitch_id
+
+- name: Test delete with vswitch
+ hetzner.hcloud.subnetwork:
+ network: "{{ hcloud_network_name }}"
+ network_zone: eu-central
+ type: vswitch
+ ip_range: 10.0.1.0/24
+ state: absent
+ register: subnet
+- name: Verify delete with vswitch
+ ansible.builtin.assert:
+ that:
+ - result is changed
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/defaults/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/defaults/main/main.yml
index f4c6a9fc9..65949c814 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/defaults/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/defaults/main/main.yml
@@ -1,5 +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_floating_ip_name: "{{hcloud_prefix}}-i"
+hcloud_volume_name: "{{ hcloud_ns }}"
+hcloud_server_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/tasks/test.yml
index f763a52f2..fd47d5343 100644
--- a/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/tasks/main.yml
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume/tasks/test.yml
@@ -2,10 +2,10 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
---
- name: setup server
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{hcloud_server_name}}"
server_type: cx11
- image: ubuntu-18.04
+ image: ubuntu-22.04
state: started
location: "fsn1"
register: vol_server
@@ -15,11 +15,11 @@
- vol_server is changed
- name: test missing size parameter on create Volume
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
server: "{{hcloud_server_name}}"
register: result
- ignore_errors: yes
+ ignore_errors: true
- name: verify fail test missing size parameter on create Volume
assert:
that:
@@ -27,19 +27,19 @@
- 'result.msg == "missing required arguments: size"'
- name: test create Volume with check mode
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
size: 10
location: "fsn1"
register: result
- check_mode: yes
+ check_mode: true
- name: verify create Volume with check mode result
assert:
that:
- result is changed
- name: test create Volume
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
size: 10
location: "fsn1"
@@ -48,14 +48,14 @@
assert:
that:
- volume is changed
- - volume.hcloud_volume.name == "{{hcloud_volume_name}}"
+ - volume.hcloud_volume.name == hcloud_volume_name
- volume.hcloud_volume.location == "fsn1"
- volume.hcloud_volume.size == 10
- - volume.hcloud_volume.server != "{{hcloud_server_name}}"
+ - volume.hcloud_volume.server != hcloud_server_name
- volume.hcloud_volume.linux_device is defined
- name: test create Volume idempotence
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
size: 10
location: "fsn1"
@@ -66,19 +66,19 @@
- volume is not changed
- name: test attach Volume with checkmode
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
server: "{{hcloud_server_name}}"
- check_mode: yes
+ check_mode: true
register: volume
- name: verify test attach Volume with checkmode
assert:
that:
- volume is changed
- - volume.hcloud_volume.server != "{{hcloud_server_name}}"
+ - volume.hcloud_volume.server != hcloud_server_name
- name: test attach Volume
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
server: "{{hcloud_server_name}}"
register: volume
@@ -86,10 +86,10 @@
assert:
that:
- volume is changed
- - volume.hcloud_volume.server == "{{hcloud_server_name}}"
+ - volume.hcloud_volume.server == hcloud_server_name
- name: test attach Volume idempotence
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
server: "{{hcloud_server_name}}"
register: volume
@@ -97,21 +97,21 @@
assert:
that:
- volume is not changed
- - volume.hcloud_volume.server == "{{hcloud_server_name}}"
+ - volume.hcloud_volume.server == hcloud_server_name
- name: test detach Volume with checkmode
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
- check_mode: yes
+ check_mode: true
register: volume
- name: verify detach Volume with checkmode
assert:
that:
- volume is changed
- - volume.hcloud_volume.server == "{{hcloud_server_name}}"
+ - volume.hcloud_volume.server == hcloud_server_name
- name: test detach Volume
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
register: volume
- name: verify detach volume
@@ -119,10 +119,10 @@
that:
- volume is changed
- volume.hcloud_volume.location == "fsn1"
- - volume.hcloud_volume.server != "{{hcloud_server_name}}"
+ - volume.hcloud_volume.server != hcloud_server_name
- name: test update Volume label
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
labels:
key: value
@@ -134,7 +134,7 @@
- volume.hcloud_volume.labels.key == "value"
- name: test update Volume label with the same label
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
labels:
key: value
@@ -145,7 +145,7 @@
- volume is not changed
- name: test increase Volume size
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
size: 11
register: volume
@@ -156,7 +156,7 @@
- volume.hcloud_volume.size == 11
- name: test decreace Volume size
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
size: 10
register: volume
@@ -167,7 +167,7 @@
- volume.hcloud_volume.size == 11
- name: test update Volume delete protection
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
delete_protection: true
register: volume
@@ -178,7 +178,7 @@
- volume.hcloud_volume.delete_protection is sameas true
- name: test update Volume delete protection idempotency
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
delete_protection: true
register: volume
@@ -189,7 +189,7 @@
- volume.hcloud_volume.delete_protection is sameas true
- name: test Volume without delete protection set to be idempotent
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
register: volume
- name: verify test Volume without delete protection set to be idempotent
@@ -199,10 +199,10 @@
- volume.hcloud_volume.delete_protection is sameas true
- name: test delete Volume fails if it is protected
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
state: absent
- ignore_errors: yes
+ ignore_errors: true
register: result
- name: verify delete Volume fails if it is protected
assert:
@@ -211,7 +211,7 @@
- 'result.msg == "volume deletion is protected"'
- name: test update Volume delete protection
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
delete_protection: false
register: volume
@@ -222,7 +222,7 @@
- volume.hcloud_volume.delete_protection is sameas false
- name: test delete Volume
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
state: absent
register: result
@@ -231,9 +231,8 @@
that:
- result is success
-
- name: test create Volume with delete protection
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
size: 10
location: "fsn1"
@@ -246,10 +245,10 @@
- volume.hcloud_volume.delete_protection is sameas true
- name: test delete Volume fails if it is protected
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
state: absent
- ignore_errors: yes
+ ignore_errors: true
register: result
- name: verify delete Volume fails if it is protected
assert:
@@ -258,7 +257,7 @@
- 'result.msg == "volume deletion is protected"'
- name: test update Volume delete protection
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
delete_protection: false
register: volume
@@ -269,7 +268,7 @@
- volume.hcloud_volume.delete_protection is sameas false
- name: test delete Volume
- hcloud_volume:
+ hetzner.hcloud.volume:
name: "{{hcloud_volume_name}}"
state: absent
register: result
@@ -279,11 +278,11 @@
- result is success
- name: cleanup
- hcloud_server:
+ hetzner.hcloud.server:
name: "{{ hcloud_server_name }}"
state: absent
register: result
- name: verify cleanup
assert:
that:
- - result is success
+ - result is success
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/aliases b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/aliases
new file mode 100644
index 000000000..0e887600e
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/aliases
@@ -0,0 +1,2 @@
+cloud/hcloud
+azp/group2
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/defaults/main/common.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/defaults/main/common.yml
new file mode 100644
index 000000000..e316b233c
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/defaults/main/common.yml
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+# Azure Pipelines will configure this value to something similar to
+# "azp-84824-1-hetzner-2-13-test-2-13-hcloud-3-9-1-default-i"
+hcloud_prefix: "tests"
+
+# Used to namespace resources created by concurrent test pipelines/targets
+hcloud_run_ns: "{{ hcloud_prefix | md5 }}"
+hcloud_role_ns: "{{ role_name | split('_') | map('first') | join() }}"
+hcloud_ns: "ansible-{{ hcloud_run_ns }}-{{ hcloud_role_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/defaults/main/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/defaults/main/main.yml
new file mode 100644
index 000000000..e243ee062
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/defaults/main/main.yml
@@ -0,0 +1,4 @@
+# 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_volume_name: "{{ hcloud_ns }}"
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/cleanup.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/cleanup.yml
new file mode 100644
index 000000000..8fa589a43
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/cleanup.yml
@@ -0,0 +1,5 @@
+---
+- name: Cleanup test_volume
+ hetzner.hcloud.volume:
+ name: "{{ hcloud_volume_name }}"
+ state: absent
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/main.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/main.yml
new file mode 100644
index 000000000..767fc465b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/main.yml
@@ -0,0 +1,31 @@
+#
+# DO NOT EDIT THIS FILE! Please edit the files in tests/integration/common instead.
+#
+---
+- name: Check if cleanup.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/cleanup.yml"
+ register: cleanup_file
+
+- name: Check if prepare.yml exists
+ ansible.builtin.stat:
+ path: "{{ role_path }}/tasks/prepare.yml"
+ register: prepare_file
+
+- name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
+
+- name: Include prepare tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/prepare.yml"
+ when: prepare_file.stat.exists
+
+- name: Run tests
+ block:
+ - name: Include test tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/test.yml"
+
+ always:
+ - name: Include cleanup tasks
+ ansible.builtin.include_tasks: "{{ role_path }}/tasks/cleanup.yml"
+ when: cleanup_file.stat.exists
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/prepare.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/prepare.yml
new file mode 100644
index 000000000..de3c70b42
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/prepare.yml
@@ -0,0 +1,9 @@
+---
+- name: Create test_volume
+ hetzner.hcloud.volume:
+ name: "{{ hcloud_volume_name }}"
+ size: 10
+ location: fsn1
+ labels:
+ key: value
+ register: test_volume
diff --git a/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/test.yml b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/test.yml
new file mode 100644
index 000000000..79912029b
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/integration/targets/volume_info/tasks/test.yml
@@ -0,0 +1,81 @@
+# 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: Gather hcloud_volume_info
+ hetzner.hcloud.volume_info:
+ register: result
+- name: Verify hcloud_volume_info
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_volume_info | list | count >= 1
+
+- name: Gather hcloud_volume_info in check mode
+ hetzner.hcloud.volume_info:
+ check_mode: true
+ register: result
+- name: Verify hcloud_volume_info in check mode
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_volume_info | list | count >= 1
+
+- name: Gather hcloud_volume_info with correct id
+ hetzner.hcloud.volume_info:
+ id: "{{ test_volume.hcloud_volume.id }}"
+ register: result
+- name: Verify hcloud_volume_info with correct id
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_volume_info | list | count == 1
+ - result.hcloud_volume_info[0].name == hcloud_volume_name
+ - result.hcloud_volume_info[0].location == 'fsn1'
+ - result.hcloud_volume_info[0].size == 10
+ - result.hcloud_volume_info[0].linux_device is defined
+
+- name: Gather hcloud_volume_info with wrong id
+ hetzner.hcloud.volume_info:
+ id: "{{ test_volume.hcloud_volume.id }}4321"
+ ignore_errors: true
+ register: result
+- name: Verify hcloud_volume_info with wrong id
+ ansible.builtin.assert:
+ that:
+ - result is failed
+
+- name: Gather hcloud_volume_info with correct name
+ hetzner.hcloud.volume_info:
+ name: "{{ hcloud_volume_name }}"
+ register: result
+- name: Verify hcloud_volume_info with correct name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_volume_info | list | count == 1
+
+- name: Gather hcloud_volume_info with wrong name
+ hetzner.hcloud.volume_info:
+ name: "{{ hcloud_volume_name }}-invalid"
+ register: result
+- name: Verify hcloud_volume_info with wrong name
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_volume_info | list | count == 0
+
+- name: Gather hcloud_volume_info with correct label selector
+ hetzner.hcloud.volume_info:
+ label_selector: "key=value"
+ register: result
+- name: Verify hcloud_volume_info with correct label selector
+ ansible.builtin.assert:
+ that:
+ - >
+ result.hcloud_volume_info
+ | selectattr('name', 'equalto', hcloud_volume_name)
+ | list | count == 1
+
+- name: Gather hcloud_volume_info with wrong label selector
+ hetzner.hcloud.volume_info:
+ label_selector: "key!=value"
+ register: result
+- name: Verify hcloud_volume_info with wrong label selector
+ ansible.builtin.assert:
+ that:
+ - result.hcloud_volume_info | list | count == 0
diff --git a/ansible_collections/hetzner/hcloud/tests/requirements.yml b/ansible_collections/hetzner/hcloud/tests/requirements.yml
index 6c49d0d9e..3fea3f392 100644
--- a/ansible_collections/hetzner/hcloud/tests/requirements.yml
+++ b/ansible_collections/hetzner/hcloud/tests/requirements.yml
@@ -1,3 +1,5 @@
-integration_tests_dependencies:
-- community.general
-- ansible.netcommon
+---
+collections:
+ - ansible.utils
+ - community.crypto
+ - community.general
diff --git a/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.12.txt b/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.12.txt
deleted file mode 100644
index caf221794..000000000
--- a/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.12.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-tests/utils/shippable/check_matrix.py replace-urlopen
-tests/utils/shippable/timing.py shebang
diff --git a/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.13.txt b/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.13.txt
index caf221794..185a458e3 100644
--- a/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.13.txt
+++ b/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.13.txt
@@ -1,2 +1,69 @@
-tests/utils/shippable/check_matrix.py replace-urlopen
-tests/utils/shippable/timing.py shebang
+plugins/inventory/hcloud.py validate-modules:illegal-future-imports
+plugins/inventory/hcloud.py validate-modules:import-before-documentation
+plugins/inventory/hcloud.py yamllint:unparsable-with-libyaml # bug in ansible-test - https://github.com/ansible/ansible/issues/82353
+plugins/modules/certificate_info.py validate-modules:illegal-future-imports
+plugins/modules/certificate_info.py validate-modules:import-before-documentation
+plugins/modules/certificate.py validate-modules:illegal-future-imports
+plugins/modules/certificate.py validate-modules:import-before-documentation
+plugins/modules/datacenter_info.py validate-modules:illegal-future-imports
+plugins/modules/datacenter_info.py validate-modules:import-before-documentation
+plugins/modules/firewall_info.py validate-modules:illegal-future-imports
+plugins/modules/firewall_info.py validate-modules:import-before-documentation
+plugins/modules/firewall_resource.py validate-modules:illegal-future-imports
+plugins/modules/firewall_resource.py validate-modules:import-before-documentation
+plugins/modules/firewall.py validate-modules:illegal-future-imports
+plugins/modules/firewall.py validate-modules:import-before-documentation
+plugins/modules/floating_ip_info.py validate-modules:illegal-future-imports
+plugins/modules/floating_ip_info.py validate-modules:import-before-documentation
+plugins/modules/floating_ip.py validate-modules:illegal-future-imports
+plugins/modules/floating_ip.py validate-modules:import-before-documentation
+plugins/modules/image_info.py validate-modules:illegal-future-imports
+plugins/modules/image_info.py validate-modules:import-before-documentation
+plugins/modules/iso_info.py validate-modules:illegal-future-imports
+plugins/modules/iso_info.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_info.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_info.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_network.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_network.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_service.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_service.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_target.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_target.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_type_info.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_type_info.py validate-modules:import-before-documentation
+plugins/modules/load_balancer.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer.py validate-modules:import-before-documentation
+plugins/modules/location_info.py validate-modules:illegal-future-imports
+plugins/modules/location_info.py validate-modules:import-before-documentation
+plugins/modules/network_info.py validate-modules:illegal-future-imports
+plugins/modules/network_info.py validate-modules:import-before-documentation
+plugins/modules/network.py validate-modules:illegal-future-imports
+plugins/modules/network.py validate-modules:import-before-documentation
+plugins/modules/placement_group.py validate-modules:illegal-future-imports
+plugins/modules/placement_group.py validate-modules:import-before-documentation
+plugins/modules/primary_ip_info.py validate-modules:illegal-future-imports
+plugins/modules/primary_ip_info.py validate-modules:import-before-documentation
+plugins/modules/primary_ip.py validate-modules:illegal-future-imports
+plugins/modules/primary_ip.py validate-modules:import-before-documentation
+plugins/modules/rdns.py validate-modules:illegal-future-imports
+plugins/modules/rdns.py validate-modules:import-before-documentation
+plugins/modules/route.py validate-modules:illegal-future-imports
+plugins/modules/route.py validate-modules:import-before-documentation
+plugins/modules/server_info.py validate-modules:illegal-future-imports
+plugins/modules/server_info.py validate-modules:import-before-documentation
+plugins/modules/server_network.py validate-modules:illegal-future-imports
+plugins/modules/server_network.py validate-modules:import-before-documentation
+plugins/modules/server_type_info.py validate-modules:illegal-future-imports
+plugins/modules/server_type_info.py validate-modules:import-before-documentation
+plugins/modules/server.py validate-modules:illegal-future-imports
+plugins/modules/server.py validate-modules:import-before-documentation
+plugins/modules/ssh_key_info.py validate-modules:illegal-future-imports
+plugins/modules/ssh_key_info.py validate-modules:import-before-documentation
+plugins/modules/ssh_key.py validate-modules:illegal-future-imports
+plugins/modules/ssh_key.py validate-modules:import-before-documentation
+plugins/modules/subnetwork.py validate-modules:illegal-future-imports
+plugins/modules/subnetwork.py validate-modules:import-before-documentation
+plugins/modules/volume_info.py validate-modules:illegal-future-imports
+plugins/modules/volume_info.py validate-modules:import-before-documentation
+plugins/modules/volume.py validate-modules:illegal-future-imports
+plugins/modules/volume.py validate-modules:import-before-documentation
diff --git a/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.14.txt b/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.14.txt
index caf221794..e0d8362f4 100644
--- a/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.14.txt
+++ b/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.14.txt
@@ -1,2 +1,68 @@
-tests/utils/shippable/check_matrix.py replace-urlopen
-tests/utils/shippable/timing.py shebang
+plugins/inventory/hcloud.py validate-modules:illegal-future-imports
+plugins/inventory/hcloud.py yamllint:unparsable-with-libyaml # bug in ansible-test - https://github.com/ansible/ansible/issues/82353
+plugins/modules/certificate_info.py validate-modules:illegal-future-imports
+plugins/modules/certificate_info.py validate-modules:import-before-documentation
+plugins/modules/certificate.py validate-modules:illegal-future-imports
+plugins/modules/certificate.py validate-modules:import-before-documentation
+plugins/modules/datacenter_info.py validate-modules:illegal-future-imports
+plugins/modules/datacenter_info.py validate-modules:import-before-documentation
+plugins/modules/firewall_info.py validate-modules:illegal-future-imports
+plugins/modules/firewall_info.py validate-modules:import-before-documentation
+plugins/modules/firewall_resource.py validate-modules:illegal-future-imports
+plugins/modules/firewall_resource.py validate-modules:import-before-documentation
+plugins/modules/firewall.py validate-modules:illegal-future-imports
+plugins/modules/firewall.py validate-modules:import-before-documentation
+plugins/modules/floating_ip_info.py validate-modules:illegal-future-imports
+plugins/modules/floating_ip_info.py validate-modules:import-before-documentation
+plugins/modules/floating_ip.py validate-modules:illegal-future-imports
+plugins/modules/floating_ip.py validate-modules:import-before-documentation
+plugins/modules/image_info.py validate-modules:illegal-future-imports
+plugins/modules/image_info.py validate-modules:import-before-documentation
+plugins/modules/iso_info.py validate-modules:illegal-future-imports
+plugins/modules/iso_info.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_info.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_info.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_network.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_network.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_service.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_service.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_target.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_target.py validate-modules:import-before-documentation
+plugins/modules/load_balancer_type_info.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer_type_info.py validate-modules:import-before-documentation
+plugins/modules/load_balancer.py validate-modules:illegal-future-imports
+plugins/modules/load_balancer.py validate-modules:import-before-documentation
+plugins/modules/location_info.py validate-modules:illegal-future-imports
+plugins/modules/location_info.py validate-modules:import-before-documentation
+plugins/modules/network_info.py validate-modules:illegal-future-imports
+plugins/modules/network_info.py validate-modules:import-before-documentation
+plugins/modules/network.py validate-modules:illegal-future-imports
+plugins/modules/network.py validate-modules:import-before-documentation
+plugins/modules/placement_group.py validate-modules:illegal-future-imports
+plugins/modules/placement_group.py validate-modules:import-before-documentation
+plugins/modules/primary_ip_info.py validate-modules:illegal-future-imports
+plugins/modules/primary_ip_info.py validate-modules:import-before-documentation
+plugins/modules/primary_ip.py validate-modules:illegal-future-imports
+plugins/modules/primary_ip.py validate-modules:import-before-documentation
+plugins/modules/rdns.py validate-modules:illegal-future-imports
+plugins/modules/rdns.py validate-modules:import-before-documentation
+plugins/modules/route.py validate-modules:illegal-future-imports
+plugins/modules/route.py validate-modules:import-before-documentation
+plugins/modules/server_info.py validate-modules:illegal-future-imports
+plugins/modules/server_info.py validate-modules:import-before-documentation
+plugins/modules/server_network.py validate-modules:illegal-future-imports
+plugins/modules/server_network.py validate-modules:import-before-documentation
+plugins/modules/server_type_info.py validate-modules:illegal-future-imports
+plugins/modules/server_type_info.py validate-modules:import-before-documentation
+plugins/modules/server.py validate-modules:illegal-future-imports
+plugins/modules/server.py validate-modules:import-before-documentation
+plugins/modules/ssh_key_info.py validate-modules:illegal-future-imports
+plugins/modules/ssh_key_info.py validate-modules:import-before-documentation
+plugins/modules/ssh_key.py validate-modules:illegal-future-imports
+plugins/modules/ssh_key.py validate-modules:import-before-documentation
+plugins/modules/subnetwork.py validate-modules:illegal-future-imports
+plugins/modules/subnetwork.py validate-modules:import-before-documentation
+plugins/modules/volume_info.py validate-modules:illegal-future-imports
+plugins/modules/volume_info.py validate-modules:import-before-documentation
+plugins/modules/volume.py validate-modules:illegal-future-imports
+plugins/modules/volume.py validate-modules:import-before-documentation
diff --git a/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.15.txt b/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.15.txt
index caf221794..d6cabf4c0 100644
--- a/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.15.txt
+++ b/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.15.txt
@@ -1,2 +1 @@
-tests/utils/shippable/check_matrix.py replace-urlopen
-tests/utils/shippable/timing.py shebang
+plugins/inventory/hcloud.py yamllint:unparsable-with-libyaml # bug in ansible-test - https://github.com/ansible/ansible/issues/82353
diff --git a/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.16.txt b/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.16.txt
new file mode 100644
index 000000000..d6cabf4c0
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/sanity/ignore-2.16.txt
@@ -0,0 +1 @@
+plugins/inventory/hcloud.py yamllint:unparsable-with-libyaml # bug in ansible-test - https://github.com/ansible/ansible/issues/82353
diff --git a/ansible_collections/hetzner/hcloud/tests/unit/module_utils/test_hcloud.py b/ansible_collections/hetzner/hcloud/tests/unit/module_utils/test_hcloud.py
new file mode 100644
index 000000000..c1a9ffb77
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/unit/module_utils/test_hcloud.py
@@ -0,0 +1,125 @@
+from __future__ import annotations
+
+import traceback
+from datetime import datetime, timezone
+from unittest.mock import MagicMock
+
+from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import AnsibleHCloud
+from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud import (
+ APIException,
+)
+from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.actions import (
+ Action,
+ ActionException,
+ ActionFailedException,
+ ActionTimeoutException,
+)
+
+
+def test_hcloud_fail_json_hcloud():
+ module = MagicMock()
+ module.params = {
+ "api_token": "fake_token",
+ "api_endpoint": "https://api.hetzner.cloud/v1",
+ }
+ AnsibleHCloud.represent = "hcloud_test"
+ hcloud = AnsibleHCloud(module)
+
+ try:
+ raise APIException(
+ code="invalid_input",
+ message="invalid input in fields 'server', 'home_location'",
+ details={
+ "fields": [
+ {"messages": ["either server or home_location must be provided"], "name": "server"},
+ {"messages": ["either server or home_location must be provided"], "name": "home_location"},
+ ]
+ },
+ )
+ except APIException as exception:
+ hcloud.fail_json_hcloud(exception)
+
+ module.fail_json.assert_called_with(
+ msg="invalid input in fields 'server', 'home_location'",
+ exception=traceback.format_exc(),
+ failure={
+ "message": "invalid input in fields 'server', 'home_location'",
+ "code": "invalid_input",
+ "details": {
+ "fields": [
+ {"messages": ["either server or home_location must be provided"], "name": "server"},
+ {"messages": ["either server or home_location must be provided"], "name": "home_location"},
+ ]
+ },
+ },
+ )
+
+ try:
+ raise ActionFailedException(
+ action=Action(
+ **{
+ "id": 1084730887,
+ "command": "change_server_type",
+ "status": "error",
+ "progress": 100,
+ "resources": [{"id": 34574042, "type": "server"}],
+ "error": {"code": "server_does_not_exist_anymore", "message": "Server does not exist anymore"},
+ "started": "2023-07-06T14:52:42+00:00",
+ "finished": "2023-07-06T14:53:08+00:00",
+ }
+ )
+ )
+ except ActionException as exception:
+ hcloud.fail_json_hcloud(exception)
+
+ module.fail_json.assert_called_with(
+ msg="The pending action failed: Server does not exist anymore",
+ exception=traceback.format_exc(),
+ failure={
+ "action": {
+ "id": 1084730887,
+ "command": "change_server_type",
+ "status": "error",
+ "progress": 100,
+ "resources": [{"id": 34574042, "type": "server"}],
+ "error": {"code": "server_does_not_exist_anymore", "message": "Server does not exist anymore"},
+ "started": datetime(2023, 7, 6, 14, 52, 42, tzinfo=timezone.utc),
+ "finished": datetime(2023, 7, 6, 14, 53, 8, tzinfo=timezone.utc),
+ }
+ },
+ )
+
+ try:
+ raise ActionTimeoutException(
+ action=Action(
+ **{
+ "id": 1084659545,
+ "command": "create_server",
+ "status": "running",
+ "progress": 50,
+ "started": "2023-07-06T13:58:38+00:00",
+ "finished": None,
+ "resources": [{"id": 34572291, "type": "server"}],
+ "error": None,
+ }
+ )
+ )
+ except ActionException as exception:
+ hcloud.fail_json_hcloud(exception)
+
+ module.fail_json.assert_called_with(
+ msg="The pending action timed out",
+ exception=traceback.format_exc(),
+ failure={
+ "action": {
+ "id": 1084659545,
+ "command": "create_server",
+ "status": "running",
+ "progress": 50,
+ "resources": [{"id": 34572291, "type": "server"}],
+ "error": None,
+ "started": datetime(2023, 7, 6, 13, 58, 38, tzinfo=timezone.utc),
+ "finished": None,
+ }
+ },
+ )
diff --git a/ansible_collections/hetzner/hcloud/tests/unit/requirements.txt b/ansible_collections/hetzner/hcloud/tests/unit/requirements.txt
new file mode 100644
index 000000000..bc314c3c2
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/unit/requirements.txt
@@ -0,0 +1,2 @@
+python-dateutil
+requests
diff --git a/ansible_collections/hetzner/hcloud/tests/utils/ci.sh b/ansible_collections/hetzner/hcloud/tests/utils/ci.sh
new file mode 100755
index 000000000..e5d73912a
--- /dev/null
+++ b/ansible_collections/hetzner/hcloud/tests/utils/ci.sh
@@ -0,0 +1,141 @@
+#!/usr/bin/env bash
+
+set -o pipefail -eux
+
+error() {
+ echo >&2 "error: $*"
+ exit 1
+}
+
+retry() {
+ local exit_code=1
+
+ for _ in 1 2 3; do
+ set +e
+ "$@"
+ exit_code=$?
+ set -e
+ if [ $exit_code == 0 ]; then
+ return $exit_code
+ fi
+ done
+
+ echo "Command '$*' failed 3 times!"
+ exit $exit_code
+}
+
+declare -a entry_point_args
+IFS='/:' read -ra entry_point_args <<< "$1"
+
+# Explode entry point args, for example '2.16/integration/3.10/2' or '2.16/sanity'
+ansible_version="${entry_point_args[0]}"
+test_name="${entry_point_args[1]}"
+python_version="${entry_point_args[2]:-}"
+test_group="${entry_point_args[3]:-}"
+
+export PYTHONIOENCODING="utf-8"
+export PIP_DISABLE_PIP_VERSION_CHECK=true
+export PIP_NO_WARN_SCRIPT_LOCATION=false # Negative options are a bit weird: https://pip.pypa.io/en/stable/topics/configuration/#boolean-options
+export ANSIBLE_COLLECTIONS_PATH="$PWD/../.."
+
+command -v python
+python -V
+
+command -v pip
+pip --version
+pip list
+
+if [ "$ansible_version" == "devel" ]; then
+ pip install "https://github.com/ansible/ansible/archive/devel.tar.gz"
+else
+ pip install "https://github.com/ansible/ansible/archive/stable-$ansible_version.tar.gz"
+fi
+command -v ansible
+ansible --version
+
+# Prepare coverage args
+if $COVERAGE; then
+ coverage_args="--coverage"
+elif [[ "$COMMIT_MESSAGE" =~ ci_coverage ]]; then
+ coverage_args="--coverage"
+else
+ coverage_args="--coverage-check"
+fi
+
+# Prepare changed args
+if $COMPLETE; then
+ changed_args=""
+elif [[ "$COMMIT_MESSAGE" =~ ci_complete ]]; then
+ changed_args=""
+else
+ changed_args="--changed"
+fi
+
+# Prepare unstable args
+if $IS_PULL_REQUEST; then
+ unstable_args="--allow-unstable-changed"
+else
+ unstable_args=""
+fi
+
+# Install dependencies
+pip install rstcheck
+
+# Ensure we can write other collections to this dir
+sudo chown "$(whoami)" "$ANSIBLE_COLLECTIONS_PATH"
+
+pip install -r tests/integration/requirements.txt -c tests/constraints.txt
+ansible-galaxy -vvv collection install -r tests/requirements.yml
+
+# Dump env and set timeout
+timeout=45
+if $COVERAGE; then
+ timeout=60
+fi
+
+ansible-test env --color -v --dump --show --timeout "$timeout"
+
+# Run tests
+case "$test_name" in
+ sanity)
+ # shellcheck disable=SC2086
+ ansible-test sanity --color -v \
+ --exclude plugins/module_utils/vendor/ \
+ --exclude scripts/ \
+ --exclude tests/utils/ \
+ --docker default \
+ --junit \
+ $coverage_args \
+ $changed_args \
+ --allow-disabled
+ ;;
+
+ units)
+ # shellcheck disable=SC2086
+ ansible-test units --color -v \
+ --docker default \
+ --python "$python_version" \
+ $coverage_args \
+ $changed_args
+ ;;
+
+ integration)
+ # shellcheck disable=SC2086
+ ansible-test integration --color -v \
+ --remote-terminate always \
+ --remote-stage prod \
+ --docker default \
+ --python "$python_version" \
+ --retry-on-error \
+ $coverage_args \
+ $changed_args \
+ --changed-all-target none \
+ --changed-all-mode include \
+ $unstable_args \
+ "azp/group$test_group/"
+ ;;
+
+ *)
+ error "found invalid test_name: $test_name"
+ ;;
+esac
diff --git a/ansible_collections/hetzner/hcloud/tests/utils/gitlab/gitlab.sh b/ansible_collections/hetzner/hcloud/tests/utils/gitlab/gitlab.sh
index b09bd2f3a..a96ad2f4c 100755
--- a/ansible_collections/hetzner/hcloud/tests/utils/gitlab/gitlab.sh
+++ b/ansible_collections/hetzner/hcloud/tests/utils/gitlab/gitlab.sh
@@ -11,77 +11,73 @@ ansible_version="${args[0]}"
script="${args[1]}"
function join {
- local IFS="$1";
- shift;
- echo "$*";
+ local IFS="$1"
+ shift
+ echo "$*"
}
test="$(join / "${args[@]:1}")"
command -v python
python -V
-function retry
-{
- # shellcheck disable=SC2034
- for repetition in 1 2 3; do
- set +e
- "$@"
- result=$?
- set -e
- if [ ${result} == 0 ]; then
- return ${result}
- fi
- echo "@* -> ${result}"
- done
- echo "Command '@*' failed 3 times!"
- exit 1
+function retry {
+ # shellcheck disable=SC2034
+ for repetition in 1 2 3; do
+ set +e
+ "$@"
+ result=$?
+ set -e
+ if [ ${result} == 0 ]; then
+ return ${result}
+ fi
+ echo "@* -> ${result}"
+ done
+ echo "Command '@*' failed 3 times!"
+ exit 1
}
command -v pip
pip --version
pip list --disable-pip-version-check
if [ "${ansible_version}" == "devel" ]; then
- retry pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
+ retry pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
else
- retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check
+ retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check
fi
-export ANSIBLE_COLLECTIONS_PATHS="${HOME}/.ansible"
+export ANSIBLE_COLLECTIONS_PATH="${HOME}/.ansible"
# shellcheck disable=SC2034
SHIPPABLE_RESULT_DIR="$(pwd)/shippable"
-TEST_DIR="${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/hetzner/hcloud"
+TEST_DIR="${ANSIBLE_COLLECTIONS_PATH}/ansible_collections/hetzner/hcloud"
rm -rf "${TEST_DIR}"
mkdir -p "${TEST_DIR}"
cp -r "." "${TEST_DIR}"
cd "${TEST_DIR}"
# STAR: HACK install dependencies
-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 pip install -r tests/integration/requirements.txt -c tests/integration/constraints.txt
+retry ansible-galaxy -vvv collection install -r tests/requirements.yml
+
retry pip install rstcheck
+retry ansible-galaxy -vvv collection install community.internal_test_tools
# END: HACK
export PYTHONIOENCODING='utf-8'
if [ "${JOB_TRIGGERED_BY_NAME:-}" == "nightly-trigger" ]; then
- COMPLETE=yes
+ COMPLETE=yes
fi
-
if [ -n "${COMPLETE:-}" ]; then
- # disable change detection triggered by setting the COMPLETE environment variable to a non-empty value
- export CHANGED=""
+ # disable change detection triggered by setting the COMPLETE environment variable to a non-empty value
+ export CHANGED=""
elif [[ "${CI_COMMIT_MESSAGE}" =~ ci_complete ]]; then
- # disable change detection triggered by having 'ci_complete' in the latest commit message
- export CHANGED=""
+ # disable change detection triggered by having 'ci_complete' in the latest commit message
+ export CHANGED=""
else
- # enable change detection (default behavior)
- export CHANGED=""
+ # enable change detection (default behavior)
+ export CHANGED=""
fi
-
export UNSTABLE="--allow-unstable-changed"
# remove empty core/extras module directories from PRs created prior to the repo-merge
diff --git a/ansible_collections/hetzner/hcloud/tests/utils/gitlab/sanity.sh b/ansible_collections/hetzner/hcloud/tests/utils/gitlab/sanity.sh
index 4ee96aefe..9f6711b05 100755
--- a/ansible_collections/hetzner/hcloud/tests/utils/gitlab/sanity.sh
+++ b/ansible_collections/hetzner/hcloud/tests/utils/gitlab/sanity.sh
@@ -8,32 +8,32 @@ IFS='/:' read -ra args <<< "$1"
group="${args[1]}"
if [ "${BASE_BRANCH:-}" ]; then
- base_branch="origin/${BASE_BRANCH}"
+ base_branch="origin/${BASE_BRANCH}"
else
- base_branch=""
+ base_branch=""
fi
if [ "${group}" == "extra" ]; then
- ../internal_test_tools/tools/run.py --color
- exit
+ ../internal_test_tools/tools/run.py --color
+ exit
fi
case "${group}" in
- 1) options=(--skip-test pylint --skip-test ansible-doc --skip-test validate-modules) ;;
- 2) options=( --test ansible-doc --test validate-modules) ;;
- 3) options=(--test pylint plugins/modules/) ;;
- 4) options=(--test pylint --exclude plugins/modules/) ;;
+ 1) options=(--skip-test pylint --skip-test ansible-doc --skip-test validate-modules) ;;
+ 2) options=(--test ansible-doc --test validate-modules) ;;
+ 3) options=(--test pylint plugins/modules/) ;;
+ 4) options=(--test pylint --exclude plugins/modules/) ;;
esac
# allow collection migration sanity tests for groups 3 and 4 to pass without updating this script during migration
network_path="lib/ansible/modules/network/"
if [ -d "${network_path}" ]; then
- if [ "${group}" -eq 3 ]; then
- options+=(--exclude "${network_path}")
- elif [ "${group}" -eq 4 ]; then
- options+=("${network_path}")
- fi
+ if [ "${group}" -eq 3 ]; then
+ options+=(--exclude "${network_path}")
+ elif [ "${group}" -eq 4 ]; then
+ options+=("${network_path}")
+ fi
fi
pip install pycodestyle
@@ -42,6 +42,8 @@ pip install voluptuous
pip install pylint==2.5.3
# shellcheck disable=SC2086
ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
- --base-branch "${base_branch}" \
- --exclude tests/utils/ \
- "${options[@]}" --allow-disabled
+ --base-branch "${base_branch}" \
+ --exclude plugins/module_utils/vendor/ \
+ --exclude scripts/ \
+ --exclude tests/utils/ \
+ "${options[@]}" --allow-disabled
diff --git a/ansible_collections/hetzner/hcloud/tests/utils/shippable/check_matrix.py b/ansible_collections/hetzner/hcloud/tests/utils/shippable/check_matrix.py
deleted file mode 100755
index dfcca3e6d..000000000
--- a/ansible_collections/hetzner/hcloud/tests/utils/shippable/check_matrix.py
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/usr/bin/env python
-"""Verify the currently executing Shippable test matrix matches the one defined in the "shippable.yml" file."""
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import datetime
-import json
-import os
-import re
-import sys
-import time
-
-try:
- from typing import NoReturn
-except ImportError:
- NoReturn = None
-
-try:
- # noinspection PyCompatibility
- from urllib2 import urlopen # pylint: disable=ansible-bad-import-from
-except ImportError:
- # noinspection PyCompatibility
- from urllib.request import urlopen
-
-
-def main(): # type: () -> None
- """Main entry point."""
- repo_full_name = os.environ['REPO_FULL_NAME']
- required_repo_full_name = 'ansible-collections/hetzner.hcloud'
-
- if repo_full_name != required_repo_full_name:
- sys.stderr.write('Skipping matrix check on repo "%s" which is not "%s".\n' % (repo_full_name, required_repo_full_name))
- return
-
- with open('shippable.yml', 'rb') as yaml_file:
- yaml = yaml_file.read().decode('utf-8').splitlines()
-
- defined_matrix = [match.group(1) for match in [re.search(r'^ *- env: T=(.*)$', line) for line in yaml] if match and match.group(1) != 'none']
-
- if not defined_matrix:
- fail('No matrix entries found in the "shippable.yml" file.',
- 'Did you modify the "shippable.yml" file?')
-
- run_id = os.environ['SHIPPABLE_BUILD_ID']
- sleep = 1
- jobs = []
-
- for attempts_remaining in range(4, -1, -1):
- try:
- jobs = json.loads(urlopen('https://api.shippable.com/jobs?runIds=%s' % run_id).read())
-
- if not isinstance(jobs, list):
- raise Exception('Shippable run %s data is not a list.' % run_id)
-
- break
- except Exception as ex:
- if not attempts_remaining:
- fail('Unable to retrieve Shippable run %s matrix.' % run_id,
- str(ex))
-
- sys.stderr.write('Unable to retrieve Shippable run %s matrix: %s\n' % (run_id, ex))
- sys.stderr.write('Trying again in %d seconds...\n' % sleep)
- time.sleep(sleep)
- sleep *= 2
-
- if len(jobs) != len(defined_matrix):
- if len(jobs) == 1:
- hint = '\n\nMake sure you do not use the "Rebuild with SSH" option.'
- else:
- hint = ''
-
- fail('Shippable run %s has %d jobs instead of the expected %d jobs.' % (run_id, len(jobs), len(defined_matrix)),
- 'Try re-running the entire matrix.%s' % hint)
-
- actual_matrix = dict((job.get('jobNumber'), dict(tuple(line.split('=', 1)) for line in job.get('env', [])).get('T', '')) for job in jobs)
- errors = [(job_number, test, actual_matrix.get(job_number)) for job_number, test in enumerate(defined_matrix, 1) if actual_matrix.get(job_number) != test]
-
- if len(errors):
- error_summary = '\n'.join('Job %s expected "%s" but found "%s" instead.' % (job_number, expected, actual) for job_number, expected, actual in errors)
-
- fail('Shippable run %s has a job matrix mismatch.' % run_id,
- 'Try re-running the entire matrix.\n\n%s' % error_summary)
-
-
-def fail(message, output): # type: (str, str) -> NoReturn
- # Include a leading newline to improve readability on Shippable "Tests" tab.
- # Without this, the first line becomes indented.
- output = '\n' + output.strip()
-
- timestamp = datetime.datetime.utcnow().replace(microsecond=0).isoformat()
-
- # hack to avoid requiring junit-xml, which isn't pre-installed on Shippable outside our test containers
- xml = '''
-<?xml version="1.0" encoding="utf-8"?>
-<testsuites disabled="0" errors="1" failures="0" tests="1" time="0.0">
-\t<testsuite disabled="0" errors="1" failures="0" file="None" log="None" name="ansible-test" skipped="0" tests="1" time="0" timestamp="%s" url="None">
-\t\t<testcase classname="timeout" name="timeout">
-\t\t\t<error message="%s" type="error">%s</error>
-\t\t</testcase>
-\t</testsuite>
-</testsuites>
-''' % (timestamp, message, output)
-
- path = 'shippable/testresults/check-matrix.xml'
- dir_path = os.path.dirname(path)
-
- if not os.path.exists(dir_path):
- os.makedirs(dir_path)
-
- with open(path, 'w') as junit_fd:
- junit_fd.write(xml.lstrip())
-
- sys.stderr.write(message + '\n')
- sys.stderr.write(output + '\n')
-
- sys.exit(1)
-
-
-if __name__ == '__main__':
- main()
diff --git a/ansible_collections/hetzner/hcloud/tests/utils/shippable/hcloud.sh b/ansible_collections/hetzner/hcloud/tests/utils/shippable/hcloud.sh
deleted file mode 100755
index da037e09e..000000000
--- a/ansible_collections/hetzner/hcloud/tests/utils/shippable/hcloud.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env bash
-
-set -o pipefail -eux
-
-declare -a args
-IFS='/:' read -ra args <<< "$1"
-
-cloud="${args[0]}"
-python="${args[1]}"
-group="${args[2]}"
-
-target="shippable/${cloud}/group${group}/"
-
-stage="${S:-prod}"
-
-changed_all_target="shippable/${cloud}/smoketest/"
-
-if ! ansible-test integration "${changed_all_target}" --list-targets > /dev/null 2>&1; then
- # no smoketest tests are available for this cloud
- changed_all_target="none"
-fi
-
-if [ "${group}" == "1" ]; then
- # only run smoketest tests for group1
- changed_all_mode="include"
-else
- # smoketest tests already covered by group1
- changed_all_mode="exclude"
-fi
-
-# shellcheck disable=SC2086
-ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
- --remote-terminate always --remote-stage "${stage}" \
- --docker --python "${python}" --changed-all-target "${changed_all_target}" --changed-all-mode "${changed_all_mode}"
diff --git a/ansible_collections/hetzner/hcloud/tests/utils/shippable/sanity.sh b/ansible_collections/hetzner/hcloud/tests/utils/shippable/sanity.sh
deleted file mode 100755
index 9339aeda4..000000000
--- a/ansible_collections/hetzner/hcloud/tests/utils/shippable/sanity.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env bash
-
-set -o pipefail -eux
-
-declare -a args
-IFS='/:' read -ra args <<< "$1"
-
-group="${args[1]}"
-
-if [ "${BASE_BRANCH:-}" ]; then
- base_branch="origin/${BASE_BRANCH}"
-else
- base_branch=""
-fi
-
-if [ "${group}" == "extra" ]; then
- # ansible-galaxy -vvv collection install community.internal_test_tools
- git clone --single-branch --depth 1 https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
-
- ../internal_test_tools/tools/run.py --color
- exit
-fi
-
-# shellcheck disable=SC2086
-ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
- --docker --base-branch "${base_branch}" \
- --allow-disabled
diff --git a/ansible_collections/hetzner/hcloud/tests/utils/shippable/shippable.sh b/ansible_collections/hetzner/hcloud/tests/utils/shippable/shippable.sh
deleted file mode 100755
index 8c0bd6deb..000000000
--- a/ansible_collections/hetzner/hcloud/tests/utils/shippable/shippable.sh
+++ /dev/null
@@ -1,213 +0,0 @@
-#!/usr/bin/env bash
-
-set -o pipefail -eux
-
-declare -a args
-IFS='/:' read -ra args <<< "$1"
-
-ansible_version="${args[0]}"
-script="${args[1]}"
-
-function join {
- local IFS="$1";
- shift;
- echo "$*";
-}
-
-# Ensure we can write other collections to this dir
-sudo chown "$(whoami)" "${PWD}/../../"
-
-test="$(join / "${args[@]:1}")"
-
-docker images ansible/ansible
-docker images quay.io/ansible/*
-docker ps
-
-for container in $(docker ps --format '{{.Image}} {{.ID}}' | grep -v -e '^drydock/' -e '^quay.io/ansible/azure-pipelines-test-container:' | sed 's/^.* //'); do
- docker rm -f "${container}" || true # ignore errors
-done
-
-docker ps
-
-if [ -d /home/shippable/cache/ ]; then
- ls -la /home/shippable/cache/
-fi
-
-command -v python
-python -V
-
-function retry
-{
- # shellcheck disable=SC2034
- for repetition in 1 2 3; do
- set +e
- "$@"
- result=$?
- set -e
- if [ ${result} == 0 ]; then
- return ${result}
- fi
- echo "@* -> ${result}"
- done
- echo "Command '@*' failed 3 times!"
- exit 1
-}
-
-command -v pip
-pip --version
-pip list --disable-pip-version-check
-if [ "${ansible_version}" == "devel" ]; then
- retry pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
-else
- retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check
-fi
-
-if [ "${SHIPPABLE_BUILD_ID:-}" ]; then
- export ANSIBLE_COLLECTIONS_PATHS="${HOME}/.ansible"
- SHIPPABLE_RESULT_DIR="$(pwd)/shippable"
- TEST_DIR="${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/hetzner/hcloud"
- mkdir -p "${TEST_DIR}"
- cp -aT "${SHIPPABLE_BUILD_DIR}" "${TEST_DIR}"
- cd "${TEST_DIR}"
-else
- export ANSIBLE_COLLECTIONS_PATHS="${PWD}/../../../"
-fi
-
-# STAR: HACK install dependencies
-retry ansible-galaxy -vvv collection install community.general
-retry ansible-galaxy -vvv collection install ansible.netcommon
-
-retry pip install hcloud
-retry pip install netaddr --disable-pip-version-check
-retry ansible-galaxy -vvv collection install community.internal_test_tools
-# END: HACK
-
-export PYTHONIOENCODING='utf-8'
-
-if [ "${JOB_TRIGGERED_BY_NAME:-}" == "nightly-trigger" ]; then
- COVERAGE=yes
- COMPLETE=yes
-fi
-
-if [ -n "${COVERAGE:-}" ]; then
- # on-demand coverage reporting triggered by setting the COVERAGE environment variable to a non-empty value
- export COVERAGE="--coverage"
-elif [[ "${COMMIT_MESSAGE}" =~ ci_coverage ]]; then
- # on-demand coverage reporting triggered by having 'ci_coverage' in the latest commit message
- export COVERAGE="--coverage"
-else
- # on-demand coverage reporting disabled (default behavior, always-on coverage reporting remains enabled)
- export COVERAGE="--coverage-check"
-fi
-
-if [ -n "${COMPLETE:-}" ]; then
- # disable change detection triggered by setting the COMPLETE environment variable to a non-empty value
- export CHANGED=""
-elif [[ "${COMMIT_MESSAGE}" =~ ci_complete ]]; then
- # disable change detection triggered by having 'ci_complete' in the latest commit message
- export CHANGED=""
-else
- # enable change detection (default behavior)
- export CHANGED="--changed"
-fi
-
-if [ "${IS_PULL_REQUEST:-}" == "true" ]; then
- # run unstable tests which are targeted by focused changes on PRs
- export UNSTABLE="--allow-unstable-changed"
-else
- # do not run unstable tests outside PRs
- export UNSTABLE=""
-fi
-
-# remove empty core/extras module directories from PRs created prior to the repo-merge
-find plugins -type d -empty -print -delete
-
-function cleanup
-{
- # for complete on-demand coverage generate a report for all files with no coverage on the "sanity/5" job so we only have one copy
- if [ "${COVERAGE}" == "--coverage" ] && [ "${CHANGED}" == "" ] && [ "${test}" == "sanity/5" ]; then
- stub="--stub"
- # trigger coverage reporting for stubs even if no other coverage data exists
- mkdir -p tests/output/coverage/
- else
- stub=""
- fi
-
- if [ -d tests/output/coverage/ ]; then
- if find tests/output/coverage/ -mindepth 1 -name '.*' -prune -o -print -quit | grep -q .; then
- process_coverage='yes' # process existing coverage files
- elif [ "${stub}" ]; then
- process_coverage='yes' # process coverage when stubs are enabled
- else
- process_coverage=''
- fi
-
- if [ "${process_coverage}" ]; then
- # use python 3.7 for coverage to avoid running out of memory during coverage xml processing
- # only use it for coverage to avoid the additional overhead of setting up a virtual environment for a potential no-op job
- virtualenv --python /usr/bin/python3.7 ~/ansible-venv
- set +ux
- . ~/ansible-venv/bin/activate
- set -ux
-
- # shellcheck disable=SC2086
- ansible-test coverage xml --color -v --requirements --group-by command --group-by version ${stub:+"$stub"}
- cp -a tests/output/reports/coverage=*.xml "$SHIPPABLE_RESULT_DIR/codecoverage/"
-
- if [ "${ansible_version}" != "2.9" ]; then
- # analyze and capture code coverage aggregated by integration test target
- ansible-test coverage analyze targets generate -v "$SHIPPABLE_RESULT_DIR/testresults/coverage-analyze-targets.json"
- fi
-
- # upload coverage report to codecov.io only when using complete on-demand coverage
- if [ "${COVERAGE}" == "--coverage" ] && [ "${CHANGED}" == "" ]; then
- for file in tests/output/reports/coverage=*.xml; do
- flags="${file##*/coverage=}"
- flags="${flags%-powershell.xml}"
- flags="${flags%.xml}"
- # remove numbered component from stub files when converting to tags
- flags="${flags//stub-[0-9]*/stub}"
- flags="${flags//=/,}"
- flags="${flags//[^a-zA-Z0-9_,]/_}"
-
- bash <(curl -s https://ansible-ci-files.s3.us-east-1.amazonaws.com/codecov/codecov.sh) \
- -f "${file}" \
- -F "${flags}" \
- -n "${test}" \
- -t 8a86e979-f37b-4d5d-95a4-960c280d5eaa \
- -X coveragepy \
- -X gcov \
- -X fix \
- -X search \
- -X xcode \
- || echo "Failed to upload code coverage report to codecov.io: ${file}"
- done
- fi
- fi
- fi
-
- if [ -d tests/output/junit/ ]; then
- cp -aT tests/output/junit/ "$SHIPPABLE_RESULT_DIR/testresults/"
- fi
-
- if [ -d tests/output/data/ ]; then
- cp -a tests/output/data/ "$SHIPPABLE_RESULT_DIR/testresults/"
- fi
-
- if [ -d tests/output/bot/ ]; then
- cp -aT tests/output/bot/ "$SHIPPABLE_RESULT_DIR/testresults/"
- fi
-}
-
-if [ "${SHIPPABLE_BUILD_ID:-}" ]; then trap cleanup EXIT; fi
-
-if [[ "${COVERAGE:-}" == "--coverage" ]]; then
- timeout=60
-else
- timeout=45
-fi
-
-ansible-test env --dump --show --timeout "${timeout}" --color -v
-
-if [ "${SHIPPABLE_BUILD_ID:-}" ]; then "tests/utils/shippable/check_matrix.py"; fi
-"tests/utils/shippable/${script}.sh" "${test}"
diff --git a/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.py b/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.py
deleted file mode 100755
index fb538271b..000000000
--- a/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python3.7
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import sys
-import time
-
-start = time.time()
-
-sys.stdin.reconfigure(errors='surrogateescape')
-sys.stdout.reconfigure(errors='surrogateescape')
-
-for line in sys.stdin:
- seconds = time.time() - start
- sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line))
- sys.stdout.flush()
diff --git a/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.sh b/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.sh
deleted file mode 100755
index 77e257830..000000000
--- a/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-
-set -o pipefail -eu
-
-"$@" 2>&1 | "$(dirname "$0")/timing.py"