aws-sam-cliで独自の環境変数を扱うには?
はじめに
この記事は、AWS SAMを用いてLambda関数の実装をローカルで行う際に、
ユーザ独自の環境変数をどう扱うかについてハマってしまったことをまとめた記事です。
Lamnda関数を通してTwitterAPIを用いてツイートを送信する処理を実装したのですが、ローカルでの実行時にAPIキーなどを扱う時に苦労しました。
これが正解かどうかは確かではありませんが、ローカルでの検証や実行を行う際のやり方の一つではないかと思います。
godotenvが使えない…?
今回、Lambda関数はGolangを用いて開発をしました。
Golangにおいて環境変数を読み込む時は、godotenvというオープンソースパッケージを用いて.envファイルから環境変数を読み込んでいます。
HOGE_ACCESS_TOKEN=""
HOGE_ACCESS_TOKEN_SECRET=""
err := godotenv.Load()
しかし、AWS SAMを用いて開発をした場合、この.env
ファイルを読み込むのには少し癖があるそうです。
というのも、AWS SAMを用いて開発をした場合、SAM側はLambdaを実行している時だけDockerコンテナを立ち上げるため、通常go run main.go
コマンドを使ってプログラムを実行するだけで読み込めた.env
ファイルが読み込めない場合がほとんどです。
※こちらについて、僕なりに.env
ファイルをDocker Lambdaで読み込む方法を調べましたが、良い方法を見つけることが出来ませんでした😢
環境変数を定義するJSONから読み込む
SAMのドキュメントを読んでみると、--env-vars
という環境変数を読み込むためのオプションが用意されています。
環境変数ファイルとは何かというのをさらに調べたところ、Lambda関数に定義されている環境変数をJSON形式で書くことによって、それらを上書きできるというものらしいです。
Lambda関数の環境変数の定義はAWSのコンソール上からも定義が出来るので、それらをJSONで管理しているものと考えて良いでしょう。
ドキュメントによると、JSONは以下のように定義が出来ます。
{
"Your function name": {
"TABLE_NAME": "hoge",
"BUCKET_NAME": "fuga"
}
}
今回私はTwitterのAPIキーをこのenv.json
に記載しました。
なおこのJSONファイルは、.gitignore
に含めることをオススメします。リポジトリにはenv.sample.json
的な名前をつけた空っぽのファイルをpushしましょう。
{
"Your function name": {
"TWITTER_API_KEY": "hogehoge",
"TWITTER_SECRET_KEY": "fugafuga"
}
}
template.yamlから定義済み環境変数を読み込む
env.json
に定義したファイルを、今度はLambda関数に読み込ませます。
SAM templateを用いてLambda関数を生成した場合、template.yaml
というファイルが生成されていると思います。
こちらのyamlファイルのParameter
セクションにAPIキーのフィールドを定義します。
このフィールドには、後ほどsam deploy
コマンドを使ってデプロイする際に上書きされます。
Description: >
Sample function
Params:
APIKey:
Type: String
SecretKey:
Type: String
受け取ったAPIキーを、Resources
セクションの中でこのlambda関数の環境変数として設定をします。
Resources:
SampleFunction:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
TWITTER_API_KEY: !Ref TwitterAPIKey
TWITTER_SECRET_KEY: !Ref TwitterSecretKey
コードから環境変数を読み込み、実行
読み込まれた環境変数は、os.Getenv()
を使ってコード上から呼び出すことが可能です。
// getCredential TwitterAPIを取得する
func getCredential() *anaconda.TwitterApi {
return anaconda.NewTwitterApiWithCredentials(
os.Getenv("TWITTER_ACCESS_TOKEN"),
os.Getenv("TWITTER_ACCESS_TOKEN_SECRET"),
)
}
忘れてはならないのが、sam local invoke
コマンドを使って実行する際に--env-vars
オプションをつけて実行することです。
sam build; sam local invoke SampleFnuction \
--env-vars env.json
デプロイ
さて、sam local invoke
コマンドにおいてはenv.json
から環境変数を読み込みましたが、デプロイを実行するsam deploy
コマンドにはそのオプションがありません😭
代わりに、--parameter-overrides
オプションがあるのでそのオプションで環境変数を定義します。
今回僕は予めzshrc
などにAPIキーをexportしておき、ShellScriptから参照できるようにしました。
sam deploy --parameter-overrides APIKey=$TWITTER_API_KEY SecretKey=$TWITTER_SECRET_KEY
まとめ
godotenv
を使って環境変数を読み込む方法を見つけられなかったので、JSONファイルから独自の環境変数を定義して読み込むやり方を採用しましたが、これよりも良い方法が何かしらあると思っています。
実際に、aws-sam-cliのissueにも、dotenvファイルを読み込むオプションを作らないかという提案が上がっているのを見つけました。
feat(init): load .env file at startup of sam local #1355
現状、sam-cliを使って.env
ファイルをローカルで読み込む方法は無さそうなので、しばらくは今回紹介したやり方で運用をしようかと思います。
Discussion
同様の問題に遭遇して参考にさせていただきました!
SAM CLI configuration file を使えば local invoke も deploy も一つのファイルで解決しそうですよ。
以下のようなファイルを project の root directory に置いておけば、引数指定しなくても
sam local invoke SampleFnuction
,sam deploy
だけで行けるはずです。コメントありがとうございます!
記事を参考にしていただき、筆者としても嬉しい限りです。
samconfig.toml
ファイルにparameter_overrides
オプションがあったのは知りませんでした…!これをすることで、記事内でも記載している
deploy.sh
などは不要になって、1つのファイルで完結しそうですね!git管理をする場合は、tomlファイルにパラメータを直書きしている関係上、取り扱いには気をつけないといけないのでどちらの方法を取るかはプロジェクト毎に変わりそうですね😃