An AWS CLI / Node.js Script for Terminating EC2 Instances


The AWS Command Line Interface (CLI) is a powerful scripting platform written in Python that uses the AWS Cloud’s RESTful management API for performing various operational tasks, like creating S3 buckets, deleting EBS volumes, etc.

In this blog, I will show you how you can terminate EC2 instances from your local computer using AWS CLI wrapped up as a Node.js app.

What you need is these four things:

  1. Have an account with AWS (a credit card will be required if you don’t have one)
  2. Have AWS CLI installed on your favorite OS. I used Windows and followed the AWS CLI installation instructions
    Mind you, that as of March 2017 the MSI installer for the AWS CLI does not work with Windows Server 2008 (version 6.0.6002). Use Python’s package manager, pip, to install with this version of Windows.

  3. Have the aws Universal Command Line Environment (tool) configured with your account credentials for remote access:
    • AWS Access Key ID, and
    • AWS Secret Access Key

    The communication between your local computer and AWS is done over SSL, so you have an effective point-to-point encrypted channel.

    I do not describe the configuration steps, which you can find on the AWS web site.

    When you run the aws tool for the first time, you will be prompted with a Firewall Alert — just select the Allow Always (or something along those lines) rule for it.

  4. Have Node.js installed on your computer.

    While you may achieve quite a lot with simple AWS CLI scripts, its real power can be unleashed by creating small Node.js utility apps scripted around the raw AWS CLI.

    I use the terms Node.js app and script interchangeably.

    As an option, you can install AWS SDK for JavaScript in Node.js, but then you will need to learn the SDK.

    Note: While request for termination is enqueued right away, the EC2 service may take quite some times (like hours) to actually remove the terminated instances.

    Here is the code for a Node.js app that terminates (stops and deletes) EC2 instances. I used Visual Studio Code IDE for developing and debugging the script.

    const exec = require("child_process").execSync;
    
    var region_id = "ca-central-1"; // Pass it as an argument
    
    console.log(`\nAbout to terminate EC2 instances in [${region_id}]`);
    
    // Get the list of the EC2 instances still available
    var cmd = `aws --region ${region_id} ec2 describe-instances --query "Reservations[*].Instances[*].[InstanceId]"`;
    var aws_response = "";
    var ec2_instances_list = [];
    
    try {
      console.log(`Running command ${cmd}`);
      aws_response =  exec(cmd);
    } catch (error) {
        console.error(error);
        return;
    }
    
    aws_response = aws_response.toString();
    // console.log(aws_response);
    
    if (aws_response.startsWith("[]")){
        console.log(`No instances found in region ${region_id}`);
        return;
    }
    
    var ec2_instances_list = eval(aws_response);
    // console.log(ec2_instances_list.length); // array's length == number of instances in the region
    
    for (var i=0; i<ec2_instances_list.length; i++) {
        // Terminate one by one
        var ec2_instance= ec2_instances_list[i][0][0];
        console.log(`About to terminate instance ${ec2_instance}`);
        cmd = `aws --region ${region_id} ec2 terminate-instances --instance-ids ` + ec2_instance; // --dry-run 
        console.log(`Issuing command: ${cmd}`);
        try {
            aws_response = exec(cmd);
            console.log(`Command completed with response ${aws_response.toString()}`);
            console.log(`Terminated ${ec2_instance}\n`);
        } catch (error) {
            console.error(error);            
        }        
    }
    


    In order to delete instances, first we need to get the list of those running in your region, which is accomplished with this command:

     
    aws --region ${region_id} ec2 describe-instances --query "Reservations[*].Instances[*].[InstanceId]
    

    The raw output of the above command looks like the one below:

    
    [
        [
            [
                "i-05aecbcad007d925e"
            ]
        ],
        [
            [
                "i-0d4561e7dffe1d05d"
            ]
        ]
    ] 
    


    To get to the instance ids, you first need to apply the eval function, and then access the i-th instance id via the [i][0][0] index path.

    Note: You can flatten out the above output structure by using the

     --output text 

    command option.

    I opted for using the plain AWS CLI submitted via the

    require("child_process").execSync 

    Node.js object.

    In a more practical context, you would need to wrap up the above app as a module and call it from a Node.js app that would need that functionality.

    module.exports.terminate_EC2_instances = function (region_id) {
    // your code goes in here … 
    }
    


    That’s all I wanted to say on this topic for now.

    Till next time!

  1. No comments yet.
(will not be published)

*