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