| // Copyright (c) The OpenTofu Authors | |
| // SPDX-License-Identifier: MPL-2.0 | |
| // Copyright (c) 2023 HashiCorp, Inc. | |
| // SPDX-License-Identifier: MPL-2.0 | |
| package refactoring_test | |
| import ( | |
| "testing" | |
| "path/filepath" | |
| "github.com/google/go-cmp/cmp" | |
| "github.com/opentofu/opentofu/internal/addrs" | |
| "github.com/opentofu/opentofu/internal/refactoring" | |
| "github.com/opentofu/opentofu/internal/tfdiags" | |
| ) | |
| func TestGetEndpointsToRemove(t *testing.T) { | |
| tests := []struct { | |
| name string | |
| fixtureName string | |
| want []*refactoring.RemoveStatement | |
| wantError string | |
| }{ | |
| { | |
| name: "Valid cases", | |
| fixtureName: "testdata/remove-statement/valid-remove-statements", | |
| want: []*refactoring.RemoveStatement{ | |
| { | |
| From: mustConfigResourceAddr("foo.basic_resource"), | |
| DeclRange: tfdiags.SourceRange{ | |
| Filename: filepath.FromSlash("testdata/remove-statement/valid-remove-statements/main.tf"), | |
| Start: tfdiags.SourcePos{Line: 1, Column: 1}, | |
| End: tfdiags.SourcePos{Line: 1, Column: 8, Byte: 7}, | |
| }, | |
| }, | |
| { | |
| From: addrs.Module{"basic_module"}, | |
| DeclRange: tfdiags.SourceRange{ | |
| Filename: filepath.FromSlash("testdata/remove-statement/valid-remove-statements/main.tf"), | |
| Start: tfdiags.SourcePos{Line: 5, Column: 1, Byte: 41}, | |
| End: tfdiags.SourcePos{Line: 5, Column: 8, Byte: 48}, | |
| }, | |
| }, | |
| { | |
| From: mustConfigResourceAddr("module.child.foo.removed_resource_from_root_module"), | |
| DeclRange: tfdiags.SourceRange{ | |
| Filename: filepath.FromSlash("testdata/remove-statement/valid-remove-statements/main.tf"), | |
| Start: tfdiags.SourcePos{Line: 9, Column: 1, Byte: 83}, | |
| End: tfdiags.SourcePos{Line: 9, Column: 8, Byte: 90}, | |
| }, | |
| }, | |
| { | |
| From: mustConfigResourceAddr("module.child.foo.removed_resource_from_child_module"), | |
| DeclRange: tfdiags.SourceRange{ | |
| Filename: filepath.FromSlash("testdata/remove-statement/valid-remove-statements/child/main.tf"), | |
| Start: tfdiags.SourcePos{Line: 1, Column: 1}, | |
| End: tfdiags.SourcePos{Line: 1, Column: 8, Byte: 7}, | |
| }, | |
| }, | |
| { | |
| From: addrs.Module{"child", "removed_module_from_child_module"}, | |
| DeclRange: tfdiags.SourceRange{ | |
| Filename: filepath.FromSlash("testdata/remove-statement/valid-remove-statements/child/main.tf"), | |
| Start: tfdiags.SourcePos{Line: 9, Column: 1, Byte: 112}, | |
| End: tfdiags.SourcePos{Line: 9, Column: 8, Byte: 119}, | |
| }, | |
| }, | |
| { | |
| From: mustConfigResourceAddr("module.child.module.grandchild.foo.removed_resource_from_grandchild_module"), | |
| DeclRange: tfdiags.SourceRange{ | |
| Filename: filepath.FromSlash("testdata/remove-statement/valid-remove-statements/child/grandchild/main.tf"), | |
| Start: tfdiags.SourcePos{Line: 1, Column: 1}, | |
| End: tfdiags.SourcePos{Line: 1, Column: 8, Byte: 7}, | |
| }, | |
| }, | |
| { | |
| From: addrs.Module{"child", "grandchild", "removed_module_from_grandchild_module"}, | |
| DeclRange: tfdiags.SourceRange{ | |
| Filename: filepath.FromSlash("testdata/remove-statement/valid-remove-statements/child/grandchild/main.tf"), | |
| Start: tfdiags.SourcePos{Line: 5, Column: 1, Byte: 66}, | |
| End: tfdiags.SourcePos{Line: 5, Column: 8, Byte: 73}, | |
| }, | |
| }, | |
| }, | |
| wantError: ``, | |
| }, | |
| { | |
| name: "Error - resource block still exist", | |
| fixtureName: "testdata/remove-statement/not-valid-resource-block-still-exist", | |
| want: []*refactoring.RemoveStatement{ | |
| {From: mustConfigResourceAddr("foo.basic_resource")}, | |
| }, | |
| wantError: `Removed resource block still exists: This statement declares a removal of the resource foo.basic_resource, but this resource block still exists in the configuration. Please remove the resource block.`, | |
| }, | |
| { | |
| name: "Error - module block still exist", | |
| fixtureName: "testdata/remove-statement/not-valid-module-block-still-exist", | |
| want: []*refactoring.RemoveStatement{}, | |
| wantError: `Removed module block still exists: This statement declares a removal of the module module.child, but this module block still exists in the configuration. Please remove the module block.`, | |
| }, | |
| { | |
| name: "Error - nested resource block still exist", | |
| fixtureName: "testdata/remove-statement/not-valid-nested-resource-block-still-exist", | |
| want: []*refactoring.RemoveStatement{}, | |
| wantError: `Removed resource block still exists: This statement declares a removal of the resource module.child.foo.basic_resource, but this resource block still exists in the configuration. Please remove the resource block.`, | |
| }} | |
| for _, tt := range tests { | |
| t.Run(tt.name, func(t *testing.T) { | |
| rootCfg, _ := loadRefactoringFixture(t, tt.fixtureName) | |
| got, diags := refactoring.FindRemoveStatements(rootCfg) | |
| if tt.wantError != "" { | |
| if !diags.HasErrors() { | |
| t.Fatalf("missing expected error\ngot: <no error>\nwant: %s", tt.wantError) | |
| } | |
| errStr := diags.Err().Error() | |
| if errStr != tt.wantError { | |
| t.Fatalf("wrong error\ngot: %s\nwant: %s", errStr, tt.wantError) | |
| } | |
| } else { | |
| if diff := cmp.Diff(tt.want, got); diff != "" { | |
| t.Errorf("wrong result\n%s", diff) | |
| } | |
| } | |
| }) | |
| } | |
| } | |
| func mustConfigResourceAddr(s string) addrs.ConfigResource { | |
| addr, diags := addrs.ParseAbsResourceStr(s) | |
| if diags.HasErrors() { | |
| panic(diags.Err()) | |
| } | |
| return addr.Config() | |
| } |