環境
- Terraform 1.7.4
- Terragrunt 0.55.1
- hashicorp/aws 5.36.0
- hashicorp/external 2.3.3
- WSL2(Ubuntu)
経緯
TerraformでLambda関数をデプロイするためにpnpmのプロジェクトをtfファイルと同一階層に配置し、apply時にトランスパイルや不要ファイルの削除を行いzip化しようとしていた
そのためにexternal data sourceやarchive_file data sourceを利用していたのだが、なぜかbashファイルの実行に失敗するという現象でハマってしまった
ディレクトリ構成
.
├── bin
│ └── build.sh
├── lambda
│ ├── index.ts
│ ├── jest.config.js
│ ├── node_modules
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── tests
│ │ └── index.spec.ts
│ └── tsconfig.json
└── lambda.tf
※記事の趣旨と関係のないファイルは除外しています
data "external" "tmp" {
program = ["./bin/build.sh"]
}
data "archive_file" "lambda_src" {
depends_on = [data.external.tmp]
type = "zip"
source_dir = "./tmp"
output_path = "./lambda.zip"
}
resource "aws_lambda_function" "main" {
depends_on = [data.archive_file.lambda_src]
filename = data.archive_file.lambda_src.output_path
function_name = "foo"
role = "bar"
handler = "index.lambdaHandler"
runtime = "nodejs20.x"
source_code_hash = data.archive_file.lambda_src.output_base64sha256
}
#!/bin/bash
# 前回実行時の一時ファイル等が残っていた場合に削除
if [ -d ./tmp ]; then
rm -rf ./tmp
fi
if [ -f ./lambda.zip ]; then
rm ./lambda.zip
fi
# pnpmのプロジェクトがあるディレクトリをコピー
cp -r ./lambda ./tmp
cd ./tmp
# jsへトランスパイル
tsc index.ts
# 本番環境で不要になるファイルの削除
rm -rf node_modules tests jest.config.js index.ts tsconfig.json
# 本番環境用のnode_modulesを取得
pnpm install --prod
exit 0
エラー
上記の状態でterragrunt apply
したところ以下のようなエラーが発生
│ The data source received unexpected results after executing the program.
│
│ Program output must be a JSON encoded map of string keys and string values.
│
│ If the error is unclear, the output can be viewed by enabling Terraform's
│ logging at TRACE level. Terraform documentation on logging:
│ https://www.terraform.io/internals/debugging
│
│ Program: ./bin/build.sh
│ Result Error: invalid character 'L' looking for beginning of value
解決方法
build.shを以下のように修正したところ問題なく実行された
修正点としては以下の2点
-
pnpm install
でsilentオプションを設定 -
echo '{}'
でjson形式の文字列を出力
#!/bin/bash
# 前回実行時の一時ファイル等が残っていた場合に削除
if [ -d ./tmp ]; then
rm -rf ./tmp
fi
if [ -f ./lambda.zip ]; then
rm ./lambda.zip
fi
# pnpmのプロジェクトがあるディレクトリをコピー
cp -r ./lambda ./tmp
cd ./tmp
# jsへトランスパイル
tsc index.ts
# 本番環境で不要になるファイルの削除
rm -rf node_modules tests jest.config.js index.ts tsconfig.json
# 本番環境用のnode_modulesを取得
pnpm install --prod --silent # silentオプションで標準出力を防止
# json形式のoutputを出力
echo '{}'
exit 0
結論
公式にちゃんと書いてありました。。。
公式はしっかり読むべき(N回目)
The program must then produce a valid JSON object on stdout, which will be used to populate the result attribute exported to the rest of the Terraform configuration. This JSON object must again have all of its values as strings. On successful completion it must exit with status zero.
If the program encounters an error and is unable to produce a result, it must print a human-readable error message (ideally a single line) to stderr and exit with a non-zero status. Any data on stdout is ignored if the program returns a non-zero status.