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