github.com/greenboxal/deis@v1.12.1/contrib/aws/gen-json.py (about) 1 #!/usr/bin/env python 2 import argparse 3 import json 4 import os 5 import urllib2 6 import yaml 7 8 parser = argparse.ArgumentParser() 9 parser.add_argument('--channel', help='the CoreOS channel to use', default='stable') 10 parser.add_argument('--version', help='the CoreOS version to use', default='current') 11 args = vars(parser.parse_args()) 12 13 CURR_DIR = os.path.dirname(os.path.realpath(__file__)) 14 15 # Add AWS-specific units to the shared user-data 16 FORMAT_DOCKER_VOLUME = ''' 17 [Unit] 18 Description=Formats the added EBS volume for Docker 19 ConditionPathExists=!/etc/docker-volume-formatted 20 [Service] 21 Type=oneshot 22 RemainAfterExit=yes 23 ExecStart=/usr/sbin/wipefs -f /dev/xvdf 24 ExecStart=/usr/sbin/mkfs.ext4 -i 4096 -b 4096 /dev/xvdf 25 ExecStart=/bin/touch /etc/docker-volume-formatted 26 ''' 27 MOUNT_DOCKER_VOLUME = ''' 28 [Unit] 29 Description=Mount Docker volume to /var/lib/docker 30 Requires=format-docker-volume.service 31 After=format-docker-volume.service 32 Before=docker.service 33 [Mount] 34 What=/dev/xvdf 35 Where=/var/lib/docker 36 Type=ext4 37 ''' 38 DOCKER_DROPIN = ''' 39 [Unit] 40 Requires=var-lib-docker.mount 41 After=var-lib-docker.mount 42 ''' 43 FORMAT_ETCD_VOLUME = ''' 44 [Unit] 45 Description=Formats the etcd device 46 ConditionPathExists=!/etc/etcd-volume-formatted 47 [Service] 48 Type=oneshot 49 RemainAfterExit=yes 50 ExecStart=/usr/sbin/wipefs -f /dev/xvdg 51 ExecStart=/usr/sbin/mkfs.ext4 -i 4096 -b 4096 /dev/xvdg 52 ExecStart=/bin/touch /etc/etcd-volume-formatted 53 ''' 54 MOUNT_ETCD_VOLUME = ''' 55 [Unit] 56 Description=Mounts the etcd volume 57 Requires=format-etcd-volume.service 58 After=format-etcd-volume.service 59 [Mount] 60 What=/dev/xvdg 61 Where=/media/etcd 62 Type=ext4 63 ''' 64 PREPARE_ETCD_DATA_DIRECTORY = ''' 65 [Unit] 66 Description=Prepares the etcd data directory 67 Requires=media-etcd.mount 68 After=media-etcd.mount 69 Before=etcd2.service 70 [Service] 71 Type=oneshot 72 RemainAfterExit=yes 73 ExecStart=/usr/bin/chown -R etcd:etcd /media/etcd 74 ''' 75 ETCD_DROPIN = ''' 76 [Unit] 77 Requires=prepare-etcd-data-directory.service 78 After=prepare-etcd-data-directory.service 79 ''' 80 81 def coreos_amis(channel, version): 82 url = "http://{channel}.release.core-os.net/amd64-usr/{version}/coreos_production_ami_all.json".format(channel=channel, version=version) 83 try: 84 amis = json.load(urllib2.urlopen(url)) 85 except (IOError, ValueError): 86 print "The URL {} is invalid.".format(url) 87 raise 88 89 return dict(map(lambda n: (n['name'], dict(PV=n['pv'], HVM=n['hvm'])), amis['amis'])) 90 91 new_units = [ 92 dict({'name': 'format-docker-volume.service', 'command': 'start', 'content': FORMAT_DOCKER_VOLUME}), 93 dict({'name': 'var-lib-docker.mount', 'command': 'start', 'content': MOUNT_DOCKER_VOLUME}), 94 dict({'name': 'docker.service', 'drop-ins': [{'name': '90-after-docker-volume.conf', 'content': DOCKER_DROPIN}]}), 95 dict({'name': 'format-etcd-volume.service', 'command': 'start', 'content': FORMAT_ETCD_VOLUME}), 96 dict({'name': 'media-etcd.mount', 'command': 'start', 'content': MOUNT_ETCD_VOLUME}), 97 dict({'name': 'prepare-etcd-data-directory.service', 'command': 'start', 'content': PREPARE_ETCD_DATA_DIRECTORY}), 98 dict({'name': 'etcd2.service', 'drop-ins': [{'name': '90-after-etcd-volume.conf', 'content': ETCD_DROPIN}]}) 99 ] 100 101 with open(os.path.join(CURR_DIR, '..', 'coreos', 'user-data'), 'r') as f: 102 data = yaml.safe_load(f) 103 104 # coreos-cloudinit will start the units in order, so we want these to be processed before etcd/fleet 105 # are started 106 data['coreos']['units'] = new_units + data['coreos']['units'] 107 108 # Point to the right data directory 109 data['coreos']['etcd2']['data-dir'] = '/media/etcd' 110 111 header = ["#cloud-config", "---"] 112 dump = yaml.dump(data, default_flow_style=False) 113 114 template = json.load(open(os.path.join(CURR_DIR, 'deis.template.json'), 'r')) 115 116 template['Resources']['CoreOSServerLaunchConfig']['Properties']['UserData']['Fn::Base64']['Fn::Join'] = ["\n", header + dump.split("\n")] 117 template['Parameters']['ClusterSize']['Default'] = str(os.getenv('DEIS_NUM_INSTANCES', 3)) 118 template['Mappings']['CoreOSAMIs'] = coreos_amis(args['channel'], args['version']) 119 120 VPC_ID = os.getenv('VPC_ID', None) 121 VPC_SUBNETS = os.getenv('VPC_SUBNETS', None) 122 VPC_PRIVATE_SUBNETS = os.getenv('VPC_PRIVATE_SUBNETS', VPC_SUBNETS) 123 VPC_ZONES = os.getenv('VPC_ZONES', None) 124 125 if VPC_ID and VPC_SUBNETS and VPC_ZONES and len(VPC_SUBNETS.split(',')) == len(VPC_ZONES.split(',')): 126 # skip VPC, subnet, route, and internet gateway creation 127 del template['Resources']['VPC'] 128 del template['Resources']['Subnet1'] 129 del template['Resources']['Subnet2'] 130 del template['Resources']['Subnet1RouteTableAssociation'] 131 del template['Resources']['Subnet2RouteTableAssociation'] 132 del template['Resources']['InternetGateway'] 133 del template['Resources']['GatewayToInternet'] 134 del template['Resources']['PublicRouteTable'] 135 del template['Resources']['PublicRoute'] 136 del template['Resources']['CoreOSServerLaunchConfig']['DependsOn'] 137 del template['Resources']['DeisWebELB']['DependsOn'] 138 139 # update VpcId fields 140 template['Resources']['DeisWebELBSecurityGroup']['Properties']['VpcId'] = VPC_ID 141 template['Resources']['VPCSecurityGroup']['Properties']['VpcId'] = VPC_ID 142 143 # update subnets and zones 144 template['Resources']['CoreOSServerAutoScale']['Properties']['AvailabilityZones'] = VPC_ZONES.split(',') 145 template['Resources']['CoreOSServerAutoScale']['Properties']['VPCZoneIdentifier'] = VPC_PRIVATE_SUBNETS.split(',') 146 template['Resources']['DeisWebELB']['Properties']['Subnets'] = VPC_SUBNETS.split(',') 147 148 print json.dumps(template)