AWS SAMの基本テンプレート(AWS Lambda, API Gateway)

AWS

AWS SAMでAWS LambdaとAPIGatewayの基本的なテンプレート解説です。

SAMプロジェクト一覧

「sam init」を行うと、以下のようなファイルが生成されます。

└── sam-app
    ├── events
    │   └── event.json
    ├── print
    │   ├── app.py #Lambda実装本体
    │   ├── Dockerfile
    │   ├── __init__.py
    │   └── requirements.txt #依存関係を定義
    ├── __init__.py
    ├── README.md
    ├── samconfig.toml
    ├── template.yaml #アプリケーションテンプレート
    └── tests
        ├── __init__.py
        └── unit
            ├── __init__.py
            └── test_handler.py

template.ymlの内容

「AWSTemplateFormatVersion」はCloudFormationのテンプレートバージョンです。
現時点ではこのバージョンしかないので固定です。
「Transform」はCloudFormationに変換するためのマクロを指定します。
独自のマクロを使用しないのであればこのバージョン固定です。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: xxxxx #説明

パラメータ、グローバルセクション

パラメータはSAMのコマンドから受け取ることが出来ます。
サンプル内で活用はしていませんが、環境を切り替えるためにdev,stg, prodパラメータを受け取るようにしています。

グローバルセクションではテンプレート全体の共通設定をしたい場合に記載します。
参考:AWS SAM テンプレートのグローバルセクション

# 入力パラメータ
Parameters:
  # デプロイ環境
  Env:
    Description: Enter environment.dev, stg, or prod.
    Type: String
    AllowedValues:
      - dev
      - stg
      - prod
    Default: dev

# 共通定義
Globals:
  # Lambda関数用
  Function:
    Timeout: 180
    Runtime: python3.7

  # APIGateway用
  Api:
    # CORS有効化
    Cors:
      # 認証情報を含めることが可能か
      AllowCredentials: False
      # 許可するメソッド
      AllowMethods: "'OPTIONS,POST,GET'"
      # 許可するヘッダー文字列
      AllowHeaders: "'authorization,Content-Type'"
      # 許可するオリジン
      AllowOrigin: "'*'"
      # CORS プリフライトリクエストをキャッシュする秒数
      MaxAge: "'180'"

Mappingsセクション

環境切替時にそれぞれの環境固有の値などを定義します。

# 環境切替用の定義。Envで切替   
Mappings: 
  EnvMap: 
    dev: 
      DynamoDbEndpoint: "http://dev:8000"
    stg: 
      DynamoDbEndpoint: "http://stg:8000"
    prod: 
      DynamoDbEndpoint: "http://prod:8000"

Mappingsの値を参照する場合は以下のようにキーを指定します。

    Environment:
      Variables:
        DYNAMODB_ENDPOINT: !FindInMap [EnvMap, !Ref Env, DynamoDbEndpoint]

Resourcesセクション

各リソースの詳細を定義していきます。「Type」では以下のリソースタイプが指定出来ます。
AWS SAM リソースおよびプロパティのリファレンス
「AWS::Serverless::Function」はLambda関数を表します。

# リソース定義
Resources:
  DemoAppDeployment:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId: !Ref ApiGatewayApps

 # ------------------------------------
 # Lambda関数定義
 #-------------------------------------
  PrintFunction:
    Type: AWS::Serverless::Function 
    Properties:
      # 関数名を指定
      FunctionName: PrintFunction
      # 関数コードのS3URL、またはローカルパス
      CodeUri: print/
      Handler: app.lambda_handler
      # 開発用エイリアス(dev)を作成しバージョニングを有効にする。
      # 開発用は常に最新バージョンを参照する。
      AutoPublishAlias: dev
      #この関数をトリガーするイベントを指定
      Events:
        Print:
          Type: Api 
          Properties:
            Path: /app/{proxy+}
            Method: ANY
            RestApiId: !Ref ApiGatewayApps

 # ------------------------------------
 # APIGateway定義
 #-------------------------------------
  # 「AWS::Serverless::Api」の場合、デフォルトでAPI統合タイプはLambda統合になる。
  ApiGatewayApps:
    Type: AWS::Serverless::Api
    Properties:
      Name: Apps
      StageName: !Ref Env
      EndpointConfiguration:
        Type: "REGIONAL"

Outputsセクション(任意)

このセクションは任意ですが、他のスタックから値を参照したい場合に定義します。

Outputs:
  ApiGatewayApps:
    Value: !Sub "https://${ApiGatewayApps}.execute-api.${AWS::Region}.amazonaws.com/${Env}/app/print"
  PrintFunction:
    Value: !GetAtt PrintFunction.Arn```

Lambdaの実装とテスト

LambdaのPythonサンプルコードです。
リクエスト本文(body),パスパラメータ、クエリ文字列、ヘッダーから
値を取り出して、文字列を組み立ててレスポンスとして返却します。

import json
import ast

def lambda_handler(event, context):
    body = event['body']
    body= ast.literal_eval(body)
    name = 'nobody' if not body['name'] else body['name']
    device = 'pc' if not event['pathParameters']['proxy'] else event['pathParameters']['proxy']
    price = '0' if not event['queryStringParameters']['price'] else event['queryStringParameters']['price']
    company = 'disney' if not event['headers']['company'] else event['headers']['company']

    parameters = name + ', ' + device + ', ' + price + ', ' + company
    print('parameters: ', parameters)

    res = {}
    res["parameters"] = parameters

    return {
        'statusCode': 200,
        'headers': {
            "x-custom-header": "custom header value",
             "Access-Control-Allow-Origin": "*",
             "Access-Control-Allow-Headers": "Content-Type",
             "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
        },
        'body': json.dumps(res),
        'isBase64Encoded': False
    }

APIGatewayのANYのメソッドテストで以下のような値をセットしてテストを実行します。

設定箇所設定値
メソッドPOST
パスprint
クエリ文字列price=evening
ヘッダcompany:amazon
リクエスト本文{ “name”:”Mike” }

テストを実行するとステータス200で以下のようなレスポンスが返されればOKです。

{
  "parameters": "Mike, print, evening, amazon"
}

参考記事

以上

タイトルとURLをコピーしました