0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

DENSOAdvent Calendar 2021

Day 13

ServerlessFramework + AWS + Pythonで作るレイヤーと単体テスト

Posted at

はじめに

ServerlessFramework + AWS + Pythonでバックエンドを構築しているとき、開発規模が大きくなってくるとLambda内のPythonコードを共通化したくなることがあると思います。そんなときに使えるのがLambdaレイヤー。Lambdaレイヤーとして作ったモジュールを色々なLambdaで使い回すことができます。モジュールのサイズが大きくなりすぎてコンソールで表示されなくなった時の切り分けにも使えそうです

以前の記事の続きです

最終的な構成

/
├── serverless.yml
├── functions/
│   ├── hello/
│   │   ├── handler.py
│   │   └── requirements.txt
├── layers/
│   ├── original_module.py
├── layers-test/
│   ├── test_original_module.py

作り方

Lambdaレイヤーを定義して、Lambdaと紐付ける

serverless.ymlのルートレベルにLayer定義を追加して、functionsと紐付けます

serverless.yml
layers:
  layer-modules:
    path: layers
    description: layer for ingredients
    CompatibleRuntimes:
      - python3.8

functions:
  hello:
    module: functions/hello
    handler: handler.hello
    layers:
      - Ref: LayerDashmodulesLambdaLayer  # layerとの紐付け部
    events:
      - http:
          path: /users/create
          method: get

LambdaとLayerを紐づけている部分ですが、少し変わった名前になっているかと思います。この名前は.serverless/serverless-state-.jsonの中で検索してもらえると出てきます。どうやらlayersで定義している名前「layer-modules」をもとに、自動で生成されているようです(modulesは先頭大文字にならないのか...)

Lambdaレイヤー側のコード

original_module.py
# coding: UTF-8

class OriginalModule:
    def add(self, arg1, arg2):
        return arg1 + arg2

Lambdaレイヤー呼び出し側のコード

hander.py
import sys
sys.path.append('/opt')
from original_module import OriginalModule

def hello(event, context):
    originalModule = OriginalModule()
    result = originalModule.add(3, 5)

# 〜 略 〜 #

LambdaにLayerを紐づけると、Lambda実行ディレクトリの/opt以下に生成されるようです。エラーが出る場合はrequirements.txtを置き忘れていたり名前を間違えていたり、Dockerデーモンが動いているかを確認してみてください

単体テストを追加

Layer化されているとAWSコンソールからでは修正できなくなります。そうすると気軽にトライアンドエラーできなくなるので、単体テストをしっかりやったほうがいいかと思っています

test_original_module.py
# coding: UTF-8
import unittest
import os
import sys

sys.path.append(
    os.path.join(os.path.dirname(__file__), 
    '../layers/')
)
from original_module import OriginalModule

class TestOriginalModule(unittest.TestCase):
    def test_case(self):
        target = OriginalModule()
        self.assertEqual(target.add(1, 2), 3)

実行するときはこんな感じです

python -m unittest test_original_module
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?