100 lines
3.3 KiB
Python
100 lines
3.3 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
|
|
import re
|
|
|
|
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. If the list item starts with a
|
|
^ it will be considered a regex pattern (i.e. passed to
|
|
re.match), otherwise it is considered a fnmatch pattern.
|
|
type: dict
|
|
default: {}
|
|
'''
|
|
EXAMPLES = '''
|
|
plugin: yamlgroup
|
|
groups:
|
|
amazing:
|
|
- fullhost.example.com
|
|
- amazing*
|
|
- ^regex.*pattern
|
|
'''
|
|
|
|
|
|
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]
|
|
|
|
# Starts with ^ means it is already a regex.
|
|
# Otherwise it's a fnmatch compatible string; use it's
|
|
# helper to turn that into a regex so we have a common
|
|
# match below.
|
|
if not candidate.startswith('^'):
|
|
candidate = fnmatch.translate(candidate)
|
|
|
|
for existing in self.inventory.hosts.values():
|
|
if re.match(candidate, existing.get_name()):
|
|
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())
|