core: Upgrade flatmap to JSON when dynamic attributes are present

When a resource type schema includes dynamically-typed attributes we can't
do any automatic conversion from flatmap to JSON because we don't know
how to interpret the keys that start with the dynamically-typed
attribute's prefix.

To work around that, we'll instead just ask the SDK to do a no-op upgrade
(current and target versions are the same) which will convert from flatmap
to JSON using the SDK's own logic as a side-effect.

This situation should rarely arise in real-world use, but it ends up being
very important for the helper/resource provider test harness because it
is forced to lower the state back to flatmap repeatedly after every step
in order to run legacy checking and processing code.
pull/20786/head
Martin Atkins 7 years ago
parent 135121562e
commit 2a64a00983

@ -19,7 +19,18 @@ 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) {
if src.SchemaVersion == currentVersion {
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
}
@ -62,10 +73,10 @@ func UpgradeResourceState(addr addrs.AbsResourceInstance, provider providers.Int
Version: int64(src.SchemaVersion),
}
if len(src.AttrsJSON) != 0 {
req.RawStateJSON = src.AttrsJSON
} else {
if stateIsFlatmap {
req.RawStateFlatmap = src.AttrsFlat
} else {
req.RawStateJSON = src.AttrsJSON
}
resp := provider.UpgradeResourceState(req)

Loading…
Cancel
Save