#!/usr/bin/env python # (c) 2012, Michael DeHaan # (c) 2013, Serge van Ginderachter # # This file was based on bin/ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . ######################################################## import sys from distutils.version import LooseVersion import yaml import ansible.constants as C from ansible import errors from ansible import inventory from ansible import __version__ try: # ansible 2.0 from ansible.cli import SortedOptParser except ImportError: # ansible 1.x from ansible.utils import SortedOptParser try: # ansible 2.0 from ansible.parsing.utils.jsonify import jsonify from ansible.parsing.yaml.dumper import AnsibleDumper as Dumper except ImportError: # ansible 1.x from ansible.utils import jsonify from yaml import SafeDumper as Dumper ANSIBLE2 = False if LooseVersion(__version__) >= LooseVersion('2'): from ansible.vars import VariableManager from ansible.parsing.dataloader import DataLoader ANSIBLE2 = True ######################################################## def flatten(terms): ret = [] for term in terms: if isinstance(term, list): ret.extend(term) else: ret.append(term) return ret class Cli(object): # ---------------------------------------------- def __init__(self): pass # ---------------------------------------------- def parse(self): ''' create an options parser for bin/ansible ''' parser = SortedOptParser( usage='%prog [options]' ) parser.add_option('-i', '--inventory-file', dest='inventory', help="specify inventory host file (default=%s)" % C.DEFAULT_HOST_LIST, default=C.DEFAULT_HOST_LIST) parser.add_option('--list-hosts', dest='listhosts', action='store_true', help="dump out a list of hosts matching input pattern") parser.add_option('--list-groups', dest='listgroups', action='store_true', help="dump out the list of groups") parser.add_option('-l', '--limit', default=C.DEFAULT_SUBSET, dest='subset', help='further limit selected hosts to an additional pattern') parser.add_option('-y', '--yaml', dest='yaml', action='store_true', help="dump out variables in yaml format") parser.add_option('-j', '--json', dest='json', action='store_true', help="dump out variables in json format (default)") options, args = parser.parse_args() if len(args) == 0 or len(args) > 1: parser.print_help() sys.exit(1) return (options, args) # ---------------------------------------------- def run(self, options, args): pattern = args[0] if ANSIBLE2: loader = DataLoader() variable_manager = VariableManager() I = inventory.Inventory(loader=loader, variable_manager=variable_manager, host_list=options.inventory) else: I = inventory.Inventory(options.inventory) if options.subset: I.subset(options.subset) hosts = I.list_hosts(pattern) groups = I.get_groups() if len(hosts) == 0: print("No hosts matched", file=sys.stderr) sys.exit(1) if options.listhosts: for host in hosts: print('%s' % host) sys.exit(0) if options.listgroups: group_subset = [] for host in hosts: group_subset.append(I.groups_for_host(host)) group_subset = list(set(flatten(group_subset))) for group in group_subset: parents = group.get_ancestors() print('%s (depth %s): parents: %s' % (group.name, group.depth, [ '%s (depth %s)' % (x.name, x.depth) for x in parents ])) sys.exit(0) results = { } for host in hosts: if ANSIBLE2: name = host.get_name() vars = variable_manager.get_vars(loader, host=host)['vars'] else: name = host vars = I.get_variables(host) results.update({name: vars}) return results ######################################################## if __name__ == '__main__': cli = Cli() (options, args) = cli.parse() try: results = cli.run(options, args) except errors.AnsibleError as e: # Generic handler for ansible specific errors print("ERROR: %s" % str(e)) sys.exit(1) if options.json and not options.yaml: print(jsonify(results, format=True)) else: print(yaml.dump(results, Dumper=Dumper, allow_unicode=True))