top of page
  • Cloud Life Team

Steampipe and Bash: Make your life easier




Overview

We are going to talk about the command line tool steampipe (website) and how to use it to easily pull data from any cloud providers (here, AWS) into a bash script.

Note: This content technical level expects some experience with using AWS CLI and bash scripting.



Table of Contents



The Situation

Have you ever wanted to more easily get information and status about your current AWS resources into a bash script? While Amazon does provide a command line tool for accessing your AWS account, sometimes you need to execute multiple queries and merge the data together in programming logic. Steampipe is a tool that maps your AWS resources to database-like schemas and then allows you to query it using queries written in SQL Lets dive into some examples.



Basic Steampipe Queries

Here is a simple Steampipe CLI query to show 3 EC2 instances along with their state:

Copy

$ steampipe query "select instance_id, instance_state from aws_ec2_instance limit 3"
+---------------------+----------------+
| instance_id         | instance_state |
+---------------------+----------------+
| i-02af95ae1b3d1b120 | running        |
| i-0e08e2f24314c34ea | stopped        |
| i-07a58563325e43d33 | stopped        |
+---------------------+----------------+

Normally, if you’d like to show the name of the instance (the Name tag) with the AWS CLI you might do something like:

aws ec2 describe-instances \
    --filters Name=tag-key,Values=Name \
    --query 'Reservations[*].Instances[*].{Instance:InstanceId,AZ:Placement.AvailabilityZone,Name:Tags[?Key==`Name`]|[0].Value}' \
    --output table

…which certainly works, but the Steampipe version is much easier to remember the SQL syntax and craft together the query:

$ steampipe query "select placement_availability_zone as az, instance_id, tags ->> 'Name' as Name  from aws_ec2_instance limit 3"
+------------+---------------------+-------------------------------------------+
| az         | instance_id         | name                                      |
+------------+---------------------+-------------------------------------------+
| us-east-1c | i-02af95ae1b3d2b120 | web-db-blue-qa-001                        |
| us-east-1c | i-0e08e2f24414c34ea | RCMWEBSTAGE3RJ                            |
| us-east-1c | i-07a28533325e43d33 | jmeter-server-good-001                    |
+------------+---------------------+-------------------------------------------+


Lets Pull it into Bash

Ok, now that we have some basic Steampipe queries down, lets work on pulling it into a bash script looping through the results to act on the data. If you’re comfortable with bash, this is probably the most important step; getting the data to where I can manipulate it.

The easiest way is to tell Steampipe to output its results in a CSV format, and then read that into individual variables. The command line option is --output csv .

Here is a script I use every day to show me all EC2 instances and the state of the virtual machines.

For this query

steampipe query "select region, instance_id, instance_state, 
             instance_type, private_ip_address, tags ->> 'Name' as Name
       from  aws_ec2_instance 
       order by name, instance_state" --output csv

This is what the results look like in CSV

region,instance_id,instance_state,instance_type,private_ip_address,name
us-west-2,i-0fa43b9a06619e2b4,running,m5a.large,172.31.19.161,jump-runner-3
us-west-2,i-0624bac744df6af45,running,t2.micro,172.31.46.14,test_server

In bash you can use a while loop setting the Internal Field Separator (IFS) to a comma and specifying the variables. My bash read line looks like this:

while IFS=, read -r region id state type ip name; do

And the data is read into the while loop using the < <(command) syntax thusly: (details in final script)

You can see that the variables I chose line up with the incoming data. As steampipe doesn’t have (as of this writing) a method of ignoring the header row, you can remove it with the tail command, piping it into tail -n +2 

done < <(steampipe query goes here)

In my final version, I add color because its easier on the eyes when parsing a large amount of data. Here is what the final output looks like:

and the full code for the sp_ec2.sh script:

#/bin/bash

normal=$(tput sgr0)
red=$(tput setaf 1)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
blue=$(tput setaf 4)

while IFS=, read -r region id state type ip name; do

    test -z "$id&& break

    scolor=$normal
    case $state in
        running) scolor=$green ;;
        stopped) scolor=$red ;;
        pending) scolor=$blue ;;
        stopping) scolor=$yellow ;;
    esac

    printf "%-10s %-31s ${scolor}%-10s${normal} %-20s %-11s ${yellow}%-15s${normal}\n\
                      "$region"${name:0:31}"$state$id "$type"$ipdone < <(STEAMPIPE_CACHE=false steampipe query "select region, instance_id, instance_state, 
            instance_type, private_ip_address, tags ->> 'Name' as Name
      from  aws_ec2_instance 
      order by name, instance_state" --output csv | tail -n +2)

Quick Lookups

A quick way to lookup the names of the AWS resources (tables) is to use the .tables command:

> .tables
 ==> aws
+--------------------------------------------------------------+--------------------------------------------------------------------+
| table                                                        | description                                                        |
+--------------------------------------------------------------+--------------------------------------------------------------------+
| aws_accessanalyzer_analyzer                                  | AWS Access Analyzer                                                |
| aws_account                                                  | AWS Account                                                        |
| aws_acm_certificate                                          | AWS ACM Certificate                                                |
| aws_amplify_app                                              | AWS Amplify App                                                    |
| aws_api_gateway_api_key                                      | AWS API Gateway API Key                                            |
| aws_api_gateway_authorizer                                   | AWS API Gateway Authorizer                                         |
...

And once you find the table you want, you can use .inspeect <table> command to view its columns:

> .inspect aws_ec2_instance
+--------------------------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------------------+
| column                                     | type                     | description                                                                                                             |
+--------------------------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------------------+
| _ctx                                       | jsonb                    | Steampipe context in JSON form, e.g. connection_name.                                                                   |
| account_id                                 | text                     | The AWS Account ID in which the resource is located.                                                                    |
| akas                                       | jsonb                    | Array of globally unique identifier strings (also known as) for the resource.                                           |
| arn                                        | text                     | The Amazon Resource Name (ARN) specifying the instance.                                                                 |
| block_device_mappings                      | jsonb                    | Block device mapping entries for the instance.                                                                          |

In Summary

Everyone has a tool of choice and for me, one of the main ones is bash scripting. When working with AWS I’ve found that the easiest way to get the data you want is to use Steampipe, so one of my goals was to get the two working together as seamlessly as possible. I hope that some of the code snippets and explanations here have helped you along your journey. Good luck!


2 views

Recent Posts

See All

Steps to Upgrade IPv4 to IPv6

As you probably know AWS is now charging for the use of every public IPv4 IP address used in your environment. The current rate is $.005/hr and while that doesn’t sound like much it amounts to approxi

How to Read IPv6 Addresses

IPv6 (Internet Protocol version 6) addressing has been around about 20 years now. It was implemented when it became apparent that we would run out of IPv4 addresses. The move to IPv6 has been slow but

Discover How Many IPv4 Addresses You will be Charged For

Starting Feb 1, 2024 AWS will charge your account for every IPv4 in your account whether it is attached or not. That is approx. $45/year for every single IPv4. Here are AWS services that can assign pu

Comments


bottom of page