I saw the previous question on this topic, but the answer was just "pipe it to a scripting language!", which I find unsatisfying. I know that JMESPath has sort_by
, and sort
, but I can't figure out how to use them.
I have
aws ec2 describe-instances \
--filters "Name=tag:Group,Values=production" "Name=instance-state-name,Values=running" "Name=tag:Name,Values=prod-*-${CURRENT_SHA}-*" \
--query 'Reservations[*].Instances[*].[LaunchTime,InstanceId,PrivateIpAddress,Tags[?Key==`Name`] | [0].Value]' \
--output table
And it outputs the right data, just in a random order. I want to sort by the last column of the data, Tag Name, aka Tags[?Key==`Name`]
, which in raw form looks like this:
{
"Tags": [{
"Value": "application-server-ab3634b34364a-2",
"Key": "Name"
}, {
"Value": "production",
"Key": "Group"
}]
}
Thoughts?
Go to VPC dashboard https://console.aws.amazon.com/vpc/home and click on Running instances -> See all regions . Example output: $ aws.
Use the AWS CLI tools to generate a list instances, then pipe them to JQ to show only their launch time and instance id. Finally use sort to bring them out in runtime order.
The AWS CLI supports the following output formats: json – The output is formatted as a JSON string. yaml – The output is formatted as a YAML string. yaml-stream – The output is streamed and formatted as a YAML string.
If you use this parameter, DescribeInstances returns a description of the specified instances. Otherwise, it returns a description of every instance. --cli-input-json (string) Performs service operation based on the JSON string provided.
add
[] | sort_by(@, &[3])
at the end of your expression. The brackets ([]
) will flatten the structure, sort_by(...)
will sort the result (which is a four-column table) by the fourth column. The full query will be:
--query 'Reservations[*].Instances[*].[LaunchTime,InstanceId,PrivateIpAddress,Tags[?Key==`Name`] | [0].Value][] | sort_by(@, &[3])'
According to the describe-instances
docs, the structure of the describe-instances
output looks like this:
{
"Reservations": [
{
"Instances": [
{
"LaunchTime": "..LaunchTime..",
"InstanceId": "R1I1",
"PrivateIpAddress": "..PrivateIpAddress..",
"Tags": [{"Key": "Name", "Value": "foo"}]
},
{
"LaunchTime": "..LaunchTime..",
"InstanceId": "R1I2",
"PrivateIpAddress": "..PrivateIpAddress..",
"Tags": [{"Key": "Name", "Value": "baz"}]
}
]
},
{
"Instances": [
{
"LaunchTime": "..LaunchTime..",
"InstanceId": "R2I1",
"PrivateIpAddress": "..PrivateIpAddress..",
"Tags": [{"Key": "Name", "Value": "bar"}]
}
]
}
]
}
Using your original query
--query 'Reservations[*].Instances[*].[LaunchTime,InstanceId,PrivateIpAddress,Tags[?Key==`Name`] | [0].Value]'
will output
[
[
[
"..LaunchTime..",
"R1I1",
"..PrivateIpAddress..",
"foo"
],
[
"..LaunchTime..",
"R1I2",
"..PrivateIpAddress..",
"baz"
]
],
[
[
"..LaunchTime..",
"R2I1",
"..PrivateIpAddress..",
"bar"
]
]
]
You can see in the above result of your query that you're getting a list of tables ([[{},{}],[{}]]
). I suppose you instead want a single non-nested table ([{},{},{}]
). To achieve that, simply add []
at the end of your query, i.e.
--query 'Reservations[*].Instances[*].[LaunchTime,InstanceId,PrivateIpAddress,Tags[?Key==`Name`] | [0].Value][]'
This will flatten the structure, resulting in
[
[
"..LaunchTime..",
"R1I1",
"..PrivateIpAddress..",
"foo"
],
[
"..LaunchTime..",
"R1I2",
"..PrivateIpAddress..",
"baz"
],
[
"..LaunchTime..",
"R2I1",
"..PrivateIpAddress..",
"bar"
]
]
Now it's time to sort the table.
When using sort_by
you shouldn't forget to prepend the expression by &
(ampersand). This way you specify a reference to that expression, which is then passed to sort_by
.
example: data | sort_by(@, &@)
is equivalent to data | sort(@)
.
The TagName
in the table you create ([LaunchTime,InstanceId,PrivateIpAddress,TagName]
) is the fourth column. You can get that column by piping the table to the expression [3]
:
TableExpression | [3]
But instead, you want to sort the table by the fourth column. You can do so like this:
TableExpression | sort_by(@, &[3])
and the resulting query will be:
--query 'Reservations[*].Instances[*].[LaunchTime,InstanceId,PrivateIpAddress,Tags[?Key==`Name`][] | [0].Value] | sort_by(@, &[3])'
Query result:
[
[
"..LaunchTime..",
"R2I1",
"..PrivateIpAddress..",
"bar"
],
[
"..LaunchTime..",
"R1I2",
"..PrivateIpAddress..",
"baz"
],
[
"..LaunchTime..",
"R1I1",
"..PrivateIpAddress..",
"foo"
]
]
As an enhancement to @ColinK's answer, I wanted to sort a table that had custom column headers but struggled with the syntax. I eventually got it to work so I thought I'd share in case someone else wanted to do the same. I added a column for State and sorted by that column.
--query 'sort_by(Reservations[*].Instances[*].{LaunchTime:LaunchTime, ID:InstanceId,IP:PrivateIpAddress,State:State.Name,Name:Tags[?Key==`Name`] | [0].Value}[], &State)'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With