github.com/opentofu/opentofu@v1.7.1/internal/tofu/node_module_expand_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/hcltest"
    12  	"github.com/opentofu/opentofu/internal/addrs"
    13  	"github.com/opentofu/opentofu/internal/configs"
    14  	"github.com/opentofu/opentofu/internal/instances"
    15  	"github.com/opentofu/opentofu/internal/states"
    16  	"github.com/zclconf/go-cty/cty"
    17  )
    18  
    19  func TestNodeExpandModuleExecute(t *testing.T) {
    20  	ctx := &MockEvalContext{
    21  		InstanceExpanderExpander: instances.NewExpander(),
    22  	}
    23  	ctx.installSimpleEval()
    24  
    25  	node := nodeExpandModule{
    26  		Addr: addrs.Module{"child"},
    27  		ModuleCall: &configs.ModuleCall{
    28  			Count: hcltest.MockExprLiteral(cty.NumberIntVal(2)),
    29  		},
    30  	}
    31  
    32  	err := node.Execute(ctx, walkApply)
    33  	if err != nil {
    34  		t.Fatalf("unexpected error: %s", err)
    35  	}
    36  
    37  	if !ctx.InstanceExpanderCalled {
    38  		t.Fatal("did not expand")
    39  	}
    40  }
    41  
    42  func TestNodeCloseModuleExecute(t *testing.T) {
    43  	t.Run("walkApply", func(t *testing.T) {
    44  		state := states.NewState()
    45  		state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
    46  		ctx := &MockEvalContext{
    47  			StateState: state.SyncWrapper(),
    48  		}
    49  		node := nodeCloseModule{addrs.Module{"child"}}
    50  		diags := node.Execute(ctx, walkApply)
    51  		if diags.HasErrors() {
    52  			t.Fatalf("unexpected error: %s", diags.Err())
    53  		}
    54  
    55  		// Since module.child has no resources, it should be removed
    56  		if _, ok := state.Modules["module.child"]; !ok {
    57  			t.Fatal("module.child should not be removed from state yet")
    58  		}
    59  
    60  		// the root module should do all the module cleanup
    61  		node = nodeCloseModule{addrs.RootModule}
    62  		diags = node.Execute(ctx, walkApply)
    63  		if diags.HasErrors() {
    64  			t.Fatalf("unexpected error: %s", diags.Err())
    65  		}
    66  
    67  		// Since module.child has no resources, it should be removed
    68  		if _, ok := state.Modules["module.child"]; ok {
    69  			t.Fatal("module.child was not removed from state")
    70  		}
    71  	})
    72  
    73  	// walkImport is a no-op
    74  	t.Run("walkImport", func(t *testing.T) {
    75  		state := states.NewState()
    76  		state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
    77  		ctx := &MockEvalContext{
    78  			StateState: state.SyncWrapper(),
    79  		}
    80  		node := nodeCloseModule{addrs.Module{"child"}}
    81  
    82  		diags := node.Execute(ctx, walkImport)
    83  		if diags.HasErrors() {
    84  			t.Fatalf("unexpected error: %s", diags.Err())
    85  		}
    86  		if _, ok := state.Modules["module.child"]; !ok {
    87  			t.Fatal("module.child was removed from state, expected no-op")
    88  		}
    89  	})
    90  }
    91  
    92  func TestNodeValidateModuleExecute(t *testing.T) {
    93  	t.Run("success", func(t *testing.T) {
    94  		ctx := &MockEvalContext{
    95  			InstanceExpanderExpander: instances.NewExpander(),
    96  		}
    97  		ctx.installSimpleEval()
    98  		node := nodeValidateModule{
    99  			nodeExpandModule{
   100  				Addr: addrs.Module{"child"},
   101  				ModuleCall: &configs.ModuleCall{
   102  					Count: hcltest.MockExprLiteral(cty.NumberIntVal(2)),
   103  				},
   104  			},
   105  		}
   106  
   107  		diags := node.Execute(ctx, walkApply)
   108  		if diags.HasErrors() {
   109  			t.Fatalf("unexpected error: %v", diags.Err())
   110  		}
   111  	})
   112  
   113  	t.Run("invalid count", func(t *testing.T) {
   114  		ctx := &MockEvalContext{
   115  			InstanceExpanderExpander: instances.NewExpander(),
   116  		}
   117  		ctx.installSimpleEval()
   118  		node := nodeValidateModule{
   119  			nodeExpandModule{
   120  				Addr: addrs.Module{"child"},
   121  				ModuleCall: &configs.ModuleCall{
   122  					Count: hcltest.MockExprLiteral(cty.StringVal("invalid")),
   123  				},
   124  			},
   125  		}
   126  
   127  		err := node.Execute(ctx, walkApply)
   128  		if err == nil {
   129  			t.Fatal("expected error, got success")
   130  		}
   131  	})
   132  
   133  }