-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcreate-linode-user-data.py
More file actions
executable file
·130 lines (96 loc) · 3.82 KB
/
create-linode-user-data.py
File metadata and controls
executable file
·130 lines (96 loc) · 3.82 KB
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
#!/usr/bin/env python
"""
Create CoreOS user-data by merging contrib/coreos/user-data and contrib/linode/linode-user-data-template
Usage: create-linode-user-data.py
"""
import base64
import sys
import os
import collections
import argparse
import yaml
import colorama
from colorama import Fore, Style
import requests
def combine_dicts(orig_dict, new_dict):
for key, val in new_dict.iteritems():
if isinstance(val, collections.Mapping):
tmp = combine_dicts(orig_dict.get(key, {}), val)
orig_dict[key] = tmp
elif isinstance(val, list):
orig_dict[key] = (orig_dict.get(key, []) + val)
else:
orig_dict[key] = new_dict[key]
return orig_dict
def get_file(name, mode="r", abspath=False):
current_dir = os.path.dirname(__file__)
if abspath:
return file(os.path.abspath(os.path.join(current_dir, name)), mode)
else:
return file(os.path.join(current_dir, name), mode)
def main():
colorama.init()
parser = argparse.ArgumentParser(description='Create Linode User Data')
parser.add_argument('--public-key', action='append', required=True, type=file, dest='public_key_files', help='Authorized SSH Keys')
parser.add_argument('--etcd-token', required=False, default=None, dest='etcd_token', help='Etcd Token')
args = parser.parse_args()
etcd_token = args.etcd_token
if etcd_token is None:
etcd_token = generate_etcd_token()
else:
if not validate_etcd_token(args.etcd_token):
raise ValueError('Invalid Etcd Token. You can generate a new token at https://discovery.etcd.io/new.')
public_keys = []
for public_key_file in args.public_key_files:
public_key = public_key_file.read()
if validate_public_key(public_key):
public_keys.append(public_key)
else:
log_warning('Invalid public key: ' + public_key_file.name)
if not len(public_keys) > 0:
raise ValueError('Must supply at least one valid public key')
linode_user_data = get_file("linode-user-data.yaml", "w", True)
linode_template = get_file("linode-user-data-template.yaml")
coreos_template = get_file("../coreos/user-data.example")
configuration_linode_template = yaml.safe_load(linode_template)
configuration_coreos_template = yaml.safe_load(coreos_template)
configuration = combine_dicts(configuration_coreos_template, configuration_linode_template)
configuration['ssh_authorized_keys'] = public_keys
dump = yaml.dump(configuration, default_flow_style=False, default_style='|')
dump = dump.replace('#DISCOVERY_URL', 'https://discovery.etcd.io/' + str(etcd_token))
with linode_user_data as outfile:
outfile.write("#cloud-config\n\n" + dump)
log_success('Wrote Linode user data to ' + linode_user_data.name)
def validate_public_key(key):
try:
type, key_string, comment = key.split()
data = base64.decodestring(key_string)
return data[4:11] == type
except:
return False
def generate_etcd_token():
log_info('Generating new Etcd token...')
data = requests.get('https://discovery.etcd.io/new').text
token = data.replace('https://discovery.etcd.io/', '')
log_success('Generated new token: ' + token)
return token
def validate_etcd_token(token):
try:
int(token, 16)
return True
except:
return False
def log_info(message):
print(Fore.CYAN + message + Fore.RESET)
def log_warning(message):
print(Fore.YELLOW + message + Fore.RESET)
def log_success(message):
print(Style.BRIGHT + Fore.GREEN + message + Fore.RESET + Style.RESET_ALL)
def log_error(message):
print(Style.BRIGHT + Fore.RED + message + Fore.RESET + Style.RESET_ALL)
if __name__ == "__main__":
try:
main()
except Exception as e:
log_error(e.message)
sys.exit(1)