system-config/playbooks/roles/install-ansible/files/inventory_plugins/yamlgroup.py
Monty Taylor e998db36f2 Add yamlgroup inventory plugin
The constructed inventory plugin allows expressing additional groups,
but it's too heavy weight for our needs. Additionally, it is a full
inventory plugin that will add hosts to the inventory if they don't
exist.

What we want instead is something that will associate existing hosts
(that would have come from another source) with groups.

This also switches to using emergency.yaml instead of emergency, which
uses the same format.

We add an extra groups file for gate testing to ensure the CI nodes
get puppet installed.

Change-Id: Iea8b2eb2e9c723aca06f75d3d3307893e320cced
2018-11-02 08:19:53 +11:00

87 lines
2.7 KiB
Python

# Copyright (c) 2018 Red Hat, Inc.
# GNU General Public License v3.0+ (see COPYING.GPL or https://www.gnu.org/licenses/gpl-3.0.txt)
import fnmatch
import os
from ansible.parsing.yaml.objects import AnsibleMapping
from ansible.plugins.inventory import BaseFileInventoryPlugin
DOCUMENTATION = '''
inventory: yamlgroup
version_added: "2.8"
short_description: Simple group manipulation for existing hosts
description:
- YAML based inventory that only manipulates group membership for
existing hosts.
options:
yaml_extensions:
description: list of 'valid' extensions for files containing YAML
type: list
default: ['.yaml', '.yml', '.json']
env:
- name: ANSIBLE_YAML_FILENAME_EXT
- name: ANSIBLE_INVENTORY_PLUGIN_EXTS
ini:
- key: yaml_valid_extensions
section: defaults
- section: inventory_plugin_yaml
key: yaml_valid_extensions
groups:
description: dict with group name as key and list of fnmatch patterns
type: dict
default: {}
'''
EXAMPLES = '''
plugin: yamlgroup
groups:
amazing:
- fullhost.example.com
- amazing*
'''
class InventoryModule(BaseFileInventoryPlugin):
NAME = 'yamlgroup'
def verify_file(self, path):
valid = False
if super(InventoryModule, self).verify_file(path):
file_name, ext = os.path.splitext(path)
if ext in self.get_option('yaml_extensions'):
valid = True
return valid
def parse(self, inventory, loader, path, cache=True):
''' parses the inventory file '''
super(InventoryModule, self).parse(inventory, loader, path)
self._read_config_data(path)
groups = self.get_option('groups')
found_groups = {}
for group, hosts in groups.items():
if not isinstance(hosts, list):
hosts = [hosts]
for candidate in hosts:
# If someone accidentally puts a dict into the list of hosts,
# the errors are ... obscure at best and the entire inventory
# will fail. Grab the dict key in those cases rather than
# failing.
if isinstance(candidate, AnsibleMapping):
candidate = list(candidate.keys())[0]
for existing in self.inventory.hosts.values():
if fnmatch.fnmatch(existing.get_name(), candidate):
found_groups.setdefault(group, [])
found_groups[group].append(existing)
for group, hosts in found_groups.items():
self.inventory.add_group(group)
for host in hosts:
self.inventory.add_child(group, host.get_name())