👋
【AWS SAM ハンズオン】API Gateway+Lambda+DynamoDBを作成。
記事について
簡単なものを作成してみました。
ハンズオンなどと偉そうな名前をつけておりますが、
私もSAMを触り始めて数日というレベル感です。
「気になっていたけど触ってなかったんだよね」という方に、空いた時間に軽い気持ちで触っていただければと思い公開してみたものです。
手元の環境で確認していますが、上手くいかないという事があった場合
までメッセージいただけたら幸いです。事前準備(お済みでない方は)
ご自身の環境に合わせて以下ご準備ください。
ハンズオン内容
簡単すぎる絵で恐縮ですが以下出来上がるリソースです。
ターミナルとブラウザのみご準備ください。
手順
1.親フォルダ作成 & 中に移動
ターミナル
$ mkdir apigw_lambda_dynamodb_sample && cd apigw_lambda_dynamodb_sample
↓
2.srcフォルダ作成 & 中にapp.pyを作成
ターミナル
$ mkdir src && vi src/app.py
↓
3.中身を貼付して保存。(i→貼付→esc→:wq→Enter)
app.py
import json
import boto3
dynamodb_client = boto3.client('dynamodb')
def lambda_handler(event, context):
dynamodb_client.put_item(TableName='SampleTable', Item={'id': {'S': '1'}, 'value': {'S': 'Value1'}})
return {
"statusCode": 200,
"body": json.dumps({
"message": "Data insertion succeeded!!!!!!!!!",
}),
}
↓
4.念の為 app.py確認
ターミナル
$ cat src/app.py
# 実行結果
import json
import boto3
dynamodb_client = boto3.client('dynamodb')
def lambda_handler(event, context):
dynamodb_client.put_item(TableName='SampleTable', Item={'id': {'S': '1'}, 'value': {'S': 'Value1'}})
return {
"statusCode": 200,
"body": json.dumps({
"message": "Data insertion succeeded!!!!!!!!!",
}),
}
↓
5.template.yaml作成
ターミナル
$ vi template.yaml
↓
6.中身を貼付して保存。(i→貼付→esc→:wq→Enter)
templaye.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Apigw + Lambda + DynamoDB
Globals:
Function:
Timeout: 3
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- x86_64
Policies:
DynamoDBCrudPolicy:
TableName: !Ref MyDynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /src
Method: get
MyDynamoDBTable:
Type: AWS::Serverless::SimpleTable
Properties:
TableName: SampleTable
Outputs:
Api:
Description: "API Gateway endpoint URL"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/src/"
↓
7.念の為 template.yaml確認
ターミナル
$ cat template.yaml
# 実行結果
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Apigw + Lambda + DynamoDB
Globals:
Function:
Timeout: 3
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src_world/
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- x86_64
Policies:
DynamoDBCrudPolicy:
TableName: !Ref MyDynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /src
Method: get
MyDynamoDBTable:
Type: AWS::Serverless::SimpleTable
Properties:
TableName: SampleTable
Outputs:
Api:
Description: "API Gateway endpoint URL"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
↓
8.この時点でのフォルダの中身を把握
フォルダ内
apigw_lambda_dynamodb_sample/
├── src/
│ └── app.py
└── template.yaml
↓
9.ビルド
ターミナル
$ sam build
# 実行結果
Your template contains a resource with logical ID "ServerlessRestApi", which is a reserved logical ID in AWS SAM. It could result in unexpected behaviors and is not recommended.
Building codeuri: /Users/[Your Directory]/apigw_lambda_dynamodb_sample/src runtime: python3.9 metadata: {} architecture: x86_64 functions: MyFunction
requirements.txt file not found. Continuing the build without dependencies.
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
[*] Deploy: sam deploy --guided
↓
10.この時点でのフォルダの中身を把握
フォルダ内
apigw_lambda_dynamodb_sample/
├── .aws-sam/ [New!!]
│ ├── build.toml
│ └── build/
│ ├── template.yaml
│ └── MyFunction/
│ └── app.py
├── src/
│ └── app.py
└── template.yaml
↓
11.念の為、build.tomlファイルの中身はこんな感じになっています。
build.toml
# This file is auto generated by SAM CLI build command
[function_build_definitions]
[function_build_definitions.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx]
codeuri = "/Users/[Your Directory]/apigw_lambda_dynamodb_sample/src"
runtime = "python3.9"
architecture = "x86_64"
handler = "app.lambda_handler"
manifest_hash = ""
packagetype = "Zip"
functions = ["MyFunction"]
[layer_build_definitions]
↓
12.デプロイ
ターミナル
$ sam deploy --guided
# 実行結果
Configuring SAM deploy
======================
Looking for config file [samconfig.toml] : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]: apigw-lambda-dynamodb-sample
AWS Region [us-east-1]: ap-northeast-1
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: Y
#Preserves the state of previously provisioned resources when an operation fails
Disable rollback [y/N]: N
MyFunction may not have authorization defined, Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]: Y
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:
Looking for resources needed for deployment:
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxxxxxx
A different default S3 bucket can be set in samconfig.toml
Saved arguments to config file
Running 'sam deploy' for future deployments will use the parameters saved above.
The above parameters can be changed by modifying samconfig.toml
Learn more about samconfig.toml syntax at
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
Uploading to apigw-lambda-dynamodb-sample/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 336 / 336 (100.00%)
Deploying with following values
===============================
Stack name : apigw-lambda-dynamodb-sample
Region : ap-northeast-1
Confirm changeset : True
Disable rollback : False
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxxxxxx
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Signing Profiles : {}
Initiating deployment
=====================
Uploading to apigw-lambda-dynamodb-sample/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.template 1049 / 1049 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-------------------------------------------------------------------------------------------------
+ Add MyDynamoDBTable AWS::DynamoDB::Table N/A
+ Add MyFunctionApiEventPerm AWS::Lambda::Permissio N/A
issionProd n
+ Add MyFunctionRole AWS::IAM::Role N/A
+ Add MyFunction AWS::Lambda::Function N/A
+ Add ServerlessRestApiDeplo AWS::ApiGateway::Deplo N/A
ymentxxxxxxxxxx yment
+ Add ServerlessRestApiProdS AWS::ApiGateway::Stage N/A
tage
+ Add ServerlessRestApi AWS::ApiGateway::RestA N/A
pi
-------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:[Your Account Id]:changeSet/samcli-deployxxxxxxxxxx/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
2022-11-07 18:20:08 - Waiting for stack create/update to complete
CloudFormation events from stack operations (refresh every 0.5 seconds)
-------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::CloudFormation::S apigw-lambda-dynamodb- User Initiated
tack sample
CREATE_IN_PROGRESS AWS::DynamoDB::Table MyDynamoDBTable -
CREATE_IN_PROGRESS AWS::DynamoDB::Table MyDynamoDBTable Resource creation
Initiated
CREATE_COMPLETE AWS::DynamoDB::Table MyDynamoDBTable -
CREATE_IN_PROGRESS AWS::IAM::Role MyFunctionRole -
CREATE_IN_PROGRESS AWS::IAM::Role MyFunctionRole Resource creation
Initiated
CREATE_COMPLETE AWS::IAM::Role MyFunctionRole -
CREATE_IN_PROGRESS AWS::Lambda::Function MyFunction -
CREATE_IN_PROGRESS AWS::Lambda::Function MyFunction Resource creation
Initiated
CREATE_COMPLETE AWS::Lambda::Function MyFunction -
CREATE_IN_PROGRESS AWS::ApiGateway::RestA ServerlessRestApi -
pi
CREATE_IN_PROGRESS AWS::ApiGateway::RestA ServerlessRestApi Resource creation
pi Initiated
CREATE_COMPLETE AWS::ApiGateway::RestA ServerlessRestApi -
pi
CREATE_IN_PROGRESS AWS::Lambda::Permissio MyFunctionApiEventPerm -
n issionProd
CREATE_IN_PROGRESS AWS::ApiGateway::Deplo ServerlessRestApiDeplo -
yment ymentxxxxxxxxxx
CREATE_IN_PROGRESS AWS::Lambda::Permissio MyFunctionApiEventPerm Resource creation
n issionProd Initiated
CREATE_IN_PROGRESS AWS::ApiGateway::Deplo ServerlessRestApiDeplo Resource creation
yment ymentxxxxxxxxxx Initiated
CREATE_COMPLETE AWS::ApiGateway::Deplo ServerlessRestApiDeplo -
yment ymentxxxxxxxxxx
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdS -
tage
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdS Resource creation
tage Initiated
CREATE_COMPLETE AWS::ApiGateway::Stage ServerlessRestApiProdS -
tage
CREATE_COMPLETE AWS::Lambda::Permissio MyFunctionApiEventPerm -
n issionProd
CREATE_COMPLETE AWS::CloudFormation::S apigw-lambda-dynamodb- -
tack sample
-------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
-------------------------------------------------------------------------------------------------
Outputs
-------------------------------------------------------------------------------------------------
Key Api
Description API Gateway endpoint URL
Value https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/src/
-------------------------------------------------------------------------------------------------
Successfully created/updated stack - apigw-lambda-dynamodb-sample in ap-northeast-1
13.この時点でのフォルダの中身を把握
フォルダ内
apigw_lambda_dynamodb_sample/
├── samconfig.toml[New!!]
├── .aws-sam/
│ ├── build.toml
│ └── build/
│ ├── template.yaml
│ └── MyFunction/
│ └── app.py
├── src/
│ └── app.py
└── template.yaml
↓
14.結果を確認
※[出力されているURLによって異なります]部分はOutput結果を見て変更して実行ください。
ターミナル
$ curl https://[出力されているURLによって異なります].execute-api.ap-northeast-1.amazonaws.com/Prod/src/
# 実行結果
{"message": "Data insertion succeeded!!!!!!!!!"}
想定通りの結果が返ってきました。
↓
15.DynamoDB→"項目の探索"を確認(コンソール画面)
無事データ挿入出来ています。
↓
16.念の為、samconfig.tomlファイルの中身はこんな感じになっています。
samconfig.toml
version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "apigw-lambda-dynamodb-sample"
s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxxxxxx"
s3_prefix = "apigw-lambda-dynamodb-sample"
region = "ap-northeast-1"
confirm_changeset = true
capabilities = "CAPABILITY_IAM"
image_repositories = []
↓
17.削除(お片付け)
ターミナル
$ sam delete
# 実行結果
Are you sure you want to delete the stack apigw-lambda-dynamodb-sample in the region ap-northeast-1 ? [y/N]: y
Are you sure you want to delete the folder apigw-lambda-dynamodb-sample in S3 which contains the artifacts? [y/N]: y
- Deleting S3 object with key apigw-lambda-dynamodb-sample/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- Deleting S3 object with key apigw-lambda-dynamodb-sample/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.template
- Deleting Cloudformation stack apigw-lambda-dynamodb-sample
Deleted successfully
※CloudFormationコンソールを確認すると「aws-sam-cli-managed-default」というAWS SAMのテンプレートを保存するバケットとバケットポリシーを作成するスタックが残りますが、これを削除するかどうかはお任せします。削除しても次回sam deployする際、新規で再作成されます。今回のハンズオン内容外のリソースと仮に紐づいていた場合や既に「aws-sam-cli-managed-default」が作業リージョンにある状態で着手した方は慎重にご確認ください。残しておいても害はないと思います。
※ローカルのフォルダを削除する場合は親フォルダである「apigw_lambda_dynamodb_sample」フォルダごと削除して問題ありません。
(コンソールからもスタックは削除出来ますが、sam deleteコマンドでの削除がまだであれば、リソースの削除後である事をお勧めします。)
以上でした。
有難うございました。
Discussion