Closed31

how to install provider when terraform init

ピン留めされたアイテム
ishii1648ishii1648
  • terraform の 対象 version は v1.10
  • install 全般を調べきるのは大変なので興味あるとこだけ
ishii1648ishii1648

.terraform.lock.hcl に selection recorded があればそのバージョンに固定される

If a particular provider already has a selection recorded in the lock file, Terraform will always re-select that version for installation, even if a newer version has become available.

https://developer.hashicorp.com/terraform/language/files/dependency-lock#dependency-installation-behavior

selection recorded は以下の version のこと(=5.84.0)

provider "registry.terraform.io/hashicorp/aws" {
  version     = "5.84.0"
  constraints = "~> 5.0"
  hashes = [
    "h1:TpsSFMkiuLC1V29n4Ov99g4L6jlsBmBMWxqDX3GZNww=",
    "zh:078f77438aba6ec8bf9154b7d223e5c71c48d805d6cd3bcf9db0cc1e82668ac3",
    "zh:1f6591ff96be00501e71b792ed3a5a14b21ff03afec9a1c4a3fd9300e6e5b674",
    "zh:2ab694e022e81dd74485351c5836148a842ed71cf640664c9d871cb517b09602",
    "zh:33c8ccb6e3dc496e828a7572dd981366c6271075c1189f249b9b5236361d7eff",
    "zh:6f31068ebad1d627e421c72ccdaafe678c53600ca73714e977bf45ff43ae5d17",
    "zh:7488623dccfb639347cae66f9001d39cf06b92e8081975235a1ac3a0ac3f44aa",
    "zh:7f042b78b9690a8725c95b91a70fc8e264011b836605bcc342ac297b9ea3937d",
    "zh:88b56ac6c7209dc0a775b79975a371918f3aed8f015c37d5899f31deff37c61a",
    "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
    "zh:a1979ba840d704af0932f8de5f541cbb4caa9b6bbd25ed552a24e6772175ba07",
    "zh:b058c0533dae580e69d1adbc1f69e6a80632374abfc10e8634d06187a108e87b",
    "zh:c88610af9cf957f8dcf4382e0c9ca566ef10e3290f5de01d4d90b2d81b078aa8",
    "zh:e9562c055a2247d0c287772b55abef468c79f8d66a74780fe1c5e5dae1a284a9",
    "zh:f7a7c71d28441d925a25c08c4485c015b2d9f0338bc9707443e91ff8e161d3d9",
    "zh:fee533e81976d0900aa6fa443dc54ef171cbd901847f28a6e8edb1d161fa6fde",
  ]
}
ishii1648ishii1648

無邪気に version を書き換えると checksum との不一致で terraform init が落ちる

❯ g diff .terraform.lock.hcl 
diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl
index b454c00..eb7f6e8 100644
--- a/.terraform.lock.hcl
+++ b/.terraform.lock.hcl
@@ -2,7 +2,7 @@
# Manual edits may be lost in future updates.

provider "registry.terraform.io/hashicorp/aws" {
-  version     = "5.84.0"
+  version     = "5.74.0"
  constraints = "~> 5.0"
  hashes = [
    "h1:TpsSFMkiuLC1V29n4Ov99g4L6jlsBmBMWxqDX3GZNww=",
❯ t init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Installing hashicorp/aws v5.74.0...
╷
│ Warning: Provider development overrides are in effect
│ 
│ The following provider development overrides are set in the CLI configuration:
│  - hashicorp.com/edu/hashicups-pf in /Users/sho/go/bin
│ 
│ Skip terraform init when using provider development overrides. It is not necessary and may error unexpectedly.
╵
╷
│ Error: Failed to install provider
│ 
│ Error while installing hashicorp/aws v5.74.0: the current package for registry.terraform.io/hashicorp/aws 5.74.0 doesn't match any of the checksums previously recorded in the
│ dependency lock file; for more information: https://www.terraform.io/language/provider-checksum-verification
ishii1648ishii1648

ちなみに .terraform.lock.hcl が存在しない状態で terraform init すると以下のようなログになる

❯ t init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.84.0...
- Installed hashicorp/aws v5.84.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

╷
│ Warning: Provider development overrides are in effect
│ 
│ The following provider development overrides are set in the CLI configuration:
│  - hashicorp.com/edu/hashicups-pf in /Users/sho/go/bin
│ 
│ Skip terraform init when using provider development overrides. It is not necessary and may error unexpectedly.
╵
Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
ishii1648ishii1648

どういうケースで locked = false になるのか?

locked = false になり得るのはここだけ。つまり mightNeed が 1個以上で loop が回り、locked[provider] = false が代入されるケース
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L285-L295

mightNeed はここで追加される
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L275

なのでまずはこの loop に入ることが前提
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L202-L204

reqs の定義は以下。恐らく terraform block と .terraform.lock.hcl の両方を merge してこの変数に入れてるのだと思う
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/getproviders/providerreqs/version.go#L49-L57

ここで locked[provider] = true が代入されているので、このブロックを skip すると locked[provider] が初期値のまま以降の処理が実行されて結果 locked = false になる
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L272

以降 locked[provider] = false になる具体的なケースを見る

ishii1648ishii1648

1. InstallMode == InstallUpgrades になるケース

InstallMode == InstallUpgrades だと以下のブロックを丸ごと skip する
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L246-L274

--upgrade オプションを指定した場合に InstallMode == InstallUpgrades になるっぽい
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/command/init.go#L863-L871

ishii1648ishii1648

log message の出力としては以上だが、実際にどうやって install しているのか?

ishii1648ishii1648

install はこの loop で provider ごとに行っている

https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L339-L343

最初に .terraform 配下をチェックして provider が install 済みの場合は continue して以降の install 処理を実行しない
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L357-L367

ishii1648ishii1648

次に globalCacheDir が設定されているかをチェックする(例:TF_PLUGIN_CACHE_DIR が設定されているケース)。globalCacheDir が設定されていて、globalCache が存在する場合は専用の install 処理を開始する
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L369-L372

globalCache provider が .terraform.lock.hcl のいずれかの hash に match してるかをチェック
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L390-L399

ishii1648ishii1648

次に globalCache が無い場合を見ていく

まずは install の前段階として packageMeta を取得する
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L547-L554

terraform registry に HTTP リクエストを投げて取得した以下レスポンスを parse して packageMeta に代入している
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/getproviders/registry_client.go#L220-L232

該当箇所の DEBUG log の例

2025-01-25T20:54:16.930+0900 [DEBUG] GET https://registry.terraform.io/v1/providers/hashicorp/aws/5.84.0/download/darwin/amd64

また後で provider を download した際の認証で利用するをここで設定する
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/getproviders/registry_client.go#L357-L361

ishii1648ishii1648

provider の install はここで行っている
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L576

meta.Location に応じて install 方法が分かれている。getproviders.PackageHTTPURL 以外のケースはどういう時に使われるのか良くわからない(filesystem mirror 使ってる時?)。が、普段遣いしないので無視して、installFromHTTPURL() の内部実装を見ていく
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/dir_modify.go#L34-L46

ishii1648ishii1648

terraform init の TRACE log からも分かるが terraform registry から provider download する場合は zip ファイルを download している

2025-01-25T19:31:26.523+0900 [TRACE] HTTP client GET request to https://releases.hashicorp.com/terraform-provider-aws/5.84.0/terraform-provider-aws_5.84.0_darwin_amd64.zip

zip ファイルを download すると認証を実行して、ファイルの妥当性をチェックする
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/package_install.go#L76-L84

認証は三段階で処理される

ishii1648ishii1648

最初の2つは hash の比較で、1つ目は terraform registry が提供している SHA-256 と一致してるかを見る。packageMeta で取得しておいた "shasums_url":"https://releases.hashicorp.com/terraform-provider-aws/5.84.0/terraform-provider-aws_5.84.0_SHA256SUMS" からファイルをダウンロードする。中身は以下のようになっていて、 SHA-256 のハッシュ値と zip ファイル名が列挙されている

b058c0533dae580e69d1adbc1f69e6a80632374abfc10e8634d06187a108e87b  terraform-provider-aws_5.84.0_darwin_amd64.zip
078f77438aba6ec8bf9154b7d223e5c71c48d805d6cd3bcf9db0cc1e82668ac3  terraform-provider-aws_5.84.0_darwin_arm64.zip
6f31068ebad1d627e421c72ccdaafe678c53600ca73714e977bf45ff43ae5d17  terraform-provider-aws_5.84.0_freebsd_386.zip
e9562c055a2247d0c287772b55abef468c79f8d66a74780fe1c5e5dae1a284a9  terraform-provider-aws_5.84.0_freebsd_amd64.zip
a1979ba840d704af0932f8de5f541cbb4caa9b6bbd25ed552a24e6772175ba07  terraform-provider-aws_5.84.0_freebsd_arm.zip
1f6591ff96be00501e71b792ed3a5a14b21ff03afec9a1c4a3fd9300e6e5b674  terraform-provider-aws_5.84.0_linux_386.zip

ここから対象の zip ファイル名のハッシュ値とその手前で terraform registry から取得してきたハッシュ値が一致してるかをチェックしている
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/getproviders/package_authentication.go#L363-L366

「このチェックいるか?」という気もするが...一応コメントに理由書かれているがよくわからない
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/getproviders/package_authentication.go#L326-L328

ishii1648ishii1648

version 決定の仕組みはどうなっているのか?

ishii1648ishii1648

最終的にここで install version を決定している
https://github.com/hashicorp/terraform/blob/f7640b36f3c4951e279e377f7bcdc72e2a7436e4/internal/providercache/installer.go#L245-L275

流れはざっと以下の通り

  1. required_providers から与えられた versionConstraints が適切な値かチェックしつつ parse して Set 型に代入
  2. --upgrade オプションを指定しておらず、かつ .terraform.lock.hcl 対象の provider 情報がある場合は記載の version を acceptableVersions として固定する
  3. 「2」に合致しない場合は required_providers の versionConstraints を acceptableVersions として設定する

つまり .terraform.lock.hcl の設定を優先し、存在しない場合は required_providers の設定が効くようになっている

ishii1648ishii1648

以下エッジケース

  • .terraform.lock.hcl が存在せず required_providers 側に version 指定が無い場合
    • latest version の provider が install される
  • .terraform.lock.hcl はあるが required_providers が無い場合
    • .terraform.lock.hcl に記載されている provider version が install される
  • .terraform.lock.hcl と required_providers 両方とも存在しない場合
    • provider block で指定した provider の latest version が install される
このスクラップは2025/03/14にクローズされました