-
Notifications
You must be signed in to change notification settings - Fork 0
/
vagrant_inventory.py
executable file
·134 lines (101 loc) · 3.9 KB
/
vagrant_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
#!/usr/bin/env python3
"""
Vagrant external inventory script. Automatically finds the IP of the booted
vagrant vm(s), and returns it under the host group 'vagrant' with either the
machine name or - if set to default - the directory name of the Vagrantfile
as ansible inventory hostname.
Copyright (C) 2013 Mark Mandel <[email protected]>
2015 Igor Khomyakov <[email protected]>
2021 Christopher Hornberger github.com/chornberger-c2c
GNU General Public License v3.0+ (see LICENSE.md or https://www.gnu.org/licenses/gpl-3.0.txt)
"""
from __future__ import (absolute_import, division, print_function)
import sys
import os.path
import subprocess
import re
import argparse
import json
from collections import defaultdict
from io import StringIO
from ansible.module_utils._text import to_text
from paramiko import SSHConfig
def main():
"""
Thanks to the spacewalk.py inventory script for giving me the basic structure
of this.
"""
global MetaClass
MetaClass = type
# Parse command line options
parser = argparse.ArgumentParser(description="")
parser.add_argument('--list', default=False, dest="list", action="store_true",
help="Produce a JSON consumable grouping of Vagrant servers for Ansible")
parser.add_argument('--host', default=None, dest="host",
help="Generate additional host specific details for given host for Ansible")
options = parser.parse_args()
global mapping
mapping = {}
_GROUP = 'vagrant' # a default group
if options.list:
list_running_boxes()
ssh_config = get_ssh_config()
meta = defaultdict(dict)
for host in ssh_config:
meta['hostvars'][host] = ssh_config[host]
print(json.dumps({_GROUP: list(mapping.values()), '_meta': meta}, indent=4))
sys.exit(0)
elif options.host:
list_running_boxes()
host_id = list(mapping.keys())[list(mapping.values()).index(options.host)]
print(json.dumps(get_a_ssh_config(host_id,options.host), indent=4))
sys.exit(0)
else:
parser.print_help()
sys.exit(0)
def list_running_boxes():
"""
List all running vagrant boxes
"""
output = to_text(subprocess.check_output(["vagrant", "global-status", "--prune"])).split('\n')
for line in output:
match = re.search(r"^([a-zA-Z0-9]+)\s+([^\/\ ]+).*(running).+?([^\/]+$)", line)
if match:
box_id = str(match.group(1))
box_name = str(match.group(2))
box_up = str(match.group(3))
box_dir = str(match.group(4)).strip()
if box_name == "default":
pretty_box_name = box_dir
else:
pretty_box_name = box_name
if box_up == "running":
mapping[box_id] = pretty_box_name
def get_ssh_config():
"""
Returns the ssh config for a box
"""
return dict((v, get_a_ssh_config(k,v)) for k,v in mapping.items())
def get_a_ssh_config(box_id,box_name):
"""
Gives back a map of all the machine's ssh configurations
"""
_ssh_to_ansible = [('user', 'ansible_user'),
('hostname', 'ansible_host'),
('identityfile', 'ansible_private_key_file'),
('port', 'ansible_port')]
output = to_text(subprocess.check_output(["vagrant", "ssh-config", box_id]))
config = SSHConfig()
config.parse(StringIO(output))
host_config = config.lookup(box_name)
if len(host_config) == 1:
host_config = config.lookup('default')
# man 5 ssh_config:
# > It is possible to have multiple identity files ...
# > all these identities will be tried in sequence.
for identity in host_config['identityfile']:
if os.path.isfile(identity):
host_config['identityfile'] = identity
return dict((v, host_config[k]) for k, v in _ssh_to_ansible)
if __name__ == "__main__":
main()