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