|
# Given the specified parameters in the main() method this will |
|
# find the latest AMI with a specific name (or wildcard prefix e.g. "my-server*") |
|
# and allocate it to an auto scaling group by generating a new launch configuration |
|
# |
|
# In the event there are multiple AMI/snapshots for a specified prefix this will |
|
# also delete old ones, so ensure that you do enter the prefix correctly |
|
# |
|
# Once the AS group has been updated with a new launch configuration this will |
|
# go further to create scheduled events to increase capacity and then decrease it |
|
# in order to push the new AMI in to production. For this to work the AS group |
|
# must be set to first terminate instance with an old launch configuration |
|
# |
|
# The scheduler assumes the user runs in British Summer Time at present as the times in |
|
# AWS seem inconsistent, so it needs to be determined how best to set the time |
|
|
|
import string |
|
import random |
|
import boto3 |
|
import datetime |
|
from pprint import pprint |
|
|
|
def insecure_random_string(string_length): |
|
return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(string_length)) |
|
|
|
|
|
def main(image_name_filter, launch_config_name_starts_with, as_group_name): |
|
ec2 = boto3.client('ec2') |
|
|
|
print "Searching for images using filter "+image_name_filter |
|
images = ec2.describe_images(Filters=[ |
|
{'Name': 'name', 'Values': [image_name_filter]}], Owners=['self']) |
|
|
|
recent_image = False |
|
old_images = [] |
|
for image in images['Images']: |
|
if (not recent_image): |
|
recent_image = image |
|
elif image['CreationDate']>recent_image['CreationDate']: |
|
old_images.append(recent_image) |
|
recent_image = image |
|
else: |
|
old_images.append(image) |
|
|
|
print "Most recent image is "+recent_image['Name']+" ("+recent_image['ImageId']+") created "+recent_image['CreationDate'] |
|
|
|
if not old_images: |
|
print "No old images to remove" |
|
|
|
for old_image in old_images: |
|
old_image_id = old_image['ImageId'] |
|
old_snapshot_id = old_image['BlockDeviceMappings'][0]['Ebs']['SnapshotId'] |
|
print "Deleting old image "+old_image_id+" and snapshot "+old_snapshot_id |
|
ec2.deregister_image(ImageId=old_image_id) |
|
ec2.delete_snapshot(SnapshotId=old_snapshot_id) |
|
|
|
autoscaling = boto3.client('autoscaling') |
|
launch_configs = autoscaling.describe_launch_configurations() |
|
|
|
for launch_config in launch_configs['LaunchConfigurations']: |
|
name = launch_config['LaunchConfigurationName'] |
|
if str.startswith(name, launch_config_name_starts_with): |
|
print("Cloning launch config named "+launch_config['LaunchConfigurationName']) |
|
launch_config['ImageId'] = recent_image['ImageId'] |
|
launch_config['BlockDeviceMappings'][0]['Ebs']['SnapshotId'] = recent_image['BlockDeviceMappings'][0]['Ebs']['SnapshotId'] |
|
launch_config['LaunchConfigurationName'] = recent_image['Name']+'_'+insecure_random_string(4) |
|
del launch_config['LaunchConfigurationARN'] |
|
del launch_config['CreatedTime'] |
|
del launch_config['KernelId'] |
|
del launch_config['RamdiskId'] |
|
print("Creating new launch config as follows") |
|
pprint(launch_config) |
|
autoscaling.create_launch_configuration(**launch_config) |
|
break |
|
|
|
autoscaling.update_auto_scaling_group(AutoScalingGroupName=as_group_name, LaunchConfigurationName=launch_config['LaunchConfigurationName']) |
|
|
|
dev_autoscale = autoscaling.describe_auto_scaling_groups(AutoScalingGroupNames=[ |
|
as_group_name, |
|
])['AutoScalingGroups'][0] |
|
|
|
size = dev_autoscale['DesiredCapacity'] |
|
boost_size = size * 2 |
|
|
|
print "Scheduling with capacity ", boost_size |
|
|
|
if boost_size>1: |
|
autoscaling.put_scheduled_update_group_action( |
|
AutoScalingGroupName=as_group_name, |
|
ScheduledActionName='as-update-boost-'+str(boost_size), |
|
StartTime=(datetime.datetime.now() + datetime.timedelta(minutes=1) - datetime.timedelta(hours=1)), |
|
MinSize=boost_size, |
|
MaxSize=boost_size, |
|
DesiredCapacity=boost_size |
|
) |
|
autoscaling.put_scheduled_update_group_action( |
|
AutoScalingGroupName=as_group_name, |
|
ScheduledActionName='as-update-reduce-'+str(size), |
|
StartTime=(datetime.datetime.now() + datetime.timedelta(minutes=15) - datetime.timedelta(hours=1)), |
|
MinSize=size, |
|
MaxSize=size, |
|
DesiredCapacity=size |