#!/usr/bin/env python3 """ Usage: kook-inventory [--list | --host | --import ] [--[no-]synchronization] Create a Kook client, and use it to generate Ansible formatted JSON inventory. In keeping with the Ansible inventory protocol, requires --list or --host. Otherwise this message will be printed. """ import argparse import json import sys from kook.client import KookClient import yaml def merge(m1, m2): return {**m1, **m2} def get_inventory(client): inventory = {} hostvars = {} inventory["_meta"] = {"hostvars": hostvars} # Import hosts for host in client.hosts(): hostvars[host.name] = host.canonicalized_vars(meta=False) for group in client.groups(): inventory[group.name] = {"children": [], "hosts": [], "vars": {}} inventory[group.name]["children"].extend([g.name for g in group.children()]) inventory[group.name]["hosts"].extend([h.name for h in group.hosts()]) return inventory def get_host(client, hostname): host = client.host(hostname) if host: return host.canonicalized_vars() def import_inventory(client, filename): with open(filename, "r") as _f: data = yaml.safe_load(_f) # mapcat out all the group(s) groups = list(data.items()) for groupname, groupdata in groups: groups.extend((groupdata or {}).get("children", {}).items()) # Import all the group(s) for groupname, groupdata in groups: g = client.create_group(groupname) print("Created,", g) if groupdata is None: continue # Import the vars for var, val in groupdata.get("vars", {}).items(): # Fixup my key(s) if var == "ansible_host": var = "host_address" g.set_var(var, val) # Import the direct host bindings for hostname, hostvars in groupdata.get("hosts", {}).items(): h = client.create_host(hostname) h.add_group(g) print(g, "added host", h) for var, val in (hostvars or {}).items(): g.set_host_var(hostname, var, val) # Import the child group(s) for childname, childvars in groupdata.get("children", {}).items(): child = client.create_group(childname) child.add_group(g) # FIXME (arrdem 2019-08-10): # Support group on child group vars? if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--synchronization", dest="use_synchronization", default=True, action="store_true", ) parser.add_argument( "--no-synchronization", dest="use_synchronization", action="store_false" ) parser.add_argument( "--list", action="store_true", dest="list", default=False, help="Output inventory groups and hosts", ) parser.add_argument( "--host", dest="host", default=None, metavar="HOST", help="Output variables only for the given hostname", ) parser.add_argument( "--import", dest="_import", default=None, metavar="IMPORT", help="Import a YAML inventory file", ) parser.add_argument("-b", "--bootstrap", help="Bootstrap servers list to use") args = parser.parse_args(sys.argv[1:]) client = KookClient( hosts=args.bootstrap, use_synchronization=args.use_synchronization ) if args.host: print(json.dumps(get_host(client, args.host), indent=2, sort_keys=True)) elif args.list: print(json.dumps(get_inventory(client), indent=2, sort_keys=True)) elif args._import: import_inventory(client, args._import) else: print(__doc__)