Skip to content

Instantly share code, notes, and snippets.

@eddmann
Created November 3, 2017 15:32
Show Gist options
  • Save eddmann/ce2c65e4000d07c421ad266d449550ab to your computer and use it in GitHub Desktop.
Save eddmann/ce2c65e4000d07c421ad266d449550ab to your computer and use it in GitHub Desktop.
Scheduled EC2 Instance Type Modification using Lambda and CloudWatch Events
// Demonstration video can be found at: https://youtu.be/_gJyK1-NGq8
// ModifyEC2InstanceType
const AWS = require('aws-sdk');
exports.handler = (event, context, callback) => {
const { instanceId, instanceRegion, instanceType } = event;
const ec2 = new AWS.EC2({ region: instanceRegion });
Promise.resolve()
.then(() => ec2.stopInstances({ InstanceIds: [instanceId] }).promise())
.then(() => ec2.waitFor('instanceStopped', { InstanceIds: [instanceId] }).promise())
.then(() => ec2.modifyInstanceAttribute({InstanceId: instanceId, InstanceType: { Value: instanceType } }).promise())
.then(() => ec2.startInstances({ InstanceIds: [instanceId] }).promise())
.then(() => callback(null, `Successfully modified ${event.instanceId} to ${event.instanceType}`))
.catch(err => callback(err));
};
@devashishchandgupta
Copy link

Even after 4 years, still works like a charm. Thnx!

@gamentionkray
Copy link

gamentionkray commented Jul 16, 2024

For Node 20 I've modified it a bit:

import {
    EC2Client,
    StopInstancesCommand,
    DescribeInstancesCommand,
    ModifyInstanceAttributeCommand,
    StartInstancesCommand,
} from "@aws-sdk/client-ec2";

const waitForInstanceStopped = async (ec2Client, instanceId, timeoutSeconds = 420) => { // Default timeout: 7 minutes
    const startTime = Date.now();

    while (true) {
        const { Reservations } = await ec2Client.send(new DescribeInstancesCommand({ InstanceIds: [instanceId] }));
        const instanceState = Reservations[0].Instances[0].State.Name;

        if (instanceState === "stopped") {
            break;
        }

        const elapsedTime = (Date.now() - startTime) / 1000;
        if (elapsedTime >= timeoutSeconds) {
            throw new Error(`Timeout waiting for instance ${instanceId} to stop.`);
        }

        await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
    }
};


export const handler = async (event, context, callback) => {
    const { instanceId, instanceRegion, instanceType } = event;

    const ec2Client = new EC2Client({ region: instanceRegion });

    try {
        await ec2Client.send(new StopInstancesCommand({ InstanceIds: [instanceId] }));
        await waitForInstanceStopped(ec2Client, instanceId); // Wait until stopped

        await ec2Client.send(
            new ModifyInstanceAttributeCommand({
                InstanceId: instanceId,
                InstanceType: { Value: instanceType },
            })
        );

        await ec2Client.send(new StartInstancesCommand({ InstanceIds: [instanceId] }));
        callback(null, `Successfully modified ${event.instanceId} to ${event.instanceType}`);
    } catch (err) {
        callback(err);
    }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment