github.com/greenboxal/deis@v1.12.1/contrib/linode/create-linode-user-data.py (about) 1 #!/usr/bin/env python 2 """ 3 Create CoreOS user-data by merging contrib/coreos/user-data and contrib/linode/linode-user-data-template 4 5 Usage: create-linode-user-data.py 6 """ 7 import base64 8 import sys 9 import os 10 import collections 11 import argparse 12 13 import yaml 14 import colorama 15 from colorama import Fore, Style 16 import requests 17 18 19 def combine_dicts(orig_dict, new_dict): 20 for key, val in new_dict.iteritems(): 21 if isinstance(val, collections.Mapping): 22 tmp = combine_dicts(orig_dict.get(key, {}), val) 23 orig_dict[key] = tmp 24 elif isinstance(val, list): 25 orig_dict[key] = (orig_dict.get(key, []) + val) 26 else: 27 orig_dict[key] = new_dict[key] 28 return orig_dict 29 30 31 def get_file(name, mode="r", abspath=False): 32 current_dir = os.path.dirname(__file__) 33 34 if abspath: 35 return file(os.path.abspath(os.path.join(current_dir, name)), mode) 36 else: 37 return file(os.path.join(current_dir, name), mode) 38 39 40 def main(): 41 colorama.init() 42 43 parser = argparse.ArgumentParser(description='Create Linode User Data') 44 parser.add_argument('--public-key', action='append', required=True, type=file, dest='public_key_files', help='Authorized SSH Keys') 45 parser.add_argument('--etcd-token', required=False, default=None, dest='etcd_token', help='Etcd Token') 46 args = parser.parse_args() 47 48 etcd_token = args.etcd_token 49 if etcd_token is None: 50 etcd_token = generate_etcd_token() 51 else: 52 if not validate_etcd_token(args.etcd_token): 53 raise ValueError('Invalid Etcd Token. You can generate a new token at https://discovery.etcd.io/new.') 54 55 public_keys = [] 56 for public_key_file in args.public_key_files: 57 public_key = public_key_file.read() 58 if validate_public_key(public_key): 59 public_keys.append(public_key) 60 else: 61 log_warning('Invalid public key: ' + public_key_file.name) 62 63 if not len(public_keys) > 0: 64 raise ValueError('Must supply at least one valid public key') 65 66 linode_user_data = get_file("linode-user-data.yaml", "w", True) 67 linode_template = get_file("linode-user-data-template.yaml") 68 coreos_template = get_file("../coreos/user-data.example") 69 70 coreos_template_string = coreos_template.read() 71 coreos_template_string = coreos_template_string.replace('#DISCOVERY_URL', 'https://discovery.etcd.io/' + str(etcd_token)) 72 73 configuration_linode_template = yaml.safe_load(linode_template) 74 configuration_coreos_template = yaml.safe_load(coreos_template_string) 75 76 configuration = combine_dicts(configuration_coreos_template, configuration_linode_template) 77 configuration['ssh_authorized_keys'] = public_keys 78 79 dump = yaml.dump(configuration, default_flow_style=False, default_style='|') 80 81 with linode_user_data as outfile: 82 outfile.write("#cloud-config\n\n" + dump) 83 log_success('Wrote Linode user data to ' + linode_user_data.name) 84 85 86 def validate_public_key(key): 87 try: 88 type, key_string, comment = key.split() 89 data = base64.decodestring(key_string) 90 return data[4:11] == type 91 except: 92 return False 93 94 95 def generate_etcd_token(): 96 log_info('Generating new Etcd token...') 97 data = requests.get('https://discovery.etcd.io/new').text 98 token = data.replace('https://discovery.etcd.io/', '') 99 log_success('Generated new token: ' + token) 100 return token 101 102 103 def validate_etcd_token(token): 104 try: 105 int(token, 16) 106 return True 107 except: 108 return False 109 110 111 def log_info(message): 112 print(Fore.CYAN + message + Fore.RESET) 113 114 115 def log_warning(message): 116 print(Fore.YELLOW + message + Fore.RESET) 117 118 119 def log_success(message): 120 print(Style.BRIGHT + Fore.GREEN + message + Fore.RESET + Style.RESET_ALL) 121 122 123 def log_error(message): 124 print(Style.BRIGHT + Fore.RED + message + Fore.RESET + Style.RESET_ALL) 125 126 127 if __name__ == "__main__": 128 try: 129 main() 130 except Exception as e: 131 log_error(e.message) 132 sys.exit(1)