Say I have the following output from querying a CloudFormation stack:
$ aws cloudformation describe-stacks --stack-name my-stack --query "Stacks[0].Outputs[*]"
[
{
"OutputKey": "VPC",
"OutputValue": "vpc-123abcd"
},
{
"OutputKey": "SubnetAZ2",
"OutputValue": "subnet-456efgh"
},
{
"OutputKey": "SubnetAZ1",
"OutputValue": "subnet-789ijkl"
},
{
"OutputKey": "PrivateSubnetAZ2",
"OutputValue": "subnet-012mnop"
},
{
"OutputKey": "PrivateSubnetAZ1",
"OutputValue": "subnet-345qrst"
}
]
I would like to format this output into a string which can be used in a aws cloudformation create-stack command, like this:
aws cloudformation create-stack \
...
--parameters "ParameterKey=VPC,ParameterValue=vpc-123abcd ParameterKey=SubnetAZ2,..."
Question: How can I convert a list of objects (like the one above) to a formatted string (like the one above) with JMESPath?
It seems like it should be possible by using map, something down the lines of:
--query Stacks[0].Outputs[*].{ParameterKey: OutputKey, ParameterValue: OutputValue} | map([&ParameterKey,&ParameterValue], #)
You can try the following:
aws cloudformation describe-stacks --stack-name <stack-name> --query "Stacks[0].Outputs[*].[join(',', [join('=',['ParameterKey', OutputKey]), join('=',['ParameterValue', OutputValue])])] | join(' ', [])" --output text
Its rather unreadable, but JMESPath syntax is far from pretty. Basically, the idea is that using join you contract the entire string in the format required.
First you construct inner parts (e.g. ParameterKey=VPC and ParameterValue=vpc-123abcd), which then you join into ParameterKey=VPC,ParameterValue=vpc-123abcd. Finally you join all them together to construct ParameterKey=VPC,ParameterValue=vpc-123abcd ParameterKey=SubnetAZ2,ParameterValue=subnet-456efgh
Related
I am running
aws configservice get-compliance-details-by-config-rule --config-rule-name required-tags --compliance-types NON_COMPLIANT
with output
{
"EvaluationResults": [
{
"EvaluationResultIdentifier": {
"EvaluationResultQualifier": {
"ConfigRuleName": "required-tags",
"ResourceType": "AWS::ACM::Certificate",
"ResourceId": "arn:aws:acm:us-east-1:***:certificate/d9863cca-9e7b-460b-b9f8-bee23e8fb607"
},
"OrderingTimestamp": "2022-08-10T12:46:18.247000+05:30"
},
"ComplianceType": "NON_COMPLIANT",
"ResultRecordedTime": "2022-08-10T13:12:00.037000+05:30",
"ConfigRuleInvokedTime": "2022-08-10T13:11:59.841000+05:30"
},
{
"EvaluationResultIdentifier": {
"EvaluationResultQualifier": {
"ConfigRuleName": "required-tags",
"ResourceType": "AWS::EC2::Instance",
"ResourceId": "i-069c8d8c72ae8db8c"
},
"OrderingTimestamp": "2022-08-10T12:46:18.784000+05:30"
},
"ComplianceType": "NON_COMPLIANT",
"ResultRecordedTime": "2022-08-10T13:11:54.648000+05:30",
"ConfigRuleInvokedTime": "2022-08-10T13:11:54.449000+05:30
I need arn names of all the resources under the rule
and need to run
aws tag-resources
--resource-arn-list <value>
--tags <value>
[--cli-input-json <value>]
[--generate-cli-skeleton <value>]
THe problem is the the aws configservice get-compliance-details-by-config-rule command doen't list the arn of the resources and i need arn of each resource to be tagged.
What can i do?
You can construct Amazon EC2 instances ARNs using aws ec2 describe-instances command line. Please note that I used jq for that so you will need it if you want to use this method.
You can aws ec2 describe-instances with a filter by instance-id. In this case the instance-id corresponds to the ResourceId in your output. It should return the all data regarding the specified instance.
Your command line should look like aws ec2 describe-instances --region eu-west-3 --instance-id i-abd123.
Then you can format the result using jq.
aws ec2 describe-instances --region us-east-1 --instance-id i-abc123 | jq -r '.Reservations[] | .OwnerId as $OwnerId | ( .Instances[] | { "ARN": "arn:aws:ec2:\(.Placement.AvailabilityZone[:-1]):\($OwnerId):instance/\(.InstanceId)"} )' | jq -s .
The output should look like this:
[
{
"ARN": "arn:aws:ec2:us-east-1:***:instance/i-abc123"
}
]
I want to filter the exported output values of this command aws cloudformation list-exports using jq or query.
Example of Data:
{
"Exports": [
{
"ExportingStackId": "arn:aws...",
"Name": "RSC-NAME-2",
"Value": "RSC-VALUE-2"
},
{
"ExportingStackId": "arn:aws...",
"Name": "My-RSC-NAME",
"Value": "My-RSC-VALUE"
}
]
}
I'm looking for a command that can return the Value and filter by Name
Example: if i search by Name equal to My-RSC-NAME the result will be My-RSC-VALUE
We can easily do with native --query
aws cloudformation list-exports --query
"Exports[?Name=='ThisIsNameOfExport'].Value" --output text
Using jq:
.Exports[] | select(.Name == "My-RSC-NAME").Value
I am trying to retrieve all the parameters under a specific path from the AWS Parameter store using the command below:
aws ssm get-parameters-by-path --path some-path --no-paginate
This returns me a JSON with a lot of fields I do not need. How can I use the --query to just retrieve the name and the value?
Any documentation on how can I use the --query parameter? I have tried passing jq query strings, but that doesn't work.
You need to extract the fields from Parameters(Array) and later select the fields you want to get using {key:value} syntax:
aws ssm get-parameters-by-path --path %PATH% --no-paginate --region %REGION% --query "Parameters[].{Key:Name,Val:Value}" --output json
Output Json:
[
{
"Key": "/test/amit",
"Val": "test1"
},
{
"Key": "/test/amit1",
"Val": "test2"
}
]
Or in case you want the output in text, change --output to text.
Output Text:
/test/amit test1
/test/amit1 test2
More info about Controlling Command Output from the AWS CLI.
How to get Latest Published version of a Lambda Function?
Apart from $LATEST, how can I get the result as "5"
$ aws lambda list-versions-by-function --function-name My_Lambda_Function --query 'Versions[*][Version, FunctionArn]' --output json
[
[
"$LATEST",
"arn:aws:lambda:us-east-2:123456789000:function:My_Lambda_Function:$LATEST"
],
[
"1",
"arn:aws:lambda:us-east-2:123456789000:function:My_Lambda_Function:1"
],
[
"2",
"arn:aws:lambda:us-east-2:123456789000:function:My_Lambda_Function:2"
],
[
"3",
"arn:aws:lambda:us-east-2:123456789000:function:My_Lambda_Function:3"
],
[
"4",
"arn:aws:lambda:us-east-2:123456789000:function:My_Lambda_Function:4"
],
[
"5",
"arn:aws:lambda:us-east-2:123456789000:function:My_Lambda_Function:5"
]
]
I found this thread on GitHub insightful, you can get the maximum non-$LATEST item a few ways but only one of them is correct:
Wrong way, this command will be correct only as far as version 9 because it will string-compare the versions and decide that "9" is greater than "10":
aws lambda list-versions-by-function --function-name my_lambda \
--query "max_by(Versions, &Version)"
Wrong way, this command will be correct only as far as version 50 (or whatever the page size is) because it will only filter the results that are returned in the first page.
aws lambda list-versions-by-function --function-name my_lambda \
--query "Versions[-1]"
Wrong way, this command will consider all the results before filtering them, but still assumes that they will be in proper order
aws lambda list-versions-by-function --function-name my_lambda \
--no-paginate \
--query "Versions[-1]"
Wrong way, this command looks right for sorting purposes but will choke on to_number("$LATEST") returning null.
aws lambda list-versions-by-function --function-name my_lambda \
--no-paginate \
--query "max_by(Versions, &to_number(Version))"
Wrong way, this command looks right for sorting purposes but (on my machine) doesn't accept the literal 0.
aws lambda list-versions-by-function --function-name my_lambda \
--no-paginate \
--query "max_by(Versions, &to_number(Version) || '0')"
Right way, this command will fetch all the all the results before considering them, and works around the issue of numeric literals by converting to a number twice.
aws lambda list-versions-by-function --function-name my_lambda \
--no-paginate \
--query "max_by(Versions, &to_number(to_number(Version) || '0'))"
You can get all the version using list-versions-by-function and then extract second last with jq
aws lambda list-versions-by-function --function-name LogsToElasticsearch_goabode --max-items 5 \
--query 'Versions[*].[Version,FunctionName]' | jq '.[-1]'
Or to get all with name
aws lambda list-versions-by-function --function-name my_lambda \
--max-items 5 --query 'Versions[*].[Version,FunctionName]'
If your lambda is always published using a Lambda function alias pointing to your latest version, then the cli query can be reduced to a single call w/o any pagination using the get-alias command.
The following are placeholders; replace with your values as-needed:
[FunctionName]
[AliasName]
[AwsAccountNumber] (nothing to replace; just a placeholder)
Full query:
aws lambda get-alias \
--function-name [FunctionName] \
--name [AliasName]
Result:
{
"AliasArn": "arn:aws:lambda:us-east-1:[AwsAccountNumber]:function:[FunctionName]:[AliasName]",
"Name": "[AliasName]",
"FunctionVersion": "15",
"Description": "Yada Yada Yada",
"RevisionId": "7aa54e5c-1b32-4436-abcd-cf0a1aacad5a"
}
Reduced query to return only the version number:
aws lambda get-alias \
--function-name [FunctionName] \
--name [AliasName] \
--query "to_number(FunctionVersion)"
Payload:
15
I would like to clone a cloudformation stack in the same region. Is this possible today using the Cloudformation console?
I have a cloudformation template that takes in a big list of parameters. Many times I want to create an identical stack with just a different stack name. Is there a quick way of doing this using the AWS console?
I am thinking of something along the lines of "Launch more like this" option in EC2.
I use the following shell script
#!/bin/sh -x
# debug
if [ -z "$1" ] ; then
STACK=jirithhu-monitorStack-1ALS8UFQP3SRV
else
STACK="$1"
fi
set -e
# parameter 1: stack ID : (example: hhu-monitorStack-1ALS8UFQP3SRV )
aws cloudformation describe-stacks --stack-name $STACK | jq .Stacks[0].Parameters > /tmp/xx.$$.pars
aws cloudformation get-template --stack-name $STACK | jq -rc .TemplateBody > /tmp/xx.$$.body
NEWNAME=`echo "COPY-$STACK"`
aws cloudformation create-stack --stack-name $NEWNAME \
--template-body file:///tmp/xx.$$.body\
--parameters "`cat /tmp/xx.$$.pars`" \
--capabilities '[ "CAPABILITY_NAMED_IAM", "CAPABILITY_AUTO_EXPAND" ]'
rm /tmp/xx.$$*
you can create an input file and quickly launch a new stack.
Ex:
Command:
aws cloudformation create-stack --stackname startmyinstance
--template-body file://startmyinstance.json
--parameters file://startmyinstance-parameters.json
Parameters file:
[
{
"ParameterKey": "KeyPairName",
"ParameterValue": "MyKey"
},
{
"ParameterKey": "InstanceType",
"ParameterValue": "m1.micro"
}
]
Ref: https://aws.amazon.com/blogs/devops/passing-parameters-to-cloudformation-stacks-with-the-aws-cli-and-powershell/