Skip to content

Instantly share code, notes, and snippets.

@kshcherban
Created July 10, 2018 07:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kshcherban/256bae174637d9b2cae7c2fb5aeddbe0 to your computer and use it in GitHub Desktop.
Save kshcherban/256bae174637d9b2cae7c2fb5aeddbe0 to your computer and use it in GitHub Desktop.
Script to upgrade autoscaling group
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import boto3
from multiprocessing.dummy import Pool as ThreadPool
import sys
import time
group_name = sys.argv[1]
ag = boto3.client('autoscaling')
def terminate_instance(instance, repeat=60):
""" Repeat terminating call N times """
if repeat == 0:
print('Maximum waiting time exceeded for {0}'.format(instance))
return
else:
try:
response = ag.terminate_instance_in_auto_scaling_group(
InstanceId=instance,
ShouldDecrementDesiredCapacity=False)
except Exception:
return
if response['Activity']['StatusCode'] != 'Successful':
print('Termintating {0}, status {1}'.format(
instance, response['Activity']['StatusCode']))
print('Sleeping 10s, round {0}, instance {1}'.format(repeat, instance))
repeat -= 1
time.sleep(10)
terminate_instance(instance, repeat)
else:
return
# Find attached launch configuration
try:
ag_data = ag.describe_auto_scaling_groups(
AutoScalingGroupNames=[group_name]
)['AutoScalingGroups'][0]
except IndexError:
print('AG {0} not found'.format(group_name))
sys.exit(1)
lauch_config = ag_data['LaunchConfigurationName']
print('AG {0} has launch configuration {1}'.format(group_name, lauch_config))
instance_ids = [i['InstanceId'] for i in ag_data['Instances']]
# Find instances with wrong launch configuration
instance_data = ag.describe_auto_scaling_instances(
InstanceIds=instance_ids,
MaxRecords=50
)['AutoScalingInstances']
to_replace = []
for i in instance_data:
try:
if i['LaunchConfigurationName'] != lauch_config:
print('{0} changes from {1}'.format(i['LaunchConfigurationName']))
print('{0} will be replaced'.format(i['InstanceId']))
to_replace.append(i['InstanceId'])
except KeyError:
print('{0} will be replaced'.format(i['InstanceId']))
to_replace.append(i['InstanceId'])
print('Totally {0} instances will be replaced'.format(len(to_replace)))
# terminate instances one by one, TODO implement batches
threadPool = ThreadPool(processes=2)
threadPool.map(terminate_instance, to_replace)
threadPool.close()
threadPool.join()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment