From 379959e3acf31cf3543ae83003e98f044d83a3ff Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Thu, 15 Aug 2024 22:51:25 +0200 Subject: [PATCH] Add credential_type module (#240) Signed-off-by: Alina Buzachis Co-authored-by: Abhijeet Kasurde --- .config/dictionary.txt | 3 + meta/runtime.yml | 4 + plugins/module_utils/common.py | 16 ++ plugins/modules/credential_type.py | 173 ++++++++++++++++ plugins/modules/credential_type_info.py | 116 +++++++++++ plugins/modules/project.py | 9 +- plugins/modules/project_info.py | 9 +- .../targets/credential_type/tasks/main.yml | 188 ++++++++++++++++++ 8 files changed, 510 insertions(+), 8 deletions(-) create mode 100644 plugins/module_utils/common.py create mode 100644 plugins/modules/credential_type.py create mode 100644 plugins/modules/credential_type_info.py create mode 100644 tests/integration/targets/credential_type/tasks/main.yml diff --git a/.config/dictionary.txt b/.config/dictionary.txt index 334fad53..a0f24299 100644 --- a/.config/dictionary.txt +++ b/.config/dictionary.txt @@ -56,3 +56,6 @@ Passw AUTHS EDAHTTP refspec +Alina +Buzachis +alinabuzachis diff --git a/meta/runtime.yml b/meta/runtime.yml index 9170d810..92e747a8 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -2,3 +2,7 @@ # https://access.redhat.com/support/policy/updates/ansible-automation-platform # https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix requires_ansible: ">=2.15.0" # AAP 2.4 or newer +action_groups: + eda: + - credential_type + - credential_type_info diff --git a/plugins/module_utils/common.py b/plugins/module_utils/common.py new file mode 100644 index 00000000..06e79f6c --- /dev/null +++ b/plugins/module_utils/common.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +# Copyright: Contributors to the Ansible project +# 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 + + +def to_list_of_dict(result): + if result is None: + return [] + if not isinstance(result, list): + return [result] + return result diff --git a/plugins/modules/credential_type.py b/plugins/modules/credential_type.py new file mode 100644 index 00000000..db75019c --- /dev/null +++ b/plugins/modules/credential_type.py @@ -0,0 +1,173 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: Contributors to the Ansible project +# 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: credential_type +author: + - Alina Buzachis (@alinabuzachis) +short_description: Manage credential types in EDA Controller +description: + - This module allows the user to create, update or delete a credential type in EDA controller. +version_added: 2.0.0 +options: + name: + description: + - The name of the credential type. + type: str + required: true + description: + description: + - The description of the credential type to give more detail about it. + type: str + new_name: + description: + - Setting this option will change the existing name. + type: str + inputs: + description: + - Inputs of the credential type. + type: dict + injectors: + description: + - Injectors of the credential type. + type: dict + state: + description: + - Desired state of the resource. + default: "present" + choices: ["present", "absent"] + type: str +extends_documentation_fragment: + - ansible.eda.eda_controller.auths +""" + + +EXAMPLES = """ + - name: Create a credential type + ansible.eda.credential_type: + name: "Test" + state: present + description: "A test credential type" + inputs: + fields: + - id: "Field1" + type: "string" + label: "Label1" + injectors: + extra_vars: + field1: "field1" + + - name: Delete a credential type + ansible.eda.credential_type: + name: "Test" + state: absent +""" + + +RETURN = """ +id: + description: ID of the credential type. + returned: when exists + type: int + sample: 37 +""" + + +from ansible.module_utils.basic import AnsibleModule + +from ..module_utils.arguments import AUTH_ARGSPEC +from ..module_utils.client import Client +from ..module_utils.controller import Controller +from ..module_utils.errors import EDAError + + +def main(): + argument_spec = dict( + name=dict(type="str", required=True), + new_name=dict(type="str"), + description=dict(type="str"), + inputs=dict(type="dict"), + injectors=dict(type="dict"), + state=dict(choices=["present", "absent"], default="present"), + ) + + argument_spec.update(AUTH_ARGSPEC) + + required_if = [("state", "present", ("inputs", "injectors"))] + + module = AnsibleModule( + argument_spec=argument_spec, required_if=required_if, supports_check_mode=True + ) + + client = Client( + host=module.params.get("controller_host"), + username=module.params.get("controller_username"), + password=module.params.get("controller_password"), + timeout=module.params.get("request_timeout"), + validate_certs=module.params.get("validate_certs"), + ) + + name = module.params.get("name") + new_name = module.params.get("new_name") + description = module.params.get("description") + inputs = module.params.get("inputs") + injectors = module.params.get("injectors") + state = module.params.get("state") + + credential_type_params = {} + if description: + credential_type_params["description"] = description + if inputs: + credential_type_params["inputs"] = inputs + if injectors: + credential_type_params["injectors"] = injectors + + controller = Controller(client, module) + + # Attempt to look up credential_type based on the provided name + try: + credential_type = controller.get_one_or_many("credential-types", name=name) + except EDAError as e: + module.fail_json(msg=f"Failed to get credential type: {e}") + + if state == "absent": + # If the state was absent we can let the module delete it if needed, the module will handle exiting from this + try: + result = controller.delete_if_needed( + credential_type, endpoint="credential-types" + ) + module.exit_json(**result) + except EDAError as e: + module.fail_json(msg=f"Failed to delete credential type: {e}") + + credential_type_params["name"] = ( + new_name + if new_name + else (controller.get_item_name(credential_type) if credential_type else name) + ) + + # If the state was present and we can let the module build or update the existing credential type, + # this will return on its own + try: + result = controller.create_or_update_if_needed( + credential_type, + credential_type_params, + endpoint="credential-types", + item_type="credential type", + ) + module.exit_json(**result) + except EDAError as e: + module.fail_json(msg=f"Failed to create/update credential type: {e}") + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/credential_type_info.py b/plugins/modules/credential_type_info.py new file mode 100644 index 00000000..11b2c6d5 --- /dev/null +++ b/plugins/modules/credential_type_info.py @@ -0,0 +1,116 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: Contributors to the Ansible project +# 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: credential_type_info +author: + - Alina Buzachis (@alinabuzachis) +short_description: List credential types in EDA Controller +description: + - List credential types in EDA controller. +version_added: 2.0.0 +options: + name: + description: + - The name of the credential type. + type: str + required: false +extends_documentation_fragment: + - ansible.eda.eda_controller.auths +""" + + +EXAMPLES = """ + - name: Get information about a credential type + ansible.eda.credential_type_info: + name: "Test" + + - name: List all credential types + ansible.eda.credential_type_info: +""" + + +RETURN = """ +credential_types: + description: Information about the credential types. + returned: always + type: list + elements: dict + sample: [{ + "created_at": "2024-08-14T08:30:14.806638Z", + "description": "A test credential type", + "id": 37, + "injectors": { + "extra_vars": { + "field1": "field1" + } + }, + "inputs": { + "fields": [ + { + "id": "field1", + "label": "Field 5", + "type": "string" + } + ] + }, + "kind": "cloud", + "managed": false, + "modified_at": "2024-08-14T08:30:14.807549Z", + "name": "Example", + "namespace": null + }] +""" + + +from ansible.module_utils.basic import AnsibleModule + +from ..module_utils.arguments import AUTH_ARGSPEC +from ..module_utils.client import Client +from ..module_utils.common import to_list_of_dict +from ..module_utils.controller import Controller +from ..module_utils.errors import EDAError + + +def main(): + argument_spec = dict( + name=dict(type="str", required=False), + ) + + argument_spec.update(AUTH_ARGSPEC) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + + client = Client( + host=module.params.get("controller_host"), + username=module.params.get("controller_username"), + password=module.params.get("controller_password"), + timeout=module.params.get("request_timeout"), + validate_certs=module.params.get("validate_certs"), + ) + + name = module.params.get("name") + controller = Controller(client, module) + + # Attempt to look up credential_type based on the provided name + try: + result = controller.get_one_or_many( + "credential-types", name=name, want_one=False + ) + except EDAError as e: + module.fail_json(msg=f"Failed to get credential type: {e}") + + module.exit_json(credential_types=to_list_of_dict(result)) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/project.py b/plugins/modules/project.py index 970fb4cd..ba47fdc8 100644 --- a/plugins/modules/project.py +++ b/plugins/modules/project.py @@ -82,10 +82,11 @@ """ from ansible.module_utils.basic import AnsibleModule -from ansible_collections.ansible.eda.plugins.module_utils.arguments import AUTH_ARGSPEC -from ansible_collections.ansible.eda.plugins.module_utils.client import Client -from ansible_collections.ansible.eda.plugins.module_utils.controller import Controller -from ansible_collections.ansible.eda.plugins.module_utils.errors import EDAError + +from ..module_utils.arguments import AUTH_ARGSPEC +from ..module_utils.client import Client +from ..module_utils.controller import Controller +from ..module_utils.errors import EDAError def main(): diff --git a/plugins/modules/project_info.py b/plugins/modules/project_info.py index 61baa988..0a1ba8c4 100644 --- a/plugins/modules/project_info.py +++ b/plugins/modules/project_info.py @@ -73,10 +73,11 @@ """ # NOQA from ansible.module_utils.basic import AnsibleModule -from ansible_collections.ansible.eda.plugins.module_utils.arguments import AUTH_ARGSPEC -from ansible_collections.ansible.eda.plugins.module_utils.client import Client -from ansible_collections.ansible.eda.plugins.module_utils.controller import Controller -from ansible_collections.ansible.eda.plugins.module_utils.errors import EDAError + +from ..module_utils.arguments import AUTH_ARGSPEC +from ..module_utils.client import Client +from ..module_utils.controller import Controller +from ..module_utils.errors import EDAError def main(): diff --git a/tests/integration/targets/credential_type/tasks/main.yml b/tests/integration/targets/credential_type/tasks/main.yml new file mode 100644 index 00000000..2f250936 --- /dev/null +++ b/tests/integration/targets/credential_type/tasks/main.yml @@ -0,0 +1,188 @@ +--- +- block: + - set_fact: + credential_defaults: &credential_defaults + controller_username: "{{ controller_username }}" + controller_password: "{{ controller_password }}" + controller_host: "{{ controller_host }}" + validate_certs: false + + - name: Generate a random_string for the test + set_fact: + random_string: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" + when: random_string is not defined + + - name: Generate a ID for the test + set_fact: + test_id: "{{ random_string | to_uuid }}" + when: test_id is not defined + + - name: Define variables for credential and project + set_fact: + credential_type_name: "Test_CredentialType_{{ test_id }}" + new_credential_type_name: "New_Test_CredentialType_{{ test_id }}" + + # CREATE + - name: Create credential type in check mode + ansible.eda.credential_type: + <<: *credential_defaults + name: "{{ credential_type_name }}" + state: present + description: "A test credential type" + inputs: + fields: + - id: "field1" + type: "string" + label: "Field 5" + injectors: + extra_vars: + field1: "field1" + check_mode: true + register: _result + + - name: Check credential type creation in check mode + assert: + that: + - _result.changed + + - name: Create credential type + ansible.eda.credential_type: + <<: *credential_defaults + name: "{{ credential_type_name }}" + state: present + description: "A test credential type" + inputs: + fields: + - id: "field1" + type: "string" + label: "Field 5" + injectors: + extra_vars: + field1: "field1" + register: _result + + - name: Check credential type creation + assert: + that: + - _result.changed + + - name: Create credential type again + ansible.eda.credential_type: + <<: *credential_defaults + name: "{{ credential_type_name }}" + state: present + description: "A test credential type" + inputs: + fields: + - id: "field1" + type: "string" + label: "Field 5" + injectors: + extra_vars: + field1: "field1" + register: _result + + - name: Check credential type is not created again + assert: + that: + - not _result.changed + + - name: Get info about a credential type + ansible.eda.credential_type_info: + <<: *credential_defaults + name: "{{ credential_type_name }}" + + # UPDATE + - name: Update credential type name + ansible.eda.credential_type: + <<: *credential_defaults + name: "{{ credential_type_name }}" + new_name: "{{ new_credential_type_name }}" + state: present + description: "A test credential type" + inputs: + fields: + - id: "field1" + type: "string" + label: "Field 5" + injectors: + extra_vars: + field1: "field1" + register: _result + + - name: Check credential type update + assert: + that: + - _result.changed + + - name: Update credential type again + ansible.eda.credential_type: + <<: *credential_defaults + name: "{{ new_credential_type_name }}" + new_name: "{{ new_credential_type_name }}" + state: present + description: "A test credential type" + inputs: + fields: + - id: "field1" + type: "string" + label: "Field 5" + injectors: + extra_vars: + field1: "field1" + register: _result + + - name: Check credential type is not updated again + assert: + that: + - not _result.changed + + # DELETE + - name: Delete operation type without required name parameter + ansible.eda.credential_type: + <<: *credential_defaults + state: absent + ignore_errors: true + register: _result + + - name: Check if credential type name is required + assert: + that: + - _result.failed + - "'missing required arguments: name' in _result.msg" + + - name: Delete non-existing credential type in check mode + ansible.eda.credential_type: + <<: *credential_defaults + name: "Example2" + state: absent + check_mode: true + register: _result + + - name: Check if delete non-existing credential type in check mode + assert: + that: + - not _result.changed + + - name: Delete credential type + ansible.eda.credential_type: + <<: *credential_defaults + name: "{{ new_credential_type_name }}" + state: absent + register: _result + + - name: Check if delete non-existing credential type + assert: + that: + - _result.changed + + always: + - name: Clean up - credential type + ansible.eda.credential_type: + <<: *credential_defaults + name: "{{ item }}" + state: absent + loop: + - "{{ credential_type_name }}" + - "{{ new_credential_type_name }}" + ignore_errors: true