chakimar Blog

Amplifyで作成したLambdaにトリガーを指定する

March 20, 2020

Amplifyで作成したLambdaにトリガーを指定することが可能だが、やり方がバラバラなのでまとめてみた。

amplify version: 4.13.4

DynamoDBトリガー

AppSyncIdがテーブル名に使われているため、AppSyncIdを取得する必要がある。

(追記1) Lambdaを新規追加する場合は amplify add function時にDynamoDBトリガーを指定できるっぽい

(追記2) amplify version 4.16.1では、 amplify function update時に storageを選択するとDynamoDBを選択できるようになるので 手動でCloudFormationをいじらなくて良さそう 結局手動でCloudFormationの追加が必要

手順

  1. amplify function update を実行し、APIを紐付ける
? Please select the Lambda Function you would want to update

-> 対象のfunction選択

? Do you want to update permissions granted to this Lambda function to perform o
n other resources in your project?

-> Y

? Select the category (Press <space> to select, <a> to toggle all, <i> to invert
 selection)

-> apiをspaceで選択

? Api has x resources in this project. Select the one you would like your Lambda
 to access (Press <space> to select, <a> to toggle all, <i> to invert selection)

-> 対象のapiを選択

? Select the operations you want to permit for vacaite (Press <space> to select,
 <a> to toggle all, <i> to invert selection)

-> readをspaceで選択

? Do you want to edit the local lambda function now?

-> lambdaを編集したければY

  1. 以下を amplify/backend/function/FUNCTION_NAME/FUNCTION_NAME-cloudformation-template.jsonResouces以下に 追加し、XXXXXX を api名に変更、 YYYYYYをトリガーにするテーブル名に変更する
"EventSourceMapping": {
	"Type": "AWS::Lambda::EventSourceMapping",
	"DependsOn": [
		"LambdaExecutionRole",
		"CustomPolicyForTableStreamSubscription"
	],
	"Properties": {
		"EventSourceArn": {
			"Fn::ImportValue": {
				"Fn::Sub": "${apiXXXXXXGraphQLAPIIdOutput}:GetAtt:YYYYYYTable:StreamArn"
			}
		},
		"FunctionName": {
			"Fn::GetAtt": [
				"LambdaFunction",
				"Arn"
			]
		},
		"StartingPosition": "TRIM_HORIZON"
	}
},
"CustomPolicyForTableStreamSubscription": {
	"Type": "AWS::IAM::Policy",
	"DependsOn": [
		"LambdaExecutionRole"
	],
	"Properties": {
		"PolicyName": "dynamodb-stream-permission",
		"Roles": [
			{
				"Ref": "LambdaExecutionRole"
			}
		],
		"PolicyDocument": {
			"Version": "2012-10-17",
			"Statement": [
				{
					"Effect": "Allow",
					"Action": [
						"dynamodb:GetRecords",
						"dynamodb:GetShardIterator",
						"dynamodb:DescribeStream",
						"dynamodb:ListStreams"
					],
					"Resource": [
						{
							"Fn::ImportValue": {
								"Fn::Sub": "${apiXXXXXXGraphQLAPIIdOutput}:GetAtt:YYYYYYTable:StreamArn"
							}
						}
					]
				}
			]
		}
	}
}

複数のDynamoDBテーブルをトリガーにする場合

以下のように AWS::Lambda::EventSourceMappingリソースを複数作成し、 CustomPolicyForTableStreamSubscriptionResource にテーブルを追加する

"YYYYYYEventSourceMapping": {
	"Type": "AWS::Lambda::EventSourceMapping",
	"DependsOn": [
		"LambdaExecutionRole",
		"CustomPolicyForTableStreamSubscription"
	],
	"Properties": {
		"EventSourceArn": {
			"Fn::ImportValue": {
				"Fn::Sub": "${apiXXXXXXGraphQLAPIIdOutput}:GetAtt:YYYYYYTable:StreamArn"
			}
		},
		"FunctionName": {
			"Fn::GetAtt": [
				"LambdaFunction",
				"Arn"
			]
		},
		"StartingPosition": "TRIM_HORIZON"
	}
},
"ZZZZZZEventSourceMapping": {
	"Type": "AWS::Lambda::EventSourceMapping",
	"DependsOn": [
		"LambdaExecutionRole",
		"CustomPolicyForTableStreamSubscription"
	],
	"Properties": {
		"EventSourceArn": {
			"Fn::ImportValue": {
				"Fn::Sub": "${apiXXXXXXGraphQLAPIIdOutput}:GetAtt:ZZZZZZTable:StreamArn"
			}
		},
		"FunctionName": {
			"Fn::GetAtt": [
				"LambdaFunction",
				"Arn"
			]
		},
		"StartingPosition": "TRIM_HORIZON"
	}
},
"CustomPolicyForTableStreamSubscription": {
	"Type": "AWS::IAM::Policy",
	"DependsOn": [
		"LambdaExecutionRole"
	],
	"Properties": {
		"PolicyName": "dynamodb-stream-permission",
		"Roles": [
			{
				"Ref": "LambdaExecutionRole"
			}
		],
		"PolicyDocument": {
			"Version": "2012-10-17",
			"Statement": [
				{
					"Effect": "Allow",
					"Action": [
						"dynamodb:GetRecords",
						"dynamodb:GetShardIterator",
						"dynamodb:DescribeStream",
						"dynamodb:ListStreams"
					],
					"Resource": [
						{
							"Fn::ImportValue": {
								"Fn::Sub": "${apiXXXXXXGraphQLAPIIdOutput}:GetAtt:YYYYYYTable:StreamArn"
							}
						},
						{
							"Fn::ImportValue": {
								"Fn::Sub": "${apiXXXXXXGraphQLAPIIdOutput}:GetAtt:ZZZZZZTable:StreamArn"
							}
						}
					]
				}
			]
		}
	}
}

参考URL

CloudWatchEvents

CloudFormationのテンプレートにリソースを追記する

手順

  1. 以下を amplify/backend/function/FUNCTION_NAME/FUNCTION_NAME-cloudformation-template.jsonResouces以下に 追加し、ScheduleExpression にスケジュールを指定
"ScheduledRule": {
  "Type": "AWS::Events::Rule",
  "Properties": {
    "Description": "lambda schedule",
    "ScheduleExpression": "rate(1 day)",
    "State": "ENABLED",
    "Targets": [
      {
        "Arn": {
          "Fn::GetAtt": [
            "LambdaFunction",
            "Arn"
          ]
        },
        "Id": "lambdaschedule"
      }
    ]
  }
},
"PermissionForEventsToInvokeLambda": {
  "Type": "AWS::Lambda::Permission",
  "Properties": {
    "FunctionName": {
      "Ref": "LambdaFunction"
    },
    "Action": "lambda:InvokeFunction",
    "Principal": "events.amazonaws.com",
    "SourceArn": {
      "Fn::GetAtt": [
        "ScheduledRule",
        "Arn"
      ]
    }
  }
}

S3トリガー

コマンドだけで対応可能。LambdaじゃなくてStorageの方を更新する。

手順

  1. amplify storage update を実行し、S3にLambdaを紐付ける
? Please select from one of the below mentioned services: (Use arrow keys)

-> 変更せずにEnter

? Who should have access: (Use arrow keys)

->変更せずにEnter

? What kind of access do you want for Authenticated users? (Press <space> to sel
ect, <a> to toggle all, <i> to invert selection)

-> 変更せずにEnter

? What kind of access do you want for Guest users? (Press <space> to select, <a>
 to toggle all, <i> to invert selection)

-> 変更せずにEnter

? Do you want to add a Lambda Trigger for your S3 Bucket? (y/N)

-> y

? Select from the following options (Use arrow keys)

-> Choose an existing function from the project を選択し、対象のLambdaを選択

注意事項

  • 細かいトリガーイベントは設定できない(作成系または削除系のイベントでトリガーされる)のでLambda内で振り分けが必要
  • Lambda内で同一S3に対して操作をする場合、循環参照になってしまいエラーとなる