website: Document ignore_changes for individual map elements
This also includes a previously-missing test that verifies the behavior described here, implemented as a planning context test for consistency with how the other ignore_changes tests are handled.
This commit is contained in:
parent
b1e92b3769
commit
1bba574fe9
|
@ -4870,6 +4870,87 @@ func TestContext2Plan_ignoreChangesWildcard(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestContext2Plan_ignoreChangesInMap(t *testing.T) {
|
||||
p := testProvider("test")
|
||||
|
||||
p.GetSchemaReturn = &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"test_ignore_changes_map": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"tags": {Type: cty.Map(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
|
||||
return providers.PlanResourceChangeResponse{
|
||||
PlannedState: req.ProposedNewState,
|
||||
}
|
||||
}
|
||||
|
||||
p.DiffFn = testDiffFn
|
||||
|
||||
s := states.BuildState(func(ss *states.SyncState) {
|
||||
ss.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "test_ignore_changes_map",
|
||||
Name: "foo",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"tags":{"ignored":"from state","other":"from state"}}`),
|
||||
},
|
||||
addrs.ProviderConfig{
|
||||
Type: "test",
|
||||
}.Absolute(addrs.RootModuleInstance),
|
||||
)
|
||||
})
|
||||
m := testModule(t, "plan-ignore-changes-in-map")
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Config: m,
|
||||
ProviderResolver: providers.ResolverFixed(
|
||||
map[string]providers.Factory{
|
||||
"test": testProviderFuncFixed(p),
|
||||
},
|
||||
),
|
||||
State: s,
|
||||
})
|
||||
|
||||
plan, diags := ctx.Plan()
|
||||
if diags.HasErrors() {
|
||||
t.Fatalf("unexpected errors: %s", diags.Err())
|
||||
}
|
||||
|
||||
schema := p.GetSchemaReturn.ResourceTypes["test_ignore_changes_map"]
|
||||
ty := schema.ImpliedType()
|
||||
|
||||
if got, want := len(plan.Changes.Resources), 1; got != want {
|
||||
t.Fatalf("wrong number of changes %d; want %d", got, want)
|
||||
}
|
||||
|
||||
res := plan.Changes.Resources[0]
|
||||
ric, err := res.Decode(ty)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if res.Action != plans.Update {
|
||||
t.Fatalf("resource %s should be updated, got %s", ric.Addr, res.Action)
|
||||
}
|
||||
|
||||
if got, want := ric.Addr.String(), "test_ignore_changes_map.foo"; got != want {
|
||||
t.Fatalf("unexpected resource address %s; want %s", got, want)
|
||||
}
|
||||
|
||||
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
||||
"tags": cty.MapVal(map[string]cty.Value{
|
||||
"ignored": cty.StringVal("from state"),
|
||||
"other": cty.StringVal("from config"),
|
||||
}),
|
||||
}), ric.After)
|
||||
}
|
||||
|
||||
func TestContext2Plan_moduleMapLiteral(t *testing.T) {
|
||||
m := testModule(t, "plan-module-map-literal")
|
||||
p := testProvider("aws")
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
resource "test_ignore_changes_map" "foo" {
|
||||
tags = {
|
||||
ignored = "from config"
|
||||
other = "from config"
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
tags["ignored"],
|
||||
]
|
||||
}
|
||||
}
|
|
@ -436,6 +436,35 @@ meta-arguments are supported:
|
|||
}
|
||||
```
|
||||
|
||||
You can also ignore specific map elements by writing references like
|
||||
`tags["Name"]` in the `ignore_changes` list, though with an important
|
||||
caveat: the ignoring applies only to in-place updates to an existing
|
||||
key. Adding or removing a key is treated by Terraform as a change to the
|
||||
containing map itself rather than to the individual key, and so if you
|
||||
wish to ignore changes to a particular tag made by an external system
|
||||
you must ensure that the Terraform configuration creates a placeholder
|
||||
element for that tag name so that the external system changes will be
|
||||
understood as an in-place edit of that key:
|
||||
|
||||
```hcl
|
||||
resource "aws_instance" "example" {
|
||||
# ...
|
||||
|
||||
tags = {
|
||||
# Initial value for Name is overridden by our automatic scheduled
|
||||
# re-tagging process; changes to this are ignored by ignore_changes
|
||||
# below.
|
||||
Name = "placeholder"
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
tags["Name"],
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Instead of a list, the special keyword `all` may be used to instruct
|
||||
Terraform to ignore _all_ attributes, which means that Terraform can
|
||||
create and destroy the remote object but will never propose updates to it.
|
||||
|
|
Loading…
Reference in New Issue