Last active
February 18, 2020 01:06
-
-
Save ajsharp/8eecd34a109f309538bad49c4a8e7a83 to your computer and use it in GitHub Desktop.
This script assigns newly launched elastic beanstalk instances to an elastic IP. It's triggered by a Cloudwatch Rule that gets triggered when a new instance transitions to the pending state. This script is intended be run as an AWS Lambda function.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const AWS = require('aws-sdk'); | |
const ec2 = new AWS.EC2(); | |
const PROD_ENV_NAME = 'my-prod-env-name'; | |
// Example Event | |
// { | |
// "version": "0", | |
// "id": "ee376907-2647-4179-9203-343cfb3017a4", | |
// "detail-type": "EC2 Instance State-change Notification", | |
// "source": "aws.ec2", | |
// "account": "123456789012", | |
// "time": "2015-11-11T21:30:34Z", | |
// "region": "us-east-1", | |
// "resources": [ | |
// "arn:aws:ec2:us-east-1:123456789012:instance/i-abcd1111" | |
// ], | |
// "detail": { | |
// "instance-id": "i-abcd1111", | |
// "state": "running" | |
// } | |
// } | |
exports.handler = async (event) => { | |
console.log("EVENT:", event); | |
// The newly launched instance ID. | |
const instanceId = event.detail['instance-id']; | |
// Fetch info about the newly launched instance | |
const result = await ec2.describeInstances({ | |
Filters: [ { Name: "instance-id", Values: [instanceId] } ] | |
}).promise() | |
// The instance details are buried in this object | |
const instance = result.Reservations[0].Instances[0]; | |
const isAttached = instance.NetworkInterfaces.find(int => int.Association.IpOwnerId !== 'amazon'); | |
// Bail if the instance is already attached to another EIP | |
if (isAttached) { | |
console.log("This instance is already assigned to an elastic IP") | |
return { statusCode: 200, body: '' } | |
} | |
// In elastic beanstalk, the instance name gets assigned to the enviroment name. | |
// There is also an environment name tag, which could be used here. | |
const name = instance.Tags.find(t => t.Key === 'Name').Value; | |
// Only assign EIPs to production instances | |
if (name !== PROD_ENV_NAME) { | |
console.log('Not a production instance. Not assigning. Instance name:', name) | |
return { statusCode: 200, body: ''} | |
} | |
// Get a list of elastic IP addresses | |
const addresses = await ec2.describeAddresses().promise(); | |
// Filter out addresses already assigned to instances | |
const availableAddresses = addresses.Addresses.filter(a => !a.NetworkInterfaceId); | |
// Raise an error if we have no more available IP addresses | |
if (availableAddresses.length === 0) { | |
console.log("ERROR: no available ip addresses"); | |
return { statusCode: 400, body: JSON.stringify("ERROR: no available ip addresses") } | |
} | |
const firstAvail = availableAddresses[0] | |
try { | |
// Associate the instance to the address | |
const result = await ec2.associateAddress({ | |
AllocationId: firstAvail.AllocationId, | |
InstanceId: instanceId | |
}).promise(); | |
console.log('allocation result', result) | |
return { statusCode: 200, body: JSON.stringify('Associated IP address.') }; | |
} catch (err) { | |
console.log("ERROR: ", err); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment