-
Notifications
You must be signed in to change notification settings - Fork 5
/
vagrant.py
executable file
·123 lines (94 loc) · 3.09 KB
/
vagrant.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
#!/usr/bin/env bash
# this is a very crude hack and can be removed once we have no more python2 systems
# that need to run this code
"exec" "$(command -v python3 || command -v python)" "$0" "$@"
# Adapted from Mark Mandel's implementation
# https://github.com/ansible/ansible/blob/devel/plugins/inventory/vagrant.py
import argparse
import json
import os
import subprocess
import sys
try:
from StringIO import StringIO # pyright: reportMissingImports=false
except ImportError:
from io import StringIO # pyright: reportMissingImports=false
from collections import defaultdict
try:
DEVNULL = subprocess.DEVNULL
except AttributeError:
DEVNULL = open(os.devnull, 'w')
def parse_args():
parser = argparse.ArgumentParser(description="Vagrant inventory script")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--list', action='store_true')
group.add_argument('--host')
return parser.parse_args()
def get_running_hosts():
try:
subprocess.check_call(["which", "vagrant"], stdout=DEVNULL)
except subprocess.CalledProcessError:
return
cmd = "vagrant status --machine-readable"
status = subprocess.check_output(cmd.split(), universal_newlines=True).rstrip()
for line in status.split('\n'):
if len(line.split(',')) == 4:
(_, host, key, value) = line.split(',')
else:
(_, host, key, value, _) = line.split(',')
if key == 'state' and value in ('active', 'running'):
yield host
def list_running_hosts():
hosts = list(get_running_hosts())
variables = dict(get_configs(hosts))
return {
"_meta": {
"hostvars": variables,
},
"all": {
"hosts": hosts,
},
}
def get_ssh_configs(hosts):
cmd = ['vagrant', 'ssh-config'] + hosts
try:
output = subprocess.check_output(cmd, universal_newlines=True, stderr=DEVNULL)
except subprocess.CalledProcessError:
return None
config = defaultdict(dict)
host = None
for line in output.splitlines():
line = line.strip()
if not line:
continue
key, value = line.split(None, 1)
if key == 'Host':
host = value
elif host:
config[host][key.lower()] = value
return config
def get_host_ssh_config(config, host):
ssh = config.get(host)
return {'ansible_host': ssh['hostname'],
'ansible_port': ssh['port'],
'ansible_user': ssh['user'],
'ansible_ssh_private_key_file': ssh['identityfile']}
def get_configs(hosts):
if not hosts:
return
ssh_configs = get_ssh_configs(hosts)
for host in hosts:
details = {}
if ssh_configs:
details.update(get_host_ssh_config(ssh_configs, host))
yield host, details
def main():
args = parse_args()
if args.list:
hosts = list_running_hosts()
json.dump(hosts, sys.stdout)
elif args.host:
details = dict(get_configs([args.host]))
json.dump(details[args.host], sys.stdout)
if __name__ == '__main__':
main()