the destroy plan should use correct type

When we plan to destroy an instance, the change recorded should use the
correct type for the resource rather than `DynamicPseudoType`. Most of
the time this is hidden when the change is encoded in the plan, because
any `null` is always encoded to the same value, and when decoded it will
be converted to the schema type. However when apply requires creating a
second plan for an instance's replacement that value is not going to be
encoded, and remains a dynamic value which is sent to the provider.

Most providers won't see that either, as the grpc request also encodes
and decodes the value to conform with the correct schema. The builtin
terraform provider does get the raw cty value though, and when that
dynamic value is returned validation fails when the type does not match.
This commit is contained in:
James Bardin 2023-04-05 10:19:26 -04:00
parent 84dc498b90
commit c872cd6d96
2 changed files with 3 additions and 15 deletions

View File

@ -440,7 +440,7 @@ func (n *NodeAbstractResourceInstance) planDestroy(ctx EvalContext, currentState
Change: plans.Change{
Action: plans.Delete,
Before: currentState.Value,
After: cty.NullVal(cty.DynamicPseudoType),
After: nullVal,
},
Private: resp.PlannedPrivate,
ProviderAddr: n.ResolvedProvider,

View File

@ -435,28 +435,16 @@ func (p *MockProvider) ApplyResourceChange(r providers.ApplyResourceChangeReques
return *p.ApplyResourceChangeResponse
}
schema, ok := p.getProviderSchema().ResourceTypes[r.TypeName]
if !ok {
resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("no schema found for %q", r.TypeName))
return resp
}
// if the value is nil, we return that directly to correspond to a delete
if r.PlannedState.IsNull() {
resp.NewState = cty.NullVal(schema.Block.ImpliedType())
return resp
}
val, err := schema.Block.CoerceValue(r.PlannedState)
if err != nil {
resp.Diagnostics = resp.Diagnostics.Append(err)
resp.NewState = r.PlannedState
return resp
}
// the default behavior will be to create the minimal valid apply value by
// setting unknowns (which correspond to computed attributes) to a zero
// value.
val, _ = cty.Transform(val, func(path cty.Path, v cty.Value) (cty.Value, error) {
val, _ := cty.Transform(r.PlannedState, func(path cty.Path, v cty.Value) (cty.Value, error) {
if !v.IsKnown() {
ty := v.Type()
switch {