はじめに
本記事はタイトルの通りです。
とてもハマったため、備忘録として残しておこうと思ったのと同じようにハマって
しまった方の参考になればと思います。
結果的にAWS Lambda上でBoxSDKを使ったAPIは動作しました。
先にどうやって動いたかを紹介したあと、ハマった経緯や原因などの解説にはいります。
Lambda環境(BoxSDK動作確認済み)
こちらの記事を参考にBoxSDKをインストール、ZIP化、S3への格納、Lambdaへのレイヤー追加を行います。cryptographyのレイヤー追加、記事ですがBoxSDKもかなり関わってました。
レイヤー追加時ですが、互換性のあるランタイムにpython3.7/3.8/3.9を指定
互換性のあるアーキテクチャはx86_64を指定しました。
続いてLambda関数を作成します。ランタイムはPython3.7、アーキテクチャはx86_64で作成しました。
BoxAPIはJWT認証で動かす予定でしたのでboxsdkのモジュールのコードは下記の通り
from boxsdk import Client
from boxsdk.auth.jwt_auth import JWTAuth
公式の通りだとNGでした。
from boxsdk import JWTAuth
APIでBoxと通信が出来ました。
ハマった点について
BoxSDKでは2つの問題により上手く動作しませんでした。
- BoxSDK自体のバグ?問題
- pipの依存関係
それぞれ、振り返っていきたいと思います。
まず、前提としてローカルのマシン環境だと問題は起きませんでした。
Lambdaで動かそうとすると動かない(正確にはAttributeやImport Module Error)
今までこのようなケースがなかったため原因がある程度わかるまで時間がかかりました。
最初のErrorの始まり
Windowsのローカル環境で動作確認済みのコードをLambdaに移し、Windowsの環境でpipインストールしたboxsdkをsite-packagesから抜き取りLambdaにレイヤー追加、コードをテストしたところ、AttributeErrorが発生
JWTAuthにはfrom_settings_fileのfrom_setting_fileなんてAttributeは持ってないよと
え?なんで??
ローカル環境では動いてまっせ・・・
ネットで手当たり次第検索してみる
pip install時はboxsdk[jwt]だけにするんだぜ!みたいな記事を見て
再度pipインストールをしてアップロード、結果変わらず・・・
色々調べてると
そもそも、boxsdkパッケージの配下にJWTAuthってないじゃん
え?なんで??ローカルでは動いてんの・・・
パッケージ内のモジュールを手当たり次第探索すると
boxsdk/auth/jwt_auth.py内にJWTAuthのClassを発見
え?公式のモジュールの呼び出し方おかしくない??
調べてみるとboxsdkの__init__.pyに原因があるっぽい
from .auth import JWTAuth, OAuth2, CCGAuth
相対パスでauthからJWTAuthをインポートしようとしててエラーになってたみたい
この件は、ネット検索してたら誰かがフォーラムに上げてたので気づいてたらもっと早く分かってた・・・
インポートのコードの記述を変更して解決
さて本当の問題はここから
依存関係
先に書くと、依存関係についてまったく無知だったのが問題でした
細かく書くと長くなるので簡潔に
まず、Windows環境でpipインストールしたパッケージはLambdaでは動かないことがある
Lambdaの実行環境がLinuxだから
- OS毎に依存関係が変わる
AWSクラウドシェルでpipインストールしたパッケージがImport Module Errorとなるのは、Lambdaのアーキテクチャをarm64では動かないと思われる(この辺りは本当にそうなのかインプットできていないので間違ってたらすみません)
- AWSクラウドシェル(AWS Linux)がx86_64アーキテクチャだから(たぶん)
AWSクラウドシェルでインストール時、おそらくPython3.7の環境でインストールしたので
- LambdaのランタイムもPython3.7に合わせないといけない(たぶん)
下記の記事の通り、Lambdaにレイヤーを追加する際はDockerを使った方がよさそうです
ちゃんと読み込んで間違っていれば後から記事を訂正します。
参考