Using Amazon Web Services Command Line Interface (AWS CLI) to Find Instances without a ‘Name’ Tag
Many times I’ve needed to find AWS EC2 instances without a certain 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 here). After coming across this Reddit post and this Stack Overflow question, I made it my mission to figure out how to get instances that were missing a tag through AWS CLI instead of using external tools like jq or python.
The --Query
Parameter, JMESPath and filtering
JMESPath is the ‘engine’ behind the --query
parameter in AWS CLI. In its most basic form, it’ll help you filter out or traverse JSON. AWS has some nice documentation on how to use it at a basic level. In this post, we will focus on the filter ability of JMESPath.
Using the bracket and a question mark will trigger the JMESPath filter: [? ... ]
For example, many people have wanted to get the instance Name
tag along with the InstanceId. This is achieved by using the filter for the Tags → Key=='Name'
:
aws ec2 describe-instances \
--output text \
--query 'Reservations[].Instances[].[Tags[?Key==`Name`].Value|[0],InstanceId]'
While this is useful, we’re looking to do the actual opposite. First, we’ll want to dive down into each instance:
aws ec2 describe-instances \
--query 'Reservations[].Instances[]'
This will spit out each of the instances. We want to create a filter on each of these where the Name
tag doesn’t exist. A tag that exists would look like:
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 that has more than one tag. That instance will register 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 JMESPath’s 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. IE: anything that isn’t not_null aka not not null 🙂
aws ec2 describe-instances \
--query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)]'
Which will return something like 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’ll flatten the instance object with a pipe:
aws ec2 describe-instances \
--query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)] | []'
And thats it! If you’d like a few more examples of some common uses, here you go:
Display InstanceId
of instances which 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 which 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 which 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 which have no CreatedBy
tag:
aws ec2 describe-snapshots \
--output text \
--owner-ids self \
--query 'Snapshots[?!not_null(Tags[?Key == `CreatedBy`].Value)] | [].[SnapshotId,StartTime]'
Why search for untagged instances with AWS CLI?
There are a number of reasons to tag instances including automation and console organization, but at Onica, our biggest driver is cost. Employing a tagging policy to help track the cost allocation of your instances 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!