octochat-awsのLambda関数を直接terminalから動かしてみた #reinvent
はじめに
DOP322-S - Continuous delivery to AWS with GitHub Actionsで用いられたDEMOアプリのLambda関数を直接動作させてみました。
一部手直しの必要な箇所があったため、forkした下記リポジトリに追加しています。
以下、実際に動かすための手順と修正内容です。
ソースコードの準備
DEMOアプリ全体をcloneした後で、スクリプトにてIAMロール作成・DynamoDB作成・Lambda関数作成を行います。事前に、Lambda関数として用いるパッケージをアップするためのバケットが一つ必要になります。
git clone git@github.com:haoyayoi/octochat-aws.git cd octochat-aws/functions pipenv install --python 3.7 pipenv shell pipenv install awscli export AWS_S3_BUCKET=${BUCKET_NAME} aws s3 mb s3://${AWS_S3_BUCKET} #バケット作成 script/bootstrap.sh script/pack_lambda . script/push_lambda message_add package.zip script/push_lambda messages_received_list package.zip script/push_lambda messages_sent_list package.zip
追加した修正
DEMO用リポジトリのファイルはポリシー用JSONファイルのフォーマットエラーと、特定リージョンの決め打ちが入っており、それらを修正する必要があります。
ポリシーフォーマットの修正
bootstrap.sh
を実行すると、以下のエラーが発生します。
% script/bootstrap.sh Creating lambda-default role... An error occurred (MalformedPolicyDocument) when calling the PutRolePolicy operation: The policy failed legacy parsing
lambda-full-access-policy.json
の1行目が空改行となっているため、削除します。
% vim .aws/lambda-full-access-policy.json - { "Version": "2012-10-17",
再実行します。
% ./script/bootstrap.sh Creating Messages table... { "TableDescription": { "AttributeDefinitions": [ { "AttributeName": "fromId", "AttributeType": "N" }, { "AttributeName": "receivedAt", "AttributeType": "N" }, { "AttributeName": "toId", "AttributeType": "N" } ], "TableName": "Messages", "KeySchema": [ { "AttributeName": "toId", "KeyType": "HASH" }, { "AttributeName": "receivedAt", "KeyType": "RANGE" } ], "TableStatus": "CREATING", "CreationDateTime": 1575974698.814, "ProvisionedThroughput": { "NumberOfDecreasesToday": 0, "ReadCapacityUnits": 1, "WriteCapacityUnits": 1 }, "TableSizeBytes": 0, "ItemCount": 0, "TableArn": "arn:aws:dynamodb:ap-northeast-1:XXXXXXXXXXXX:table/Messages", "TableId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "GlobalSecondaryIndexes": [ { "IndexName": "SentMessages", "KeySchema": [ { "AttributeName": "fromId", "KeyType": "HASH" }, { "AttributeName": "receivedAt", "KeyType": "RANGE" } ], "Projection": { "ProjectionType": "ALL" }, "IndexStatus": "CREATING", "ProvisionedThroughput": { "NumberOfDecreasesToday": 0, "ReadCapacityUnits": 1, "WriteCapacityUnits": 1 }, "IndexSizeBytes": 0, "ItemCount": 0, "IndexArn": "arn:aws:dynamodb:ap-northeast-1:XXXXXXXXXXXX:table/Messages/index/SentMessages" } ] } }
リージョンの決め打ち解除
以下のPythonスクリプトに対して修正を入れます。
- message_add.py
- messages_received_list.py
- messages_sent_list.py
def handler(event, context): - dynamodb = boto3.resource("dynamodb", region_name="eu-west-1") + dynamodb = boto3.resource("dynamodb")
生成されるリソース
IAMロール
lambda-defaultのIAMロールが生成されます。すでに存在する場合はポリシーが追加されます。
% aws iam get-role --role-name lambda-default { "Role": { "Description": "Lambda execution role", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" } } ] }, "MaxSessionDuration": 3600, "RoleId": "XXXXXXXXXXXXXXXXXXX", "CreateDate": "2019-12-10T10:38:48Z", "RoleName": "lambda-default", "Path": "/", "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/lambda-default" } }
DynamoDB Table
Messagesテーブルが生成されます。すでに存在する場合は作成されません。
% aws dynamodb describe-table --table-name Messages { "Table": { "TableArn": "arn:aws:dynamodb:ap-northeast-1:XXXXXXXXXXXX:table/Messages", "AttributeDefinitions": [ { "AttributeName": "fromId", "AttributeType": "N" }, { "AttributeName": "receivedAt", "AttributeType": "N" }, { "AttributeName": "toId", "AttributeType": "N" } ], "GlobalSecondaryIndexes": [ { "IndexSizeBytes": 0, "IndexName": "SentMessages", "Projection": { "ProjectionType": "ALL" }, "ProvisionedThroughput": { "NumberOfDecreasesToday": 0, "WriteCapacityUnits": 1, "ReadCapacityUnits": 1 }, "IndexStatus": "ACTIVE", "KeySchema": [ { "KeyType": "HASH", "AttributeName": "fromId" }, { "KeyType": "RANGE", "AttributeName": "receivedAt" } ], "IndexArn": "arn:aws:dynamodb:ap-northeast-1:XXXXXXXXXXXX:table/Messages/index/SentMessages", "ItemCount": 0 } ], "ProvisionedThroughput": { "NumberOfDecreasesToday": 0, "WriteCapacityUnits": 1, "ReadCapacityUnits": 1 }, "TableSizeBytes": 0, "TableName": "Messages", "TableStatus": "ACTIVE", "TableId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "KeySchema": [ { "KeyType": "HASH", "AttributeName": "toId" }, { "KeyType": "RANGE", "AttributeName": "receivedAt" } ], "ItemCount": 0, "CreationDateTime": 1575974698.814 } }
Lambda関数
以下3つの関数となります。
- message_add
- messages_received_list
- messages
message_add
% aws lambda get-function --function-name message_add { "Code": { "RepositoryType": "S3", "Location": "https://awslambda-ap-ne-1-tasks.s3.ap-northeast-1.amazonaws.com/snapshots/.... }, "Configuration": { "TracingConfig": { "Mode": "PassThrough" }, "Version": "$LATEST", "CodeSha256": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "FunctionName": "message_add", "MemorySize": 128, "RevisionId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "CodeSize": 29399523, "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:message_add", "Handler": "message_add.handler", "Role": "arn:aws:iam::XXXXXXXXXXXX:role/lambda-default", "Timeout": 3, "LastModified": "2019-12-11T04:42:44.340+0000", "Runtime": "python3.7", "Description": "" } }
messages_received_list
% aws lambda get-function --function-name messages_received_list { "Code": { "RepositoryType": "S3", "Location": "https://awslambda-ap-ne-1-tasks.s3.ap-northeast-1.amazonaws.com/snapshots/... }, "Configuration": { "TracingConfig": { "Mode": "PassThrough" }, "Version": "$LATEST", "CodeSha256": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "FunctionName": "messages_received_list", "MemorySize": 128, "RevisionId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "CodeSize": 29399523, "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:messages_received_list", "Handler": "messages_received_list.handler", "Role": "arn:aws:iam::XXXXXXXXXXXX:role/lambda-default", "Timeout": 3, "LastModified": "2019-12-11T04:43:07.340+0000", "Runtime": "python3.7", "Description": "" } }
messages_sent_list
% aws lambda get-function --function-name messages_sent_list { "Code": { "RepositoryType": "S3", "Location": "https://awslambda-ap-ne-1-tasks.s3.ap-northeast-1.amazonaws.com/snapshots/... }, "Configuration": { "TracingConfig": { "Mode": "PassThrough" }, "Version": "$LATEST", "CodeSha256": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "FunctionName": "messages_sent_list", "MemorySize": 128, "RevisionId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "CodeSize": 29399523, "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:messages_sent_list", "Handler": "messages_sent_list.handler", "Role": "arn:aws:iam::XXXXXXXXXXXX:role/lambda-default", "Timeout": 3, "LastModified": "2019-12-11T04:43:42.376+0000", "Runtime": "python3.7", "Description": "" } }
実際に操作してみる
リポジトリにあるサンプル操作を実行してみます。
メッセージの送信
% script/exec_lambda message_add '{"toId": 2993937, "to": "imjohnbo", "fromId": 27806, "from": "swinton", "message": "Hello, John, how are you?"}' true
メッセージの受信
% script/exec_lambda messages_received_list '{"toId": 2993937}' {"data": [{"receivedAt": 1576039472.0, "fromId": 27806.0, "message": "Hello, John, how are you?", "toId": 2993937.0, "to": "imjohnbo", "from": "swinton"}]}
送信したメッセージ
% script/exec_lambda messages_sent_list '{"fromId": 27806}' {"data": [{"receivedAt": 1576039472.0, "fromId": 27806.0, "message": "Hello, John, how are you?", "toId": 2993937.0, "to": "imjohnbo", "from": "swinton"}]}
あとがき
octochat-awsリポジトリ内を確認していたところ、Lambda関数の実装が含まれているディレクトリを見つけ、単独起動にも対応していたので試したものの、製作者自身の環境で動かす前提になっていたというものでした。
Lambda関数をバッチ処理で更新する手続き等で参考になる点が多かったので、興味のある方は試してみて下さい。