SAM CLI で Lambda 関数のリモート呼び出し機能を使ってみた

目次

概要

SAM CLIのコマンドを使用してデプロイ後のLambda関数を呼び出すことができるようになりました。
これまではAWSマネジメントコンソールからテストイベントを作成してテストしたり、aws lambda invokeなどのAWS CLIコマンドを使用してLambda関数を呼び出していましたが、開発~デプロイ~テストまでSAM CLIで完結できるようになり効率が上がることが見込まれます。

AWS公式の記事はこちらになります。
※この機能は、SAM CLI バージョン 1.88.0 以降で利用可能です。

実際にやってみました

実行環境

sam --version
SAM CLI, version 1.95.0

Lambda関数のデプロイ

まずはSAM CLIでLambda関数をデプロイしてみます。
sam initを実行して「Hello World Example」を選択します。

$ sam init

You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.

Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1

Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - Data processing
        3 - Hello World Example with Powertools for AWS Lambda
        4 - Multi-step workflow
        5 - Scheduled task
        6 - Standalone function
        7 - Serverless API
        8 - Infrastructure event management
        9 - Lambda Response Streaming
        10 - Serverless Connector Hello World Example
        11 - Multi-step workflow with Connectors
        12 - GraphQLApi Hello World Example
        13 - Full Stack
        14 - Lambda EFS example
        15 - Hello World Example With Powertools
        16 - DynamoDB Example
        17 - Machine Learning
Template: 1

~~~~~中略~~~~~

    -----------------------
    Generating application:
    -----------------------
    Name: sam-app
    Runtime: python3.9
    Architectures: x86_64
    Dependency Manager: pip
    Application Template: hello-world
    Output Directory: .
    Configuration file: sam-app\samconfig.toml

    Next steps can be found in the README file at sam-app\README.md


Commands you can use next
=========================
[*] Create pipeline: cd sam-app && sam pipeline init --bootstrap
[*] Validate SAM template: cd sam-app && sam validate
[*] Test Function in the Cloud: cd sam-app && sam sync --stack-name {stack-name} --watch

「sam-app」という名前で作成が完了しました。
生成されたtemplate.yamlは下記の通りです。
Lambda関数が「HelloWorldFunction」の論理IDで定義されています。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3
    MemorySize: 128

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

sam buildを実行してビルド完了を確認します。

$ cd sam-app
$ sam build

Starting Build use cache

~~~~~中略~~~~~

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

次に実行できるコマンド(Commands you can use next)の「Test Function in the Cloud」を実行します。
sam sync --stack-name sam-app --watch

$ sam sync --stack-name sam-app --watch

The SAM CLI will use the AWS Lambda, Amazon API Gateway, and AWS StepFunctions APIs to upload your code without 
performing a CloudFormation deployment. This will cause drift in your CloudFormation stack. 
**The sync command should only be used against a development stack**.

~~~~~中略~~~~~

Stack creation succeeded. Sync infra completed.

CodeTrigger not created as CodeUri or DefinitionUri is missing for ServerlessRestApi.
Infra sync completed.

「Infra sync completed.」が表示されるとデプロイ成功です。
これでコードと依存関係がローカルとクラウドで同期されるため、ローカルでの変更が即時クラウドに反映されます。
sam syncは開発環境に推奨されるコマンドです。

リモート呼び出し機能を使ってみた

いよいよ本題です。
別のターミナルを用意して、リモート呼び出しコマンドを実行します。
コマンドの実行に必要な引数、オプションはこちらに記載されています。
基本的には「Lambda関数の論理ID」と「CloudFormationのスタック名」を指定すればよさそうです。
sam remote invoke HelloWorldFunction --stack-name sam-appを実行します。

$ sam remote invoke HelloWorldFunction --stack-name sam-app

Invoking Lambda Function HelloWorldFunction
START RequestId: 7599d0db-f7fc-432b-8889-0c932d01e713 Version: $LATEST
END RequestId: 7599d0db-f7fc-432b-8889-0c932d01e713
REPORT RequestId: 7599d0db-f7fc-432b-8889-0c932d01e713  Duration: 1.34 ms       Billed Duration: 2 ms   Memory Size: 128 MB     Max Memory Used: 36 MB  Init Duration: 108.51 ms
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}

呼び出しに成功してレスポンスが返ってきました!
実行秒数や使用メモリなどのREPORTログまで表示してくれるのは嬉しいですね!

さらに…

Lambda関数のデプロイにてローカルでの変更が即時クラウドに反映されるようにしました。
実際にコードを変更して再度リモート呼び出しを実施してみます。

app.pyの変更

return {
    "statusCode": 200,
    "body": json.dumps({
        "message": "hello world",
        "test_message": "test_message" ← 追加
        # "location": ip.text.replace("\n", "")
    }),
}

sam syncターミナル

Syncing Lambda Function HelloWorldFunction...
Manifest is not changed for (HelloWorldFunction), running incremental build
Building codeuri: C:\xxxxxxxxxx\sam-app\hello_world runtime: python3.9 metadata: {} architecture: x86_64  
functions: HelloWorldFunction
Running PythonPipBuilder:CopySource
Finished syncing Lambda Function HelloWorldFunction.

変更が少ないからなのか、数秒程度で同期が完了しました。

リモート呼び出し実行

$ sam remote invoke HelloWorldFunction --stack-name sam-app

Invoking Lambda Function HelloWorldFunction
START RequestId: 0be84c27-c971-4bfe-b2b0-b7dc68d0e116 Version: $LATEST
END RequestId: 0be84c27-c971-4bfe-b2b0-b7dc68d0e116
REPORT RequestId: 0be84c27-c971-4bfe-b2b0-b7dc68d0e116  Duration: 1.57 ms       Billed Duration: 2 ms   Memory Size: 128 MB     Max Memory Used: 36 MB  Init Duration: 108.95 ms
{"statusCode": 200, "body": "{\"message\": \"hello world\", \"test_message\": \"test_message\"}"}

app.pyに追加したtest_messageがレスポンスに表示されています。
sam syncsam remote invokeを組み合わせることで動作の確認がより迅速に実施できそうです。

コマンドのその他使用例

  • SAMで管理しているLambda関数が1つのみの場合は引数やオプションを省略できます
    • sam remote invoke
  • LambdaのARNを指定することでSAM管理外のLambda関数も呼び出すことができます
    • sam remote invoke {{LambdaArn}}
  • eventevent-fileのオプションでテストイベントを渡すことができます
    • sam remote invoke TranslateFunction --stack-name remote-test --event '{"test_message":"test_message"}'
    • sam remote invoke TranslateFunction --stack-name remote-test --event-file '{{テストイベントファイルパス}}'

まとめ

Lambda関数のテストがより簡単に行えるようになりました。
コードエディタとAWSマネジメントコンソールを行き来することなく、開発に注力できるようになりそうです。
さらにログの出力内容も確認できるようになったため、より細かい粒度でテストが実施できるようになったと思います。

投稿者プロフィール

nagura
2021年4月からスカイアーチに中途入社しました。
AWSともっと仲良くなるべく日々勉強中です。