-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtidal_inventory.py
executable file
·179 lines (154 loc) · 6.44 KB
/
tidal_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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/env python
import os
import requests
import sys
import json
import yaml
import argparse
import getpass
PY3 = sys.version_info[0] == 3
def fail(msg):
sys.stderr.write("%s\n" % msg)
sys.exit(1)
class Tidal(object):
def __init__(self):
self.args = self._parse_cli_args()
def run(self):
self._get_params()
self._args = self._parse_cli_args()
self.config_file = self._parse_config_file()
self._set_default_config()
Tidal.headers = {"Authorization":"Bearer " + self.login()}
if self.groups is not None:
output = self.get_group_servers()
elif self._args.host is None:
servers = self.get_servers()
output = self.generate_data(servers)
else:
servers = self.get_server()
output = self.generate_data(servers)
self.output_data(output)
def _get_params(self):
API_PREFIX = "/api/v1/"
self.config_path = os.environ.get('CONFIG_PATH')
email = os.environ.get('TIDAL_EMAIL') or self._prompt_for('TIDAL_EMAIL')
password = os.environ.get('TIDAL_PASSWORD') or self._prompt_for('TIDAL_PASSWORD')
domain = os.environ.get('TIDAL_DOMAIN') or self._prompt_for('TIDAL_DOMAIN')
if domain and email and password:
self.email = email
self.domain = domain
self.password = password
self.api_url = "https://" + domain + API_PREFIX
else:
fail("You must provide three environment variables: TIDAL_EMAIL TIDAL_PASSWORD and TIDAL_DOMAIN. The value found for these thee variables was TIDAL_EMAIL: '%s' TIDAL_PASSWORD '%s' and TIDAL_DOMAIN '%s'" % (email, password, domain))
def _prompt_for(self, var):
prompts = {
'TIDAL_EMAIL': 'Tidal E-mail: ',
'TIDAL_PASSWORD': 'Tidal Password: ',
'TIDAL_DOMAIN': 'Tidal domain: '
}
if var == 'TIDAL_PASSWORD':
return getpass.getpass(prompt=prompts[var])
sys.stderr.write(prompts[var])
if PY3:
return input()
else:
return raw_input()
def _parse_config_file(self):
config = dict()
if self.config_path:
if self.config_path and os.path.exists(self.config_path):
with open(self.config_path) as f:
try:
config = yaml.safe_load(f.read())
except Exception as exc:
fail("Error: parsing %s - %s" % (self.config_path, str(exc)))
return config
def _set_default_config(self):
# Set the defaults for the config here. The defaults are used when there is no config file
# or when there is no matching parameter in the config file.
self.property = self.config_file.get("property", "fqdn")
self.filter_tags = self.config_file.get("filter-tags", None)
self.groups = self.config_file.get("groups", None)
def _parse_cli_args(self):
parser = argparse.ArgumentParser(
description='Return Ansible inventory for one or more hosts via the Tidal Migrations API')
parser.add_argument('--list', action='store_true', default=True,
help='List all hosts (default: True)')
parser.add_argument('--host', action='store',
help='Only get information for a specific host.')
parser.add_argument('--pretty', action='store_true', default=False,
help='Pretty print JSON output(default: False)')
return parser.parse_args()
def login(self):
login_uri = self.api_url + "authenticate"
body = {"username": self.email, "password": self.password}
r = requests.post(login_uri, data = body)
return r.json()["access_token"]
def get_servers(self):
if self.filter_tags and self.filter_tags["tags"]:
tags = []
for t in self.filter_tags["tags"]:
tags.append(self.get_tag(t))
ids = ",".join(str(t) for t in tags)
params = {"tag_ids":ids}
if self.filter_tags["logic"]:
params["query_type"] = self.filter_tags["logic"]
else:
params["query_type"] = "All"
s = requests.get(self.api_url + "servers", params = params, headers = self.headers)
else:
s = requests.get(self.api_url + "servers", headers = self.headers)
return s.json()
def get_server(self):
data = self.get_servers()
data = filter(lambda s: s[self.property] == self._args.host, data)
return data
def get_group_servers(self):
groups = self.get_tags()
data = {}
for g, props in groups.iteritems():
tag_ids = ",".join([str(t["id"]) for t in props["tags"]])
params = {"query_type": props["logic"], "tag_ids": tag_ids}
s = requests.get(self.api_url + "servers", params = params, headers = self.headers)
data[g] = s.json()
hostvars = {}
for group, servers in data.iteritems():
data[group] = []
for s in servers:
if s[self.property] is not None:
data[group].append(s[self.property])
hostvars[s[self.property]] = s
response = data
response["_meta"] = {"hostvars": hostvars}
return response
def get_tags(self):
groups = {}
for g, props in self.groups.iteritems():
tags = []
groups[g]= {}
for t in props["tags"]:
tags.append({"name": t, "id": self.get_tag(t)})
groups[g]["tags"] = tags
groups[g]["logic"] = props["logic"]
return groups
def get_tag(self, tag):
r = requests.get(self.api_url + "tags", params = {"search" : tag}, headers = self.headers)
return r.json()[0]["id"]
def generate_data(self, data):
if type(data) is list:
servers = []
hostvars = {}
for s in data:
if s[self.property] is not None:
servers.append(s[self.property])
hostvars[s[self.property]] = s
return {"servers":{"hosts":servers}, "_meta": {"hostvars": hostvars}}
else:
return data
def output_data(self, data):
if self._args.pretty:
print(json.dumps(data, sort_keys=True, indent=2))
else:
print(json.dumps(data))
Tidal().run()