AWS CLI query examples
While some users may prefer to pipe AWS CLI JSON output to jq
for parsing, it is possible to leverage the --query
functionality that’s built-in.
Commonly, users deal with large JSON outputs when executing AWS CLI commands in their environments. To mitigate the process, JMESPath, a powerful filtering language, can specify resource properties, create lists, search output, etc.
AWS CLI Output
For reference, the AWS CLI documentation lists JSON document outputs. The commands listed below use aws ec2 describe-images
, but any combination of the examples can be used for other services and properties.
1aws ec2 describe-images \
2 --region us-east-1 \
3 --image-ids ami-1234567890EXAMPLE
Output (provided by AWS):
1{
2 "Images": [
3 {
4 "VirtualizationType": "hvm",
5 "Description": "Provided by Red Hat, Inc.",
6 "PlatformDetails": "Red Hat Enterprise Linux",
7 "EnaSupport": true,
8 "Hypervisor": "xen",
9 "State": "available",
10 "SriovNetSupport": "simple",
11 "ImageId": "ami-1234567890EXAMPLE",
12 "UsageOperation": "RunInstances:0010",
13 "BlockDeviceMappings": [
14 {
15 "DeviceName": "/dev/sda1",
16 "Ebs": {
17 "SnapshotId": "snap-111222333444aaabb",
18 "DeleteOnTermination": true,
19 "VolumeType": "gp2",
20 "VolumeSize": 10,
21 "Encrypted": false
22 }
23 }
24 ],
25 "Architecture": "x86_64",
26 "ImageLocation": "123456789012/RHEL-8.0.0_HVM-20190618-x86_64-1-Hourly2-GP2",
27 "RootDeviceType": "ebs",
28 "OwnerId": "123456789012",
29 "RootDeviceName": "/dev/sda1",
30 "CreationDate": "2019-05-10T13:17:12.000Z",
31 "Public": true,
32 "ImageType": "machine",
33 "Name": "RHEL-8.0.0_HVM-20190618-x86_64-1-Hourly2-GP2"
34 }
35 ]
36}
Please note Images
is a top-level list-type element in the JSON document.
Examples
Warning: The AWS describe-images
commands outputs a large JSON document. The JMESPath list slicing (Images[:3]
) feature is leveraged to truncate the results. If the full output is desired, use Images[]
instead.
Listing Outputs
List the ImageId
of the first 3 images owned by Amazon:
1$ aws ec2 describe-images \
2 --owner amazon \
3 --query "Images[:3].ImageId"
4[
5 "aki-04206613",
6 "aki-0a4aa863",
7 "aki-12f0127b"
8]
Note: Images[:3].ImageId
outputs the property into a single list. If a list for each image is desired, use Images[:3].[ImageId]
. As shown in the next example, it’s useful for listing multiple properties.
List the ImageId
and OwnerId
of the first 3 images owned by Amazon:
1$ aws ec2 describe-images \
2 --owner amazon \
3 --query "Images[:3].[ImageId,OwnerId]"
4[
5 [
6 "aki-04206613",
7 "137112412989"
8 ],
9 [
10 "aki-0a4aa863",
11 "470254534024"
12 ],
13 [
14 "aki-12f0127b",
15 "470254534024"
16 ]
17]
List the ImageId
and OwnerId
of the first 3 images owned by Amazon in a list of JSON objects:
If desired, the output values can be nested in a hash object using JMESPath’s hash multi-selection feature.
1$ aws ec2 describe-images \
2 --owner amazon \
3 --query "Images[:3].{image:ImageId,owner:OwnerId}"
4[
5 {
6 "image": "aki-04206613",
7 "owner": "137112412989"
8 },
9 {
10 "image": "aki-0a4aa863",
11 "owner": "470254534024"
12 },
13 {
14 "image": "aki-12f0127b",
15 "owner": "470254534024"
16 }
17]
Filter Projection & Pipe Expressions
List the ImageId
of the first 3 images that are owned by Amazon’s OwnerId
of 137112412989
:
JMESPath provides two features needed to accomplish this query:
1$ aws ec2 describe-images \
2 --owner amazon \
3 --query "Images[?OwnerId=='137112412989'] | [:3].ImageId"
4[
5 "aki-04206613",
6 "aki-499ccb20",
7 "aki-5c21674b"
8]
The combination of a filter projection, Images[?OwnerId=='137112412989']
, and a pipe expression, | [:3].ImageId
satisfies the requirement.
Here’s the Python code representing the filter projection operation:
1result = []
2for image in inputData['Images']:
3 if image['OwnerId'] == '137112412989'
4 result.append(image)
5return result
It returns:
1[
2 {
3 "ImageId": "aki-04206613",
4 "OwnerId": "137112412989",
5 "..."
6 },
7 {
8 "ImageId": "aki-499ccb20",
9 "OwnerId": "137112412989",
10 "..."
11 },
12 {
13 "ImageId": "aki-5c21674b",
14 "OwnerId": "137112412989",
15 "..."
16 },
17 "...",
18 "...",
19 "..."
20]
Then, grab the first three using the pipe expression:
| [:3]
1[
2 {
3 "ImageId": "aki-04206613",
4 "OwnerId": "137112412989",
5 "..."
6 },
7 {
8 "ImageId": "aki-499ccb20",
9 "OwnerId": "137112412989",
10 "..."
11 },
12 {
13 "ImageId": "aki-5c21674b",
14 "OwnerId": "137112412989",
15 "..."
16 }
17]
Then, add the specific ImageId
property:
| [:3].ImageId
1[
2 "aki-04206613",
3 "aki-499ccb20",
4 "aki-5c21674b"
5]
Function Expressions
JMESPath supports function expressions:
List the Id
and CreationDate
of the first 3 images that are owned by Amazon whose PlatformDetails
contain the string ‘Linux’ in sorted order by CreationDate
:
Step #1: Use the contains
function and grab the first 3 results:
1$ aws ec2 describe-images \
2 --owner amazon \
3 --query "Images[?contains(PlatformDetails, 'Linux')] | [:3]"
4[
5 {
6 "CreationDate": "2016-09-28T21:31:10.000Z",
7 "ImageId": "aki-04206613",
8 "PlatformDetails": "Linux/UNIX",
9 "..."
10 },
11 {
12 "CreationDate": "2009-12-15T18:44:15.000Z",
13 "ImageId": "aki-0a4aa863",
14 "PlatformDetails": "Linux/UNIX",
15 "..."
16 },
17 {
18 "CreationDate": "",
19 "ImageId": "aki-12f0127b",
20 "PlatformDetails": "Linux/UNIX",
21 "..."
22 }
23]
This filters the top-level Images
for all objects with Linux
in their PlatformDetails
value.
Step #2: Sort by CreationDate
:
1$ aws ec2 describe-images \
2 --owner amazon \
3 --query "Images[?contains(PlatformDetails, 'Linux')] | [:3] | sort_by(@, &CreationDate)[].{CreationDate:CreationDate,Id:ImageId}"
The sort_by
function requires an input similar to this:
1KeyNameHere: [
2 {
3 "key1": "val1",
4 "key2": "val2"
5 }
6]
If results were ordered by the key2
field, the query would be:
sort_by(KeyNameHere, &key2)
Similarly, the input to the sort_by
function in the example was:
1[
2 {
3 "CreationDate": "2016-09-28T21:31:10.000Z",
4 "ImageId": "aki-04206613",
5 "PlatformDetails": "Linux/UNIX",
6 "..."
7 },
8 { "..." },
9 { "..." }
10]
There is not a top-level key present. In this case, the character @
is used to represent the list that is being passed. Additionally, the key that is being sorted on must begin with an &
.
After the sort_by
function, the list is “retrieved” []
and the result is formatted to a customized JSON output.
1[
2 {
3 "CreationDate": "",
4 "Id": "aki-12f0127b"
5 },
6 {
7 "CreationDate": "2009-12-15T18:44:15.000Z",
8 "Id": "aki-0a4aa863"
9 },
10 {
11 "CreationDate": "2016-09-28T21:31:10.000Z",
12 "Id": "aki-04206613"
13 }
14]
The first object contains a null CreationDate
value. Luckily, it can be removed from the output using the not_null
function.
1$ aws ec2 describe-images \
2 --owner amazon \
3 --query "Images[?contains(PlatformDetails, 'Linux')] | [:4] | @[?not_null(CreationDate)] | sort_by(@, &CreationDate)[].{CreationDate:CreationDate,Id:ImageId}"
4[
5 {
6 "CreationDate": "2009-12-15T18:44:15.000Z",
7 "Id": "aki-0a4aa863"
8 },
9 {
10 "CreationDate": "2010-09-28T03:52:22.000Z",
11 "Id": "aki-1c669375"
12 },
13 {
14 "CreationDate": "2016-09-28T21:31:10.000Z",
15 "Id": "aki-04206613"
16 }
17]
Lastly, a common scenario is to filter based on environment variables:
Retrieve a cloudformation export by name and store the value
1$ export_name=$(aws cloudformation list-exports \
2 --query "Exports[?Name=='$ENV_VAR'].Value" \
3 --output text)
4$ echo $export_name
5value_here
The environment variable was used by wrapping with single quotes!