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
This commit is contained in:
Igor Khomyakov 2015-07-21 17:55:25 +03:00
parent 827b0443c8
commit 8113409d34

View file

@ -13,6 +13,7 @@ Example Vagrant configuration using this script:
""" """
# Copyright (C) 2013 Mark Mandel <mark@compoundtheory.com> # Copyright (C) 2013 Mark Mandel <mark@compoundtheory.com>
# 2015 Igor Khomyakov <homyakov@gmail.com>
# #
# This program is free software: you can redistribute it and/or modify # 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 # 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 sys
import os.path
import subprocess import subprocess
import re import re
import string from paramiko import SSHConfig
from cStringIO import StringIO
from optparse import OptionParser from optparse import OptionParser
from collections import defaultdict
try: try:
import json import json
except: except:
import simplejson as json 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 # Options
#------------------------------ # ------------------------------
parser = OptionParser(usage="%prog [options] --list | --host <machine>") parser = OptionParser(usage="%prog [options] --list | --host <machine>")
parser.add_option('--list', default=False, dest="list", action="store_true", 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 # helper functions
# #
# get all the ssh configs for all boxes in an array of dictionaries. # get all the ssh configs for all boxes in an array of dictionaries.
def get_ssh_config(): def get_ssh_config():
configs = [] return {k: get_a_ssh_config(k) for k in list_running_boxes()}
boxes = list_running_boxes()
for box in boxes: # list all the running boxes
config = get_a_ssh_config(box)
configs.append(config)
return configs
#list all the running boxes
def list_running_boxes(): def list_running_boxes():
output = subprocess.check_output(["vagrant", "status"]).split('\n') output = subprocess.check_output(["vagrant", "status"]).split('\n')
@ -79,54 +83,47 @@ def list_running_boxes():
if matcher: if matcher:
boxes.append(matcher.group(1)) boxes.append(matcher.group(1))
return boxes 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): def get_a_ssh_config(box_name):
"""Gives back a map of all the machine's ssh configurations""" """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 = {} # man 5 ssh_config:
for line in output: # > It is possible to have multiple identity files ...
if line.strip() != '': # > all these identities will be tried in sequence.
matcher = re.search("( )?([a-zA-Z]+) (.*)", line) for id in host_config['identityfile']:
config[matcher.group(2)] = matcher.group(3) if os.path.isfile(id):
host_config['identityfile'] = id
return config
return {v: host_config[k] for k, v in _ssh_to_ansible}
# List out servers that vagrant has running # List out servers that vagrant has running
#------------------------------ # ------------------------------
if options.list: if options.list:
ssh_config = get_ssh_config() ssh_config = get_ssh_config()
hosts = { 'vagrant': []} meta = defaultdict(dict)
for data in ssh_config: for host in ssh_config:
hosts['vagrant'].append(data['HostName']) meta['hostvars'][host] = ssh_config[host]
print json.dumps(hosts) print json.dumps({_group: list(ssh_config.keys()), '_meta': meta})
sys.exit(0) sys.exit(0)
# Get out the host details # Get out the host details
#------------------------------ # ------------------------------
elif options.host: elif options.host:
result = {} print json.dumps(get_a_ssh_config(options.host))
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)
sys.exit(0) sys.exit(0)
# Print out help # Print out help
#------------------------------ # ------------------------------
else: else:
parser.print_help() parser.print_help()
sys.exit(0) sys.exit(0)