github.com/opentofu/opentofu@v1.7.1/internal/instances/set_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 instances
     7  
     8  import (
     9  	"testing"
    10  
    11  	"github.com/opentofu/opentofu/internal/addrs"
    12  	"github.com/zclconf/go-cty/cty"
    13  )
    14  
    15  func TestSet(t *testing.T) {
    16  	exp := NewExpander()
    17  
    18  	// The following constructs the following imaginary module/resource tree:
    19  	// - root module
    20  	//   - test_thing.single: no repetition
    21  	//   - test_thing.count: count = 1
    22  	//   - test_thing.for_each: for_each = { c = "C" }
    23  	//   - module.single: no repetition
    24  	//     - test_thing.single: no repetition
    25  	//     - module.nested_single: no repetition
    26  	//       - module.zero_count: count = 0
    27  	//   - module.count: count = 2
    28  	//     - module.nested_for_each: [0] for_each = {}, [1] for_each = { e = "E" }
    29  	//   - module.for_each: for_each = { a = "A", b = "B" }
    30  	//     - test_thing.count: ["a"] count = 0, ["b"] count = 1
    31  	exp.SetModuleSingle(addrs.RootModuleInstance, addrs.ModuleCall{Name: "single"})
    32  	exp.SetModuleCount(addrs.RootModuleInstance, addrs.ModuleCall{Name: "count"}, 2)
    33  	exp.SetModuleForEach(addrs.RootModuleInstance, addrs.ModuleCall{Name: "for_each"}, map[string]cty.Value{
    34  		"a": cty.StringVal("A"),
    35  		"b": cty.StringVal("B"),
    36  	})
    37  	exp.SetModuleSingle(addrs.RootModuleInstance.Child("single", addrs.NoKey), addrs.ModuleCall{Name: "nested_single"})
    38  	exp.SetModuleForEach(addrs.RootModuleInstance.Child("count", addrs.IntKey(0)), addrs.ModuleCall{Name: "nested_for_each"}, nil)
    39  	exp.SetModuleForEach(addrs.RootModuleInstance.Child("count", addrs.IntKey(1)), addrs.ModuleCall{Name: "nested_for_each"}, map[string]cty.Value{
    40  		"e": cty.StringVal("E"),
    41  	})
    42  	exp.SetModuleCount(
    43  		addrs.RootModuleInstance.Child("single", addrs.NoKey).Child("nested_single", addrs.NoKey),
    44  		addrs.ModuleCall{Name: "zero_count"},
    45  		0,
    46  	)
    47  
    48  	rAddr := func(name string) addrs.Resource {
    49  		return addrs.Resource{
    50  			Mode: addrs.ManagedResourceMode,
    51  			Type: "test_thing",
    52  			Name: name,
    53  		}
    54  	}
    55  	exp.SetResourceSingle(addrs.RootModuleInstance, rAddr("single"))
    56  	exp.SetResourceCount(addrs.RootModuleInstance, rAddr("count"), 1)
    57  	exp.SetResourceForEach(addrs.RootModuleInstance, rAddr("for_each"), map[string]cty.Value{
    58  		"c": cty.StringVal("C"),
    59  	})
    60  	exp.SetResourceSingle(addrs.RootModuleInstance.Child("single", addrs.NoKey), rAddr("single"))
    61  	exp.SetResourceCount(addrs.RootModuleInstance.Child("for_each", addrs.StringKey("a")), rAddr("count"), 0)
    62  	exp.SetResourceCount(addrs.RootModuleInstance.Child("for_each", addrs.StringKey("b")), rAddr("count"), 1)
    63  
    64  	set := exp.AllInstances()
    65  
    66  	// HasModuleInstance tests
    67  	if input := addrs.RootModuleInstance; !set.HasModuleInstance(input) {
    68  		t.Errorf("missing %T %s", input, input.String())
    69  	}
    70  	if input := addrs.RootModuleInstance.Child("single", addrs.NoKey); !set.HasModuleInstance(input) {
    71  		t.Errorf("missing %T %s", input, input.String())
    72  	}
    73  	if input := addrs.RootModuleInstance.Child("single", addrs.NoKey).Child("nested_single", addrs.NoKey); !set.HasModuleInstance(input) {
    74  		t.Errorf("missing %T %s", input, input.String())
    75  	}
    76  	if input := addrs.RootModuleInstance.Child("count", addrs.IntKey(0)); !set.HasModuleInstance(input) {
    77  		t.Errorf("missing %T %s", input, input.String())
    78  	}
    79  	if input := addrs.RootModuleInstance.Child("count", addrs.IntKey(1)); !set.HasModuleInstance(input) {
    80  		t.Errorf("missing %T %s", input, input.String())
    81  	}
    82  	if input := addrs.RootModuleInstance.Child("count", addrs.IntKey(1)).Child("nested_for_each", addrs.StringKey("e")); !set.HasModuleInstance(input) {
    83  		t.Errorf("missing %T %s", input, input.String())
    84  	}
    85  	if input := addrs.RootModuleInstance.Child("for_each", addrs.StringKey("a")); !set.HasModuleInstance(input) {
    86  		t.Errorf("missing %T %s", input, input.String())
    87  	}
    88  	if input := addrs.RootModuleInstance.Child("for_each", addrs.StringKey("b")); !set.HasModuleInstance(input) {
    89  		t.Errorf("missing %T %s", input, input.String())
    90  	}
    91  	if input := addrs.RootModuleInstance.Child("single", addrs.IntKey(0)); set.HasModuleInstance(input) {
    92  		t.Errorf("unexpected %T %s", input, input.String())
    93  	}
    94  	if input := addrs.RootModuleInstance.Child("single", addrs.StringKey("a")); set.HasModuleInstance(input) {
    95  		t.Errorf("unexpected %T %s", input, input.String())
    96  	}
    97  	if input := addrs.RootModuleInstance.Child("single", addrs.NoKey).Child("nonexist", addrs.NoKey); set.HasModuleInstance(input) {
    98  		t.Errorf("unexpected %T %s", input, input.String())
    99  	}
   100  	if input := addrs.RootModuleInstance.Child("count", addrs.NoKey); set.HasModuleInstance(input) {
   101  		t.Errorf("unexpected %T %s", input, input.String())
   102  	}
   103  	if input := addrs.RootModuleInstance.Child("count", addrs.IntKey(2)); set.HasModuleInstance(input) {
   104  		t.Errorf("unexpected %T %s", input, input.String())
   105  	}
   106  	if input := addrs.RootModuleInstance.Child("count", addrs.StringKey("a")); set.HasModuleInstance(input) {
   107  		t.Errorf("unexpected %T %s", input, input.String())
   108  	}
   109  	if input := addrs.RootModuleInstance.Child("count", addrs.IntKey(0)).Child("nested_for_each", addrs.StringKey("e")); set.HasModuleInstance(input) {
   110  		t.Errorf("unexpected %T %s", input, input.String())
   111  	}
   112  	if input := addrs.RootModuleInstance.Child("single", addrs.NoKey).Child("nested_single", addrs.NoKey).Child("zero_count", addrs.NoKey); set.HasModuleInstance(input) {
   113  		t.Errorf("unexpected %T %s", input, input.String())
   114  	}
   115  	if input := addrs.RootModuleInstance.Child("single", addrs.NoKey).Child("nested_single", addrs.NoKey).Child("zero_count", addrs.IntKey(0)); set.HasModuleInstance(input) {
   116  		t.Errorf("unexpected %T %s", input, input.String())
   117  	}
   118  
   119  	// HasModuleCall tests
   120  	if input := addrs.RootModuleInstance.ChildCall("single"); !set.HasModuleCall(input) {
   121  		t.Errorf("missing %T %s", input, input.String())
   122  	}
   123  	if input := addrs.RootModuleInstance.Child("single", addrs.NoKey).ChildCall("nested_single"); !set.HasModuleCall(input) {
   124  		t.Errorf("missing %T %s", input, input.String())
   125  	}
   126  	if input := addrs.RootModuleInstance.ChildCall("count"); !set.HasModuleCall(input) {
   127  		t.Errorf("missing %T %s", input, input.String())
   128  	}
   129  	if input := addrs.RootModuleInstance.Child("count", addrs.IntKey(0)).ChildCall("nested_for_each"); !set.HasModuleCall(input) {
   130  		t.Errorf("missing %T %s", input, input.String())
   131  	}
   132  	if input := addrs.RootModuleInstance.Child("count", addrs.IntKey(1)).ChildCall("nested_for_each"); !set.HasModuleCall(input) {
   133  		t.Errorf("missing %T %s", input, input.String())
   134  	}
   135  	if input := addrs.RootModuleInstance.ChildCall("for_each"); !set.HasModuleCall(input) {
   136  		t.Errorf("missing %T %s", input, input.String())
   137  	}
   138  	if input := addrs.RootModuleInstance.Child("single", addrs.NoKey).Child("nested_single", addrs.NoKey).ChildCall("zero_count"); !set.HasModuleCall(input) {
   139  		t.Errorf("missing %T %s", input, input.String())
   140  	}
   141  	if input := addrs.RootModuleInstance.ChildCall("nonexist"); set.HasModuleCall(input) {
   142  		t.Errorf("unexpected %T %s", input, input.String())
   143  	}
   144  	if input := addrs.RootModuleInstance.Child("single", addrs.NoKey).ChildCall("nonexist"); set.HasModuleCall(input) {
   145  		t.Errorf("unexpected %T %s", input, input.String())
   146  	}
   147  
   148  	// HasResourceInstance tests
   149  	if input := rAddr("single").Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance); !set.HasResourceInstance(input) {
   150  		t.Errorf("missing %T %s", input, input.String())
   151  	}
   152  	if input := rAddr("count").Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance); !set.HasResourceInstance(input) {
   153  		t.Errorf("missing %T %s", input, input.String())
   154  	}
   155  	if input := rAddr("for_each").Instance(addrs.StringKey("c")).Absolute(addrs.RootModuleInstance); !set.HasResourceInstance(input) {
   156  		t.Errorf("missing %T %s", input, input.String())
   157  	}
   158  	if input := rAddr("single").Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("single", addrs.NoKey)); !set.HasResourceInstance(input) {
   159  		t.Errorf("missing %T %s", input, input.String())
   160  	}
   161  	if input := rAddr("count").Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance.Child("for_each", addrs.StringKey("b"))); !set.HasResourceInstance(input) {
   162  		t.Errorf("missing %T %s", input, input.String())
   163  	}
   164  	if input := rAddr("single").Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance); set.HasResourceInstance(input) {
   165  		t.Errorf("unexpected %T %s", input, input.String())
   166  	}
   167  	if input := rAddr("single").Instance(addrs.StringKey("")).Absolute(addrs.RootModuleInstance); set.HasResourceInstance(input) {
   168  		t.Errorf("unexpected %T %s", input, input.String())
   169  	}
   170  	if input := rAddr("count").Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance); set.HasResourceInstance(input) {
   171  		t.Errorf("unexpected %T %s", input, input.String())
   172  	}
   173  	if input := rAddr("count").Instance(addrs.StringKey("")).Absolute(addrs.RootModuleInstance); set.HasResourceInstance(input) {
   174  		t.Errorf("unexpected %T %s", input, input.String())
   175  	}
   176  	if input := rAddr("count").Instance(addrs.IntKey(1)).Absolute(addrs.RootModuleInstance); set.HasResourceInstance(input) {
   177  		t.Errorf("unexpected %T %s", input, input.String())
   178  	}
   179  	if input := rAddr("single").Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("single", addrs.IntKey(0))); set.HasResourceInstance(input) {
   180  		t.Errorf("unexpected %T %s", input, input.String())
   181  	}
   182  	if input := rAddr("count").Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance.Child("for_each", addrs.StringKey("a"))); set.HasResourceInstance(input) {
   183  		t.Errorf("unexpected %T %s", input, input.String())
   184  	}
   185  
   186  	// HasResource tests
   187  	if input := rAddr("single").Absolute(addrs.RootModuleInstance); !set.HasResource(input) {
   188  		t.Errorf("missing %T %s", input, input.String())
   189  	}
   190  	if input := rAddr("count").Absolute(addrs.RootModuleInstance); !set.HasResource(input) {
   191  		t.Errorf("missing %T %s", input, input.String())
   192  	}
   193  	if input := rAddr("for_each").Absolute(addrs.RootModuleInstance); !set.HasResource(input) {
   194  		t.Errorf("missing %T %s", input, input.String())
   195  	}
   196  	if input := rAddr("single").Absolute(addrs.RootModuleInstance.Child("single", addrs.NoKey)); !set.HasResource(input) {
   197  		t.Errorf("missing %T %s", input, input.String())
   198  	}
   199  	if input := rAddr("count").Absolute(addrs.RootModuleInstance.Child("for_each", addrs.StringKey("a"))); !set.HasResource(input) {
   200  		t.Errorf("missing %T %s", input, input.String())
   201  	}
   202  	if input := rAddr("count").Absolute(addrs.RootModuleInstance.Child("for_each", addrs.StringKey("b"))); !set.HasResource(input) {
   203  		t.Errorf("missing %T %s", input, input.String())
   204  	}
   205  	if input := rAddr("nonexist").Absolute(addrs.RootModuleInstance); set.HasResource(input) {
   206  		t.Errorf("unexpected %T %s", input, input.String())
   207  	}
   208  	if input := rAddr("count").Absolute(addrs.RootModuleInstance.Child("for_each", addrs.StringKey("nonexist"))); set.HasResource(input) {
   209  		t.Errorf("unexpected %T %s", input, input.String())
   210  	}
   211  
   212  	// ensure we can lookup non-existent addrs in a set without panic
   213  	if set.InstancesForModule(addrs.RootModule.Child("missing")) != nil {
   214  		t.Error("unexpected instances from missing module")
   215  	}
   216  }