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.
This commit is contained in:
Martin Atkins 2019-11-20 16:53:56 -08:00
parent 1ae47ae314
commit 7cf782c1bf
2 changed files with 47 additions and 0 deletions

View File

@ -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)

View File

@ -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