工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

Lambda レイヤーのソースコードをアップデートするPythonスクリプト

概要

layerのコードをアップデートするPythonスクリプトを作成した。



背景と目的

Lambda レイヤーのコードをデバッグしていて、手動でアップロードするのが面倒になってきたので、スクリプト化した。



詳細

zipの構造の確認

手動でアップロードする場合、.zipファイルの構造としては、を解凍した時に以下のようになる必要がある。すなわち、pythonというフォルダが出てきて、その中にレイヤー名フォルダが入る形。

python/
    レイヤー名フォルダ/
        __init__.py
        ソースコード.py


作成したスクリプト

作成したものは以下。

引数として、レイヤー名と同じ名前のフォルダがあってその中にソースコードが入っている想定で、そのレイヤー名フォルダのパスを指定する。

一時フォルダpythonを作ってそこにソースコードを入れて、圧縮することで、必要な構造を実現する。

送信は、boto3を使う。CompatibleRuntimesは、適宜設定。

import zipfile
import os
import json
import boto3
import sys
import shutil

"""
Lambdaのlayerを更新

update_layer.py target

target
-------------------------
親フォルダ/
    python.zip --- 一時zip
    python/ --- zip作成用一時ディレクトリ
        : レイヤー名フォルダがコピーされる
    レイヤー名ディレクトリ/ --- ここを引数targetで指定
        __init__.py
        ソースコード.py
"""

zipFileName = "python.zip"
CompatibleRuntimes = [ 'python3.7', 'python3.8' ]

target = None
if len(sys.argv) >= 2:
    target = sys.argv[1]

print("sys.argv[1]", sys.argv[1])

if target is None:
    print("no args")
    sys.exit()

# 出力先
outputDir = os.path.dirname(target) # zip出力先
LayerName = os.path.basename(target) # フォルダ名のみ
pythonDir = os.path.join(outputDir, "python")
zipFilePath = os.path.join(outputDir, zipFileName)

# 念のため一時ファイルを削除
try:
    os.remove(zipFilePath)
except:
    pass
try:
    shutil.rmtree(pythonDir)
except:
    pass

# 一時ディレクトリ作成
os.makedirs(pythonDir, exist_ok=True)

# ソースコードフォルダをコピー
shutil.copytree(target, os.path.join(pythonDir, LayerName))

# ZIPファイルを作成
zipFile = zipfile.ZipFile(zipFilePath, 'w')

# 圧縮するファイルのディレクトリへ移動
os.chdir(outputDir)

# ZIPファイルに追加
for dirName, dirs, files in os.walk(pythonDir):
    # dirNameの絶対パスを相対パス化
    dirName2 = dirName.replace("\\", "/").replace(outputDir.replace("\\", "/") + "/", "")
    #print("dirName2", dirName2)
    for fileName in files:
        filepath = os.path.join(dirName2, fileName)
        print("filepath", filepath)
        zipFile.write(filepath, compress_type=zipfile.ZIP_DEFLATED)

# 閉じる
zipFile.close()

# zipをバイナリで読み取る
fo = open(zipFilePath, "rb")
zf = fo.read()
fo.close()

# アップロード
client = boto3.client("lambda")
resp = client.publish_layer_version(
    LayerName=LayerName,
    Content={
        'ZipFile': zf
    },
    CompatibleRuntimes=CompatibleRuntimes
)

# 一時ファイル削除
try:
    os.remove(os.path.join(outputDir, zipFileName))
except:
    pass
shutil.rmtree(pythonDir)

# 結果
print(json.dumps(resp, indent=4))


テスト

無事、更新され新しいバージョンが発行された。



まとめと今後の課題

これで、少しレイヤー周りのデバッグが楽になる。