Skip to content

Commit

Permalink
Merge pull request #31747 from hashicorp/jbardin/ignore-changes-all-c…
Browse files Browse the repository at this point in the history
…omputed

filter computed attrs from `ignore_changes=all`
  • Loading branch information
jbardin committed Sep 28, 2022
2 parents a29fefb + 3e281e1 commit 8c98e1f
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 6 deletions.
17 changes: 15 additions & 2 deletions internal/terraform/context_plan_test.go
Expand Up @@ -4536,15 +4536,28 @@ func TestContext2Plan_ignoreChanges(t *testing.T) {
func TestContext2Plan_ignoreChangesWildcard(t *testing.T) {
m := testModule(t, "plan-ignore-changes-wildcard")
p := testProvider("aws")
p.PlanResourceChangeFn = testDiffFn
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
// computed attributes should not be set in config
id := req.Config.GetAttr("id")
if !id.IsNull() {
t.Error("computed id set in plan config")
}

foo := req.Config.GetAttr("foo")
if foo.IsNull() {
t.Error(`missing "foo" during plan, was set to "bar" in state and config`)
}

return testDiffFn(req)
}

state := states.NewState()
root := state.EnsureModule(addrs.RootModuleInstance)
root.SetResourceInstanceCurrent(
mustResourceInstanceAddr("aws_instance.foo").Resource,
&states.ResourceInstanceObjectSrc{
Status: states.ObjectReady,
AttrsJSON: []byte(`{"id":"bar","ami":"ami-abcd1234","instance":"t2.micro","type":"aws_instance"}`),
AttrsJSON: []byte(`{"id":"bar","ami":"ami-abcd1234","instance":"t2.micro","type":"aws_instance","foo":"bar"}`),
},
mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`),
)
Expand Down
22 changes: 18 additions & 4 deletions internal/terraform/node_resource_abstract_instance.go
Expand Up @@ -777,7 +777,7 @@ func (n *NodeAbstractResourceInstance) plan(
// starting values.
// Here we operate on the marked values, so as to revert any changes to the
// marks as well as the value.
configValIgnored, ignoreChangeDiags := n.processIgnoreChanges(priorVal, origConfigVal)
configValIgnored, ignoreChangeDiags := n.processIgnoreChanges(priorVal, origConfigVal, schema)
diags = diags.Append(ignoreChangeDiags)
if ignoreChangeDiags.HasErrors() {
return plan, state, keyData, diags
Expand Down Expand Up @@ -881,7 +881,7 @@ func (n *NodeAbstractResourceInstance) plan(
// 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)
plannedNewVal, ignoreChangeDiags = n.processIgnoreChanges(unmarkedPriorVal, plannedNewVal, schema)
diags = diags.Append(ignoreChangeDiags)
if ignoreChangeDiags.HasErrors() {
return plan, state, keyData, diags
Expand Down Expand Up @@ -1145,7 +1145,7 @@ func (n *NodeAbstractResourceInstance) plan(
return plan, state, keyData, diags
}

func (n *NodeAbstractResource) processIgnoreChanges(prior, config cty.Value) (cty.Value, tfdiags.Diagnostics) {
func (n *NodeAbstractResource) processIgnoreChanges(prior, config cty.Value, schema *configschema.Block) (cty.Value, tfdiags.Diagnostics) {
// ignore_changes only applies when an object already exists, since we
// can't ignore changes to a thing we've not created yet.
if prior.IsNull() {
Expand All @@ -1158,9 +1158,23 @@ func (n *NodeAbstractResource) processIgnoreChanges(prior, config cty.Value) (ct
if len(ignoreChanges) == 0 && !ignoreAll {
return config, nil
}

if ignoreAll {
return prior, nil
// If we are trying to ignore all attribute changes, we must filter
// computed attributes out from the prior state to avoid sending them
// to the provider as if they were included in the configuration.
ret, _ := cty.Transform(prior, func(path cty.Path, v cty.Value) (cty.Value, error) {
attr := schema.AttributeByPath(path)
if attr != nil && attr.Computed && !attr.Optional {
return cty.NullVal(v.Type()), nil
}

return v, nil
})

return ret, nil
}

if prior.IsNull() || config.IsNull() {
// Ignore changes doesn't apply when we're creating for the first time.
// Proposed should never be null here, but if it is then we'll just let it be.
Expand Down
Expand Up @@ -5,6 +5,7 @@ variable "bar" {}
resource "aws_instance" "foo" {
ami = "${var.foo}"
instance = "${var.bar}"
foo = "bar"

lifecycle {
ignore_changes = all
Expand Down

0 comments on commit 8c98e1f

Please sign in to comment.