1#!/usr/local/bin/python3.8 2# 3# (c) 2018, Red Hat, Inc. 4# 5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 7from __future__ import (absolute_import, division, print_function) 8__metaclass__ = type 9 10import os 11import sys 12import json 13import argparse 14 15from ansible.parsing.dataloader import DataLoader 16from ansible.module_utils.six import iteritems, raise_from 17from ansible.module_utils._text import to_text 18try: 19 from ansible_collections.community.general.plugins.module_utils.net_tools.nios.api import WapiInventory 20 from ansible_collections.community.general.plugins.module_utils.net_tools.nios.api import normalize_extattrs, flatten_extattrs 21except ImportError as exc: 22 try: 23 # Fallback for Ansible 2.9 24 from ansible.module_utils.net_tools.nios.api import WapiInventory 25 from ansible.module_utils.net_tools.nios.api import normalize_extattrs, flatten_extattrs 26 except ImportError: 27 raise_from( 28 Exception( 29 'This inventory plugin only works with Ansible 2.9, 2.10, or 3, or when community.general is installed correctly in PYTHONPATH.' 30 ' Try using the inventory plugin from infoblox.nios_modules instead.'), 31 exc) 32 33 34CONFIG_FILES = [ 35 os.environ.get('INFOBLOX_CONFIG_FILE', ''), 36 '/usr/local/etc/ansible/infoblox.yaml', 37 '/usr/local/etc/ansible/infoblox.yml' 38] 39 40 41def parse_args(): 42 parser = argparse.ArgumentParser() 43 44 parser.add_argument('--list', action='store_true', 45 help='List host records from NIOS for use in Ansible') 46 47 parser.add_argument('--host', 48 help='List meta data about single host (not used)') 49 50 return parser.parse_args() 51 52 53def main(): 54 args = parse_args() 55 56 for config_file in CONFIG_FILES: 57 if os.path.exists(config_file): 58 break 59 else: 60 sys.stderr.write('unable to locate config file at /usr/local/etc/ansible/infoblox.yaml\n') 61 sys.exit(-1) 62 63 try: 64 loader = DataLoader() 65 config = loader.load_from_file(config_file) 66 provider = config.get('provider') or {} 67 wapi = WapiInventory(provider) 68 except Exception as exc: 69 sys.stderr.write(to_text(exc)) 70 sys.exit(-1) 71 72 if args.host: 73 host_filter = {'name': args.host} 74 else: 75 host_filter = {} 76 77 config_filters = config.get('filters') 78 79 if config_filters.get('view') is not None: 80 host_filter['view'] = config_filters['view'] 81 82 if config_filters.get('extattrs'): 83 extattrs = normalize_extattrs(config_filters['extattrs']) 84 else: 85 extattrs = {} 86 87 hostvars = {} 88 inventory = { 89 '_meta': { 90 'hostvars': hostvars 91 } 92 } 93 94 return_fields = ['name', 'view', 'extattrs', 'ipv4addrs'] 95 96 hosts = wapi.get_object('record:host', 97 host_filter, 98 extattrs=extattrs, 99 return_fields=return_fields) 100 101 if hosts: 102 for item in hosts: 103 view = item['view'] 104 name = item['name'] 105 106 if view not in inventory: 107 inventory[view] = {'hosts': []} 108 109 inventory[view]['hosts'].append(name) 110 111 hostvars[name] = { 112 'view': view 113 } 114 115 if item.get('extattrs'): 116 for key, value in iteritems(flatten_extattrs(item['extattrs'])): 117 if key.startswith('ansible_'): 118 hostvars[name][key] = value 119 else: 120 if 'extattrs' not in hostvars[name]: 121 hostvars[name]['extattrs'] = {} 122 hostvars[name]['extattrs'][key] = value 123 124 sys.stdout.write(json.dumps(inventory, indent=4)) 125 sys.exit(0) 126 127 128if __name__ == '__main__': 129 main() 130