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)