Lambdaのテンプレートファイルを設定してみる

## はじめに
```CloudFormation```はAWSリソースをプロビジョニングできるサービスです。このサービスを使用すると、システム構成をテンプレート化し、環境作成を容易に行うことができます。
これらのテンプレートは```template.yaml```ファイルで作成されます。

## template.yamlの全体像

```yaml
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: A sample SAM template for deploying Lambda functions.

Mappings:
  VpcConfig:
    dev:
      SubnetIds:
        - subnet-hogehoge1
      SecurityGroupIds: hoge_stg
    stg:
      SubnetIds:
        - subnet-hogehoge2
      SecurityGroupIds: hoge_stg
    prd:
      SubnetIds:
        - subnet-hogehoge3
      SecurityGroupIds: hoge_prd

Globals:
  Function:
    Runtime: python3.10
    Timeout: 30
    MemorySize: 256
    Environment:
      Variables:
        DB_NAME: "hoge_db"

Parameters:
  Env:
    Description: Please enter the Enviroment.
    Type: String
    Default: stg
    AllowedValues: [dev, stg, prd]

Resources:
  testFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: test
      Handler: test.lambda_handler
      CodeUri: ./app/functions
      Role: hogehoge
      Layers: TestLayer
      VpcConfig:
        SubnetIds: !FindInMap [VpcConfig, !Ref Env, SubnetIds]
        SecurityGroupIds: !FindInMap [VpcConfig, !Ref Env, SecurityGroupIds]
      Events:
        ApiEvent:
          Type: Api
          Properties:
            Path: /test
            Method: get
            RestApiId: RestApi

 RestApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Sub ${Env}
      OpenApiVersion: 3.0.2
      EndpointConfiguration: EndpointConfiguration
      Name: !Sub $${Env}-test-api
      Description: test apigateway.
      Cors:
        AllowOrigin: "'*'"
        AllowCredentials: true
        AllowMethods: "'OPTIONS,POST,PUT,DELETE,GET'"
        AllowHeaders: "'Content-Type,Authorization'"
```

## 各項目の説明
### Mappings
開発(dev)、ステージング(stg)、本番(prd)環境ごとに異なるサブネットやセキュリティグループなどのVPC設定を行います。

例えば、Resources内でVPC設定を参照する際に```!FindInMap [VpcConfig, !Ref Env, SubnetIds]```という記述を使用します。この場合、Envの値に応じて異なるサブネットIDが取得されます。

```!Ref Env```については、Globalsに設定したENVは可変で、```Parameters```内のEnv内で設定されています。
Envのデフォルトはdevなので、特に指定しなければ、参照内容は```!FindInMap [VpcConfig, stg, SubnetIds]```として subnet-hogehoge2 が取得されます。
ローカルで起動させる場合でdevを指定したい場合は、```.env.local.json```というローカルの環境変数ファイル内でParametersを上書きして、```sam local start-api```コマンドに```--env-vars .env.local.json```を指定して実行します。
```yaml
{
  "Parameters": {
    "ENV": "dev",
  }
}
```

### Globals
Lambda関数に共通する設定（ランタイム、タイムアウト、メモリサイズ、環境変数）を指定します。
例えば、DB_NAMEという環境変数を設定すると、Lambda関数内でos.environ["DB_NAME"]を使って値を参照できます。

### Parameters
テンプレートにカスタム値を入力します。
例えば、Envというパラメータを設定して、その値に基づいて異なる環境設定を行うことができます。値の使用方法は、単体の参照には!Ref 変数名を、文字列結合には!Sub hoge${変数名}を使用します。

### Resources
ここでは具体的なAWSリソース（例えば、Lambda関数やAPI Gateway）を定義します。
Lambda関数の設定では、関数名、ハンドラ、コードの場所、ロール、レイヤー、VPC設定、APIイベントなどを指定します。
詳しくは[AWSのドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html)を参照ください

### RestApi
HTTPSエンドポイントを介してアクセス可能な```Amazon API Gateway```のリソースとメソッドを定義します。
CORS設定により、指定されたオリジンからのアクセスを許可することができます。

CORSとは、オリジンから別のオリジンへのリソースへのアクセスを安全にするための仕組みであり、```Cors```を設定することで特定のオリジンからのアクセスを許可することができます。
詳しくは[AWSのドキュメント](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-resource-api.html#sam-api-endpointconfiguration)を参照ください

## 参考
[AWSドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/quickref-lambda.html)
各項目がわからない場合は、ドキュメント内の検索欄でも調べることができます。