From 34c23caed3366f2296f5bbce1039dcc85fd7f87b Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Thu, 2 Jul 2020 12:11:16 -0400 Subject: [PATCH] make lookup plugin compatible with ansible.tower namespace (#9) --- awx_collection/plugins/inventory/tower.py | 59 +++++++------- awx_collection/plugins/lookup/tower_api.py | 5 +- awx_collection/plugins/modules/tower_meta.py | 78 +++++++++++++++++++ .../tower_lookup_api_plugin/tasks/main.yml | 25 +++--- .../roles/template_galaxy/tasks/main.yml | 11 ++- 5 files changed, 131 insertions(+), 47 deletions(-) create mode 100644 awx_collection/plugins/modules/tower_meta.py diff --git a/awx_collection/plugins/inventory/tower.py b/awx_collection/plugins/inventory/tower.py index 3a650552b6..872e2a3328 100644 --- a/awx_collection/plugins/inventory/tower.py +++ b/awx_collection/plugins/inventory/tower.py @@ -6,36 +6,35 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type DOCUMENTATION = ''' - name: tower - plugin_type: inventory - author: - - Matthew Jones (@matburt) - - Yunfan Zhang (@YunfanZhang42) - short_description: Ansible dynamic inventory plugin for Ansible Tower. - description: - - Reads inventories from Ansible Tower. - - Supports reading configuration from both YAML config file and environment variables. - - If reading from the YAML file, the file name must end with tower.(yml|yaml) or tower_inventory.(yml|yaml), - the path in the command would be /path/to/tower_inventory.(yml|yaml). If some arguments in the config file - are missing, this plugin will try to fill in missing arguments by reading from environment variables. - - If reading configurations from environment variables, the path in the command must be @tower_inventory. - extends_documentation_fragment: - - awx.awx.auth_plugin - options: - inventory_id: - description: - - The ID of the Ansible Tower inventory that you wish to import. - - This is allowed to be either the inventory primary key or its named URL slug. - - Primary key values will be accepted as strings or integers, and URL slugs must be strings. - - Named URL slugs follow the syntax of "inventory_name++organization_name". - type: raw - env: - - name: TOWER_INVENTORY - required: True - include_metadata: - description: Make extra requests to provide all group vars with metadata about the source Ansible Tower host. - type: bool - default: False +name: tower +plugin_type: inventory +author: + - Matthew Jones (@matburt) + - Yunfan Zhang (@YunfanZhang42) +short_description: Ansible dynamic inventory plugin for Ansible Tower. +description: + - Reads inventories from Ansible Tower. + - Supports reading configuration from both YAML config file and environment variables. + - If reading from the YAML file, the file name must end with tower.(yml|yaml) or tower_inventory.(yml|yaml), + the path in the command would be /path/to/tower_inventory.(yml|yaml). If some arguments in the config file + are missing, this plugin will try to fill in missing arguments by reading from environment variables. + - If reading configurations from environment variables, the path in the command must be @tower_inventory. +extends_documentation_fragment: awx.awx.auth_plugin +options: + inventory_id: + description: + - The ID of the Ansible Tower inventory that you wish to import. + - This is allowed to be either the inventory primary key or its named URL slug. + - Primary key values will be accepted as strings or integers, and URL slugs must be strings. + - Named URL slugs follow the syntax of "inventory_name++organization_name". + type: raw + env: + - name: TOWER_INVENTORY + required: True + include_metadata: + description: Make extra requests to provide all group vars with metadata about the source Ansible Tower host. + type: bool + default: False ''' EXAMPLES = ''' diff --git a/awx_collection/plugins/lookup/tower_api.py b/awx_collection/plugins/lookup/tower_api.py index 00205e0146..63e3d30be1 100644 --- a/awx_collection/plugins/lookup/tower_api.py +++ b/awx_collection/plugins/lookup/tower_api.py @@ -12,8 +12,9 @@ requirements: description: - Returns GET requests from the Ansible Tower API. See U(https://docs.ansible.com/ansible-tower/latest/html/towerapi/index.html) for API usage. -extends_documentation_fragment: - - awx.awx.auth_plugin + - For use that is cross-compatible between the awx.awx and ansible.tower collection + see the tower_meta module +extends_documentation_fragment: awx.awx.auth_plugin options: _terms: description: diff --git a/awx_collection/plugins/modules/tower_meta.py b/awx_collection/plugins/modules/tower_meta.py new file mode 100644 index 0000000000..34b4453c18 --- /dev/null +++ b/awx_collection/plugins/modules/tower_meta.py @@ -0,0 +1,78 @@ +#!/usr/bin/python +# coding: utf-8 -*- + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: tower_meta +author: "Alan Rominger (@alancoding)" +short_description: Returns metadata about the collection this module lives in. +description: + - Allows a user to find out what collection this module exists in. + - This takes common module parameters, but does nothing with them. +options: {} +extends_documentation_fragment: awx.awx.auth +''' + + +RETURN = ''' +prefix: + description: Collection namespace and name in the namespace.name format + returned: success + sample: awx.awx +name: + description: Collection name + returned: success + sample: awx +namespace: + description: Collection namespace + returned: success + sample: awx +version: + description: Version of the collection + returned: success + sample: 0.0.1-devel +''' + + +EXAMPLES = ''' +- tower_meta: + register: result + +- name: Show details about the collection + debug: var=result + +- name: Load the UI setting without hard-coding the collection name + debug: + msg: "{{ lookup(result.prefix + '.tower_api', 'settings/ui') }}" +''' + + +from ..module_utils.tower_api import TowerModule + + +def main(): + module = TowerModule(argument_spec={}) + namespace = { + 'awx': 'awx', + 'tower': 'ansible' + }.get(module._COLLECTION_TYPE, 'unknown') + namespace_name = '{0}.{1}'.format(namespace, module._COLLECTION_TYPE) + module.exit_json( + prefix=namespace_name, + name=module._COLLECTION_TYPE, + namespace=namespace, + version=module._COLLECTION_VERSION + ) + + +if __name__ == '__main__': + main() diff --git a/awx_collection/tests/integration/targets/tower_lookup_api_plugin/tasks/main.yml b/awx_collection/tests/integration/targets/tower_lookup_api_plugin/tasks/main.yml index 06d2d18ca9..36325fe9df 100644 --- a/awx_collection/tests/integration/targets/tower_lookup_api_plugin/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_lookup_api_plugin/tasks/main.yml @@ -19,10 +19,13 @@ loop: "{{ usernames }}" register: user_creation_results +- tower_meta: + register: tower_meta + - block: - name: Test too many params (failure from validation of terms) set_fact: - junk: "{{ query('awx.awx.tower_api', 'users', 'teams', query_params={}, ) }}" + junk: "{{ query(tower_meta.prefix + '.tower_api', 'users', 'teams', query_params={}, ) }}" ignore_errors: true register: result @@ -33,7 +36,7 @@ - name: Try to load invalid endpoint set_fact: - junk: "{{ query('awx.awx.tower_api', 'john', query_params={}, ) }}" + junk: "{{ query(tower_meta.prefix + '.tower_api', 'john', query_params={}, ) }}" ignore_errors: true register: result @@ -44,7 +47,7 @@ - name: Load user of a specific name without promoting objects set_fact: - users: "{{ lookup('awx.awx.tower_api', 'users', query_params={ 'username' : user_creation_results['results'][0]['item'] }, return_objects=False) }}" + users: "{{ lookup(tower_meta.prefix + '.tower_api', 'users', query_params={ 'username' : user_creation_results['results'][0]['item'] }, return_objects=False) }}" - assert: that: @@ -56,13 +59,13 @@ assert: that: - item['id'] == user_creation_results['results'][0]['id'] - loop: "{{ query('awx.awx.tower_api', 'users', query_params={ 'username' : user_creation_results['results'][0]['item'] }) }}" + loop: "{{ query(tower_meta.prefix + '.tower_api', 'users', query_params={ 'username' : user_creation_results['results'][0]['item'] }) }}" loop_control: label: "{{ item['id'] }}" - name: Get a page of users as just ids set_fact: - users: "{{ query('awx.awx.tower_api', 'users', query_params={ 'username__endswith': test_id, 'page_size': 2 }, return_ids=True ) }}" + users: "{{ query(tower_meta.prefix + '.tower_api', 'users', query_params={ 'username__endswith': test_id, 'page_size': 2 }, return_ids=True ) }}" - name: Assert that user list has 2 integer ids only assert: @@ -72,7 +75,7 @@ - name: Get all users of a system through next attribute set_fact: - users: "{{ query('awx.awx.tower_api', 'users', query_params={ 'username__endswith': test_id, 'page_size': 1 }, return_all=true ) }}" + users: "{{ query(tower_meta.prefix + '.tower_api', 'users', query_params={ 'username__endswith': test_id, 'page_size': 1 }, return_all=true ) }}" - assert: that: @@ -80,11 +83,11 @@ - name: Get the ID of the first user created and verify that it is correct assert: - that: "{{ query('awx.awx.tower_api', 'users', query_params={ 'username' : user_creation_results['results'][0]['item'] }, return_ids=True) }}[0] == {{ user_creation_results['results'][0]['id'] }}" + that: "{{ query(tower_meta.prefix + '.tower_api', 'users', query_params={ 'username' : user_creation_results['results'][0]['item'] }, return_ids=True) }}[0] == {{ user_creation_results['results'][0]['id'] }}" - name: Try to get an ID of someone who does not exist set_fact: - failed_user_id: "{{ query('awx.awx.tower_api', 'users', query_params={ 'username': 'john jacob jingleheimer schmidt' }, expect_one=True) }}" + failed_user_id: "{{ query(tower_meta.prefix + '.tower_api', 'users', query_params={ 'username': 'john jacob jingleheimer schmidt' }, expect_one=True) }}" register: result ignore_errors: true @@ -95,7 +98,7 @@ - name: Lookup too many users set_fact: - too_many_user_ids: " {{ query('awx.awx.tower_api', 'users', query_params={ 'username__endswith': test_id }, expect_one=True) }}" + too_many_user_ids: " {{ query(tower_meta.prefix + '.tower_api', 'users', query_params={ 'username__endswith': test_id }, expect_one=True) }}" register: results ignore_errors: true @@ -107,11 +110,11 @@ - name: Get the settings page assert: that: - - "'CUSTOM_LOGO' in {{ lookup('awx.awx.tower_api', 'settings/ui' ) }}" + - "'CUSTOM_LOGO' in {{ lookup(tower_meta.prefix + '.tower_api', 'settings/ui' ) }}" - name: Get the ping page set_fact: - ping_data: "{{ lookup('awx.awx.tower_api', 'ping' ) }}" + ping_data: "{{ lookup(tower_meta.prefix + '.tower_api', 'ping' ) }}" register: results - assert: diff --git a/awx_collection/tools/roles/template_galaxy/tasks/main.yml b/awx_collection/tools/roles/template_galaxy/tasks/main.yml index d2f7b2929d..414f55b7de 100644 --- a/awx_collection/tools/roles/template_galaxy/tasks/main.yml +++ b/awx_collection/tools/roles/template_galaxy/tasks/main.yml @@ -11,7 +11,7 @@ replace: path: "{{ collection_path }}/plugins/module_utils/tower_api.py" regexp: '^ _COLLECTION_TYPE = "awx"' - replace: ' _COLLECTION_TYPE = "{{ collection_namespace }}"' + replace: ' _COLLECTION_TYPE = "{{ collection_package }}"' - name: Do file content replacements for non-default namespace or package name block: @@ -19,9 +19,12 @@ - name: Change module doc_fragments to support desired namespace and package names replace: path: "{{ item }}" - regexp: '^extends_documentation_fragment: awx.awx.auth' - replace: 'extends_documentation_fragment: {{ collection_namespace }}.{{ collection_package }}.auth' - with_fileglob: "{{ collection_path }}/plugins/modules/tower_*.py" + regexp: '^extends_documentation_fragment: awx.awx.auth([a-zA-Z0-9_]*)$' + replace: 'extends_documentation_fragment: {{ collection_namespace }}.{{ collection_package }}.auth\1' + with_fileglob: + - "{{ collection_path }}/plugins/inventory/*.py" + - "{{ collection_path }}/plugins/lookup/*.py" + - "{{ collection_path }}/plugins/modules/tower_*.py" loop_control: label: "{{ item | basename }}"