codebuildでterraform init
をした時に下記のようなエラーが出力されて落ちた
Initializing provider plugins... - Reusing previous version of hashicorp/aws from the dependency lock file - Installing hashicorp/aws v3.42.0... Error: Failed to install provider Error while installing hashicorp/aws v3.42.0: the current package for registry.terraform.io/hashicorp/aws 3.42.0 doesn't match any of the checksums previously recorded in the dependency lock file
メッセージを読むと、どうやらリポジトリの.terraform.lock.hcl
に含まれているproviderのハッシュ値が一致しないことが原因となっている模様。
.terraform.hcl.lock
依存しているproviderとそのバージョンを固定するlockファイルであり、Terraform0.14から導入された。多くの言語に備わっているpackage.lockなどの仕組みと似ている。
terraform init
を実行した際、.terraform.hcl.lockに.tfで宣言しているproviderの記述がなければバージョン制約に基づいて最新のものを取得した後、その情報をlockファイルに書き込む。記述があればそれと同じバージョンを取得する。
この時同時にlockファイルのproviderに付随しているチェックサムをもとに、initで取得したproviderと一致するかの検証が行われ、*1検証が失敗するとinitは失敗する。
原因
ローカルでterraform initした時に記述された.terraform.hcl.lockに含まれるproviderのチェックサムが、CI上でinitした時に取得・計算されたproviderのチェックサムと一致しなかったことが原因。ローカルとリモートでOSなどのプラットフォームが異なっていたり、ローカルでProvider Plugin Cache*2を使っている場合にチェックサムの不一致が生じてしまう。
対処
terraform providers lock
というコマンドを利用することで事前に複数のプラットフォーム向けにチェックサムを生成し、.terraform.hcl.lockを生成することができる。例えば、ローカルのmacOSとCI上のLinuxでinitを実行する場合、ローカルで次のコマンドを実行することで.terraform.hcl.lockを生成する。
$ terraform providers lock \ -platform=darwin_amd64 \ # 64-bit macOS -platform=linux_amd64 # 64-bit Linux
参考
実際にはもっと複雑な事情があるらしい。 speakerdeck.com
*1:SSHのknown_hostsの仕組みと同じくtrust on first useを採用している
*2:https://www.terraform.io/docs/cli/config/config-file.html#provider-plugin-cache