github.com/opentofu/opentofu@v1.7.1/internal/tofu/evaluate_triggers_test.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package tofu
     7  
     8  import (
     9  	"testing"
    10  
    11  	"github.com/hashicorp/hcl/v2"
    12  	"github.com/hashicorp/hcl/v2/hclsyntax"
    13  	"github.com/opentofu/opentofu/internal/addrs"
    14  	"github.com/opentofu/opentofu/internal/instances"
    15  	"github.com/zclconf/go-cty/cty"
    16  )
    17  
    18  func TestEvalReplaceTriggeredBy(t *testing.T) {
    19  	tests := map[string]struct {
    20  		// Raw config expression from within replace_triggered_by list.
    21  		// If this does not contains any count or each references, it should
    22  		// directly parse into the same *addrs.Reference.
    23  		expr string
    24  
    25  		// If the expression contains count or each, then we need to add
    26  		// repetition data, and the static string to parse into the desired
    27  		// *addrs.Reference
    28  		repData   instances.RepetitionData
    29  		reference string
    30  	}{
    31  		"single resource": {
    32  			expr: "test_resource.a",
    33  		},
    34  
    35  		"resource instance attr": {
    36  			expr: "test_resource.a.attr",
    37  		},
    38  
    39  		"resource instance index attr": {
    40  			expr: "test_resource.a[0].attr",
    41  		},
    42  
    43  		"resource instance count": {
    44  			expr: "test_resource.a[count.index]",
    45  			repData: instances.RepetitionData{
    46  				CountIndex: cty.NumberIntVal(0),
    47  			},
    48  			reference: "test_resource.a[0]",
    49  		},
    50  		"resource instance for_each": {
    51  			expr: "test_resource.a[each.key].attr",
    52  			repData: instances.RepetitionData{
    53  				EachKey: cty.StringVal("k"),
    54  			},
    55  			reference: `test_resource.a["k"].attr`,
    56  		},
    57  		"resource instance for_each map attr": {
    58  			expr: "test_resource.a[each.key].attr[each.key]",
    59  			repData: instances.RepetitionData{
    60  				EachKey: cty.StringVal("k"),
    61  			},
    62  			reference: `test_resource.a["k"].attr["k"]`,
    63  		},
    64  	}
    65  
    66  	for name, tc := range tests {
    67  		pos := hcl.Pos{Line: 1, Column: 1}
    68  		t.Run(name, func(t *testing.T) {
    69  			expr, hclDiags := hclsyntax.ParseExpression([]byte(tc.expr), "", pos)
    70  			if hclDiags.HasErrors() {
    71  				t.Fatal(hclDiags)
    72  			}
    73  
    74  			got, diags := evalReplaceTriggeredByExpr(expr, tc.repData)
    75  			if diags.HasErrors() {
    76  				t.Fatal(diags.Err())
    77  			}
    78  
    79  			want := tc.reference
    80  			if want == "" {
    81  				want = tc.expr
    82  			}
    83  
    84  			// create the desired reference
    85  			traversal, travDiags := hclsyntax.ParseTraversalAbs([]byte(want), "", pos)
    86  			if travDiags.HasErrors() {
    87  				t.Fatal(travDiags)
    88  			}
    89  			ref, diags := addrs.ParseRef(traversal)
    90  			if diags.HasErrors() {
    91  				t.Fatal(diags.Err())
    92  			}
    93  
    94  			if got.DisplayString() != ref.DisplayString() {
    95  				t.Fatalf("expected %q: got %q", ref.DisplayString(), got.DisplayString())
    96  			}
    97  		})
    98  	}
    99  }