From 8113409d3454fe834e0e380d3246ff480201ce0e Mon Sep 17 00:00:00 2001 From: Igor Khomyakov Date: Tue, 21 Jul 2015 17:55:25 +0300 Subject: [PATCH] Refactored. Paramiko module is used to parse ssh_config. Added multi-vm support Added "_meta" element https://docs.ansible.com/ansible/developing_inventory.html#tuning-the-external-inventory-script --- contrib/inventory/vagrant.py | 75 +++++++++++++++++------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/contrib/inventory/vagrant.py b/contrib/inventory/vagrant.py index 7f6dc925e83..10dc61cdb24 100755 --- a/contrib/inventory/vagrant.py +++ b/contrib/inventory/vagrant.py @@ -13,6 +13,7 @@ Example Vagrant configuration using this script: """ # Copyright (C) 2013 Mark Mandel +# 2015 Igor Khomyakov # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -33,17 +34,26 @@ Example Vagrant configuration using this script: # import sys +import os.path import subprocess import re -import string +from paramiko import SSHConfig +from cStringIO import StringIO from optparse import OptionParser +from collections import defaultdict try: import json except: import simplejson as json +_group = 'vagrant' # a default group +_ssh_to_ansible = [('user', 'ansible_ssh_user'), + ('hostname', 'ansible_ssh_host'), + ('identityfile', 'ansible_ssh_private_key_file'), + ('port', 'ansible_ssh_port')] + # Options -#------------------------------ +# ------------------------------ parser = OptionParser(usage="%prog [options] --list | --host ") parser.add_option('--list', default=False, dest="list", action="store_true", @@ -56,19 +66,13 @@ parser.add_option('--host', default=None, dest="host", # helper functions # + # get all the ssh configs for all boxes in an array of dictionaries. def get_ssh_config(): - configs = [] - - boxes = list_running_boxes() + return {k: get_a_ssh_config(k) for k in list_running_boxes()} - for box in boxes: - config = get_a_ssh_config(box) - configs.append(config) - return configs - -#list all the running boxes +# list all the running boxes def list_running_boxes(): output = subprocess.check_output(["vagrant", "status"]).split('\n') @@ -79,54 +83,47 @@ def list_running_boxes(): if matcher: boxes.append(matcher.group(1)) - return boxes -#get the ssh config for a single box + +# get the ssh config for a single box def get_a_ssh_config(box_name): """Gives back a map of all the machine's ssh configurations""" - output = subprocess.check_output(["vagrant", "ssh-config", box_name]).split('\n') + output = subprocess.check_output(["vagrant", "ssh-config", box_name]) + config = SSHConfig() + config.parse(StringIO(output)) + host_config = config.lookup(box_name) - config = {} - for line in output: - if line.strip() != '': - matcher = re.search("( )?([a-zA-Z]+) (.*)", line) - config[matcher.group(2)] = matcher.group(3) - - return config + # man 5 ssh_config: + # > It is possible to have multiple identity files ... + # > all these identities will be tried in sequence. + for id in host_config['identityfile']: + if os.path.isfile(id): + host_config['identityfile'] = id + return {v: host_config[k] for k, v in _ssh_to_ansible} # List out servers that vagrant has running -#------------------------------ +# ------------------------------ if options.list: ssh_config = get_ssh_config() - hosts = { 'vagrant': []} + meta = defaultdict(dict) - for data in ssh_config: - hosts['vagrant'].append(data['HostName']) + for host in ssh_config: + meta['hostvars'][host] = ssh_config[host] - print json.dumps(hosts) + print json.dumps({_group: list(ssh_config.keys()), '_meta': meta}) sys.exit(0) # Get out the host details -#------------------------------ +# ------------------------------ elif options.host: - result = {} - ssh_config = get_ssh_config() - - details = filter(lambda x: (x['HostName'] == options.host), ssh_config) - if len(details) > 0: - #pass through the port, in case it's non standard. - result = details[0] - result['ansible_ssh_port'] = result['Port'] - - print json.dumps(result) + print json.dumps(get_a_ssh_config(options.host)) sys.exit(0) - # Print out help -#------------------------------ +# ------------------------------ else: parser.print_help() sys.exit(0)