

# AWS SAM と Infrastructure Composer での Lambda 関数の使用
<a name="foundation-iac-getting-started"></a>

このチュートリアルでは、既存の Lambda 関数で AWS SAM テンプレートを作成し、他の AWS リソースを追加して Infrastructure Composer でサーバーレスアプリケーションを構築することで、IaC を Lambda で使用開始できます。

このチュートリアルを実行すると、AWS リソースの AWS SAM での指定方法など、いくつかの基本的な概念を習得できます。また、Infrastructure Composer で、AWS SAM または CloudFormation を使用してデプロイできるサーバーレスアプリケーションを構築する方法についても習得します。

このチュートリアルを完了するには、次のステップを実行します。
+ サンプル Lambda 関数の作成
+ Lambda コンソールを使用して、関数の AWS SAM テンプレートを表示します
+ 関数の設定を AWS Infrastructure Composer にエクスポートし、関数の設定に基づいてシンプルなサーバーレスアプリケーションを設計します。
+ 更新した AWS SAM テンプレートを保存して、サーバーレスアプリケーションをデプロイするための基礎として使用できます。

## 前提条件
<a name="foundation-iac-prerequisites"></a>

このチュートリアルでは、Infrastructure Composer の[ローカル同期](https://docs.aws.amazon.com/application-composer/latest/dg/reference-features-local-sync.html)機能を使用して、テンプレートとコードファイルをローカルビルドマシンに保存します。この機能を使用するには、File System Access API に対応するブラウザが必要です。これにより、Web アプリケーションでローカルファイルシステム内のファイルの読み取り、書き込み、保存を行うことができます。Google Chrome または Microsoft Edge の使用が推奨されます。File System Access API の詳細については、「[What is the File System Access API?](https://docs.aws.amazon.com/application-composer/latest/dg/reference-fsa.html#reference-fsa-api)」を参照してください。

## Lambda 関数を作成する
<a name="foundation-iac-create-function"></a>

この最初のステップでは、チュートリアルの残りの部分を完了するために使用できる Lambda 関数を作成します。簡単に言うと、Lambda コンソールで Python 3.11 ランタイムを使用して、基本的な「Hello world」関数を作成します。

**コンソールで「Hello world」Lambda 関数を作成するには**

1. [Lambdaのコンソール](https://console.aws.amazon.com/lambda)を開きます。

1. [**Create function**] (関数の作成) をクリックします。

1. **[一から作成]** を選択したままにし、**[基本的な情報]** の **[関数名]** に **LambdaIaCDemo** と入力します。

1. **[ランタイム]** で **[Python 3.11]** を選択します。

1. [**Create function**] (関数の作成) をクリックします。

## 関数の AWS SAM テンプレートを表示する
<a name="foundation-iac-view-template"></a>

関数の設定を Infrastructure Composer にエクスポートする前に、Lambda コンソールを使用して関数の現在の設定を AWS SAM テンプレートとして表示します。このセクションのステップに従うことで、AWS SAM テンプレートの構造と、Lambda 関数などのリソースを定義してサーバーレスアプリケーションの指定を開始する方法について学びます。

**関数の AWS SAM テンプレートを表示するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 先ほど作成した関数 (`LambdaIaCDemo`) を選択します。

1. **[関数の概要]** ペインで、**[テンプレート]** を選択します。

   関数の設定を表す図の代わりに、その関数の AWS SAM テンプレートが表示されます。テンプレートは次のようになります。

   ```
   # This AWS SAM template has been generated from your function's 
   # configuration. If your function has one or more triggers, note 
   # that the AWS resources associated with these triggers aren't fully 
   # specified in this template and include placeholder values.Open this template 
   # in AWS Application Composer or your favorite IDE and modify 
   # it to specify a serverless application with other AWS resources. 
   AWSTemplateFormatVersion: '2010-09-09'
   Transform: AWS::Serverless-2016-10-31
   Description: An AWS Serverless Specification template describing your function.
   Resources:
     LambdaIaCDemo:
       Type: AWS::Serverless::Function
       Properties:
         CodeUri: .
         Description: ''
         MemorySize: 128
         Timeout: 3
         Handler: lambda_function.lambda_handler
         Runtime: python3.11
         Architectures:
           - x86_64
         EventInvokeConfig:
           MaximumEventAgeInSeconds: 21600
           MaximumRetryAttempts: 2
         EphemeralStorage:
           Size: 512
         RuntimeManagementConfig:
           UpdateRuntimeOn: Auto
         SnapStart:
           ApplyOn: None
         PackageType: Zip
         Policies:
           Statement:
             - Effect: Allow
               Action:
                 - logs:CreateLogGroup
               Resource: arn:aws:logs:us-east-1:123456789012:*
             - Effect: Allow
               Action:
                 - logs:CreateLogStream
                 - logs:PutLogEvents
               Resource:
                 - >-
                   arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/LambdaIaCDemo:*
   ```

作成した関数の YAML テンプレートを確認する時間を作り、いくつかの主要な概念について理解しておきましょう。

テンプレートは `Transform: AWS::Serverless-2016-10-31` を宣言することから始まります。この宣言は必須です。というのも、AWS SAM テンプレートはバックグラウンドで CloudFormation を介してデプロイされるからです。`Transform` ステートメントを使用すると、テンプレートが AWS SAM テンプレートファイルとして識別されます。

`Transform` 宣言の後に `Resources` セクションがあります。ここで、AWS SAM テンプレートと共にデプロイする AWS リソースを定義します。AWS SAM テンプレートには、AWS SAM リソースと CloudFormation リソースを組み合わせて含めることができます。これは、デプロイ中に AWS SAM テンプレートが CloudFormation テンプレートに拡張されるためであり、有効な CloudFormation 構文を AWS SAM テンプレートに追加できます。

現時点では、テンプレートの `Resources` セクションで定義されているリソースは Lambda 関数だけです。`LambdaIaCDemo`Lambda 関数を AWS SAM テンプレートに追加するには、`AWS::Serverless::Function` リソースタイプを使用します。Lambda 関数リソースの `Properties` で、関数のランタイム、関数ハンドラー、およびその他の設定オプションを定義します。AWS SAM で関数のデプロイに使用する必要のある関数のソースコードへのパスも、ここで定義されます。AWS SAM の Lambda 関数リソースの詳細については、「AWS SAM 開発者ガイド」の「[AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)」を参照してください。

テンプレートでは、関数のプロパティと設定だけでなく、関数の AWS Identity and Access Management (IAM) ポリシーも指定されています。このポリシーにより、Amazon CloudWatch Logs にログを書き込むアクセス許可が関数に付与されます。Lambda コンソールで関数を作成すると、Lambda は自動的にこのポリシーを関数にアタッチします。AWS SAM テンプレートの関数に IAM ポリシーを指定する方法の詳細については、「AWS SAM 開発者ガイド」の「[AWS:: Serverless:: Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)」ページにある `policies` プロパティを参照してください。

AWS SAM テンプレートの構造の詳細については、「[AWS SAM テンプレートの構造](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy.html)」を参照してください。

## AWS Infrastructure Composer をサーバーレスアプリケーションの設計に使用する
<a name="foundation-iac-design-app"></a>

関数の AWS SAM テンプレートを基にして単純なサーバーレスアプリケーションの構築を開始するには、関数の設定を Infrastructure Composer にエクスポートし、Infrastructure Composer のローカル同期モードを有効化します。ローカル同期で関数のコードと AWS SAM テンプレートがローカルビルドマシンに自動的に保存され、Infrastructure Composer に他の AWS リソースを追加しても保存したテンプレートは同期されたままになります。

**関数を Infrastructure Composer にエクスポートするには**

1. **[関数の概要]** ペインで、**[Application Composer にエクスポート]** を選択します。

   関数の設定とコードを Infrastructure Composer にエクスポートするには、Lambda でアカウントに Amazon S3 バケットを作成し、このデータを一時的に保存します。

1. ダイアログボックスで **[プロジェクトの確認と作成]** を選択し、このバケットのデフォルト名をそのまま使用して、関数の設定とコードを Infrastructure Composer にエクスポートします。

1. (オプション) Lambda で作成する Amazon S3 バケットに別の名前を選択する場合は、新しい名前を入力して **[プロジェクトの確認と作成]** を選択します。Amazon S3 バケットの名前は、グローバルに一意で、[バケットの命名規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)に従ったものである必要があります。

   **[プロジェクトの確認と作成]** を選択すると、Infrastructure Composer コンソールが開きます。キャンバスに、Lambda 関数が表示されます。

1. **[メニュー]** ドロップダウンから **[ローカル同期をアクティブ化]** を選択します。

1. 表示されたダイアログボックスで **[フォルダを選択]** を選び、ローカルビルドマシンのフォルダを選択します。

1. **[アクティブ化]** を選択してローカル同期をアクティブ化します。

関数を Infrastructure Composer にエクスポートするには、特定の API アクションを使用するためのアクセス許可が必要です。関数をエクスポートできない場合は、[必要なアクセス許可](services-appcomposer.md#services-appcomposer-permissions) を参照して、必要な権限があることを確認してください。

**注記**  
関数を Infrastructure Composer にエクスポートする場合、Lambda が作成するバケットに標準の [Amazon S3 の料金](https://aws.amazon.com/s3/pricing)が適用されます。Lambda がバケットに取り込むオブジェクトは 10 日後に自動的に削除されますが、Lambda でバケット自体が削除されることはありません。  
追加料金が AWS アカウント にかからないようにするには、関数を Infrastructure Composer にエクスポートしてから「[バケットの削除](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html)」の手順に従ってください。Lambda で作成される Amazon S3 バケットの詳細については、「[での AWS Lambda の使用AWS Infrastructure Composer](services-appcomposer.md)」を参照してください。

**Infrastructure Composer でサーバーレスアプリケーションを設計するには**

ローカル同期を有効化すると、Infrastructure Composer で行った変更がローカルビルドマシンに保存されている AWS SAM テンプレートに反映されます。追加の AWS リソースを Infrastructure Composer のキャンバスにドラッグアンドドロップして、アプリケーションを構築できるようになりました。この例では、Lambda 関数のトリガーとして Amazon SQS のシンプルなキューを追加し、データを書き込む関数に DynamoDB テーブルを追加します。

1. Amazon SQS トリガーを Lambda 関数に追加するには、次の手順を実行します。

   1. **[リソース]** パレットの検索フィールドに、「**SQS**」と入力します。

   1. **[SQS キュー]** リソースをキャンバスにドラッグし、Lambda 関数の左側に配置します。

   1. **[詳細]** を選択し、**[論理 ID]** に「**LambdaIaCQueue**」と入力します。

   1. **[保存]** を選択します。

   1. SQS キューカードの **[サブスクリプション]** ポートをクリックし、Lambda 関数カードの左側のポートにドラッグして、Amazon SQS リソースと Lambda リソースを接続します。2 つのリソースの間に線が表示されれば、接続に成功しています。また、Infrastructure Composer では、2 つのリソースが正常に接続されたことを示すメッセージもキャンバスの下部に表示されます。

1. 以下を実行して、Lambda 関数に Amazon DynamoDB テーブルを追加し、データを書き込みます。

   1. **[リソース]** パレットの検索フィールドに、「**DynamoDB**」と入力します。

   1. **[DynamoDB テーブル]** リソースをキャンバスにドラッグし、Lambda 関数の右側に配置します。

   1. **[詳細]** を選択し、**[論理 ID]** に「**LambdaIaCTable**」と入力します。

   1. **[保存]** を選択します。

   1. DynamoDB テーブルを Lambda 関数に接続するには、Lambda 関数カードの右側のポートをクリックして、DynamoDB カードの左側のポートにドラッグします。

これらのリソースを追加したところで、Infrastructure Composer が作成した更新済みの AWS SAM テンプレートを見てみましょう。

**更新した AWS SAM テンプレートを表示するには**
+ Infrastructure Composer のキャンバスで **[テンプレート]** を選択し、キャンバスビューからテンプレートビューに切り替えます。

これで、AWS SAM テンプレートに以下の追加のリソースとプロパティが含まれているはずです。
+ 識別子 `LambdaIaCQueue` を含む Amazon SQS キュー

  ```
  LambdaIaCQueue:
      Type: AWS::SQS::Queue
      Properties:
        MessageRetentionPeriod: 345600
  ```

  Infrastructure Composer を使用して Amazon SQS キューを追加すると、Infrastructure Composer は `MessageRetentionPeriod` プロパティを設定します。SQS キューカードで **[詳細]** を選択し、**[FIFO キュー]** をオンまたはオフにして `FifoQueue` プロパティを設定することもできます。

  キューに他のプロパティを設定するには、テンプレートを手動で編集して追加できます。`AWS::SQS::Queue` のリソースと使用可能なプロパティの詳細については、「CloudFormation ユーザーガイド」の「[AWS::SQS::Queue](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html)」を参照してください。
+ Amazon SQS キューを関数のトリガーとして指定する Lambda 関数定義の `Events` プロパティ

  ```
  Events:
    LambdaIaCQueue:
      Type: SQS
      Properties:
        Queue: !GetAtt LambdaIaCQueue.Arn
        BatchSize: 1
  ```

  `Events` プロパティは、1 つのイベントタイプと、そのタイプに依存する一連のプロパティで構成されます。Lambda 関数をトリガーするために設定できるさまざまな AWS のサービス と設定できるプロパティについては、「AWS SAM 開発者ガイド」の「[EventSource](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-eventsource.html)」を参照してください。
+ 識別子 `LambdaIaCTable` を含む DynamoDB テーブル

  ```
  LambdaIaCTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        BillingMode: PAY_PER_REQUEST
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        StreamSpecification:
          StreamViewType: NEW_AND_OLD_IMAGES
  ```

  Infrastructure Composer を使用して DynamoDB テーブルを追加するときに、DynamoDB テーブルカードで **[詳細]** を選択し、キー値を編集することでテーブルのキーを設定できます。Infrastructure Composer は、`BillingMode` や `StreamViewType` を含む他の多くのプロパティにもデフォルト値を設定します。

  これらのプロパティやお使いの AWS SAM テンプレートに追加できるその他のプロパティの詳細については、「CloudFormation ユーザーガイド」の「[AWS::DynamoDB::Table](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html)」を参照してください。
+ 追加した DynamoDB テーブルで CRUD オペレーションを実行する権限を関数に付与する新しい IAM ポリシー。

  ```
  Policies:
  ...
    - DynamoDBCrudPolicy:
      TableName: !Ref LambdaIaCTable
  ```

以下の例は、最終的に完成した AWS SAM テンプレートを示しています。

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: An AWS Serverless Specification template describing your function.
Resources:
  LambdaIaCDemo:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: .
      Description: ''
      MemorySize: 128
      Timeout: 3
      Handler: lambda_function.lambda_handler
      Runtime: python3.11
      Architectures:
        - x86_64
      EventInvokeConfig:
        MaximumEventAgeInSeconds: 21600
        MaximumRetryAttempts: 2
      EphemeralStorage:
        Size: 512
      RuntimeManagementConfig:
        UpdateRuntimeOn: Auto
      SnapStart:
        ApplyOn: None
      PackageType: Zip
      Policies:
        - Statement:
            - Effect: Allow
              Action:
                - logs:CreateLogGroup
              Resource: arn:aws:logs:us-east-1:594035263019:*
            - Effect: Allow
              Action:
                - logs:CreateLogStream
                - logs:PutLogEvents
              Resource:
                - arn:aws:logs:us-east-1:594035263019:log-group:/aws/lambda/LambdaIaCDemo:*
        - DynamoDBCrudPolicy:
            TableName: !Ref LambdaIaCTable
      Events:
        LambdaIaCQueue:
          Type: SQS
          Properties:
            Queue: !GetAtt LambdaIaCQueue.Arn
            BatchSize: 1
      Environment:
        Variables:
          LAMBDAIACTABLE_TABLE_NAME: !Ref LambdaIaCTable
          LAMBDAIACTABLE_TABLE_ARN: !GetAtt LambdaIaCTable.Arn
  LambdaIaCQueue:
    Type: AWS::SQS::Queue
    Properties:
      MessageRetentionPeriod: 345600
  LambdaIaCTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      StreamSpecification:
        StreamViewType: NEW_AND_OLD_IMAGES
```

## (オプション) AWS SAM を使用したサーバーレスアプリケーションのデプロイ
<a name="foundation-iac-deploy"></a>

AWS SAM を使用し、Infrastructure Composer で作成したばかりのテンプレートを使用してサーバーレスアプリケーションをデプロイする場合は、まず AWS SAM CLI をインストールする必要があります。これを行うには、「[AWS SAM CLI のインストール](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)」の指示に従います。

アプリケーションをデプロイする前に、Infrastructure Composer がテンプレートと共に保存した関数コードも更新する必要があります。現時点では、Infrastructure Composer が保存した `lambda_function.py` ファイルには、関数を作成したときに Lambda によって提供された基本的な「Hello world」コードのみが含まれています。

関数コードを更新するには、以下のコードをコピーして、Infrastructure Composer がローカルビルドマシンに保存した `lambda_function.py` ファイルに貼り付けます。ローカル同期モードをアクティブ化したときのこのファイルの保存先として Infrastructure Composer のディレクトリを指定しました。

このコードによって、Infrastructure Composer で作成した Amazon SQS キューからのメッセージに含まれるキーと値のペアを受け入れます。キーと値の両方が文字列の場合、コードはそれらの文字列を使用して、テンプレートで定義されている DynamoDB テーブルに項目を書き込みます。

### 更新済みの Python 関数コード
<a name="foundation-iac-updated-code"></a>

```
import boto3
import os
import json

# define the DynamoDB table that Lambda will connect to
tablename = os.environ['LAMBDAIACTABLE_TABLE_NAME']

# create the DynamoDB resource
dynamo = boto3.client('dynamodb')

def lambda_handler(event, context):
    # get the message out of the SQS event
    message = event['Records'][0]['body']
    data = json.loads(message)
    # write event data to DDB table
    if check_message_format(data):
        key = next(iter(data))
        value = data[key]
        dynamo.put_item(
            TableName=tablename,
            Item={
                'id': {'S': key},
                'Value': {'S': value}
            }
        )
    else:
        raise ValueError("Input data not in the correct format")

# check that the event object contains a single key value  
# pair that can be written to the database
def check_message_format(message):
    if len(message) != 1:
        return False
        
    key, value = next(iter(message.items()))
    
    if not (isinstance(key, str) and isinstance(value, str)):
        return False

    else:
        return True
```

**サーバーレスアプリケーションをデプロイするには**

AWS SAM CLI を使用してアプリケーションをデプロイするには、次の手順を実行します。関数が正しく構築およびデプロイされるように、Python バージョン 3.11 をお使いのビルドマシンと `PATH` にインストールする必要があります。

1. Infrastructure Composer で `template.yaml` ファイルおよび `lambda_function.py` ファイルを保存したディレクトリから、以下のコマンドを実行します。

   ```
   sam build
   ```

   このコマンドによって、アプリケーションのビルドアーティファクトが収集され、それらをデプロイする場所を適切な形式で配置します。

1. アプリケーションをデプロイし、AWS SAM テンプレートで指定された Lambda、Amazon SQS、DynamoDB の各リソースを作成するには、次のコマンドを実行します。

   ```
   sam deploy --guided
   ```

   `--guided` フラグを使用すると、AWS SAM にデプロイプロセスの手順が示されます。このデプロイでは、Enter キーを押してデフォルトのオプションをそのまま使用してください。

デプロイプロセス中に、AWS SAM でお使いの AWS アカウントに次のリソースが作成されます。
+ `sam-app` という名前の CloudFormation[ スタック](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html#cfn-concepts-stacks)
+ `sam-app-LambdaIaCDemo-99VXPpYQVv1M` 名前形式の Lambda 関数
+ `sam-app-LambdaIaCQueue-xL87VeKsGiIo` 名前形式の Amazon SQS キュー
+ `sam-app-LambdaIaCTable-CN0S66C0VLNV` 名前形式の DynamoDB テーブル

また、Lambda 関数が Amazon SQS キューからメッセージを読み取り、DynamoDB テーブルで CRUD オペレーションを実行できるように、AWS SAM で必要な IAM ロールとポリシーを作成します。

## デプロイしたアプリケーションのテスト (オプション)
<a name="foundation-iac-test"></a>

サーバーレスアプリケーションが正しくデプロイされたことを確認するには、メッセージをキーと値のペアを含む Amazon SQS キューに送信し、Lambda がこれらの値を使用して DynamoDB テーブルに項目を書き込むことを確認します。

**サーバーレスアプリケーションをテストするには**

1. Amazon SQS コンソールの [[キュー]](https://console.aws.amazon.com/sqs/v2/home#/queues) ページを開き、お使いのテンプレートで AWS SAM が作成したキューを選択します。名前の形式は `sam-app-LambdaIaCQueue-xL87VeKsGiIo` になります。

1. **[メッセージを送受信]** を選択し、**[メッセージの送信]** セクションの **[メッセージ本文]** に次の JSON を貼り付けます。

   ```
   {
       "myKey": "myValue"
   }
   ```

1. **[メッセージの送信]** を選択します。

   メッセージをキューに送信すると、Lambda はお使いの AWS SAM テンプレートで定義されたイベントソースマッピングを通じて関数を呼び出します。Lambda が意図したとおりに関数を呼び出したことを確認するには、DynamoDB テーブルに項目が追加されていることを確認します。

1. DynamoDB コンソールの [[テーブル]](https://console.aws.amazon.com/dynamodbv2#tables) ページを開いてテーブルを選択します。名前の形式は `sam-app-LambdaIaCTable-CN0S66C0VLNV` になります。

1. **[テーブルアイテムの探索]** を選択します。**[返された項目]** ペインに、**[id]** `myKey` と **[値]** `myValue` がある項目が表示されるはずです。