re-apply ignore_changes after plan for legacy
Because we allow legacy providers to depart from the contract and return changes to non-computed values, the plan response may have altered values that were already suppressed with ignore_changes. A prime example of this is where providers attempt to obfuscate config data by turning the config value into a hash and storing the hash value in the state. There are enough cases of this in existing providers that we must accommodate the behavior for now, so for ignore_changes to work at all on these values, we will revert the ignored values once more on the planned state.
This commit is contained in:
parent
aa5c8add2e
commit
02e7efab9e
|
@ -6473,3 +6473,69 @@ resource "test_instance" "a" {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_changes needs to be re-applied to the planned value for provider
|
||||
// using the LegacyTypeSystem
|
||||
func TestContext2Plan_legacyProviderIgnoreChanges(t *testing.T) {
|
||||
m := testModuleInline(t, map[string]string{
|
||||
"main.tf": `
|
||||
resource "test_instance" "a" {
|
||||
lifecycle {
|
||||
ignore_changes = [data]
|
||||
}
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
||||
p := testProvider("test")
|
||||
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
|
||||
m := req.ProposedNewState.AsValueMap()
|
||||
// this provider "hashes" the data attribute as bar
|
||||
m["data"] = cty.StringVal("bar")
|
||||
|
||||
resp.PlannedState = cty.ObjectVal(m)
|
||||
resp.LegacyTypeSystem = true
|
||||
return resp
|
||||
}
|
||||
|
||||
p.GetSchemaReturn = &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"test_instance": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Computed: true},
|
||||
"data": {Type: cty.String, Optional: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
state := states.NewState()
|
||||
root := state.EnsureModule(addrs.RootModuleInstance)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_instance.a").Resource,
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"id":"a","data":"foo"}`),
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`),
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Config: m,
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
State: state,
|
||||
})
|
||||
plan, diags := ctx.Plan()
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
for _, c := range plan.Changes.Resources {
|
||||
if c.Action != plans.NoOp {
|
||||
t.Fatalf("expected no changes, got %s for %q", c.Action, c.Addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -322,6 +322,23 @@ func (n *EvalDiff) Eval(ctx EvalContext) tfdiags.Diagnostics {
|
|||
}
|
||||
}
|
||||
|
||||
if resp.LegacyTypeSystem {
|
||||
// Because we allow legacy providers to depart from the contract and
|
||||
// return changes to non-computed values, the plan response may have
|
||||
// altered values that were already suppressed with ignore_changes.
|
||||
// A prime example of this is where providers attempt to obfuscate
|
||||
// config data by turning the config value into a hash and storing the
|
||||
// hash value in the state. There are enough cases of this in existing
|
||||
// providers that we must accommodate the behavior for now, so for
|
||||
// ignore_changes to work at all on these values, we will revert the
|
||||
// ignored values once more.
|
||||
plannedNewVal, ignoreChangeDiags = n.processIgnoreChanges(unmarkedPriorVal, plannedNewVal)
|
||||
diags = diags.Append(ignoreChangeDiags)
|
||||
if ignoreChangeDiags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
}
|
||||
|
||||
// Add the marks back to the planned new value -- this must happen after ignore changes
|
||||
// have been processed
|
||||
unmarkedPlannedNewVal := plannedNewVal
|
||||
|
|
Loading…
Reference in New Issue