diff options
Diffstat (limited to 'lib/ansible/plugins/inventory/tower.py')
-rw-r--r-- | lib/ansible/plugins/inventory/tower.py | 221 |
1 files changed, 0 insertions, 221 deletions
diff --git a/lib/ansible/plugins/inventory/tower.py b/lib/ansible/plugins/inventory/tower.py deleted file mode 100644 index f4f20fe509..0000000000 --- a/lib/ansible/plugins/inventory/tower.py +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright (c) 2018 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 = ''' - name: tower - plugin_type: inventory - author: - - Matthew Jones (@matburt) - - Yunfan Zhang (@YunfanZhang42) - short_description: Ansible dynamic inventory plugin for Ansible Tower. - version_added: "2.7" - 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. - options: - plugin: - description: the name of this plugin, it should always be set to 'tower' - for this plugin to recognize it as it's own. - env: - - name: ANSIBLE_INVENTORY_ENABLED - required: True - choices: ['tower'] - host: - description: The network address of your Ansible Tower host. - type: string - env: - - name: TOWER_HOST - required: True - username: - description: The user that you plan to use to access inventories on Ansible Tower. - type: string - env: - - name: TOWER_USERNAME - required: True - password: - description: The password for your Ansible Tower user. - type: string - env: - - name: TOWER_PASSWORD - required: True - 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 - validate_certs: - description: Specify whether Ansible should verify the SSL certificate of Ansible Tower host. - type: bool - default: True - env: - - name: TOWER_VERIFY_SSL - required: False - aliases: [ verify_ssl ] - include_metadata: - description: Make extra requests to provide all group vars with metadata about the source Ansible Tower host. - type: bool - default: False - version_added: "2.8" -''' - -EXAMPLES = ''' -# Before you execute the following commands, you should make sure this file is in your plugin path, -# and you enabled this plugin. - -# Example for using tower_inventory.yml file - -plugin: tower -host: your_ansible_tower_server_network_address -username: your_ansible_tower_username -password: your_ansible_tower_password -inventory_id: the_ID_of_targeted_ansible_tower_inventory -# Then you can run the following command. -# If some of the arguments are missing, Ansible will attempt to read them from environment variables. -# ansible-inventory -i /path/to/tower_inventory.yml --list - -# Example for reading from environment variables: - -# Set environment variables: -# export TOWER_HOST=YOUR_TOWER_HOST_ADDRESS -# export TOWER_USERNAME=YOUR_TOWER_USERNAME -# export TOWER_PASSWORD=YOUR_TOWER_PASSWORD -# export TOWER_INVENTORY=THE_ID_OF_TARGETED_INVENTORY -# Read the inventory specified in TOWER_INVENTORY from Ansible Tower, and list them. -# The inventory path must always be @tower_inventory if you are reading all settings from environment variables. -# ansible-inventory -i @tower_inventory --list -''' - -import re -import os -import json -from ansible.module_utils import six -from ansible.module_utils.urls import Request, urllib_error, ConnectionError, socket, httplib -from ansible.module_utils._text import to_text, to_native -from ansible.errors import AnsibleParserError, AnsibleOptionsError -from ansible.plugins.inventory import BaseInventoryPlugin -from ansible.config.manager import ensure_type - -# Python 2/3 Compatibility -try: - from urlparse import urljoin -except ImportError: - from urllib.parse import urljoin - - -class InventoryModule(BaseInventoryPlugin): - NAME = 'tower' - # Stays backward compatible with tower inventory script. - # 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 - return True - elif super(InventoryModule, self).verify_file(path): - return path.endswith(('tower_inventory.yml', 'tower_inventory.yaml', 'tower.yml', 'tower.yaml')) - else: - return False - - def parse(self, inventory, loader, path, cache=True): - super(InventoryModule, self).parse(inventory, loader, path) - if not self.no_config_file_supplied and os.path.isfile(path): - self._read_config_data(path) - # Read inventory from tower server. - # Note the environment variables will be handled automatically by InventoryManager. - tower_host = self.get_option('host') - if not re.match('(?:http|https)://', tower_host): - tower_host = 'https://{tower_host}'.format(tower_host=tower_host) - - request_handler = Request(url_username=self.get_option('username'), - url_password=self.get_option('password'), - force_basic_auth=True, - validate_certs=self.get_option('validate_certs')) - - # 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 = urljoin(tower_host, inventory_url) - - inventory = self.make_request(request_handler, inventory_url) - # To start with, create all the groups. - for group_name in inventory: - if group_name != '_meta': - self.inventory.add_group(group_name) - - # Then, create all hosts and add the host vars. - all_hosts = inventory['_meta']['hostvars'] - for host_name, host_vars in six.iteritems(all_hosts): - self.inventory.add_host(host_name) - for var_name, var_value in six.iteritems(host_vars): - self.inventory.set_variable(host_name, var_name, var_value) - - # Lastly, create to group-host and group-group relationships, and set group vars. - for group_name, group_content in six.iteritems(inventory): - if group_name != 'all' and group_name != '_meta': - # First add hosts to groups - for host_name in group_content.get('hosts', []): - self.inventory.add_host(host_name, group_name) - # Then add the parent-children group relationships. - for child_group_name in group_content.get('children', []): - self.inventory.add_child(group_name, child_group_name) - # Set the group vars. Note we should set group var for 'all', but not '_meta'. - if group_name != '_meta': - for var_name, var_value in six.iteritems(group_content.get('vars', {})): - self.inventory.set_variable(group_name, var_name, var_value) - - # 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) - server_data = {} - server_data['license_type'] = config_data.get('license_info', {}).get('license_type', 'unknown') - for key in ('version', 'ansible_version'): - server_data[key] = config_data.get(key, 'unknown') - self.inventory.set_variable('all', 'tower_metadata', server_data) - - # Clean up the inventory. - self.inventory.reconcile_inventory() |