How to output multiple elements via AWS query? - amazon-web-services

I trying to output in a column format three keys from 'rds'. If I start with this statement:
aws rds describe-db-instances --region us-east-1 --query 'DBInstances[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroupId]' --output text
...I get:
DBId true none
However, if I include another element to pull the security group:
aws rds describe-db-instances --region us-east-1 --query 'DBInstances[*].VpcSecurityGroups[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroupId]' --output text
...I get:
none none sg-id
I am not quite sure why my first two columns now become none and the sg-id is presented.

The difference is VpcSecurityGroups[*]:
'DBInstances[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroupId]'
vs
'DBInstances[*].VpcSecurityGroups[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroupId]'
In the second one, you are receiving none because DBInstanceIdentifier and PubliclyAccessible are not attributes of VpcSecurityGroups.
Here's a portion of an output to show the hierarchy:
{
"DBInstances": [
{
"PubliclyAccessible": false,
"VpcSecurityGroups": [
{
"Status": "active",
"VpcSecurityGroupId": "sg-1203dc23"
}
],
"DBInstanceIdentifier": "mydbinstance-1"
}
]
}
Try this instead:
'DBInstances[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroups[*].VpcSecurityGroupId]'
It won't look very pretty if there are multiple security groups, since it is a one-to-many relationship.

Related

How do I get the value of a tag in the aws cli describe-instances output?

I want to get the instance id and the value of the name tag, this doesn't work:
aws ec2 describe-instances --filters 'Name=tag:Name,Values=InstaneNameTagPrefix*' --query 'Reservations[*].Instances[*].{InstanceId:InstanceId,Tags:Tags.Key=Name}'
After going this through JMESPath example, I was able to make it working. Try this and let me know how it goes at your end.
aws ec2 describe-instances --filters 'Name=tag:Name,Values=myDevEC2*' --query 'Reservations[*].Instances[*].{InstanceId:InstanceId,Tags:Tags[?Key == `Name`] | [0].Value}'
Output -
[
[
{
"InstanceId": "i-xxxxxxxxxxxxxx",
"Tags": "myDevEC2-123"
}
]
]
Since Tags is an array, you will need to filter to just Name pair. After that pipe the Tags result and select Value.
PS - You might want to rename JSON output second element to InstanceName instead Tags :)

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]

How to filter results from AWS CLI command

How can I filter the following so just results with IP starting with 10.* are returned?
aws ec2 describe-instances --filters "Name=tag-value,Values=mytagavalue" --query 'Reservations[*].Instances[*].{InstanceId:InstanceId,PrivateDnsName:PrivateDnsName,State:State.Name, IP:NetworkInterfaces[0].PrivateIpAddress}'
[
[
{
"InstanceId": "i-12345bnmsdfod",
"PrivateDnsName": "ip-10-34-24-4.my.there.com",
"State": "running",
"IP": "10.10.10.4"
}
],
[
{
"InstanceId": "i-12345bnmsdfop",
"PrivateDnsName": "",
"State": "terminated",
"IP": null
}
],
Option 1) Via Filters
Use the network-interface.addresses.private-ip-address filter to select values matching only "10.*", which will match addresses starting with "10.".
--filters "Name=network-interface.addresses.private-ip-address,Values=10.*"
Simply include a space between different filters to delimit them.
Full Example
aws ec2 describe-instances --filters "Name=tag-value,Values=mytagavalue" "Name=network-interface.addresses.private-ip-address,Values=10.*" --query 'Reservations[*].Instances[*].{InstanceId:InstanceId,PrivateDnsName:PrivateDnsName,State:State.Name, IP:NetworkInterfaces[0].PrivateIpAddress}'
Option 2) Via Query
Use the JMESPath starts_with() function to perform a partial string comparison of "10." against each network interface's private IP address.
Step By Step
First, select all instances:
Reservations[].Instances[]
Then pipe to filter for only instances containing network interfaces that have a private ip address starting with "10.":
| [? NetworkInterfaces [? starts_with(PrivateIpAddress, '10.')]]
Then select the fields just like you did before. This has not changed. (Note that you may want to select for all network interfaces instead of just the first.)
.{InstanceId:InstanceId,PrivateDnsName:PrivateDnsName,State:State.Name, IP:NetworkInterfaces[0].PrivateIpAddress}"
Full Example
aws ec2 describe-instances --filters "Name=tag-value,Values=mytagavalue" --query "Reservations[].Instances[] | [? NetworkInterfaces [? starts_with(PrivateIpAddress, '10.')]].{InstanceId:InstanceId,PrivateDnsName:PrivateDnsName,State:State.Name, IP:NetworkInterfaces[0].PrivateIpAddress}"
Further Reading
JMESPath Documentation - starts_with()
AWS Documentation - Controlling Command Output from the AWS Command Line Interface
AWS Documentation - Listing and Filtering Using the CLI and API

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"
]
]

How to remove extra parentheses and angular brackets while using aws cli?

I am trying to get the info using of NetworkInterface using following command.
[root#ip-172-29-45-82 ~]# aws ec2 describe-instances --instance-ids i-dd6f6f53 --query Reservations[*].{VpcId:Instances[*].NetworkInterfaces[*].VpcId}
[
{
"VpcId": [
[
"vpc-38fb075d"
]
]
}
]
I don't want extra parentheses and angular brackets.
It should be something like as follows:
["VpcId":"vpc-38fb075d"] or [{"VpcId":"vpc-38fb075d"}] or {"VpcId":"vpc-38fb075d"}
Is there any way to achieve above output from the above command.
Thanks in advance.
Result can be further refined by adding this to the end of your command
--output text
And the output will be unstructured text:
"VpcId": "vpc-38fb075d"
I solved it.
I used following command.
aws ec2 describe-instances --instance-ids i-dd6f6f53 --query Reservations[0].{VpcId:Instances[0].NetworkInterfaces[0].VpcId}
I just changed * to 0 and its working.
Now the output is
{
"VpcId": "vpc-38fb075d"
}
You could run - given that you can't have ENIs in different VPCs:
aws ec2 describe-instances --query 'Reservations[].Instances[].VpcId' --output text --instance-ids i-dd6f6f53
You can also try nesting your JSON objects - for example, trying to get the name tag from the parent bracket Tags:
aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,PrivateIpAddress, [Tags[?Key==`Name`].Value][0][0]]' --output text
It is easier to develop the query using the JSON output, then cleaning things up with --output text.