mirror of
https://github.com/hashicorp/terraform.git
synced 2026-05-28 04:03:27 -04:00
init: Make both provider override methods (dev_overrides and reattaching providers) behave same in the context of provider download (#38634)
Some checks are pending
build / Determine intended Terraform version (push) Waiting to run
build / Determine Go toolchain version (push) Waiting to run
build / Generate release metadata (push) Blocked by required conditions
build / Build for freebsd_386 (push) Blocked by required conditions
build / Build for linux_386 (push) Blocked by required conditions
build / Build for openbsd_386 (push) Blocked by required conditions
build / Build for windows_386 (push) Blocked by required conditions
build / Build for darwin_amd64 (push) Blocked by required conditions
build / Build for freebsd_amd64 (push) Blocked by required conditions
build / Build for linux_amd64 (push) Blocked by required conditions
build / Build for openbsd_amd64 (push) Blocked by required conditions
build / Build for solaris_amd64 (push) Blocked by required conditions
build / Build for windows_amd64 (push) Blocked by required conditions
build / Build for freebsd_arm (push) Blocked by required conditions
build / Build for linux_arm (push) Blocked by required conditions
build / Build for darwin_arm64 (push) Blocked by required conditions
build / Build for linux_arm64 (push) Blocked by required conditions
build / Build for windows_arm64 (push) Blocked by required conditions
build / Build for linux_s390x (push) Blocked by required conditions
build / Build Docker image for linux_386 (push) Blocked by required conditions
build / Build Docker image for linux_amd64 (push) Blocked by required conditions
build / Build Docker image for linux_arm (push) Blocked by required conditions
build / Build Docker image for linux_arm64 (push) Blocked by required conditions
build / Build Docker image for linux_s390x (push) Blocked by required conditions
build / Build e2etest for linux_386 (push) Blocked by required conditions
build / Build e2etest for windows_386 (push) Blocked by required conditions
build / Build e2etest for darwin_amd64 (push) Blocked by required conditions
build / Build e2etest for linux_amd64 (push) Blocked by required conditions
build / Build e2etest for windows_amd64 (push) Blocked by required conditions
build / Build e2etest for linux_arm (push) Blocked by required conditions
build / Build e2etest for darwin_arm64 (push) Blocked by required conditions
build / Build e2etest for linux_arm64 (push) Blocked by required conditions
build / Run e2e test for linux_386 (push) Blocked by required conditions
build / Run e2e test for windows_386 (push) Blocked by required conditions
build / Run e2e test for darwin_amd64 (push) Blocked by required conditions
build / Run e2e test for linux_amd64 (push) Blocked by required conditions
build / Run e2e test for windows_amd64 (push) Blocked by required conditions
build / Run e2e test for linux_arm (push) Blocked by required conditions
build / Run e2e test for linux_arm64 (push) Blocked by required conditions
build / Run terraform-exec test for linux amd64 (push) Blocked by required conditions
Quick Checks / Unit Tests (push) Waiting to run
Quick Checks / Race Tests (push) Waiting to run
Quick Checks / End-to-end Tests (push) Waiting to run
Quick Checks / Code Consistency Checks (push) Waiting to run
Quick Checks / Automated defect checks (push) Waiting to run
Some checks are pending
build / Determine intended Terraform version (push) Waiting to run
build / Determine Go toolchain version (push) Waiting to run
build / Generate release metadata (push) Blocked by required conditions
build / Build for freebsd_386 (push) Blocked by required conditions
build / Build for linux_386 (push) Blocked by required conditions
build / Build for openbsd_386 (push) Blocked by required conditions
build / Build for windows_386 (push) Blocked by required conditions
build / Build for darwin_amd64 (push) Blocked by required conditions
build / Build for freebsd_amd64 (push) Blocked by required conditions
build / Build for linux_amd64 (push) Blocked by required conditions
build / Build for openbsd_amd64 (push) Blocked by required conditions
build / Build for solaris_amd64 (push) Blocked by required conditions
build / Build for windows_amd64 (push) Blocked by required conditions
build / Build for freebsd_arm (push) Blocked by required conditions
build / Build for linux_arm (push) Blocked by required conditions
build / Build for darwin_arm64 (push) Blocked by required conditions
build / Build for linux_arm64 (push) Blocked by required conditions
build / Build for windows_arm64 (push) Blocked by required conditions
build / Build for linux_s390x (push) Blocked by required conditions
build / Build Docker image for linux_386 (push) Blocked by required conditions
build / Build Docker image for linux_amd64 (push) Blocked by required conditions
build / Build Docker image for linux_arm (push) Blocked by required conditions
build / Build Docker image for linux_arm64 (push) Blocked by required conditions
build / Build Docker image for linux_s390x (push) Blocked by required conditions
build / Build e2etest for linux_386 (push) Blocked by required conditions
build / Build e2etest for windows_386 (push) Blocked by required conditions
build / Build e2etest for darwin_amd64 (push) Blocked by required conditions
build / Build e2etest for linux_amd64 (push) Blocked by required conditions
build / Build e2etest for windows_amd64 (push) Blocked by required conditions
build / Build e2etest for linux_arm (push) Blocked by required conditions
build / Build e2etest for darwin_arm64 (push) Blocked by required conditions
build / Build e2etest for linux_arm64 (push) Blocked by required conditions
build / Run e2e test for linux_386 (push) Blocked by required conditions
build / Run e2e test for windows_386 (push) Blocked by required conditions
build / Run e2e test for darwin_amd64 (push) Blocked by required conditions
build / Run e2e test for linux_amd64 (push) Blocked by required conditions
build / Run e2e test for windows_amd64 (push) Blocked by required conditions
build / Run e2e test for linux_arm (push) Blocked by required conditions
build / Run e2e test for linux_arm64 (push) Blocked by required conditions
build / Run terraform-exec test for linux amd64 (push) Blocked by required conditions
Quick Checks / Unit Tests (push) Waiting to run
Quick Checks / Race Tests (push) Waiting to run
Quick Checks / End-to-end Tests (push) Waiting to run
Quick Checks / Code Consistency Checks (push) Waiting to run
Quick Checks / Automated defect checks (push) Waiting to run
This PR makes a few related changes:
1. Construct provider cache Installers so they have knowledge about dev_override providers
Prior to this change, providercache.Installer variables were made in the command package with knowledge about reattached/unmanaged providers, but not with knowledge about dev_override providers. Now both sets of overridden providers are present in the installer and can affect installation logic.
2. Make the provider installation logic skip any dev_override providers from being installed from the Registry (or other configured sources)
This means that if a provider is first added to a config while someone uses a dev_override an init command will not add that provider to the lock file. If the overridden provider is already in the lock file then the lock will be unchanged. An edge case, that already exists for unmanaged providers, is that if a dev_override is in play while an init -upgrade command is used, only the providers that aren't overridden or unmanaged will be upgraded
This change is coupled to another change in the PR described below.
3. Fix the provider download process (in context of init) so that dev_overrides are not removed from the provider requirements.
This reverts a change in https://github.com/hashicorp/terraform/pull/37884. The original motivation of that PR was to address a situation where the provider supplied by dev_overrides isn't published to the Registry yet. The config may need to include an entry in required_providers for that provider, which means that init would always fail due to the provider being unavailable in the Registry for download. The prior commit (bfc08b5d96) changed installer logic to skip dev_override providers, which cancels out this commit's changes; dev_override providers will remain in the provider requirements passed to installation logic, but that logic will now ignore them. As a consequence of no longer removing these provider requirements we will retain any pre-existing locks for the provider through the init process.
4. The `providers locks` command will now warn users about any dev_overrides in effect, as these will stop provider locks from being downloaded.
This commit is contained in:
parent
81053e9d70
commit
234ef96aec
10 changed files with 107 additions and 61 deletions
5
.changes/v1.16/BUG FIXES-20260522-180848.yaml
Normal file
5
.changes/v1.16/BUG FIXES-20260522-180848.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
kind: BUG FIXES
|
||||
body: 'init: Stop removing locks from the dependency lock file corresponding to providers configured as a dev_override'
|
||||
time: 2026-05-22T18:08:48.823127+01:00
|
||||
custom:
|
||||
Issue: "38634"
|
||||
5
.changes/v1.16/NOTES-20260526-164738.yaml
Normal file
5
.changes/v1.16/NOTES-20260526-164738.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
kind: NOTES
|
||||
body: 'providers: The `providers locks` command will now warn users about any dev_overrides in effect, as these will stop provider locks from being downloaded.'
|
||||
time: 2026-05-26T16:47:38.947615+01:00
|
||||
custom:
|
||||
Issue: "38634"
|
||||
|
|
@ -23,9 +23,9 @@ import (
|
|||
)
|
||||
|
||||
// Test that users can do the full init-plan-apply workflow with pluggable state storage
|
||||
// when the state storage provider is reattached/unmanaged by Terraform.
|
||||
// when the state storage provider is unmanaged by Terraform.
|
||||
// As well as ensuring that the state store can be initialised ok, this tests that
|
||||
// the state store's details can be stored in the plan file despite the fact it's reattached.
|
||||
// the state store's details can be stored in the plan file despite the fact it's unmanaged.
|
||||
func TestPrimary_stateStore_unmanaged_separatePlan(t *testing.T) {
|
||||
if !canRunGoBuild {
|
||||
// We're running in a separate-build-then-run context, so we can't
|
||||
|
|
|
|||
|
|
@ -396,9 +396,9 @@ func TestPrimary_stateStore_swapProviderSupplyMode_betweenInitAndPlanApply(t *te
|
|||
// that change doesn't impact the hash of the state store. The hash is impacted by the Version data, and all unmanaged
|
||||
// providers used for PSS will have null version data.
|
||||
//
|
||||
// In contrast, swapping between a managed provider and any of reattached/dev_override/builtin WILL trigger a hash mismatch
|
||||
// In contrast, swapping between a managed provider and any of unmanaged/dev_override/builtin WILL trigger a hash mismatch
|
||||
// because the version data will change.
|
||||
t.Run("users are NOT prompted to migrate state if an unmanaged provider used for PSS provider swaps supply mode (e.g. swap from reattached to dev_override) between init and plan+apply", func(t *testing.T) {
|
||||
t.Run("users are NOT prompted to migrate state if an unmanaged provider used for PSS provider swaps supply mode (e.g. swap from unmanaged to dev_override) between init and plan+apply", func(t *testing.T) {
|
||||
if !canRunGoBuild {
|
||||
// We're running in a separate-build-then-run context, so we can't
|
||||
// currently execute this test which depends on being able to build
|
||||
|
|
@ -417,13 +417,13 @@ func TestPrimary_stateStore_swapProviderSupplyMode_betweenInitAndPlanApply(t *te
|
|||
reattachStr, _ := reattachedProviderForTest(t, addrs.NewDefaultProvider("simple6"), 6)
|
||||
tf.AddEnv("TF_REATTACH_PROVIDERS=" + string(reattachStr))
|
||||
|
||||
//// INIT - using reattached provider.
|
||||
//// INIT - using unmanaged provider.
|
||||
_, stderr, err := tf.Run("init", "-enable-pluggable-state-storage-experiment=true", "-no-color")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected init error: %s\nstderr:\n%s", err, stderr)
|
||||
}
|
||||
|
||||
// Assert backend state file says the provider is a reattached
|
||||
// Assert backend state file says the provider is unmanaged
|
||||
statePath := filepath.Join(tf.WorkDir(), ".terraform", command.DefaultStateFilename)
|
||||
sMgr := &clistate.LocalState{Path: statePath}
|
||||
if err := sMgr.RefreshState(); err != nil {
|
||||
|
|
@ -439,7 +439,7 @@ func TestPrimary_stateStore_swapProviderSupplyMode_betweenInitAndPlanApply(t *te
|
|||
|
||||
//// PLAN - using same provider but supplied via dev_override instead of reattach config.
|
||||
|
||||
// No longer using reattached providers.
|
||||
// No longer using unmanaged providers.
|
||||
tf.RemoveEnv("TF_REATTACH_PROVIDERS")
|
||||
|
||||
// Build the provider binary and direct Terraform to use it via dev_override, which should cause Terraform to treat it as a dev_override in a CLI configuration file.
|
||||
|
|
@ -683,9 +683,9 @@ func TestPrimary_stateStore_swapProviderSupplyMode_betweenSuccessiveInits(t *tes
|
|||
// that change doesn't impact the hash of the state store. The hash is impacted by the Version data, and all unmanaged
|
||||
// providers used for PSS will have null version data.
|
||||
//
|
||||
// In contrast, swapping between a managed provider and any of reattached/dev_override/builtin WILL trigger a hash mismatch
|
||||
// In contrast, swapping between a managed provider and any of unmanaged/dev_override/builtin WILL trigger a hash mismatch
|
||||
// because the version data will change.
|
||||
t.Run("users are NOT prompted to migrate state if an unmanaged provider used for PSS provider swaps supply mode (e.g. swap from reattached to dev_override) between init and plan+apply", func(t *testing.T) {
|
||||
t.Run("users are NOT prompted to migrate state if an unmanaged provider used for PSS provider swaps supply mode (e.g. swap from unmanaged to dev_override) between init and plan+apply", func(t *testing.T) {
|
||||
if !canRunGoBuild {
|
||||
// We're running in a separate-build-then-run context, so we can't
|
||||
// currently execute this test which depends on being able to build
|
||||
|
|
@ -704,13 +704,13 @@ func TestPrimary_stateStore_swapProviderSupplyMode_betweenSuccessiveInits(t *tes
|
|||
reattachStr, _ := reattachedProviderForTest(t, addrs.NewDefaultProvider("simple6"), 6)
|
||||
tf.AddEnv("TF_REATTACH_PROVIDERS=" + string(reattachStr))
|
||||
|
||||
//// INIT 1 - using reattached provider.
|
||||
//// INIT 1 - using unmanaged provider.
|
||||
_, stderr, err := tf.Run("init", "-enable-pluggable-state-storage-experiment=true", "-no-color")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected init error: %s\nstderr:\n%s", err, stderr)
|
||||
}
|
||||
|
||||
// Assert backend state file says the provider is a reattached
|
||||
// Assert backend state file says the provider is unmanaged
|
||||
statePath := filepath.Join(tf.WorkDir(), ".terraform", command.DefaultStateFilename)
|
||||
sMgr := &clistate.LocalState{Path: statePath}
|
||||
if err := sMgr.RefreshState(); err != nil {
|
||||
|
|
@ -726,7 +726,7 @@ func TestPrimary_stateStore_swapProviderSupplyMode_betweenSuccessiveInits(t *tes
|
|||
|
||||
//// INIT 2 - using same provider but supplied via dev_override instead of reattach config.
|
||||
|
||||
// No longer using reattached providers.
|
||||
// No longer using unmanaged providers.
|
||||
tf.RemoveEnv("TF_REATTACH_PROVIDERS")
|
||||
|
||||
// Build the provider binary and direct Terraform to use it via dev_override, which should cause Terraform to treat it as a dev_override in a CLI configuration file.
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ provider "registry.terraform.io/hashicorp/simple" {
|
|||
}
|
||||
})
|
||||
|
||||
t.Run("dev_override causes provider to be removed from dependency lock file during init", func(t *testing.T) {
|
||||
t.Run("dev_override providers are still represented in the dependency lock file after init", func(t *testing.T) {
|
||||
terraformBin := e2e.GoBuild("github.com/hashicorp/terraform", "terraform")
|
||||
tf := e2e.NewBinary(t, terraformBin, fixturePath)
|
||||
|
||||
|
|
@ -286,29 +286,18 @@ provider "registry.terraform.io/hashicorp/simple6" {
|
|||
t.Fatalf("unexpected error: %s\nstdout: %s\nstderr: %s", err, stdout, stderr)
|
||||
}
|
||||
|
||||
// Lockfile has been altered to remove the simple6 provider
|
||||
// Lockfile is unchanged despite use of a dev_override simple6 provider
|
||||
buf, err := os.ReadFile(lockFile)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error accessing lock file: %s", err)
|
||||
}
|
||||
buf = bytes.TrimSpace(buf)
|
||||
expectedLockFile := fmt.Sprintf(`# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/simple" {
|
||||
version = "1.0.0"
|
||||
hashes = [
|
||||
"%s",
|
||||
]
|
||||
}`,
|
||||
simple5v1_0_0Hash,
|
||||
)
|
||||
if diff := cmp.Diff(expectedLockFile, string(buf)); diff != "" {
|
||||
if diff := cmp.Diff(priorLockFile, string(buf)); diff != "" {
|
||||
t.Fatalf("unexpected difference in lock file content: %s", diff)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("dev_override also causes provider to be removed from dependency lock file during init -upgrade", func(t *testing.T) {
|
||||
t.Run("dev_override providers are unchanged in the dependency lock file during init -upgrade", func(t *testing.T) {
|
||||
terraformBin := e2e.GoBuild("github.com/hashicorp/terraform", "terraform")
|
||||
tf := e2e.NewBinary(t, terraformBin, fixturePath)
|
||||
|
||||
|
|
@ -363,8 +352,16 @@ provider "registry.terraform.io/hashicorp/simple" {
|
|||
hashes = [
|
||||
"%s",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/simple6" {
|
||||
version = "1.0.0"
|
||||
hashes = [
|
||||
"%s",
|
||||
]
|
||||
}`,
|
||||
simple5v2_0_0Hash,
|
||||
simple6v1_0_0Hash, // not upgraded to 2.0.0
|
||||
)
|
||||
if diff := cmp.Diff(expectedLockFileContent, string(buf)); diff != "" {
|
||||
t.Errorf("unexpected difference in lock file content: %s", diff)
|
||||
|
|
@ -372,9 +369,9 @@ provider "registry.terraform.io/hashicorp/simple" {
|
|||
})
|
||||
}
|
||||
|
||||
// TestProviderInstall_reattached verifies provider plugin installation behaviour
|
||||
// when a reattached/unmanaged provider is in use.
|
||||
func TestProviderInstall_reattached(t *testing.T) {
|
||||
// TestProviderInstall_unmanaged verifies provider plugin installation behaviour
|
||||
// when an unmanaged provider is in use.
|
||||
func TestProviderInstall_unmanaged(t *testing.T) {
|
||||
if !canRunGoBuild {
|
||||
// We're running in a separate-build-then-run context, so we can't
|
||||
// currently execute this test which depends on being able to build
|
||||
|
|
@ -448,11 +445,11 @@ func TestProviderInstall_reattached(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Launch a separate simple6 provider process to be re-used as a reattached provider.
|
||||
// Launch a separate simple6 provider process to be re-used as an unmanaged provider.
|
||||
// Tests will use this via the TF_REATTACH_PROVIDERS environment variable.
|
||||
reattachConfig, _ := reattachedProviderForTest(t, addrs.NewDefaultProvider("simple6"), 6)
|
||||
|
||||
t.Run("reattached provider not installed when provider not present in dependency lock file", func(t *testing.T) {
|
||||
t.Run("unmanaged provider not installed when provider not present in dependency lock file", func(t *testing.T) {
|
||||
terraformBin := e2e.GoBuild("github.com/hashicorp/terraform", "terraform")
|
||||
tf := e2e.NewBinary(t, terraformBin, fixturePath)
|
||||
|
||||
|
|
@ -466,7 +463,7 @@ func TestProviderInstall_reattached(t *testing.T) {
|
|||
t.Fatalf("expected error due to file not existing, got different error: %s", err)
|
||||
}
|
||||
|
||||
// The simple6 provider is reattached/unmanaged
|
||||
// The simple6 provider is unmanaged
|
||||
tf.AddEnv("TF_REATTACH_PROVIDERS=" + reattachConfig)
|
||||
|
||||
// The init process should succeed.
|
||||
|
|
@ -482,7 +479,7 @@ func TestProviderInstall_reattached(t *testing.T) {
|
|||
}
|
||||
buf = bytes.TrimSpace(buf)
|
||||
|
||||
// We expect the lock file to not contain the simple6 provider that's being reattached/unmanaged,
|
||||
// We expect the lock file to not contain the simple6 provider that's being unmanaged,
|
||||
// because that provider is skipped during the installation process.
|
||||
// The simple (v5) provider is installed as usual, pulling in the latest version.
|
||||
expectedLockFileContent := fmt.Sprintf(`# This file is maintained automatically by "terraform init".
|
||||
|
|
@ -500,7 +497,7 @@ provider "registry.terraform.io/hashicorp/simple" {
|
|||
}
|
||||
})
|
||||
|
||||
t.Run("reattached providers do NOT cause provider to be removed from dependency lock file during init", func(t *testing.T) {
|
||||
t.Run("unmanaged providers are still represented in the dependency lock file after init", func(t *testing.T) {
|
||||
terraformBin := e2e.GoBuild("github.com/hashicorp/terraform", "terraform")
|
||||
tf := e2e.NewBinary(t, terraformBin, fixturePath)
|
||||
|
||||
|
|
@ -529,7 +526,7 @@ provider "registry.terraform.io/hashicorp/simple6" {
|
|||
t.Fatalf("error writing prior lock file: %s", err)
|
||||
}
|
||||
|
||||
// The simple6 provider is reattached/unmanaged
|
||||
// The simple6 provider is unmanaged
|
||||
tf.AddEnv("TF_REATTACH_PROVIDERS=" + reattachConfig)
|
||||
|
||||
// The init process should succeed.
|
||||
|
|
@ -538,7 +535,7 @@ provider "registry.terraform.io/hashicorp/simple6" {
|
|||
t.Fatalf("unexpected error: %s\nstdout: %s\nstderr: %s", err, stdout, stderr)
|
||||
}
|
||||
|
||||
// Lockfile is unchanged despite use of a reattached/unmanaged simple6 provider
|
||||
// Lockfile is unchanged despite use of an unmanaged simple6 provider
|
||||
buf, err := os.ReadFile(lockFile)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error accessing lock file: %s", err)
|
||||
|
|
@ -549,7 +546,7 @@ provider "registry.terraform.io/hashicorp/simple6" {
|
|||
}
|
||||
})
|
||||
|
||||
t.Run("reattached providers are unchanged in the dependency lock file during init -upgrade", func(t *testing.T) {
|
||||
t.Run("unmanaged providers are unchanged in the dependency lock file during init -upgrade", func(t *testing.T) {
|
||||
terraformBin := e2e.GoBuild("github.com/hashicorp/terraform", "terraform")
|
||||
tf := e2e.NewBinary(t, terraformBin, fixturePath)
|
||||
|
||||
|
|
@ -578,7 +575,7 @@ provider "registry.terraform.io/hashicorp/simple6" {
|
|||
t.Fatalf("error writing prior lock file: %s", err)
|
||||
}
|
||||
|
||||
// The simple6 provider is reattached/unmanaged
|
||||
// The simple6 provider is unmanaged
|
||||
tf.AddEnv("TF_REATTACH_PROVIDERS=" + reattachConfig)
|
||||
|
||||
// The init -upgrade process should succeed.
|
||||
|
|
@ -589,7 +586,7 @@ provider "registry.terraform.io/hashicorp/simple6" {
|
|||
|
||||
// Lockfile shows evidence of upgrade process
|
||||
// simple provider is upgraded to the newer 2.0.0 version,
|
||||
// but the reattached simple6 provider is unchanged due to being reattached.
|
||||
// but the unmanaged simple6 provider is unchanged due to being unmanaged.
|
||||
buf, err := os.ReadFile(lockFile)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error accessing lock file: %s", err)
|
||||
|
|
@ -613,7 +610,7 @@ provider "registry.terraform.io/hashicorp/simple6" {
|
|||
]
|
||||
}`,
|
||||
simple5v2_0_0Hash,
|
||||
simple6v1_0_0Hash,
|
||||
simple6v1_0_0Hash, // not upgraded to 2.0.0
|
||||
)
|
||||
if diff := cmp.Diff(expectedLockFileContent, string(buf)); diff != "" {
|
||||
t.Errorf("unexpected difference in lock file content: %s", diff)
|
||||
|
|
@ -621,7 +618,7 @@ provider "registry.terraform.io/hashicorp/simple6" {
|
|||
})
|
||||
}
|
||||
|
||||
// reattachedProviderForTest launches a provider process and returns a reattach config string
|
||||
// reattachConfigForTest launches a provider process and returns a reattach config string
|
||||
// that can be used as the value for the TF_REATTACH_PROVIDERS environment variable in tests.
|
||||
// Cleanup of the provider process is handled internally.
|
||||
func reattachedProviderForTest(t *testing.T, provider addrs.Provider, protocol int) (string, *providerServer) {
|
||||
|
|
|
|||
|
|
@ -401,8 +401,6 @@ func (c *InitCommand) getProvidersFromConfig(ctx context.Context, config *config
|
|||
return false, nil, SafeInitActionInvalid, nil, diags
|
||||
}
|
||||
|
||||
reqs = c.removeDevOverrides(reqs)
|
||||
|
||||
for providerAddr := range reqs {
|
||||
if providerAddr.IsLegacy() {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import (
|
|||
builtinProviders "github.com/hashicorp/terraform/internal/builtin/providers"
|
||||
"github.com/hashicorp/terraform/internal/depsfile"
|
||||
"github.com/hashicorp/terraform/internal/getproviders"
|
||||
"github.com/hashicorp/terraform/internal/getproviders/providerreqs"
|
||||
"github.com/hashicorp/terraform/internal/logging"
|
||||
tfplugin "github.com/hashicorp/terraform/internal/plugin"
|
||||
tfplugin6 "github.com/hashicorp/terraform/internal/plugin6"
|
||||
|
|
@ -74,11 +73,21 @@ func (m *Meta) providerInstallerCustomSource(source getproviders.Source) *provid
|
|||
builtinProviderTypes = append(builtinProviderTypes, ty)
|
||||
}
|
||||
inst.SetBuiltInProviderTypes(builtinProviderTypes)
|
||||
|
||||
// Overridden providers consist of both:
|
||||
// 1. reattached providers
|
||||
// 2. development override providers
|
||||
unmanagedProviderTypes := make(map[addrs.Provider]struct{}, len(m.UnmanagedProviders))
|
||||
for ty := range m.UnmanagedProviders {
|
||||
unmanagedProviderTypes[ty] = struct{}{}
|
||||
}
|
||||
inst.SetUnmanagedProviderTypes(unmanagedProviderTypes)
|
||||
devOverrideProviderTypes := make(map[addrs.Provider]struct{}, len(m.ProviderDevOverrides))
|
||||
for ty := range m.ProviderDevOverrides {
|
||||
devOverrideProviderTypes[ty] = struct{}{}
|
||||
}
|
||||
inst.SetDevOverrideTypes(devOverrideProviderTypes)
|
||||
|
||||
return inst
|
||||
}
|
||||
|
||||
|
|
@ -187,6 +196,29 @@ func (m *Meta) providerDevOverrideInitWarnings() tfdiags.Diagnostics {
|
|||
}
|
||||
}
|
||||
|
||||
// providerDevOverrideProviderLockWarnings is just like providerDevOverrideInitWarnings
|
||||
// except the diagnostic is written with a message specific to the `providers lock` command.
|
||||
// Similarly, diags will only be returned if there is 1+ dev_overrides in effect, and no error
|
||||
// diags will be returned.
|
||||
func (m *Meta) providerDevOverrideProvidersLockWarnings() tfdiags.Diagnostics {
|
||||
if len(m.ProviderDevOverrides) == 0 {
|
||||
return nil
|
||||
}
|
||||
var detailMsg strings.Builder
|
||||
detailMsg.WriteString("The following provider development overrides are set in the CLI configuration:\n")
|
||||
for addr, path := range m.ProviderDevOverrides {
|
||||
detailMsg.WriteString(fmt.Sprintf(" - %s in %s\n", addr.ForDisplay(), path))
|
||||
}
|
||||
detailMsg.WriteString("\nThese provider locks will not be recorded because the provider is overwritten. If this is unintentional please re-run without the development overrides set.")
|
||||
return tfdiags.Diagnostics{
|
||||
tfdiags.Sourceless(
|
||||
tfdiags.Warning,
|
||||
"Provider development overrides are in effect",
|
||||
detailMsg.String(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Meta) isProviderDevOverride(pAddr addrs.Provider) bool {
|
||||
if len(m.ProviderDevOverrides) == 0 {
|
||||
return false
|
||||
|
|
@ -195,21 +227,6 @@ func (m *Meta) isProviderDevOverride(pAddr addrs.Provider) bool {
|
|||
return overridden
|
||||
}
|
||||
|
||||
func (m *Meta) removeDevOverrides(reqs providerreqs.Requirements) providerreqs.Requirements {
|
||||
// Deep copy the requirements to avoid mutating the input
|
||||
copiedReqs := make(providerreqs.Requirements)
|
||||
for provider, versions := range reqs {
|
||||
// Only copy if the provider is not overridden
|
||||
if _, overridden := m.ProviderDevOverrides[provider]; !overridden {
|
||||
copiedVersions := make(providerreqs.VersionConstraints, len(versions))
|
||||
copy(copiedVersions, versions)
|
||||
copiedReqs[provider] = copiedVersions
|
||||
}
|
||||
}
|
||||
|
||||
return copiedReqs
|
||||
}
|
||||
|
||||
// providerDevOverrideRuntimeWarnings returns a diagnostics that contains at
|
||||
// least one warning if and only if there is at least one provider development
|
||||
// override in effect. If not, the result is always empty. The result never
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ func TestEnsureProviderVersions_devOverrideAndReattachedProviders(t *testing.T)
|
|||
providerA.ForDisplay(),
|
||||
providerB.ForDisplay(),
|
||||
providerC.ForDisplay(),
|
||||
providerD.ForDisplay(), // D is installed despite being dev overridden
|
||||
// D is not installed due to being dev override
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -195,6 +195,11 @@ func (c *ProvidersLockCommand) Run(args []string) int {
|
|||
// merge all of the generated locks together at the end.
|
||||
updatedLocks := map[getproviders.Platform]*depsfile.Locks{}
|
||||
selectedVersions := map[addrs.Provider]getproviders.Version{}
|
||||
|
||||
// Warn users about any development overrides in effect; they will block
|
||||
// locks being obtained for the overridden providers.
|
||||
c.showDiagnostics(c.providerDevOverrideProvidersLockWarnings())
|
||||
|
||||
for _, platform := range platforms {
|
||||
tempDir, err := ioutil.TempDir("", "terraform-providers-lock")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,12 @@ type Installer struct {
|
|||
// lifecycle for, and therefore does not need to worry about the
|
||||
// installation of.
|
||||
unmanagedProviderTypes map[addrs.Provider]struct{}
|
||||
|
||||
// devOverrideTypes is a set of provider addresses that should be
|
||||
// considered implemented. Binaries of these providers are supplied
|
||||
// from the users machine via CLI configuration, so Terraform does
|
||||
// not need to worry about installing them.
|
||||
devOverrideTypes map[addrs.Provider]struct{}
|
||||
}
|
||||
|
||||
// NewInstaller constructs and returns a new installer with the given target
|
||||
|
|
@ -161,6 +167,15 @@ func (i *Installer) SetUnmanagedProviderTypes(types map[addrs.Provider]struct{})
|
|||
i.unmanagedProviderTypes = types
|
||||
}
|
||||
|
||||
// SetDevOverrideTypes tells the receiver to consider the providers
|
||||
// indicated by the passed addrs.Providers as dev overrides. Terraform should not
|
||||
// try to install these providers and record their versions in the dependency lock
|
||||
// file; the binaries supplied via CLI configuration have no version information
|
||||
// available.
|
||||
func (i *Installer) SetDevOverrideTypes(types map[addrs.Provider]struct{}) {
|
||||
i.devOverrideTypes = types
|
||||
}
|
||||
|
||||
// EnsureProviderVersions compares the given provider requirements with what
|
||||
// is already available in the installer's target directory and then takes
|
||||
// appropriate installation actions to ensure that suitable packages
|
||||
|
|
@ -237,6 +252,10 @@ func (i *Installer) EnsureProviderVersions(ctx context.Context, locks *depsfile.
|
|||
// unmanaged providers do not require installation
|
||||
continue
|
||||
}
|
||||
if _, ok := i.devOverrideTypes[provider]; ok {
|
||||
// development override providers do not require installation
|
||||
continue
|
||||
}
|
||||
acceptableVersions := versions.MeetingConstraints(versionConstraints)
|
||||
if !mode.forceQueryAllProviders() {
|
||||
// If we're not forcing potential changes of version then an
|
||||
|
|
|
|||
Loading…
Reference in a new issue