diff --git a/CHANGELOG.md b/CHANGELOG.md index c486bb8059..b3ff2ec56c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,13 +8,14 @@ UPGRADE NOTES: NEW FEATURES: - New builtin provider functions added ([#2306](https://github.com/opentofu/opentofu/pull/2306)) : - - `provider::terraform::decode_tfvars` - Decode a TFVars file content into an object. - - `provider::terraform::encode_tfvars` - Encode an object into a string with the same format as a TFVars file. - - `provider::terraform::encode_expr` - Encode an arbitrary expression into a string with valid OpenTofu syntax. + - `provider::terraform::decode_tfvars` - Decode a TFVars file content into an object. + - `provider::terraform::encode_tfvars` - Encode an object into a string with the same format as a TFVars file. + - `provider::terraform::encode_expr` - Encode an arbitrary expression into a string with valid OpenTofu syntax. ENHANCEMENTS: * OpenTofu will now recommend using `-exclude` instead of `-target`, when possible, in the error messages about unknown values in `count` and `for_each` arguments, thereby providing a more definitive workaround. ([#2154](https://github.com/opentofu/opentofu/pull/2154)) * State encryption now supports using external programs as key providers. Additionally, the PBKDF2 key provider now supports chaining via the `chain` parameter. ([#2023](https://github.com/opentofu/opentofu/pull/2023)) +* Added count of forgotten resources to plan and apply outputs. ([#1956](https://github.com/opentofu/opentofu/issues/1956)) * The `element` function now accepts negative indices, which extends the existing "wrapping" model into the negative direction. In particular, choosing element `-1` selects the final element in the sequence. ([#2371](https://github.com/opentofu/opentofu/pull/2371)) * `moved` now supports moving between different types ([#2370](https://github.com/opentofu/opentofu/pull/2370)) * `moved` block can now be used to migrate from the `null_resource` to the `terraform_data` resource. ([#2481](https://github.com/opentofu/opentofu/pull/2481)) diff --git a/internal/command/jsonformat/plan.go b/internal/command/jsonformat/plan.go index e9236e7fca..a469a7014d 100644 --- a/internal/command/jsonformat/plan.go +++ b/internal/command/jsonformat/plan.go @@ -64,6 +64,7 @@ func (plan Plan) renderHuman(renderer Renderer, mode plans.Mode, opts ...plans.Q willPrintResourceChanges := false counts := make(map[plans.Action]int) importingCount := 0 + forgettingCount := 0 var changes []diff for _, diff := range diffs.changes { action := jsonplan.UnmarshalActions(diff.change.Change.Actions) @@ -82,6 +83,10 @@ func (plan Plan) renderHuman(renderer Renderer, mode plans.Mode, opts ...plans.Q importingCount++ } + if action == plans.Forget { + forgettingCount++ + } + // Don't count move-only changes if action != plans.NoOp { willPrintResourceChanges = true @@ -224,12 +229,29 @@ func (plan Plan) renderHuman(renderer Renderer, mode plans.Mode, opts ...plans.Q } if importingCount > 0 { + if forgettingCount > 0 { + renderer.Streams.Printf( + renderer.Colorize.Color("\n[bold]Plan:[reset] %d to import, %d to add, %d to change, %d to destroy, %d to forget.\n"), + importingCount, + counts[plans.Create]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete], + counts[plans.Update], + counts[plans.Delete]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete], + forgettingCount) + } else { + renderer.Streams.Printf( + renderer.Colorize.Color("\n[bold]Plan:[reset] %d to import, %d to add, %d to change, %d to destroy.\n"), + importingCount, + counts[plans.Create]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete], + counts[plans.Update], + counts[plans.Delete]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete]) + } + } else if forgettingCount > 0 { renderer.Streams.Printf( - renderer.Colorize.Color("\n[bold]Plan:[reset] %d to import, %d to add, %d to change, %d to destroy.\n"), - importingCount, + renderer.Colorize.Color("\n[bold]Plan:[reset] %d to add, %d to change, %d to destroy, %d to forget.\n"), counts[plans.Create]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete], counts[plans.Update], - counts[plans.Delete]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete]) + counts[plans.Delete]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete], + forgettingCount) } else { renderer.Streams.Printf( renderer.Colorize.Color("\n[bold]Plan:[reset] %d to add, %d to change, %d to destroy.\n"), diff --git a/internal/command/testdata/apply/output.jsonlog b/internal/command/testdata/apply/output.jsonlog index 0c63ab56c8..5b8896fb6a 100644 --- a/internal/command/testdata/apply/output.jsonlog +++ b/internal/command/testdata/apply/output.jsonlog @@ -1,7 +1,7 @@ {"@level":"info","@message":"Terraform 0.15.0-dev","@module":"tofu.ui","terraform":"0.15.0-dev","type":"version","ui":"0.1.0"} {"@level":"info","@message":"test_instance.foo: Plan to create","@module":"tofu.ui","change":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"planned_change"} -{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"tofu.ui","changes":{"add":1,"import":0,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"} +{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"tofu.ui","changes":{"add":1,"import":0,"change":0,"forget":0,"remove":0,"operation":"plan"},"type":"change_summary"} {"@level":"info","@message":"test_instance.foo: Creating...","@module":"tofu.ui","hook":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"apply_start"} {"@level":"info","@message":"test_instance.foo: Creation complete after 0s","@module":"tofu.ui","hook":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create","elapsed_seconds":0},"type":"apply_complete"} -{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"tofu.ui","changes":{"add":1,"import":0,"change":0,"remove":0,"operation":"apply"},"type":"change_summary"} +{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"tofu.ui","changes":{"add":1,"import":0,"change":0,"forget":0,"remove":0,"operation":"apply"},"type":"change_summary"} {"@level":"info","@message":"Outputs: 0","@module":"tofu.ui","outputs":{},"type":"outputs"} diff --git a/internal/command/testdata/plan/output.jsonlog b/internal/command/testdata/plan/output.jsonlog index 4a54f36930..c2dc801968 100644 --- a/internal/command/testdata/plan/output.jsonlog +++ b/internal/command/testdata/plan/output.jsonlog @@ -2,4 +2,4 @@ {"@level":"info","@message":"data.test_data_source.a: Refreshing...","@module":"tofu.ui","hook":{"resource":{"addr":"data.test_data_source.a","module":"","resource":"data.test_data_source.a","implied_provider":"test","resource_type":"test_data_source","resource_name":"a","resource_key":null},"action":"read"},"type":"apply_start"} {"@level":"info","@message":"data.test_data_source.a: Refresh complete after 0s [id=zzzzz]","@module":"tofu.ui","hook":{"resource":{"addr":"data.test_data_source.a","module":"","resource":"data.test_data_source.a","implied_provider":"test","resource_type":"test_data_source","resource_name":"a","resource_key":null},"action":"read","id_key":"id","id_value":"zzzzz","elapsed_seconds":0},"type":"apply_complete"} {"@level":"info","@message":"test_instance.foo: Plan to create","@module":"tofu.ui","change":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"planned_change"} -{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"tofu.ui","changes":{"add":1,"import":0,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"} +{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"tofu.ui","changes":{"add":1,"import":0,"change":0,"forget":0,"remove":0,"operation":"plan"},"type":"change_summary"} diff --git a/internal/command/views/apply.go b/internal/command/views/apply.go index ac967b12d2..9c7a4da47d 100644 --- a/internal/command/views/apply.go +++ b/internal/command/views/apply.go @@ -69,12 +69,31 @@ func (v *ApplyHuman) ResourceCount(stateOutPath string) { v.countHook.Removed, ) } else if v.countHook.Imported > 0 { + if v.countHook.Forgotten > 0 { + v.view.streams.Printf( + v.view.colorize.Color("[reset][bold][green]\nApply complete! Resources: %d imported, %d added, %d changed, %d destroyed, %d forgotten.\n"), + v.countHook.Imported, + v.countHook.Added, + v.countHook.Changed, + v.countHook.Removed, + v.countHook.Forgotten, + ) + } else { + v.view.streams.Printf( + v.view.colorize.Color("[reset][bold][green]\nApply complete! Resources: %d imported, %d added, %d changed, %d destroyed.\n"), + v.countHook.Imported, + v.countHook.Added, + v.countHook.Changed, + v.countHook.Removed, + ) + } + } else if v.countHook.Forgotten > 0 { v.view.streams.Printf( - v.view.colorize.Color("[reset][bold][green]\nApply complete! Resources: %d imported, %d added, %d changed, %d destroyed.\n"), - v.countHook.Imported, + v.view.colorize.Color("[reset][bold][green]\nApply complete! Resources: %d added, %d changed, %d destroyed, %d forgotten.\n"), v.countHook.Added, v.countHook.Changed, v.countHook.Removed, + v.countHook.Forgotten, ) } else { v.view.streams.Printf( @@ -144,6 +163,7 @@ func (v *ApplyJSON) ResourceCount(stateOutPath string) { Change: v.countHook.Changed, Remove: v.countHook.Removed, Import: v.countHook.Imported, + Forget: v.countHook.Forgotten, Operation: operation, }) } diff --git a/internal/command/views/apply_test.go b/internal/command/views/apply_test.go index 3a44d879e6..4ad9c3cc08 100644 --- a/internal/command/views/apply_test.go +++ b/internal/command/views/apply_test.go @@ -105,24 +105,34 @@ func TestApplyHuman_help(t *testing.T) { // Hooks and ResourceCount are tangled up and easiest to test together. func TestApply_resourceCount(t *testing.T) { testCases := map[string]struct { - destroy bool - want string - importing bool + destroy bool + want string + importing bool + forgetting bool }{ "apply": { false, "Apply complete! Resources: 1 added, 2 changed, 3 destroyed.", false, + false, }, "destroy": { true, "Destroy complete! Resources: 3 destroyed.", false, + false, }, "import": { false, "Apply complete! Resources: 1 imported, 1 added, 2 changed, 3 destroyed.", true, + false, + }, + "forget": { + false, + "Apply complete! Resources: 1 added, 2 changed, 3 destroyed, 1 forgotten.", + false, + true, }, } @@ -155,6 +165,10 @@ func TestApply_resourceCount(t *testing.T) { count.Imported = 1 } + if tc.forgetting { + count.Forgotten = 1 + } + v.ResourceCount("") got := done(t).Stdout() diff --git a/internal/command/views/hook_count.go b/internal/command/views/hook_count.go index 8ecfd4465f..d94671e359 100644 --- a/internal/command/views/hook_count.go +++ b/internal/command/views/hook_count.go @@ -19,10 +19,11 @@ import ( // countHook is a hook that counts the number of resources // added, removed, changed during the course of an apply. type countHook struct { - Added int - Changed int - Removed int - Imported int + Added int + Changed int + Removed int + Imported int + Forgotten int ToAdd int ToChange int @@ -46,6 +47,7 @@ func (h *countHook) Reset() { h.Changed = 0 h.Removed = 0 h.Imported = 0 + h.Forgotten = 0 } func (h *countHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (tofu.HookAction, error) { @@ -81,6 +83,7 @@ func (h *countHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generat h.Removed++ case plans.Update: h.Changed++ + } } } @@ -119,3 +122,11 @@ func (h *countHook) PostApplyImport(addr addrs.AbsResourceInstance, importing pl h.Imported++ return tofu.HookActionContinue, nil } + +func (h *countHook) PostApplyForget(_ addrs.AbsResourceInstance) (tofu.HookAction, error) { + h.Lock() + defer h.Unlock() + + h.Forgotten++ + return tofu.HookActionContinue, nil +} diff --git a/internal/command/views/json/change_summary.go b/internal/command/views/json/change_summary.go index 2083efc8a1..4a2ecd5839 100644 --- a/internal/command/views/json/change_summary.go +++ b/internal/command/views/json/change_summary.go @@ -5,7 +5,10 @@ package json -import "fmt" +import ( + "fmt" + "strings" +) type Operation string @@ -20,6 +23,7 @@ type ChangeSummary struct { Change int `json:"change"` Import int `json:"import"` Remove int `json:"remove"` + Forget int `json:"forget"` Operation Operation `json:"operation"` } @@ -27,19 +31,34 @@ type ChangeSummary struct { // used by Terraform Cloud and Terraform Enterprise, so the exact formats of // these strings are important. func (cs *ChangeSummary) String() string { + var builder strings.Builder switch cs.Operation { case OperationApplied: + builder.WriteString("Apply complete! Resources: ") if cs.Import > 0 { - return fmt.Sprintf("Apply complete! Resources: %d imported, %d added, %d changed, %d destroyed.", cs.Import, cs.Add, cs.Change, cs.Remove) + builder.WriteString(fmt.Sprintf("%d imported, ", cs.Import)) } - return fmt.Sprintf("Apply complete! Resources: %d added, %d changed, %d destroyed.", cs.Add, cs.Change, cs.Remove) + builder.WriteString(fmt.Sprintf("%d added, %d changed, %d destroyed", cs.Add, cs.Change, cs.Remove)) + if cs.Forget > 0 { + builder.WriteString(fmt.Sprintf(", %d forgotten.", cs.Forget)) + } else { + builder.WriteString(".") + } + return builder.String() case OperationDestroyed: return fmt.Sprintf("Destroy complete! Resources: %d destroyed.", cs.Remove) case OperationPlanned: + builder.WriteString("Plan: ") if cs.Import > 0 { - return fmt.Sprintf("Plan: %d to import, %d to add, %d to change, %d to destroy.", cs.Import, cs.Add, cs.Change, cs.Remove) + builder.WriteString(fmt.Sprintf("%d to import, ", cs.Import)) } - return fmt.Sprintf("Plan: %d to add, %d to change, %d to destroy.", cs.Add, cs.Change, cs.Remove) + builder.WriteString(fmt.Sprintf("%d to add, %d to change, %d to destroy", cs.Add, cs.Change, cs.Remove)) + if cs.Forget > 0 { + builder.WriteString(fmt.Sprintf(", %d to forget.", cs.Forget)) + } else { + builder.WriteString(".") + } + return builder.String() default: return fmt.Sprintf("%s: %d add, %d change, %d destroy", cs.Operation, cs.Add, cs.Change, cs.Remove) } diff --git a/internal/command/views/json_view_test.go b/internal/command/views/json_view_test.go index 8b18cddc78..e6ba154350 100644 --- a/internal/command/views/json_view_test.go +++ b/internal/command/views/json_view_test.go @@ -282,6 +282,7 @@ func TestJSONView_ChangeSummary(t *testing.T) { "import": float64(0), "change": float64(2), "remove": float64(3), + "forget": float64(0), "operation": "apply", }, }, @@ -312,6 +313,38 @@ func TestJSONView_ChangeSummaryWithImport(t *testing.T) { "change": float64(2), "remove": float64(3), "import": float64(1), + "forget": float64(0), + "operation": "apply", + }, + }, + } + testJSONViewOutputEquals(t, done(t).Stdout(), want) +} + +func TestJSONView_ChangeSummaryWithForget(t *testing.T) { + streams, done := terminal.StreamsForTesting(t) + jv := NewJSONView(NewView(streams)) + + jv.ChangeSummary(&viewsjson.ChangeSummary{ + Add: 1, + Change: 2, + Remove: 3, + Forget: 1, + Operation: viewsjson.OperationApplied, + }) + + want := []map[string]interface{}{ + { + "@level": "info", + "@message": "Apply complete! Resources: 1 added, 2 changed, 3 destroyed, 1 forgotten.", + "@module": "tofu.ui", + "type": "change_summary", + "changes": map[string]interface{}{ + "add": float64(1), + "change": float64(2), + "remove": float64(3), + "import": float64(0), + "forget": float64(1), "operation": "apply", }, }, diff --git a/internal/command/views/operation.go b/internal/command/views/operation.go index d5ef27659b..aa893ab86c 100644 --- a/internal/command/views/operation.go +++ b/internal/command/views/operation.go @@ -247,6 +247,8 @@ func (v *OperationJSON) Plan(plan *plans.Plan, schemas *tofu.Schemas) { case plans.CreateThenDelete, plans.DeleteThenCreate: cs.Add++ cs.Remove++ + case plans.Forget: + cs.Forget++ } if change.Action != plans.NoOp || !change.Addr.Equal(change.PrevRunAddr) || change.Importing != nil { diff --git a/internal/command/views/operation_test.go b/internal/command/views/operation_test.go index c0e24ee416..efd98162cb 100644 --- a/internal/command/views/operation_test.go +++ b/internal/command/views/operation_test.go @@ -582,6 +582,7 @@ func TestOperationJSON_planNoChanges(t *testing.T) { "add": float64(0), "import": float64(0), "change": float64(0), + "forget": float64(0), "remove": float64(0), }, }, @@ -750,6 +751,7 @@ func TestOperationJSON_plan(t *testing.T) { "add": float64(3), "import": float64(0), "change": float64(1), + "forget": float64(0), "remove": float64(3), }, }, @@ -897,6 +899,7 @@ func TestOperationJSON_planWithImport(t *testing.T) { "add": float64(1), "import": float64(4), "change": float64(1), + "forget": float64(0), "remove": float64(2), }, }, @@ -1034,6 +1037,7 @@ func TestOperationJSON_planDriftWithMove(t *testing.T) { "add": float64(0), "import": float64(0), "change": float64(0), + "forget": float64(0), "remove": float64(0), }, }, @@ -1165,6 +1169,7 @@ func TestOperationJSON_planDriftWithMoveRefreshOnly(t *testing.T) { "add": float64(0), "import": float64(0), "change": float64(0), + "forget": float64(0), "remove": float64(0), }, }, @@ -1226,6 +1231,7 @@ func TestOperationJSON_planOutputChanges(t *testing.T) { "import": float64(0), "change": float64(0), "remove": float64(0), + "forget": float64(0), }, }, // Output changes diff --git a/internal/tofu/context_apply.go b/internal/tofu/context_apply.go index c4dfce6434..be80d4e16e 100644 --- a/internal/tofu/context_apply.go +++ b/internal/tofu/context_apply.go @@ -32,8 +32,9 @@ func (c *Context) Apply(ctx context.Context, plan *plans.Plan, config *configs.C log.Printf("[DEBUG] Building and walking apply graph for %s plan", plan.UIMode) + var diags tfdiags.Diagnostics + if plan.Errored { - var diags tfdiags.Diagnostics diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, "Cannot apply failed plan", @@ -47,10 +48,30 @@ func (c *Context) Apply(ctx context.Context, plan *plans.Plan, config *configs.C // like to show some helpful output that mirrors the way we show other changes. if rc.Importing != nil { for _, h := range c.hooks { - // In future, we may need to call PostApplyImport separately elsewhere in the apply + // In the future, we may need to call PostApplyImport separately elsewhere in the apply // operation. For now, though, we'll call Pre and Post hooks together. - h.PreApplyImport(rc.Addr, *rc.Importing) - h.PostApplyImport(rc.Addr, *rc.Importing) + _, err := h.PreApplyImport(rc.Addr, *rc.Importing) + if err != nil { + return nil, diags.Append(err) + } + _, err = h.PostApplyImport(rc.Addr, *rc.Importing) + if err != nil { + return nil, diags.Append(err) + } + } + } + + // Following the same logic, we want to show helpful output for forget operations as well. + if rc.Action == plans.Forget { + for _, h := range c.hooks { + _, err := h.PreApplyForget(rc.Addr) + if err != nil { + return nil, diags.Append(err) + } + _, err = h.PostApplyForget(rc.Addr) + if err != nil { + return nil, diags.Append(err) + } } } } diff --git a/internal/tofu/hook.go b/internal/tofu/hook.go index 708226d8c5..7a84448d12 100644 --- a/internal/tofu/hook.go +++ b/internal/tofu/hook.go @@ -92,6 +92,10 @@ type Hook interface { PreApplyImport(addr addrs.AbsResourceInstance, importing plans.ImportingSrc) (HookAction, error) PostApplyImport(addr addrs.AbsResourceInstance, importing plans.ImportingSrc) (HookAction, error) + // PreApplyForget and PostApplyForget are called during an apply for each forgotten resource. + PreApplyForget(addr addrs.AbsResourceInstance) (HookAction, error) + PostApplyForget(addr addrs.AbsResourceInstance) (HookAction, error) + // Stopping is called if an external signal requests that OpenTofu // gracefully abort an operation in progress. // @@ -188,6 +192,14 @@ func (h *NilHook) PostApplyImport(addr addrs.AbsResourceInstance, importing plan return HookActionContinue, nil } +func (h *NilHook) PreApplyForget(_ addrs.AbsResourceInstance) (HookAction, error) { + return HookActionContinue, nil +} + +func (h *NilHook) PostApplyForget(_ addrs.AbsResourceInstance) (HookAction, error) { + return HookActionContinue, nil +} + func (*NilHook) Stopping() { // Does nothing at all by default } diff --git a/internal/tofu/hook_mock.go b/internal/tofu/hook_mock.go index 461a6a5cc8..0d21b6f33c 100644 --- a/internal/tofu/hook_mock.go +++ b/internal/tofu/hook_mock.go @@ -133,6 +133,14 @@ type MockHook struct { PostApplyImportReturn HookAction PostApplyImportError error + PreApplyForgetCalled bool + PreApplyForgetReturn HookAction + PreApplyForgetError error + + PostApplyForgetCalled bool + PostApplyForgetReturn HookAction + PostApplyForgetError error + StoppingCalled bool PostStateUpdateCalled bool @@ -327,6 +335,22 @@ func (h *MockHook) PostApplyImport(addr addrs.AbsResourceInstance, importing pla return h.PostApplyImportReturn, h.PostApplyImportError } +func (h *MockHook) PreApplyForget(_ addrs.AbsResourceInstance) (HookAction, error) { + h.Lock() + defer h.Unlock() + + h.PreApplyForgetCalled = true + return h.PreApplyForgetReturn, h.PreApplyForgetError +} + +func (h *MockHook) PostApplyForget(_ addrs.AbsResourceInstance) (HookAction, error) { + h.Lock() + defer h.Unlock() + + h.PostApplyForgetCalled = true + return h.PostApplyForgetReturn, h.PostApplyForgetError +} + func (h *MockHook) Stopping() { h.Lock() defer h.Unlock() diff --git a/internal/tofu/hook_stop.go b/internal/tofu/hook_stop.go index 5ca18da765..4e86e014d9 100644 --- a/internal/tofu/hook_stop.go +++ b/internal/tofu/hook_stop.go @@ -92,6 +92,14 @@ func (h *stopHook) PostApplyImport(addr addrs.AbsResourceInstance, importing pla return h.hook() } +func (h *stopHook) PreApplyForget(_ addrs.AbsResourceInstance) (HookAction, error) { + return h.hook() +} + +func (h *stopHook) PostApplyForget(_ addrs.AbsResourceInstance) (HookAction, error) { + return h.hook() +} + func (h *stopHook) Stopping() {} func (h *stopHook) PostStateUpdate(new *states.State) (HookAction, error) { diff --git a/internal/tofu/hook_test.go b/internal/tofu/hook_test.go index 58922166f4..ee8e827a0d 100644 --- a/internal/tofu/hook_test.go +++ b/internal/tofu/hook_test.go @@ -157,6 +157,20 @@ func (h *testHook) PostApplyImport(addr addrs.AbsResourceInstance, importing pla return HookActionContinue, nil } +func (h *testHook) PreApplyForget(addr addrs.AbsResourceInstance) (HookAction, error) { + h.mu.Lock() + defer h.mu.Unlock() + h.Calls = append(h.Calls, &testHookCall{"PreApplyForget", addr.String()}) + return HookActionContinue, nil +} + +func (h *testHook) PostApplyForget(addr addrs.AbsResourceInstance) (HookAction, error) { + h.mu.Lock() + defer h.mu.Unlock() + h.Calls = append(h.Calls, &testHookCall{"PostApplyForget", addr.String()}) + return HookActionContinue, nil +} + func (h *testHook) Stopping() { h.mu.Lock() defer h.mu.Unlock() diff --git a/testing/equivalence-tests/outputs/basic_json_string_update/apply.json b/testing/equivalence-tests/outputs/basic_json_string_update/apply.json index 89e3940ac5..aa191b198a 100644 --- a/testing/equivalence-tests/outputs/basic_json_string_update/apply.json +++ b/testing/equivalence-tests/outputs/basic_json_string_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_list/apply.json b/testing/equivalence-tests/outputs/basic_list/apply.json index a608e8fa38..a42022a049 100644 --- a/testing/equivalence-tests/outputs/basic_list/apply.json +++ b/testing/equivalence-tests/outputs/basic_list/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_list_empty/apply.json b/testing/equivalence-tests/outputs/basic_list_empty/apply.json index f2dda29514..d2b390ca7f 100644 --- a/testing/equivalence-tests/outputs/basic_list_empty/apply.json +++ b/testing/equivalence-tests/outputs/basic_list_empty/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_list_null/apply.json b/testing/equivalence-tests/outputs/basic_list_null/apply.json index f2dda29514..d2b390ca7f 100644 --- a/testing/equivalence-tests/outputs/basic_list_null/apply.json +++ b/testing/equivalence-tests/outputs/basic_list_null/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_list_update/apply.json b/testing/equivalence-tests/outputs/basic_list_update/apply.json index f2dda29514..d2b390ca7f 100644 --- a/testing/equivalence-tests/outputs/basic_list_update/apply.json +++ b/testing/equivalence-tests/outputs/basic_list_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_map/apply.json b/testing/equivalence-tests/outputs/basic_map/apply.json index 5db80cdb9f..9c0589c6c9 100644 --- a/testing/equivalence-tests/outputs/basic_map/apply.json +++ b/testing/equivalence-tests/outputs/basic_map/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_map_empty/apply.json b/testing/equivalence-tests/outputs/basic_map_empty/apply.json index b17e01c7bb..09002aee01 100644 --- a/testing/equivalence-tests/outputs/basic_map_empty/apply.json +++ b/testing/equivalence-tests/outputs/basic_map_empty/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_map_null/apply.json b/testing/equivalence-tests/outputs/basic_map_null/apply.json index b17e01c7bb..09002aee01 100644 --- a/testing/equivalence-tests/outputs/basic_map_null/apply.json +++ b/testing/equivalence-tests/outputs/basic_map_null/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_map_update/apply.json b/testing/equivalence-tests/outputs/basic_map_update/apply.json index b17e01c7bb..09002aee01 100644 --- a/testing/equivalence-tests/outputs/basic_map_update/apply.json +++ b/testing/equivalence-tests/outputs/basic_map_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_multiline_string_update/apply.json b/testing/equivalence-tests/outputs/basic_multiline_string_update/apply.json index 17ea20e49a..9f824e3acb 100644 --- a/testing/equivalence-tests/outputs/basic_multiline_string_update/apply.json +++ b/testing/equivalence-tests/outputs/basic_multiline_string_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_set/apply.json b/testing/equivalence-tests/outputs/basic_set/apply.json index 6957204a12..8e6a4d7ef1 100644 --- a/testing/equivalence-tests/outputs/basic_set/apply.json +++ b/testing/equivalence-tests/outputs/basic_set/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_set_empty/apply.json b/testing/equivalence-tests/outputs/basic_set_empty/apply.json index ebae21bc34..a74a7f46e5 100644 --- a/testing/equivalence-tests/outputs/basic_set_empty/apply.json +++ b/testing/equivalence-tests/outputs/basic_set_empty/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_set_null/apply.json b/testing/equivalence-tests/outputs/basic_set_null/apply.json index ebae21bc34..a74a7f46e5 100644 --- a/testing/equivalence-tests/outputs/basic_set_null/apply.json +++ b/testing/equivalence-tests/outputs/basic_set_null/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/basic_set_update/apply.json b/testing/equivalence-tests/outputs/basic_set_update/apply.json index ebae21bc34..a74a7f46e5 100644 --- a/testing/equivalence-tests/outputs/basic_set_update/apply.json +++ b/testing/equivalence-tests/outputs/basic_set_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/drift_refresh_only/apply.json b/testing/equivalence-tests/outputs/drift_refresh_only/apply.json index ec3d908f62..1a276a86a8 100644 --- a/testing/equivalence-tests/outputs/drift_refresh_only/apply.json +++ b/testing/equivalence-tests/outputs/drift_refresh_only/apply.json @@ -5,6 +5,7 @@ "changes": { "add": 0, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/drift_relevant_attributes/apply.json b/testing/equivalence-tests/outputs/drift_relevant_attributes/apply.json index 659a71a15b..fa2abe1091 100644 --- a/testing/equivalence-tests/outputs/drift_relevant_attributes/apply.json +++ b/testing/equivalence-tests/outputs/drift_relevant_attributes/apply.json @@ -117,6 +117,7 @@ "changes": { "add": 0, "change": 2, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/drift_simple/apply.json b/testing/equivalence-tests/outputs/drift_simple/apply.json index a7a780e06f..fdb65279de 100644 --- a/testing/equivalence-tests/outputs/drift_simple/apply.json +++ b/testing/equivalence-tests/outputs/drift_simple/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/fully_populated_complex/apply.json b/testing/equivalence-tests/outputs/fully_populated_complex/apply.json index 54f5ef4858..f3f5d6eda1 100644 --- a/testing/equivalence-tests/outputs/fully_populated_complex/apply.json +++ b/testing/equivalence-tests/outputs/fully_populated_complex/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/fully_populated_complex_destroy/apply.json b/testing/equivalence-tests/outputs/fully_populated_complex_destroy/apply.json index a40399ea99..77caab404a 100644 --- a/testing/equivalence-tests/outputs/fully_populated_complex_destroy/apply.json +++ b/testing/equivalence-tests/outputs/fully_populated_complex_destroy/apply.json @@ -58,6 +58,7 @@ "changes": { "add": 0, "change": 0, + "forget": 0, "import": 0, "operation": "plan", "remove": 1 @@ -107,6 +108,7 @@ "changes": { "add": 0, "change": 0, + "forget": 0, "import": 0, "operation": "destroy", "remove": 1 diff --git a/testing/equivalence-tests/outputs/fully_populated_complex_update/apply.json b/testing/equivalence-tests/outputs/fully_populated_complex_update/apply.json index 7bfc356cef..21799bd46f 100644 --- a/testing/equivalence-tests/outputs/fully_populated_complex_update/apply.json +++ b/testing/equivalence-tests/outputs/fully_populated_complex_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/local_provider_basic/apply.json b/testing/equivalence-tests/outputs/local_provider_basic/apply.json index 40ef952f1d..4ca99afe0f 100644 --- a/testing/equivalence-tests/outputs/local_provider_basic/apply.json +++ b/testing/equivalence-tests/outputs/local_provider_basic/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/local_provider_delete/apply.json b/testing/equivalence-tests/outputs/local_provider_delete/apply.json index 746d1eb0cc..828d5c3e97 100644 --- a/testing/equivalence-tests/outputs/local_provider_delete/apply.json +++ b/testing/equivalence-tests/outputs/local_provider_delete/apply.json @@ -60,6 +60,7 @@ "changes": { "add": 0, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 1 diff --git a/testing/equivalence-tests/outputs/local_provider_update/apply.json b/testing/equivalence-tests/outputs/local_provider_update/apply.json index ed9b031bde..96428f9a21 100644 --- a/testing/equivalence-tests/outputs/local_provider_update/apply.json +++ b/testing/equivalence-tests/outputs/local_provider_update/apply.json @@ -97,6 +97,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 1 diff --git a/testing/equivalence-tests/outputs/moved_simple/apply.json b/testing/equivalence-tests/outputs/moved_simple/apply.json index ec3d908f62..1a276a86a8 100644 --- a/testing/equivalence-tests/outputs/moved_simple/apply.json +++ b/testing/equivalence-tests/outputs/moved_simple/apply.json @@ -5,6 +5,7 @@ "changes": { "add": 0, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/moved_with_drift/apply.json b/testing/equivalence-tests/outputs/moved_with_drift/apply.json index 1cd32d6c09..00e1d46064 100644 --- a/testing/equivalence-tests/outputs/moved_with_drift/apply.json +++ b/testing/equivalence-tests/outputs/moved_with_drift/apply.json @@ -126,6 +126,7 @@ "changes": { "add": 0, "change": 2, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/moved_with_refresh_only/apply.json b/testing/equivalence-tests/outputs/moved_with_refresh_only/apply.json index ec3d908f62..1a276a86a8 100644 --- a/testing/equivalence-tests/outputs/moved_with_refresh_only/apply.json +++ b/testing/equivalence-tests/outputs/moved_with_refresh_only/apply.json @@ -5,6 +5,7 @@ "changes": { "add": 0, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/moved_with_update/apply.json b/testing/equivalence-tests/outputs/moved_with_update/apply.json index 41b9950ae6..badcf533a4 100644 --- a/testing/equivalence-tests/outputs/moved_with_update/apply.json +++ b/testing/equivalence-tests/outputs/moved_with_update/apply.json @@ -70,6 +70,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/multiple_block_types/apply.json b/testing/equivalence-tests/outputs/multiple_block_types/apply.json index 1553911173..e3f13ead0a 100644 --- a/testing/equivalence-tests/outputs/multiple_block_types/apply.json +++ b/testing/equivalence-tests/outputs/multiple_block_types/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/multiple_block_types_update/apply.json b/testing/equivalence-tests/outputs/multiple_block_types_update/apply.json index 753e6d4d11..ab98153ca3 100644 --- a/testing/equivalence-tests/outputs/multiple_block_types_update/apply.json +++ b/testing/equivalence-tests/outputs/multiple_block_types_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/nested_list/apply.json b/testing/equivalence-tests/outputs/nested_list/apply.json index aa1544d3aa..cdfc667636 100644 --- a/testing/equivalence-tests/outputs/nested_list/apply.json +++ b/testing/equivalence-tests/outputs/nested_list/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/nested_list_update/apply.json b/testing/equivalence-tests/outputs/nested_list_update/apply.json index 2a9fa02e51..32033a52ba 100644 --- a/testing/equivalence-tests/outputs/nested_list_update/apply.json +++ b/testing/equivalence-tests/outputs/nested_list_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/nested_map/apply.json b/testing/equivalence-tests/outputs/nested_map/apply.json index 10039b036e..7b12b37716 100644 --- a/testing/equivalence-tests/outputs/nested_map/apply.json +++ b/testing/equivalence-tests/outputs/nested_map/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/nested_map_update/apply.json b/testing/equivalence-tests/outputs/nested_map_update/apply.json index bb8f6ed0c9..9227c5d662 100644 --- a/testing/equivalence-tests/outputs/nested_map_update/apply.json +++ b/testing/equivalence-tests/outputs/nested_map_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/nested_objects/apply.json b/testing/equivalence-tests/outputs/nested_objects/apply.json index 7f17207401..5310053395 100644 --- a/testing/equivalence-tests/outputs/nested_objects/apply.json +++ b/testing/equivalence-tests/outputs/nested_objects/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/nested_objects_update/apply.json b/testing/equivalence-tests/outputs/nested_objects_update/apply.json index bdf7a1b90b..18fa0ea0f6 100644 --- a/testing/equivalence-tests/outputs/nested_objects_update/apply.json +++ b/testing/equivalence-tests/outputs/nested_objects_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/nested_set/apply.json b/testing/equivalence-tests/outputs/nested_set/apply.json index a98b707ae5..f76c717387 100644 --- a/testing/equivalence-tests/outputs/nested_set/apply.json +++ b/testing/equivalence-tests/outputs/nested_set/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/nested_set_update/apply.json b/testing/equivalence-tests/outputs/nested_set_update/apply.json index 0559575fa6..5a93df5a3e 100644 --- a/testing/equivalence-tests/outputs/nested_set_update/apply.json +++ b/testing/equivalence-tests/outputs/nested_set_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/null_provider_delete/apply.json b/testing/equivalence-tests/outputs/null_provider_delete/apply.json index 1a2b41de1c..06821b6a41 100644 --- a/testing/equivalence-tests/outputs/null_provider_delete/apply.json +++ b/testing/equivalence-tests/outputs/null_provider_delete/apply.json @@ -60,6 +60,7 @@ "changes": { "add": 0, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 1 diff --git a/testing/equivalence-tests/outputs/replace_within_list/apply.json b/testing/equivalence-tests/outputs/replace_within_list/apply.json index d65275425d..af715fe81a 100644 --- a/testing/equivalence-tests/outputs/replace_within_list/apply.json +++ b/testing/equivalence-tests/outputs/replace_within_list/apply.json @@ -97,6 +97,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 1 diff --git a/testing/equivalence-tests/outputs/replace_within_map/apply.json b/testing/equivalence-tests/outputs/replace_within_map/apply.json index 6616e7a499..5690b16b61 100644 --- a/testing/equivalence-tests/outputs/replace_within_map/apply.json +++ b/testing/equivalence-tests/outputs/replace_within_map/apply.json @@ -97,6 +97,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 1 diff --git a/testing/equivalence-tests/outputs/replace_within_object/apply.json b/testing/equivalence-tests/outputs/replace_within_object/apply.json index 56f2e2044b..bae2a79e41 100644 --- a/testing/equivalence-tests/outputs/replace_within_object/apply.json +++ b/testing/equivalence-tests/outputs/replace_within_object/apply.json @@ -97,6 +97,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 1 diff --git a/testing/equivalence-tests/outputs/replace_within_set/apply.json b/testing/equivalence-tests/outputs/replace_within_set/apply.json index c855d1a566..d24e9d46e3 100644 --- a/testing/equivalence-tests/outputs/replace_within_set/apply.json +++ b/testing/equivalence-tests/outputs/replace_within_set/apply.json @@ -97,6 +97,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 1 diff --git a/testing/equivalence-tests/outputs/simple_object/apply.json b/testing/equivalence-tests/outputs/simple_object/apply.json index d7d00f22a7..9b8156d734 100644 --- a/testing/equivalence-tests/outputs/simple_object/apply.json +++ b/testing/equivalence-tests/outputs/simple_object/apply.json @@ -59,6 +59,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/simple_object_empty/apply.json b/testing/equivalence-tests/outputs/simple_object_empty/apply.json index d7d1df894b..6175cd040e 100644 --- a/testing/equivalence-tests/outputs/simple_object_empty/apply.json +++ b/testing/equivalence-tests/outputs/simple_object_empty/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/simple_object_null/apply.json b/testing/equivalence-tests/outputs/simple_object_null/apply.json index d7d1df894b..6175cd040e 100644 --- a/testing/equivalence-tests/outputs/simple_object_null/apply.json +++ b/testing/equivalence-tests/outputs/simple_object_null/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/simple_object_replace/apply.json b/testing/equivalence-tests/outputs/simple_object_replace/apply.json index 5ed2084344..de57cbc0a4 100644 --- a/testing/equivalence-tests/outputs/simple_object_replace/apply.json +++ b/testing/equivalence-tests/outputs/simple_object_replace/apply.json @@ -97,6 +97,7 @@ "changes": { "add": 1, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 1 diff --git a/testing/equivalence-tests/outputs/simple_object_update/apply.json b/testing/equivalence-tests/outputs/simple_object_update/apply.json index d7d1df894b..6175cd040e 100644 --- a/testing/equivalence-tests/outputs/simple_object_update/apply.json +++ b/testing/equivalence-tests/outputs/simple_object_update/apply.json @@ -61,6 +61,7 @@ "changes": { "add": 0, "change": 1, + "forget": 0, "import": 0, "operation": "apply", "remove": 0 diff --git a/testing/equivalence-tests/outputs/variables_and_outputs/apply.json b/testing/equivalence-tests/outputs/variables_and_outputs/apply.json index 7d268a5afb..1b961a96a5 100644 --- a/testing/equivalence-tests/outputs/variables_and_outputs/apply.json +++ b/testing/equivalence-tests/outputs/variables_and_outputs/apply.json @@ -5,6 +5,7 @@ "changes": { "add": 0, "change": 0, + "forget": 0, "import": 0, "operation": "apply", "remove": 0