Originally published in Feb 2017, at Onica.com/blog
I often need to find AWS® EC2® instances without a particular tag. Usually, it’s
the Name tag, but other tags come up from time to time (we use a tag of Owner
quite
a bit).
After coming across this Reddit post and this Stack Overflow question, we made it our mission to figure out how to get instances that were missing a tag through the AWS command line interface (CLI) instead of using external tools like jq or python.
JMESPath is the engine behind the –query parameter in AWS CLI. In its most basic form, it helps you filter out or traverse JSON. AWS has some nice documentation describing how to use it at a basic level. In this post, we focus on the filtering ability of JMESPath.
Using the bracket and a question mark triggers the JMESPath filter: [? ... ]
For example, many people want to get the instance Name tag and the InstanceId. You
can do this by using the filter for the Tags -> Key=='Name'
, as shown in the following
example:
aws ec2 describe-instances \
--output text \
--query 'Reservations[].Instances[].[Tags[?Key==`Name`].Value|[0],InstanceId]'
While this is useful, we actually want to do the opposite. So, we start by diving down into each instance:
aws ec2 describe-instances \
--query 'Reservations[].Instances[]'
This operation spits out each of the instances. Then, we create a filter on each of these where the Name tag doesn’t exist. A tag that exists would look similar to the following example:
aws ec2 describe-instances \
--query 'Reservations[].Instances[?Tags[?Key != `Name`]]'
The problem with this filter is that as we loop through the Tags array, we’ll most
likely hit an instance with more than one tag. That instance registers true
because the
first tag may have "Key:" "SomeTag"
(but the second could be "Key:" "Name"
). So we want
to look for the object with the Name key but with no value (aka null
).
First, lets get the value from the Name tag:
aws ec2 describe-instances \
--query 'Reservations[].Instances[].Tags[?Key == `Name`].Value'
Now we can use the JMESPath not_null() function to filter for ones that exist:
aws ec2 describe-instances \
--query 'Reservations[].Instances[?not_null(Tags[?Key == `Name`].Value)]'
The problem is that this still captures anything with a Name tag. So we negate it.
That is, we want anything that isn’t not_null
[aka not not null]!
aws ec2 describe-instances \
--query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)]'
This operation returns something similar to the following:
[
[
{
"Monitoring": {
"State": "disabled"
},
"PublicDnsName": "",
"RootDeviceType": "ebs"
...
}
],
[],
[],
[],
[],
[],
[],
[
{
"Monitoring": {
"State": "disabled"
},
"PublicDnsName": "",
"RootDeviceType": "ebs"
...
}
],
[]
]
We don’t want to have these empty arrays, so we flatten the instance object with a pipe:
aws ec2 describe-instances \
--query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)] | []'
And that’s it!
If you want a few more examples of some common uses, here you go:
Display InstanceId of instances that have no Name tag:
aws ec2 describe-instances \
--output text \
--query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)] | [].[InstanceId]'
Display InstanceId of running instances that have no Owner tag:
aws ec2 describe-instances \
--output text \
--filters Name=instance-state-name,Values=running \
--query 'Reservations[].Instances[?!not_null(Tags[?Key == `Owner`].Value)] | [].[InstanceId]'
Display VolumeId and Size of volumes that have no Name tag:
aws ec2 describe-volumes \
--output text \
--query 'Volumes[?!not_null(Tags[?Key == `Name`].Value)] | [].[VolumeId,Size]'
Display SnapshotId and StartTime of my snapshots that have no CreatedBy tag:
aws ec2 describe-snapshots \
--output text \
--owner-ids self \
--query 'Snapshots[?!not_null(Tags[?Key == `CreatedBy`].Value)] | [].[SnapshotId,StartTime]'
There are many reasons to tag instances, including automation and console organization, but at Rackspace Technology Onica, our biggest driver is cost. Employing a tagging policy to help track your instances' cost allocation is an important step in optimizing your AWS cost!
For more tips and tricks to lower your monthly AWS cost by up to 50%, download our eBook!
(Learn more about Rackspace AWS services.) for assistance.
Use the Feedback tab to make any comments or ask questions. You can also start a conversation with us.