github.com/opentofu/opentofu@v1.7.1/internal/tofumigrate/tofumigrate.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package tofumigrate 7 8 import ( 9 "os" 10 11 "github.com/hashicorp/hcl/v2" 12 tfaddr "github.com/opentofu/registry-address" 13 14 "github.com/opentofu/opentofu/internal/configs" 15 "github.com/opentofu/opentofu/internal/getproviders" 16 "github.com/opentofu/opentofu/internal/states" 17 "github.com/opentofu/opentofu/internal/tfdiags" 18 ) 19 20 // MigrateStateProviderAddresses can be used to update the in-memory view of the state to use registry.opentofu.org 21 // provider addresses. This only applies for providers which are *not* explicitly referenced in the configuration in full form. 22 // For example, if the configuration contains a provider block like this: 23 // 24 // terraform { 25 // required_providers { 26 // random = {} 27 // } 28 // } 29 // 30 // we will migrate the in-memory view of the statefile to use registry.opentofu.org/hashicorp/random. 31 // However, if the configuration contains a provider block like this: 32 // 33 // terraform { 34 // required_providers { 35 // random = { 36 // source = "registry.terraform.io/hashicorp/random" 37 // } 38 // } 39 // } 40 // 41 // then we keep the old address. 42 func MigrateStateProviderAddresses(config *configs.Config, state *states.State) (*states.State, tfdiags.Diagnostics) { 43 if os.Getenv("OPENTOFU_STATEFILE_PROVIDER_ADDRESS_TRANSLATION") == "0" { 44 return state, nil 45 } 46 47 if state == nil { 48 return nil, nil 49 } 50 51 var diags tfdiags.Diagnostics 52 53 stateCopy := state.DeepCopy() 54 55 providers := getproviders.Requirements{} 56 // config could be nil when we're e.g. showing a statefile without the configuration present 57 if config != nil { 58 var hclDiags hcl.Diagnostics 59 providers, hclDiags = config.ProviderRequirements() 60 diags = diags.Append(hclDiags) 61 if hclDiags.HasErrors() { 62 return nil, diags 63 } 64 } 65 66 for _, module := range stateCopy.Modules { 67 for _, resource := range module.Resources { 68 _, referencedInConfig := providers[resource.ProviderConfig.Provider] 69 if resource.ProviderConfig.Provider.Hostname == "registry.terraform.io" && !referencedInConfig { 70 resource.ProviderConfig.Provider.Hostname = tfaddr.DefaultProviderRegistryHost 71 } 72 } 73 } 74 75 return stateCopy, diags 76 }