github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/configs/module_merge_test.go (about)

     1  package configs
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/hcl/v2"
     8  	"github.com/hashicorp/hcl/v2/gohcl"
     9  	"github.com/hashicorp/terraform/internal/addrs"
    10  	"github.com/zclconf/go-cty/cty"
    11  )
    12  
    13  func TestModuleOverrideVariable(t *testing.T) {
    14  	mod, diags := testModuleFromDir("testdata/valid-modules/override-variable")
    15  	assertNoDiagnostics(t, diags)
    16  	if mod == nil {
    17  		t.Fatalf("module is nil")
    18  	}
    19  
    20  	got := mod.Variables
    21  	want := map[string]*Variable{
    22  		"fully_overridden": {
    23  			Name:           "fully_overridden",
    24  			Description:    "b_override description",
    25  			DescriptionSet: true,
    26  			Default:        cty.StringVal("b_override"),
    27  			Nullable:       false,
    28  			NullableSet:    true,
    29  			Type:           cty.String,
    30  			ConstraintType: cty.String,
    31  			ParsingMode:    VariableParseLiteral,
    32  			DeclRange: hcl.Range{
    33  				Filename: "testdata/valid-modules/override-variable/primary.tf",
    34  				Start: hcl.Pos{
    35  					Line:   1,
    36  					Column: 1,
    37  					Byte:   0,
    38  				},
    39  				End: hcl.Pos{
    40  					Line:   1,
    41  					Column: 28,
    42  					Byte:   27,
    43  				},
    44  			},
    45  		},
    46  		"partially_overridden": {
    47  			Name:           "partially_overridden",
    48  			Description:    "base description",
    49  			DescriptionSet: true,
    50  			Default:        cty.StringVal("b_override partial"),
    51  			Nullable:       true,
    52  			NullableSet:    false,
    53  			Type:           cty.String,
    54  			ConstraintType: cty.String,
    55  			ParsingMode:    VariableParseLiteral,
    56  			DeclRange: hcl.Range{
    57  				Filename: "testdata/valid-modules/override-variable/primary.tf",
    58  				Start: hcl.Pos{
    59  					Line:   7,
    60  					Column: 1,
    61  					Byte:   103,
    62  				},
    63  				End: hcl.Pos{
    64  					Line:   7,
    65  					Column: 32,
    66  					Byte:   134,
    67  				},
    68  			},
    69  		},
    70  	}
    71  	assertResultDeepEqual(t, got, want)
    72  }
    73  
    74  func TestModuleOverrideModule(t *testing.T) {
    75  	mod, diags := testModuleFromDir("testdata/valid-modules/override-module")
    76  	assertNoDiagnostics(t, diags)
    77  	if mod == nil {
    78  		t.Fatalf("module is nil")
    79  	}
    80  
    81  	if _, exists := mod.ModuleCalls["example"]; !exists {
    82  		t.Fatalf("no module 'example'")
    83  	}
    84  	if len(mod.ModuleCalls) != 1 {
    85  		t.Fatalf("wrong number of module calls in result %d; want 1", len(mod.ModuleCalls))
    86  	}
    87  
    88  	got := mod.ModuleCalls["example"]
    89  	want := &ModuleCall{
    90  		Name:          "example",
    91  		SourceAddr:    addrs.ModuleSourceLocal("./example2-a_override"),
    92  		SourceAddrRaw: "./example2-a_override",
    93  		SourceAddrRange: hcl.Range{
    94  			Filename: "testdata/valid-modules/override-module/a_override.tf",
    95  			Start: hcl.Pos{
    96  				Line:   3,
    97  				Column: 12,
    98  				Byte:   31,
    99  			},
   100  			End: hcl.Pos{
   101  				Line:   3,
   102  				Column: 35,
   103  				Byte:   54,
   104  			},
   105  		},
   106  		SourceSet: true,
   107  		DeclRange: hcl.Range{
   108  			Filename: "testdata/valid-modules/override-module/primary.tf",
   109  			Start: hcl.Pos{
   110  				Line:   2,
   111  				Column: 1,
   112  				Byte:   1,
   113  			},
   114  			End: hcl.Pos{
   115  				Line:   2,
   116  				Column: 17,
   117  				Byte:   17,
   118  			},
   119  		},
   120  		DependsOn: []hcl.Traversal{
   121  			{
   122  				hcl.TraverseRoot{
   123  					Name: "null_resource",
   124  					SrcRange: hcl.Range{
   125  						Filename: "testdata/valid-modules/override-module/primary.tf",
   126  						Start:    hcl.Pos{Line: 11, Column: 17, Byte: 149},
   127  						End:      hcl.Pos{Line: 11, Column: 30, Byte: 162},
   128  					},
   129  				},
   130  				hcl.TraverseAttr{
   131  					Name: "test",
   132  					SrcRange: hcl.Range{
   133  						Filename: "testdata/valid-modules/override-module/primary.tf",
   134  						Start:    hcl.Pos{Line: 11, Column: 30, Byte: 162},
   135  						End:      hcl.Pos{Line: 11, Column: 35, Byte: 167},
   136  					},
   137  				},
   138  			},
   139  		},
   140  		Providers: []PassedProviderConfig{
   141  			{
   142  				InChild: &ProviderConfigRef{
   143  					Name: "test",
   144  					NameRange: hcl.Range{
   145  						Filename: "testdata/valid-modules/override-module/b_override.tf",
   146  						Start:    hcl.Pos{Line: 7, Column: 5, Byte: 97},
   147  						End:      hcl.Pos{Line: 7, Column: 9, Byte: 101},
   148  					},
   149  				},
   150  				InParent: &ProviderConfigRef{
   151  					Name: "test",
   152  					NameRange: hcl.Range{
   153  						Filename: "testdata/valid-modules/override-module/b_override.tf",
   154  						Start:    hcl.Pos{Line: 7, Column: 12, Byte: 104},
   155  						End:      hcl.Pos{Line: 7, Column: 16, Byte: 108},
   156  					},
   157  					Alias: "b_override",
   158  					AliasRange: &hcl.Range{
   159  						Filename: "testdata/valid-modules/override-module/b_override.tf",
   160  						Start:    hcl.Pos{Line: 7, Column: 16, Byte: 108},
   161  						End:      hcl.Pos{Line: 7, Column: 27, Byte: 119},
   162  					},
   163  				},
   164  			},
   165  		},
   166  	}
   167  
   168  	// We're going to extract and nil out our hcl.Body here because DeepEqual
   169  	// is not a useful way to assert on that.
   170  	gotConfig := got.Config
   171  	got.Config = nil
   172  
   173  	assertResultDeepEqual(t, got, want)
   174  
   175  	type content struct {
   176  		Kept  *string `hcl:"kept"`
   177  		Foo   *string `hcl:"foo"`
   178  		New   *string `hcl:"new"`
   179  		Newer *string `hcl:"newer"`
   180  	}
   181  	var gotArgs content
   182  	diags = gohcl.DecodeBody(gotConfig, nil, &gotArgs)
   183  	assertNoDiagnostics(t, diags)
   184  
   185  	wantArgs := content{
   186  		Kept:  stringPtr("primary kept"),
   187  		Foo:   stringPtr("a_override foo"),
   188  		New:   stringPtr("b_override new"),
   189  		Newer: stringPtr("b_override newer"),
   190  	}
   191  
   192  	assertResultDeepEqual(t, gotArgs, wantArgs)
   193  }
   194  
   195  func TestModuleOverrideDynamic(t *testing.T) {
   196  	schema := &hcl.BodySchema{
   197  		Blocks: []hcl.BlockHeaderSchema{
   198  			{Type: "foo"},
   199  			{Type: "dynamic", LabelNames: []string{"type"}},
   200  		},
   201  	}
   202  
   203  	t.Run("base is dynamic", func(t *testing.T) {
   204  		mod, diags := testModuleFromDir("testdata/valid-modules/override-dynamic-block-base")
   205  		assertNoDiagnostics(t, diags)
   206  		if mod == nil {
   207  			t.Fatalf("module is nil")
   208  		}
   209  
   210  		if _, exists := mod.ManagedResources["test.foo"]; !exists {
   211  			t.Fatalf("no module 'example'")
   212  		}
   213  		if len(mod.ManagedResources) != 1 {
   214  			t.Fatalf("wrong number of managed resources in result %d; want 1", len(mod.ManagedResources))
   215  		}
   216  
   217  		body := mod.ManagedResources["test.foo"].Config
   218  		content, diags := body.Content(schema)
   219  		assertNoDiagnostics(t, diags)
   220  
   221  		if len(content.Blocks) != 1 {
   222  			t.Fatalf("wrong number of blocks in result %d; want 1", len(content.Blocks))
   223  		}
   224  		if got, want := content.Blocks[0].Type, "foo"; got != want {
   225  			t.Fatalf("wrong block type %q; want %q", got, want)
   226  		}
   227  	})
   228  	t.Run("override is dynamic", func(t *testing.T) {
   229  		mod, diags := testModuleFromDir("testdata/valid-modules/override-dynamic-block-override")
   230  		assertNoDiagnostics(t, diags)
   231  		if mod == nil {
   232  			t.Fatalf("module is nil")
   233  		}
   234  
   235  		if _, exists := mod.ManagedResources["test.foo"]; !exists {
   236  			t.Fatalf("no module 'example'")
   237  		}
   238  		if len(mod.ManagedResources) != 1 {
   239  			t.Fatalf("wrong number of managed resources in result %d; want 1", len(mod.ManagedResources))
   240  		}
   241  
   242  		body := mod.ManagedResources["test.foo"].Config
   243  		content, diags := body.Content(schema)
   244  		assertNoDiagnostics(t, diags)
   245  
   246  		if len(content.Blocks) != 1 {
   247  			t.Fatalf("wrong number of blocks in result %d; want 1", len(content.Blocks))
   248  		}
   249  		if got, want := content.Blocks[0].Type, "dynamic"; got != want {
   250  			t.Fatalf("wrong block type %q; want %q", got, want)
   251  		}
   252  		if got, want := content.Blocks[0].Labels[0], "foo"; got != want {
   253  			t.Fatalf("wrong dynamic block label %q; want %q", got, want)
   254  		}
   255  	})
   256  }
   257  
   258  func TestModuleOverrideSensitiveVariable(t *testing.T) {
   259  	type testCase struct {
   260  		sensitive    bool
   261  		sensitiveSet bool
   262  	}
   263  	cases := map[string]testCase{
   264  		"false_true": {
   265  			sensitive:    true,
   266  			sensitiveSet: true,
   267  		},
   268  		"true_false": {
   269  			sensitive:    false,
   270  			sensitiveSet: true,
   271  		},
   272  		"false_false_true": {
   273  			sensitive:    true,
   274  			sensitiveSet: true,
   275  		},
   276  		"true_true_false": {
   277  			sensitive:    false,
   278  			sensitiveSet: true,
   279  		},
   280  		"false_true_false": {
   281  			sensitive:    false,
   282  			sensitiveSet: true,
   283  		},
   284  		"true_false_true": {
   285  			sensitive:    true,
   286  			sensitiveSet: true,
   287  		},
   288  	}
   289  
   290  	mod, diags := testModuleFromDir("testdata/valid-modules/override-variable-sensitive")
   291  
   292  	assertNoDiagnostics(t, diags)
   293  
   294  	if mod == nil {
   295  		t.Fatalf("module is nil")
   296  	}
   297  
   298  	got := mod.Variables
   299  
   300  	for v, want := range cases {
   301  		t.Run(fmt.Sprintf("variable %s", v), func(t *testing.T) {
   302  			if got[v].Sensitive != want.sensitive {
   303  				t.Errorf("wrong result for sensitive\ngot: %t want: %t", got[v].Sensitive, want.sensitive)
   304  			}
   305  
   306  			if got[v].SensitiveSet != want.sensitiveSet {
   307  				t.Errorf("wrong result for sensitive set\ngot: %t want: %t", got[v].Sensitive, want.sensitive)
   308  			}
   309  		})
   310  	}
   311  }
   312  
   313  func TestModuleOverrideResourceFQNs(t *testing.T) {
   314  	mod, diags := testModuleFromDir("testdata/valid-modules/override-resource-provider")
   315  	assertNoDiagnostics(t, diags)
   316  
   317  	got := mod.ManagedResources["test_instance.explicit"]
   318  	wantProvider := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "bar", "test")
   319  	wantProviderCfg := &ProviderConfigRef{
   320  		Name: "bar-test",
   321  		NameRange: hcl.Range{
   322  			Filename: "testdata/valid-modules/override-resource-provider/a_override.tf",
   323  			Start:    hcl.Pos{Line: 2, Column: 14, Byte: 51},
   324  			End:      hcl.Pos{Line: 2, Column: 22, Byte: 59},
   325  		},
   326  	}
   327  
   328  	if !got.Provider.Equals(wantProvider) {
   329  		t.Fatalf("wrong provider %s, want %s", got.Provider, wantProvider)
   330  	}
   331  	assertResultDeepEqual(t, got.ProviderConfigRef, wantProviderCfg)
   332  
   333  	// now verify that a resource with no provider config falls back to default
   334  	got = mod.ManagedResources["test_instance.default"]
   335  	wantProvider = addrs.NewDefaultProvider("test")
   336  	if !got.Provider.Equals(wantProvider) {
   337  		t.Fatalf("wrong provider %s, want %s", got.Provider, wantProvider)
   338  	}
   339  	if got.ProviderConfigRef != nil {
   340  		t.Fatalf("wrong result: found provider config ref %s, expected nil", got.ProviderConfigRef)
   341  	}
   342  }
   343  
   344  func TestModuleOverrideIgnoreAllChanges(t *testing.T) {
   345  	mod, diags := testModuleFromDir("testdata/valid-modules/override-ignore-changes")
   346  	assertNoDiagnostics(t, diags)
   347  
   348  	r := mod.ManagedResources["test_instance.foo"]
   349  	if !r.Managed.IgnoreAllChanges {
   350  		t.Fatalf("wrong result: expected r.Managed.IgnoreAllChanges to be true")
   351  	}
   352  }