localstack を使ってモックの AWS Lambda 呼び出しを行う


概要

自分向けの備忘録。

Lambda 側では Python、 呼び出し側では Node.js という構成を試した。

この記事を参考にさせていただいた。

https://kazuhira-r.hatenablog.com/entry/2018/10/24/002715

環境

  • macOS
  • Docker 20.10
  • python 3.9
  • node 16.13

localstack

version: "3"
services:
  localstack:
    image: localstack/localstack:latest
    ports:
      - "4566:4566"
    environment:
      - SERVICES=${SERVICES- }
      - DEBUG=${DEBUG- }
      - DATA_DIR=${DATA_DIR- }
      - PORT_WEB_UI=${PORT_WEB_UI- }
      - LAMBDA_EXECUTOR=docker
      - KINESIS_ERROR_PROBABILITY=${KINESIS_ERROR_PROBABILITY- }
      - DOCKER_HOST=unix:///var/run/docker.sock
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
docker-compose up

4566ポートで localstack が立ち上がり、モックの AWS Lambda が使えるようになる。

関数登録

lambda.py
def my_handler(event, context):
    return { "result": event["n"] * 2 }

dist.zip に固める。

pack.sh
zip -r dist.zip lambda.py

localstack 上のモック AWS Lambda に関数登録。

create.sh
aws --endpoint-url=http://localhost:4566 \
   lambda create-function \
   --function-name hello_lambda \
   --runtime python3.9 \
   --zip-file fileb://`pwd`/dist.zip \
   --role test-role \
   --handler lambda.my_handler

関数一覧。

ls.sh
aws --endpoint-url=http://localhost:4566 lambda list-functions

AWS CLI で実行。

invoke.sh
 aws --endpoint-url=http://localhost:4566 \
  lambda invoke \
  --function-name hello_lambda \
  --payload '{"n": 5}' \
  result.log

結果は以下の通り。

result.log
{"result":10}

Node.js からの呼び出し

yarn init -y
yarn add @aws-sdk/client-lambda
invoke.mjs
import { Lambda } from "@aws-sdk/client-lambda";

export const invokeLambda = async (n) => {
  const lambdaClient = new Lambda({
    endpoint: "http://localhost:4566",
    forcePathStyle: true,
  });
  const result = await lambdaClient.invoke({
    FunctionName: "hello_lambda",
    LogType: "None",
    Payload: new TextEncoder().encode(JSON.stringify({ n })),
  });
  const res = JSON.parse(
    new TextDecoder("utf-8").decode(result.Payload) || "{}"
  );
  return res;
};

const main = async () => {
  const res = await invokeLambda(50);
  console.log(res);
};

main();

実行してみる。

invoke.mjs
node invoke.mjs

結果。

{ result: 100 }

うまく行った。