Enable autoloading of inventory plugins (#32709)
* Automatically loads and executes an inventory plugin specified by a standard YAML inventory config file containing a `plugin` key at its root. * Moved inventory PluginLoader to a shared global instance.
This commit is contained in:
parent
abc4210a33
commit
5ff36c3423
5 changed files with 67 additions and 5 deletions
|
@ -29,7 +29,7 @@ from ansible.module_utils._text import to_native
|
||||||
from ansible.module_utils.six import string_types
|
from ansible.module_utils.six import string_types
|
||||||
from ansible.parsing.yaml.dumper import AnsibleDumper
|
from ansible.parsing.yaml.dumper import AnsibleDumper
|
||||||
from ansible.plugins.loader import module_loader, action_loader, lookup_loader, callback_loader, cache_loader, \
|
from ansible.plugins.loader import module_loader, action_loader, lookup_loader, callback_loader, cache_loader, \
|
||||||
vars_loader, connection_loader, strategy_loader, PluginLoader
|
vars_loader, connection_loader, strategy_loader, inventory_loader
|
||||||
from ansible.utils import plugin_docs
|
from ansible.utils import plugin_docs
|
||||||
try:
|
try:
|
||||||
from __main__ import display
|
from __main__ import display
|
||||||
|
@ -97,7 +97,7 @@ class DocCLI(CLI):
|
||||||
elif plugin_type == 'vars':
|
elif plugin_type == 'vars':
|
||||||
loader = vars_loader
|
loader = vars_loader
|
||||||
elif plugin_type == 'inventory':
|
elif plugin_type == 'inventory':
|
||||||
loader = PluginLoader('InventoryModule', 'ansible.plugins.inventory', C.DEFAULT_INVENTORY_PLUGIN_PATH, 'inventory_plugins')
|
loader = inventory_loader
|
||||||
else:
|
else:
|
||||||
loader = module_loader
|
loader = module_loader
|
||||||
|
|
||||||
|
|
|
@ -1239,7 +1239,7 @@ HOST_KEY_CHECKING:
|
||||||
type: boolean
|
type: boolean
|
||||||
INVENTORY_ENABLED:
|
INVENTORY_ENABLED:
|
||||||
name: Active Inventory plugins
|
name: Active Inventory plugins
|
||||||
default: ['host_list', 'script', 'yaml', 'ini']
|
default: ['host_list', 'script', 'yaml', 'ini', 'auto']
|
||||||
description: List of enabled inventory plugins, it also determines the order in which they are used.
|
description: List of enabled inventory plugins, it also determines the order in which they are used.
|
||||||
env: [{name: ANSIBLE_INVENTORY_ENABLED}]
|
env: [{name: ANSIBLE_INVENTORY_ENABLED}]
|
||||||
ini:
|
ini:
|
||||||
|
|
|
@ -30,7 +30,7 @@ from ansible.inventory.data import InventoryData
|
||||||
from ansible.module_utils.six import string_types
|
from ansible.module_utils.six import string_types
|
||||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||||
from ansible.parsing.utils.addresses import parse_address
|
from ansible.parsing.utils.addresses import parse_address
|
||||||
from ansible.plugins.loader import PluginLoader
|
from ansible.plugins.loader import inventory_loader
|
||||||
from ansible.utils.path import unfrackpath
|
from ansible.utils.path import unfrackpath
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -178,7 +178,6 @@ class InventoryManager(object):
|
||||||
def _setup_inventory_plugins(self):
|
def _setup_inventory_plugins(self):
|
||||||
''' sets up loaded inventory plugins for usage '''
|
''' sets up loaded inventory plugins for usage '''
|
||||||
|
|
||||||
inventory_loader = PluginLoader('InventoryModule', 'ansible.plugins.inventory', C.DEFAULT_INVENTORY_PLUGIN_PATH, 'inventory_plugins')
|
|
||||||
display.vvvv('setting up inventory plugins')
|
display.vvvv('setting up inventory plugins')
|
||||||
|
|
||||||
for name in C.INVENTORY_ENABLED:
|
for name in C.INVENTORY_ENABLED:
|
||||||
|
|
56
lib/ansible/plugins/inventory/auto.py
Normal file
56
lib/ansible/plugins/inventory/auto.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
# Copyright (c) 2017 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: auto
|
||||||
|
plugin_type: inventory
|
||||||
|
authors:
|
||||||
|
- Matt Davis <@nitzmahone>
|
||||||
|
short_description: Loads and executes an inventory plugin specified in a YAML config
|
||||||
|
description:
|
||||||
|
- By whitelisting C(auto) as the final inventory plugin, any YAML inventory config file with a
|
||||||
|
C(plugin) key at its root will automatically cause the named plugin to be loaded and executed with that
|
||||||
|
config. This effectively provides automatic whitelisting of all installed/accessible inventory plugins.
|
||||||
|
- To disable this behavior, remove C(auto) from the C(INVENTORY_ENABLED) config element.
|
||||||
|
options:
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
# This plugin is not intended for direct use; it is a fallback mechanism for automatic whitelisting of
|
||||||
|
# all installed inventory plugins.
|
||||||
|
'''
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleParserError
|
||||||
|
from ansible.plugins.inventory import BaseInventoryPlugin
|
||||||
|
from ansible.plugins.loader import inventory_loader
|
||||||
|
|
||||||
|
|
||||||
|
class InventoryModule(BaseInventoryPlugin):
|
||||||
|
|
||||||
|
NAME = 'auto'
|
||||||
|
|
||||||
|
def verify_file(self, path):
|
||||||
|
if not path.endswith('.yml') and not path.endswith('.yaml'):
|
||||||
|
return False
|
||||||
|
return super(InventoryModule, self).verify_file(path)
|
||||||
|
|
||||||
|
def parse(self, inventory, loader, path, cache=True):
|
||||||
|
config_data = loader.load_from_file(path)
|
||||||
|
|
||||||
|
plugin_name = config_data.get('plugin')
|
||||||
|
|
||||||
|
if not plugin_name:
|
||||||
|
raise AnsibleParserError("no root 'plugin' key found, '{0}' is not a valid YAML inventory plugin config file".format(path))
|
||||||
|
|
||||||
|
plugin = inventory_loader.get(plugin_name)
|
||||||
|
|
||||||
|
if not plugin:
|
||||||
|
raise AnsibleParserError("inventory config '{0}' specifies unknown plugin '{1}'".format(path, plugin_name))
|
||||||
|
|
||||||
|
if not plugin.verify_file(path):
|
||||||
|
raise AnsibleParserError("inventory config '{0}' could not be verified by plugin '{1}'".format(path, plugin_name))
|
||||||
|
|
||||||
|
plugin.parse(inventory, loader, path, cache=cache)
|
|
@ -582,3 +582,10 @@ netconf_loader = PluginLoader(
|
||||||
'netconf_plugins',
|
'netconf_plugins',
|
||||||
required_base_class='NetconfBase'
|
required_base_class='NetconfBase'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
inventory_loader = PluginLoader(
|
||||||
|
'InventoryModule',
|
||||||
|
'ansible.plugins.inventory',
|
||||||
|
C.DEFAULT_INVENTORY_PLUGIN_PATH,
|
||||||
|
'inventory_plugins'
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue