From 3e3ed54f0bb503a8c34870fa519d8d0eab76b567 Mon Sep 17 00:00:00 2001 From: Chris Ladd Date: Thu, 22 Oct 2020 11:08:18 -0700 Subject: [PATCH] FEATURE: Ansible module for appliance info An Ansible module for returning appliance info. The module takes a single optional parameter: `name` for requesting the data for a specific appliance. If name is not provided, then the data for all appliances is returned. The data returned is a list of `appliances`. Example playbook: ``` --- - hosts: localhost tasks: - name: Get all appliance info stacki_appliance_info: register: result - name: All appliances output debug: var: result - name: Get info for appliance backend stacki_appliance_info: name: backend register: result - name: Appliance backend output debug: var: result ``` Output of the debug commands, showing the structure of the data returned: ``` TASK [All appliances output] ******************************************************************** ok: [localhost] => { "result": { "appliances": [ { "appliance": "backend", "public": true }, { "appliance": "barnacle", "public": false }, { "appliance": "builder", "public": false }, { "appliance": "external", "public": false }, { "appliance": "frontend", "public": false }, { "appliance": "hypervisor", "public": true }, { "appliance": "replicant", "public": true }, { "appliance": "switch", "public": false } ], "changed": false, "failed": false } } TASK [Appliance backend output] ***************************************************************** ok: [localhost] => { "result": { "appliances": [ { "appliance": "backend", "public": true } ], "changed": false, "failed": false } } ``` --- .../plugins/modules/stacki_appliance_info.py | 99 +++++++++++++++++++ .../ansible/test_stacki_appliance_info.py | 27 +++++ 2 files changed, 126 insertions(+) create mode 100644 common/src/stack/ansible/plugins/modules/stacki_appliance_info.py create mode 100644 test-framework/test-suites/integration/tests/ansible/test_stacki_appliance_info.py diff --git a/common/src/stack/ansible/plugins/modules/stacki_appliance_info.py b/common/src/stack/ansible/plugins/modules/stacki_appliance_info.py new file mode 100644 index 000000000..4f8f4637f --- /dev/null +++ b/common/src/stack/ansible/plugins/modules/stacki_appliance_info.py @@ -0,0 +1,99 @@ +# @copyright@ +# Copyright (c) 2006 - 2020 Teradata +# All rights reserved. Stacki(r) v5.x stacki.com +# https://github.com/Teradata/stacki/blob/master/LICENSE.txt +# @copyright@ + +DOCUMENTATION = """ +module: stacki_appliance_info +short_description: Return data about Stacki appliances +description: + - If name is supplied, returns data about a single appliance + - If name is not supplied, returns data about all appliances in the system + +options: + name: + description: + - The name of the appliance to return data about + required: false +""" + +EXAMPLES = """ +- name: Get appliance backend + stacki_appliance_info: + name: backend + register: result + +- name: Get all appliances + stacki_appliance_info: + register: result +""" + +RETURN = """ +appliances: + description: + - List of appliances + returned: on success + type: complex + contains: + name: + description: + - Name of the appliance + type: str + + public: + description: + - True if the appliance is considered public + type: bool +""" + +from stack.bool import str2bool + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.stacki import run_stack_command, StackCommandError + + +def main(): + # Define the arguments for this module + argument_spec = dict( + name=dict(type="str", required=False, default=None) + ) + + # Create our module object + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True + ) + + # Initialize a blank result + result = { + "changed": False, + "appliances": [] + } + + # Bail if the user is just checking syntax of their playbook + if module.check_mode: + module.exit_json(**result) + + # Fetch our appliance info from Stacki + args = [] + if module.params["name"]: + args.append(module.params["name"]) + + try: + for appliance in run_stack_command("list.appliance", args): + # Public needs to be a bool + appliance["public"] = str2bool(appliance["public"]) + + result["appliances"].append(appliance) + + except StackCommandError as e: + # Fetching the data failed + module.fail_json(msg=e.message, **result) + + # Return our data + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/test-framework/test-suites/integration/tests/ansible/test_stacki_appliance_info.py b/test-framework/test-suites/integration/tests/ansible/test_stacki_appliance_info.py new file mode 100644 index 000000000..4da9fac09 --- /dev/null +++ b/test-framework/test-suites/integration/tests/ansible/test_stacki_appliance_info.py @@ -0,0 +1,27 @@ +class TestStackiApplianceInfo: + def test_no_name(self, run_ansible_module): + result = run_ansible_module("stacki_appliance_info") + + assert result.status == "SUCCESS" + assert result.data["changed"] == False + + assert len(result.data["appliances"]) > 1 + + def test_with_name(self, run_ansible_module): + result = run_ansible_module("stacki_appliance_info", name="backend") + + assert result.status == "SUCCESS" + assert result.data["changed"] == False + assert result.data["appliances"] == [{ + "appliance": "backend", + "public": True + }] + + def test_bad_name(self, run_ansible_module): + result = run_ansible_module("stacki_appliance_info", name="foo") + + assert result.status == "FAILED!" + assert result.data["changed"] == False + + assert "error" in result.data["msg"] + assert "not a valid appliance" in result.data["msg"]