前提
goのバージョンとterraformのバージョンは以下
今回の記事の対象は恐らくgo 1.18以降を使っている人
go version
go version go1.19.2 darwin/arm64
terraform -v
Terraform v1.3.6
今回の問題
terraformで以下のようなコードでlambdaのリソース管理をしていた
resource "aws_lambda_function" "go_function" {
filename = "go_function.zip"
function_name = "go_function"
handler = "main"
source_code_hash = filebase64sha256("go_function.zip")
runtime = "go1.x"
}
go_function.zip
はgithub actionsのworkflow内でbuildしたbinaryをzip化していた。
その際のコマンドは以下
GOOS=linux GOARCH=amd64 go build -o dist/go-function go-function
zip -j go_function.zip dist/go-function
なおbinaryファイルとzipファイルはgitignoreしている。
lambda以外にもAWSのリソース管理を同じリポジトリでおこなっており、他のリソースをコード化しcommit後planを確認した。
goのソースコードに変更はないのだが、planでlambdaのsource_code_hash
の差分が出る
# aws_lambda_function.go_function will be updated in-place
~ resource "aws_lambda_function" "go_function" {
id = "go_function"
~ last_modified = "2022-01-01T00:00:00.000+0000" -> (known after apply)
~ source_code_hash = "old hash" -> "new hash"
# (3 unchanged attributes hidden)
# (3 unchanged blocks hidden)
}
試した事
zip化する際に日付とかの余計な情報を持ってしまっているのでは?
と思い調べたが、よく分からず...
たどり着いたのがterraformの archive_fileを使えばzip化を行うことができ、output_base64sha256
を source_code_hash
に使えば良いという記事
早速以下に変更し試してみる
data "archive_file" "go_function_zip" {
type = "zip"
source_file = "../dist/go-function"
output_path = "../dist/go_function.zip"
}
resource "aws_lambda_function" "go_function" {
filename = data.archive_file.go_function_zip.output_path
function_name = "go_function"
handler = "main"
source_code_hash = data.archive_file.go_function_zip.output_base64sha256
runtime = "go1.x"
}
一度applyし、その後READMEだけを更新したコミットで差分を見てみる
# aws_lambda_function.go_function will be updated in-place
~ resource "aws_lambda_function" "go_function" {
id = "go_function"
~ last_modified = "2022-01-01T00:00:00.000+0000" -> (known after apply)
~ source_code_hash = "old hash" -> "new hash"
# (3 unchanged attributes hidden)
# (3 unchanged blocks hidden)
}
上手くいかず。
色々試行錯誤していくうちに気付く。あれ?build後のbinaryファイルのhashが違う
READMEのみ更新したコミットでbuildしたbinaryファイルのhashと、一つ前のコミットでbuildしたbinaryファイルのhashが違った
結論
どうやらgo1.18以降ではbinaryファイルにコミットハッシュなどのmeta情報を持っているらしい
go version -m dist/go-function
dist/go-function: go1.19.2
...省略
build -compiler=gc
build CGO_ENABLED=0
build GOARCH=amd64
build GOOS=linux
build GOAMD64=v1
build vcs=git
build vcs.revision=commit hash
build vcs.time=2022-01-01T00:00:00Z
build vcs.modified=false
このvpc.revision
にcommit hashを持っていたため、goのリソースに何も変更がなくてもコミットする度に差分が出ていた模様
これはbuildする際に-buildvcs=false
をつければbinaryファイルにこの情報を含めないよう出来るとのこと
って事でbuildする際のコマンドを以下に変更
GOOS=linux GOARCH=amd64 go build -buildvcs=false -o dist/go-function go-function
無事毎回差分が出なくなりました