forked from jtyr/ansible-ini_inventory
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathini_inventory.py
executable file
·162 lines (129 loc) · 4.2 KB
/
ini_inventory.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env 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 <[email protected]>
#
#####
from ansible.utils.shlex import shlex_split
from ansible.plugins.inventory.ini import InventoryModule
import argparse
import json
import os
import sys
class MyInventoryModule(InventoryModule):
def __init__(self):
pass
def msg(_type, text, exit=0):
sys.stderr.write("%s: %s\n" % (_type, text))
sys.exit(exit)
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',
help='Path to the inventory file')
parser.add_argument(
'--list',
action='store_true',
help='List all groups and hosts')
args = parser.parse_args()
# Get the filename from the command line arguments
if args.filename:
filename = args.filename
elif 'INI_INVENTORY_FILENAME' in os.environ:
filename = os.environ['INI_INVENTORY_FILENAME']
else:
msg('E', 'No inventory file provided.')
try:
f = open(filename)
except Exception as e:
msg('E', 'Cannot open inventory file %s. %s' % (filename, str(e)))
# Some default values
data = {}
group = None
state = None
mim = MyInventoryModule()
# 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 as e:
msg('E', "Error parsing host definition '%s': %s" % (line, e))
(hostnames, port) = mim._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] = mim._parse_value(v)
if state == 'vars':
for key, val in variables.items():
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.items():
data['_meta']['hostvars'][host][key] = val
if args.list:
print(json.dumps(data, sort_keys=True, indent=2))
try:
f.close()
except IOError as e:
msg('E', 'Cannot close inventory file %s. %s' % (filename, str(e)))
if __name__ == '__main__':
main()