Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save unacceptable/96a14eacc16eff3fe877bc32910da180 to your computer and use it in GitHub Desktop.
Save unacceptable/96a14eacc16eff3fe877bc32910da180 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
'''
This script will check for instances with tags "start", "shutdown" or "restart"
and will start, stop or restart them based on the time specified in the tag value
relative to the past execution.
'''
import json
import logging
import time
import boto3
ec2 = boto3.client('ec2')
SUPPORTED_ACTIONS = ["start", "shutdown", "restart"]
EXECUTION_INTERVAL = 15 # execution interval in minutes
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
def get_instances():
'''
Get all instances with tags "start", "shutdown" or "restart"
and return a list of dictionaries with the instance id and the tags like the following:
[
{
'InstanceId': 'i-1234567890abcdef0',
'Tags': {
'start': '0800',
'restart': '1200',
'shutdown': '1800'
}
},
...
]
'''
instances = ec2.describe_instances(
Filters=[
{
'Name': 'tag-key',
'Values': SUPPORTED_ACTIONS
}
]
)['Reservations'][0]['Instances']
simplified_list = [
{
'InstanceId': instance['InstanceId'],
'Tags': {
# pylint: disable=line-too-long
tag['Key']: tag['Value'] for tag in instance['Tags'] if tag['Key'] in SUPPORTED_ACTIONS
}
} for instance in instances
]
logging.info(json.dumps(simplified_list, indent=2))
return simplified_list
def validate_time(tag_time):
'''
Validate the time format and values
'''
if len(str(tag_time)) != 4:
logging.error("Time format is not valid")
raise ValueError("Time format is not valid")
if int(str(tag_time)[0:2]) > 24:
logging.error("Hour value is not valid")
raise ValueError("Hour value is not valid")
if int(str(tag_time)[2:4]) > 59:
logging.error("Minute value is not valid")
raise ValueError("Minute value is not valid")
return int(tag_time)
def compare_time(tag_time):
'''
Compare the current time with the time specified in the tag value
and return True if the current time is between the tag time and
the tag time + execution interval
'''
tag_time = validate_time(tag_time)
current_time = int(time.strftime("%H%M", time.localtime()))
logging.info(
"Current time: %s | Tag time: %s | Execution interval: %s",
current_time,
tag_time,
EXECUTION_INTERVAL
)
return current_time >= tag_time and current_time < tag_time + EXECUTION_INTERVAL
def take_action(action, instance_id):
'''
Execute the action for the instance
'''
logging.info("Executing action: %s for instance: %s", action, instance_id)
if action == "start":
ec2.start_instances(InstanceIds=[instance_id])
elif action == "shutdown":
ec2.stop_instances(InstanceIds=[instance_id])
elif action == "restart":
ec2.reboot_instances(InstanceIds=[instance_id])
else:
logging.info("Action not supported")
def main():
'''
Main function
'''
instances = get_instances()
for instance in instances:
for action in SUPPORTED_ACTIONS:
logging.info("Checking for action: %s", action)
if action in instance['Tags'].keys():
logging.info("'%s' tag found for instance %s", action, instance['InstanceId'])
if compare_time(instance['Tags'][action]):
take_action(action, instance['InstanceId'])
else:
logging.info("Nothing to do.")
def lambda_handler(event, context):
'''
Lambda handler
'''
logging.info('Loading function')
logging.info(event)
logging.info(context)
main()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment