#!/usr/bin/env python ''' Example custom dynamic inventory script for Ansible, in Python. ''' from argparse import ArgumentParser from json import load as json_load, dumps, JSONEncoder from os import remove from os.path import isfile from traceback import print_exc from sys import stderr, argv from risotto.machine import load, TIRAMISU_CACHE, VALUES_CACHE, INFORMATIONS_CACHE, ROUGAIL_NAMESPACE, ROUGAIL_NAMESPACE_DESCRIPTION from tiramisu import Config from tiramisu.error import PropertiesOptionError from rougail.utils import normalize_family from rougail import RougailSystemdTemplate, RougailConfig from rougail.template.base import RougailLeader, RougailExtra DEBUG = False class RougailEncoder(JSONEncoder): def default(self, obj): if isinstance(obj, RougailLeader): return obj._follower if isinstance(obj, RougailExtra): return obj._suboption if isinstance(obj, PropertiesOptionError): return 'PropertiesOptionError' return JSONEncoder.default(self, obj) class RisottoInventory(object): def __init__(self): parser = ArgumentParser() parser.add_argument('--list', action='store_true') parser.add_argument('--host', action='store') parser.add_argument('--nocache', action='store_true') parser.add_argument('--debug', action='store_true') parser.add_argument('--pretty_print', action='store_true') parser.add_argument('--quiet', action='store_true') parser.add_argument('--server', action='store', default=None) self.args = parser.parse_args() if self.args.debug: global DEBUG DEBUG = True def run(self): if self.args.list and self.args.host: raise Exception('cannot have --list and --host together') if self.args.list or self.args.nocache: if isfile(TIRAMISU_CACHE): remove(TIRAMISU_CACHE) if isfile(VALUES_CACHE): remove(VALUES_CACHE) if isfile(INFORMATIONS_CACHE): remove(INFORMATIONS_CACHE) config = load(TIRAMISU_CACHE, VALUES_CACHE, INFORMATIONS_CACHE, ) if self.args.list: return self.do_inventory(config) elif self.args.host: return self.get_vars(config, self.args.host, self.args.server, ) raise Exception('pfff') def do_inventory(self, config: Config, ) -> dict: servers = [subconfig.doc() for subconfig in config.option.list('optiondescription') if subconfig.information.get('module') == 'host'] return dumps({ 'group': { 'hosts': servers, 'vars': { # FIXME # 'ansible_ssh_host': '192.168.0.28', 'ansible_ssh_user': 'root', 'ansible_python_interpreter': '/usr/bin/python3' } } }) def get_vars(self, config: Config, host_name: str, only_server_name: str, ) -> dict: ret = {} rougailconfig = RougailConfig.copy() rougailconfig['variable_namespace'] = ROUGAIL_NAMESPACE rougailconfig['variable_namespace_description'] = ROUGAIL_NAMESPACE_DESCRIPTION for subconfig in config.option.list('optiondescription'): server_name = subconfig.description() module_name = subconfig.option(subconfig.information.get('provider:global:module_name')).value.get() if module_name == 'host' and server_name != host_name: continue engine = RougailSystemdTemplate(subconfig, rougailconfig) engine.load_variables(with_flatten=False) if module_name != 'host' and engine.rougail_variables_dict['general']['host'] != host_name: continue ret[server_name] = engine.rougail_variables_dict if only_server_name is None: ret['modules'] = config.information.get('modules') ret['delete_old_image'] = False ret['configure_host'] = True ret['only_machine'] = None ret['copy_templates'] = False ret['copy_tests'] = False ret['host_install_dir'] = ret[host_name]['general']['host_install_dir'] return dumps(ret, cls=RougailEncoder) else: if only_server_name not in ret: raise Exception(f'cannot find server name "{only_server_name}" in {list(ret)}') return dumps(ret[only_server_name], cls=RougailEncoder) # Get the inventory. def main(): try: inv = RisottoInventory() values = inv.run() if inv.args.pretty_print: from pprint import pprint from json import loads pprint(loads(values)) elif not inv.args.quiet: print(values) except Exception as err: if DEBUG: print_exc() print('---', file=stderr) extra='' else: extra=f'\nmore informations with commandline "{" ".join(argv)} --debug"' print(f'{err}{extra}', file=stderr) exit(1) main()