From d5ca1eed89c44fec5f803d0c64b49f0e6c35a6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20K=C3=A4mmerling?= <4281581+LKaemmerling@users.noreply.github.com> Date: Wed, 27 Mar 2019 11:51:36 +0100 Subject: [PATCH] Add hcloud_server_facts module (#53850) --- .../cloud/hcloud/hcloud_server_facts.py | 200 ++++++++++++++++++ .../targets/hcloud_server_facts/aliases | 2 + .../hcloud_server_facts/defaults/main.yml | 5 + .../hcloud_server_facts/tasks/main.yml | 97 +++++++++ 4 files changed, 304 insertions(+) create mode 100644 lib/ansible/modules/cloud/hcloud/hcloud_server_facts.py create mode 100644 test/integration/targets/hcloud_server_facts/aliases create mode 100644 test/integration/targets/hcloud_server_facts/defaults/main.yml create mode 100644 test/integration/targets/hcloud_server_facts/tasks/main.yml diff --git a/lib/ansible/modules/cloud/hcloud/hcloud_server_facts.py b/lib/ansible/modules/cloud/hcloud/hcloud_server_facts.py new file mode 100644 index 00000000000..6e87add1c0a --- /dev/null +++ b/lib/ansible/modules/cloud/hcloud/hcloud_server_facts.py @@ -0,0 +1,200 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = """ +--- +module: hcloud_server_facts + +short_description: Gather facts about your Hetzner Cloud servers. + +version_added: "2.8" + +description: + - Gather facts about your Hetzner Cloud servers. + +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 servery you want to get. + type: str +extends_documentation_fragment: hcloud +""" + +EXAMPLES = """ +- name: Gather hcloud server facts + local_action: + module: hcloud_server_facts + +- name: Print the gathered facts + debug: + var: ansible_facts.hcloud_server_facts +""" + +RETURN = """ +hcloud_server_facts: + description: The server facts 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 + location: + description: Name of the location of the server + returned: always + type: str + sample: fsn1 + 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 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + pass + + +class AnsibleHcloudServerFacts(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_server_facts") + self.hcloud_server_facts = None + + def _prepare_result(self): + tmp = [] + + for server in self.hcloud_server_facts: + if server is not None: + tmp.append({ + "id": to_native(server.id), + "name": to_native(server.name), + "ipv4_address": to_native(server.public_net.ipv4.ip), + "ipv6": to_native(server.public_net.ipv6.ip), + "image": to_native(server.image.name), + "server_type": to_native(server.server_type.name), + "datacenter": to_native(server.datacenter.name), + "location": to_native(server.datacenter.location.name), + "rescue_enabled": server.rescue_enabled, + "backup_window": to_native(server.backup_window), + "labels": server.labels, + "status": to_native(server.status), + }) + return tmp + + def get_servers(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_server_facts = [self.client.servers.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_server_facts = [self.client.servers.get_by_name( + self.module.params.get("name") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_server_facts = self.client.servers.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_server_facts = self.client.servers.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudServerFacts.define_module() + + hcloud = AnsibleHcloudServerFacts(module) + hcloud.get_servers() + result = hcloud.get_result() + ansible_facts = { + 'hcloud_server_facts': result['hcloud_server_facts'] + } + module.exit_json(ansible_facts=ansible_facts) + + +if __name__ == "__main__": + main() diff --git a/test/integration/targets/hcloud_server_facts/aliases b/test/integration/targets/hcloud_server_facts/aliases new file mode 100644 index 00000000000..51742ee23f7 --- /dev/null +++ b/test/integration/targets/hcloud_server_facts/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +unsupported diff --git a/test/integration/targets/hcloud_server_facts/defaults/main.yml b/test/integration/targets/hcloud_server_facts/defaults/main.yml new file mode 100644 index 00000000000..b9a9a8df7b1 --- /dev/null +++ b/test/integration/targets/hcloud_server_facts/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH +# 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}}-integration" diff --git a/test/integration/targets/hcloud_server_facts/tasks/main.yml b/test/integration/targets/hcloud_server_facts/tasks/main.yml new file mode 100644 index 00000000000..d81d0f95252 --- /dev/null +++ b/test/integration/targets/hcloud_server_facts/tasks/main.yml @@ -0,0 +1,97 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH +# 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: test gather hcloud server facts - empty resources + hcloud_server_facts: +- name: verify test gather hcloud server facts - empty resources + assert: + that: + - ansible_facts.hcloud_server_facts | count == 0 + +- name: create server + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: cx11 + image: ubuntu-18.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 facts in check mode + hcloud_server_facts: + check_mode: yes + +- name: verify test gather hcloud server facts in check mode + assert: + that: + - ansible_facts.hcloud_server_facts|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1 + + +- name: test gather hcloud server facts with correct label selector + hcloud_server_facts: + label_selector: "key=value" +- name: verify test gather hcloud server with correct label selector + assert: + that: + - ansible_facts.hcloud_server_facts|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1 + +- name: test gather hcloud server facts with wrong label selector + hcloud_server_facts: + label_selector: "key!=value" +- name: verify test gather hcloud server with wrong label selector + assert: + that: + - ansible_facts.hcloud_server_facts | list | count == 0 + +- name: test gather hcloud server facts with correct name + hcloud_server_facts: + name: "{{hcloud_server_name}}" +- name: verify test gather hcloud server with correct name + assert: + that: + - ansible_facts.hcloud_server_facts|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1 + +- name: test gather hcloud server facts with wrong name + hcloud_server_facts: + name: "{{hcloud_server_name}}1" +- name: verify test gather hcloud server with wrong name + assert: + that: + - ansible_facts.hcloud_server_facts | list | count == 0 + +- name: test gather hcloud server facts with correct id + hcloud_server_facts: + id: "{{main_server.hcloud_server.id}}" +- name: verify test gather hcloud server with correct id + assert: + that: + - ansible_facts.hcloud_server_facts|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1 + +- name: test gather hcloud server facts with wrong id + hcloud_server_facts: + name: "4711" +- name: verify test gather hcloud server with wrong id + assert: + that: + - ansible_facts.hcloud_server_facts | list | count == 0 + +- name: cleanup + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent