Skip to content

Instantly share code, notes, and snippets.

@lightszentip
Forked from jtyr/hostsfile.py
Last active March 5, 2017 18:58
Show Gist options
  • Save lightszentip/881593f03a7e3d1b107e3be889547941 to your computer and use it in GitHub Desktop.
Save lightszentip/881593f03a7e3d1b107e3be889547941 to your computer and use it in GitHub Desktop.
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