しようとしたら失敗したので備忘録的に解決策を残しておこうと思いました。
AWS曰く
このクールなコードでビルドできるよ!
とのこと。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Example of processing messages on an SQS queue with Lambda
Resources:
MySQSQueueFunction:
Type: AWS::Serverless::Function
Properties:
Handler: handler
Runtime: runtime
Events:
MySQSEvent:
Type: SQS
Properties:
Queue: !GetAtt MySqsQueue.Arn
BatchSize: 10
MySqsQueue:
Type: AWS::SQS::Queue
出典:AWS SAM Template for an Amazon SQS Application
そして失敗
エラー1:LambdaがSQSを呼ぶ権限がない
謎のエラーを吐いてCloudFormationが失敗に終わる。
The provided execution role does not have permissions to call ReceiveMessage on SQS (Service: AWSLambda; Status Code: 400; Error Code: InvalidParameterValueException
Lambdaに設定したロールには AWSLambdaSQSQueueExecutionRole が付いている。
つまりIAMロールには(おそらく)問題がない。
なぜ失敗する?
解決1:SQSにも権限の設定をする
冷静に考えたら、コンソールからキューを作る時も権限をいじった気がする。
というわけで、下記を追加する事で上述のエラーは出なくなった。
MySqsQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
PolicyDocument:
Id: !Ref MySqsQueue
Statement:
- Sid: QueuePolicy-MySqsQueue
Effect: Allow
Principal: "*"
Action: "SQS:*"
Resource:
Fn::GetAtt:
- MySqsQueue
- Arn
Queues:
- !Ref MySqsQueue
エラー2:キューの可視性タイムアウトがLambdaのタイムアウトより短い
エラー1が解決したら、今度はこれが出るようになった。
コンソールから設定する時はあなたそんな事言わなかったじゃない。
Queue visibility timeout: 30 seconds is less than Function timeout: 60 seconds
解決2:可視性タイムアウトを伸ばす
明示的に指定しないとdefaultで30秒になるらしいので、キューのPropertiesにVisibilityTimeoutを設定する。
※Lambdaのタイムアウトを明示的に60秒にしていたので、もしかしたらその設定の影響かもしれない。
MySqsQueue:
Type: AWS::SQS::Queue
Properties:
VisibilityTimeout: 60
結論
SQSキューポリシーと、可視性タイムアウトの設定をするとうまくいきました。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Example of processing messages on an SQS queue with Lambda
Resources:
MySQSQueueFunction:
Type: AWS::Serverless::Function
Properties:
Handler: handler
Runtime: runtime
Timeout: 60
Events:
MySQSEvent:
Type: SQS
Properties:
Queue: !GetAtt MySqsQueue.Arn
BatchSize: 10
MySqsQueue:
Type: AWS::SQS::Queue
Properties:
VisibilityTimeout: 60
MySqsQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
PolicyDocument:
Id: !Ref MySqsQueue
Statement:
- Sid: QueuePolicy-MySqsQueue
Effect: Allow
Principal: "*"
Action: "SQS:*"
Resource:
Fn::GetAtt:
- MySqsQueue
- Arn
Queues:
- !Ref MySqsQueue
蛇足
実はこの前段階でCloudFormationの実行ロールにSQSの権限が無かった事により一度失敗している。
CodeStarを使っているため、自動で作成されるロールに何の疑問も持たなかった事が原因ですね。私は悲しい。