Adding SQS redrive policy using AWS CLI command - amazon-web-services

I am trying to set redrive policy for SQS using the AWS CLI Command below , but seeing an error related to redrive JSON. Can you please let me know how I can fix this?
redrive_policy="{\"RedrivePolicy\":{\"deadLetterTargetArn\":\"$dlq_arn\",\"maxReceiveCount\":\"15\"}}"
AWS CLI COMMAND
aws sqs set-queue-attributes --queue-url https://queue.amazonaws.com/12345678/test-queue --attributes $redrive_policy --region=us-east-1
Error Message
Parameter validation failed: Invalid type for parameter
Attributes.RedrivePolicy, value: OrderedDict([(u'deadLetterTargetArn',
u'arn:aws:sqs:us-east-1:12345678:dlq'), (u'maxReceiveCount', u'15')]),
type: , valid types:

Have you tried just creating the JSON in a separate file and passing it as an argument to your AWS CLI command? I find it's difficult to get all of the escaping correct when passing the JSON as a parameter. So you'd basically do it as the example shows in the AWS documentation:
https://docs.aws.amazon.com/cli/latest/reference/sqs/set-queue-attributes.html#examples
So first you'd create a new file called "set-queue-attributes.json" like so:
{
"DelaySeconds": "10",
"MaximumMessageSize": "131072",
"MessageRetentionPeriod": "259200",
"ReceiveMessageWaitTimeSeconds": "20",
"RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:80398EXAMPLE:MyDeadLetterQueue\",\"maxReceiveCount\":\"1000\"}",
"VisibilityTimeout": "60"
}
Then run the command like this:
aws sqs set-queue-attributes --queue-url https://sqs.us-east-1.amazonaws.com/80398EXAMPLE/MyNewQueue --attributes file://set-queue-attributes.json --region=us-east-1

if you want to run in the same command you can use this example:
aws sqs set-queue-attributes \
--queue-url https://sqs.us-east-1.amazonaws.com/80398EXAMPLE/MyNewQueue \
--attributes '{
"RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:80398EXAMPLE:MyDeadLetterQueue\",\"maxReceiveCount\":\"1000\"}",
"MessageRetentionPeriod": "259200",
"VisibilityTimeout": "90"
}'

Three Methods to achieve this:
Note: The solutions also work on any other AWS CLI commands that require a stringified JSON
1. Using the Command-line JSON processor jq (Recommended)
This method is recommended because of many reasons:
I've found jq a handy tool to use when working with AWS CLI as the need to stringify JSON comes up quite frequently.
Install for Ubuntu: sudo apt install jq
Basic Options:
jq -R: Returns the stringified JSON
jq -c: Eliminates spacing and newline characters
The benefit is that you can write JSON as JSON and Pipe the result into the jq -R command.
Method 1:
aws sqs set-queue-attributes \
--queue-url "https://sqs.ap-south-1.amazonaws.com/IAMEXAMPLE12345678/ExampleQueue" \
--attributes RedrivePolicy=$(echo '{"maxReceiveCount":500,"deadLetterTargetArn":"arn:aws:sqs:ap-south-1:IAMEXAMPLE12345678:ExampleDeadLetterQueue"}' | jq -R)
OR if you have a sqs-redrive-policy.json file:
Method 2:
In sqs-redrive-policy.json,
{
"maxReceiveCount": 500,
"deadLetterTargetArn": "arn:aws:sqs:ap-south-1:IAMEXAMPLE12345678:ExampleDeadLetterQueue"
}
Run in Command Line:
aws sqs set-queue-attributes \
--queue-url "https://sqs.ap-south-1.amazonaws.com/IAMEXAMPLE12345678/ExampleQueue" \
--attributes RedrivePolicy=$(cat ~/path/to/file/sqs-redrive-policy.json | jq -c | jq -R)
As you can see the second benefit is that you can isolately modify only the --redrive-policy without having to touch any of the other attributes.
Common Confusion: A confusion is the name set-queue-attributes (it would be better named put-queue-attributes). as it doesn't overwrite all attributes but only overwrites the attributes mentioned with the command. So if you already set a Policy attribute earlier during create-queue, this will not overwrite the Policy to null. In other words, this is safe to use.
2. Using a stringified JSON
This is a pain to be honest, and I avoid this.
aws sqs set-queue-attributes \
--queue-url "https://sqs.us-east-1.amazonaws.com/IAMEXAMPLE12345678/ExampleQueue" \
--attributes '{
"RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:ap-south-1:IAMEXAMPLE12345678:ExampleDeadLetterQueue\",\"maxReceiveCount\":\"500\"}",
}'
3. Use a filePathURL to the JSON file for attributes.json NOT sqs-redrive-policy.json
This is my last preference.
Reason:
This means setting all the attributes specified in the attributes.json file again at a single go.
Doesn't escape the pain of writing stringified JSON as text.
In attributes.json,
{
"RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:ap-south-1:IAMEXAMPLE12345678:ExampleDeadLetterQueue\", \"maxReceiveCount\":\"5\"}"
}
Run in command line:
aws sqs set-queue-attributes \
--queue-url "https://sqs.ap-south-1.amazonaws.com/IAMEXAMPLE12345678/ExampleQueue" \
--attributes file:///home/yourusername/path/to/file/attributes.json

Related

Custom prefix string is not evaluated by localstack firehose with s3 destination

I'm trying to test a firehose delivery-stream to s3 creation with custom prefix, using localstack
https://docs.aws.amazon.com/firehose/latest/dev/s3-prefixes.html
but it seems that the format string I send as Prefix parameter is not evaluated, but rather taken as is and placed as prefix.
This is the aws cli command I'm using to create the delivery-stream
aws --endpoint-url $EP_URL firehose create-delivery-stream \
--delivery-stream-name $DELIVERY_STREAM_NAME \
--region $TEST_REGION \
--s3-destination-configuration "RoleARN=arn:aws:iam::123456789012:role/Test-Role,BucketARN=$DEST_BUCKET, \
BufferingHints={SizeInMBs=1,IntervalInSeconds=60},\
Prefix=\"myprefix/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/hour=!{timestamp:HH}/\""
and this is the resulting object in s3 after writing to the stream:
aws --endpoint-url $EP_URL s3 ls --recursive $DEST_BUCKET | tail -n 20
2022-11-23 17:11:10 5 myprefix/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/hour=!{timestamp:HH}/2022/11/23/15/mystream-2022-11-23-15-11-10-dd405ee0-0f74-4a16-9e24-df936935b782
Any ideas anyone? Thank you in advance!

Adding tags to multiple SQS queues through a single cli command or a script

I have multiple aws sqs queues and some have tags but some do not. Now I want to add tags to the ones which do not have them. We have the cli command: aws sqs tag-queue to add tags for a single queue. Is it possible to add multiple tags to multiple queues through a single cli command or would I have to write it through any script.
The cli command aws sqs tag-queue can only target a single queue. However, you could write a script that loops over all queues and calls tag-queue for each.
#!/bin/bash
for url in $(aws sqs list-queues --output text --query 'QueueUrls')
do
aws sqs tag-queue --queue-url $url --tags YourKey=YourValue
done
You can use the resourcegroupstaggingapi tag-resources command to tag (almost) any arbitrary resources you'd like, not just SQS queues!
For example,
aws resourcegroupstaggingapi tag-resources \
--resource-arn-list arn:aws:sqs:us-east-2:123456789:foobarqueue arn:aws:sqs:us-east-2:123456789:fizzbuzzqueue \
--tags Foo=Bar,Fizz=Buzz
Note that you can also do this in the console if you find that easier if you click on Resource Groups > Tag Editor at the top of the console.
This worked for me using the AWS CLI :
queueurl=https://sqs.us-west-2.amazonaws.com/<yourAWSaccountnumber>/L7Cn
aws sqs tag-queue --queue-url $queueurl --tags Key1=Value1,Key2=Value2
I recommend creating tags when initially creating the SQS queue using the AWS CLI :
queuename=trymeout
aws sqs create-queue --queue-name $queuename --tags Key1=Value1,Key2=Value2
Then check your tags after creating the SQS queue using the AWS CLI :
aws sqs list-queue-tags --queue-url https://sqs.us-west-2.amazonaws.com/<yourAWSaccountnumber>/trymeout
Make sure you have the newest AWS CLI installed.
Older versions of the AWS CLI can contain bugs so....
To get my AWS CLI version I run : aws --version and today I get:
aws-cli/2.7.14 Python/3.9.11 Darwin/21.5.0 exe/x86_64 prompt/off

aws cli command to subscribe to a topic with filters

I'm trying to write a cross account aws cli command to subscribe to a topic and create a filter for that subscription at the same time. Below is how my command looks like.
aws sns subscribe --topic-arn arn:aws:sns:region:accountId:my_topic --protocol sqs --notification-endpoint arn:aws:sqs:region:differentAccountId:my_sqs_queue --attributes "{'RawMessageDelivery': 'true', 'FilterPolicy': '{\"filter\": [\"value1\", \"value2\"]}'}"
I'm getting below error when I run this.
Unknown options: --attributes, [\value1\,, \value2\]}'}, {'RawMessageDelivery': 'true', 'FilterPolicy': '{" filter\:
I've access to admin access both the aws accounts. Any suggestions on what I'm doing wrong?
EDIT:
I'm running this in VS Code powershell terminal in windows.
There's probably an easier way to do it (eg using --cli-input-json and providing JSON in a file), but I got this working:
aws sns subscribe \
--topic-arn arn:aws:sns:region:accountId:my_topic \
--protocol sqs \
--notification-endpoint arn:aws:sqs:region:differentAccountId:my_sqs_queue \
--attributes '{\"RawMessageDelivery\": \"true\", \"FilterPolicy\": \"{\\\"filter\\\": [\\\"value1\\\", \\\"value2\\\"]}\"}'
The problem was the JSON included in a string, which needed \" to be escaped as \\\".
This Github repo has an example: https://github.com/Haple/sns-sqs-subscribe
#!/bin/sh
# SETUP
queue_arn=$(awslocal sqs create-queue --queue-name test_queue --output text)
echo "Queue ARN: $queue_arn"
topic_arn=$(awslocal sns create-topic --name test_topic --output text)
echo "Topic ARN: $topic_arn"
subscription_arn=$(awslocal sns subscribe \
--topic-arn "$topic_arn" \
--protocol sqs \
--notification-endpoint "$queue_arn" \
--output text)
echo "Subscription ARN: $subscription_arn"
awslocal sns set-subscription-attributes \
--subscription-arn "$subscription_arn" \
--attribute-name FilterPolicy \
--attribute-value "{ \"EVENT_TYPE\": [\"SUCCESS\"] }"
# TEST
awslocal sns publish \
--topic-arn "$topic_arn" \
--message "SUCCESS PAYLOAD (SHOULD GO TO THE QUEUE)" \
--message-attributes '{"EVENT_TYPE" : { "DataType":"String", "StringValue":"SUCCESS"}}'
awslocal sns publish \
--topic-arn "$topic_arn" \
--message "ERROR PAYLOAD (SHOULD NOT GO TO THE QUEUE)" \
--message-attributes '{"EVENT_TYPE" : { "DataType":"String", "StringValue":"ERROR"}}'
awslocal sqs get-queue-attributes \
--queue-url http://localhost:4576/queue/test_queue \
--attribute-names All
The overall process in the previous answers is OK, but there is a huge issue:
I do not know why no one is mentioning this, but the whole thing doesn't work if you do not set the SQS queue policy document correctly.
The github example doesn't do it and for some reason, AWS documentation doesn't even mention it.
Refer to this question: Set SQS policy document with AWS CLI
I wasted a couple of days troubleshooting this. So hope it helps.

Access updated lambda version from command: `aws lambda publish-version`

My CI pipeline will do two things
generate new lambda version and publish
Update an alias to point at that new version
This will be done via cli commands. My question is, how do I access the version number that been generated from the first command. It is returned and posted to the CLI. Can this be access easily via some nifty was command or will I have to parse it myself?
e.g.
version=$(aws lambda publish-version \
--function-name test_lambda --description "updated via cli" --region eu-west-1 \
--query Version \
--output text)
See Controlling Command Output from the AWS Command Line Interface page of AWS CLI User Guide, specifically How to Filter the Output with the --query Option and Text Output Format
This works but still curious if there is a better way.
version=$(aws lambda publish-version --function-name test_lambda --description "updated via cli" --region eu-west-1| jq '.Version')
NEW_LAMBDA_VERSION=$(aws lambda list-versions-by-function --function-name $LAMBDA_NAME_FOR_DEPLOY --no-paginate --query "max_by(Versions, &to_number(to_number(Version) || '0'))")
NEW_LAMBDA_VERSION=$(echo $NEW_LAMBDA_VERSION | jq -r .Version)
echo $NEW_LAMBDA_VERSION
In this case, I use on .gitlab-ci.yml.

How pass json as parameter to aws cli?

I am trying to update crawler using this command:
aws glue update-crawler --name my-crawler --configuration '{"Version":1.0,"CrawlerOutput":{"Partitions":{"AddOrUpdateBehavior":"InheritFromTable"}}}' --region us-west-2
As described here
Instead of update I got:
An error occurred (InvalidInputException) when calling the UpdateCrawler operation: Crawler configuration not valid: Error parsing JSON: Received JsonParseException: Unexpected character (''' (code 39)): expected a valid value (number, String, array, object, 'true', 'false' or 'null'). Check that your JSON is well formed. For more information about the crawler configuration structure, see http://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-crawler-crawling.html.
The jsonlint tells me that json is ok.
What is wrong? How pass json as parameter for aws cli?
cli is used under windows 10
You have to escape the quotes under Windows:
aws glue update-crawler --name my-crawler --configuration "{\"Version\":1.0,\"CrawlerOutput\":{\"Partitions\":{\"AddOrUpdateBehavior\":\"InheritFromTable\"}}}" --region us-west-2
For Windows, you have to do some "special" escaping, which I've learned the hard way. Take the following JSON snippet...
{ "#t": "timestamp" }`
Here's how you'd enter it on Windows...
DOS
aws dynamodb scan --table-name MyTable --region "us-east-1" --profile dev --projection-expression "failureKey, #t" --expression-attribute-names "{ ""#t"": ""timestamp"" }"
For Powershell, it's a little different...
Powershell
aws dynamodb scan --table-name "MyTable" --region "us-east-1" --profile "dev" --projection-expression "failureKey, #t" --expression-attribute-names '{ \"#t\": \"timestamp\" }'
Used an example with a shorter JSON snippet, but you get the idea. Apply the same concept to your string based on the shell your using.