From bcf2aa06dddf463fc3f3a4f18d6ea13a362e65c4 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Fri, 10 May 2019 09:25:02 -0700 Subject: [PATCH] core: Call providers' UpgradeResourceState every time Previously we tried to short-circuit this if the schema version hadn't changed and we were already using JSON serialization. However, if we instead call into UpgradeResourceState every time we can let the provider or the SDK do some general, systematic normalization and cleanup steps without always requiring a schema version increase. What exactly would be fixed up this way is for the SDK to decide, but for example the SDK might choose to automatically delete from the state anything that is no longer present in the schema, avoiding the need to write explicit state migration functions for that common case where the remedy is always the same. The actual update logic is delegated to the provider/SDK intentionally so that it can evolve over time and potentially differ depending on how each SDK thinks about schema. --- terraform/eval_state_upgrade.go | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/terraform/eval_state_upgrade.go b/terraform/eval_state_upgrade.go index b7720d71b..e1940005e 100644 --- a/terraform/eval_state_upgrade.go +++ b/terraform/eval_state_upgrade.go @@ -19,26 +19,13 @@ import ( // If any errors occur during upgrade, error diagnostics are returned. In that // case it is not safe to proceed with using the original state object. func UpgradeResourceState(addr addrs.AbsResourceInstance, provider providers.Interface, src *states.ResourceInstanceObjectSrc, currentSchema *configschema.Block, currentVersion uint64) (*states.ResourceInstanceObjectSrc, tfdiags.Diagnostics) { - currentTy := currentSchema.ImpliedType() - - // If the state is currently in flatmap format and the current schema - // contains DynamicPseudoType attributes then we won't be able to convert - // it to JSON without the provider's help even if the schema version matches, - // since only the provider knows how to interpret the dynamic attribute - // value in flatmap format to convert it to JSON. - schemaHasDynamic := currentTy.HasDynamicTypes() - stateIsFlatmap := len(src.AttrsJSON) == 0 - forceProviderUpgrade := schemaHasDynamic && stateIsFlatmap - - if src.SchemaVersion == currentVersion && !forceProviderUpgrade { - // No upgrading required, then. - return src, nil - } if addr.Resource.Resource.Mode != addrs.ManagedResourceMode { // We only do state upgrading for managed resources. return src, nil } + stateIsFlatmap := len(src.AttrsJSON) == 0 + providerType := addr.Resource.Resource.DefaultProviderConfig().Type if src.SchemaVersion > currentVersion { log.Printf("[TRACE] UpgradeResourceState: can't downgrade state for %s from version %d to %d", addr, src.SchemaVersion, currentVersion) @@ -60,7 +47,11 @@ func UpgradeResourceState(addr addrs.AbsResourceInstance, provider providers.Int // v0.12, this also includes translating from legacy flatmap to new-style // representation, since only the provider has enough information to // understand a flatmap built against an older schema. - log.Printf("[TRACE] UpgradeResourceState: upgrading state for %s from version %d to %d using provider %q", addr, src.SchemaVersion, currentVersion, providerType) + if src.SchemaVersion != currentVersion { + log.Printf("[TRACE] UpgradeResourceState: upgrading state for %s from version %d to %d using provider %q", addr, src.SchemaVersion, currentVersion, providerType) + } else { + log.Printf("[TRACE] UpgradeResourceState: schema version of %s is still %d; calling provider %q for any other minor fixups", addr, currentVersion, providerType) + } req := providers.UpgradeResourceStateRequest{ TypeName: addr.Resource.Resource.Type,