Allow tower inventory plugin to accept integer inventory_id (#62157)

* Allow tower inventory plugin to accept integer inventory_id

* Use to_native for error messages, fix docs typo
pull/62378/head
Alan Rominger 5 years ago committed by Toshio Kuratomi
parent 148cdc1268
commit f273a766b3

@ -0,0 +1,3 @@
---
bugfixes:
- tower inventory plugin - fix TypeError when giving inventory_id as integer (https://github.com/ansible/ansible/issues/61333)

@ -47,8 +47,12 @@ DOCUMENTATION = '''
- name: TOWER_PASSWORD - name: TOWER_PASSWORD
required: True required: True
inventory_id: inventory_id:
description: The ID of the Ansible Tower inventory that you wish to import. description:
type: string - 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: env:
- name: TOWER_INVENTORY - name: TOWER_INVENTORY
required: True required: True
@ -99,9 +103,10 @@ import os
import json import json
from ansible.module_utils import six 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, urllib_error, ConnectionError, socket, httplib
from ansible.module_utils._text import to_native from ansible.module_utils._text import to_text, to_native
from ansible.errors import AnsibleParserError from ansible.errors import AnsibleParserError, AnsibleOptionsError
from ansible.plugins.inventory import BaseInventoryPlugin from ansible.plugins.inventory import BaseInventoryPlugin
from ansible.config.manager import ensure_type
# Python 2/3 Compatibility # Python 2/3 Compatibility
try: try:
@ -122,18 +127,18 @@ class InventoryModule(BaseInventoryPlugin):
try: try:
response = request_handler.get(tower_url) response = request_handler.get(tower_url)
except (ConnectionError, urllib_error.URLError, socket.error, httplib.HTTPException) as e: except (ConnectionError, urllib_error.URLError, socket.error, httplib.HTTPException) as e:
error_msg = 'Connection to remote host failed: {err}'.format(err=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 Tower gives a readable error message, display that message to the user.
if callable(getattr(e, 'read', None)): if callable(getattr(e, 'read', None)):
error_msg += ' with message: {err_msg}'.format(err_msg=e.read()) n_error_msg += ' with message: {err_msg}'.format(err_msg=to_native(e.read()))
raise AnsibleParserError(to_native(error_msg)) raise AnsibleParserError(n_error_msg)
# Attempt to parse JSON. # Attempt to parse JSON.
try: try:
return json.loads(response.read()) return json.loads(response.read())
except (ValueError, TypeError) as e: except (ValueError, TypeError) as e:
# If the JSON parse fails, print the ValueError # If the JSON parse fails, print the ValueError
raise AnsibleParserError(to_native('Failed to parse json from host: {err}'.format(err=e))) raise AnsibleParserError('Failed to parse json from host: {err}'.format(err=to_native(e)))
def verify_file(self, path): def verify_file(self, path):
if path.endswith('@tower_inventory'): if path.endswith('@tower_inventory'):
@ -159,7 +164,19 @@ class InventoryModule(BaseInventoryPlugin):
force_basic_auth=True, force_basic_auth=True,
validate_certs=self.get_option('validate_certs')) validate_certs=self.get_option('validate_certs'))
inventory_id = self.get_option('inventory_id').replace('/', '') # validate type of inventory_id because we allow two types as special case
inventory_id = self.get_option('inventory_id')
if isinstance(inventory_id, int):
inventory_id = to_text(inventory_id, nonstring='simplerepr')
else:
try:
inventory_id = ensure_type(inventory_id, 'str')
except ValueError as e:
raise AnsibleOptionsError(
'Invalid type for configuration option inventory_id, '
'not integer, and cannot convert to string: {err}'.format(err=to_native(e))
)
inventory_id = inventory_id.replace('/', '')
inventory_url = '/api/v2/inventories/{inv_id}/script/?hostvars=1&towervars=1&all=1'.format(inv_id=inventory_id) 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_url = urljoin(tower_host, inventory_url)

Loading…
Cancel
Save