From 7cf782c1bf99368d32a24a6efba7cbd7c94724ad Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Wed, 20 Nov 2019 16:53:56 -0800 Subject: [PATCH] states/statefile: Better error messages for some unsupported v3 cases There are a few situations that we've seen arise quite commonly for folks upgrading from Terraform 0.11 to 0.12. These particular problems are not things that Terraform 0.12 can fix automatically during upgrading, but we can at least give some better feedback to users that they ought to be addressed _before_ upgrading. The provider address problem is already detected and flagged by the "terraform 0.11checklist" command that folks should run as part of their upgrade process, but the module address problem is not something we noticed was lacking validation in 0.11 and so the checklist tool doesn't cover it. Due to the lack of coverage in the checklist tool, this commit also includes an additional section in the upgrade guide that mentions the problem and gives instructions on how to address it. --- states/statefile/version3_upgrade.go | 22 ++++++++++++++++++++ website/upgrade-guides/0-12.html.markdown | 25 +++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/states/statefile/version3_upgrade.go b/states/statefile/version3_upgrade.go index 64c3c1afb..753298ff0 100644 --- a/states/statefile/version3_upgrade.go +++ b/states/statefile/version3_upgrade.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" + "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/zclconf/go-cty/cty" ctyjson "github.com/zclconf/go-cty/cty/json" @@ -51,6 +52,13 @@ func upgradeStateV3ToV4(old *stateV3) (*stateV4, error) { // all of the modules are unkeyed. moduleAddr := make(addrs.ModuleInstance, len(msOld.Path)-1) for i, name := range msOld.Path[1:] { + if !hclsyntax.ValidIdentifier(name) { + // If we don't fail here then we'll produce an invalid state + // version 4 which subsequent operations will reject, so we'll + // fail early here for safety to make sure we can never + // inadvertently commit an invalid snapshot to a backend. + return nil, fmt.Errorf("state contains invalid module path %#v: %q is not a valid identifier; rename it in Terraform 0.11 before upgrading to Terraform 0.12", msOld.Path, name) + } moduleAddr[i] = addrs.ModuleInstanceStep{ Name: name, InstanceKey: addrs.NoKey, @@ -99,6 +107,13 @@ func upgradeStateV3ToV4(old *stateV3) (*stateV4, error) { var diags tfdiags.Diagnostics providerAddr, diags = addrs.ParseAbsProviderConfigStr(oldProviderAddr) if diags.HasErrors() { + if strings.Contains(oldProviderAddr, "${") { + // There seems to be a common misconception that + // interpolation was valid in provider aliases + // in 0.11, so we'll use a specialized error + // message for that case. + return nil, fmt.Errorf("invalid provider config reference %q for %s: this alias seems to contain a template interpolation sequence, which was not supported but also not error-checked in Terraform 0.11. To proceed, rename the associated provider alias to a valid identifier and apply the change with Terraform 0.11 before upgrading to Terraform 0.12", oldProviderAddr, instAddr) + } return nil, fmt.Errorf("invalid provider config reference %q for %s: %s", oldProviderAddr, instAddr, diags.Err()) } } else { @@ -110,6 +125,13 @@ func upgradeStateV3ToV4(old *stateV3) (*stateV4, error) { if oldProviderAddr != "" { localAddr, diags := addrs.ParseProviderConfigCompactStr(oldProviderAddr) if diags.HasErrors() { + if strings.Contains(oldProviderAddr, "${") { + // There seems to be a common misconception that + // interpolation was valid in provider aliases + // in 0.11, so we'll use a specialized error + // message for that case. + return nil, fmt.Errorf("invalid legacy provider config reference %q for %s: this alias seems to contain a template interpolation sequence, which was not supported but also not error-checked in Terraform 0.11. To proceed, rename the associated provider alias to a valid identifier and apply the change with Terraform 0.11 before upgrading to Terraform 0.12", oldProviderAddr, instAddr) + } return nil, fmt.Errorf("invalid legacy provider config reference %q for %s: %s", oldProviderAddr, instAddr, diags.Err()) } providerAddr = localAddr.Absolute(moduleAddr) diff --git a/website/upgrade-guides/0-12.html.markdown b/website/upgrade-guides/0-12.html.markdown index d5a3c432b..b4e9ca741 100644 --- a/website/upgrade-guides/0-12.html.markdown +++ b/website/upgrade-guides/0-12.html.markdown @@ -106,6 +106,31 @@ After all of the tasks are complete, run `terraform 0.12checklist` one more time to verify that everything is complete. If so, continue reading the following sections to complete the upgrade! +### Addendum: Invalid module names + +There is one additional pre-upgrade checklist item that the Terraform team did +not become aware of until after the release of Terraform v0.11.14, and thus +cannot be detected automatically by the checklist tool: renaming modules which +have names that start with digits. + +Terraform 0.11 inadvertently tolerated leading-digit names for modules as a +result of a validation bug, but Terraform 0.12 has corrected that bug and will +reject such module names. Unfortunately, module names are also recorded in +state snapshots and so a state snapshot created for a configuration with an +invalid module name will itself be invalid as far as Terraform 0.12 is +concerned. + +You can address this in a similar way to what the checklist tool suggests for +invalid resource names and provider aliases: + +* Rename the module in your configuration. +* Use `terraform state mv module.old module.new` _in Terraform 0.11.14_ to + update the state to use the new name instead of the old name. + +As with all of the pre-upgrade checklist items, be sure to run `terraform apply` +once more before upgrading in order to ensure that the latest state snapshot is +synchronized with the latest configuration. + ## Upgrading to Terraform 0.12 Before switching to Terraform 0.12, we recommend using Terraform v0.11.14 (or