From d9e41547a1e528e5ff1a75db818f65d4fc9a3feb Mon Sep 17 00:00:00 2001 From: beeankha Date: Fri, 13 Dec 2019 12:41:40 -0500 Subject: [PATCH 1/6] Refactor Inventory Plugin module to import from module_utils --- awx_collection/plugins/inventory/tower.py | 27 +++--------------- .../plugins/module_utils/ansible_tower.py | 28 ++++++++++++++++++- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/awx_collection/plugins/inventory/tower.py b/awx_collection/plugins/inventory/tower.py index 2cc35b339d..044eb09dd1 100644 --- a/awx_collection/plugins/inventory/tower.py +++ b/awx_collection/plugins/inventory/tower.py @@ -98,15 +98,15 @@ inventory_id: the_ID_of_targeted_ansible_tower_inventory # ansible-inventory -i @tower_inventory --list ''' -import re import os -import json +import re from ansible.module_utils import six -from ansible.module_utils.urls import Request, urllib_error, ConnectionError, socket, httplib +from ansible.module_utils.urls import Request from ansible.module_utils._text import to_text, to_native -from ansible.errors import AnsibleParserError, AnsibleOptionsError +from ansible.errors import AnsibleOptionsError from ansible.plugins.inventory import BaseInventoryPlugin from ansible.config.manager import ensure_type +from ..module_utils.ansible_tower import make_request # Python 2/3 Compatibility try: @@ -121,25 +121,6 @@ class InventoryModule(BaseInventoryPlugin): # If the user supplies '@tower_inventory' as path, the plugin will read from environment variables. no_config_file_supplied = False - def make_request(self, request_handler, tower_url): - """Makes the request to given URL, handles errors, returns JSON - """ - try: - response = request_handler.get(tower_url) - except (ConnectionError, urllib_error.URLError, socket.error, httplib.HTTPException) as e: - n_error_msg = 'Connection to remote host failed: {err}'.format(err=to_native(e)) - # If Tower gives a readable error message, display that message to the user. - if callable(getattr(e, 'read', None)): - n_error_msg += ' with message: {err_msg}'.format(err_msg=to_native(e.read())) - raise AnsibleParserError(n_error_msg) - - # Attempt to parse JSON. - try: - return json.loads(response.read()) - except (ValueError, TypeError) as e: - # If the JSON parse fails, print the ValueError - raise AnsibleParserError('Failed to parse json from host: {err}'.format(err=to_native(e))) - def verify_file(self, path): if path.endswith('@tower_inventory'): self.no_config_file_supplied = True diff --git a/awx_collection/plugins/module_utils/ansible_tower.py b/awx_collection/plugins/module_utils/ansible_tower.py index 97dff798a9..52be49babe 100644 --- a/awx_collection/plugins/module_utils/ansible_tower.py +++ b/awx_collection/plugins/module_utils/ansible_tower.py @@ -29,8 +29,12 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type +import json import os import traceback +from ansible.module_utils._text import to_native +from ansible.module_utils.urls import Request, urllib_error, ConnectionError, socket, httplib +from ansible.errors import AnsibleParserError TOWER_CLI_IMP_ERR = None try: @@ -46,8 +50,30 @@ except ImportError: from ansible.module_utils.basic import AnsibleModule, missing_required_lib +def make_request(self, request_handler, tower_url): + ''' + Makes the request to given URL, handles errors, returns JSON + ''' + try: + response = request_handler.get(tower_url) + except (ConnectionError, urllib_error.URLError, socket.error, httplib.HTTPException) as e: + n_error_msg = 'Connection to remote host failed: {err}'.format(err=to_native(e)) + # If Tower gives a readable error message, display that message to the user. + if callable(getattr(e, 'read', None)): + n_error_msg += ' with message: {err_msg}'.format(err_msg=to_native(e.read())) + raise AnsibleParserError(n_error_msg) + + # Attempt to parse JSON. + try: + return json.loads(response.read()) + except (ValueError, TypeError) as e: + # If the JSON parse fails, print the ValueError + raise AnsibleParserError('Failed to parse json from host: {err}'.format(err=to_native(e))) + + def tower_auth_config(module): - '''tower_auth_config attempts to load the tower-cli.cfg file + ''' + `tower_auth_config` attempts to load the tower-cli.cfg file specified from the `tower_config_file` parameter. If found, if returns the contents of the file as a dictionary, else it will attempt to fetch values from the module params and From 61c2968a7c99cfdf478a79449d1d2819bad7902d Mon Sep 17 00:00:00 2001 From: beeankha Date: Fri, 13 Dec 2019 15:50:48 -0500 Subject: [PATCH 2/6] Fix module-specific lint errors --- awx_collection/plugins/inventory/tower.py | 4 ++-- awx_collection/plugins/module_utils/ansible_tower.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/awx_collection/plugins/inventory/tower.py b/awx_collection/plugins/inventory/tower.py index 044eb09dd1..01bc781558 100644 --- a/awx_collection/plugins/inventory/tower.py +++ b/awx_collection/plugins/inventory/tower.py @@ -161,7 +161,7 @@ class InventoryModule(BaseInventoryPlugin): inventory_url = '/api/v2/inventories/{inv_id}/script/?hostvars=1&towervars=1&all=1'.format(inv_id=inventory_id) inventory_url = urljoin(tower_host, inventory_url) - inventory = self.make_request(request_handler, inventory_url) + inventory = make_request(request_handler, inventory_url) # To start with, create all the groups. for group_name in inventory: if group_name != '_meta': @@ -191,7 +191,7 @@ class InventoryModule(BaseInventoryPlugin): # Fetch extra variables if told to do so if self.get_option('include_metadata'): config_url = urljoin(tower_host, '/api/v2/config/') - config_data = self.make_request(request_handler, config_url) + config_data = make_request(request_handler, config_url) server_data = {} server_data['license_type'] = config_data.get('license_info', {}).get('license_type', 'unknown') for key in ('version', 'ansible_version'): diff --git a/awx_collection/plugins/module_utils/ansible_tower.py b/awx_collection/plugins/module_utils/ansible_tower.py index 52be49babe..495d60e39c 100644 --- a/awx_collection/plugins/module_utils/ansible_tower.py +++ b/awx_collection/plugins/module_utils/ansible_tower.py @@ -33,7 +33,7 @@ import json import os import traceback from ansible.module_utils._text import to_native -from ansible.module_utils.urls import Request, urllib_error, ConnectionError, socket, httplib +from ansible.module_utils.urls import urllib_error, ConnectionError, socket, httplib from ansible.errors import AnsibleParserError TOWER_CLI_IMP_ERR = None @@ -50,7 +50,7 @@ except ImportError: from ansible.module_utils.basic import AnsibleModule, missing_required_lib -def make_request(self, request_handler, tower_url): +def make_request(module, request_handler, tower_url): ''' Makes the request to given URL, handles errors, returns JSON ''' From c532c6fe619d2df2cafd21040778bd32d30e21df Mon Sep 17 00:00:00 2001 From: beeankha Date: Wed, 18 Dec 2019 11:14:10 -0500 Subject: [PATCH 3/6] Update parameters, add whitespace --- awx_collection/plugins/inventory/tower.py | 2 ++ awx_collection/plugins/module_utils/ansible_tower.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/awx_collection/plugins/inventory/tower.py b/awx_collection/plugins/inventory/tower.py index 01bc781558..6785d738aa 100644 --- a/awx_collection/plugins/inventory/tower.py +++ b/awx_collection/plugins/inventory/tower.py @@ -100,12 +100,14 @@ inventory_id: the_ID_of_targeted_ansible_tower_inventory import os import re + from ansible.module_utils import six from ansible.module_utils.urls import Request from ansible.module_utils._text import to_text, to_native from ansible.errors import AnsibleOptionsError from ansible.plugins.inventory import BaseInventoryPlugin from ansible.config.manager import ensure_type + from ..module_utils.ansible_tower import make_request # Python 2/3 Compatibility diff --git a/awx_collection/plugins/module_utils/ansible_tower.py b/awx_collection/plugins/module_utils/ansible_tower.py index 495d60e39c..e3972fb7d8 100644 --- a/awx_collection/plugins/module_utils/ansible_tower.py +++ b/awx_collection/plugins/module_utils/ansible_tower.py @@ -32,6 +32,7 @@ __metaclass__ = type import json import os import traceback + from ansible.module_utils._text import to_native from ansible.module_utils.urls import urllib_error, ConnectionError, socket, httplib from ansible.errors import AnsibleParserError @@ -50,7 +51,7 @@ except ImportError: from ansible.module_utils.basic import AnsibleModule, missing_required_lib -def make_request(module, request_handler, tower_url): +def make_request(request_handler, tower_url): ''' Makes the request to given URL, handles errors, returns JSON ''' From 63ffff3b760f5927e38acf86b10e49b2ef2e998c Mon Sep 17 00:00:00 2001 From: beeankha Date: Fri, 20 Dec 2019 08:53:02 -0500 Subject: [PATCH 4/6] Import request into module_utils instead --- awx_collection/plugins/inventory/tower.py | 3 +-- awx_collection/plugins/module_utils/ansible_tower.py | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/awx_collection/plugins/inventory/tower.py b/awx_collection/plugins/inventory/tower.py index 6785d738aa..ad463434eb 100644 --- a/awx_collection/plugins/inventory/tower.py +++ b/awx_collection/plugins/inventory/tower.py @@ -102,13 +102,12 @@ import os import re from ansible.module_utils import six -from ansible.module_utils.urls import Request from ansible.module_utils._text import to_text, to_native from ansible.errors import AnsibleOptionsError from ansible.plugins.inventory import BaseInventoryPlugin from ansible.config.manager import ensure_type -from ..module_utils.ansible_tower import make_request +from ..module_utils.ansible_tower import make_request, Request # Python 2/3 Compatibility try: diff --git a/awx_collection/plugins/module_utils/ansible_tower.py b/awx_collection/plugins/module_utils/ansible_tower.py index e3972fb7d8..692ad49ced 100644 --- a/awx_collection/plugins/module_utils/ansible_tower.py +++ b/awx_collection/plugins/module_utils/ansible_tower.py @@ -35,6 +35,7 @@ import traceback from ansible.module_utils._text import to_native from ansible.module_utils.urls import urllib_error, ConnectionError, socket, httplib +from ansible.module_utils.urls import Request # noqa (the sole purpose of this line is to allow for import into other files) from ansible.errors import AnsibleParserError TOWER_CLI_IMP_ERR = None From 0c696bfd96dc85001384d3cef96b066cc3877cdd Mon Sep 17 00:00:00 2001 From: beeankha Date: Mon, 6 Jan 2020 12:01:48 -0500 Subject: [PATCH 5/6] Add new CollectionsParserError class for exceptions --- awx_collection/plugins/module_utils/ansible_tower.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/awx_collection/plugins/module_utils/ansible_tower.py b/awx_collection/plugins/module_utils/ansible_tower.py index 692ad49ced..0cee7f4e6c 100644 --- a/awx_collection/plugins/module_utils/ansible_tower.py +++ b/awx_collection/plugins/module_utils/ansible_tower.py @@ -35,8 +35,7 @@ import traceback from ansible.module_utils._text import to_native from ansible.module_utils.urls import urllib_error, ConnectionError, socket, httplib -from ansible.module_utils.urls import Request # noqa (the sole purpose of this line is to allow for import into other files) -from ansible.errors import AnsibleParserError +from ansible.module_utils.urls import Request # noqa TOWER_CLI_IMP_ERR = None try: @@ -63,14 +62,14 @@ def make_request(request_handler, tower_url): # If Tower gives a readable error message, display that message to the user. if callable(getattr(e, 'read', None)): n_error_msg += ' with message: {err_msg}'.format(err_msg=to_native(e.read())) - raise AnsibleParserError(n_error_msg) + raise CollectionsParserError(n_error_msg) # Attempt to parse JSON. try: return json.loads(response.read()) except (ValueError, TypeError) as e: # If the JSON parse fails, print the ValueError - raise AnsibleParserError('Failed to parse json from host: {err}'.format(err=to_native(e))) + raise CollectionsParserError('Failed to parse json from host: {err}'.format(err=to_native(e))) def tower_auth_config(module): @@ -142,3 +141,7 @@ class TowerModule(AnsibleModule): if not HAS_TOWER_CLI: self.fail_json(msg=missing_required_lib('ansible-tower-cli'), exception=TOWER_CLI_IMP_ERR) + + +class CollectionsParserError(Exception): + pass From b19e5aab28df7afd3560d5c516d48793e97bb570 Mon Sep 17 00:00:00 2001 From: beeankha Date: Thu, 9 Jan 2020 15:30:23 -0500 Subject: [PATCH 6/6] Raise AnsibleParserError via a custom exception --- awx_collection/plugins/inventory/tower.py | 17 +++++++++++++---- .../plugins/module_utils/ansible_tower.py | 8 ++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/awx_collection/plugins/inventory/tower.py b/awx_collection/plugins/inventory/tower.py index ad463434eb..7ed641eefc 100644 --- a/awx_collection/plugins/inventory/tower.py +++ b/awx_collection/plugins/inventory/tower.py @@ -103,11 +103,11 @@ import re from ansible.module_utils import six from ansible.module_utils._text import to_text, to_native -from ansible.errors import AnsibleOptionsError +from ansible.errors import AnsibleParserError, AnsibleOptionsError from ansible.plugins.inventory import BaseInventoryPlugin from ansible.config.manager import ensure_type -from ..module_utils.ansible_tower import make_request, Request +from ..module_utils.ansible_tower import make_request, CollectionsParserError, Request # Python 2/3 Compatibility try: @@ -162,7 +162,11 @@ class InventoryModule(BaseInventoryPlugin): inventory_url = '/api/v2/inventories/{inv_id}/script/?hostvars=1&towervars=1&all=1'.format(inv_id=inventory_id) inventory_url = urljoin(tower_host, inventory_url) - inventory = make_request(request_handler, inventory_url) + try: + inventory = make_request(request_handler, inventory_url) + except CollectionsParserError as e: + raise AnsibleParserError(to_native(e)) + # To start with, create all the groups. for group_name in inventory: if group_name != '_meta': @@ -192,7 +196,12 @@ class InventoryModule(BaseInventoryPlugin): # Fetch extra variables if told to do so if self.get_option('include_metadata'): config_url = urljoin(tower_host, '/api/v2/config/') - config_data = make_request(request_handler, config_url) + + try: + config_data = make_request(request_handler, config_url) + except CollectionsParserError as e: + raise AnsibleParserError(to_native(e)) + server_data = {} server_data['license_type'] = config_data.get('license_info', {}).get('license_type', 'unknown') for key in ('version', 'ansible_version'): diff --git a/awx_collection/plugins/module_utils/ansible_tower.py b/awx_collection/plugins/module_utils/ansible_tower.py index 0cee7f4e6c..f1738a54bf 100644 --- a/awx_collection/plugins/module_utils/ansible_tower.py +++ b/awx_collection/plugins/module_utils/ansible_tower.py @@ -51,6 +51,10 @@ except ImportError: from ansible.module_utils.basic import AnsibleModule, missing_required_lib +class CollectionsParserError(Exception): + pass + + def make_request(request_handler, tower_url): ''' Makes the request to given URL, handles errors, returns JSON @@ -141,7 +145,3 @@ class TowerModule(AnsibleModule): if not HAS_TOWER_CLI: self.fail_json(msg=missing_required_lib('ansible-tower-cli'), exception=TOWER_CLI_IMP_ERR) - - -class CollectionsParserError(Exception): - pass