# Taken initially from https://aws.amazon.com/premiumsupport/knowledge-center/attach-second-eni-auto-scaling/ # This code is intended as an example for a blog post by Alex Addison / Lexis Nexis # In order to use it, you will need to replace the interface ID (marked #TODO) import boto3 import botocore from datetime import datetime ec2_client = boto3.client('ec2') asg_client = boto3.client('autoscaling') def lambda_handler(event, context): if event["detail-type"] == "EC2 Instance-launch Lifecycle Action": instance_id = event['detail']['EC2InstanceId'] LifecycleHookName=event['detail']['LifecycleHookName'] AutoScalingGroupName=event['detail']['AutoScalingGroupName'] subnet_id = get_subnet_id(instance_id) interface_id = "eni-0123456789abcdef" #TODO specify or find interface attachment = attach_interface(interface_id, instance_id) if not interface_id or not attachment: complete_lifecycle_action_failure(LifecycleHookName,AutoScalingGroupName,instance_id) else: complete_lifecycle_action_success(LifecycleHookName,AutoScalingGroupName,instance_id) def get_subnet_id(instance_id): try: result = ec2_client.describe_instances(InstanceIds=[instance_id]) vpc_subnet_id = result['Reservations'][0]['Instances'][0]['SubnetId'] log("Subnet id: {}".format(vpc_subnet_id)) except botocore.exceptions.ClientError as e: log("Error describing the instance {}: {}".format(instance_id, e.response['Error'])) vpc_subnet_id = None return vpc_subnet_id def attach_interface(network_interface_id, instance_id): attachment = None if network_interface_id and instance_id: try: attach_interface = ec2_client.attach_network_interface( NetworkInterfaceId=network_interface_id, InstanceId=instance_id, DeviceIndex=1 ) attachment = attach_interface['AttachmentId'] log("Created network attachment: {}".format(attachment)) except botocore.exceptions.ClientError as e: log("Error attaching network interface: {}".format(e.response['Error'])) return attachment def complete_lifecycle_action_success(hookname,groupname,instance_id): try: asg_client.complete_lifecycle_action( LifecycleHookName=hookname, AutoScalingGroupName=groupname, InstanceId=instance_id, LifecycleActionResult='CONTINUE' ) log("Lifecycle hook CONTINUEd for: {}".format(instance_id)) except botocore.exceptions.ClientError as e: log("Error completing life cycle hook for instance {}: {}".format(instance_id, e.response['Error'])) log('{"Error": "1"}') def complete_lifecycle_action_failure(hookname,groupname,instance_id): try: asg_client.complete_lifecycle_action( LifecycleHookName=hookname, AutoScalingGroupName=groupname, InstanceId=instance_id, LifecycleActionResult='ABANDON' ) log("Lifecycle hook ABANDONed for: {}".format(instance_id)) except botocore.exceptions.ClientError as e: log("Error completing life cycle hook for instance {}: {}".format(instance_id, e.response['Error'])) log('{"Error": "1"}') def log(error): print('{}Z {}'.format(datetime.utcnow().isoformat(), error))