-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!/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