aws cli ec2 describe-instances table output - amazon-web-services

I want to run an ec2 describe-instances command and get output in a table format as follows (where name is the Value of the Tag with Key 'Name'):
----------------------------------------------------------
| DescribeInstances |
+-------------+----------------+--------------+----------+
| instance_id | ip_address | name | state |
+-------------+----------------+--------------+----------+
| i-g93g494d | 99.99.99.01 | name1 | running |
| i-a93f754c | 99.99.99.02 | name2 | running |
+-------------+----------------+--------------+----------+
I can run the following command:
aws ec2 describe-instances --instance-ids i-g93g494d i-a93f754c --query "Reservations[*].Instances[*].{name: Tags[?Key=='Name'].Value, instance_id: InstanceId, ip_address: PrivateIpAddress, state: State.Name}" --output json
and obtain output:
[
[
{
"instance_id": "i-g93g494d",
"state": "running",
"ip_address": "99.99.99.01",
"name": [
"name1"
]
}
],
[
{
"instance_id": "i-a93f754c",
"state": "running",
"ip_address": "99.99.99.02",
"name": [
"name2"
]
}
]
]
However, when I run the same command with --output table rather than --output json I get an error.
command:
aws ec2 describe-instances --instance-ids i-g93g494d i-a93f754c --query "Reservations[*].Instances[*].{name: Tags[?Key=='Name'].Value, instance_id: InstanceId, ip_address: PrivateIpAddress, state: State.Name}" --output json
output:
list index out of range
I would like the table output to look like the above example but I'm having difficulty solving this. I'd very much appreciate any help anyone can offer on this.

You need to use pipe expression to filter the Tag results and get the first value such as:
aws ec2 describe-instances --instance-ids i-g93g494d i-a93f754c --query "Reservations[*].Instances[*].{name: Tags[?Key=='Name'] | [0].Value, instance_id: InstanceId, ip_address: PrivateIpAddress, state: State.Name}" --output table
There is a nice related blog post here: Get a list of instance with id, name and type

Here's a python program that can be used to generate listings from the descibe-instances command:
import json
import sys
with open( sys.argv[1] ) as f:
aws = json.load( f )
Reservations = aws['Reservations']
for Reservation in Reservations:
Instances = Reservation['Instances']
for Instance in Instances:
Tags = Instance['Tags']
for Tag in Tags:
if Tag['Key'] == "Name":
print Tag['Value'],Instance['PrivateIpAddress'],Instance['InstanceId'],Instance['State']['Name']
BTW, I absolutely LOVE Volkan Paksoy's answer. That's going into my bag o' tricks. The above python may have the advantage of allowing you to be more expressive with your search criteria or somehow combining results. In short, it's python, and you don't have to figure out how to use the aws syntax.
Here's how to invoke the python script above:
python parse.py <( aws ec2 describe-instances )
Of course, your mileage may vary. For instance, you may not have your region defaulted so, you may need to add an extra parameter as follows:
python parse.py <( aws ec2 --region us-east-2 describe-instances )
And you can than manipulate the output a bit to select only running instances and put in a well formatted column list:
python parse.py <( aws ec2 --region us-east-2 describe-instances ) | column -t | sort -k1,1 | cat -n | grep running
One last note, as I stated, I am a fan of the one liner provided by Volkan. I was just wondering how if the column ordering can be manipulated. I found that aws is sorting the columns alphabetically. To make the ordering obvious, I put numbers in front of the attribute names. However, these attribute names weren't interpreted properly as identifiers, so I had to quote them with double quotes. Here's what I wound up with, please note the subtle quoting changes ( and not so subtle quoting around 'Name' ):
aws ec2 describe-instances --query 'Reservations[*].Instances[*].{"01-name": Tags[?Key=='"'Name'"'] | [0].Value, "03-instance_id": InstanceId, "02-ip_address": PrivateIpAddress, "04-state" : State.Name}' --output table

Related

aws cli query and output table format with named column

I just want to list EC2 with a table output format with a name for my column. But when I add the query to avoid to get EC2 from Auto Scaling Group, I got an error...
aws ec2 describe-instances --query 'Reservations[].Instances[].{AZ:Placement.AvailabilityZone}' --profile dev --output table
-------------------
|DescribeInstances|
+-----------------+
| AZ |
+-----------------+
| eu-west-3a |
| eu-west-3a |
| eu-west-3a |
...
OK
And there :
aws ec2 describe-instances --query 'Reservations[].Instances[?!contains(Tags[].Key, `aws:autoscaling:groupName`)].{AZ:Placement.AvailabilityZone}' --profile dev --output table
Row should have 1 elements, instead it has 0
Yeah, JMESPATH can be weird sometimes. Try:
aws ec2 describe-instances --query 'Reservations[].Instances[?!contains(Tags[].Key, `aws:autoscaling:groupName`)]|[].{AZ:Placement.AvailabilityZone}' --profile dev --output table
(If it works, don't ask me why.)

AWS CLI Loading Output Onto Multiple Lines

I am using the aws cli to give me some output which I require in .csv format.
The below shows the commands I've put together:
aws ec2 describe-instances --output text --query 'Reservations[*].Instances[*].[VpcId, SubnetId, InstanceId, InstanceType, ImageId, State.Name, LaunchTime, Placement.AvailabilityZone, Placement.Tenancy, PrivateIpAddress, PrivateDnsName, PublicDnsName,[Tags[?Key==`Name`].Value],[Tags[?Key==`PowerData`].Value] ]' --output text | sed -E 's/\s+/,/g'
For some reason, the final two pieces of info, "Name" and "PowerData" end up on separate lines. This screws up my formatting when I open it up in a spreadsheet.
Anyone have any ideas on what might be causing that or how I may resolve it please?
The reason is TAGs return array so you need to print the only value on 0 index to display the TAGs on a single line.
You can verify this
aws ec2 describe-instances --output json --query 'Reservations[*].Instances[*].Tags[]'
output
[
{
"Key": "Name",
"Value": "demo"
},
{
"Key": "PowerData",
"Value": "demo"
}
]
so you need pipe expression
Tags[?Key==`Name`].Value| [0]
With the addition of filters, we could pass the result of one expression to another, operating on the result of a projection (or any expression).
Expression:
foo.*.bar | [0]
jmespath-pipe-expressions
So try this
aws ec2 describe-instances --output text --query 'Reservations[*].Instances[*].[VpcId, SubnetId, InstanceId, InstanceType, ImageId, State.Name, LaunchTime, Placement.AvailabilityZone, Placement.Tenancy, PrivateIpAddress, PrivateDnsName, PublicDnsName,Tags[?Key==`Name`].Value| [0],Tags[?Key==`PowerData`].Value | [0] ]' --output text | sed -E 's/\s+/,/g'

How to get all security groups through AWS CLI of an EC2 to show in a table

I am trying to show all instances along with attached security groups, block device name and their deleteontermination status. I need to show this data in table format but I am continuously getting the below error.
Kindly help me to understand what I am missing here.
PR-MacBook-Pro:~ pr$ aws ec2 describe-instances --output table --query 'Reservations[*].Instances[*].[InstanceId,SecurityGroups[].GroupName,Placement.AvailabilityZone,BlockDeviceMappings[].DeviceName, BlockDeviceMappings[].Ebs.DeleteOnTermination]'
Row should have 1 elements, instead it has 2
PR-MacBook-Pro:~ pr$
I came across this while searching in google.
After I did a bit of research I found that you have to use | join(`, `, #)
So the command will be
aws ec2 describe-instances --output table --query 'Reservations[*].Instances[*].[InstanceId,SecurityGroups[].GroupName | join(`, `, #),Placement.AvailabilityZone,BlockDeviceMappings[].DeviceName | join(`, `, #), BlockDeviceMappings[].Ebs.DeleteOnTermination | join(`, `, to_array(to_string(#)))]'
modify your command as below to make it work
aws ec2 describe-instances --output table --region "us-east-1" --query 'Reservations[*].Instances[*].[InstanceId,SecurityGroups[].GroupName |[0],Placement.AvailabilityZone,BlockDeviceMappings[].DeviceName |[0], BlockDeviceMappings[].Ebs.DeleteOnTermination|[0] ]'
the response was in the format of
[
[
"i-xxxxxxxx",
[
"xxxxxx"
],
"us-east-1a",
[
"/dev/xvda"
],
[
true
]
]
]
so you need parse the array element using | [0]

AWS-cli ec2 describe instances

i am digging on aws cli and from past 5 hours i struggling with 2 cli commands
i should get InstanceId, Name(this is a tag value) and specific tag value by providing its key ( including not tags given i.e NULL)
I should get InstanceId, Name and specific tag value by providing its key ( excluding NULL tags)
i got 50% of the answer for the 1 Question & 2 Question 0%
My cli command:
aws ec2 describe-instances --query 'jsondata[ ].Instances[
].[InstanceId, [Tags[?keys='Name'].Value] [0][0]' --output table`
Ex: {
"Jsondata" : [
{ "Instances" : "i-xxxxxx",
"Tags":[
{ "valve":" testserver",
"key": "server"
},
{ "valve":" elb",
"key": "Name"
}
]
},
{ "Instances" : "i-yyyyyy",
"Tags":[
{ "valve": " ",
"key": " "
},
{ "valve":" elb2",
"key": "Name"
}
]
}
]`
Thanks in advance. Please help me i need to sleep
To describe all instances with Tag "NAME" Use:
aws ec2 describe-instances --filters "Name=tag-key,Values=Name"
or
This Gives InstanceId with Particular Tag "Name"
aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId, Tags[?Key==`Name`].Value[0]]'
or
This Gives InstanceId with Particular Tag "Name" and Value of Tag
aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId, Tags[?Key==`Name`], Tags[?Key==`Name`].Value[]]'
To describe all instances with Tag "Purpose" and its value as "test" Use:
aws ec2 describe-instances --filters "Name=tag:Purpose,Values=test"
If you already know the Instance id:
aws ec2 describe-instances --instance-ids i-1234567890abcdef0
To find every instance which doesn't contain a tag named "Purpose":
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "Purpose"} ]}) | not)'
To filter against the value of the tag, instead of the name of the tag:
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "Name"}, {Value: "testbox1"}]}) | not)'
To find every instance which doesn't contain a tag:
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: ""}, {Value: ""}]}) | not)'

How to extract a particular Key-Value Tag from ec2 describe-instances

I've got the following from describe-instances:
{
"Reservations": [
{
"Instances": [
{
"PublicDnsName": "ec2-xxxxx.amazonaws.com",
"Tags": [
{
"Key": "Name",
"Value": "yyyyy"
},
{
"Key": "budget_cluster",
"Value": "zzzzz"
},
{
"Key": "poc",
"Value": "aaaaaaa"
}
]
}
]
}
]
}
For each instance, I would like to extract the PublicDnsName and the value of the "budget_cluster" tag key. How to do this either with ec2 describe-instances or with jq ?
Modifying Frédéric's answer:
aws ec2 describe-instances --output text --query \
'Reservations[].Instances[].[PublicDnsName, Tags[?Key==`budget_cluster`].Value | [0]]'
Would produce:
ec2-xxxxx.amazonaws.com zzzzz
ec2-bbbbb.amazonaws.com yyyyy
I've changed the output to text, which removes as much formatting as possible and selected the individual tag value with | [0] since there will only ever be one per instance anyway. Finally, I removed the [] at the end so that the resulting list isn't flattened. That way in text output each entry will be on its own line.
You can also make this more robust by only selecting instances that actually have that tag. You could do so with further modifications to the --query parameter, but it is better in this case to use the --filters parameter since it does service-side filtering. Specifically you want the tag-key filter: --filters "Name=tag-key,Values=budget_cluster"
aws ec2 describe-instances --output text \
--filters "Name=tag-key,Values=budget_cluster" --query \
'Reservations[].Instances[?Tags[?Key==`budget_cluster`]].[PublicDnsName, Tags[?Key==`budget_cluster`].Value | [0]]'
Would still produce:
ec2-xxxxx.amazonaws.com zzzzz
ec2-bbbbb.amazonaws.com yyyyy
But over the wire you would only be getting the instances you care about, thus saving money on bandwidth.
Using jq 1.5 or later, the simplest approach is to use from_entries.
After a minimal fix of the illustrative input, the following invocation:
$ jq '.Reservations[]
| .Instances[]
| [.PublicDnsName, (.Tags|from_entries|.budget_cluster)]' input.json
produces:
[
"ec2-xxxxx.amazonaws.com",
"zzzzz"
]
If you do not have jq 1.5 or later, the following should work:
$ jq1.4 '.Reservations[]
| .Instances[]
| [.PublicDnsName, (.Tags[]|select(.Key=="budget_cluster") | .Value)]' input.json
The answer of #peak is great and I keep learning from him on the jq part but again you can achieve quite a lot from the AWS CLI
aws ec2 describe-instances --query \
'Reservations[].Instances[].{PublicDnsName:PublicDnsName, Budget:Tags[?Key==`budget_cluster`].Value}'
would produce
[
{
"PublicDnsName": "ec2-xxxxx.amazonaws.com",
"Budget": [
"zzzz",
]
}
]
If you do not want to make a new strict JSon out of it, just take the values
aws ec2 describe-instances --query \
'Reservations[].Instances[].[PublicDnsName, Tags[?Key==`budget_cluster`].Value][]'
will produce
[
"ec2-xxxxx.amazonaws.com",
[
"zzzz"
]
]