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.
This commit is contained in:
Martin Atkins 2019-05-10 09:25:02 -07:00 committed by James Bardin
parent abdd680fd2
commit bcf2aa06dd
1 changed files with 7 additions and 16 deletions

View File

@ -19,26 +19,13 @@ import (
// If any errors occur during upgrade, error diagnostics are returned. In that // 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. // 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) { 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 { if addr.Resource.Resource.Mode != addrs.ManagedResourceMode {
// We only do state upgrading for managed resources. // We only do state upgrading for managed resources.
return src, nil return src, nil
} }
stateIsFlatmap := len(src.AttrsJSON) == 0
providerType := addr.Resource.Resource.DefaultProviderConfig().Type providerType := addr.Resource.Resource.DefaultProviderConfig().Type
if src.SchemaVersion > currentVersion { if src.SchemaVersion > currentVersion {
log.Printf("[TRACE] UpgradeResourceState: can't downgrade state for %s from version %d to %d", addr, 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 // v0.12, this also includes translating from legacy flatmap to new-style
// representation, since only the provider has enough information to // representation, since only the provider has enough information to
// understand a flatmap built against an older schema. // 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{ req := providers.UpgradeResourceStateRequest{
TypeName: addr.Resource.Resource.Type, TypeName: addr.Resource.Resource.Type,