Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Ansible dynamic inventory script that reads any Ansible hosts file and transforms it into the JSON data structure.
!/usr/bin/python
#####
#
# Description
# -----------
#
# This is an Ansible dynamic inventory script that reads any Ansible hosts file
# and transforms it into the JSON data structure.
#
# Author
# ------
#
# Jiri Tyr <jiri.tyr@gmail.com> see original from fork
# lightszentip <lightszentip@gmail.com>
#####
from ansible.utils.shlex import shlex_split
from ansible.inventory.ini import InventoryParser
import argparse
import sys,pexpect
import getpass
import json
class MyInventoryParser(InventoryParser):
def __init__(self):
pass
def msg(_type, text, exit=0):
sys.stderr.write("%s: %s\n" % (_type, text))
sys.exit(exit)
def getHostname(dataDict ,host):
return dataDict['_meta']['hostvars'][host]['ansible_ssh_user']+"@"+host+" -p" + str(dataDict['_meta']['hostvars'][host].get('ansible_port', 22))
def ssh_copy_id(pub_key_path ,hostname):
str_ssh = '/usr/bin/ssh-copy-id -i %s %s' %(pub_key_path,hostname)
print str_ssh
child = pexpect.spawn(str_ssh)
try:
index = child.expect(['continue connecting \(yes/no\)', '\'s password:', pexpect.EOF], timeout=20)
if index == 0:
child.sendline('yes')
if index == 1:
passwd2 = getpass.getpass("Enter the Password:")
child.sendline(passwd2)
child.expect('password:')
child.sendline(passwd2)
if index == 2:
print '[ failed ]'
print child.after, child.before
child.close()
except pexpect.TIMEOUT:
print child.read()
child.close()
except pexpect.EOF:
print child.after, child.before
child.close()
#else:
#print 'error'
# child.close()
def main():
# Read command line options
parser = argparse.ArgumentParser(
description=(
'Dynamic inventory script that reads inventory file in the INI '
'format.'))
parser.add_argument(
'--filename',
metavar='filename',
required=True,
help='Path to the inventory file')
parser.add_argument(
'--keypath',
metavar='keypath',
required=True,
help='Path to the id_rsa.pub file')
parser.add_argument(
'--group',
metavar='group',
help='Hosts group from inventory file')
args = parser.parse_args()
# Get the filename from the command line arguments
filename = args.filename
keypath = args.keypath
filterGroupName = args.group
try:
f = open(filename)
except Exception, e:
msg('E', 'Cannot open inventory file %s. %s' % (filename, str(e)))
try:
f2 = open(keypath)
except Exception, e:
msg('E', 'Cannot open keypath file %s. %s' % (keypath, str(e)))
# Some default values
data = {}
group = None
state = None
mip = MyInventoryParser()
# Walk through the file and build the data structure
for line in f:
line = line.strip()
# Skip comments and empty lines
if line.startswith('#') or line.startswith(';') or len(line) == 0:
continue
if line.startswith('['):
# Parse group
section = line[1:-1]
if ':' in line:
group, state = line[1:-1].split(':')
else:
group = section
state = 'hosts'
if group not in data:
data[group] = {}
if state not in data[group]:
if state == 'vars':
data[group][state] = {}
else:
data[group][state] = []
else:
# Parse hosts or group members/vars
try:
tokens = shlex_split(line, comments=True)
except ValueError, e:
msg('E', "Error parsing host definition '%s': %s" % (line, e))
(hostnames, port) = mip._expand_hostpattern(tokens[0])
# Create 'all' group if no group was defined yet
if group is None:
group = 'all'
state = 'hosts'
data['all'] = {
'hosts': []
}
tok = []
if state == 'hosts':
tok = tokens[1:]
elif state == 'vars':
tok = tokens
variables = {}
for t in tok:
if '=' not in t:
msg(
'E',
"Expected key=value host variable assignment, "
"got: %s" % (t))
(k, v) = t.split('=', 1)
variables[k] = mip._parse_value(v)
if state == 'vars':
for key, val in variables.iteritems():
data[group][state][key] = val
else:
for host in hostnames:
data[group][state].append(host)
if state == 'hosts' and len(variables):
if '_meta' not in data:
data['_meta'] = {
'hostvars': {}
}
data['_meta']['hostvars'][host] = {}
for key, val in variables.iteritems():
data['_meta']['hostvars'][host][key] = val
print json.dumps(data, sort_keys=True, indent=2)
try:
f.close()
except IOError, e:
msg('E', 'Cannot close inventory file %s. %s' % (filename, str(e)))
if str(filterGroupName) != 'None':
if data.has_key(filterGroupName):
for hostFromFilterGroupName in data[filterGroupName]['hosts']:
if hostFromFilterGroupName == host:
ssh_copy_id(keypath,getHostname(data,host))
else:
print "Group "+str(filterGroupName)+" is not in inventory file"
else:
for group in data:
if group != '_meta':
for host in data[group]['hosts']:
print host
ssh_copy_id(keypath,getHostname(data,host))
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment