github.com/opentofu/opentofu@v1.7.1/internal/configs/removed_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package configs
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/google/go-cmp/cmp"
    10  	"github.com/hashicorp/hcl/v2"
    11  	"github.com/hashicorp/hcl/v2/hcltest"
    12  	"github.com/opentofu/opentofu/internal/addrs"
    13  )
    14  
    15  func TestRemovedBlock_decode(t *testing.T) {
    16  	blockRange := hcl.Range{
    17  		Filename: "mock.tf",
    18  		Start:    hcl.Pos{Line: 3, Column: 12, Byte: 27},
    19  		End:      hcl.Pos{Line: 3, Column: 19, Byte: 34},
    20  	}
    21  
    22  	foo_expr := hcltest.MockExprTraversalSrc("test_instance.foo")
    23  	mod_foo_expr := hcltest.MockExprTraversalSrc("module.foo")
    24  	foo_index_expr := hcltest.MockExprTraversalSrc("test_instance.foo[1]")
    25  	mod_boop_index_foo_expr := hcltest.MockExprTraversalSrc("module.boop[1].test_instance.foo")
    26  	data_foo_expr := hcltest.MockExprTraversalSrc("data.test_instance.foo")
    27  
    28  	tests := map[string]struct {
    29  		input *hcl.Block
    30  		want  *Removed
    31  		err   string
    32  	}{
    33  		"success": {
    34  			&hcl.Block{
    35  				Type: "removed",
    36  				Body: hcltest.MockBody(&hcl.BodyContent{
    37  					Attributes: hcl.Attributes{
    38  						"from": {
    39  							Name: "from",
    40  							Expr: foo_expr,
    41  						},
    42  					},
    43  				}),
    44  				DefRange: blockRange,
    45  			},
    46  			&Removed{
    47  				From:      mustRemoveEndpointFromExpr(foo_expr),
    48  				DeclRange: blockRange,
    49  			},
    50  			``,
    51  		},
    52  		"modules": {
    53  			&hcl.Block{
    54  				Type: "removed",
    55  				Body: hcltest.MockBody(&hcl.BodyContent{
    56  					Attributes: hcl.Attributes{
    57  						"from": {
    58  							Name: "from",
    59  							Expr: mod_foo_expr,
    60  						},
    61  					},
    62  				}),
    63  				DefRange: blockRange,
    64  			},
    65  			&Removed{
    66  				From:      mustRemoveEndpointFromExpr(mod_foo_expr),
    67  				DeclRange: blockRange,
    68  			},
    69  			``,
    70  		},
    71  		"error: missing argument": {
    72  			&hcl.Block{
    73  				Type: "removed",
    74  				Body: hcltest.MockBody(&hcl.BodyContent{
    75  					Attributes: hcl.Attributes{},
    76  				}),
    77  				DefRange: blockRange,
    78  			},
    79  			&Removed{
    80  				DeclRange: blockRange,
    81  			},
    82  			"Missing required argument",
    83  		},
    84  		"error: indexed resources": {
    85  			&hcl.Block{
    86  				Type: "removed",
    87  				Body: hcltest.MockBody(&hcl.BodyContent{
    88  					Attributes: hcl.Attributes{
    89  						"from": {
    90  							Name: "from",
    91  							Expr: foo_index_expr,
    92  						},
    93  					},
    94  				}),
    95  				DefRange: blockRange,
    96  			},
    97  			&Removed{
    98  				DeclRange: blockRange,
    99  			},
   100  			"Resource instance address with keys is not allowed",
   101  		},
   102  		"error: indexed modules": {
   103  			&hcl.Block{
   104  				Type: "removed",
   105  				Body: hcltest.MockBody(&hcl.BodyContent{
   106  					Attributes: hcl.Attributes{
   107  						"from": {
   108  							Name: "from",
   109  							Expr: mod_boop_index_foo_expr,
   110  						},
   111  					},
   112  				}),
   113  				DefRange: blockRange,
   114  			},
   115  			&Removed{
   116  				DeclRange: blockRange,
   117  			},
   118  			"Module instance address with keys is not allowed",
   119  		},
   120  		"error: data address": {
   121  			&hcl.Block{
   122  				Type: "moved",
   123  				Body: hcltest.MockBody(&hcl.BodyContent{
   124  					Attributes: hcl.Attributes{
   125  						"from": {
   126  							Name: "from",
   127  							Expr: data_foo_expr,
   128  						},
   129  					},
   130  				}),
   131  				DefRange: blockRange,
   132  			},
   133  			&Removed{
   134  				DeclRange: blockRange,
   135  			},
   136  			"Data source address is not allowed",
   137  		},
   138  	}
   139  
   140  	for name, test := range tests {
   141  		t.Run(name, func(t *testing.T) {
   142  			got, diags := decodeRemovedBlock(test.input)
   143  
   144  			if diags.HasErrors() {
   145  				if test.err == "" {
   146  					t.Fatalf("unexpected error: %s", diags.Errs())
   147  				}
   148  				if gotErr := diags[0].Summary; gotErr != test.err {
   149  					t.Errorf("wrong error, got %q, want %q", gotErr, test.err)
   150  				}
   151  			} else if test.err != "" {
   152  				t.Fatal("expected error")
   153  			}
   154  
   155  			if !cmp.Equal(got, test.want, cmp.AllowUnexported(addrs.MoveEndpoint{})) {
   156  				t.Fatalf("wrong result: %s", cmp.Diff(got, test.want))
   157  			}
   158  		})
   159  	}
   160  }
   161  
   162  func TestRemovedBlock_inModule(t *testing.T) {
   163  	parser := NewParser(nil)
   164  	mod, diags := parser.LoadConfigDir("testdata/valid-modules/removed-blocks")
   165  	if diags.HasErrors() {
   166  		t.Errorf("unexpected error: %s", diags.Error())
   167  	}
   168  
   169  	var got []string
   170  	for _, mc := range mod.Removed {
   171  		got = append(got, mc.From.RelSubject.String())
   172  	}
   173  	want := []string{
   174  		`test.foo`,
   175  		`test.foo`,
   176  		`module.a`,
   177  		`module.a`,
   178  		`test.foo`,
   179  		`test.boop`,
   180  	}
   181  	if diff := cmp.Diff(want, got); diff != "" {
   182  		t.Errorf("wrong addresses\n%s", diff)
   183  	}
   184  }
   185  
   186  func mustRemoveEndpointFromExpr(expr hcl.Expression) *addrs.RemoveEndpoint {
   187  	traversal, hcldiags := hcl.AbsTraversalForExpr(expr)
   188  	if hcldiags.HasErrors() {
   189  		panic(hcldiags.Errs())
   190  	}
   191  
   192  	ep, diags := addrs.ParseRemoveEndpoint(traversal)
   193  	if diags.HasErrors() {
   194  		panic(diags.Err())
   195  	}
   196  
   197  	return ep
   198  }